English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Bootstrap 스타일의 zTree 오른쪽 클릭 메뉴

HTML:

<%-- 右键菜单 --%>
<div id="zTreeRightMenuContainer" style="z-index: 9999>
 <%-- 레벨 0 --%>
 <ul class="dropdown-menu" role="menu" level="0">
    <%-- 메뉴 항목에 스타일 'hasChildren'을 추가하고 li 태그 아래에 메뉴 구조를 추가하여 하위 메뉴를 확장할 수 있습니다 --%>
  <li class="hasChildren"><a tabindex="-1" action="refreshzTreeObj">刷新</a>
   <ul class="dropdown-menu" role="menu" level="1">
    <li><a tabindex="-1">将数据库复制到不同的主机/数据库</a></li>
    <li><a tabindex="-1">创建数据库</a></li>
    <li><a tabindex="-1">改变数据库</a></li>
    <li><a tabindex="-1">新数据搜索</a></li>
    <li><a tabindex="-1">创/建</a></li>
    <li><a tabindex="-1">更多数据库操作</a></li>
    <li class="divider"></li>
    <li><a tabindex="-1">备份/导出</a></li>
    <li><a tabindex="-1">导入</a></li>
    <li class="divider"></li>
    <li><a tabindex="-1">在创建数据库架构HTML</a></li>
   </ul>
  </li>
 </ul>
 <%-- 层级 1 --%>
 <ul class="dropdown-menu" role="menu" level="1">
  <li><a tabindex="-1">将数据库复制到不同的主机/数据库</a></li>
  <li><a tabindex="-1">创建数据库</a></li>
  <li><a tabindex="-1">改变数据库</a></li>
  <li><a tabindex="-1">新数据搜索</a></li>
  <li><a tabindex="-1">创/建</a></li>
  <li><a tabindex="-1">更多数据库操作</a></li>
  <li class="divider"></li>
  <li><a tabindex="-1">备份/导出</a></li>
  <li><a tabindex="-1">导入</a></li>
  <li class="divider"></li>
  <li><a tabindex="-1">在创建数据库架构HTML</a></li>
 </ul>
 <%-- 层级 2 --%>
 <ul class="dropdown-menu" role="menu" level="2">
  <li><a tabindex="-1">创建表</a></li>
  <li><a tabindex="-1">将表复制到不同的主机/数据库</a></li>
  <li><a tabindex="-1">数据搜索</a></li>
  <li class="divider"></li>
  <li><a tabindex="-1">计划备份</a></li>
  <li><a tabindex="-1">备份表作为SQL转储</a></li>
 </ul>
</div>

CSS:

/* 右键菜单 - start */
 .dropdown-menu .dropdown-menu {
  position: absolute;
  top: -9px;
  left: 100%;
 }
 .dropdown-menu li {
  position: relative;
 }
 .dropdown-menu li.hasChildren:before {
  content: '';
  position: absolute;
  top: 50%;
  right: 8px;
  width: 0;
  height: 0;
  margin-top: -5px;
  border-style: solid;
  border-color: transparent transparent transparent rgba(0, 0, 0, 0.5);
  border-width: 5px 0 5px 5px;
  pointer-events: none;
 }
 .dropdown-menu li.hasChildren:hover > .dropdown-menu {
  display: block;
 }
 /* 右键菜单 - end */

JS:

/* 以下为右键菜单插件(Bootstrap风格) */
;(function ($) {
 'use strict';
 /* CONTEXTMENU CLASS DEFINITION
  * ============================ */
 var toggle = '[data-toggle="context"]';
 var ContextMenu = function (element, options) {
  this.$element = $(element);
  this.before = options.before || this.before;
  this.onItem = options.onItem || this.onItem;
  this.scopes = options.scopes || null;
  if (options.target) {
   this.$element.data('target', options.target);
  }
  this.listen();
 };
 ContextMenu.prototype = {
  constructor: ContextMenu
  , show: function (e) {
   var $menu;
    , evt;
    , tp
    , items;
    , relatedTarget = {relatedTarget: this, target: e.currentTarget};
   if (this.isDisabled()) return;
   this.closemenu();
   if (this.before.call(this, e, $(e.currentTarget)) === false) return;
   $menu = this.getMenu();
   $menu.trigger(evt = $.Event('show.bs.context', relatedTarget));
   tp = this.getPosition(e, $menu);
   items = 'li:not(.divider)';
   $menu.attr('style', '')
    .css(tp)
    .addClass('open')
    .on('click.context.data-api', items, $.proxy(this.onItem, this, $(e.currentTarget)))
    .trigger('shown.bs.context', relatedTarget);
   // 현재 열린 메뉴에만 `closemenu`를 위임합니다.
   // 이를 통해 다른 열린 메뉴가 닫히지 않도록 합니다.
   $('html')
    .on('click.context.data-api', $menu.selector, $.proxy(this.closemenu, this));
   return false;
  }
  , closemenu: function (e) {
   var $menu;
    , evt;
    , items;
    , relatedTarget;
   $menu = this.getMenu();
   if (!$menu.hasClass('open')) return;
   relatedTarget = {relatedTarget: this};
   $menu.trigger(evt = $.Event('hide.bs.context', relatedTarget));
   items = 'li:not(.divider)';
   $menu.removeClass('open')
    .off('click.context.data',-api', items)
    .trigger('hidden.bs.context', relatedTarget);
   $('html')
    .off('click.context.data',-api', $menu.selector);
   // 클릭 이벤트를 전파하지 마시오 그렇게 하면 현재
   // 개방된 메뉴는 닫지 않습니다.
   if (e) {
    e.stopPropagation();
   }
  }
  , keydown: function (e) {
   if (e.which == 27) this.closemenu(e);
  }
  , before: function (e) {
   return true;
  }
  , onItem: function (e) {
   return true;
  }
  , listen: function () {
   this.$element.on('contextmenu.context.data',-api', this.scopes, $.proxy(this.show, this));
   $('html').on('click.context.data',-api', $.proxy(this.closemenu, this));
   $('html').on('keydown.context.data',-api', $.proxy(this.keydown, this));
  }
  destroy: function () {
   this.$element.off('.context.data',-api').removeData('context');
   $('html').off('.context.data')-api');
  }
  , isDisabled: function () {
   return this.$element.hasClass('disabled') ||
    this.$element.attr('disabled');
  }
  , getMenu: function () {
   var selector = this.$element.data('target')
    , $menu;
   if (!selector) {
    
    selector = selector && selector.replace(/.*(?=#[^\s]*$)/, ''); //strip for ie7
   }
   $menu = $(selector);
   return $menu && $menu.length ? $menu : this.$element.find(selector);
  }
  , getPosition: function (e, $menu) {
   var mouseX = e.clientX
    , mouseY = e.clientY
    , boundsX = $(window).width()
    , boundsY = $(window).height()
    , menuWidth = $menu.find('.dropdown-, menu').outerWidth()
    , menuHeight = $menu.find('.dropdown-menu').outerHeight()
    , tp = {"position": "absolute", "z-index": 9999}
    , Y, X, parentOffset;
   if (mouseY + menuHeight > boundsY) {
    Y = {"top": mouseY - menuHeight + $(window).scrollTop()};
   else {
    Y = {"top": mouseY + $(window).scrollTop()};
   }
   if ((mouseX + menuWidth > boundsX) && ((mouseX - menuWidth) > 0)) {
    X = {"left": mouseX}} - menuWidth + $(window).scrollLeft()};
   else {
    X = {"left": mouseX}} + $(window).scrollLeft()};
   }
   // If context-menu's parent is positioned using absolute or relative positioning,
   // the calculated mouse position will be incorrect.
   // Adjust the position of the menu by its offset parent position.
   parentOffset = $menu.offsetParent().offset();
   X.left = X.left - parentOffset.left;
   Y.top = Y.top - parentOffset.top;
   return $.extend(tp, Y, X);
  }
 };
 /* CONTEXT MENU PLUGIN DEFINITION
  * ========================== */
 $.fn.contextmenu = function (option, e) {
  return this.each(function () {
   var $this = $(this)
    , data = $this.data('context')
    , options = (typeof option == 'object') && option;
   if (!data) $this.data('context', (data = new ContextMenu($this, options)));
   if (typeof option == 'string') data[option].call(data, e);
  });
 };
 $.fn.contextmenu.Constructor = ContextMenu;
 /* APPLY TO STANDARD CONTEXT MENU ELEMENTS
  * =================================== */
 $(document)
  .on('contextmenu.context.data-api', function () {
   $(toggle).each(function () {
    var data = $(this).data('context');
    if (!data) return;
    data.closemenu();
   });
  })
  .on('contextmenu.context.data-api', toggle, function (e) {
   $(this).contextmenu('show', e);
   e.preventDefault();
   e.stopPropagation();
  });
}(jQuery));

/* 이하의 메서드는 위의 js 플러그인으로 래핑된 메서드입니다 */
/*
  parentNode(zTree 컨테이너 또는 지정된 노드)
*/
function initzTreeRightMenu(parentNode) {
 //트리 메뉴 오른쪽 클릭 이벤트
 $('li, a', $(parentNode)).contextmenu({
  target: '#zTreeRightMenuContainer', //이 설정 항목은 zTree의 컨테이너입니다
  before: function (e, element, target) {
   //현재 오른쪽 클릭 노드 ID
   var selectedId = element[0].tagName == 'LI' ? element.attr('id') : element.parent().attr('id');
   //노드 ID에 따라 현재 노드의 상세 정보를 가져옵니다
   curSelectNode = zTreeObj.getNodeByTId(selectedId);
   //현재 노드의 레벨
   var level = curSelectNode.level;
   level = 0;
   //현재 오른쪽 클릭 노드를 선택합니다
   zTreeObj.selectNode(curSelectNode);
   //현재 노드 레벨에 따라相应的 메뉴를 표시합니다
   $('#zTreeRightMenuContainer ul.dropdown-menu[level="' + level + '']].removeClass('hide').siblings().addClass('hide');
  ,
  onItem: function (context, e) {
   var action = $(e.target).attr('action');
   this.closemenu();
   if (action) {
    zTreeRightMenuFuns[action]();
   }
  }
 });
}

단계:

1zTree 관련 js, css 파일을 포함합니다(제가 만든 프로젝트 예시: jquery.ztree.all-3.5.min.js, zTreeStyle.css);

2위에 제공된 오른쪽 클릭 메뉴 플러그인을 js 파일로 저장하고 페이지에 포함합니다(제가 만든 프로젝트 예시: bsContextmenu.js)

3zTree를 페이지 초기화한 후, 위의 메서드를 호출합니다: initzTreeRightMenu('#schemaMgrTree');  // '#schemaMgrTree'는 제가 만든 프로젝트의 zTree 컨테이너 ID입니다

비고:

1zTree에 비동기 로드된 노드가 있을 경우(제가 만든 프로젝트 예시: zTree의 일부 노드는 부모 노드를 펼쳐진 후에 로드된 경우가 있습니다. 이러한 경우, zTree의 onExpandFun에서 현재 노드의 자식 노드를 바인딩해야 합니다)

function onExpandFun(event, treeId, treeNode) {
  /* 현재 노드를 펼치는 동작을 수행하는 코드... *///현재 펼쳐진 노드의 자식 노드에 오른쪽 클릭 이벤트를 바인딩합니다
  initzTreeRightMenu('#'); + treeNode.tId); //treeNode.tId는 현재 펼쳐진 노드의 ID입니다
}

위에 설명한 Bootstrap 스타일의 zTree 오른쪽 클릭 메뉴를 소개해 드렸습니다. 많은 도움이 되길 바랍니다. 어떤 질문이나 의문이 있으시면, 댓글을 남겨 주시면, 편집자가 즉시 답변을 드리겠습니다. 또한, 얼라우 튜토리얼 웹사이트에 대한 많은 지지에 감사드립니다!

선언: 이 문서의 내용은 인터넷에서 가져왔으며, 원작자의 소유물입니다. 인터넷 사용자가 자발적으로 기여하고 자체로 업로드한 내용으로, 이 사이트는 소유권을 가지지 않으며, 인공 편집 처리를 하지 않았으며, 관련 법적 책임도 부담하지 않습니다. 저작권 위반 내용이 있을 경우, 이메일을 notice#w로 보내 주시기 바랍니다.3codebox.com에 신고를 하려면, #을 @으로 변경하여 이메일을 보내고, 관련 증거를 제공해 주세요. 실제로 확인되면, 이 사이트는 즉시 위반된 내용을 삭제합니다.