Capturing the newly created node with JSTree contextmenu - javascript

I'm trying to capture the name of the newly created node with jstree's contextmenu. I can capture the name of the parent node that I'm adding the new node under (with obj.text()), however, what I really need is the name of the newly created node.
So, somehow, there needs to be an "onChange" event that can be called within jstree contextmenu that fires once the user hits enter on that newly created node?
Any ideas? I've enclosed the contextmenu code:
}).jstree({
json_data: {
data: RBSTreeModel,
ajax: {
type: "POST",
data: function (n) {
return {
NodeID: n.attr("id").substring(4),
Level: n.attr("name").substring(7)
};
},
url: function (node) {
return "/Audit/GetRequirementsTreeStructure";
},
success: function (new_data) {
return new_data;
}
}
},
contextmenu: {
items: function($node) {
return {
createItem : {
"label" : "Create New Branch",
"action" : function(obj) { this.create(obj); alert(obj.text())},
"_class" : "class"
},
renameItem : {
"label" : "Rename Branch",
"action" : function(obj) { this.rename(obj);}
},
deleteItem : {
"label" : "Remove Branch",
"action" : function(obj) { this.remove(obj); }
}
};
}
},
plugins: ["themes", "json_data", "ui", "crrm", "contextmenu"]
});

You can bind to the "create.jstree" event, which will fire after a node is created. In the callback of that event, you will have access to the newly created node and can rollback/revert the create node action if you choose. The documentation for it is lacking, but there is an example on the demo page. Here is another example that came from my code:
}).jstree({... You jstree setup code...})
.bind("create.jstree", function(e, data) {
// use your dev tools to examine the data object
// It is packed with lots of useful info
// data.rslt is your new node
if (data.rslt.parent == -1) {
alert("Can not create new root directory");
// Rollback/delete the newly created node
$.jstree.rollback(data.rlbk);
return;
}
if (!FileNameIsValid(data.rslt.name)) {
alert("Invalid file name");
// Rollback/delete the newly created node
$.jstree.rollback(data.rlbk);
return;
}
.. Your code etc...
})

Based on Bojin Li's answer, it seems that the latest version of jsTree uses the event "create_node" instead of "create":
}).jstree({... You jstree setup code...})
.bind("create_node.jstree", function(e, data) {
...
});

Related

Jstree save tree to xml file after drag and drop

using jstree plugin I input the tree data from an xml file. I need to save the xml data after drag and drop operation on a button click.
The data.inst.get_xml("nest", -1, li_attr, a_attr) event gives the current xml. How do I save this to an xml file in MVC 3 view
This is the javascript used to render the tree-
$(document).ready(function () {
li_attr = ["id", "class"];
a_attr = ["href"];
$("#Sampletree").jstree({
"xml_data": {
"ajax": {
"url": "../../Content/Files/Sample.xml"
},
"xsl": "nest"
},
"plugins": ["themes", "xml_data", "dnd", "ui"
},
{
"dnd": {
"drop_finish": function () {
alert("DROP");
},
"drag_check": function (data) {
if (data.r.attr("id") == "phtml_1") {
return false;
}
return {
after: false,
before: false,
inside: true
};
},
"drag_finish": function (data) {
alert("DRAG OK");
}
}
})
.bind("select_node.jstree", function (e, data) {
alert(data.inst.get_xml("nest", -1, li_attr, a_attr)
});
});
The data.inst.get_xml("nest", -1, li_attr, a_attr) event gives the current xml as a string. Set this as a hidden input field. This hidden field value can be received while submitting the form. The rest can take care by the controller.
Cheers,
Princi

Set jsTree Node to "Undetermined" State

I'm using jsTree to show a tree with checkboxes. Each level of nodes is loaded on-demand using the json_data plugin.
If a node's descendent is checked, then that node should be in an "undetermined state" (like ACME and USA).
The problem is, the tree starts out collapsed. ACME looks unchecked but should be undetermined. When I finally expand to a checked node, jsTree realizes the ancestors should be undetermined.
So I need to be able to put a checkbox in the undetermined state without loading its children.
With jsTree you can pre-check a box by adding the jstree-checked class to the <li>. I tried adding the jstree-undetermined class, but it doesn't work. It just puts them in a checked state.
Here's my code:
$("#tree").jstree({
plugins: ["json_data", "checkbox"],
json_data: {
ajax: {
url: '/api/group/node',
success: function (groups) {
var nodes = [];
for (var i=0; i<groups.length; i++) {
var group = groups[i];
var cssClass = "";
if(group.isSelected)
cssClass = "jstree-checked";
else if(group.isDecendantSelected)
cssClass = "jstree-undetermined";
nodes.push({
data: group.name,
attr: { 'class': cssClass }
});
}
return nodes;
}
}
}
})
My Question
How do I set a node to the undetermined state?
I had the same problem and the solution I found was this one:
var tree = $("#tree").jstree({
plugins: ["json_data", "checkbox"],
json_data: {
ajax: {
url: '/api/group/node',
success: function(groups) {
var nodes = [];
for (var i = 0; i < groups.length; i++) {
var group = groups[i];
var checkedState = "false";
if (group.isSelected)
checkedState = "true";
else if (group.isDecendantSelected)
checkedState = "undetermined";
nodes.push({
data: group.name,
attr: { 'checkedNode': checkedState }
});
}
return nodes;
},
complete: function () {
$('li[checkedNode="undetermined"]', tree).each(function () {
$(this).removeClass('jstree-unchecked').removeClass('jstree-checked').addClass('jstree-undetermined');
});
$('li[checkedNode="true"]', tree).each(function () {
$(this).removeClass('jstree-unchecked').removeClass('jstree-undetermined').addClass('jstree-checked');
});
$('li[checkedNode="false"]', tree).each(function () {
$(this).removeClass('jstree-checked').removeClass('jstree-undetermined').addClass('jstree-unchecked');
});
}
}
}
});
Hope it helps you!
Maybe this changed in the meanwhile...
But now (version 3.0.0) the really simple solution works:
{
id : "string" // will be autogenerated if omitted
text : "string" // node text
icon : "string" // string for custom
state : {
opened : boolean // is the node open
disabled : boolean // is the node disabled
selected : boolean // is the node selected
undetermined : boolean // is the node undetermined <<==== HERE: JUST SET THIS
},
children : [] // array of strings or objects
li_attr : {} // attributes for the generated LI node
a_attr : {} // attributes for the generated A node
}
Learned directly from the source code at: https://github.com/vakata/jstree/blob/6507d5d71272bc754eb1d198e4a0317725d771af/src/jstree.checkbox.js#L318
Thank you guys, and I found an additional trick which makes life a little better, but it requires a code change in jstree.js. Looks like an oversight:
Look at the get_undetermined function, and scan for the keyword break. That break should be a continue.
If you make that one change, then all you need to do is provide the state (for the main object and its children), and jstree will automatically take care of cascading upwards for undetermined state. It was bailing out early from the scripting and failing to catch all the undetermined nodes properly, requiring the above ugly workarounds for styling and such.
Here's my config (no special attrs or complete() function required) using AJAX:
var tree = $('#jstree').jstree({
"core": {
"themes": {
"variant": "large"
},
'data': {
'url': function (node) {
return "{{API}}/" + node.id + "?product_id={{Product.ID}}"
},
'dataType': 'json',
'type': 'GET',
'success': function (data) {
if (data.length == 0) {
data = rootStub
}
return {
'id': data.id,
'text': data.text,
'children': data.children,
'state': data.state,
}
}
}
},
"checkbox": {
// "keep_selected_style": false,
"three_state": false,
"cascade": "undetermined"
},
"plugins": ["wholerow", "checkbox"],
});

JsTree contextmenu error

A javascript error indicating that this.rename(obj) is not defined when selecting to rename a node.
JavaScript runtime error: Object doesn't support property or method 'rename'
$(document).ready(function () {
$('#marketing-category-tree').jstree({
themes: {
theme: "default",
dots: true,
icons: true
},
contextmenu: {
items: {
"rename" : {
"label": "Rename",
"action": function (obj) { this.rename(obj); }
}
}
},
plugins: ["themes", "html_data", "ui", "crrm", "contextmenu"]
})
.bind("rename.jstree", function (e, data) {
debugger;
alert("RENAMING!!!");
});
});
I have also tried the following code and am able to select and do a rename but cannot capture the change event.
$('#marketing-category-tree').jstree({
themes: {
theme: "default",
dots: true,
icons: true
},
plugins: ["themes", "html_data", "ui", "crrm", "contextmenu"]
})
.bind("rename.jstree", function (e, data) {
alert("RENAMING!!!");
});
I think the method you are looking for is edit. But first you have to get the node of the tree. Try to use this code below:
...
"contextmenu" : {
"items" : renameItem : { // The "rename" menu item
label : "Rename",
action : function (obj) {
n = $('#marketing-category-tree').jstree(true).get_node(obj.reference); //get node
$('#marketing-category-tree').jstree(true).edit(n); //puts the node into edit mode
}
}
}
...
HTH
Your first code example ain't gonna work because
"action": function (obj) { this.rename(obj); }
in this case "this" is a point to Window object the next things is that documentation http://www.jstree.com/api/ doesn't have mentions of method rename and only rename_node
Here is the working example (right click at any node and then click on rename)
http://jsfiddle.net/w9snc6z1/4/
Pay attention that rename_node also not working but according to documentation
set_text: set the text value of a node. Used internally, please use rename_node(obj, val).
it's not recommended to use set_text instead of rename_node.
you should get node of the tree with var tree = $("#marketing-category-tree").jstree(true);then operate on nodes.
u can use this example
goodluck
:)

How do I get the id of a newly created created node from data.args?

I would like to display a fancybox when a user clicks the Create button to have them fill in a form. This is used to capture additional data and associate it with the newly created node in jsTree. I need to get the ID of the newly created node and pass it along as a GET parameter in the fancybox call. So far I just can't seem to figure out how to get the ID.
Here is what I have so far:
$("#demo").jstree({
// List of active plugins
"plugins" : ["themes", "json_data", "ui", "crrm", "cookies", "dnd", "search", "types", "hotkeys", "contextmenu", "unique"],
.bind("create.jstree", function (e, data) {
$.post(
"server.php",
{
"operation" : "create_node",
"id" : data.rslt.parent.attr("id").replace("node_",""),
"position" : data.rslt.position,
"title" : data.rslt.name,
"type" : data.rslt.obj.attr("rel")
},
function (r) {
if(r.status) {
$(data.rslt.obj).attr("id", "node_" + r.id);
}else{
$.jstree.rollback(data.rlbk);
}
}
);
})
$("#demo").bind("before.jstree", function (e, data) {
if(data.func === "create") {
var id = data.args[0].attr("id").replace("node_","");
showFancybox("edit_task.php?action=create&parent_id="+id);
}
})
// Code for the menu buttons
$(function () {
$("#mmenu input").click(function () {
switch(this.id) {
case "add_default":
case "add_folder":
$("#demo").jstree("create", null, "last", { "attr" : { "rel" : this.id.toString().replace("add_", "") } });
break;
case "search":
$("#demo").jstree("search", document.getElementById("search_text").value);
break;
case "text": break;
default:
$("#demo").jstree(this.id);
break;
}
});
});
The code that I have now finds the parent id before the new node is created. I tried waiting a few seconds and then trying to read the newest entry from the database, but this doesn't work very reliably and is slower than needed. How can I get the new node's ID from jsTree once it's been created and added to the database?
This works:
id = data.args[0].attr("id");

[jsTree]: why the 'rename' and 'move' events are not fired with new nodes?

I am using jstree for a tree view in a web page.
The tree makes possible to rename and move nodes. Moving or renaming a node fires the rename_node.jstree and rename_node.jstree events.
With new nodes (created with rename_node.jstree events), the node can still be renamed and moved but the move_node.jstree and rename_node.jstree events are not fired.
It seems that the events are only bound with the inital nodes. I don't see any 'live' method to bind the events with nodes created after.
Is there any possibility to do that?
Here is a sample that helps (I hope) to understand my problem:
$(function(){
$("#nodes").jstree({
"plugins" : [ "themes", "html_data", "dnd", "ui", "crrm" ]
}).bind("move_node.jstree", function (event, data) {
alert('move');
}).bind("rename_node.jstree", function (event, data) {
alert('rename');
}).bind("create_node.jstree", function (event, data) {
alert('create_node');
})
$("#create_button").click(function () {
$("#nodes").jstree("create",null,"last",{data:"name"});
});
});
The command is create_node, not create, I think. See http://www.jstree.com/documentation/core for more details.
FYI, your code would be better written as:
$(function() {
$("#nodes").jstree({
"plugins": ["themes", "html_data", "dnd", "ui", "crrm"]
}).bind("move_node.jstree rename_node.jstree create_node.jstree", function(event, data) {
var type = event.type;
alert(type);
if (type === 'move_node.jstree') {
//handle move_node.jstree here
} else if (type === 'rename_node.jstree') {
//handle rename_node.jstree here
} else if (type === 'create_node.jstree') {
//handle create_node.jstree here
}
});
$("#create_button").click(function() {
$("#nodes").jstree("create", null, "last", {
data: "name"
});
});
});
I know that is subjective, but take it for what is worth.
It seems that the events are fired correctly. The problem was somewhere in the logic. I had to set the id of the item too to be handled correctly.
$("#nodes").jstree("create",null,"last",{data:the_name, attr: {id: the_id}});
Sorry for this mistake.

Categories