722 lines
No EOL
28 KiB
HTML
722 lines
No EOL
28 KiB
HTML
<html><head><title>Tree.js</title><link rel="stylesheet" type="text/css" href="../resources/style.css" media="screen"/></head><body><h1>Tree.js</h1><pre class="highlighted"><code><i>/**
|
|
* @class Ext.data.Tree
|
|
* @extends Ext.util.Observable
|
|
* Represents a tree data structure and bubbles all the events <b>for</b> its nodes. The nodes
|
|
* <b>in</b> the tree have most standard DOM functionality.
|
|
* @constructor
|
|
* @param {Node} root (optional) The root node
|
|
*/</i>
|
|
Ext.data.Tree = <b>function</b>(root){
|
|
<b>this</b>.nodeHash = {};
|
|
<i>/**
|
|
* The root node <b>for</b> this tree
|
|
* @type Node
|
|
*/</i>
|
|
<b>this</b>.root = null;
|
|
<b>if</b>(root){
|
|
<b>this</b>.setRootNode(root);
|
|
}
|
|
<b>this</b>.addEvents({
|
|
<i>/**
|
|
* @event append
|
|
* Fires when a <b>new</b> child node is appended to a node <b>in</b> this tree.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} parent The parent node
|
|
* @param {Node} node The newly appended node
|
|
* @param {Number} index The index of the newly appended node
|
|
*/</i>
|
|
"append" : true,
|
|
<i>/**
|
|
* @event remove
|
|
* Fires when a child node is removed from a node <b>in</b> this tree.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} parent The parent node
|
|
* @param {Node} node The child node removed
|
|
*/</i>
|
|
"remove" : true,
|
|
<i>/**
|
|
* @event move
|
|
* Fires when a node is moved to a <b>new</b> location <b>in</b> the tree
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} node The node moved
|
|
* @param {Node} oldParent The old parent of <b>this</b> node
|
|
* @param {Node} newParent The <b>new</b> parent of <b>this</b> node
|
|
* @param {Number} index The index it was moved to
|
|
*/</i>
|
|
"move" : true,
|
|
<i>/**
|
|
* @event insert
|
|
* Fires when a <b>new</b> child node is inserted <b>in</b> a node <b>in</b> this tree.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} parent The parent node
|
|
* @param {Node} node The child node inserted
|
|
* @param {Node} refNode The child node the node was inserted before
|
|
*/</i>
|
|
"insert" : true,
|
|
<i>/**
|
|
* @event beforeappend
|
|
* Fires before a <b>new</b> child is appended to a node <b>in</b> this tree, <b>return</b> false to cancel the append.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} parent The parent node
|
|
* @param {Node} node The child node to be appended
|
|
*/</i>
|
|
"beforeappend" : true,
|
|
<i>/**
|
|
* @event beforeremove
|
|
* Fires before a child is removed from a node <b>in</b> this tree, <b>return</b> false to cancel the remove.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} parent The parent node
|
|
* @param {Node} node The child node to be removed
|
|
*/</i>
|
|
"beforeremove" : true,
|
|
<i>/**
|
|
* @event beforemove
|
|
* Fires before a node is moved to a <b>new</b> location <b>in</b> the tree. Return false to cancel the move.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} node The node being moved
|
|
* @param {Node} oldParent The parent of the node
|
|
* @param {Node} newParent The <b>new</b> parent the node is moving to
|
|
* @param {Number} index The index it is being moved to
|
|
*/</i>
|
|
"beforemove" : true,
|
|
<i>/**
|
|
* @event beforeinsert
|
|
* Fires before a <b>new</b> child is inserted <b>in</b> a node <b>in</b> this tree, <b>return</b> false to cancel the insert.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} parent The parent node
|
|
* @param {Node} node The child node to be inserted
|
|
* @param {Node} refNode The child node the node is being inserted before
|
|
*/</i>
|
|
"beforeinsert" : true
|
|
});
|
|
|
|
Ext.data.Tree.superclass.constructor.call(<b>this</b>);
|
|
};
|
|
|
|
Ext.extend(Ext.data.Tree, Ext.util.Observable, {
|
|
pathSeparator: "/",
|
|
|
|
<i>/**
|
|
* Returns <b>this</b> root node <b>for</b> this tree
|
|
* @<b>return</b> {Node}
|
|
*/</i>
|
|
getRootNode : <b>function</b>(){
|
|
<b>return</b> this.root;
|
|
},
|
|
|
|
<i>/**
|
|
* Sets the root node <b>for</b> this tree
|
|
* @param {Node} node
|
|
* @<b>return</b> {Node}
|
|
*/</i>
|
|
setRootNode : <b>function</b>(node){
|
|
<b>this</b>.root = node;
|
|
node.ownerTree = <b>this</b>;
|
|
node.isRoot = true;
|
|
<b>this</b>.registerNode(node);
|
|
<b>return</b> node;
|
|
},
|
|
|
|
<i>/**
|
|
* Gets a node <b>in</b> this tree by its id
|
|
* @param {String} id
|
|
* @<b>return</b> {Node}
|
|
*/</i>
|
|
getNodeById : <b>function</b>(id){
|
|
<b>return</b> this.nodeHash[id];
|
|
},
|
|
|
|
registerNode : <b>function</b>(node){
|
|
<b>this</b>.nodeHash[node.id] = node;
|
|
},
|
|
|
|
unregisterNode : <b>function</b>(node){
|
|
<b>delete</b> this.nodeHash[node.id];
|
|
},
|
|
|
|
toString : <b>function</b>(){
|
|
<b>return</b> "[Tree"+(<b>this</b>.id?" "+<b>this</b>.id:"")+"]";
|
|
}
|
|
});
|
|
|
|
<i>/**
|
|
* @class Ext.data.Node
|
|
* @extends Ext.util.Observable
|
|
* @cfg {Boolean} leaf true <b>if</b> this node is a leaf and does not have children
|
|
* @cfg {String} id The id <b>for</b> this node. If one is not specified, one is generated.
|
|
* @constructor
|
|
* @param {Object} attributes The attributes/config <b>for</b> the node
|
|
*/</i>
|
|
Ext.data.Node = <b>function</b>(attributes){
|
|
<i>/**
|
|
* The attributes supplied <b>for</b> the node. You can use <b>this</b> property to access any custom attributes you supplied.
|
|
* @type {Object}
|
|
*/</i>
|
|
<b>this</b>.attributes = attributes || {};
|
|
<b>this</b>.leaf = <b>this</b>.attributes.leaf;
|
|
<i>/**
|
|
* The node id. @type String
|
|
*/</i>
|
|
<b>this</b>.id = <b>this</b>.attributes.id;
|
|
<b>if</b>(!<b>this</b>.id){
|
|
<b>this</b>.id = Ext.id(null, "ynode-");
|
|
<b>this</b>.attributes.id = <b>this</b>.id;
|
|
}
|
|
<i>/**
|
|
* All child nodes of <b>this</b> node. @type Array
|
|
*/</i>
|
|
<b>this</b>.childNodes = [];
|
|
<b>if</b>(!<b>this</b>.childNodes.indexOf){ <i>// indexOf is a must</i>
|
|
<b>this</b>.childNodes.indexOf = <b>function</b>(o){
|
|
<b>for</b>(var i = 0, len = <b>this</b>.length; i < len; i++){
|
|
<b>if</b>(this[i] == o) <b>return</b> i;
|
|
}
|
|
<b>return</b> -1;
|
|
};
|
|
}
|
|
<i>/**
|
|
* The parent node <b>for</b> this node. @type Node
|
|
*/</i>
|
|
<b>this</b>.parentNode = null;
|
|
<i>/**
|
|
* The first direct child node of <b>this</b> node, or null <b>if</b> this node has no child nodes. @type Node
|
|
*/</i>
|
|
<b>this</b>.firstChild = null;
|
|
<i>/**
|
|
* The last direct child node of <b>this</b> node, or null <b>if</b> this node has no child nodes. @type Node
|
|
*/</i>
|
|
<b>this</b>.lastChild = null;
|
|
<i>/**
|
|
* The node immediately preceding <b>this</b> node <b>in</b> the tree, or null <b>if</b> there is no sibling node. @type Node
|
|
*/</i>
|
|
<b>this</b>.previousSibling = null;
|
|
<i>/**
|
|
* The node immediately following <b>this</b> node <b>in</b> the tree, or null <b>if</b> there is no sibling node. @type Node
|
|
*/</i>
|
|
<b>this</b>.nextSibling = null;
|
|
|
|
<b>this</b>.addEvents({
|
|
<i>/**
|
|
* @event append
|
|
* Fires when a <b>new</b> child node is appended
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} <b>this</b> This node
|
|
* @param {Node} node The newly appended node
|
|
* @param {Number} index The index of the newly appended node
|
|
*/</i>
|
|
"append" : true,
|
|
<i>/**
|
|
* @event remove
|
|
* Fires when a child node is removed
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} <b>this</b> This node
|
|
* @param {Node} node The removed node
|
|
*/</i>
|
|
"remove" : true,
|
|
<i>/**
|
|
* @event move
|
|
* Fires when <b>this</b> node is moved to a <b>new</b> location <b>in</b> the tree
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} <b>this</b> This node
|
|
* @param {Node} oldParent The old parent of <b>this</b> node
|
|
* @param {Node} newParent The <b>new</b> parent of <b>this</b> node
|
|
* @param {Number} index The index it was moved to
|
|
*/</i>
|
|
"move" : true,
|
|
<i>/**
|
|
* @event insert
|
|
* Fires when a <b>new</b> child node is inserted.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} <b>this</b> This node
|
|
* @param {Node} node The child node inserted
|
|
* @param {Node} refNode The child node the node was inserted before
|
|
*/</i>
|
|
"insert" : true,
|
|
<i>/**
|
|
* @event beforeappend
|
|
* Fires before a <b>new</b> child is appended, <b>return</b> false to cancel the append.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} <b>this</b> This node
|
|
* @param {Node} node The child node to be appended
|
|
*/</i>
|
|
"beforeappend" : true,
|
|
<i>/**
|
|
* @event beforeremove
|
|
* Fires before a child is removed, <b>return</b> false to cancel the remove.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} <b>this</b> This node
|
|
* @param {Node} node The child node to be removed
|
|
*/</i>
|
|
"beforeremove" : true,
|
|
<i>/**
|
|
* @event beforemove
|
|
* Fires before <b>this</b> node is moved to a <b>new</b> location <b>in</b> the tree. Return false to cancel the move.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} <b>this</b> This node
|
|
* @param {Node} oldParent The parent of <b>this</b> node
|
|
* @param {Node} newParent The <b>new</b> parent <b>this</b> node is moving to
|
|
* @param {Number} index The index it is being moved to
|
|
*/</i>
|
|
"beforemove" : true,
|
|
<i>/**
|
|
* @event beforeinsert
|
|
* Fires before a <b>new</b> child is inserted, <b>return</b> false to cancel the insert.
|
|
* @param {Tree} tree The owner tree
|
|
* @param {Node} <b>this</b> This node
|
|
* @param {Node} node The child node to be inserted
|
|
* @param {Node} refNode The child node the node is being inserted before
|
|
*/</i>
|
|
"beforeinsert" : true
|
|
});
|
|
<b>this</b>.listeners = <b>this</b>.attributes.listeners;
|
|
Ext.data.Node.superclass.constructor.call(<b>this</b>);
|
|
};
|
|
|
|
Ext.extend(Ext.data.Node, Ext.util.Observable, {
|
|
fireEvent : <b>function</b>(evtName){
|
|
<i>// first <b>do</b> standard event <b>for</b> this node</i>
|
|
<b>if</b>(Ext.data.Node.superclass.fireEvent.apply(<b>this</b>, arguments) === false){
|
|
<b>return</b> false;
|
|
}
|
|
<i>// then bubble it up to the tree <b>if</b> the event wasn't cancelled</i>
|
|
<b>var</b> ot = <b>this</b>.getOwnerTree();
|
|
<b>if</b>(ot){
|
|
<b>if</b>(ot.fireEvent.apply(<b>this</b>.ownerTree, arguments) === false){
|
|
<b>return</b> false;
|
|
}
|
|
}
|
|
<b>return</b> true;
|
|
},
|
|
|
|
<i>/**
|
|
* Returns true <b>if</b> this node is a leaf
|
|
* @<b>return</b> {Boolean}
|
|
*/</i>
|
|
isLeaf : <b>function</b>(){
|
|
<b>return</b> this.leaf === true;
|
|
},
|
|
|
|
<i>// private</i>
|
|
setFirstChild : <b>function</b>(node){
|
|
<b>this</b>.firstChild = node;
|
|
},
|
|
|
|
<i>//private</i>
|
|
setLastChild : <b>function</b>(node){
|
|
<b>this</b>.lastChild = node;
|
|
},
|
|
|
|
|
|
<i>/**
|
|
* Returns true <b>if</b> this node is the last child of its parent
|
|
* @<b>return</b> {Boolean}
|
|
*/</i>
|
|
isLast : <b>function</b>(){
|
|
<b>return</b> (!<b>this</b>.parentNode ? true : <b>this</b>.parentNode.lastChild == <b>this</b>);
|
|
},
|
|
|
|
<i>/**
|
|
* Returns true <b>if</b> this node is the first child of its parent
|
|
* @<b>return</b> {Boolean}
|
|
*/</i>
|
|
isFirst : <b>function</b>(){
|
|
<b>return</b> (!<b>this</b>.parentNode ? true : <b>this</b>.parentNode.firstChild == <b>this</b>);
|
|
},
|
|
|
|
hasChildNodes : <b>function</b>(){
|
|
<b>return</b> !<b>this</b>.isLeaf() && <b>this</b>.childNodes.length > 0;
|
|
},
|
|
|
|
<i>/**
|
|
* Insert node(s) as the last child node of <b>this</b> node.
|
|
* @param {Node/Array} node The node or Array of nodes to append
|
|
* @<b>return</b> {Node} The appended node <b>if</b> single append, or null <b>if</b> an array was passed
|
|
*/</i>
|
|
appendChild : <b>function</b>(node){
|
|
<b>var</b> multi = false;
|
|
<b>if</b>(node instanceof Array){
|
|
multi = node;
|
|
}<b>else</b> if(arguments.length > 1){
|
|
multi = arguments;
|
|
}
|
|
<i>// <b>if</b> passed an array or multiple args <b>do</b> them one by one</i>
|
|
<b>if</b>(multi){
|
|
<b>for</b>(var i = 0, len = multi.length; i < len; i++) {
|
|
<b>this</b>.appendChild(multi[i]);
|
|
}
|
|
}<b>else</b>{
|
|
<b>if</b>(this.fireEvent("beforeappend", <b>this</b>.ownerTree, <b>this</b>, node) === false){
|
|
<b>return</b> false;
|
|
}
|
|
<b>var</b> index = <b>this</b>.childNodes.length;
|
|
<b>var</b> oldParent = node.parentNode;
|
|
<i>// it's a move, make sure we move it cleanly</i>
|
|
<b>if</b>(oldParent){
|
|
<b>if</b>(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, <b>this</b>, index) === false){
|
|
<b>return</b> false;
|
|
}
|
|
oldParent.removeChild(node);
|
|
}
|
|
index = <b>this</b>.childNodes.length;
|
|
<b>if</b>(index == 0){
|
|
<b>this</b>.setFirstChild(node);
|
|
}
|
|
<b>this</b>.childNodes.push(node);
|
|
node.parentNode = <b>this</b>;
|
|
<b>var</b> ps = <b>this</b>.childNodes[index-1];
|
|
<b>if</b>(ps){
|
|
node.previousSibling = ps;
|
|
ps.nextSibling = node;
|
|
}<b>else</b>{
|
|
node.previousSibling = null;
|
|
}
|
|
node.nextSibling = null;
|
|
<b>this</b>.setLastChild(node);
|
|
node.setOwnerTree(<b>this</b>.getOwnerTree());
|
|
<b>this</b>.fireEvent("append", <b>this</b>.ownerTree, <b>this</b>, node, index);
|
|
<b>if</b>(oldParent){
|
|
node.fireEvent("move", <b>this</b>.ownerTree, node, oldParent, <b>this</b>, index);
|
|
}
|
|
<b>return</b> node;
|
|
}
|
|
},
|
|
|
|
<i>/**
|
|
* Removes a child node from <b>this</b> node.
|
|
* @param {Node} node The node to remove
|
|
* @<b>return</b> {Node} The removed node
|
|
*/</i>
|
|
removeChild : <b>function</b>(node){
|
|
<b>var</b> index = <b>this</b>.childNodes.indexOf(node);
|
|
<b>if</b>(index == -1){
|
|
<b>return</b> false;
|
|
}
|
|
<b>if</b>(this.fireEvent("beforeremove", <b>this</b>.ownerTree, <b>this</b>, node) === false){
|
|
<b>return</b> false;
|
|
}
|
|
|
|
<i>// remove it from childNodes collection</i>
|
|
<b>this</b>.childNodes.splice(index, 1);
|
|
|
|
<i>// update siblings</i>
|
|
<b>if</b>(node.previousSibling){
|
|
node.previousSibling.nextSibling = node.nextSibling;
|
|
}
|
|
<b>if</b>(node.nextSibling){
|
|
node.nextSibling.previousSibling = node.previousSibling;
|
|
}
|
|
|
|
<i>// update child refs</i>
|
|
<b>if</b>(this.firstChild == node){
|
|
<b>this</b>.setFirstChild(node.nextSibling);
|
|
}
|
|
<b>if</b>(this.lastChild == node){
|
|
<b>this</b>.setLastChild(node.previousSibling);
|
|
}
|
|
|
|
node.setOwnerTree(null);
|
|
<i>// clear any references from the node</i>
|
|
node.parentNode = null;
|
|
node.previousSibling = null;
|
|
node.nextSibling = null;
|
|
<b>this</b>.fireEvent("remove", <b>this</b>.ownerTree, <b>this</b>, node);
|
|
<b>return</b> node;
|
|
},
|
|
|
|
<i>/**
|
|
* Inserts the first node before the second node <b>in</b> this nodes childNodes collection.
|
|
* @param {Node} node The node to insert
|
|
* @param {Node} refNode The node to insert before (<b>if</b> null the node is appended)
|
|
* @<b>return</b> {Node} The inserted node
|
|
*/</i>
|
|
insertBefore : <b>function</b>(node, refNode){
|
|
<b>if</b>(!refNode){ <i>// like standard Dom, refNode can be null <b>for</b> append</i>
|
|
<b>return</b> this.appendChild(node);
|
|
}
|
|
<i>// nothing to <b>do</b></i>
|
|
<b>if</b>(node == refNode){
|
|
<b>return</b> false;
|
|
}
|
|
|
|
<b>if</b>(this.fireEvent("beforeinsert", <b>this</b>.ownerTree, <b>this</b>, node, refNode) === false){
|
|
<b>return</b> false;
|
|
}
|
|
<b>var</b> index = <b>this</b>.childNodes.indexOf(refNode);
|
|
<b>var</b> oldParent = node.parentNode;
|
|
<b>var</b> refIndex = index;
|
|
|
|
<i>// when moving internally, indexes will change after remove</i>
|
|
<b>if</b>(oldParent == <b>this</b> && <b>this</b>.childNodes.indexOf(node) < index){
|
|
refIndex--;
|
|
}
|
|
|
|
<i>// it's a move, make sure we move it cleanly</i>
|
|
<b>if</b>(oldParent){
|
|
<b>if</b>(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, <b>this</b>, index, refNode) === false){
|
|
<b>return</b> false;
|
|
}
|
|
oldParent.removeChild(node);
|
|
}
|
|
<b>if</b>(refIndex == 0){
|
|
<b>this</b>.setFirstChild(node);
|
|
}
|
|
<b>this</b>.childNodes.splice(refIndex, 0, node);
|
|
node.parentNode = <b>this</b>;
|
|
<b>var</b> ps = <b>this</b>.childNodes[refIndex-1];
|
|
<b>if</b>(ps){
|
|
node.previousSibling = ps;
|
|
ps.nextSibling = node;
|
|
}<b>else</b>{
|
|
node.previousSibling = null;
|
|
}
|
|
node.nextSibling = refNode;
|
|
refNode.previousSibling = node;
|
|
node.setOwnerTree(<b>this</b>.getOwnerTree());
|
|
<b>this</b>.fireEvent("insert", <b>this</b>.ownerTree, <b>this</b>, node, refNode);
|
|
<b>if</b>(oldParent){
|
|
node.fireEvent("move", <b>this</b>.ownerTree, node, oldParent, <b>this</b>, refIndex, refNode);
|
|
}
|
|
<b>return</b> node;
|
|
},
|
|
|
|
<i>/**
|
|
* Returns the child node at the specified index.
|
|
* @param {Number} index
|
|
* @<b>return</b> {Node}
|
|
*/</i>
|
|
item : <b>function</b>(index){
|
|
<b>return</b> this.childNodes[index];
|
|
},
|
|
|
|
<i>/**
|
|
* Replaces one child node <b>in</b> this node <b>with</b> another.
|
|
* @param {Node} newChild The replacement node
|
|
* @param {Node} oldChild The node to replace
|
|
* @<b>return</b> {Node} The replaced node
|
|
*/</i>
|
|
replaceChild : <b>function</b>(newChild, oldChild){
|
|
<b>this</b>.insertBefore(newChild, oldChild);
|
|
<b>this</b>.removeChild(oldChild);
|
|
<b>return</b> oldChild;
|
|
},
|
|
|
|
<i>/**
|
|
* Returns the index of a child node
|
|
* @param {Node} node
|
|
* @<b>return</b> {Number} The index of the node or -1 <b>if</b> it was not found
|
|
*/</i>
|
|
indexOf : <b>function</b>(child){
|
|
<b>return</b> this.childNodes.indexOf(child);
|
|
},
|
|
|
|
<i>/**
|
|
* Returns the tree <b>this</b> node is <b>in</b>.
|
|
* @<b>return</b> {Tree}
|
|
*/</i>
|
|
getOwnerTree : <b>function</b>(){
|
|
<i>// <b>if</b> it doesn't have one, look <b>for</b> one</i>
|
|
<b>if</b>(!<b>this</b>.ownerTree){
|
|
<b>var</b> p = <b>this</b>;
|
|
<b>while</b>(p){
|
|
<b>if</b>(p.ownerTree){
|
|
<b>this</b>.ownerTree = p.ownerTree;
|
|
<b>break</b>;
|
|
}
|
|
p = p.parentNode;
|
|
}
|
|
}
|
|
<b>return</b> this.ownerTree;
|
|
},
|
|
|
|
<i>/**
|
|
* Returns depth of <b>this</b> node (the root node has a depth of 0)
|
|
* @<b>return</b> {Number}
|
|
*/</i>
|
|
getDepth : <b>function</b>(){
|
|
<b>var</b> depth = 0;
|
|
<b>var</b> p = <b>this</b>;
|
|
<b>while</b>(p.parentNode){
|
|
++depth;
|
|
p = p.parentNode;
|
|
}
|
|
<b>return</b> depth;
|
|
},
|
|
|
|
<i>// private</i>
|
|
setOwnerTree : <b>function</b>(tree){
|
|
<i>// <b>if</b> it's move, we need to update everyone</i>
|
|
<b>if</b>(tree != <b>this</b>.ownerTree){
|
|
<b>if</b>(this.ownerTree){
|
|
<b>this</b>.ownerTree.unregisterNode(<b>this</b>);
|
|
}
|
|
<b>this</b>.ownerTree = tree;
|
|
<b>var</b> cs = <b>this</b>.childNodes;
|
|
<b>for</b>(var i = 0, len = cs.length; i < len; i++) {
|
|
cs[i].setOwnerTree(tree);
|
|
}
|
|
<b>if</b>(tree){
|
|
tree.registerNode(<b>this</b>);
|
|
}
|
|
}
|
|
},
|
|
|
|
<i>/**
|
|
* Returns the path <b>for</b> this node. The path can be used to expand or select <b>this</b> node programmatically.
|
|
* @param {String} attr (optional) The attr to use <b>for</b> the path (defaults to the node's id)
|
|
* @<b>return</b> {String} The path
|
|
*/</i>
|
|
getPath : <b>function</b>(attr){
|
|
attr = attr || "id";
|
|
<b>var</b> p = <b>this</b>.parentNode;
|
|
<b>var</b> b = [<b>this</b>.attributes[attr]];
|
|
<b>while</b>(p){
|
|
b.unshift(p.attributes[attr]);
|
|
p = p.parentNode;
|
|
}
|
|
<b>var</b> sep = <b>this</b>.getOwnerTree().pathSeparator;
|
|
<b>return</b> sep + b.join(sep);
|
|
},
|
|
|
|
<i>/**
|
|
* Bubbles up the tree from <b>this</b> node, calling the specified <b>function</b> with each node. The scope (<i><b>this</b></i>) of
|
|
* <b>function</b> call will be the scope provided or the current node. The arguments to the <b>function</b>
|
|
* will be the args provided or the current node. If the <b>function</b> returns false at any point,
|
|
* the bubble is stopped.
|
|
* @param {Function} fn The <b>function</b> to call
|
|
* @param {Object} scope (optional) The scope of the <b>function</b> (defaults to current node)
|
|
* @param {Array} args (optional) The args to call the <b>function</b> with (<b>default</b> to passing the current node)
|
|
*/</i>
|
|
bubble : <b>function</b>(fn, scope, args){
|
|
<b>var</b> p = <b>this</b>;
|
|
<b>while</b>(p){
|
|
<b>if</b>(fn.call(scope || p, args || p) === false){
|
|
<b>break</b>;
|
|
}
|
|
p = p.parentNode;
|
|
}
|
|
},
|
|
|
|
<i>/**
|
|
* Cascades down the tree from <b>this</b> node, calling the specified <b>function</b> with each node. The scope (<i><b>this</b></i>) of
|
|
* <b>function</b> call will be the scope provided or the current node. The arguments to the <b>function</b>
|
|
* will be the args provided or the current node. If the <b>function</b> returns false at any point,
|
|
* the cascade is stopped on that branch.
|
|
* @param {Function} fn The <b>function</b> to call
|
|
* @param {Object} scope (optional) The scope of the <b>function</b> (defaults to current node)
|
|
* @param {Array} args (optional) The args to call the <b>function</b> with (<b>default</b> to passing the current node)
|
|
*/</i>
|
|
cascade : <b>function</b>(fn, scope, args){
|
|
<b>if</b>(fn.call(scope || <b>this</b>, args || <b>this</b>) !== false){
|
|
<b>var</b> cs = <b>this</b>.childNodes;
|
|
<b>for</b>(var i = 0, len = cs.length; i < len; i++) {
|
|
cs[i].cascade(fn, scope, args);
|
|
}
|
|
}
|
|
},
|
|
|
|
<i>/**
|
|
* Interates the child nodes of <b>this</b> node, calling the specified <b>function</b> with each node. The scope (<i><b>this</b></i>) of
|
|
* <b>function</b> call will be the scope provided or the current node. The arguments to the <b>function</b>
|
|
* will be the args provided or the current node. If the <b>function</b> returns false at any point,
|
|
* the iteration stops.
|
|
* @param {Function} fn The <b>function</b> to call
|
|
* @param {Object} scope (optional) The scope of the <b>function</b> (defaults to current node)
|
|
* @param {Array} args (optional) The args to call the <b>function</b> with (<b>default</b> to passing the current node)
|
|
*/</i>
|
|
eachChild : <b>function</b>(fn, scope, args){
|
|
<b>var</b> cs = <b>this</b>.childNodes;
|
|
<b>for</b>(var i = 0, len = cs.length; i < len; i++) {
|
|
<b>if</b>(fn.call(scope || <b>this</b>, args || cs[i]) === false){
|
|
<b>break</b>;
|
|
}
|
|
}
|
|
},
|
|
|
|
<i>/**
|
|
* Finds the first child that has the attribute <b>with</b> the specified value.
|
|
* @param {String} attribute The attribute name
|
|
* @param {Mixed} value The value to search <b>for</b>
|
|
* @<b>return</b> {Node} The found child or null <b>if</b> none was found
|
|
*/</i>
|
|
findChild : <b>function</b>(attribute, value){
|
|
<b>var</b> cs = <b>this</b>.childNodes;
|
|
<b>for</b>(var i = 0, len = cs.length; i < len; i++) {
|
|
<b>if</b>(cs[i].attributes[attribute] == value){
|
|
<b>return</b> cs[i];
|
|
}
|
|
}
|
|
<b>return</b> null;
|
|
},
|
|
|
|
<i>/**
|
|
* Finds the first child by a custom <b>function</b>. The child matches <b>if</b> the <b>function</b> passed
|
|
* returns true.
|
|
* @param {Function} fn
|
|
* @param {Object} scope (optional)
|
|
* @<b>return</b> {Node} The found child or null <b>if</b> none was found
|
|
*/</i>
|
|
findChildBy : <b>function</b>(fn, scope){
|
|
<b>var</b> cs = <b>this</b>.childNodes;
|
|
<b>for</b>(var i = 0, len = cs.length; i < len; i++) {
|
|
<b>if</b>(fn.call(scope||cs[i], cs[i]) === true){
|
|
<b>return</b> cs[i];
|
|
}
|
|
}
|
|
<b>return</b> null;
|
|
},
|
|
|
|
<i>/**
|
|
* Sorts <b>this</b> nodes children using the supplied sort <b>function</b>
|
|
* @param {Function} fn
|
|
* @param {Object} scope (optional)
|
|
*/</i>
|
|
sort : <b>function</b>(fn, scope){
|
|
<b>var</b> cs = <b>this</b>.childNodes;
|
|
<b>var</b> len = cs.length;
|
|
<b>if</b>(len > 0){
|
|
<b>var</b> sortFn = scope ? <b>function</b>(){fn.apply(scope, arguments);} : fn;
|
|
cs.sort(sortFn);
|
|
<b>for</b>(var i = 0; i < len; i++){
|
|
<b>var</b> n = cs[i];
|
|
n.previousSibling = cs[i-1];
|
|
n.nextSibling = cs[i+1];
|
|
<b>if</b>(i == 0){
|
|
<b>this</b>.setFirstChild(n);
|
|
}
|
|
<b>if</b>(i == len-1){
|
|
<b>this</b>.setLastChild(n);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
<i>/**
|
|
* Returns true <b>if</b> this node is an ancestor (at any point) of the passed node.
|
|
* @param {Node} node
|
|
* @<b>return</b> {Boolean}
|
|
*/</i>
|
|
contains : <b>function</b>(node){
|
|
<b>return</b> node.isAncestor(<b>this</b>);
|
|
},
|
|
|
|
<i>/**
|
|
* Returns true <b>if</b> the passed node is an ancestor (at any point) of <b>this</b> node.
|
|
* @param {Node} node
|
|
* @<b>return</b> {Boolean}
|
|
*/</i>
|
|
isAncestor : <b>function</b>(node){
|
|
<b>var</b> p = <b>this</b>.parentNode;
|
|
<b>while</b>(p){
|
|
<b>if</b>(p == node){
|
|
<b>return</b> true;
|
|
}
|
|
p = p.parentNode;
|
|
}
|
|
<b>return</b> false;
|
|
},
|
|
|
|
toString : <b>function</b>(){
|
|
<b>return</b> "[Node"+(<b>this</b>.id?" "+<b>this</b>.id:"")+"]";
|
|
}
|
|
});</code></pre><hr><div style="font-size:10px;text-align:center;color:gray;">Ext - Copyright © 2006-2007 Ext JS, LLC<br />All rights reserved.</div>
|
|
</body></html> |