Настройка jstree щелкните правой кнопкой мыши contextmenu для различных типов узлов
Я видел пример где-то в интернете, показывающий, как настроить внешний вид контекстного меню jstree (используя плагин contextmenu).
например, разрешить моим пользователям удалять "документы", но не" папки "(скрыв параметр" Удалить " из контекстного меню для папок).
теперь я не могу найти этот пример. Может ли кто-нибудь указать мне в правильном направлении? Чиновник документация не помощь.
Edit:
Так как я хочу контекстное меню по умолчанию только с одним или двумя незначительными изменениями, я бы предпочел не воссоздавать все меню (хотя, конечно, я буду, если это единственный способ). То, что я хотел бы сделать, это что-то вроде этого:
"contextmenu" : {
items: {
"ccp" : false,
"create" : {
// The item label
"label" : "Create",
// The function to execute upon a click
"action": function (obj) { this.create(obj); },
"_disabled": function (obj) {
alert("obj=" + obj);
return "default" != obj.attr('rel');
}
}
}
}
но это не работает - элемент create всегда отключен (предупреждение никогда не появляется).
6 ответов:
The
contextmenuплагин уже имеет поддержку для этого. Из документации, которую вы связали с:
items: ожидает объект или функция, которая должна возвращать объект. Если функция используется, она запускается в контексте дерева и получает один аргумент - узел, который был щелкнут Правой Кнопкой Мыши.так вместо того, чтобы дать
contextmenuжестко закодированный объект для работы, вы можете предоставить следующую функцию. Он проверяет элемент, который был щелкните по классу с именем " папка "и удалите пункт меню" Удалить", удалив его из объекта:function customMenu(node) { // The default set of all items var items = { renameItem: { // The "rename" menu item label: "Rename", action: function () {...} }, deleteItem: { // The "delete" menu item label: "Delete", action: function () {...} } }; if ($(node).hasClass("folder")) { // Delete the "delete" menu item delete items.deleteItem; } return items; }обратите внимание, что выше будет полностью скрыть опцию удаления, но плагин также позволяет показать элемент при отключении его поведения, добавив
_disabled: trueк соответствующему пункту. В этом случае вы можете использоватьitems.deleteItem._disabled = trueвнутри заявление.должно быть очевидно, но не забудьте инициализировать плагин с
выполнены с различными типами узлов:
$('#jstree').jstree({ 'contextmenu' : { 'items' : customMenu }, 'plugins' : ['contextmenu', 'types'], 'types' : { '#' : { /* options */ }, 'level_1' : { /* options */ }, 'level_2' : { /* options */ } // etc... } });и функция customMenu:
function customMenu(node) { var items = { 'item1' : { 'label' : 'item1', 'action' : function () { /* action */ } }, 'item2' : { 'label' : 'item2', 'action' : function () { /* action */ } } } if (node.type === 'level_1') { delete items.item2; } else if (node.type === 'level_2') { delete items.item1; } return items; }прекрасно работает.
очистить все.
вместо этого:
$("#xxx").jstree({ 'plugins' : 'contextmenu', 'contextmenu' : { 'items' : { ... bla bla bla ...} } });используйте этот:
$("#xxx").jstree({ 'plugins' : 'contextmenu', 'contextmenu' : { 'items' : customMenu } });
Я адаптировать предложенное решение для работы с типами немного по-другому, хотя, возможно, это может помочь кому-то еще:
где #{$id_arr[$k]} - ссылка на контейнер div... в моем случае я использую много деревьев, поэтому весь этот код будет выводиться в браузер, но вы получите идею.. В основном я хочу, чтобы все параметры контекстного меню, но только "создать" и "вставить" на узле диска. Очевидно, с правильными привязками к этим операциям позже:
<div id="$id_arr[$k]" class="jstree_container"></div> </div> </li> <!-- JavaScript neccessary for this tree : {$value} --> <script type="text/javascript" > jQuery.noConflict(); jQuery(function ($) { // This is for the context menu to bind with operations on the right clicked node function customMenu(node) { // The default set of all items var control; var items = { createItem: { label: "Create", action: function (node) { return { createItem: this.create(node) }; } }, renameItem: { label: "Rename", action: function (node) { return { renameItem: this.rename(node) }; } }, deleteItem: { label: "Delete", action: function (node) { return { deleteItem: this.remove(node) }; }, "separator_after": true }, copyItem: { label: "Copy", action: function (node) { $(node).addClass("copy"); return { copyItem: this.copy(node) }; } }, cutItem: { label: "Cut", action: function (node) { $(node).addClass("cut"); return { cutItem: this.cut(node) }; } }, pasteItem: { label: "Paste", action: function (node) { $(node).addClass("paste"); return { pasteItem: this.paste(node) }; } } }; // We go over all the selected items as the context menu only takes action on the one that is right clicked $.jstree._reference("#{$id_arr[$k]}").get_selected(false, true).each(function (index, element) { if ($(element).attr("id") != $(node).attr("id")) { // Let's deselect all nodes that are unrelated to the context menu -- selected but are not the one right clicked $("#{$id_arr[$k]}").jstree("deselect_node", '#' + $(element).attr("id")); } }); //if any previous click has the class for copy or cut $("#{$id_arr[$k]}").find("li").each(function (index, element) { if ($(element) != $(node)) { if ($(element).hasClass("copy") || $(element).hasClass("cut")) control = 1; } else if ($(node).hasClass("cut") || $(node).hasClass("copy")) { control = 0; } }); //only remove the class for cut or copy if the current operation is to paste if ($(node).hasClass("paste")) { control = 0; // Let's loop through all elements and try to find if the paste operation was done already $("#{$id_arr[$k]}").find("li").each(function (index, element) { if ($(element).hasClass("copy")) $(this).removeClass("copy"); if ($(element).hasClass("cut")) $(this).removeClass("cut"); if ($(element).hasClass("paste")) $(this).removeClass("paste"); }); } switch (control) { //Remove the paste item from the context menu case 0: switch ($(node).attr("rel")) { case "drive": delete items.renameItem; delete items.deleteItem; delete items.cutItem; delete items.copyItem; delete items.pasteItem; break; case "default": delete items.pasteItem; break; } break; //Remove the paste item from the context menu only on the node that has either copy or cut added class case 1: if ($(node).hasClass("cut") || $(node).hasClass("copy")) { switch ($(node).attr("rel")) { case "drive": delete items.renameItem; delete items.deleteItem; delete items.cutItem; delete items.copyItem; delete items.pasteItem; break; case "default": delete items.pasteItem; break; } } else //Re-enable it on the clicked node that does not have the cut or copy class { switch ($(node).attr("rel")) { case "drive": delete items.renameItem; delete items.deleteItem; delete items.cutItem; delete items.copyItem; break; } } break; //initial state don't show the paste option on any node default: switch ($(node).attr("rel")) { case "drive": delete items.renameItem; delete items.deleteItem; delete items.cutItem; delete items.copyItem; delete items.pasteItem; break; case "default": delete items.pasteItem; break; } break; } return items; $("#{$id_arr[$k]}").jstree({ // List of active plugins used "plugins" : [ "themes","json_data", "ui", "crrm" , "hotkeys" , "types" , "dnd", "contextmenu"], "contextmenu" : { "items" : customMenu , "select_node": true},
вы можете изменить код @Box9 в соответствии с вашим требованием динамического отключения контекстного меню как:
function customMenu(node) { ............ ................ // Disable the "delete" menu item // Original // delete items.deleteItem; if ( node[0].attributes.yyz.value == 'notdelete' ) { items.deleteItem._disabled = true; } }вам нужно добавить один атрибут " xyz " в ваших данных XML или JSOn
по состоянию на jsTree 3.0.9 мне нужно использовать что-то вроде
var currentNode = treeElem.jstree('get_node', node, true); if (currentNode.hasClass("folder")) { // Delete the "delete" menu item delete items.deleteItem; }, потому что
nodeпредоставленный объект не является объектом jQuery.
Comments