<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The source code</title>
- <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
- <script type="text/javascript" src="../prettify/prettify.js"></script>
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
<style type="text/css">
.highlight { display: block; background-color: #ddd; }
</style>
</head>
<body onload="prettyPrint(); highlight();">
<pre class="prettyprint lang-js"><span id='Ext-data-NodeInterface'>/**
-</span> * @class Ext.data.NodeInterface
- * This class is meant to be used as a set of methods that are applied to the prototype of a
- * Record to decorate it with a Node API. This means that models used in conjunction with a tree
+</span> * This class is used as a set of methods that are applied to the prototype of a
+ * Model to decorate it with a Node API. This means that models used in conjunction with a tree
* will have all of the tree related methods available on the model. In general this class will
- * not be used directly by the developer.
+ * not be used directly by the developer. This class also creates extra fields on the model if
+ * they do not exist, to help maintain the tree state and UI. These fields are documented as
+ * config options.
*/
Ext.define('Ext.data.NodeInterface', {
requires: ['Ext.data.Field'],
-
+
+<span id='Ext-data-NodeInterface-cfg-parentId'> /**
+</span> * @cfg {String} parentId
+ * ID of parent node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-index'> /**
+</span> * @cfg {Number} index
+ * The position of the node inside its parent. When parent has 4 children and the node is third amongst them,
+ * index will be 2.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-depth'> /**
+</span> * @cfg {Number} depth
+ * The number of parents this node has. A root node has depth 0, a child of it depth 1, and so on...
+ */
+
+<span id='Ext-data-NodeInterface-cfg-expanded'> /**
+</span> * @cfg {Boolean} [expanded=false]
+ * True if the node is expanded.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-expandable'> /**
+</span> * @cfg {Boolean} [expandable=false]
+ * Set to true to allow for expanding/collapsing of this node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-checked'> /**
+</span> * @cfg {Boolean} [checked=null]
+ * Set to true or false to show a checkbox alongside this node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-leaf'> /**
+</span> * @cfg {Boolean} [leaf=false]
+ * Set to true to indicate that this child can have no children. The expand icon/arrow will then not be
+ * rendered for this node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-cls'> /**
+</span> * @cfg {String} cls
+ * CSS class to apply for this node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-iconCls'> /**
+</span> * @cfg {String} iconCls
+ * CSS class to apply for this node's icon.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-icon'> /**
+</span> * @cfg {String} icon
+ * URL for this node's icon.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-root'> /**
+</span> * @cfg {Boolean} root
+ * True if this is the root node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-isLast'> /**
+</span> * @cfg {Boolean} isLast
+ * True if this is the last node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-isFirst'> /**
+</span> * @cfg {Boolean} isFirst
+ * True if this is the first node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-allowDrop'> /**
+</span> * @cfg {Boolean} [allowDrop=true]
+ * Set to false to deny dropping on this node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-allowDrag'> /**
+</span> * @cfg {Boolean} [allowDrag=true]
+ * Set to false to deny dragging of this node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-loaded'> /**
+</span> * @cfg {Boolean} [loaded=false]
+ * True if the node has finished loading.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-loading'> /**
+</span> * @cfg {Boolean} [loading=false]
+ * True if the node is currently loading.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-href'> /**
+</span> * @cfg {String} href
+ * An URL for a link that's created when this config is specified.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-hrefTarget'> /**
+</span> * @cfg {String} hrefTarget
+ * Target for link. Only applicable when {@link #href} also specified.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-qtip'> /**
+</span> * @cfg {String} qtip
+ * Tooltip text to show on this node.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-qtitle'> /**
+</span> * @cfg {String} qtitle
+ * Tooltip title.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-text'> /**
+</span> * @cfg {String} text
+ * The text for to show on node label.
+ */
+
+<span id='Ext-data-NodeInterface-cfg-children'> /**
+</span> * @cfg {Ext.data.NodeInterface[]} children
+ * Array of child nodes.
+ */
+
+
+<span id='Ext-data-NodeInterface-property-nextSibling'> /**
+</span> * @property nextSibling
+ * A reference to this node's next sibling node. `null` if this node does not have a next sibling.
+ */
+
+<span id='Ext-data-NodeInterface-property-previousSibling'> /**
+</span> * @property previousSibling
+ * A reference to this node's previous sibling node. `null` if this node does not have a previous sibling.
+ */
+
+<span id='Ext-data-NodeInterface-property-parentNode'> /**
+</span> * @property parentNode
+ * A reference to this node's parent node. `null` if this node is the root node.
+ */
+
+<span id='Ext-data-NodeInterface-property-lastChild'> /**
+</span> * @property lastChild
+ * A reference to this node's last child node. `null` if this node has no children.
+ */
+
+<span id='Ext-data-NodeInterface-property-firstChild'> /**
+</span> * @property firstChild
+ * A reference to this node's first child node. `null` if this node has no children.
+ */
+
+<span id='Ext-data-NodeInterface-property-childNodes'> /**
+</span> * @property childNodes
+ * An array of this nodes children. Array will be empty if this node has no chidren.
+ */
+
statics: {
-<span id='Ext-data-NodeInterface-method-decorate'> /**
+<span id='Ext-data-NodeInterface-static-method-decorate'> /**
</span> * This method allows you to decorate a Record's prototype to implement the NodeInterface.
* This adds a set of methods, new events, new properties and new fields on every Record
* with the same Model as the passed Record.
- * @param {Ext.data.Record} record The Record you want to decorate the prototype of.
+ * @param {Ext.data.Model} record The Record you want to decorate the prototype of.
* @static
*/
decorate: function(record) {
modelName = record.modelName,
modelClass = mgr.getModel(modelName),
idName = modelClass.prototype.idProperty,
- instances = Ext.Array.filter(mgr.all.getArray(), function(item) {
- return item.modelName == modelName;
- }),
- iln = instances.length,
newFields = [],
- i, instance, jln, j, newField;
+ i, newField, len;
// Start by adding the NodeInterface methods to the Model's prototype
modelClass.override(this.getPrototypeBody());
newFields = this.applyFields(modelClass, [
- {name: idName, type: 'string', defaultValue: null},
- {name: 'parentId', type: 'string', defaultValue: null},
- {name: 'index', type: 'int', defaultValue: null},
- {name: 'depth', type: 'int', defaultValue: 0},
- {name: 'expanded', type: 'bool', defaultValue: false, persist: false},
- {name: 'checked', type: 'auto', defaultValue: null},
- {name: 'leaf', type: 'bool', defaultValue: false, persist: false},
- {name: 'cls', type: 'string', defaultValue: null, persist: false},
- {name: 'iconCls', type: 'string', defaultValue: null, persist: false},
- {name: 'root', type: 'boolean', defaultValue: false, persist: false},
- {name: 'isLast', type: 'boolean', defaultValue: false, persist: false},
- {name: 'isFirst', type: 'boolean', defaultValue: false, persist: false},
- {name: 'allowDrop', type: 'boolean', defaultValue: true, persist: false},
- {name: 'allowDrag', type: 'boolean', defaultValue: true, persist: false},
- {name: 'loaded', type: 'boolean', defaultValue: false, persist: false},
- {name: 'loading', type: 'boolean', defaultValue: false, persist: false},
- {name: 'href', type: 'string', defaultValue: null, persist: false},
- {name: 'hrefTarget',type: 'string', defaultValue: null, persist: false},
- {name: 'qtip', type: 'string', defaultValue: null, persist: false},
- {name: 'qtitle', type: 'string', defaultValue: null, persist: false}
+ {name: idName, type: 'string', defaultValue: null},
+ {name: 'parentId', type: 'string', defaultValue: null},
+ {name: 'index', type: 'int', defaultValue: null},
+ {name: 'depth', type: 'int', defaultValue: 0},
+ {name: 'expanded', type: 'bool', defaultValue: false, persist: false},
+ {name: 'expandable', type: 'bool', defaultValue: true, persist: false},
+ {name: 'checked', type: 'auto', defaultValue: null},
+ {name: 'leaf', type: 'bool', defaultValue: false, persist: false},
+ {name: 'cls', type: 'string', defaultValue: null, persist: false},
+ {name: 'iconCls', type: 'string', defaultValue: null, persist: false},
+ {name: 'icon', type: 'string', defaultValue: null, persist: false},
+ {name: 'root', type: 'boolean', defaultValue: false, persist: false},
+ {name: 'isLast', type: 'boolean', defaultValue: false, persist: false},
+ {name: 'isFirst', type: 'boolean', defaultValue: false, persist: false},
+ {name: 'allowDrop', type: 'boolean', defaultValue: true, persist: false},
+ {name: 'allowDrag', type: 'boolean', defaultValue: true, persist: false},
+ {name: 'loaded', type: 'boolean', defaultValue: false, persist: false},
+ {name: 'loading', type: 'boolean', defaultValue: false, persist: false},
+ {name: 'href', type: 'string', defaultValue: null, persist: false},
+ {name: 'hrefTarget', type: 'string', defaultValue: null, persist: false},
+ {name: 'qtip', type: 'string', defaultValue: null, persist: false},
+ {name: 'qtitle', type: 'string', defaultValue: null, persist: false}
]);
- jln = newFields.length;
- // Set default values to all instances already out there
- for (i = 0; i < iln; i++) {
- instance = instances[i];
- for (j = 0; j < jln; j++) {
- newField = newFields[j];
- if (instance.get(newField.name) === undefined) {
- instance.data[newField.name] = newField.defaultValue;
- }
+ len = newFields.length;
+ // Set default values
+ for (i = 0; i < len; ++i) {
+ newField = newFields[i];
+ if (record.get(newField.name) === undefined) {
+ record.data[newField.name] = newField.defaultValue;
}
}
}
-
+
Ext.applyIf(record, {
firstChild: null,
lastChild: null,
});
// Commit any fields so the record doesn't show as dirty initially
record.commit(true);
-
+
record.enableBubble([
<span id='Ext-data-NodeInterface-event-append'> /**
</span> * @event append
* Fires when a new child node is appended
- * @param {Node} this This node
- * @param {Node} node The newly appended node
+ * @param {Ext.data.NodeInterface} this This node
+ * @param {Ext.data.NodeInterface} node The newly appended node
* @param {Number} index The index of the newly appended node
*/
"append",
<span id='Ext-data-NodeInterface-event-remove'> /**
</span> * @event remove
* Fires when a child node is removed
- * @param {Node} this This node
- * @param {Node} node The removed node
+ * @param {Ext.data.NodeInterface} this This node
+ * @param {Ext.data.NodeInterface} node The removed node
*/
"remove",
<span id='Ext-data-NodeInterface-event-move'> /**
</span> * @event move
* Fires when this node is moved to a new location in the tree
- * @param {Node} this This node
- * @param {Node} oldParent The old parent of this node
- * @param {Node} newParent The new parent of this node
+ * @param {Ext.data.NodeInterface} this This node
+ * @param {Ext.data.NodeInterface} oldParent The old parent of this node
+ * @param {Ext.data.NodeInterface} newParent The new parent of this node
* @param {Number} index The index it was moved to
*/
"move",
<span id='Ext-data-NodeInterface-event-insert'> /**
</span> * @event insert
* Fires when a new child node is inserted.
- * @param {Node} this This node
- * @param {Node} node The child node inserted
- * @param {Node} refNode The child node the node was inserted before
+ * @param {Ext.data.NodeInterface} this This node
+ * @param {Ext.data.NodeInterface} node The child node inserted
+ * @param {Ext.data.NodeInterface} refNode The child node the node was inserted before
*/
"insert",
<span id='Ext-data-NodeInterface-event-beforeappend'> /**
</span> * @event beforeappend
* Fires before a new child is appended, return false to cancel the append.
- * @param {Node} this This node
- * @param {Node} node The child node to be appended
+ * @param {Ext.data.NodeInterface} this This node
+ * @param {Ext.data.NodeInterface} node The child node to be appended
*/
"beforeappend",
<span id='Ext-data-NodeInterface-event-beforeremove'> /**
</span> * @event beforeremove
* Fires before a child is removed, return false to cancel the remove.
- * @param {Node} this This node
- * @param {Node} node The child node to be removed
+ * @param {Ext.data.NodeInterface} this This node
+ * @param {Ext.data.NodeInterface} node The child node to be removed
*/
"beforeremove",
<span id='Ext-data-NodeInterface-event-beforemove'> /**
</span> * @event beforemove
* Fires before this node is moved to a new location in the tree. Return false to cancel the move.
- * @param {Node} this This node
- * @param {Node} oldParent The parent of this node
- * @param {Node} newParent The new parent this node is moving to
+ * @param {Ext.data.NodeInterface} this This node
+ * @param {Ext.data.NodeInterface} oldParent The parent of this node
+ * @param {Ext.data.NodeInterface} newParent The new parent this node is moving to
* @param {Number} index The index it is being moved to
*/
"beforemove",
<span id='Ext-data-NodeInterface-event-beforeinsert'> /**
</span> * @event beforeinsert
* Fires before a new child is inserted, return false to cancel the insert.
- * @param {Node} this This node
- * @param {Node} node The child node to be inserted
- * @param {Node} refNode The child node the node is being inserted before
+ * @param {Ext.data.NodeInterface} this This node
+ * @param {Ext.data.NodeInterface} node The child node to be inserted
+ * @param {Ext.data.NodeInterface} refNode The child node the node is being inserted before
*/
"beforeinsert",
-
+
<span id='Ext-data-NodeInterface-event-expand'> /**
</span> * @event expand
* Fires when this node is expanded.
- * @param {Node} this The expanding node
+ * @param {Ext.data.NodeInterface} this The expanding node
*/
"expand",
-
+
<span id='Ext-data-NodeInterface-event-collapse'> /**
</span> * @event collapse
* Fires when this node is collapsed.
- * @param {Node} this The collapsing node
+ * @param {Ext.data.NodeInterface} this The collapsing node
*/
"collapse",
-
+
<span id='Ext-data-NodeInterface-event-beforeexpand'> /**
</span> * @event beforeexpand
* Fires before this node is expanded.
- * @param {Node} this The expanding node
+ * @param {Ext.data.NodeInterface} this The expanding node
*/
"beforeexpand",
-
+
<span id='Ext-data-NodeInterface-event-beforecollapse'> /**
</span> * @event beforecollapse
* Fires before this node is collapsed.
- * @param {Node} this The collapsing node
+ * @param {Ext.data.NodeInterface} this The collapsing node
*/
"beforecollapse",
-
-<span id='Ext-data-NodeInterface-event-beforecollapse'> /**
-</span> * @event beforecollapse
- * Fires before this node is collapsed.
- * @param {Node} this The collapsing node
+
+<span id='Ext-data-NodeInterface-event-sort'> /**
+</span> * @event sort
+ * Fires when this node's childNodes are sorted.
+ * @param {Ext.data.NodeInterface} this This node.
+ * @param {Ext.data.NodeInterface[]} childNodes The childNodes of this node.
*/
"sort"
]);
-
+
return record;
},
-
+
applyFields: function(modelClass, addFields) {
var modelPrototype = modelClass.prototype,
fields = modelPrototype.fields,
ln = addFields.length,
addField, i, name,
newFields = [];
-
+
for (i = 0; i < ln; i++) {
addField = addFields[i];
if (!Ext.Array.contains(keys, addField.name)) {
addField = Ext.create('data.field', addField);
-
+
newFields.push(addField);
fields.add(addField);
}
}
-
+
return newFields;
},
-
+
getPrototypeBody: function() {
return {
isNode: true,
// Make sure the node implements the node interface
return Ext.data.NodeInterface.decorate(node);
},
-
+
<span id='Ext-data-NodeInterface-method-isLeaf'> /**
</span> * Returns true if this node is a leaf
* @return {Boolean}
while (parent.parentNode) {
++depth;
parent = parent.parentNode;
- }
-
+ }
+
me.beginEdit();
me.set({
isFirst: isFirst,
if (silent) {
me.commit();
}
-
+
for (i = 0; i < len; i++) {
children[i].updateInfo(silent);
}
<span id='Ext-data-NodeInterface-method-isExpandable'> /**
</span> * Returns true if this node has one or more child nodes, or if the <tt>expandable</tt>
- * node attribute is explicitly specified as true (see {@link #attributes}), otherwise returns false.
+ * node attribute is explicitly specified as true, otherwise returns false.
* @return {Boolean}
*/
isExpandable : function() {
- return this.get('expandable') || this.hasChildNodes();
+ var me = this;
+
+ if (me.get('expandable')) {
+ return !(me.isLeaf() || (me.isLoaded() && !me.hasChildNodes()));
+ }
+ return false;
},
<span id='Ext-data-NodeInterface-method-appendChild'> /**
-</span> * <p>Insert node(s) as the last child node of this node.</p>
- * <p>If the node was previously a child node of another parent node, it will be removed from that node first.</p>
- * @param {Node/Array} node The node or Array of nodes to append
- * @return {Node} The appended node if single append, or null if an array was passed
+</span> * Inserts node(s) as the last child node of this node.
+ *
+ * If the node was previously a child node of another parent node, it will be removed from that node first.
+ *
+ * @param {Ext.data.NodeInterface/Ext.data.NodeInterface[]} node The node or Array of nodes to append
+ * @return {Ext.data.NodeInterface} The appended node if single append, or null if an array was passed
*/
appendChild : function(node, suppressEvents, suppressNodeUpdate) {
var me = this,
} else {
// Make sure it is a record
node = me.createNode(node);
-
+
if (suppressEvents !== true && me.fireEvent("beforeappend", me, node) === false) {
- return false;
+ return false;
}
index = me.childNodes.length;
node.nextSibling = null;
me.setLastChild(node);
-
+
ps = me.childNodes[index - 1];
if (ps) {
node.previousSibling = ps;
}
node.updateInfo(suppressNodeUpdate);
-
+
// As soon as we append a child to this node, we are loaded
if (!me.isLoaded()) {
- me.set('loaded', true);
+ me.set('loaded', true);
}
// If this node didnt have any childnodes before, update myself
else if (me.childNodes.length === 1) {
me.set('loaded', me.isLoaded());
}
-
+
if (suppressEvents !== true) {
me.fireEvent("append", me, node, index);
if (oldParent) {
node.fireEvent("move", node, oldParent, me, index);
- }
+ }
}
return node;
}
},
-
+
<span id='Ext-data-NodeInterface-method-getBubbleTarget'> /**
</span> * Returns the bubble target for this node
* @private
<span id='Ext-data-NodeInterface-method-removeChild'> /**
</span> * Removes a child node from this node.
- * @param {Node} node The node to remove
- * @param {Boolean} destroy <tt>true</tt> to destroy the node upon removal. Defaults to <tt>false</tt>.
- * @return {Node} The removed node
+ * @param {Ext.data.NodeInterface} node The node to remove
+ * @param {Boolean} [destroy=false] True to destroy the node upon removal.
+ * @return {Ext.data.NodeInterface} The removed node
*/
removeChild : function(node, destroy, suppressEvents, suppressNodeUpdate) {
var me = this,
index = me.indexOf(node);
-
+
if (index == -1 || (suppressEvents !== true && me.fireEvent("beforeremove", me, node) === false)) {
return false;
}
// remove it from childNodes collection
- me.childNodes.splice(index, 1);
+ Ext.Array.erase(me.childNodes, index, 1);
// update child refs
if (me.firstChild == node) {
if (me.lastChild == node) {
me.setLastChild(node.previousSibling);
}
-
+
// update siblings
if (node.previousSibling) {
node.previousSibling.nextSibling = node.nextSibling;
if (suppressEvents !== true) {
me.fireEvent("remove", me, node);
}
-
-
+
+
// If this node suddenly doesnt have childnodes anymore, update myself
if (!me.childNodes.length) {
me.set('loaded', me.isLoaded());
}
-
+
if (destroy) {
node.destroy(true);
} else {
<span id='Ext-data-NodeInterface-method-copy'> /**
</span> * Creates a copy (clone) of this Node.
- * @param {String} id (optional) A new id, defaults to this Node's id. See <code>{@link #id}</code>.
- * @param {Boolean} deep (optional) <p>If passed as <code>true</code>, all child Nodes are recursively copied into the new Node.</p>
- * <p>If omitted or false, the copy will have no child Nodes.</p>
- * @return {Node} A copy of this Node.
+ * @param {String} [id] A new id, defaults to this Node's id.
+ * @param {Boolean} [deep=false] True to recursively copy all child Nodes into the new Node.
+ * False to copy without child Nodes.
+ * @return {Ext.data.NodeInterface} A copy of this Node.
*/
copy: function(newId, deep) {
var me = this,
},
<span id='Ext-data-NodeInterface-method-clear'> /**
-</span> * Clear the node.
+</span> * Clears the node.
* @private
- * @param {Boolean} destroy True to destroy the node.
+ * @param {Boolean} [destroy=false] True to destroy the node.
*/
clear : function(destroy) {
var me = this;
-
+
// clear any references from the node
me.parentNode = me.previousSibling = me.nextSibling = null;
if (destroy) {
*/
var me = this,
options = me.destroyOptions;
-
+
if (silent === true) {
me.clear(true);
Ext.each(me.childNodes, function(n) {
<span id='Ext-data-NodeInterface-method-insertBefore'> /**
</span> * Inserts the first node before the second node in this nodes childNodes collection.
- * @param {Node} node The node to insert
- * @param {Node} refNode The node to insert before (if null the node is appended)
- * @return {Node} The inserted node
+ * @param {Ext.data.NodeInterface} node The node to insert
+ * @param {Ext.data.NodeInterface} refNode The node to insert before (if null the node is appended)
+ * @return {Ext.data.NodeInterface} The inserted node
*/
insertBefore : function(node, refNode, suppressEvents) {
var me = this,
oldParent = node.parentNode,
refIndex = index,
ps;
-
+
if (!refNode) { // like standard Dom, refNode can be null for append
return me.appendChild(node);
}
-
+
// nothing to do
if (node == refNode) {
return false;
// Make sure it is a record with the NodeInterface
node = me.createNode(node);
-
+
if (suppressEvents !== true && me.fireEvent("beforeinsert", me, node, refNode) === false) {
return false;
}
-
+
// when moving internally, indexes will change after remove
if (oldParent == me && me.indexOf(node) < index) {
refIndex--;
me.setFirstChild(node);
}
- me.childNodes.splice(refIndex, 0, node);
+ Ext.Array.splice(me.childNodes, refIndex, 0, node);
node.parentNode = me;
-
+
node.nextSibling = refNode;
refNode.previousSibling = node;
-
+
ps = me.childNodes[refIndex - 1];
if (ps) {
node.previousSibling = ps;
} else {
node.previousSibling = null;
}
-
+
node.updateInfo();
-
+
if (!me.isLoaded()) {
- me.set('loaded', true);
- }
+ me.set('loaded', true);
+ }
// If this node didnt have any childnodes before, update myself
else if (me.childNodes.length === 1) {
me.set('loaded', me.isLoaded());
if (oldParent) {
node.fireEvent("move", node, oldParent, me, refIndex, refNode);
- }
+ }
}
return node;
},
-
+
<span id='Ext-data-NodeInterface-method-insertChild'> /**
</span> * Insert a node into this node
* @param {Number} index The zero-based index to insert the node at
* @param {Ext.data.Model} node The node to insert
- * @return {Ext.data.Record} The record you just inserted
- */
+ * @return {Ext.data.Model} The record you just inserted
+ */
insertChild: function(index, node) {
var sibling = this.childNodes[index];
if (sibling) {
<span id='Ext-data-NodeInterface-method-remove'> /**
</span> * Removes this node from its parent
- * @param {Boolean} destroy <tt>true</tt> to destroy the node upon removal. Defaults to <tt>false</tt>.
- * @return {Node} this
+ * @param {Boolean} [destroy=false] True to destroy the node upon removal.
+ * @return {Ext.data.NodeInterface} this
*/
remove : function(destroy, suppressEvents) {
var parentNode = this.parentNode;
<span id='Ext-data-NodeInterface-method-removeAll'> /**
</span> * Removes all child nodes from this node.
- * @param {Boolean} destroy <tt>true</tt> to destroy the node upon removal. Defaults to <tt>false</tt>.
- * @return {Node} this
+ * @param {Boolean} [destroy=false] <True to destroy the node upon removal.
+ * @return {Ext.data.NodeInterface} this
*/
removeAll : function(destroy, suppressEvents) {
var cn = this.childNodes,
<span id='Ext-data-NodeInterface-method-getChildAt'> /**
</span> * Returns the child node at the specified index.
* @param {Number} index
- * @return {Node}
+ * @return {Ext.data.NodeInterface}
*/
getChildAt : function(index) {
return this.childNodes[index];
<span id='Ext-data-NodeInterface-method-replaceChild'> /**
</span> * Replaces one child node in this node with another.
- * @param {Node} newChild The replacement node
- * @param {Node} oldChild The node to replace
- * @return {Node} The replaced node
+ * @param {Ext.data.NodeInterface} newChild The replacement node
+ * @param {Ext.data.NodeInterface} oldChild The node to replace
+ * @return {Ext.data.NodeInterface} The replaced node
*/
replaceChild : function(newChild, oldChild, suppressEvents) {
var s = oldChild ? oldChild.nextSibling : null;
-
+
this.removeChild(oldChild, suppressEvents);
this.insertBefore(newChild, s, suppressEvents);
return oldChild;
<span id='Ext-data-NodeInterface-method-indexOf'> /**
</span> * Returns the index of a child node
- * @param {Node} node
+ * @param {Ext.data.NodeInterface} node
* @return {Number} The index of the node or -1 if it was not found
*/
indexOf : function(child) {
return Ext.Array.indexOf(this.childNodes, child);
},
+<span id='Ext-data-NodeInterface-method-getPath'> /**
+</span> * Gets the hierarchical path from the root of the current node.
+ * @param {String} [field] The field to construct the path from. Defaults to the model idProperty.
+ * @param {String} [separator="/"] A separator to use.
+ * @return {String} The node path
+ */
+ getPath: function(field, separator) {
+ field = field || this.idProperty;
+ separator = separator || '/';
+
+ var path = [this.get(field)],
+ parent = this.parentNode;
+
+ while (parent) {
+ path.unshift(parent.get(field));
+ parent = parent.parentNode;
+ }
+ return separator + path.join(separator);
+ },
+
<span id='Ext-data-NodeInterface-method-getDepth'> /**
</span> * Returns depth of this node (the root node has a depth of 0)
* @return {Number}
* will be the args provided or the current node. If the function returns false at any point,
* the bubble is stopped.
* @param {Function} fn The function to call
- * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node.
- * @param {Array} args (optional) The args to call the function with (default to passing the current Node)
+ * @param {Object} [scope] The scope (this reference) in which the function is executed. Defaults to the current Node.
+ * @param {Array} [args] The args to call the function with. Defaults to passing the current Node.
*/
bubble : function(fn, scope, args) {
var p = this;
* will be the args provided or the current node. If the function returns false at any point,
* the cascade is stopped on that branch.
* @param {Function} fn The function to call
- * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node.
- * @param {Array} args (optional) The args to call the function with (default to passing the current Node)
+ * @param {Object} [scope] The scope (this reference) in which the function is executed. Defaults to the current Node.
+ * @param {Array} [args] The args to call the function with. Defaults to passing the current Node.
*/
cascadeBy : function(fn, scope, args) {
if (fn.apply(scope || this, args || [this]) !== false) {
* will be the args provided or the current node. If the function returns false at any point,
* the iteration stops.
* @param {Function} fn The function to call
- * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node in the iteration.
- * @param {Array} args (optional) The args to call the function with (default to passing the current Node)
+ * @param {Object} [scope] The scope (this reference) in which the function is executed. Defaults to the current Node in iteration.
+ * @param {Array} [args] The args to call the function with. Defaults to passing the current Node.
*/
eachChild : function(fn, scope, args) {
var childNodes = this.childNodes,
<span id='Ext-data-NodeInterface-method-findChild'> /**
</span> * Finds the first child that has the attribute with the specified value.
* @param {String} attribute The attribute name
- * @param {Mixed} value The value to search for
- * @param {Boolean} deep (Optional) True to search through nodes deeper than the immediate children
- * @return {Node} The found child or null if none was found
+ * @param {Object} value The value to search for
+ * @param {Boolean} [deep=false] True to search through nodes deeper than the immediate children
+ * @return {Ext.data.NodeInterface} The found child or null if none was found
*/
findChild : function(attribute, value, deep) {
return this.findChildBy(function() {
},
<span id='Ext-data-NodeInterface-method-findChildBy'> /**
-</span> * Finds the first child by a custom function. The child matches if the function passed returns <code>true</code>.
- * @param {Function} fn A function which must return <code>true</code> if the passed Node is the required Node.
- * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the Node being tested.
- * @param {Boolean} deep (Optional) True to search through nodes deeper than the immediate children
- * @return {Node} The found child or null if none was found
+</span> * Finds the first child by a custom function. The child matches if the function passed returns true.
+ * @param {Function} fn A function which must return true if the passed Node is the required Node.
+ * @param {Object} [scope] The scope (this reference) in which the function is executed. Defaults to the Node being tested.
+ * @param {Boolean} [deep=false] True to search through nodes deeper than the immediate children
+ * @return {Ext.data.NodeInterface} The found child or null if none was found
*/
findChildBy : function(fn, scope, deep) {
var cs = this.childNodes,
<span id='Ext-data-NodeInterface-method-contains'> /**
</span> * Returns true if this node is an ancestor (at any point) of the passed node.
- * @param {Node} node
+ * @param {Ext.data.NodeInterface} node
* @return {Boolean}
*/
contains : function(node) {
<span id='Ext-data-NodeInterface-method-isAncestor'> /**
</span> * Returns true if the passed node is an ancestor (at any point) of this node.
- * @param {Node} node
+ * @param {Ext.data.NodeInterface} node
* @return {Boolean}
*/
isAncestor : function(node) {
<span id='Ext-data-NodeInterface-method-sort'> /**
</span> * Sorts this nodes children using the supplied sort function.
* @param {Function} fn A function which, when passed two Nodes, returns -1, 0 or 1 depending upon required sort order.
- * @param {Boolean} recursive Whether or not to apply this sort recursively
- * @param {Boolean} suppressEvent Set to true to not fire a sort event.
+ * @param {Boolean} [recursive=false] True to apply this sort recursively
+ * @param {Boolean} [suppressEvent=false] True to not fire a sort event.
*/
sort : function(sortFn, recursive, suppressEvent) {
var cs = this.childNodes,
ln = cs.length,
i, n;
-
+
if (ln > 0) {
Ext.Array.sort(cs, sortFn);
for (i = 0; i < ln; i++) {
n = cs[i];
n.previousSibling = cs[i-1];
n.nextSibling = cs[i+1];
-
+
if (i === 0) {
this.setFirstChild(n);
n.updateInfo();
n.sort(sortFn, true, true);
}
}
-
+
if (suppressEvent !== true) {
this.fireEvent('sort', this, cs);
}
}
},
-
+
<span id='Ext-data-NodeInterface-method-isExpanded'> /**
</span> * Returns true if this node is expaned
* @return {Boolean}
- */
+ */
isExpanded: function() {
return this.get('expanded');
},
-
+
<span id='Ext-data-NodeInterface-method-isLoaded'> /**
</span> * Returns true if this node is loaded
* @return {Boolean}
- */
+ */
isLoaded: function() {
return this.get('loaded');
},
<span id='Ext-data-NodeInterface-method-isLoading'> /**
</span> * Returns true if this node is loading
* @return {Boolean}
- */
+ */
isLoading: function() {
return this.get('loading');
},
-
+
<span id='Ext-data-NodeInterface-method-isRoot'> /**
</span> * Returns true if this node is the root node
* @return {Boolean}
- */
+ */
isRoot: function() {
return !this.parentNode;
},
-
+
<span id='Ext-data-NodeInterface-method-isVisible'> /**
</span> * Returns true if this node is visible
* @return {Boolean}
- */
+ */
isVisible: function() {
var parent = this.parentNode;
while (parent) {
}
return true;
},
-
+
<span id='Ext-data-NodeInterface-method-expand'> /**
</span> * Expand this node.
- * @param {Function} recursive (Optional) True to recursively expand all the children
- * @param {Function} callback (Optional) The function to execute once the expand completes
- * @param {Object} scope (Optional) The scope to run the callback in
+ * @param {Boolean} [recursive=false] True to recursively expand all the children
+ * @param {Function} [callback] The function to execute once the expand completes
+ * @param {Object} [scope] The scope to run the callback in
*/
expand: function(recursive, callback, scope) {
var me = this;
// First we start by checking if this node is a parent
if (!me.isLeaf()) {
- // Now we check if this record is already expanding or expanded
- if (!me.isLoading() && !me.isExpanded()) {
- // The TreeStore actually listens for the beforeexpand method and checks
- // whether we have to asynchronously load the children from the server
- // first. Thats why we pass a callback function to the event that the
- // store can call once it has loaded and parsed all the children.
- me.fireEvent('beforeexpand', me, function(records) {
- me.set('expanded', true);
- me.fireEvent('expand', me, me.childNodes, false);
-
- // Call the expandChildren method if recursive was set to true
- if (recursive) {
- me.expandChildren(true, callback, scope);
- }
- else {
- Ext.callback(callback, scope || me, [me.childNodes]);
- }
- }, me);
- }
- // If it is is already expanded but we want to recursively expand then call expandChildren
- else if (recursive) {
- me.expandChildren(true, callback, scope);
- }
- else {
- Ext.callback(callback, scope || me, [me.childNodes]);
+ // If it's loaded, wait until it loads before proceeding
+ if (me.isLoading()) {
+ me.on('expand', function(){
+ me.expand(recursive, callback, scope);
+ }, me, {single: true});
+ } else {
+ // Now we check if this record is already expanding or expanded
+ if (!me.isExpanded()) {
+ // The TreeStore actually listens for the beforeexpand method and checks
+ // whether we have to asynchronously load the children from the server
+ // first. Thats why we pass a callback function to the event that the
+ // store can call once it has loaded and parsed all the children.
+ me.fireEvent('beforeexpand', me, function(){
+ me.set('expanded', true);
+ me.fireEvent('expand', me, me.childNodes, false);
+
+ // Call the expandChildren method if recursive was set to true
+ if (recursive) {
+ me.expandChildren(true, callback, scope);
+ } else {
+ Ext.callback(callback, scope || me, [me.childNodes]);
+ }
+ }, me);
+ } else if (recursive) {
+ // If it is is already expanded but we want to recursively expand then call expandChildren
+ me.expandChildren(true, callback, scope);
+ } else {
+ Ext.callback(callback, scope || me, [me.childNodes]);
+ }
}
-
- // TODO - if the node isLoading, we probably need to defer the
- // callback until it is loaded (e.g., selectPath would need us
- // to not make the callback until the childNodes exist).
- }
- // If it's not then we fire the callback right away
- else {
+ } else {
+ // If it's not then we fire the callback right away
Ext.callback(callback, scope || me); // leaf = no childNodes
}
},
-
+
<span id='Ext-data-NodeInterface-method-expandChildren'> /**
</span> * Expand all the children of this node.
- * @param {Function} recursive (Optional) True to recursively expand all the children
- * @param {Function} callback (Optional) The function to execute once all the children are expanded
- * @param {Object} scope (Optional) The scope to run the callback in
+ * @param {Boolean} [recursive=false] True to recursively expand all the children
+ * @param {Function} [callback] The function to execute once all the children are expanded
+ * @param {Object} [scope] The scope to run the callback in
*/
expandChildren: function(recursive, callback, scope) {
var me = this,
nodes[i].expand(recursive, function () {
expanding--;
if (callback && !expanding) {
- Ext.callback(callback, scope || me, [me.childNodes]);
+ Ext.callback(callback, scope || me, [me.childNodes]);
}
- });
+ });
}
}
-
+
if (!expanding && callback) {
Ext.callback(callback, scope || me, [me.childNodes]); }
},
<span id='Ext-data-NodeInterface-method-collapse'> /**
</span> * Collapse this node.
- * @param {Function} recursive (Optional) True to recursively collapse all the children
- * @param {Function} callback (Optional) The function to execute once the collapse completes
- * @param {Object} scope (Optional) The scope to run the callback in
+ * @param {Boolean} [recursive=false] True to recursively collapse all the children
+ * @param {Function} [callback] The function to execute once the collapse completes
+ * @param {Object} [scope] The scope to run the callback in
*/
collapse: function(recursive, callback, scope) {
var me = this;
if (!me.isLeaf()) {
// Now we check if this record is already collapsing or collapsed
if (!me.collapsing && me.isExpanded()) {
- me.fireEvent('beforecollapse', me, function(records) {
- me.set('expanded', false);
+ me.fireEvent('beforecollapse', me, function() {
+ me.set('expanded', false);
me.fireEvent('collapse', me, me.childNodes, false);
-
- // Call the collapseChildren method if recursive was set to true
+
+ // Call the collapseChildren method if recursive was set to true
if (recursive) {
me.collapseChildren(true, callback, scope);
}
else {
- Ext.callback(callback, scope || me, [me.childNodes]);
+ Ext.callback(callback, scope || me, [me.childNodes]);
}
- }, me);
+ }, me);
}
// If it is is already collapsed but we want to recursively collapse then call collapseChildren
else if (recursive) {
}
// If it's not then we fire the callback right away
else {
- Ext.callback(callback, scope || me, [me.childNodes]);
+ Ext.callback(callback, scope || me, [me.childNodes]);
}
},
-
+
<span id='Ext-data-NodeInterface-method-collapseChildren'> /**
</span> * Collapse all the children of this node.
- * @param {Function} recursive (Optional) True to recursively collapse all the children
- * @param {Function} callback (Optional) The function to execute once all the children are collapsed
- * @param {Object} scope (Optional) The scope to run the callback in
+ * @param {Function} [recursive=false] True to recursively collapse all the children
+ * @param {Function} [callback] The function to execute once all the children are collapsed
+ * @param {Object} [scope] The scope to run the callback in
*/
collapseChildren: function(recursive, callback, scope) {
var me = this,
nodes[i].collapse(recursive, function () {
collapsing--;
if (callback && !collapsing) {
- Ext.callback(callback, scope || me, [me.childNodes]);
+ Ext.callback(callback, scope || me, [me.childNodes]);
}
- });
+ });
}
}
-
+
if (!collapsing && callback) {
Ext.callback(callback, scope || me, [me.childNodes]);
}