Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jsTree: progressive_render with ajax / render nodes from an array

This is regarding the jsTree jQuery plugin. I've been struggling with this for a while now only to realise it's not (natively) possible to do, so I thought about the following solution to my problem below (which doesn't work).

I have a tree that uses the json_data plugin with ajax. Once you open a specific node the result from the server is an array of over 1000 json nodes. The response is pretty fast but the rendering itself takes a while (the user experience is that he gets the annoying "script not responding - stop script / continue" message.

The solution I thought about was limiting the results sent back from the server to a smaller number (say 200) and using some "show more" label (or using the jQuery scroll event) to fetch the next 200. However, using the jstree.create on each of those nodes appears to be very slow. I then noticed this thread on the jsTree google group in which Ivan suggest it's possible to create all nodes at once using the parse_json function - this doesn't work for me.

A short code snippet of what I'm trying to do: (when clicking the "show more" label):

$.ajax({
   // send data to server in order to get the relevant json back
   }(),
   success : function (r) {
           var parent_node = data.inst._get_parent(data.rslt.obj);
           var id = parent_node.attr("id");
           $("#root_tree").jstree("_parse_json", r, parent_node );
           $("#root_tree").jstree("clean_node", parent_node, false);
           }
   });

The above example doesn't render the json and adds the children to the parent node.

I would highly appreciate any other approach or if anyone could point out what am I doing wrong. Again, using:

$.each(r, function(i, node) {
       var id = parent_node.attr("id");
       $("#root_tree").jstree("create", "#"+id, "last", node, false, true);
});

Does work, but very very slowly (slower than rendering all 1000 nodes together).

Thanks

like image 634
Amir Avatar asked Feb 23 '12 09:02

Amir


2 Answers

Ok, so my usage was a bit off.

What I ended up doing, was calling the function on the tree view instead of listening to the event:

 var ref = parent_node.attr("id");
 $.each(data, function(i, jsonNode) {
       var node = inst._parse_json(jsonNode);
       node.insertInside(ref);
 });
like image 173
Amir Avatar answered Nov 14 '22 22:11

Amir


This is how I have my tree set up and i have well over a few hundred nodes and it works like a charm. I did have a very very slight performance issue in IE6/7 but works like a champ everywhere else.

$('#serverTree').bind("select_node.jstree", function (e, data) {
        var url = data.rslt.obj.children("a:eq(0)").attr("href");
        if (url === "hasChild") {
            data.inst.toggle_node(data.rslt.obj);
        }
        else {
           //Do something when the leaf nodes are clicked
        }

    }).jstree({
        "themes": { "theme": "apple", "dots": false, "icons": false },
        "json_data": {
            "ajax": {
                "url": "/Home/GetNodes",
                "data": function (n) {
                    return { id: n.attr ? n.attr("id") : 0 };
                }
            }
        },
        "plugins": ["themes", "json_data", "ui"]
    });

This is how my JSON coming back from the server looks like :

[{"data":{"title":"Node1","attr":{"id":null,"href":"hasChild"}},
 "attr":{"id":"Node1","href":null},"state":"closed"}]
like image 45
mithun_daa Avatar answered Nov 15 '22 00:11

mithun_daa