Panel4.html 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-tree-Panel'>/**
  19. </span> * The TreePanel provides tree-structured UI representation of tree-structured data.
  20. * A TreePanel must be bound to a {@link Ext.data.TreeStore}. TreePanel's support
  21. * multiple columns through the {@link #columns} configuration.
  22. *
  23. * Simple TreePanel using inline data:
  24. *
  25. * @example
  26. * var store = Ext.create('Ext.data.TreeStore', {
  27. * root: {
  28. * expanded: true,
  29. * children: [
  30. * { text: &quot;detention&quot;, leaf: true },
  31. * { text: &quot;homework&quot;, expanded: true, children: [
  32. * { text: &quot;book report&quot;, leaf: true },
  33. * { text: &quot;alegrbra&quot;, leaf: true}
  34. * ] },
  35. * { text: &quot;buy lottery tickets&quot;, leaf: true }
  36. * ]
  37. * }
  38. * });
  39. *
  40. * Ext.create('Ext.tree.Panel', {
  41. * title: 'Simple Tree',
  42. * width: 200,
  43. * height: 150,
  44. * store: store,
  45. * rootVisible: false,
  46. * renderTo: Ext.getBody()
  47. * });
  48. *
  49. * For the tree node config options (like `text`, `leaf`, `expanded`), see the documentation of
  50. * {@link Ext.data.NodeInterface NodeInterface} config options.
  51. */
  52. Ext.define('Ext.tree.Panel', {
  53. extend: 'Ext.panel.Table',
  54. alias: 'widget.treepanel',
  55. alternateClassName: ['Ext.tree.TreePanel', 'Ext.TreePanel'],
  56. requires: ['Ext.tree.View', 'Ext.selection.TreeModel', 'Ext.tree.Column', 'Ext.data.TreeStore'],
  57. viewType: 'treeview',
  58. selType: 'treemodel',
  59. treeCls: Ext.baseCSSPrefix + 'tree-panel',
  60. deferRowRender: false,
  61. <span id='Ext-tree-Panel-cfg-rowLines'> /**
  62. </span> * @cfg {Boolean} rowLines
  63. * False so that rows are not separated by lines.
  64. */
  65. rowLines: false,
  66. <span id='Ext-tree-Panel-cfg-lines'> /**
  67. </span> * @cfg {Boolean} lines
  68. * False to disable tree lines.
  69. */
  70. lines: true,
  71. <span id='Ext-tree-Panel-cfg-useArrows'> /**
  72. </span> * @cfg {Boolean} useArrows
  73. * True to use Vista-style arrows in the tree.
  74. */
  75. useArrows: false,
  76. <span id='Ext-tree-Panel-cfg-singleExpand'> /**
  77. </span> * @cfg {Boolean} singleExpand
  78. * True if only 1 node per branch may be expanded.
  79. */
  80. singleExpand: false,
  81. ddConfig: {
  82. enableDrag: true,
  83. enableDrop: true
  84. },
  85. <span id='Ext-tree-Panel-cfg-animate'> /**
  86. </span> * @cfg {Boolean} animate
  87. * True to enable animated expand/collapse. Defaults to the value of {@link Ext#enableFx}.
  88. */
  89. <span id='Ext-tree-Panel-cfg-rootVisible'> /**
  90. </span> * @cfg {Boolean} rootVisible
  91. * False to hide the root node.
  92. */
  93. rootVisible: true,
  94. <span id='Ext-tree-Panel-cfg-displayField'> /**
  95. </span> * @cfg {String} displayField
  96. * The field inside the model that will be used as the node's text.
  97. */
  98. displayField: 'text',
  99. <span id='Ext-tree-Panel-cfg-root'> /**
  100. </span> * @cfg {Ext.data.Model/Ext.data.NodeInterface/Object} root
  101. * Allows you to not specify a store on this TreePanel. This is useful for creating a simple tree with preloaded
  102. * data without having to specify a TreeStore and Model. A store and model will be created and root will be passed
  103. * to that store. For example:
  104. *
  105. * Ext.create('Ext.tree.Panel', {
  106. * title: 'Simple Tree',
  107. * root: {
  108. * text: &quot;Root node&quot;,
  109. * expanded: true,
  110. * children: [
  111. * { text: &quot;Child 1&quot;, leaf: true },
  112. * { text: &quot;Child 2&quot;, leaf: true }
  113. * ]
  114. * },
  115. * renderTo: Ext.getBody()
  116. * });
  117. */
  118. root: null,
  119. // Required for the Lockable Mixin. These are the configurations which will be copied to the
  120. // normal and locked sub tablepanels
  121. normalCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible', 'scroll'],
  122. lockedCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible'],
  123. isTree: true,
  124. <span id='Ext-tree-Panel-cfg-hideHeaders'> /**
  125. </span> * @cfg {Boolean} hideHeaders
  126. * True to hide the headers.
  127. */
  128. <span id='Ext-tree-Panel-cfg-folderSort'> /**
  129. </span> * @cfg {Boolean} folderSort
  130. * True to automatically prepend a leaf sorter to the store.
  131. */
  132. <span id='Ext-tree-Panel-cfg-store'> /**
  133. </span> * @cfg {Ext.data.TreeStore} store (required)
  134. * The {@link Ext.data.TreeStore Store} the tree should use as its data source.
  135. */
  136. constructor: function(config) {
  137. config = config || {};
  138. if (config.animate === undefined) {
  139. config.animate = Ext.isDefined(this.animate) ? this.animate : Ext.enableFx;
  140. }
  141. this.enableAnimations = config.animate;
  142. delete config.animate;
  143. this.callParent([config]);
  144. },
  145. initComponent: function() {
  146. var me = this,
  147. cls = [me.treeCls],
  148. view;
  149. if (me.useArrows) {
  150. cls.push(Ext.baseCSSPrefix + 'tree-arrows');
  151. me.lines = false;
  152. }
  153. if (me.lines) {
  154. cls.push(Ext.baseCSSPrefix + 'tree-lines');
  155. } else if (!me.useArrows) {
  156. cls.push(Ext.baseCSSPrefix + 'tree-no-lines');
  157. }
  158. if (Ext.isString(me.store)) {
  159. me.store = Ext.StoreMgr.lookup(me.store);
  160. } else if (!me.store || Ext.isObject(me.store) &amp;&amp; !me.store.isStore) {
  161. me.store = new Ext.data.TreeStore(Ext.apply({}, me.store || {}, {
  162. root: me.root,
  163. fields: me.fields,
  164. model: me.model,
  165. folderSort: me.folderSort
  166. }));
  167. } else if (me.root) {
  168. me.store = Ext.data.StoreManager.lookup(me.store);
  169. me.store.setRootNode(me.root);
  170. if (me.folderSort !== undefined) {
  171. me.store.folderSort = me.folderSort;
  172. me.store.sort();
  173. }
  174. }
  175. // I'm not sure if we want to this. It might be confusing
  176. // if (me.initialConfig.rootVisible === undefined &amp;&amp; !me.getRootNode()) {
  177. // me.rootVisible = false;
  178. // }
  179. me.viewConfig = Ext.apply({}, me.viewConfig);
  180. me.viewConfig = Ext.applyIf(me.viewConfig, {
  181. rootVisible: me.rootVisible,
  182. animate: me.enableAnimations,
  183. singleExpand: me.singleExpand,
  184. node: me.store.getRootNode(),
  185. hideHeaders: me.hideHeaders
  186. });
  187. me.mon(me.store, {
  188. scope: me,
  189. rootchange: me.onRootChange,
  190. clear: me.onClear
  191. });
  192. me.relayEvents(me.store, [
  193. <span id='Ext-tree-Panel-event-beforeload'> /**
  194. </span> * @event beforeload
  195. * @inheritdoc Ext.data.TreeStore#beforeload
  196. */
  197. 'beforeload',
  198. <span id='Ext-tree-Panel-event-load'> /**
  199. </span> * @event load
  200. * @inheritdoc Ext.data.TreeStore#load
  201. */
  202. 'load'
  203. ]);
  204. me.mon(me.store, {
  205. <span id='Ext-tree-Panel-event-itemappend'> /**
  206. </span> * @event itemappend
  207. * @inheritdoc Ext.data.TreeStore#append
  208. */
  209. append: me.createRelayer('itemappend'),
  210. <span id='Ext-tree-Panel-event-itemremove'> /**
  211. </span> * @event itemremove
  212. * @inheritdoc Ext.data.TreeStore#remove
  213. */
  214. remove: me.createRelayer('itemremove'),
  215. <span id='Ext-tree-Panel-event-itemmove'> /**
  216. </span> * @event itemmove
  217. * @inheritdoc Ext.data.TreeStore#move
  218. */
  219. move: me.createRelayer('itemmove', [0, 4]),
  220. <span id='Ext-tree-Panel-event-iteminsert'> /**
  221. </span> * @event iteminsert
  222. * @inheritdoc Ext.data.TreeStore#insert
  223. */
  224. insert: me.createRelayer('iteminsert'),
  225. <span id='Ext-tree-Panel-event-beforeitemappend'> /**
  226. </span> * @event beforeitemappend
  227. * @inheritdoc Ext.data.TreeStore#beforeappend
  228. */
  229. beforeappend: me.createRelayer('beforeitemappend'),
  230. <span id='Ext-tree-Panel-event-beforeitemremove'> /**
  231. </span> * @event beforeitemremove
  232. * @inheritdoc Ext.data.TreeStore#beforeremove
  233. */
  234. beforeremove: me.createRelayer('beforeitemremove'),
  235. <span id='Ext-tree-Panel-event-beforeitemmove'> /**
  236. </span> * @event beforeitemmove
  237. * @inheritdoc Ext.data.TreeStore#beforemove
  238. */
  239. beforemove: me.createRelayer('beforeitemmove'),
  240. <span id='Ext-tree-Panel-event-beforeiteminsert'> /**
  241. </span> * @event beforeiteminsert
  242. * @inheritdoc Ext.data.TreeStore#beforeinsert
  243. */
  244. beforeinsert: me.createRelayer('beforeiteminsert'),
  245. <span id='Ext-tree-Panel-event-itemexpand'> /**
  246. </span> * @event itemexpand
  247. * @inheritdoc Ext.data.TreeStore#expand
  248. */
  249. expand: me.createRelayer('itemexpand', [0, 1]),
  250. <span id='Ext-tree-Panel-event-itemcollapse'> /**
  251. </span> * @event itemcollapse
  252. * @inheritdoc Ext.data.TreeStore#collapse
  253. */
  254. collapse: me.createRelayer('itemcollapse', [0, 1]),
  255. <span id='Ext-tree-Panel-event-beforeitemexpand'> /**
  256. </span> * @event beforeitemexpand
  257. * @inheritdoc Ext.data.TreeStore#beforeexpand
  258. */
  259. beforeexpand: me.createRelayer('beforeitemexpand', [0, 1]),
  260. <span id='Ext-tree-Panel-event-beforeitemcollapse'> /**
  261. </span> * @event beforeitemcollapse
  262. * @inheritdoc Ext.data.TreeStore#beforecollapse
  263. */
  264. beforecollapse: me.createRelayer('beforeitemcollapse', [0, 1])
  265. });
  266. // If the user specifies the headers collection manually then dont inject our own
  267. if (!me.columns) {
  268. if (me.initialConfig.hideHeaders === undefined) {
  269. me.hideHeaders = true;
  270. }
  271. me.addCls(Ext.baseCSSPrefix + 'autowidth-table');
  272. me.columns = [{
  273. xtype : 'treecolumn',
  274. text : 'Name',
  275. width : Ext.isIE6 ? null : 10000,
  276. dataIndex: me.displayField
  277. }];
  278. }
  279. if (me.cls) {
  280. cls.push(me.cls);
  281. }
  282. me.cls = cls.join(' ');
  283. me.callParent();
  284. view = me.getView();
  285. me.relayEvents(view, [
  286. <span id='Ext-tree-Panel-event-checkchange'> /**
  287. </span> * @event checkchange
  288. * Fires when a node with a checkbox's checked property changes
  289. * @param {Ext.data.NodeInterface} node The node who's checked property was changed
  290. * @param {Boolean} checked The node's new checked state
  291. */
  292. 'checkchange',
  293. <span id='Ext-tree-Panel-event-afteritemexpand'> /**
  294. </span> * @event afteritemexpand
  295. * @inheritdoc Ext.tree.View#afteritemexpand
  296. */
  297. 'afteritemexpand',
  298. <span id='Ext-tree-Panel-event-afteritemcollapse'> /**
  299. </span> * @event afteritemcollapse
  300. * @inheritdoc Ext.tree.View#afteritemcollapse
  301. */
  302. 'afteritemcollapse'
  303. ]);
  304. // If the root is not visible and there is no rootnode defined, then just lets load the store
  305. if (!view.rootVisible &amp;&amp; !me.getRootNode()) {
  306. me.setRootNode({
  307. expanded: true
  308. });
  309. }
  310. },
  311. onClear: function(){
  312. this.view.onClear();
  313. },
  314. <span id='Ext-tree-Panel-method-setRootNode'> /**
  315. </span> * Sets root node of this tree.
  316. * @param {Ext.data.Model/Ext.data.NodeInterface/Object} root
  317. * @return {Ext.data.NodeInterface} The new root
  318. */
  319. setRootNode: function() {
  320. return this.store.setRootNode.apply(this.store, arguments);
  321. },
  322. <span id='Ext-tree-Panel-method-getRootNode'> /**
  323. </span> * Returns the root node for this tree.
  324. * @return {Ext.data.NodeInterface}
  325. */
  326. getRootNode: function() {
  327. return this.store.getRootNode();
  328. },
  329. onRootChange: function(root) {
  330. this.view.setRootNode(root);
  331. },
  332. <span id='Ext-tree-Panel-method-getChecked'> /**
  333. </span> * Retrieve an array of checked records.
  334. * @return {Ext.data.NodeInterface[]} An array containing the checked records
  335. */
  336. getChecked: function() {
  337. return this.getView().getChecked();
  338. },
  339. isItemChecked: function(rec) {
  340. return rec.get('checked');
  341. },
  342. <span id='Ext-tree-Panel-method-expandNode'> /**
  343. </span> * Expands a record that is loaded in the tree.
  344. * @param {Ext.data.Model} record The record to expand
  345. * @param {Boolean} [deep] True to expand nodes all the way down the tree hierarchy.
  346. * @param {Function} [callback] The function to run after the expand is completed
  347. * @param {Object} [scope] The scope of the callback function.
  348. */
  349. expandNode: function(record, deep, callback, scope) {
  350. return this.getView().expand(record, deep, callback, scope || this);
  351. },
  352. <span id='Ext-tree-Panel-method-collapseNode'> /**
  353. </span> * Collapses a record that is loaded in the tree.
  354. * @param {Ext.data.Model} record The record to collapse
  355. * @param {Boolean} [deep] True to collapse nodes all the way up the tree hierarchy.
  356. * @param {Function} [callback] The function to run after the collapse is completed
  357. * @param {Object} [scope] The scope of the callback function.
  358. */
  359. collapseNode: function(record, deep, callback, scope) {
  360. return this.getView().collapse(record, deep, callback, scope || this);
  361. },
  362. <span id='Ext-tree-Panel-method-expandAll'> /**
  363. </span> * Expand all nodes
  364. * @param {Function} [callback] A function to execute when the expand finishes.
  365. * @param {Object} [scope] The scope of the callback function
  366. */
  367. expandAll : function(callback, scope) {
  368. var me = this,
  369. root = me.getRootNode(),
  370. animate = me.enableAnimations,
  371. view = me.getView();
  372. if (root) {
  373. if (!animate) {
  374. view.beginBulkUpdate();
  375. }
  376. root.expand(true, callback, scope || me);
  377. if (!animate) {
  378. view.endBulkUpdate();
  379. }
  380. }
  381. },
  382. <span id='Ext-tree-Panel-method-collapseAll'> /**
  383. </span> * Collapse all nodes
  384. * @param {Function} [callback] A function to execute when the collapse finishes.
  385. * @param {Object} [scope] The scope of the callback function
  386. */
  387. collapseAll : function(callback, scope) {
  388. var me = this,
  389. root = me.getRootNode(),
  390. animate = me.enableAnimations,
  391. view = me.getView();
  392. if (root) {
  393. if (!animate) {
  394. view.beginBulkUpdate();
  395. }
  396. scope = scope || me;
  397. if (view.rootVisible) {
  398. root.collapse(true, callback, scope);
  399. } else {
  400. root.collapseChildren(true, callback, scope);
  401. }
  402. if (!animate) {
  403. view.endBulkUpdate();
  404. }
  405. }
  406. },
  407. <span id='Ext-tree-Panel-method-expandPath'> /**
  408. </span> * Expand the tree to the path of a particular node.
  409. * @param {String} path The path to expand. The path should include a leading separator.
  410. * @param {String} [field] The field to get the data from. Defaults to the model idProperty.
  411. * @param {String} [separator='/'] A separator to use.
  412. * @param {Function} [callback] A function to execute when the expand finishes. The callback will be called with
  413. * (success, lastNode) where success is if the expand was successful and lastNode is the last node that was expanded.
  414. * @param {Object} [scope] The scope of the callback function
  415. */
  416. expandPath: function(path, field, separator, callback, scope) {
  417. var me = this,
  418. current = me.getRootNode(),
  419. index = 1,
  420. view = me.getView(),
  421. keys,
  422. expander;
  423. field = field || me.getRootNode().idProperty;
  424. separator = separator || '/';
  425. if (Ext.isEmpty(path)) {
  426. Ext.callback(callback, scope || me, [false, null]);
  427. return;
  428. }
  429. keys = path.split(separator);
  430. if (current.get(field) != keys[1]) {
  431. // invalid root
  432. Ext.callback(callback, scope || me, [false, current]);
  433. return;
  434. }
  435. expander = function(){
  436. if (++index === keys.length) {
  437. Ext.callback(callback, scope || me, [true, current]);
  438. return;
  439. }
  440. var node = current.findChild(field, keys[index]);
  441. if (!node) {
  442. Ext.callback(callback, scope || me, [false, current]);
  443. return;
  444. }
  445. current = node;
  446. current.expand(false, expander);
  447. };
  448. current.expand(false, expander);
  449. },
  450. <span id='Ext-tree-Panel-method-selectPath'> /**
  451. </span> * Expand the tree to the path of a particular node, then select it.
  452. * @param {String} path The path to select. The path should include a leading separator.
  453. * @param {String} [field] The field to get the data from. Defaults to the model idProperty.
  454. * @param {String} [separator='/'] A separator to use.
  455. * @param {Function} [callback] A function to execute when the select finishes. The callback will be called with
  456. * (bSuccess, oLastNode) where bSuccess is if the select was successful and oLastNode is the last node that was expanded.
  457. * @param {Object} [scope] The scope of the callback function
  458. */
  459. selectPath: function(path, field, separator, callback, scope) {
  460. var me = this,
  461. root,
  462. keys,
  463. last;
  464. field = field || me.getRootNode().idProperty;
  465. separator = separator || '/';
  466. keys = path.split(separator);
  467. last = keys.pop();
  468. if (keys.length &gt; 1) {
  469. me.expandPath(keys.join(separator), field, separator, function(success, node){
  470. var lastNode = node;
  471. if (success &amp;&amp; node) {
  472. node = node.findChild(field, last);
  473. if (node) {
  474. me.getSelectionModel().select(node);
  475. Ext.callback(callback, scope || me, [true, node]);
  476. return;
  477. }
  478. }
  479. Ext.callback(callback, scope || me, [false, lastNode]);
  480. }, me);
  481. } else {
  482. root = me.getRootNode();
  483. if (root.getId() === last) {
  484. me.getSelectionModel().select(root);
  485. Ext.callback(callback, scope || me, [true, root]);
  486. } else {
  487. Ext.callback(callback, scope || me, [false, null]);
  488. }
  489. }
  490. }
  491. });
  492. </pre>
  493. </body>
  494. </html>