JsTree Open a node then select a child node (using json_result)
I am having trouble with a JsTree I am using in an MVC2 project. I would like to create a function to deselect/close all nodes on the tree. Then open a specific node开发者_如何学运维, and select a specific child node (I have the Id values for both).
The trouble is that the select_node is always called before the open_node finishes, so the node is not selected, as the tree has not loaded the data yet, and the node ID does not exist.
I first tried this function.
$('#demo3').jstree('deselect_all');
$('#demo3').jstree('close_all');
$('#demo3').jstree("open_node", $('#ParentId'), false, true);
$('#demo3').jstree("select_node", $('#ChildId'));
I then tried moving the code to the select_node and move_node binds of the tree, but no luck. At the moment I'm stuck using a setTimeout(), which is a horrible solution.
Does anyone know how I can tell the tree to only select the node after opening has finished?
You could try passing a function that selects the node as a callback like:
$('#demo3').jstree('open_node', '#ParentID', function(e, data) {
$('#demo3').jstree('select_node', '#ChildId');
}, true);
This way select_node
will be called once the open_node returns success.
I am currently using it in a MVC4 project.
if you configure the open_node function to load the node JSON (in the "core" plugin you set load_open to true), then the new added node is exists in the server side but its DOM element is still not because the open_node function does not finish it job. Therefore, you need to wait or use a second parameter (success callback). In the callback the new node rendered in the DOM tree and its selector valid.
jsTree configuration sample:
"core": {
"open_parents": true,
"load_open": true
}
My working code:
$("iframe#UploadTarget").load(function () {
var result = jQuery.parseJSON($(this).contents().text());
if (result.Result == true) {
$("#uploadDialog").dialog("close");
var tree = jQuery.jstree._focused();
/*
open_node will open the parent, get the childs from the server
(controller) and renders the new item before the callback executed,
so the jQuery selector will be valid
*/
tree.open_node(result.ParentId,/*CALLBACK*/ function () {
var newNode = $("#" + result.Id);
tree.select_node(newNode, false, null);
});
} else {
alert(result.Result + ":" + result.ResultDescription);
}
});//GOOD LUCK :-)
hope this might help and sorry I am not using json. I am using jstree together with function to open nodes by clicking on elements outside from the html of jstree.
each node in our setup is like a webpage, so on the homepage of the dashboard we have list of recently edited pages.
each of those links has this javascript to execute
<a href="javascript: selectLeftNavNode(339);">Edit</a>
where 339 is the id of the page we want to edit
and this is fhe function that used to be executed
function selectLeftNavNode(node) {
$('#demo').jstree('deselect_all');
$('#demo').jstree('select_node', '#node_' + node);
}
the problem we noticed recently that if the page recently edited is deep within the tree more specifically in the section that has not been loaded yet it will fail
this is why I decided to make ajax request to the server in order to retrieve all parent id's
changed code below, the ajax in my case will return something like this looking xml
<?xml version="1.0" encoding="UTF-8"?>
<response>
<paths>
<path>339</path>
<path>338</path>
<path>38</path>
</paths>
</response>
and the function
function selectLeftNavNode(node) {
$('#demo').jstree('deselect_all');
if($('#demo').jstree('select_node', '#node_' + node) === false)
{
// if it is false means that the node is not yet rendered
// so instead of loading we will require to get list of parent nodes to open in order, then it will become available
// an ajax call should get us all the nodes
$.ajax({
type: "POST",
dataType: "xml",
url: your_url_to_php_script',
data: {node_id:node},
success: function(data)
{
var remaining_nodes = new Array();
var paths_count = $(data).find('response').find('path').length;
for(var x=1;x<=paths_count;x++){
remaining_nodes[x-1] = $(data).find('response').find('paths path:nth-child('+x+')').text();
}
open_nodes_step_by_step(remaining_nodes);
}
});
}
}
and in addition to that a function that is looped through on callbacks from open_node, the function opens node by node and when it hits the last entry that should be the actual node id we want to select it will use select_node instead
function open_nodes_step_by_step(remaining_nodes)
{
var nodes = remaining_nodes.slice();
tree = jQuery.jstree._focused();
if(nodes.length > 1){
var nodes_left = remaining_nodes.slice();
nodes_left.pop();
var to_open = nodes.length - 1;
tree.open_node(document.getElementById('node_' + nodes[to_open]), /*CALLBACK*/ function () {
open_nodes_step_by_step(nodes_left);
});
}
else{
tree.select_node('#node_' + nodes[0]);
}
}
i have tested my solution with IE8, FF and Chrome all seems to be working just fine, on top of that i use jQuery v1.10.1 and jsTree 1.0-rc1 (unfortunately as the code has been there for years now and it has all that database and other integrations i decided not to change to newer versions, it works)
hope I have helped someone
Tom
精彩评论