여러 노드 유형에 대해 jstree 마우스 오른쪽 버튼 클릭 상황에 맞는 메뉴 구성
온라인 어딘가에서 jstree의 오른쪽 클릭 컨텍스트 메뉴(컨텍스트 메뉴 플러그인 사용)의 모양을 사용자 지정하는 방법을 보여주는 예를 보았습니다.
예를 들어, 폴더의 상황에 맞는 메뉴에서 "삭제" 선택사항을 숨겨 사용자가 "문서"는 삭제하지 않고 "폴더"는 삭제할 수 있도록 허용합니다.
지금은 그 예를 찾을 수가 없습니다.누가 제게 올바른 방향을 가르쳐 줄 수 있습니까?공식 문서는 별로 도움이 되지 않았습니다.
편집:
기본 상황에 맞는 메뉴를 한두 개만 변경하고 싶으므로 전체 메뉴를 재생성하지 않는 것이 좋습니다(단, 유일한 방법이라면 당연히 재생성합니다).제가 하고 싶은 것은 다음과 같습니다.
"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');
}
}
}
}
그러나 작동하지 않습니다. 생성 항목이 항상 비활성화되어 있을 뿐입니다(알림은 나타나지 않습니다).
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
내에if
대신 진술.
.customMenu
이전에 사용했던 기능 대신 기능:
$("#tree").jstree({plugins: ["contextmenu"], contextmenu: {items: customMenu}});
// ^
// ___________________________________________________________________|
편집: 우클릭할 때마다 메뉴를 재생성하지 않으려면 삭제 메뉴 항목 자체에 대한 작업 처리기에 로직을 넣을 수 있습니다.
"label": "Delete",
"action": function (obj) {
if ($(this._get_node(obj)).hasClass("folder") return; // cancel action
}
다시 편집:jsTree 소스 코드를 보고 나면 어차피 표시될 때마다 컨텍스트 메뉴가 다시 생성되는 것 같습니다( 참조).show()
그리고.parse()
functions)를 선택할 수 있으므로 첫 번째 솔루션에 문제가 없다고 봅니다.
, 에 . 함수를 다음의 값으로._disabled
할 수 인 경로는 의 . .을 포장하는 입니다.parse()
합니다에서 합니다.disabled: function () {...}
합니다._disabled
에, parse()
.
그들의 소스 코드를 직접 수정하는 것도 어렵지 않을 것입니다.버전 1.0-rc1의 라인 2867이 관련된 것입니다.
str += "<li class='" + (val._class || "") + (val._disabled ? " jstree-contextmenu-disabled " : "") + "'><ins ";
를 하는 줄 할 수 .$.isFunction(val._disabled)
, 만약 그렇다면,val._disabled = val._disabled()
그럼 제작자분들께 패치로 제출해주세요 :)
다양한 노드 유형으로 구현:
$('#jstree').jstree({
'contextmenu' : {
'items' : customMenu
},
'plugins' : ['contextmenu', 'types'],
'types' : {
'#' : { /* options */ },
'level_1' : { /* options */ },
'level_2' : { /* options */ }
// etc...
}
});
그리고 사용자 지정 메뉴 기능:
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 컨테이너의 참조인 경우...제 경우에는 제가 많은 트리를 사용하기 때문에 이 코드들은 브라우저로 출력될 것입니다. 하지만 당신은 그 아이디어를 알고 있습니다.기본적으로 드라이브 노드에서 'Create'와 'Paste'만 빼고 모든 컨텍스트 메뉴 옵션을 원합니다.다음 작업에 대한 정확한 바인딩을 통해 다음 작업을 수행할 수 있습니다.
<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},
Btw: 기존 컨텍스트 메뉴에서 옵션을 제거하고 싶다면 이 방법이 효과가 있었습니다.
function customMenu(node)
{
var items = $.jstree.defaults.contextmenu.items(node);
if (node.type === 'root') {
delete items.create;
delete items.rename;
delete items.remove;
delete items.ccp;
}
return items;
}
상황에 맞는 메뉴를 동적으로 비활성화해야 하는 요구 사항에 맞게 @Box9 코드를 다음과 같이 수정할 수 있습니다.
function customMenu(node) {
............
................
// Disable the "delete" menu item
// Original // delete items.deleteItem;
if ( node[0].attributes.yyz.value == 'notdelete' ) {
items.deleteItem._disabled = true;
}
}
XML 또는 JSon 데이터에 하나의 속성 "xyz"를 추가해야 합니다.
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 개체가 아닙니다.
데이빗의 대응은 훌륭하고 효율적인 것 같습니다.a_attr 속성을 사용하여 다른 노드를 구별하고 이를 기반으로 다른 컨텍스트 메뉴를 생성할 수 있는 솔루션의 또 다른 변형을 찾았습니다.
아래 예제에서는 두 가지 유형의 노드 Folder와 Files를 사용했습니다.저도 글리폰을 이용해서 여러 가지 아이콘을 써본 적이 있습니다.파일 형식 노드의 경우 이름을 바꾸고 제거할 컨텍스트 메뉴만 얻을 수 있습니다.폴더의 경우, 모든 옵션은 파일 작성, 폴더 작성, 이름 변경, 제거입니다.
전체 코드 조각을 보려면 https://everyething.com/Example-of-jsTree-with-different-context-menu-for-different-node-type 을 확인할 수 있습니다.
$('#SimpleJSTree').jstree({
"core": {
"check_callback": true,
'data': jsondata
},
"plugins": ["contextmenu"],
"contextmenu": {
"items": function ($node) {
var tree = $("#SimpleJSTree").jstree(true);
if($node.a_attr.type === 'file')
return getFileContextMenu($node, tree);
else
return getFolderContextMenu($node, tree);
}
}
});
초기 json 데이터는 아래와 같으며, 여기서 노드 유형은 a_attr 내에 언급됩니다.
var jsondata = [
{ "id": "ajson1", "parent": "#", "text": "Simple root node", icon: 'glyphicon glyphicon-folder-open', "a_attr": {type:'folder'} },
{ "id": "ajson2", "parent": "#", "text": "Root node 2", icon: 'glyphicon glyphicon-folder-open', "a_attr": {type:'folder'} },
{ "id": "ajson3", "parent": "ajson2", "text": "Child 1", icon: 'glyphicon glyphicon-folder-open', "a_attr": {type:'folder'} },
{ "id": "ajson4", "parent": "ajson2", "text": "Child 2", icon: 'glyphicon glyphicon-folder-open', "a_attr": {type:'folder'} },
];
파일과 폴더를 만들기 위한 연결 메뉴 항목의 일부로 아래와 유사한 코드를 파일 작업으로 사용합니다.
action: function (obj) {
$node = tree.create_node($node, { text: 'New File', icon: 'glyphicon glyphicon-file', a_attr:{type:'file'} });
tree.deselect_all();
tree.select_node($node);
}
폴더 작업으로:
action: function (obj) {
$node = tree.create_node($node, { text: 'New Folder', icon:'glyphicon glyphicon-folder-open', a_attr:{type:'folder'} });
tree.deselect_all();
tree.select_node($node);
}
여기 제 전체 플러그인 설정이 있습니다.
var ktTreeDocument = $("#jstree_html_id");
jQuery(document).ready(function () {
DocumentKTTreeview.init();
});
var DocumentKTTreeview = function() {
var treeDocument = function() {
ktTreeDocument.jstree({
"core": {
"themes": {
"responsive": false
},
"check_callback": function(operation, node, node_parent, node_position, more) {
documentAllModuleObj.selectedNode = ktTreeDocument.jstree().get_selected('full', true);
if (operation === 'delete_node') {
if (!confirm('are you sure?')) {
return false;
}
}
return true;
},
'data': {
'dataType': 'json',
'url': BASE_URL + ('tree/get/?lazy'),
'data': function(node) {
return { 'id': node.id };
}
},
},
"types": {
"default": {
"icon": "fa fa-folder kt-font-success"
},
"file": {
"icon": "fa fa-file kt-font-success"
}
},
"state": { "key": "demo2" },
"plugins": ["contextmenu", "dnd", "state", "types"],
"contextmenu": {
"items": function($node) {
var tree = $("#jstree_html_id").jstree(true);
return {
"Create": {
"separator_before": false,
"separator_after": false,
"label": "Create",
"action": function(obj) {
tree.create_node($node);
}
},
"Rename": {
"separator_before": false,
"separator_after": false,
"label": "Rename",
"action": function(obj) {
tree.edit($node);
}
},
"Remove": {
"separator_before": false,
"separator_after": false,
"_disabled": $node.original.root ? true : false,
"label": "Remove",
"action": function(obj) {
tree.delete_node($node);
}
}
};
}
}
})
}
return {
init: function() {
treeDocument();
}
};
}();
언급URL : https://stackoverflow.com/questions/4559543/configuring-jstree-right-click-contextmenu-for-different-node-types
'programing' 카테고리의 다른 글
angularjs 및 local스토리지 변경 이벤트 (0) | 2023.10.16 |
---|---|
null-terminal이 아닌 문자열의 strstr() (0) | 2023.10.16 |
Jest와 함께 하나의 테스트만 실행 (0) | 2023.10.16 |
속성 유형이 내부 유형을 사용하므로 public으로 선언할 수 없습니다. (0) | 2023.10.16 |
wo commerce는 제품을 카트에 추가한 후 firefox에서 카트가 비어 있다고 표시합니다. (0) | 2023.10.16 |