vue-menu icon indicating copy to clipboard operation
vue-menu copied to clipboard

How can I successfully *remotely* fire an event to open a right context menu?

Open DAMisener opened this issue 5 years ago • 0 comments

Background:

  • 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();
      });
    

DAMisener avatar Sep 25 '19 20:09 DAMisener