swisnl / jQuery-contextMenu

jQuery contextMenu plugin & polyfill
https://swisnl.github.io/jQuery-contextMenu/
MIT License
2.25k stars 744 forks source link

Sometimes the property 'autoHide' has some problem #723

Open YonSunZhen opened 4 years ago

YonSunZhen commented 4 years ago

Hi, when i use contextMenu on kityminder, set autoHide to true, and it is not work. the demo as follows:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>test</title>

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">

  <link type="text/css" rel="stylesheet" href="./assets/styles/jquery.contextMenu.css">
  <link type="text/css" rel="stylesheet" href="./assets/styles/font-awesome/css/font-awesome.min.css">
</head>

<body>
  <div id="minder-container1" style="width: 1000px; height: 800px;"></div>

  <script type="text/javascript" src="./assets/js/jquery-1.6.2.min.js"></script>
  <script type="text/javascript" src="./assets/js/jquery.ui.position.min.js"></script>
  <script type="text/javascript" src="./assets/js/jquery.contextMenu.js"></script>
  <script type="text/javascript" src="./assets/js/kity.js"></script>
  <script type="text/javascript" src="./assets/js/kityminder.core.modified.js"></script>

  <script>
    const renderData = {
      "root": {
          "data": {
              "text": "百度产品",
              "image": "https://www.baidu.com/img/bd_logo1.png?where=super",
              "imageSize": { "width": 270, "height": 129 }
          },
          "children": [
              { "data": { "text": "新闻" } },
              { "data": { "text": "网页", "priority": 1 } },
              { "data": { "text": "贴吧", "priority": 2 } },
              { "data": { "text": "知道", "priority": 2 } },
              { "data": { "text": "音乐", "priority": 3 } },
              { "data": { "text": "图片", "priority": 3 } },
              { "data": { "text": "视频", "priority": 3 } },
              { "data": { "text": "地图", "priority": 3 } },
              { "data": { "text": "百科", "priority": 3 } },
              { "data": { "text": "更多", "hyperlink": "http://www.baidu.com/more" } }
          ]
      }
    }
    const minder = new kityminder.Minder({
      renderTo: '#minder-container1'
    });
    minder.importJson(renderData);

    $.contextMenu({
      selector: 'g[id^="minder_node"]',
      autoHide: true,
      callback: (itemKey, opt) => { },
      events: {
        preShow: options => { },
        show: options => { },
        hide: options => { }
      },
      build: ($trigger, e) => {
        return {
          items: {
            addField: {
              name: 'Add',
              icon: 'fa-dot-circle-o',
              callback: async (itemKey, opt, rootMenu, originalEvent) => {

              }
            },
            sep2: '---------',
            remove: {
              name: 'Delete',
              icon: 'fa-dot-circle-o',
              callback: (itemKey, opt, rootMenu, originalEvent) => {

              }
            }
          }
        }
      }
    })
  </script>
</body>
</html>

and when i update the code as follows, it works.

if (opt.autoHide) {
          // mouse position handler
          $(document).on('mousemove.contextMenuAutoHide', function (e) {
            // need to capture the offset on mousemove,
            // since the page might've been scrolled since activation
            var pos = $trigger.offset();

            if ($trigger.outerWidth() === 0 && $trigger.outerHeight() === 0) {
              const nodeId = $trigger[0].getAttribute('id');
              const path = $(`#${nodeId} [id^='node_outline']`)[0];
              const pathInfo = path.getBBox();
              const width = pathInfo.width;
              const height = pathInfo.height;
              pos.right = pos.left + width;
              pos.bottom = pos.top + height;
            } else {
              pos.right = pos.left + $trigger.outerWidth();
              pos.bottom = pos.top + $trigger.outerHeight();
            }

            // pos.right = pos.left + $trigger.outerWidth();
            // pos.bottom = pos.top + $trigger.outerHeight();

            if (opt.$layer && !opt.hovering && (!(e.pageX >= pos.left && e.pageX <= pos.right) || !(e.pageY >= pos.top && e.pageY <= pos.bottom))) {
              /* Additional hover check after short time, you might just miss the edge of the menu */
              setTimeout(function () {
                if (!opt.hovering && opt.$menu !== null && typeof opt.$menu !== 'undefined') {
                  opt.$menu.trigger('contextmenu:hide');
                }
              }, 50);
            }
          });
 }

i guess that $trigger.outerWidth() and $trigger.outerHeight() could not get the width and height of element,because the element is svg.

kityminder