michitaro / vue-menu

Menu/Contextmenu Component for vue2
https://michitaro.github.io/vue-menu/
MIT License
263 stars 26 forks source link

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

Open DAMisener opened 5 years ago

DAMisener commented 5 years ago

Background:

My current attempt:

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