Bootstrap风格的zTree右键菜单


Posted in Javascript onFebruary 17, 2017

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右键菜单,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JavaScript的面向对象方法以及差别
Mar 31 Javascript
js 跨域和ajax 跨域问题小结
Jul 01 Javascript
有趣的javascript数组定义方法
Sep 10 Javascript
深入理解JavaScript 闭包究竟是什么
Apr 12 Javascript
jquery控制select的text/value值为选中状态
Jun 03 Javascript
深入理解Javascript中this的作用域
Aug 12 Javascript
textarea不能通过maxlength属性来限制字数的解决方法
Sep 01 Javascript
JavaScript循环_动力节点Java学院整理
Jun 28 Javascript
angularjs结合html5实现拖拽功能
Jun 25 Javascript
JavaScript事件对象event用法分析
Jul 27 Javascript
详解vuex之store源码简单解析
Jun 13 Javascript
前端学习——JavaScript原生实现购物车案例
Mar 31 Javascript
js仿新浪微博消息发布功能
Feb 17 #Javascript
babel基本使用详解
Feb 17 #Javascript
JS及JQuery对Html内容编码,Html转义
Feb 17 #Javascript
canvas 实现中国象棋
Feb 17 #Javascript
使用vue.js实现checkbox的全选和多个的删除功能
Feb 17 #Javascript
js实现横向拖拽导航条功能
Feb 17 #Javascript
js转换对象为xml
Feb 17 #Javascript
You might like
选择PHP作为网站开发语言的原因分享
2012/01/03 PHP
Yii把CGridView文本框换成下拉框的方法
2014/12/03 PHP
php单例模式实现方法分析
2015/03/14 PHP
PHP将进程作为守护进程的方法
2015/03/19 PHP
javascript 短路法代码精简
2009/08/20 Javascript
40个有创意的jQuery图片和内容滑动及弹出插件收藏集之二
2011/12/31 Javascript
Jquery颜色选择器ColorPicker实现代码
2012/11/14 Javascript
HTML上传控件取消选择
2013/03/06 Javascript
Jquery加载时从后台读取数据绑定到dropdownList实例
2013/06/09 Javascript
js数组的基本用法及数组根据下标(数值或字符)移除元素
2013/10/20 Javascript
js计算任意值之间随机数的方法
2015/01/16 Javascript
js实现鼠标感应向下滑动隐藏菜单的方法
2015/02/20 Javascript
jQuery实现点击小图显示大图代码分享
2015/08/25 Javascript
js实现倒计时及时间对象
2016/11/15 Javascript
使用vue官方提供的模板vue-cli搭建一个helloWorld案例分析
2018/01/16 Javascript
Vue实现导出excel表格功能
2018/03/30 Javascript
vue-preview动态获取图片宽高并增加旋转功能的实现
2020/07/29 Javascript
Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
2008/09/06 Python
Python实现将目录中TXT合并成一个大TXT文件的方法
2015/07/15 Python
详解Python如何获取列表(List)的中位数
2016/08/12 Python
Python内置函数——__import__ 的使用方法
2017/11/24 Python
python使用pil进行图像处理(等比例压缩、裁剪)实例代码
2017/12/11 Python
python TK库简单应用(实时显示子进程输出)
2019/10/29 Python
Python如何输出百分比
2020/07/31 Python
英国奢侈品概念店:Base Blu
2019/05/16 全球购物
官方授权图形T恤和服装:Fifth Sun
2019/06/12 全球购物
澳大利亚儿童精品仓库:Goo & Co.
2019/06/20 全球购物
澳大利亚最受欢迎的女士度假服装:Kabana Shop
2020/10/10 全球购物
创业计划书中要认真思考的问题
2013/12/28 职场文书
学习新党章思想汇报
2014/01/09 职场文书
2014年幼儿园后勤工作总结
2014/11/10 职场文书
2014年汽车销售工作总结
2014/12/01 职场文书
优秀教师事迹材料
2014/12/15 职场文书
工作迟到检讨书范文
2015/05/06 职场文书
校运会宣传稿大全
2015/07/23 职场文书
办公室规章制度范本
2015/08/04 职场文书