Remember state with YUI TreeView
I’ve got a YUI tree which loads the leaves dynamically with Ajax calls. But I want to open up the tree to a specific leaf – on the third level down – after the page loads – as the server is delivering content specific to that node.
How to do? It’s like saving state after a roundtrip to the server. (the hierarchy is team->role->position)
The server tells the team node to expand which in turn tells the role node to unsubscribe and expand itself. In effect the tree opens to the third leaf.
during page load
after drawing the tree with teams nodes
get the specific team node
subscribe to 'expandcomplete' with this function
unsubscribe from the expansion event
expand the specific role node
now expand the team node
var teamnode = tree.getNodeByProperty("tmn_id","#getPosIds.tmn_id#");
tree.subscribe("expandComplete", function(node) {
var rolenode = this.getNodeByProperty("pos_id","#getPosIds.pos_id#");
tree.unsubscribe("expandComplete");
rolenode.expand();
});
teamnode.expand();
Another suggested solution is to save state with a cookie, but i didn’t try that one.
I’ve gone a little Ajax crazy; every solution looks like ajax at the moment, and this is just with the YAHOO! library. I know there are others, potentially better ones out there (extjs.com?) but I’ve not evaluated them.
John is a freelance programmer living in Sydney Australia. He blogs whatever takes his fancy; computing tips, travel letters, and random stuff from his life. He does it primarily to learn and demonstrate the running of a website.
John,
Did you get this working? I am also trying to do the same thing. Could you please send me your code?
Hi Das,
Yes got it working.
Sadly I don’t have a copy of the whole thing as it stayed at the company it was for and I managed to screw up the virtual server that i reserved as my backup. Whatsmore this piece will be deployed behind authentication. Sorry. Yes the fragment is specific to my problem and a hasty post.
Some notes in looking at it now…
1) “during page load” in the psuedocode
Not shown in the fragment. I used the yui loader and had this fragment invoked when the yui considered the page loaded
2) “get the specific team node”
Refers to the first line – var teamnode. However I’ve not shown the construction of the tree in this fragment which is a bit poor of me.
During tree construction the top level nodes were keyed with “tmn_id” and the middle level keyed “pos_id” which is obviously significant as these are the keys ‘getNodeByProperty’ uses to find the node. Hopefully how I did that is obvious when you examine the API to construct nodes.
3) #variable_name#
The server-side was Coldfusion and this is how coldfusion injects variables into markup. So “getPosIds” refers to a server-side variable containing a query resultset. Thus “#getPosIds.tmd_id#” is substituted with the contents of the first “tmn_id” field from the first row. An integer. eg “44″.
So the client would actually be sent…
var teamnode = tree.getNodeByProperty(“tmn_id”,”44″);
4) the how
I’ve done it by creating a routine to expand the innermost node. Then I’ve attached that routine to an event which is fired after the top-level node is expanded. Thus, by expanding the top level node, the child node gets opened as well. There’s a little gotcha in that you want the routine to self-destruct on first use – hence the unsubscribe.
Maybe that helps. I think the secret lies in understanding how it was done rather than trying to copy the code fragment.
John
Hi John,
Do you have any idea how to get a node in a treeview that currently has focus? I’ve scoured the docs but I can’t find any way to do this. If you have any thoughts they would be gratefully received.
Hi John Mee
I am wondering if you can remember if the whole code below was inside a loop which iterated the first children of the tree.getRoot() ?
for(var i=0; i < root.children.length; i++){ var node = root.children[i]; var pozid = node.data.pozid; if (the node should be expanded){ (your code)* } }Petronel:
No. There were no loops.
When the client-side code was generated at the server-side I embedded an identifier into each node (“pos_id”). When the code runs on the client it gets the node it wants by calling the “getNodeByProperty” function with my identifier “pos_id” and a value for it.