PDA

View Full Version : Ext.ux.TreeIterator 1.0



Ronaldo
6 Nov 2008, 3:14 AM
Hi all,

I needed to recursively iterator over all loaded nodes of a tree, and I could not find an iterator or a visitor for that, so I created a tree iterator.
It's simple, you can only go forward (down) in the tree, and you can't reset it during iteration, but I think it works just fine (Of course, any comments/remarks are welcome).

I'd suppose this could be added to the Ext.tree namespace and be included with the Ext distribution, it's fine with me. If not, that's fine too.

I've added documentation in the code so I hope it speaks for itself, but for clarity, here's some client code:



var treenode;
var iterator = new Ext.ux.TreeIterator(node);
while(iterator.hasNext()) {
treenode = iterator.next();
// Do something with the treenode
}
And here's the full code:



/*
* Ext.ux.TreeIterator 1.0 for the Ext JS Library 2.2
* Copyright(c) Twensoc.nl
* email: info@twensoc.nl
*
* GPL License as stated by Ext JS, LLC.
*/

/**
* @class Ext.ux.TreeIterator
* @extends
* Provides a convenient way of iterating over all loaded {@link Ext.tree.TreeNode}s of a {@link Ext.tree.TreePanel}.
* Examples:
* <pre><code>
var treenode;
var iterator = new Ext.ux.TreeIterator(node);
while(iterator.hasNext()) {
treenode = iterator.next();
// Do something with the treenode
}
// Iteration has finished and implicit autoDestroy is set to true
// No need to call iterator.destroy()
</code></pre>
* <pre><code>
var treenode;
var iterator = new Ext.ux.TreeIterator(node);
while(iterator.hasNext()) {
treenode = iterator.next();
if(somecondition)
break;
// Do something with the treenode
}
// Iteration may not have finished and though implicit autoDestroy is set to true
// we need to call iterator.destroy() to release all references
iterator.destroy();
</code></pre>
* @constructor
* Creates a new TreeIterator.
* @param {Ext.tree.TreeNode} node with which the iteration starts. This is the first node to be returned.
* All children of the node will be iterated, but not the node's next sibling. If you want to iterate over all
* treenodes, pass the root node.
* @param {Boolean} autoDestroy Destroy all references to treenodes if the iteration has finished completely.
* If you stop the iteration before it has finished, call the {#link destroy} method to unlink the iterator
* and release all references. Defaults to true.
*/
Ext.ux.TreeIterator = function(node, autoDestroy) {
this.autoDestroy = autoDestroy;
if(!autoDestroy)
this.autoDestroy = true;
this.node = node;
this.root = node;
this.indx = -2;
};

Ext.ux.TreeIterator.prototype = {
/**
* Returns a boolean value indicating whether the iterator will return another node.
* @return {Boolean} A boolean value indicating whether there's another node to be iterated.
*/
hasNext : function() {
if(!this.root) // Safety check for calling hasNext multiple times after
return false; // the iteration has finished and autoDestroy is applied.

var i = this.indx + 1; // Pointer to the current node to be returned
var nn; // The next node to be returned from next() method
var cn = this.node; // The current node

// Return the node itself
if(i == -1) {
nn = cn;

} else if(i == 0 && this.node.childNodes.length > 0) {
// Hop into first child
nn = cn.firstChild;
i = -1;
} else {
// Next sibling
i = -1;
nn = cn.nextSibling;
if(!nn) {
// No next sibling found, return to parent (or the parents parent)
do {
cn = cn.parentNode;
if(cn) {
if(cn == this.root)
break;
nn = cn.nextSibling;
}
} while (cn && !nn);
}
}
this.nextNode = nn;
this.nextIndex = i;
if(this.nextNode) {
return true;
}
if(this.autoDestroy == true)
this.destroy();
return false;
},
/**
* Returns the next TreeNode in the iteration.
* @return {TreeNode} The next TreeNode in the iteration.
*/
next : function() {
this.node = this.nextNode;
this.indx = this.nextIndex;
return this.node;
},
/**
* Remove all references to any treenode used in the iteration
* @return {void}
*/
destroy : function() {
delete(this.root);
delete(this.node);
delete(this.nextNode);
}
}
Enjoy

Ronaldo

Animal
6 Nov 2008, 5:13 AM
I might use http://extjs.com/deploy/dev/docs/?class=Ext.tree.TreeNode&member=eachChild for this, but for efficiency, I'd just code up a loop through http://extjs.com/deploy/dev/docs/?class=Ext.tree.TreeNode&member=childNodes and process each element.

Ronaldo
6 Nov 2008, 5:22 AM
Hi Animal,

Yes, but that would iterate the direct children of the node only. What I actually needed was a findChild(...) method that would search all (loaded) child nodes.

I'm updating a record in a formpanel, and some properties saved in that panel are also stored as attributes in a treepanel. So, to keep it all synchronised, I'm broadcasting a 'savedRecord' event with the saved values, and if the same record is already loaded as a node in the treepanel, I'm updating the node attributes with the new values.

Ronaldo