欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Bootstrap风格的zTree右键菜单

程序员文章站 2023-12-06 11:54:16
html: <%-- 右键菜单 --%>

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);
   // delegating the `closemenu` only on the currently opened menu.
   // this prevents other opened menus from closing.
   $('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);
   // don't propagate click event so other currently
   // opened menus won't close.
   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 = this.$element.attr('href');
    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]();
   }
  }
 });
}

步骤:

1、引入ztree相关js、css文件(以我自己的项目为例:jquery.ztree.all-3.5.min.js,ztreestyle.css);

2、将上面给出的右键菜单插件另存为js文件引入页面(以我自己的项目为例:bscontextmenu.js)

3、在页面初始化ztree之后,调用上面的方法:initztreerightmenu('#schemamgrtree');  // ‘#schemamgrtree' 是我自己项目的ztree容器id

备注:

1、假如ztree中有异步载入的节点(以我自己项目为例:ztree中有部分节点是展开了父节点之后才加载的,像这种情况则需要在 ztree 的 onexpandfun 里面绑定当前节点的子节点)

function onexpandfun(event, treeid, treenode) {
  /* 展开当前节点执行的代码.... *///绑定当前展开节点的子节点右击事件
  initztreerightmenu('#' + treenode.tid); //treenode.tid 是当前展开节点的id
}

以上所述是小编给大家介绍的bootstrap风格的ztree右键菜单,希望对大家有所帮助