]> git.proxmox.com Git - extjs.git/blob - extjs/packages/ux/src/ajax/DataSimlet.js
bump version to 7.0.0-4
[extjs.git] / extjs / packages / ux / src / ajax / DataSimlet.js
1 /**
2 * This base class is used to handle data preparation (e.g., sorting, filtering and
3 * group summary).
4 */
5 Ext.define('Ext.ux.ajax.DataSimlet', function() {
6 function makeSortFn(def, cmp) {
7 var order = def.direction,
8 sign = (order && order.toUpperCase() === 'DESC') ? -1 : 1;
9
10 return function(leftRec, rightRec) {
11 var lhs = leftRec[def.property],
12 rhs = rightRec[def.property],
13 c = (lhs < rhs) ? -1 : ((rhs < lhs) ? 1 : 0);
14
15 if (c || !cmp) {
16 return c * sign;
17 }
18
19 return cmp(leftRec, rightRec);
20 };
21 }
22
23 function makeSortFns(defs, cmp) {
24 var sortFn, i;
25
26 for (sortFn = cmp, i = defs && defs.length; i;) {
27 sortFn = makeSortFn(defs[--i], sortFn);
28 }
29
30 return sortFn;
31 }
32
33 return {
34 extend: 'Ext.ux.ajax.Simlet',
35
36 buildNodes: function(node, path) {
37 var me = this,
38 nodeData = {
39 data: []
40 },
41 len = node.length,
42 children, i, child, name;
43
44 me.nodes[path] = nodeData;
45
46 for (i = 0; i < len; ++i) {
47 nodeData.data.push(child = node[i]);
48 name = child.text || child.title;
49
50 child.id = path ? path + '/' + name : name;
51 children = child.children;
52
53 if (!(child.leaf = !children)) {
54 delete child.children;
55
56 me.buildNodes(children, child.id);
57 }
58 }
59 },
60
61 deleteRecord: function(pos) {
62 if (this.data && typeof this.data !== 'function') {
63 Ext.Array.removeAt(this.data, pos);
64 }
65 },
66
67 fixTree: function(ctx, tree) {
68 var me = this,
69 node = ctx.params.node,
70 nodes;
71
72 if (!(nodes = me.nodes)) {
73 me.nodes = nodes = {};
74 me.buildNodes(tree, '');
75 }
76
77 node = nodes[node];
78
79 if (node) {
80 if (me.node) {
81 me.node.sortedData = me.sortedData;
82 me.node.currentOrder = me.currentOrder;
83 }
84
85 me.node = node;
86 me.data = node.data;
87 me.sortedData = node.sortedData;
88 me.currentOrder = node.currentOrder;
89 }
90 else {
91 me.data = null;
92 }
93 },
94
95 getData: function(ctx) {
96 var me = this,
97 params = ctx.params,
98 order = (params.filter || '') + (params.group || '') + '-' + (params.sort || '') +
99 '-' + (params.dir || ''),
100 tree = me.tree,
101 dynamicData, data, fields, sortFn, filters;
102
103 if (tree) {
104 me.fixTree(ctx, tree);
105 }
106
107 data = me.data;
108
109 if (typeof data === 'function') {
110 dynamicData = true;
111 data = data.call(this, ctx);
112 }
113
114 // If order is '--' then it means we had no order passed, due to the string concat above
115 if (!data || order === '--') {
116 return data || [];
117 }
118
119 if (!dynamicData && order === me.currentOrder) {
120 return me.sortedData;
121 }
122
123 ctx.filterSpec = params.filter && Ext.decode(params.filter);
124 ctx.groupSpec = params.group && Ext.decode(params.group);
125
126 fields = params.sort;
127
128 if (params.dir) {
129 fields = [{ direction: params.dir, property: fields }];
130 }
131 else if (params.sort) {
132 fields = Ext.decode(params.sort);
133 }
134 else {
135 fields = null;
136 }
137
138 if (ctx.filterSpec) {
139 filters = new Ext.util.FilterCollection();
140
141 filters.add(this.processFilters(ctx.filterSpec));
142 data = Ext.Array.filter(data, filters.getFilterFn());
143 }
144
145 sortFn = makeSortFns((ctx.sortSpec = fields));
146
147 if (ctx.groupSpec) {
148 sortFn = makeSortFns([ctx.groupSpec], sortFn);
149 }
150
151 // If a straight Ajax request, data may not be an array.
152 // If an Array, preserve 'physical' order of raw data...
153 data = Ext.isArray(data) ? data.slice(0) : data;
154
155 if (sortFn) {
156 Ext.Array.sort(data, sortFn);
157 }
158
159 me.sortedData = data;
160 me.currentOrder = order;
161
162 return data;
163 },
164
165 processFilters: Ext.identityFn,
166
167 getPage: function(ctx, data) {
168 var ret = data,
169 length = data.length,
170 start = ctx.params.start || 0,
171 end = ctx.params.limit ? Math.min(length, start + ctx.params.limit) : length;
172
173 if (start || end < length) {
174 ret = ret.slice(start, end);
175 }
176
177 return ret;
178 },
179
180 getGroupSummary: function(groupField, rows, ctx) {
181 return rows[0];
182 },
183
184 getSummary: function(ctx, data, page) {
185 var me = this,
186 groupField = ctx.groupSpec.property,
187 accum,
188 todo = {},
189 summary = [],
190 fieldValue,
191 lastFieldValue;
192
193 Ext.each(page, function(rec) {
194 fieldValue = rec[groupField];
195 todo[fieldValue] = true;
196 });
197
198 function flush() {
199 if (accum) {
200 summary.push(me.getGroupSummary(groupField, accum, ctx));
201 accum = null;
202 }
203 }
204
205 // data is ordered primarily by the groupField, so one pass can pick up all
206 // the summaries one at a time.
207 Ext.each(data, function(rec) {
208 fieldValue = rec[groupField];
209
210 if (lastFieldValue !== fieldValue) {
211 flush();
212 lastFieldValue = fieldValue;
213 }
214
215 if (!todo[fieldValue]) {
216 // if we have even 1 summary, we have summarized all that we need
217 // (again because data and page are ordered by groupField)
218 return !summary.length;
219 }
220
221 if (accum) {
222 accum.push(rec);
223 }
224 else {
225 accum = [rec];
226 }
227
228 return true;
229 });
230
231 flush(); // make sure that last pesky summary goes...
232
233 return summary;
234 }
235 };
236 }());