Ext.define('Ext.ux.ajax.GroupingSimlet', {
extend: 'Ext.ux.ajax.JsonSimlet',
alias: 'simlet.grouping',
lastPost: null, // last Ajax params sent to this simlet
lastResponse: null, // last JSON response produced by this simlet
doGet: function(ctx) {
var me = this,
data = me.getData(ctx),
page = me.getPage(ctx, data),
reader = ctx.xhr.options.proxy && ctx.xhr.options.proxy.getReader(),
root = reader && reader.getRootProperty(),
ret = me.callParent(arguments), // pick up status/statusText
response = {},
summary = {},
i, len, s;
if (root && Ext.isArray(page)) {
response[root] = page;
response[reader.getTotalProperty()] = data.length;
}
else {
response = page;
}
if (ctx.groupSpec && ctx.summarySpec) {
response[reader.getGroupRootProperty()] = me.getGroupSummaries(ctx, data, page);
len = ctx.summarySpec.length;
for (i = 0; i < len; i++) {
s = ctx.summarySpec[i];
summary[s.name] = s.data.calculate(data, s.name, null, 0, data.length);
}
response[reader.getSummaryRootProperty()] = summary;
}
me.lastResponse = response;
ret.responseText = Ext.encode(me.lastResponse);
return ret;
},
doPost: function(ctx) {
return this.doGet(ctx);
},
getData: function(ctx) {
var me = this,
params = ctx.params,
order = (params.filter || '') + (params.group || '') + '-' +
(params.sort || '') + '-' + (params.dir || ''),
tree = me.tree,
data, fields, sortFn, filters;
if (tree) {
me.fixTree(ctx, tree);
}
me.lastPost = params;
data = me.data;
if (typeof data === 'function') {
data = data.call(this, ctx);
}
// If order is '--' then it means we had no order passed, due to the string concat above
if (!data || order === '--') {
return data || [];
}
ctx.filterSpec = params.filter && Ext.decode(params.filter);
ctx.groupSpec = params.group && Ext.decode(params.group);
ctx.summarySpec = params.summary && Ext.decode(params.summary);
fields = params.sort;
if (params.dir) {
fields = [{ direction: params.dir, property: fields }];
}
else {
fields = params.sort && Ext.decode(params.sort);
}
if (ctx.filterSpec) {
filters = new Ext.util.FilterCollection();
filters.add(this.processFilters(ctx.filterSpec));
data = Ext.Array.filter(data, filters.getFilterFn());
}
sortFn = this.makeSortFns((ctx.sortSpec = fields));
if (ctx.groupSpec) {
sortFn = this.makeSortFns(ctx.groupSpec, sortFn);
}
// If a straight Ajax request, data may not be an array.
// If an Array, preserve 'physical' order of raw data...
data = Ext.isArray(data) ? data.slice(0) : data;
if (sortFn) {
Ext.Array.sort(data, sortFn);
}
me.sortedData = data;
me.currentOrder = order;
return data;
},
getGroupSummaries: function(ctx, data, page) {
var groupers = ctx.groupSpec,
summaries = ctx.summarySpec,
out = [],
i, j, k, len, length, len2, grouper, record, values, summary, keys;
len = groupers.length;
for (i = 0; i < len; i++) {
grouper = groupers[i];
values = Ext.Array.pluck(page, grouper.property);
grouper.values = Ext.Array.unique(values);
}
for (i = 0; i < len; i++) {
grouper = groupers[i];
values = grouper.values;
length = values.length;
record = {};
if (i > 0) {
len2 = out.length;
for (j = 0; j < len2; j++) {
for (k = 0; k < length; k++) {
record = Ext.clone(out[j]);
record[grouper.property] = values[k];
out.push(record);
}
}
}
else {
for (j = 0; j < length; j++) {
record = {};
record[grouper.property] = values[j];
out.push(record);
}
}
}
len = out.length;
for (i = 0; i < len; i++) {
record = out[i];
keys = Ext.Object.getKeys(record);
values = Ext.Array.filter(data, function(item) {
var match = true,
i, len, key;
len = keys.length;
for (i = 0; i < len; i++) {
key = keys[i];
match = match && item[key] === record[key];
}
return match;
});
length = summaries.length;
for (j = 0; j < length; j++) {
summary = summaries[j];
if (!summary.data) {
summary.data = Ext.Factory.dataSummary(summary.summary);
}
// eslint-disable-next-line max-len
record[summary.name] = summary.data.calculate(values, summary.name, null, 0, values.length);
}
}
return out;
},
makeSortFn: function(def, cmp) {
var order = def.direction,
sign = (order && order.toUpperCase() === 'DESC') ? -1 : 1;
return function(leftRec, rightRec) {
var lhs = leftRec[def.property],
rhs = rightRec[def.property],
c = (lhs < rhs) ? -1 : ((rhs < lhs) ? 1 : 0);
if (c || !cmp) {
return c * sign;
}
return cmp(leftRec, rightRec);
};
},
makeSortFns: function(defs, cmp) {
var sortFn, i;
defs = Ext.Array.from(defs);
for (sortFn = cmp, i = defs && defs.length; i;) {
sortFn = this.makeSortFn(defs[--i], sortFn);
}
return sortFn;
}
});