Re-opening a treeview after refreshing it
11 October 2005 at 6:56 am
Ever used a treeview-component for dynamic content? When the underlying data changes you send it off to the server and then update the tree with the result from the server. Problem is: all the nodes you opened are now collapsed… Wouldn’t it be nice to have the tree open to the state it was before the refresh? Here’s one way to solve it.
I’ve been working on our Flash-based CMS lately and I’ve bought the dndTreecomponent from Drumbeat. Brilliant component and features (slightly messy documantation, but workable). It’s a steal at $29 compared to the time it would take you to build something similar.It does it’s magic by extending the existing tree-component (class) in Flash with all the stuff you want like label editing and drag and drop. The problem with expanding nodes back after refreshing is that you may have changed the nodes so that when new data is returned from the server, you’ll open a different node since the numbering was changed or somewhat. In my case, I have unique ID’s on the server and by passing these via an XML node called “id”, I can use the XML idMap feature to access the nodes directly.
All I do before a refresh is parsing me back from the last open node, saving those ID’s. I put these into an array (nodesToOpen) and when the the new XML is loaded, I add a isOpen-attribute to the nodes that are to be opened:
for(var i=0;i<nodesToOpen.length;i++ ){ var node = this.idMap[nodesToOpen]; node.attributes.isOpen = "true"; }
I just love the idMap way of accessing XML. So fast, but as said, it requires unique IDs for every XML node. Then I parse through my XML and open nodes where required:
function recurseAndOpen(x:XML,tree:Object){ if(!_global.xHowManyNodes){ _global.xHowManyNodes = 0; } for(var each in x.childNodes){ if(x.childNodes[each].attributes.isOpen == "true"){ var t = tree.getDisplayIndex(x.childNodes[each]); tree.setIsOpen(tree.getNodeDisplayedAt(t), true,false,false); } _global.xHowManyNodes++; // then recurse for all subnodes if(x.childNodes[each] != undefined){ recurseAndOpen(x.childNodes[each],tree); } } } // Send in the XML and the tree-object like this recurseAndOpen(this.firstChild, main.rootObject.tree);
Figuring out this last bit took me way too much time so I’m posting it here for future reference and so that others may find it also. Once again, I got a hint at how to do things by finding gems in the comments on the Macromedia LiveDocs. I did not find it in the Flash 8 section but in the old MX04. Macromedia should really move the best of these comments over to the new docs just like php.net does.
After a bit of fiddeling with what nodes to keep and not, I now have a treeview where the user won’t know that the underlying data changed. The refreshes and re-opening are totally invisible to the end user and that’s exactly the way I want it.