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

Menú contextual de zTree con estilo Bootstrap

HTML:

<%-- 右键菜单 --%>
<div id="zTreeRightMenuContainer" style="z-index: 9999>
 <%-- Nivel 0 --%>
 <ul class="dropdown-menu" role="menu" level="0">
    <%-- A través de agregar estilos "hasChildren" a los elementos del menú y agregar la estructura del menú debajo de las etiquetas li, se puede expandir el menú de nivel inferior --%>
  <li class="hasChildren"><a tabindex="-1" action="refreshzTreeObj">Refresh/a>
   <ul class="dropdown-menu" role="menu" level="1">
    <li><a tabindex="-1">Copy database to a different host/Database</a></li>
    <li><a tabindex="-1">Create database</a></li>
    <li><a tabindex="-1">Modify database</a></li>
    <li><a tabindex="-1">New data search</a></li>
    <li><a tabindex="-1">Create/Build</a></li>
    <li><a tabindex="-1">More database operations</a></li>
    <li class="divider"></li>
    <li><a tabindex="-1">Backup/Export</a></li>
    <li><a tabindex="-1">Import</a></li>
    <li class="divider"></li>
    <li><a tabindex="-1">Create database architecture HTML</a></li>
   </ul>
  </li>
 </ul>
 <%-- Level 1 --%>
 <ul class="dropdown-menu" role="menu" level="1">
  <li><a tabindex="-1">Copy database to a different host/Database</a></li>
  <li><a tabindex="-1">Create database</a></li>
  <li><a tabindex="-1">Modify database</a></li>
  <li><a tabindex="-1">New data search</a></li>
  <li><a tabindex="-1">Create/Build</a></li>
  <li><a tabindex="-1">More database operations</a></li>
  <li class="divider"></li>
  <li><a tabindex="-1">Backup/Export</a></li>
  <li><a tabindex="-1">Import</a></li>
  <li class="divider"></li>
  <li><a tabindex="-1">Create database architecture HTML</a></li>
 </ul>
 <%-- Level 2 --%>
 <ul class="dropdown-menu" role="menu" level="2">
  <li><a tabindex="-1">Create table</a></li>
  <li><a tabindex="-1">Copy table to a different host/Database</a></li>
  <li><a tabindex="-1">Data search</a></li>
  <li class="divider"></li>
  <li><a tabindex="-1">Schedule backup</a></li>
  <li><a tabindex="-1">Backup table as SQL dump</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 = opciones.before || this.before;
  this.onItem = opciones.onItem || this.onItem;
  this.scopes = opciones.scopes || null;
  if (opciones.target) {
   this.$element.data('target', opciones.target);
  }
  this.listen();
 };
 ContextMenu.prototype = {
  constructor: ContextMenu
  , mostrar: function (e) {
   var $menu
    , evt
    , tp
    , items
    , relatedTarget = {relatedTarget: this, target: e.currentTarget};
   if (this.isDisabled()) devolver;
   this.closemenu();
   if (this.before.call(this, e, $(e.currentTarget)) === false) devolver;
   $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);
   // Delegar `closemenu` solo en el menú abierto actualmente.
   // Esto previene que otros menús abiertos se cierren.
   $('html')
    .on('click.context.data-api', $menu.selector, $.proxy(this.closemenu, this));
   devolver falso;
  }
  , 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);
   // No propague el evento de clic para que otros eventos
   // Los menús abiertos no se cerrarán.
   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));

/* Los siguientes métodos son métodos encapsulados por el plugin js anterior */
/*
  parentNode (contenedor de zTree o nodo especificado)
*/
function initzTreeRightMenu(parentNode) {
 //Evento de clic derecho del menú de árbol
 $('li, a', $(parentNode)).contextmenu({
  target: '#zTreeRightMenuContainer', //Esta opción de configuración es el contenedor de zTree
  before: function (e, element, target) {
   //ID del nodo derecho clickeado
   var selectedId = element[0].tagName == 'LI' ? element.attr('id') : element.parent().attr('id');
   //Obtener detalles del nodo actual según el ID del nodo
   curSelectNode = zTreeObj.getNodeByTId(selectedId);
   //Nivel del nodo actual
   var level = curSelectNode.level;
   level = 0;
   //Seleccionar el nodo derecho clickeado
   zTreeObj.selectNode(curSelectNode);
   //Mostrar el menú correspondiente al nivel del nodo actual
   $('#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]();
   }
  }
 });
}

Pasos:

1Introduzca los archivos js y css relacionados de zTree (tomando mi proyecto como ejemplo: jquery.ztree.all-3.5.min.js, zTreeStyle.css);

2Almacene el plugin de menú contextual derecho proporcionado anteriormente como archivo js y áloje en la página (tomando mi proyecto como ejemplo: bsContextmenu.js)

3Después de inicializar zTree en la página, llame al método anterior: initzTreeRightMenu('#schemaMgrTree');  // '#schemaMgrTree' es el ID del contenedor de zTree en mi proyecto

Notas:

1Supongamos que zTree tiene nodos cargados de manera asincrónica (tomando mi proyecto como ejemplo: algunos nodos de zTree son expandidos y luego se cargan, en este caso,则需要 en el onExpandFun de zTree enlazar los nodos subyacentes del nodo actual)

function onExpandFun(event, treeId, treeNode) {
  /* Código ejecutado al expandir el nodo actual... *///Asignar evento de clic derecho en el nodo subyacente del nodo actualmente expandido
  initzTreeRightMenu('#' + treeNode.tId); //treeNode.tId es el ID del nodo actualmente expandido
}

Lo anterior es el menú contextual de estilo Bootstrap que el editor le ha presentado a todos, esperamos que sea útil para ustedes. Si tienen alguna pregunta, déjenos un mensaje y el editor responderá a tiempo. También agradecemos enormemente el apoyo de todos a la página web de la教程 de alarido!

Declaración: El contenido de este artículo se obtiene de la red, pertenece al autor original, el contenido se contribuye y sube por los usuarios de Internet, este sitio no posee los derechos de propiedad, no se ha realizado un procesamiento editorial humano y no asume la responsabilidad legal relevante. Si encuentra contenido sospechoso de copyright, por favor envíe un correo electrónico a: notice#oldtoolbag.com (al enviar un correo electrónico, reemplace # con @) para denunciar y proporcionar evidencia relevante. Una vez verificada, este sitio eliminará inmediatamente el contenido sospechoso de infracción.

Te gustará