]>
git.proxmox.com Git - sencha-touch.git/blob - src/src/data/NodeStore.js
4 Ext
.define('Ext.data.NodeStore', {
5 extend
: 'Ext.data.Store',
7 requires
: ['Ext.data.NodeInterface'],
11 * @cfg {Ext.data.Model} node The Record you want to bind this Store to. Note that
12 * this record will be decorated with the {@link Ext.data.NodeInterface} if this is not the
19 * @cfg {Boolean} recursive Set this to `true` if you want this NodeStore to represent
20 * all the descendants of the node in its flat data collection. This is useful for
21 * rendering a tree structure to a DataView and is being used internally by
22 * the TreeView. Any records that are moved, removed, inserted or appended to the
23 * node at any depth below the node this store is bound to will be automatically
24 * updated in this Store's internal flat data structure.
30 * @cfg {Boolean} rootVisible `false` to not include the root node in this Stores collection.
39 * @cfg {Boolean} folderSort
40 * Set to `true` to automatically prepend a leaf sorter.
45 afterEdit: function(record
, modifiedFields
) {
47 if (modifiedFields
.indexOf('loaded') !== -1) {
48 return this.add(this.retrieveChildNodes(record
));
50 if (modifiedFields
.indexOf('expanded') !== -1) {
53 if (modifiedFields
.indexOf('sorted') !== -1) {
57 this.callParent(arguments
);
60 onNodeAppend: function(parent
, node
) {
61 this.add([node
].concat(this.retrieveChildNodes(node
)));
64 onNodeInsert: function(parent
, node
) {
65 this.add([node
].concat(this.retrieveChildNodes(node
)));
68 onNodeRemove: function(parent
, node
) {
69 this.remove([node
].concat(this.retrieveChildNodes(node
)));
72 onNodeSort: function() {
76 updateFolderSort: function(folderSort
) {
78 this.setGrouper(function(node
) {
85 this.setGrouper(null);
89 createDataCollection: function() {
90 var collection
= this.callParent();
91 collection
.handleSort
= Ext
.Function
.bind(this.handleTreeSort
, this, [collection
], true);
92 collection
.findInsertionIndex
= Ext
.Function
.bind(this.handleTreeInsertionIndex
, this, [collection
, collection
.findInsertionIndex
], true);
96 handleTreeInsertionIndex: function(items
, item
, collection
, originalFn
) {
97 return originalFn
.call(collection
, items
, item
, this.treeSortFn
);
100 handleTreeSort: function(data
) {
101 Ext
.Array
.sort(data
, this.treeSortFn
);
106 * This is a custom tree sorting algorithm. It uses the index property on each node to determine
107 * how to sort siblings. It uses the depth property plus the index to create a weight for each node.
108 * This weight algorithm has the limitation of not being able to go more then 80 levels in depth, or
109 * more then 10k nodes per parent. The end result is a flat collection being correctly sorted based
110 * on this one single sort function.
111 * @param {Ext.data.NodeInterface} node1
112 * @param {Ext.data.NodeInterface} node2
116 treeSortFn: function(node1
, node2
) {
117 // A shortcut for siblings
118 if (node1
.parentNode
=== node2
.parentNode
) {
119 return (node1
.data
.index
< node2
.data
.index
) ? -1 : 1;
122 // @NOTE: with the following algorithm we can only go 80 levels deep in the tree
123 // and each node can contain 10000 direct children max
130 weight1
+= (Math
.pow(10, (parent1
.data
.depth
+1) * -4) * (parent1
.data
.index
+1));
131 parent1
= parent1
.parentNode
;
134 weight2
+= (Math
.pow(10, (parent2
.data
.depth
+1) * -4) * (parent2
.data
.index
+1));
135 parent2
= parent2
.parentNode
;
138 if (weight1
> weight2
) {
140 } else if (weight1
< weight2
) {
143 return (node1
.data
.index
> node2
.data
.index
) ? 1 : -1;
146 applyFilters: function(filters
) {
148 return function(item
) {
149 return me
.isVisible(item
);
153 applyProxy: function(proxy
) {
156 Ext
.Logger
.warn("A NodeStore cannot be bound to a proxy. Instead bind it to a record " +
157 "decorated with the NodeInterface by setting the node config.");
162 applyNode: function(node
) {
164 node
= Ext
.data
.NodeInterface
.decorate(node
);
169 updateNode: function(node
, oldNode
) {
170 if (oldNode
&& !oldNode
.isDestroyed
) {
172 append
: 'onNodeAppend',
173 insert
: 'onNodeInsert',
174 remove
: 'onNodeRemove',
178 oldNode
.unjoin(this);
184 append
: 'onNodeAppend',
185 insert
: 'onNodeInsert',
186 remove
: 'onNodeRemove',
193 if (node
.childNodes
.length
) {
194 data
= data
.concat(this.retrieveChildNodes(node
));
196 if (this.getRootVisible()) {
198 } else if (node
.isLoaded() || node
.isLoading()) {
199 node
.set('expanded', true);
203 this.fireEvent('clear', this);
205 this.suspendEvents();
209 if(data
.length
=== 0) {
210 this.loaded
= node
.loaded
= true;
213 this.fireEvent('refresh', this, this.data
);
218 * Private method used to deeply retrieve the children of a record without recursion.
220 * @param {Ext.data.NodeInterface} root
223 retrieveChildNodes: function(root
) {
224 var node
= this.getNode(),
225 recursive
= this.getRecursive(),
229 if (!root
.childNodes
.length
|| (!recursive
&& root
!== node
)) {
234 return root
.childNodes
;
240 if (child
=== root
) {
243 child
= child
.nextSibling
|| child
.parentNode
;
246 if (child
!== root
) {
249 if (child
.firstChild
) {
251 child
= child
.firstChild
;
253 child
= child
.nextSibling
|| child
.parentNode
;
262 * @param {Object} node
265 isVisible: function(node
) {
266 var parent
= node
.parentNode
;
268 if (!this.getRecursive() && parent
!== this.getNode()) {
273 if (!parent
.isExpanded()) {
277 //we need to check this because for a nodestore the node is not likely to be the root
278 //so we stop going up the chain when we hit the original node as we don't care about any
279 //ancestors above the configured node
280 if (parent
=== this.getNode()) {
284 parent
= parent
.parentNode
;