다양한 노드 유형에 대해 jstree 오른쪽 클릭 컨텍스트 메뉴 구성
온라인 어딘가에서 jstree의 오른쪽 클릭 컨텍스트 메뉴 (contextmenu 플러그인 사용)의 모양을 사용자 정의하는 방법을 보여주는 예제를 보았습니다.
예를 들어, 내 사용자가 "문서"는 삭제할 수 있지만 "폴더"는 삭제할 수 없도록 허용합니다 (폴더의 상황에 맞는 메뉴에서 "삭제"옵션을 숨겨서).
이제 그 예를 찾을 수 없습니다. 누구든지 올바른 방향으로 나를 가리킬 수 있습니까? 공식 문서 는 실제로 도움이되지 않았습니다.
편집하다:
하나 또는 두 개의 사소한 변경 만있는 기본 컨텍스트 메뉴를 원하기 때문에 전체 메뉴를 다시 생성하지 않는 것이 좋습니다 (물론 그것이 유일한 방법이라면 할 것입니다). 내가하고 싶은 것은 다음과 같습니다.
"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
작업 할 하드 코딩 된 개체를 제공 하는 대신 다음 함수를 제공 할 수 있습니다. "folder"라는 클래스에 대해 클릭 된 요소를 확인하고 객체에서 삭제하여 "delete"메뉴 항목을 제거합니다.
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()
기능 참조 ) 첫 번째 솔루션에 문제가 없습니다.
그러나 나는 당신이 제안하는 표기법을 좋아하는데, 함수를 _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...
}
});
그리고 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},
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 객체가 아니기 때문 입니다.
'your programing' 카테고리의 다른 글
SVN에서 버전이 지정되지 않은 모든 파일 목록을 얻으려면 어떻게해야합니까? (0) | 2020.10.09 |
---|---|
Eclipse DDMS 오류 "디버거 용 로컬 8600에 바인딩 할 수 없음" (0) | 2020.10.09 |
Matplotlib에서 동일한 그림에 여러 함수를 그리는 방법은 무엇입니까? (0) | 2020.10.09 |
eigenclass가 너무 비슷해 보이지만 self.class와 동등하지 않은 이유는 무엇입니까? (0) | 2020.10.09 |
CSS : "div"안에 "라벨"과 "입력"을 수직으로 정렬하는 방법은 무엇입니까? (0) | 2020.10.09 |