I have an VIS-Timeline component and want to establish a right-click context menu for each
embedded timeline item.
The items are programmatically rendered by VIS but the HTML label content for each
item are supplied via a template: callback function.
I inject a Vue component with vue-menu constructed context menu via this
callback.
If I right click the label the context menu does appear.
Unfortunately the label text is a small click-target. It would be
desirable to be able to right-click anywhere within the containing item
bar.
My current attempt:
I have used the VIS-timeline Timeline.on(...) handler to catch
right-click (contextmenu events) and forward them to the HTML
wrapping
the vue-menu click handler (the same one I right-click manually to bring up
the context menu). See code snippet below
When I uncomment the console output code and right click the label text and then
right-click the containing event bar... I see a successful redirection.
the original event on the containing element
then the redirected even to the vue-menu decorated div
Sadly the context menu doesn't open.
Any suggestions would be appreciated.
Testing Harness Code:
// Template generation using mock multi-level context-menu
// - note *item.content* contains the item label text
// (Sue Simmons in this example).
const ItemEntry = Vue.extend({
template: `
<hsc-menu-style-white>
<hsc-menu-button-menu ref="itemContextMenu"
style="z-index:2; position:relative;"
@contextmenu.native.prevent>
<div> {{item.content}} </div>
<template slot="contextmenu">
<hsc-menu-item label="MenuItem 1">
<hsc-menu-item label="MenuItem 1a" @click.native="processMenu('1a')"/>
<hsc-menu-item label="MenuItem 1b" @click.native="processMenu('1b')"/>
</hsc-menu-item>
<hsc-menu-item label="MenuItem 2" @click.native="processMenu('2')" />
<hsc-menu-item label="MenuItem 3">
<hsc-menu-item label="MenuItem 3a" @click.native="processMenu('3a')"/>
<hsc-menu-item label="MenuItem 3b" @click.native="processMenu('3b')"/>
</hsc-menu-item>
</template>
</hsc-menu-button-menu>
</hsc-menu-style-white>`,
methods: {
processMenu(label){
alert('ProcessItemMenu: '+label);
// See: https://github.com/michitaro/vue-menu/issues/21
this.$refs.itemContextMenu.$refs.menu.close(true);
}
},
props: ['item'],
});
...
// Remotely fire the contextmenu event
this.timeline.on('contextmenu', (props) => {
# Simplified search for approriate vue-menu div
var findNode = function(start, regexp){
node = start;
while (true){
var html = node.outerHTML;
if (html == undefined){
node = undefined;
break;
} else {
if (html.match(regexp)) break;
};
node = node.firstChild;
if (node == undefined) break;
};
return node;
};
// if (window.$$debugger) debugger;
// console.log('ContextMenu:',event);
// Sue Simmon is the exemplar rendered label -- see above
if (event.target.outerHTML.match(/^<div> Sue Simmons <\/div>$/)){
// Record original event which does fire
window.$$saveEvent = new MouseEvent(event.type, event);
} else {
var newEvent = new MouseEvent(event.type, event);
// Use working right-click event (NOTE: *isTrusted* field can't be set to true)
if (window.$$saveEvent) newEvent = window.$$saveEvent;
var node = findNode(event.target, /^<div> Sue Simmons <\/div>$/);
if (node) node.dispatchEvent(newEvent);
}
props.event.preventDefault();
});
Background:
My current attempt:
Any suggestions would be appreciated.
Testing Harness Code: