/ext-4.1.0_b3/src/data/Tree.js

https://bitbucket.org/srogerf/javascript · JavaScript · 290 lines · 105 code · 39 blank · 146 comment · 9 complexity · e425521e463b8a73ef42830015f7428f MD5 · raw file

  1. /**
  2. * @class Ext.data.Tree
  3. *
  4. * This class is used as a container for a series of nodes. The nodes themselves maintain
  5. * the relationship between parent/child. The tree itself acts as a manager. It gives functionality
  6. * to retrieve a node by its identifier: {@link #getNodeById}.
  7. *
  8. * The tree also relays events from any of it's child nodes, allowing them to be handled in a
  9. * centralized fashion. In general this class is not used directly, rather used internally
  10. * by other parts of the framework.
  11. *
  12. */
  13. Ext.define('Ext.data.Tree', {
  14. alias: 'data.tree',
  15. mixins: {
  16. observable: "Ext.util.Observable"
  17. },
  18. /**
  19. * @property {Ext.data.NodeInterface}
  20. * The root node for this tree
  21. */
  22. root: null,
  23. /**
  24. * Creates new Tree object.
  25. * @param {Ext.data.NodeInterface} root (optional) The root node
  26. */
  27. constructor: function(root) {
  28. var me = this;
  29. me.mixins.observable.constructor.call(me);
  30. if (root) {
  31. me.setRootNode(root);
  32. }
  33. },
  34. /**
  35. * Returns the root node for this tree.
  36. * @return {Ext.data.NodeInterface}
  37. */
  38. getRootNode : function() {
  39. return this.root;
  40. },
  41. /**
  42. * Sets the root node for this tree.
  43. * @param {Ext.data.NodeInterface} node
  44. * @return {Ext.data.NodeInterface} The root node
  45. */
  46. setRootNode : function(node) {
  47. var me = this;
  48. me.root = node;
  49. if (me.fireEvent('beforeappend', null, node) !== false) {
  50. node.set('root', true);
  51. node.updateInfo();
  52. // root node should never be phantom or dirty, so commit it
  53. node.commit();
  54. node.on({
  55. scope: me,
  56. insert: me.onNodeInsert,
  57. append: me.onNodeAppend,
  58. remove: me.onNodeRemove
  59. });
  60. me.relayEvents(node, [
  61. /**
  62. * @event append
  63. * @inheritdoc Ext.data.NodeInterface#append
  64. */
  65. "append",
  66. /**
  67. * @event remove
  68. * @inheritdoc Ext.data.NodeInterface#remove
  69. */
  70. "remove",
  71. /**
  72. * @event move
  73. * @inheritdoc Ext.data.NodeInterface#move
  74. */
  75. "move",
  76. /**
  77. * @event insert
  78. * @inheritdoc Ext.data.NodeInterface#insert
  79. */
  80. "insert",
  81. /**
  82. * @event beforeappend
  83. * @inheritdoc Ext.data.NodeInterface#beforeappend
  84. */
  85. "beforeappend",
  86. /**
  87. * @event beforeremove
  88. * @inheritdoc Ext.data.NodeInterface#beforeremove
  89. */
  90. "beforeremove",
  91. /**
  92. * @event beforemove
  93. * @inheritdoc Ext.data.NodeInterface#beforemove
  94. */
  95. "beforemove",
  96. /**
  97. * @event beforeinsert
  98. * @inheritdoc Ext.data.NodeInterface#beforeinsert
  99. */
  100. "beforeinsert",
  101. /**
  102. * @event expand
  103. * @inheritdoc Ext.data.NodeInterface#expand
  104. */
  105. "expand",
  106. /**
  107. * @event collapse
  108. * @inheritdoc Ext.data.NodeInterface#collapse
  109. */
  110. "collapse",
  111. /**
  112. * @event beforeexpand
  113. * @inheritdoc Ext.data.NodeInterface#beforeexpand
  114. */
  115. "beforeexpand",
  116. /**
  117. * @event beforecollapse
  118. * @inheritdoc Ext.data.NodeInterface#beforecollapse
  119. */
  120. "beforecollapse" ,
  121. /**
  122. * @event sort
  123. * @inheritdoc Ext.data.NodeInterface#event-sort
  124. */
  125. "sort",
  126. /**
  127. * @event rootchange
  128. * Fires whenever the root node is changed in the tree.
  129. * @param {Ext.data.Model} root The new root
  130. */
  131. "rootchange"
  132. ]);
  133. me.nodeHash = {};
  134. me.registerNode(node);
  135. me.fireEvent('append', null, node);
  136. me.fireEvent('rootchange', node);
  137. }
  138. return node;
  139. },
  140. /**
  141. * Flattens all the nodes in the tree into an array.
  142. * @private
  143. * @return {Ext.data.NodeInterface[]} The flattened nodes.
  144. */
  145. flatten: function(){
  146. var nodes = [],
  147. hash = this.nodeHash,
  148. key;
  149. for (key in hash) {
  150. if (hash.hasOwnProperty(key)) {
  151. nodes.push(hash[key]);
  152. }
  153. }
  154. return nodes;
  155. },
  156. /**
  157. * Fired when a node is inserted into the root or one of it's children
  158. * @private
  159. * @param {Ext.data.NodeInterface} parent The parent node
  160. * @param {Ext.data.NodeInterface} node The inserted node
  161. */
  162. onNodeInsert: function(parent, node) {
  163. this.registerNode(node, true);
  164. },
  165. /**
  166. * Fired when a node is appended into the root or one of it's children
  167. * @private
  168. * @param {Ext.data.NodeInterface} parent The parent node
  169. * @param {Ext.data.NodeInterface} node The appended node
  170. */
  171. onNodeAppend: function(parent, node) {
  172. this.registerNode(node, true);
  173. },
  174. /**
  175. * Fired when a node is removed from the root or one of it's children
  176. * @private
  177. * @param {Ext.data.NodeInterface} parent The parent node
  178. * @param {Ext.data.NodeInterface} node The removed node
  179. */
  180. onNodeRemove: function(parent, node) {
  181. this.unregisterNode(node, true);
  182. },
  183. /**
  184. * Fired when a node's id changes. Updates the node's id in the node hash.
  185. * @private
  186. * @param {Ext.data.NodeInterface} node
  187. * @param {Number} oldId The old id
  188. * @param {Number} newId The new id
  189. */
  190. onNodeIdChanged: function(node, oldId, newId) {
  191. var nodeHash = this.nodeHash;
  192. nodeHash[newId] = node;
  193. delete nodeHash[oldId || node.internalId];
  194. },
  195. /**
  196. * Gets a node in this tree by its id.
  197. * @param {String} id
  198. * @return {Ext.data.NodeInterface} The match node.
  199. */
  200. getNodeById : function(id) {
  201. return this.nodeHash[id];
  202. },
  203. /**
  204. * Registers a node with the tree
  205. * @private
  206. * @param {Ext.data.NodeInterface} The node to register
  207. * @param {Boolean} [includeChildren] True to unregister any child nodes
  208. */
  209. registerNode : function(node, includeChildren) {
  210. var me = this;
  211. me.nodeHash[node.getId() || node.internalId] = node;
  212. node.on('idchanged', me.onNodeIdChanged, me);
  213. if (includeChildren === true) {
  214. node.eachChild(function(child){
  215. me.registerNode(child, true);
  216. });
  217. }
  218. },
  219. /**
  220. * Unregisters a node with the tree
  221. * @private
  222. * @param {Ext.data.NodeInterface} The node to unregister
  223. * @param {Boolean} [includeChildren] True to unregister any child nodes
  224. */
  225. unregisterNode : function(node, includeChildren) {
  226. delete this.nodeHash[node.getId() || node.internalId];
  227. if (includeChildren === true) {
  228. node.eachChild(function(child){
  229. this.unregisterNode(child, true);
  230. }, this);
  231. }
  232. },
  233. /**
  234. * Sorts this tree
  235. * @private
  236. * @param {Function} sorterFn The function to use for sorting
  237. * @param {Boolean} recursive True to perform recursive sorting
  238. */
  239. sort: function(sorterFn, recursive) {
  240. this.getRootNode().sort(sorterFn, recursive);
  241. },
  242. /**
  243. * Filters this tree
  244. * @private
  245. * @param {Function} sorterFn The function to use for filtering
  246. * @param {Boolean} recursive True to perform recursive filtering
  247. */
  248. filter: function(filters, recursive) {
  249. this.getRootNode().filter(filters, recursive);
  250. }
  251. });