demo/sample-3rd-contextmenu-abs.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Fancytree - Example: Context Menu</title>
<script src="//code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="//code.jquery.com/ui/1.13.0/jquery-ui.min.js"></script>
<link href="../src/skin-win8/ui.fancytree.css" rel="stylesheet">
<script src="../src/jquery.fancytree.js"></script>
<script src="../src/jquery.fancytree.dnd.js"></script>
<!-- jquery.contextmenu, A Beautiful Site (http://abeautifulsite.net/) -->
<script src="../lib/contextmenu-abs/jquery.contextMenu-custom.js"></script>
<link href="../lib/contextmenu-abs/jquery.contextMenu.css" rel="stylesheet" >
<!-- Start_Exclude: This block is not part of the sample code -->
<link href="../lib/prettify.css" rel="stylesheet">
<script src="../lib/prettify.js"></script>
<link href="sample.css" rel="stylesheet">
<script src="sample.js"></script>
<!-- End_Exclude -->
<script type="text/javascript">
// --- Implement Cut/Copy/Paste --------------------------------------------
var clipboardNode = null;
var pasteMode = null;
function copyPaste(action, node) {
switch( action ) {
case "cut":
case "copy":
clipboardNode = node;
pasteMode = action;
break;
case "paste":
if( !clipboardNode ) {
alert("Clipoard is empty.");
break;
}
if( pasteMode == "cut" ) {
// Cut mode: check for recursion and remove source
var cb = clipboardNode.toDict(true);
if( node.isDescendantOf(cb) ) {
alert("Cannot move a node to it's sub node.");
return;
}
node.addChildren(cb);
node.render();
clipboardNode.remove();
} else {
// Copy mode: prevent duplicate keys:
var cb = clipboardNode.toDict(true, function(dict, node){
dict.title = "Copy of " + dict.title;
delete dict.key; // Remove key, so a new one will be created
});
alert("cb = " + JSON.stringify(cb));
// node.addChildren(cb);
// node.render();
node.applyPatch(cb);
}
clipboardNode = pasteMode = null;
break;
default:
alert("Unhandled clipboard action '" + action + "'");
}
};
// --- Contextmenu helper --------------------------------------------------
function bindContextMenu(span) {
// Add context menu to this node:
$(span).contextMenu({menu: "myMenu"}, function(action, el, pos) {
// The event was bound to the <span> tag, but the node object
// is stored in the parent <li> tag
var node = $.ui.fancytree.getNode(el);
switch( action ) {
case "cut":
case "copy":
case "paste":
copyPaste(action, node);
break;
default:
alert("Todo: appply action '" + action + "' to node " + node);
}
});
};
// --- Init fancytree during startup ----------------------------------------
$(function(){
$("#tree").fancytree({
extensions: ["dnd"],
activate: function(event, data) {
var node = data.node;
$("#echoActivated").text(node.title + ", key=" + node.key);
},
click: function(event, data) {
// Close menu on click
if( $(".contextMenu:visible").length > 0 ){
$(".contextMenu").hide();
// return false;
}
},
keydown: function(event, data) {
var node = data.node;
// Eat keyboard events, when a menu is open
if( $(".contextMenu:visible").length > 0 )
return false;
switch( event.which ) {
// Open context menu on [Space] key (simulate right click)
case 32: // [Space]
$(node.span).trigger("mousedown", {
preventDefault: true,
button: 2
})
.trigger("mouseup", {
preventDefault: true,
pageX: node.span.offsetLeft,
pageY: node.span.offsetTop,
button: 2
});
return false;
// Handle Ctrl-C, -X and -V
case 67:
if( event.ctrlKey ) { // Ctrl-C
copyPaste("copy", node);
return false;
}
break;
case 86:
if( event.ctrlKey ) { // Ctrl-V
copyPaste("paste", node);
return false;
}
break;
case 88:
if( event.ctrlKey ) { // Ctrl-X
copyPaste("cut", node);
return false;
}
break;
}
},
/*Bind context menu for every node when its DOM element is created.
We do it here, so we can also bind to lazy nodes, which do not
exist at load-time. (abeautifulsite.net menu control does not
support event delegation)*/
createNode: function(event, data){
bindContextMenu(data.node.span);
},
/*Load lazy content (to show that context menu will work for new items too)*/
lazyLoad: function(event, data){
data.result = {url: "sample-data2.json"};
},
/* D'n'd, just to show it's compatible with a context menu.
See http://code.google.com/p/dynatree/issues/detail?id=174 */
dnd: {
preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
autoExpandMS: 400,
dragStart: function(node, data) {
return true;
},
dragEnter: function(node, data) {
// return true;
if(node.parent !== data.otherNode.parent)
return false;
return ["before", "after"];
},
dragDrop: function(node, data) {
data.otherNode.moveTo(node, data.hitMode);
}
}
});
});
</script>
</head>
<body class="example">
<h1>Example: Context Menu</h1>
<div class="description">
Implementation of a context menu. Right-click a node and see what happens.
<ul>
<li>Also [space] key is supported to open the menu.
<li>This example also demonstrates, how to copy or move branches and how
to implement clipboard functionality.
<li>A keyboard handler implements Cut, Copy, and Paste with <kbd>Ctrl-X</kbd>,
<kbd>Ctrl-C</kbd>, <kbd>Ctrl-V</kbd>.
</ul>
This sample uses the jQuery Context Menu Plugin by Cory S.N. LaViska.
Visit <a href="http://abeautifulsite.net/">A Beautiful Site</a> for usage and more information.
<br>
<b>NOTE:</b></br>
I had to <a href="http://code.google.com/p/dynatree/issues/detail?id=174">patch Cory's code</a> in order to make it work. Please understand, that I am not able to support this plugin. There are many other context menus
out there :-)
</div>
<div>
<label for="skinswitcher">Skin:</label> <select id="skinswitcher"></select>
</div>
<!-- Definition of context menu -->
<ul id="myMenu" class="contextMenu">
<li class="edit"><a href="#edit">Edit</a></li>
<li class="cut separator"><a href="#cut">Cut</a></li>
<li class="copy"><a href="#copy">Copy</a></li>
<li class="paste"><a href="#paste">Paste</a></li>
<li class="delete"><a href="#delete">Delete</a></li>
<li class="quit separator"><a href="#quit">Quit</a></li>
</ul>
<!-- Definition tree structure -->
<div id="tree">
<ul>
<li id="id1" title="Look, a tool tip!">item1 with key and tooltip
<li id="id2" class="activate">item2: activated on init
<li id="id3" class="folder">Folder with some children
<ul>
<li id="id3.1">Sub-item 3.1
<li id="id3.2">Sub-item 3.2
</ul>
<li id="id4" class="expanded">Document with some children (expanded on init)
<ul>
<li id="id4.1">Sub-item 4.1
<li id="id4.2">Sub-item 4.2
</ul>
<li id="id5" class="lazy folder">Lazy folder
</ul>
</div>
<div>Selected node: <span id="echoActivated">-</span></div>
<!-- Start_Exclude: This block is not part of the sample code -->
<hr>
<p class="sample-links no_code">
<a class="hideInsideFS" href="https://github.com/mar10/fancytree">jquery.fancytree.js project home</a>
<a class="hideOutsideFS" href="#">Link to this page</a>
<a class="hideInsideFS" href="index.html">Example Browser</a>
<a href="#" id="codeExample">View source code</a>
</p>
<pre id="sourceCode" class="prettyprint" style="display:none"></pre>
<!-- End_Exclude -->
</body>
</html>