3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.data.NodeStore
17 * @extends Ext.data.AbstractStore
21 Ext.define('Ext.data.NodeStore', {
22 extend: 'Ext.data.Store',
24 requires: ['Ext.data.NodeInterface'],
27 * @cfg {Ext.data.Model} node
28 * The Record you want to bind this Store to. Note that
29 * this record will be decorated with the Ext.data.NodeInterface if this is not the
35 * @cfg {Boolean} recursive
36 * Set this to true if you want this NodeStore to represent
37 * all the descendents of the node in its flat data collection. This is useful for
38 * rendering a tree structure to a DataView and is being used internally by
39 * the TreeView. Any records that are moved, removed, inserted or appended to the
40 * node at any depth below the node this store is bound to will be automatically
41 * updated in this Store's internal flat data structure.
46 * @cfg {Boolean} rootVisible
47 * False to not include the root node in this Stores collection.
51 constructor: function(config) {
55 config = config || {};
56 Ext.apply(me, config);
59 if (Ext.isDefined(me.proxy)) {
60 Ext.Error.raise("A NodeStore cannot be bound to a proxy. Instead bind it to a record " +
61 "decorated with the NodeInterface by setting the node config.");
65 config.proxy = {type: 'proxy'};
66 me.callParent([config]);
68 me.addEvents('expand', 'collapse', 'beforeexpand', 'beforecollapse');
77 setNode: function(node) {
80 if (me.node && me.node != node) {
81 // We want to unbind our listeners on the old node
83 expand: me.onNodeExpand,
84 collapse: me.onNodeCollapse,
85 append: me.onNodeAppend,
86 insert: me.onNodeInsert,
87 remove: me.onNodeRemove,
95 Ext.data.NodeInterface.decorate(node);
101 expand: me.onNodeExpand,
102 collapse: me.onNodeCollapse,
103 append: me.onNodeAppend,
104 insert: me.onNodeInsert,
105 remove: me.onNodeRemove,
110 if (node.isExpanded() && node.isLoaded()) {
111 me.onNodeExpand(node, node.childNodes, true);
116 onNodeSort: function(node, childNodes) {
119 if ((me.indexOf(node) !== -1 || (node === me.node && !me.rootVisible) && node.isExpanded())) {
120 me.onNodeCollapse(node, childNodes, true);
121 me.onNodeExpand(node, childNodes, true);
125 onNodeExpand: function(parent, records, suppressEvent) {
127 insertIndex = me.indexOf(parent) + 1,
128 ln = records ? records.length : 0,
131 if (!me.recursive && parent !== me.node) {
135 if (!me.isVisible(parent)) {
139 if (!suppressEvent && me.fireEvent('beforeexpand', parent, records, insertIndex) === false) {
144 me.insert(insertIndex, records);
145 for (i = 0; i < ln; i++) {
147 if (record.isExpanded()) {
148 if (record.isLoaded()) {
150 me.onNodeExpand(record, record.childNodes, true);
153 record.set('expanded', false);
160 if (!suppressEvent) {
161 me.fireEvent('expand', parent, records);
165 onNodeCollapse: function(parent, records, suppressEvent) {
168 collapseIndex = me.indexOf(parent) + 1,
171 if (!me.recursive && parent !== me.node) {
175 if (!suppressEvent && me.fireEvent('beforecollapse', parent, records, collapseIndex) === false) {
179 for (i = 0; i < ln; i++) {
182 if (record.isExpanded()) {
183 me.onNodeCollapse(record, record.childNodes, true);
187 if (!suppressEvent) {
188 me.fireEvent('collapse', parent, records, collapseIndex);
192 onNodeAppend: function(parent, node, index) {
196 if (me.isVisible(node)) {
200 sibling = node.previousSibling;
201 while (sibling.isExpanded() && sibling.lastChild) {
202 sibling = sibling.lastChild;
206 me.insert(me.indexOf(refNode) + 1, node);
207 if (!node.isLeaf() && node.isExpanded()) {
208 if (node.isLoaded()) {
210 me.onNodeExpand(node, node.childNodes, true);
213 node.set('expanded', false);
220 onNodeInsert: function(parent, node, refNode) {
222 index = this.indexOf(refNode);
224 if (index != -1 && me.isVisible(node)) {
225 me.insert(index, node);
226 if (!node.isLeaf() && node.isExpanded()) {
227 if (node.isLoaded()) {
229 me.onNodeExpand(node, node.childNodes, true);
232 node.set('expanded', false);
239 onNodeRemove: function(parent, node, index) {
241 if (me.indexOf(node) != -1) {
242 if (!node.isLeaf() && node.isExpanded()) {
243 me.onNodeCollapse(node, node.childNodes, true);
249 isVisible: function(node) {
250 var parent = node.parentNode;
252 if (parent === this.node && !this.rootVisible && parent.isExpanded()) {
256 if (this.indexOf(parent) === -1 || !parent.isExpanded()) {
260 parent = parent.parentNode;