1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>The source code</title>
- <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>
- <script type="text/javascript">
- function highlight() {
- document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
- }
- </script>
- </head>
- <body onload="prettyPrint(); highlight();">
- <pre class="prettyprint lang-js"><span id='Ext-data-NodeInterface'>/**
- </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. 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-static-method-decorate'> /**
- </span> * This method allows you to decorate a Model's class to implement the NodeInterface.
- * This adds a set of methods, new events, new properties and new fields on every Record.
- * @param {Ext.Class/Ext.data.Model} modelClass The Model class or an instance of the Model class you want to
- * decorate the prototype of.
- * @static
- */
- decorate: function(modelClass) {
- var idName, idType;
-
- // get the reference to the model class, in case the argument was a string or a record
- if (typeof modelClass == 'string') {
- modelClass = Ext.ModelManager.getModel(modelClass);
- } else if (modelClass.isModel) {
- modelClass = Ext.ModelManager.getModel(modelClass.modelName);
- }
-
- // avoid unnecessary work in case the model was already decorated
- if (modelClass.prototype.isNode) {
- return;
- }
- idName = modelClass.prototype.idProperty;
- idField = modelClass.prototype.fields.get(idName);
- idType = modelClass.prototype.fields.get(idName).type.type;
- modelClass.override(this.getPrototypeBody());
- this.applyFields(modelClass, [
- {name: 'parentId', type: idType, defaultValue: null, useNull: idField.useNull},
- {name: 'index', type: 'int', defaultValue: null, persist: false},
- {name: 'depth', type: 'int', defaultValue: 0, persist: false},
- {name: 'expanded', type: 'bool', defaultValue: false, persist: false},
- {name: 'expandable', type: 'bool', defaultValue: true, persist: false},
- {name: 'checked', type: 'auto', defaultValue: null, persist: false},
- {name: 'leaf', type: 'bool', defaultValue: 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},
- {name: 'children', type: 'auto', defaultValue: null, persist: false}
- ]);
- },
-
- applyFields: function(modelClass, addFields) {
- var modelPrototype = modelClass.prototype,
- fields = modelPrototype.fields,
- keys = fields.keys,
- ln = addFields.length,
- addField, i;
- for (i = 0; i < ln; i++) {
- addField = addFields[i];
- if (!Ext.Array.contains(keys, addField.name)) {
- fields.add(new Ext.data.Field(addField));
- }
- }
- },
- getPrototypeBody: function() {
- return {
- <span id='Ext-data-NodeInterface-property-isNode'> /**
- </span> * @property {Boolean} isNode
- * `true` in this class to identify an object as an instantiated Node, or subclass thereof.
- */
- isNode: true,
-
- constructor: function() {
- var me = this;
- this.callParent(arguments);
- Ext.applyIf(me, {
- firstChild: null,
- lastChild: null,
- parentNode: null,
- previousSibling: null,
- nextSibling: null,
- childNodes: []
- });
- me.enableBubble([
- <span id='Ext-data-NodeInterface-event-append'> /**
- </span> * @event append
- * Fires when a new child node is appended
- * @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 {Ext.data.NodeInterface} this This node
- * @param {Ext.data.NodeInterface} node The removed node
- * @param {Boolean} isMove `true` if the child node is being removed so it can be moved to another position in the tree.
- * (a side effect of calling {@link Ext.data.NodeInterface#appendChild appendChild} or
- * {@link Ext.data.NodeInterface#insertBefore insertBefore} with a node that already has a parentNode)
- */
- "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 {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 {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 {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 {Ext.data.NodeInterface} this This node
- * @param {Ext.data.NodeInterface} node The child node to be removed
- * @param {Boolean} isMove `true` if the child node is being removed so it can be moved to another position in the tree.
- * (a side effect of calling {@link Ext.data.NodeInterface#appendChild appendChild} or
- * {@link Ext.data.NodeInterface#insertBefore insertBefore} with a node that already has a parentNode)
- */
- "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 {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 {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 {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 {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 {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 {Ext.data.NodeInterface} this The collapsing node
- */
- "beforecollapse",
- <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 me;
- },
- <span id='Ext-data-NodeInterface-method-createNode'> /**
- </span> * Ensures that the passed object is an instance of a Record with the NodeInterface applied
- * @return {Ext.data.NodeInterface}
- */
- createNode: function(node) {
- if (Ext.isObject(node) && !node.isModel) {
- node = Ext.ModelManager.create(node, this.modelName);
- }
- // The node may already decorated, but may not have been
- // so when the model constructor was called. If not,
- // setup defaults here
- if (!node.childNodes) {
- Ext.applyIf(node, {
- firstChild: null,
- lastChild: null,
- parentNode: null,
- previousSibling: null,
- nextSibling: null,
- childNodes: []
- });
- }
- return node;
- },
- <span id='Ext-data-NodeInterface-method-isLeaf'> /**
- </span> * Returns true if this node is a leaf
- * @return {Boolean}
- */
- isLeaf : function() {
- return this.get('leaf') === true;
- },
- <span id='Ext-data-NodeInterface-method-setFirstChild'> /**
- </span> * Sets the first child of this node
- * @private
- * @param {Ext.data.NodeInterface} node
- */
- setFirstChild : function(node) {
- this.firstChild = node;
- },
- <span id='Ext-data-NodeInterface-method-setLastChild'> /**
- </span> * Sets the last child of this node
- * @private
- * @param {Ext.data.NodeInterface} node
- */
- setLastChild : function(node) {
- this.lastChild = node;
- },
- <span id='Ext-data-NodeInterface-method-updateInfo'> /**
- </span> * Updates general data of this node like isFirst, isLast, depth. This
- * method is internally called after a node is moved. This shouldn't
- * have to be called by the developer unless they are creating custom
- * Tree plugins.
- * @return {Boolean}
- */
- updateInfo: function(commit) {
- var me = this,
- isRoot = me.isRoot(),
- parentNode = me.parentNode,
- isFirst = (!parentNode || isRoot ? true : parentNode.firstChild === me),
- isLast = (!parentNode || isRoot ? true : parentNode.lastChild === me),
- depth = 0,
- parent = me,
- children = me.childNodes,
- len = children.length,
- i = 0,
- phantom = me.phantom;
- while (parent.parentNode) {
- ++depth;
- parent = parent.parentNode;
- }
- me.beginEdit();
- me.set({
- isFirst: isFirst,
- isLast: isLast,
- depth: depth,
- index: parentNode ? parentNode.indexOf(me) : 0,
- parentId: parentNode ? parentNode.getId() : null
- });
- me.endEdit(true);
- if (commit) {
- me.commit();
- me.phantom = phantom;
- }
- for (i = 0; i < len; i++) {
- children[i].updateInfo(commit);
- }
- },
- <span id='Ext-data-NodeInterface-method-isLast'> /**
- </span> * Returns true if this node is the last child of its parent
- * @return {Boolean}
- */
- isLast : function() {
- return this.get('isLast');
- },
- <span id='Ext-data-NodeInterface-method-isFirst'> /**
- </span> * Returns true if this node is the first child of its parent
- * @return {Boolean}
- */
- isFirst : function() {
- return this.get('isFirst');
- },
- <span id='Ext-data-NodeInterface-method-hasChildNodes'> /**
- </span> * Returns true if this node has one or more child nodes, else false.
- * @return {Boolean}
- */
- hasChildNodes : function() {
- return !this.isLeaf() && this.childNodes.length > 0;
- },
- <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, otherwise returns false.
- * @return {Boolean}
- */
- isExpandable : function() {
- var me = this;
- if (me.get('expandable')) {
- return !(me.isLeaf() || (me.isLoaded() && !me.hasChildNodes()));
- }
- return false;
- },
-
- triggerUIUpdate: function(){
- // This isn't ideal, however none of the underlying fields have changed
- // but we still need to update the UI
- this.afterEdit([]);
- },
- <span id='Ext-data-NodeInterface-method-appendChild'> /**
- </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, commit) {
- var me = this,
- i, ln,
- index,
- oldParent,
- ps;
- // if passed an array do them one by one
- if (Ext.isArray(node)) {
- // suspend auto syncing while we append all the nodes
- me.callStore('suspendAutoSync');
- for (i = 0, ln = node.length - 1; i < ln; i++) {
- me.appendChild(node[i]);
- }
- // resume auto syncing before we append the last node
- me.callStore('resumeAutoSync');
- me.appendChild(node[ln]);
- } else {
- // Make sure it is a record
- node = me.createNode(node);
- if (suppressEvents !== true && (!me.hasListeners.beforeappend || me.fireEvent("beforeappend", me, node) === false)) {
- return false;
- }
- index = me.childNodes.length;
- oldParent = node.parentNode;
- // it's a move, make sure we move it cleanly
- if (oldParent) {
- if (suppressEvents !== true && (!me.hasListeners.beforeremove || node.fireEvent("beforemove", node, oldParent, me, index) === false)) {
- return false;
- }
- oldParent.removeChild(node, false, false, true);
- }
- index = me.childNodes.length;
- if (index === 0) {
- me.setFirstChild(node);
- }
- me.childNodes.push(node);
- node.parentNode = me;
- node.nextSibling = null;
- me.setLastChild(node);
- ps = me.childNodes[index - 1];
- if (ps) {
- node.previousSibling = ps;
- ps.nextSibling = node;
- ps.updateInfo(commit);
- } else {
- node.previousSibling = null;
- }
- node.updateInfo(commit);
- // As soon as we append a child to this node, we are loaded
- if (!me.isLoaded()) {
- me.set('loaded', true);
- } else if (me.childNodes.length === 1) {
- me.triggerUIUpdate();
- }
- if(!node.isLeaf() && node.phantom) {
- node.set('loaded', true);
- }
- 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
- * @return {Object} The bubble target
- */
- getBubbleTarget: function() {
- return this.parentNode;
- },
- <span id='Ext-data-NodeInterface-method-removeChild'> /**
- </span> * Removes a child node from this 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, isMove) {
- var me = this,
- index = me.indexOf(node),
- i, childCount;
- if (index == -1 || (suppressEvents !== true && (!me.hasListeners.beforeremove || me.fireEvent("beforeremove", me, node, !!isMove) === false))) {
- return false;
- }
- // remove it from childNodes collection
- Ext.Array.erase(me.childNodes, index, 1);
- // update child refs
- if (me.firstChild == node) {
- me.setFirstChild(node.nextSibling);
- }
- if (me.lastChild == node) {
- me.setLastChild(node.previousSibling);
- }
- // update siblings
- if (node.previousSibling) {
- node.previousSibling.nextSibling = node.nextSibling;
- }
- if (node.nextSibling) {
- node.nextSibling.previousSibling = node.previousSibling;
- }
- // update the info for all siblings starting at the index before the node's old index (or 0 if the removed node was the firstChild)
- for(i = index > 0 ? index - 1 : 0, childCount = me.childNodes.length; i < childCount; i++) {
- me.childNodes[i].updateInfo();
- }
- // If this node suddenly doesnt have childnodes anymore, update myself
- if (!me.childNodes.length) {
- me.triggerUIUpdate();
- }
- if (suppressEvents !== true) {
- if (me.hasListeners.remove) {
- me.fireEvent("remove", me, node, !!isMove);
- }
- }
- if (destroy) {
- node.destroy(true);
- } else {
- node.clear();
- }
- return node;
- },
- <span id='Ext-data-NodeInterface-method-copy'> /**
- </span> * Creates a copy (clone) 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,
- result = me.callOverridden(arguments),
- len = me.childNodes ? me.childNodes.length : 0,
- i;
- // Move child nodes across to the copy if required
- if (deep) {
- for (i = 0; i < len; i++) {
- result.appendChild(me.childNodes[i].copy(true));
- }
- }
- return result;
- },
- <span id='Ext-data-NodeInterface-method-clear'> /**
- </span> * Clears the node.
- * @private
- * @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) {
- me.firstChild = me.lastChild = null;
- }
- },
- <span id='Ext-data-NodeInterface-method-destroy'> /**
- </span> * Destroys the node.
- */
- destroy : function(silent) {
- /*
- * Silent is to be used in a number of cases
- * 1) When setRoot is called.
- * 2) When destroy on the tree is called
- * 3) For destroying child nodes on a node
- */
- var me = this,
- options = me.destroyOptions,
- nodes = me.childNodes,
- nLen = nodes.length,
- n;
- if (silent === true) {
- me.clear(true);
- for (n = 0; n < nLen; n++) {
- nodes[n].destroy(true);
- }
- me.childNodes = null;
- delete me.destroyOptions;
- me.callOverridden([options]);
- } else {
- me.destroyOptions = silent;
- // overridden method will be called, since remove will end up calling destroy(true);
- me.remove(true);
- }
- },
- <span id='Ext-data-NodeInterface-method-insertBefore'> /**
- </span> * Inserts the first node before the second node in this nodes childNodes collection.
- * @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,
- index = me.indexOf(refNode),
- oldParent = node.parentNode,
- refIndex = index,
- childCount, ps, i;
- 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.hasListeners.beforeinsert || 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--;
- }
- // it's a move, make sure we move it cleanly
- if (oldParent) {
- if (suppressEvents !== true && (!me.hasListeners.beforeremove || node.fireEvent("beforemove", node, oldParent, me, index, refNode) === false)) {
- return false;
- }
- oldParent.removeChild(node, false, false, true);
- }
- if (refIndex === 0) {
- me.setFirstChild(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;
- ps.nextSibling = node;
- } else {
- node.previousSibling = null;
- }
- // update the info for all siblings starting at the index before the node's insertion point (or 0 if the inserted node is the firstChild)
- for(i = refIndex > 0 ? refIndex - 1 : 0, childCount = me.childNodes.length; i < childCount; i++) {
- me.childNodes[i].updateInfo();
- }
- if (!me.isLoaded()) {
- me.set('loaded', true);
- }
- // If this node didnt have any childnodes before, update myself
- else if (me.childNodes.length === 1) {
- me.triggerUIUpdate();
- }
- if(!node.isLeaf() && node.phantom) {
- node.set('loaded', true);
- }
- if (suppressEvents !== true) {
- if (me.hasListeners.insert) {
- me.fireEvent("insert", me, node, refNode);
- }
- if (oldParent && me.hasListeners.move) {
- node.fireEvent("move", node, oldParent, me, refIndex, refNode);
- }
- }
- return node;
- },
- <span id='Ext-data-NodeInterface-method-insertChild'> /**
- </span> * Inserts a node into this node.
- * @param {Number} index The zero-based index to insert the node at
- * @param {Ext.data.NodeInterface} node The node to insert
- * @return {Ext.data.NodeInterface} The node you just inserted
- */
- insertChild: function(index, node) {
- var sibling = this.childNodes[index];
- if (sibling) {
- return this.insertBefore(node, sibling);
- }
- else {
- return this.appendChild(node);
- }
- },
- <span id='Ext-data-NodeInterface-method-remove'> /**
- </span> * Removes this node from its parent
- * @param {Boolean} [destroy=false] True to destroy the node upon removal.
- * @return {Ext.data.NodeInterface} this
- */
- remove : function(destroy, suppressEvents) {
- var parentNode = this.parentNode;
- if (parentNode) {
- parentNode.removeChild(this, destroy, suppressEvents);
- }
- return this;
- },
- <span id='Ext-data-NodeInterface-method-removeAll'> /**
- </span> * Removes all child nodes from this node.
- * @param {Boolean} [destroy=false] <True to destroy the node upon removal.
- * @return {Ext.data.NodeInterface} this
- */
- removeAll : function(destroy, suppressEvents) {
- var cn = this.childNodes,
- n;
- while ((n = cn[0])) {
- this.removeChild(n, destroy, suppressEvents);
- }
- return this;
- },
- <span id='Ext-data-NodeInterface-method-getChildAt'> /**
- </span> * Returns the child node at the specified index.
- * @param {Number} index
- * @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 {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, false, suppressEvents);
- this.insertBefore(newChild, s, suppressEvents);
- return oldChild;
- },
- <span id='Ext-data-NodeInterface-method-indexOf'> /**
- </span> * Returns the index of a child 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-indexOfId'> /**
- </span> * Returns the index of a child node that matches the id
- * @param {String} id The id of the node to find
- * @return {Number} The index of the node or -1 if it was not found
- */
- indexOfId: function(id) {
- var childNodes = this.childNodes,
- len = childNodes.length,
- i = 0;
-
- for (; i < len; ++i) {
- if (childNodes[i].getId() === id) {
- return i;
- }
- }
- return -1;
- },
- <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}
- */
- getDepth : function() {
- return this.get('depth');
- },
- <span id='Ext-data-NodeInterface-method-bubble'> /**
- </span> * Bubbles up the tree from this node, calling the specified function with each node. The arguments to the function
- * 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] 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;
- while (p) {
- if (fn.apply(scope || p, args || [p]) === false) {
- break;
- }
- p = p.parentNode;
- }
- },
- //<deprecated since=0.99>
- cascade: function() {
- if (Ext.isDefined(Ext.global.console)) {
- Ext.global.console.warn('Ext.data.Node: cascade has been deprecated. Please use cascadeBy instead.');
- }
- return this.cascadeBy.apply(this, arguments);
- },
- //</deprecated>
- <span id='Ext-data-NodeInterface-method-cascadeBy'> /**
- </span> * Cascades down the tree from this node, calling the specified function with each node. The arguments to the function
- * 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] 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) {
- var childNodes = this.childNodes,
- length = childNodes.length,
- i;
- for (i = 0; i < length; i++) {
- childNodes[i].cascadeBy(fn, scope, args);
- }
- }
- },
- <span id='Ext-data-NodeInterface-method-eachChild'> /**
- </span> * Interates the child nodes of this node, calling the specified function with each node. The arguments to the function
- * 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] 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,
- length = childNodes.length,
- i;
- for (i = 0; i < length; i++) {
- if (fn.apply(scope || this, args || [childNodes[i]]) === false) {
- break;
- }
- }
- },
- <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 {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() {
- return this.get(attribute) == value;
- }, null, deep);
- },
- <span id='Ext-data-NodeInterface-method-findChildBy'> /**
- </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,
- len = cs.length,
- i = 0, n, res;
- for (; i < len; i++) {
- n = cs[i];
- if (fn.call(scope || n, n) === true) {
- return n;
- }
- else if (deep) {
- res = n.findChildBy(fn, scope, deep);
- if (res !== null) {
- return res;
- }
- }
- }
- return null;
- },
- <span id='Ext-data-NodeInterface-method-contains'> /**
- </span> * Returns true if this node is an ancestor (at any point) of the passed node.
- * @param {Ext.data.NodeInterface} node
- * @return {Boolean}
- */
- contains : function(node) {
- return node.isAncestor(this);
- },
- <span id='Ext-data-NodeInterface-method-isAncestor'> /**
- </span> * Returns true if the passed node is an ancestor (at any point) of this node.
- * @param {Ext.data.NodeInterface} node
- * @return {Boolean}
- */
- isAncestor : function(node) {
- var p = this.parentNode;
- while (p) {
- if (p == node) {
- return true;
- }
- p = p.parentNode;
- }
- return false;
- },
- <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=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);
- }
- if (i == ln - 1) {
- this.setLastChild(n);
- }
- n.updateInfo();
- if (recursive && !n.isLeaf()) {
- 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) {
- if (!parent.isExpanded()) {
- return false;
- }
- parent = parent.parentNode;
- }
- return true;
- },
- <span id='Ext-data-NodeInterface-method-expand'> /**
- </span> * Expand this node.
- * @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;
- // all paths must call the callback (eventually) or things like
- // selectPath fail
- // First we start by checking if this node is a parent
- if (!me.isLeaf()) {
- // 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);
- if (me.hasListeners.expand) {
- 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]);
- }
- }
- } 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 {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,
- i = 0,
- nodes = me.childNodes,
- ln = nodes.length,
- node,
- expanding = 0;
- for (; i < ln; ++i) {
- node = nodes[i];
- if (!node.isLeaf()) {
- expanding++;
- nodes[i].expand(recursive, function () {
- expanding--;
- if (callback && !expanding) {
- 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 {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;
- // First we start by checking if this node is a parent
- if (!me.isLeaf()) {
- // Now we check if this record is already collapsing or collapsed
- if (!me.collapsing && me.isExpanded()) {
- me.fireEvent('beforecollapse', me, function() {
- me.set('expanded', false);
- if (me.hasListeners.collapse) {
- me.fireEvent('collapse', me, me.childNodes, false);
- }
- // 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]);
- }
- }, me);
- }
- // If it is is already collapsed but we want to recursively collapse then call collapseChildren
- else if (recursive) {
- me.collapseChildren(true, callback, scope);
- } else {
- Ext.callback(callback, scope || me, [me.childNodes]);
- }
- }
- // If it's not then we fire the callback right away
- else {
- 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=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,
- i = 0,
- nodes = me.childNodes,
- ln = nodes.length,
- node,
- collapsing = 0;
- for (; i < ln; ++i) {
- node = nodes[i];
- if (!node.isLeaf()) {
- collapsing++;
- nodes[i].collapse(recursive, function () {
- collapsing--;
- if (callback && !collapsing) {
- Ext.callback(callback, scope || me, [me.childNodes]);
- }
- });
- }
- }
- if (!collapsing && callback) {
- Ext.callback(callback, scope || me, [me.childNodes]);
- }
- }
- };
- }
- }
- });
- </pre>
- </body>
- </html>
|