Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 373
Joe Avatar asked Sep 05 '11 10:09

Joe


3 Answers

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.

like image 62
Nikos Steiakakis Avatar answered Nov 11 '22 03:11

Nikos Steiakakis


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 :-)
like image 38
Ashraf Sayied-Ahmad Avatar answered Nov 11 '22 03:11

Ashraf Sayied-Ahmad


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

like image 1
tomhre Avatar answered Nov 11 '22 01:11

tomhre