How can I tell if jsTree has fully loaded?
I am trying to write a function that opens specific nodes on a jsTree but I am having a problem where the function is executed before my base tree is loaded from the ajax call. How can I tell if my jstree data has been loaded and wait until it is done loading. Below is the function I am trying to use.
function openNodes(tree, nodes) {
for (i in nodes) {
$('#navigation').jstree("open_node", $(nodes[i]));
}
}
I am loading my initial tree with the following command
$("#navigation").jstree({
"json_data": {
"ajax": {
"url": function(node) {
var url;
if (node == -1) {
url = "@Url.Action("BaseTreeItems", "Part")";
} else {
url = node.attr('ajax');
}
return url;
},
"dataType": "text json",
"contentType": "application/json charset=utf-8",
"data": function(n) { return { id: n.attr ? n.attr("id") : 0, ajax: n.attr ? n.attr("ajax") : 0 }; },
"success": function() {
}
}
},
"themes": { "theme": "classic" },
"plugins": ["themes", "json_data", "ui"]
});
Before you call .jstree() on an element, you can bind your callbacks to before.jstree
and loaded.jstree
events:
$(selector)
.bind('before.jstree', function(e, data) {
// invoked before jstree starts loading
})
.bind('loaded.jstree', function(e, data) {
// invoked after jstree has loaded
$(this).jstree("open_node", $(nodes[i]));
})
.jstree( ... )
In the more recent versions of jstree, you may need to wait until all the nodes have finished loading before interacting with them. To do this you need:
ready.jstree
So:
$(selector)
.bind('ready.jstree', function(e, data) {
// invoked after jstree has loaded
})
...
I used setInterval and clearInterval:
var interval_id = setInterval(function(){
// $("li#"+id).length will be zero until the node is loaded
if($("li#"+id).length != 0){
// "exit" the interval loop with clearInterval command
clearInterval(interval_id)
// since the node is loaded, now we can open it without an error
$("#tree").jstree("open_node", $("li#"+id))
}
}, 5);
JStree’s “.loaded” callback only works for root nodes; “._is_loaded” may work instead of checking the node’s length, but I haven’t tried it. Either way, the animation settings cause nodes that are deeper in the tree to be loaded a few milliseconds later. The setInterval command creates a timed loop that exits when your desired node(s) is loaded.
You had better call $.ajax() function to get data you want at first, you can call $().jstree() function in the success: field like bellow my code.
var fullTree;
$.ajax({
url :"./php/select_tree.php",
data : fullTree,
method : "GET",
dataType : "json",
success : function(fullTree){
$("#jstree").jstree({
"core" : {
"data" :fullTree,
"check_callback" : true
},
"plugins" : [ "contextmenu", "dnd", "changed", "wholerow" ]
});
}
})
;
I use refresh.jstree
event in my case (I need to dynamically change and refresh the nodes in jstree very often).
According to the docoment, it
triggered when a refresh call completes
Sample code:
$.post(
[url],
...
).done(function(){
$jstree.jstree().settings.core.data = result;
$jstree.jstree().refresh();
});
$(selector).on('refresh.jstree', function(){
// do something
});
[Disclaimer: this does not apply to the OP since the state plugin is not listed in the setup code.]
If you are using the state plugin, use the state_ready.jstree event instead of the ready.jstree or loaded.jstree events.
$(selector).on('state_ready.jstree', function () {
// open desired node
})
You don’t have to add an interval. The plugin sets a class on the node that it’s loading via ajax.
.one("reselect.jstree", function (evt, data) {
if ($("#MYTREEID").find(".jstree-loading").length == 0) {
alert('my ajax tree is done loading");
}
})
Since i found no solution, that is working for the current version of JSTree (3.3.7) i will publish my work aproach here.
First i bind on the select_node and tell jstree to open the parent, whenever i select i node.
var strIdentifierJsTree = "#your-whatever-id-to-jstree";
var strNode2Select = "#your-whatever-id-to-your-node-which-parents-has-to-be-showed";
$( strIdentifierJsTree ).on("select_node.jstree", function (e, data) {
$(strIdentifierJsTree).jstree(true).open_node( data.node.parent );
});
Then i bind to the load-Function:
$( strIdentifierJsTree ).bind('loaded.jstree', function(e, data) {
$(strIdentifierJsTree).jstree(true).select_node( strNode2Select );
});
Now it will select my Node after initialisation of JSTree (when fully loaded) and also open all the parents, whatever the depth of nesting is. The single open-node approach, like mentioned in other answers did not work for me.