@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
1,454 lines (1,167 loc) • 177 kB
JavaScript
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ({
/***/ 0:
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(1282);
/***/ }),
/***/ 3:
/***/ (function(module, exports) {
module.exports = function() { throw new Error("define cannot be used indirect"); };
/***/ }),
/***/ 1003:
/***/ (function(module, exports) {
module.exports = require("./kendo.dom");
/***/ }),
/***/ 1015:
/***/ (function(module, exports) {
module.exports = require("./kendo.data");
/***/ }),
/***/ 1282:
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(1003), __webpack_require__(1015) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
})(function(){
var __meta__ = { // jshint ignore:line
id: "pivotgrid",
name: "PivotGrid",
category: "web",
description: "The PivotGrid widget is a data summarization tool.",
depends: [ "dom", "data", "data.xml", "sortable" ],
features: [{
id: "pivotgrid-configurator",
name: "Configurator",
description: "The PivotConfigurator widget allows the user to select data slices displayed in PivotGrid",
depends: [ "pivot.configurator" ]
}, {
id: "pivotgrid-filtering",
name: "Filtering",
description: "Support for filtering",
depends: [ "pivot.fieldmenu" ]
}, {
id: "pivotgrid-excel-export",
name: "Excel export",
description: "Export pivot grid data as Excel spreadsheet",
depends: [ "ooxml" ]
}, {
id: "pivotgrid-pdf-export",
name: "PDF export",
description: "Export pivot grid data as PDF",
depends: [ "pdf", "drawing" ]
}, {
id: "mobile-scroller",
name: "Mobile scroller",
description: "Support for kinetic scrolling in mobile device",
depends: [ "mobile.scroller" ]
}]
};
/*jshint eqnull: true*/
(function($, undefined) {
var kendo = window.kendo,
ui = kendo.ui,
Class = kendo.Class,
Widget = ui.Widget,
DataSource = kendo.data.DataSource,
outerWidth = kendo._outerWidth,
outerHeight = kendo._outerHeight,
toString = {}.toString,
identity = function(o) { return o; },
map = $.map,
extend = $.extend,
isFunction = kendo.isFunction,
CHANGE = "change",
ERROR = "error",
MEASURES = "Measures",
PROGRESS = "progress",
STATERESET = "stateReset",
AUTO = "auto",
DIV = "<div/>",
NS = ".kendoPivotGrid",
ROW_TOTAL_KEY = "__row_total__",
DATABINDING = "dataBinding",
DATABOUND = "dataBound",
EXPANDMEMBER = "expandMember",
COLLAPSEMEMBER = "collapseMember",
STATE_EXPANDED = "k-i-collapse",
STATE_COLLAPSED = "k-i-expand",
HEADER_TEMPLATE = "<span>#: data.member.caption || data.member.name #</span>",
KPISTATUS_TEMPLATE = '<span class="k-icon k-i-kpi-status-#=data.dataItem.value > 0 ? \"open\" : data.dataItem.value < 0 ? \"deny\" : \"hold\"#" title="#:data.dataItem.value#"></span>',
KPITREND_TEMPLATE = '<span class="k-icon k-i-kpi-trend-#=data.dataItem.value > 0 ? \"increase\" : data.dataItem.value < 0 ? \"decrease\" : \"equal\"#" title="#:data.dataItem.value#"></span>',
DATACELL_TEMPLATE = '#= data.dataItem ? kendo.htmlEncode(data.dataItem.fmtValue || data.dataItem.value) || " " : " " #',
LAYOUT_TABLE = '<table class="k-pivot-layout">' +
'<tr>' +
'<td>' +
'<div class="k-pivot-rowheaders"></div>' +
'</td>' +
'<td>' +
'<div class="k-pivot-table k-state-default"></div>' +
'</td>' +
'</tr>' +
'</table>';
var AXIS_ROWS = "rows";
var AXIS_COLUMNS = "columns";
function normalizeMeasures(measure) {
var descriptor = typeof measure === "string" ? [{ name: measure }] : measure;
var descriptors = toString.call(descriptor) === "[object Array]" ? descriptor : (descriptor !== undefined ? [descriptor] : []);
return map(descriptors, function(d) {
if (typeof d === "string") {
return { name: d };
}
return { name: d.name, type: d.type };
});
}
function normalizeMembers(member) {
var descriptor = typeof member === "string" ? [{ name: [member], expand: false }] : member;
var descriptors = toString.call(descriptor) === "[object Array]" ? descriptor : (descriptor !== undefined ? [descriptor] : []);
return map(descriptors, function(d) {
if (typeof d === "string") {
return { name: [d], expand: false };
}
return { name: (toString.call(d.name) === "[object Array]" ? d.name.slice() : [d.name]), expand: d.expand };
});
}
function normalizeName(name) {
if (name.indexOf(" ") !== -1) {
name = '["' + name + '"]';
}
return name;
}
function accumulateMembers(accumulator, rootTuple, tuple, level) {
var idx, length;
var children;
var member;
if (!tuple) {
tuple = rootTuple;
}
if (!level) {
level = 0;
}
member = tuple.members[level];
if (!member || member.measure) { //return if no member or measure
return;
}
children = member.children;
length = children.length;
if (tuple === rootTuple) {
accumulator[kendo.stringify([member.name])] = !!length;
} else if (length) {
accumulator[kendo.stringify(buildPath(tuple, level))] = true;
}
if (length) {
for (idx = 0; idx < length; idx++) {
accumulateMembers(accumulator, rootTuple, children[idx], level);
}
}
accumulateMembers(accumulator, rootTuple, tuple, level + 1);
}
function descriptorsForAxes(tuples) {
var result = {};
if (tuples.length) {
accumulateMembers(result, tuples[0]);
}
var descriptors = [];
for (var k in result) {
descriptors.push({ name: $.parseJSON(k), expand: result[k] });
}
return descriptors;
}
function addMissingPathMembers(members, axis) {
var tuples = axis.tuples || [];
var firstTuple = tuples[0];
if (firstTuple && members.length < firstTuple.members.length) {
var tupleMembers = firstTuple.members;
for (var idx = 0; idx < tupleMembers.length; idx++) {
if (tupleMembers[idx].measure) {
continue;
}
var found = false;
for (var j = 0; j < members.length; j++) {
if (getName(members[j]).indexOf(tupleMembers[idx].hierarchy) === 0) {
found = true;
break;
}
}
if (!found) {
members.push({ name: [tupleMembers[idx].name], expand: false }); //calling normalize here to make name from string to array
}
}
}
}
function tupleToDescriptors(tuple) {
var result = [];
var members = tuple.members;
for (var idx = 0; idx < members.length; idx++) {
if (members[idx].measure) {
continue;
}
//make tuple name an array
result.push({ name: [members[idx].name], expand: members[idx].children.length > 0});
}
return result;
}
function descriptorsForMembers(axis, members, measures) {
axis = axis || {};
addMissingPathMembers(members, axis);
if (measures.length > 1) {
members.push({
name: MEASURES,
measure: true,
children: normalizeMembers(measures)
});
}
var tupletoSearch = {
members: members
};
if (axis.tuples) {
var result = findExistingTuple(axis.tuples, tupletoSearch);
if (result.tuple) {
members = tupleToDescriptors(result.tuple);
}
}
return members;
}
function createAggregateGetter(m) {
var measureGetter = kendo.getter(m.field, true);
return function(aggregatorContext, state) {
return m.aggregate(measureGetter(aggregatorContext.dataItem), state, aggregatorContext);
};
}
function isNumber(val) {
return typeof val === "number" && !isNaN(val);
}
function isDate(val) {
return val && val.getTime;
}
var functions = {
sum: function(value, state) {
var accumulator = state.accumulator;
if (!isNumber(accumulator)) {
accumulator = value;
} else if (isNumber(value)) {
accumulator += value;
}
return accumulator;
},
count: function(value, state) {
return (state.accumulator || 0) + 1;
},
average: {
aggregate: function(value, state) {
var accumulator = state.accumulator;
if (state.count === undefined) {
state.count = 0;
}
if (!isNumber(accumulator)) {
accumulator = value;
} else if (isNumber(value)) {
accumulator += value;
}
if (isNumber(value)) {
state.count++;
}
return accumulator;
},
result: function(state) {
var accumulator = state.accumulator;
if (isNumber(accumulator)) {
accumulator = accumulator / state.count;
}
return accumulator;
}
},
max: function(value, state) {
var accumulator = state.accumulator;
if (!isNumber(accumulator) && !isDate(accumulator)) {
accumulator = value;
}
if(accumulator < value && (isNumber(value) || isDate(value))) {
accumulator = value;
}
return accumulator;
},
min: function(value, state) {
var accumulator = state.accumulator;
if (!isNumber(accumulator) && !isDate(accumulator)) {
accumulator = value;
}
if(accumulator > value && (isNumber(value) || isDate(value))) {
accumulator = value;
}
return accumulator;
}
};
var PivotCubeBuilder = Class.extend({
init: function(options) {
this.options = extend({}, this.options, options);
this.dimensions = this._normalizeDescriptors("field", this.options.dimensions);
this.measures = this._normalizeDescriptors("name", this.options.measures);
},
_normalizeDescriptors: function(keyField, descriptors) {
descriptors = descriptors || {};
var fields = {};
var field;
if (toString.call(descriptors) === "[object Array]") {
for (var idx = 0, length = descriptors.length; idx < length; idx++) {
field = descriptors[idx];
if (typeof field === "string") {
fields[field] = {};
} else if (field[keyField]) {
fields[field[keyField]] = field;
}
}
descriptors = fields;
}
return descriptors;
},
_rootTuples: function(rootNames, measureAggregators) {
var aggregatorsLength = measureAggregators.length || 1;
var dimensionsSchema = this.dimensions || [];
var root, name, parts;
var measureIdx = 0;
var idx;
var rootNamesLength = rootNames.length;
var result = [];
var keys = [];
if (rootNamesLength || measureAggregators.length) {
for (measureIdx = 0; measureIdx < aggregatorsLength; measureIdx++) {
root = { members: [] };
for (idx = 0; idx < rootNamesLength; idx++) {
name = rootNames[idx];
parts = name.split("&");
root.members[root.members.length] = {
children: [],
caption: (dimensionsSchema[name] || {}).caption || "All",
name: name,
levelName: name,
levelNum: "0",
hasChildren: true,
parentName: parts.length > 1 ? parts[0] : undefined,
hierarchy: name
};
}
if (aggregatorsLength > 1) {
root.members[root.members.length] = {
children: [],
caption: (measureAggregators[measureIdx]).caption,
name: measureAggregators[measureIdx].descriptor.name,
levelName: "MEASURES",
levelNum: "0",
hasChildren: false,
parentName: undefined,
hierarchy: "MEASURES"
};
}
result[result.length] = root;
}
keys.push(ROW_TOTAL_KEY);
}
return {
keys: keys,
tuples: result
};
},
_expandedTuples: function(map, expanded, measureAggregators) {
var aggregatorsLength = measureAggregators.length || 1;
var dimensionsSchema = this.dimensions || [];
var measureIdx;
var tuple;
var key;
var mapItem;
var current;
var currentKeys;
var accumulator = [];
var accumulatorKeys = [];
var memberInfo;
var expandedNames;
var parts;
var name;
var idx;
for (key in map) {
mapItem = map[key];
memberInfo = this._findExpandedMember(expanded, mapItem.uniquePath);
current = accumulator[memberInfo.index] || [];
currentKeys = accumulatorKeys[memberInfo.index] || [];
expandedNames = memberInfo.member.names;
for (measureIdx = 0; measureIdx < aggregatorsLength; measureIdx++) {
tuple = { members: [] };
for (idx = 0; idx < expandedNames.length; idx++) {
if (idx === memberInfo.member.expandedIdx) {
tuple.members[tuple.members.length] = {
children: [],
caption: mapItem.value,
name: mapItem.name,
hasChildren: false,
levelNum: 1,
levelName: mapItem.parentName + mapItem.name,
parentName: mapItem.parentName,
hierarchy: mapItem.parentName + mapItem.name
};
if (measureIdx === 0) {
currentKeys.push(buildPath(tuple, idx).join(""));
}
} else {
name = expandedNames[idx];
parts = name.split("&");
tuple.members[tuple.members.length] = {
children: [],
caption: (dimensionsSchema[name] || {}).caption || "All",
name: name,
levelName: name,
levelNum: "0",
hasChildren: true,
parentName: parts.length > 1 ? parts[0] : undefined,
hierarchy: name
};
}
}
if (aggregatorsLength > 1) {
tuple.members[tuple.members.length] = {
children: [],
caption: measureAggregators[measureIdx].caption,
name: measureAggregators[measureIdx].descriptor.name,
levelName: "MEASURES",
levelNum: "0",
hasChildren: true,
parentName: undefined,
hierarchy: "MEASURES"
};
}
current[current.length] = tuple;
}
accumulator[memberInfo.index] = current;
accumulatorKeys[memberInfo.index] = currentKeys;
}
return {
keys: accumulatorKeys,
tuples: accumulator
};
},
_findExpandedMember: function(members, parentName) {
for (var idx = 0; idx < members.length; idx++) {
if (members[idx].uniquePath === parentName) {
return {
member: members[idx],
index: idx
};
}
}
},
_asTuples: function(map, descriptor, measureAggregators) {
measureAggregators = measureAggregators || [];
var rootInfo = this._rootTuples(descriptor.root, measureAggregators);
var expandedInfo = this._expandedTuples(map, descriptor.expanded, measureAggregators);
return {
keys: [].concat.apply(rootInfo.keys, expandedInfo.keys),
tuples: [].concat.apply(rootInfo.tuples, expandedInfo.tuples)
};
},
_measuresInfo: function(measures, rowAxis) {
var idx = 0;
var length = measures && measures.length;
var aggregateNames = [];
var resultFuncs= {};
var formats = {};
var descriptors = (this.measures || {});
var measure;
var name;
for (; idx < length; idx++) {
name = measures[idx].descriptor.name;
measure = descriptors[name] || {};
aggregateNames.push(name);
if (measure.result) {
resultFuncs[name] = measure.result;
}
if (measure.format) {
formats[name] = measure.format;
}
}
return {
names: aggregateNames,
formats: formats,
resultFuncs: resultFuncs,
rowAxis: rowAxis
};
},
_toDataArray: function(map, measuresInfo, rowKeys, columnKeys) {
var result = [];
var aggregates;
var name, i, j, k, n;
var row, column, columnKey;
var rowMeasureNamesLength = 1;
var rowMeasureNames = [];
var columnMeasureNames;
var rowLength = rowKeys.length || 1;
var columnLength = columnKeys.length || 1;
if (measuresInfo.rowAxis) {
rowMeasureNames = measuresInfo.names;
rowMeasureNamesLength = rowMeasureNames.length;
} else {
columnMeasureNames = measuresInfo.names;
}
for (i = 0; i < rowLength; i++) {
row = map[rowKeys[i] || ROW_TOTAL_KEY];
for (n = 0; n < rowMeasureNamesLength; n++) {
if (measuresInfo.rowAxis) {
columnMeasureNames = [rowMeasureNames[n]];
}
for (j = 0; j < columnLength; j++) {
columnKey = columnKeys[j] || ROW_TOTAL_KEY;
column = row.items[columnKey];
if (columnKey === ROW_TOTAL_KEY) {
aggregates = row.aggregates;
} else {
aggregates = column ? column.aggregates : {};
}
for (k = 0; k < columnMeasureNames.length; k++) {
name = columnMeasureNames[k];
this._addData(result, aggregates[name], measuresInfo.formats[name], measuresInfo.resultFuncs[name]);
}
}
}
}
return result;
},
_addData: function(result, value, format, resultFunc) {
var fmtValue = "";
var ordinal;
if (value) {
value = resultFunc ? resultFunc(value) : value.accumulator;
fmtValue = format ? kendo.format(format, value) : value;
}
ordinal = result.length;
result[ordinal] = {
ordinal: ordinal,
value: value || "",
fmtValue: fmtValue
};
},
_matchDescriptors: function(dataItem, descriptor, getters) {
var parts;
var parentField;
var expectedValue;
var names = descriptor.names;
var idx = descriptor.expandedIdx;
var value;
while (idx > 0) {
parts = names[--idx].split("&");
if (parts.length > 1) {
parentField = parts[0];
expectedValue = parts[1];
value = getters[parentField](dataItem);
value = (value !== undefined && value !== null) ? value.toString() : value;
if (value != expectedValue) {
return false;
}
}
}
return true;
},
_calculateAggregate: function(measureAggregators, aggregatorContext, totalItem) {
var result = {};
var state;
var name;
for (var measureIdx = 0; measureIdx < measureAggregators.length; measureIdx++) {
name = measureAggregators[measureIdx].descriptor.name;
state = totalItem.aggregates[name] || { };
state.accumulator = measureAggregators[measureIdx].aggregator(aggregatorContext, state);
result[name] = state;
}
return result;
},
_processColumns: function(measureAggregators, descriptors, getters, columns, aggregatorContext, rowTotal, state, updateColumn) {
var value;
var descriptor;
var column;
var totalItem;
var key, name, parentName, path;
var dataItem = aggregatorContext.dataItem;
var idx = 0;
for (; idx < descriptors.length; idx++) {
descriptor = descriptors[idx];
//checks whether the dataItem is relevant to the descriptors
if (!this._matchDescriptors(dataItem, descriptor, getters)) {
continue;
}
path = descriptor.names.slice(0, descriptor.expandedIdx).join("");
name = descriptor.names[descriptor.expandedIdx];
value = getters[name](dataItem);
value = (value !== undefined && value !== null) ? value.toString() : value;
parentName = name;
name = name + "&" + value;
key = path + name;
column = columns[key] || {
index: state.columnIndex,
parentName: parentName,
name: name,
uniquePath: path + parentName,
value: value
};
totalItem = rowTotal.items[key] || {
aggregates: {}
};
rowTotal.items[key] = {
index: column.index,
aggregates: this._calculateAggregate(measureAggregators, aggregatorContext, totalItem)
};
if (updateColumn) {
if (!columns[key]) {
state.columnIndex++;
}
columns[key] = column;
}
}
},
_measureAggregators: function(options) {
var measureDescriptors = options.measures || [];
var measures = this.measures || {};
var aggregators = [];
var descriptor, measure, idx, length;
var defaultAggregate, aggregate;
if (measureDescriptors.length) {
for (idx = 0, length = measureDescriptors.length; idx < length; idx++) {
descriptor = measureDescriptors[idx];
measure = measures[descriptor.name];
defaultAggregate = null;
if (measure) {
aggregate = measure.aggregate;
if (typeof aggregate === "string") {
defaultAggregate = functions[aggregate.toLowerCase()];
if (!defaultAggregate) {
throw new Error("There is no such aggregate function");
}
measure.aggregate = defaultAggregate.aggregate || defaultAggregate;
measure.result = defaultAggregate.result;
}
aggregators.push({
descriptor: descriptor,
caption: measure.caption,
result: measure.result,
aggregator: createAggregateGetter(measure)
});
}
}
} else {
aggregators.push({
descriptor: { name: "default"},
caption: "default",
aggregator: function() { return 1; }
});
}
return aggregators;
},
_buildGetters: function(names) {
var result = {};
var parts;
var name;
for (var idx = 0; idx < names.length; idx++) {
name = names[idx];
parts = name.split("&");
if (parts.length > 1) {
result[parts[0]] = kendo.getter(parts[0], true);
} else {
result[name] = kendo.getter(normalizeName(name), true);
}
}
return result;
},
_parseDescriptors: function (descriptors) {
var parsedDescriptors = parseDescriptors(descriptors);
var rootNames = getRootNames(parsedDescriptors.root);
var expanded = parsedDescriptors.expanded;
var result = [];
for (var idx = 0; idx < expanded.length; idx++) {
result.push(mapNames(expanded[idx].name, rootNames));
}
return {
root: rootNames,
expanded: result
};
},
_filter: function(data, filter) {
if (!filter) {
return data;
}
var expr;
var idx = 0;
var filters = filter.filters;
for (; idx < filters.length; idx++) {
expr = filters[idx];
if (expr.operator === "in") {
filters[idx] = this._normalizeFilter(expr);
}
}
return new kendo.data.Query(data).filter(filter).data;
},
_normalizeFilter: function(filter) {
var value = filter.value.split(",");
var result = [];
if (!value.length) {
return value;
}
for (var idx = 0; idx < value.length; idx++) {
result.push({
field: filter.field,
operator: "eq",
value: value[idx]
});
}
return {
logic: "or",
filters: result
};
},
process: function(data, options) {
data = data || [];
options = options || {};
data = this._filter(data, options.filter);
var measures = options.measures || [];
var measuresRowAxis = options.measuresAxis === "rows";
var columnDescriptors = options.columns || [];
var rowDescriptors = options.rows || [];
if (!columnDescriptors.length && rowDescriptors.length && (!measures.length || (measures.length && measuresRowAxis))) {
columnDescriptors = rowDescriptors;
rowDescriptors = [];
measuresRowAxis = false;
}
if (!columnDescriptors.length && !rowDescriptors.length) {
measuresRowAxis = false;
}
if (!columnDescriptors.length && measures.length) {
columnDescriptors = normalizeMembers(options.measures);
}
columnDescriptors = this._parseDescriptors(columnDescriptors);
rowDescriptors = this._parseDescriptors(rowDescriptors);
var aggregatedData = {};
var columns = {};
var rows = {};
var rowValue;
var state = { columnIndex: 0 };
var measureAggregators = this._measureAggregators(options);
var columnGetters = this._buildGetters(columnDescriptors.root);
var rowGetters = this._buildGetters(rowDescriptors.root);
var processed = false;
var expandedColumns = columnDescriptors.expanded;
var expandedRows = rowDescriptors.expanded;
var dataItem;
var aggregatorContext;
var hasExpandedRows = expandedRows.length !== 0;
var rowIdx, rowDescriptor, rowName, rowTotal;
var key, path, parentName, value;
var columnsInfo, rowsInfo;
var length = data.length;
var idx = 0;
if (columnDescriptors.root.length || rowDescriptors.root.length) {
processed = true;
for (idx = 0; idx < length; idx++) {
dataItem = data[idx];
aggregatorContext = {
dataItem: dataItem,
index: idx
};
rowTotal = aggregatedData[ROW_TOTAL_KEY] || {
items: {},
aggregates: {}
};
this._processColumns(measureAggregators, expandedColumns, columnGetters, columns, aggregatorContext, rowTotal, state, !hasExpandedRows);
rowTotal.aggregates = this._calculateAggregate(measureAggregators, aggregatorContext, rowTotal);
aggregatedData[ROW_TOTAL_KEY] = rowTotal;
for (rowIdx = 0; rowIdx < expandedRows.length; rowIdx++) {
rowDescriptor = expandedRows[rowIdx];
if (!this._matchDescriptors(dataItem, rowDescriptor, rowGetters)) {
this._processColumns(measureAggregators, expandedColumns, columnGetters, columns, aggregatorContext, { items: {}, aggregates: {} }, state, true);
continue;
}
path = rowDescriptor.names.slice(0, rowDescriptor.expandedIdx).join("");
rowName = rowDescriptor.names[rowDescriptor.expandedIdx];
parentName = rowName;
rowValue = rowGetters[rowName](dataItem);
rowValue = rowValue !== undefined ? rowValue.toString() : rowValue;
rowName = rowName + "&" + rowValue;
key = path + rowName;
rows[key] = {
uniquePath: path + parentName,
parentName: parentName,
name: rowName,
value: rowValue
};
value = aggregatedData[key] || {
items: {},
aggregates: {}
};
this._processColumns(measureAggregators, expandedColumns, columnGetters, columns, aggregatorContext, value, state, true);
value.aggregates = this._calculateAggregate(measureAggregators, aggregatorContext, value);
aggregatedData[key] = value;
}
}
}
if (processed && length) {
if (measureAggregators.length > 1 && (!options.columns || !options.columns.length)) {
columnDescriptors = {
root: [],
expanded: []
};
}
columnsInfo = this._asTuples(columns, columnDescriptors, measuresRowAxis ? [] : measureAggregators);
rowsInfo = this._asTuples(rows, rowDescriptors, measuresRowAxis ? measureAggregators : []);
columns = columnsInfo.tuples;
rows = rowsInfo.tuples;
aggregatedData = this._toDataArray(aggregatedData, this._measuresInfo(measureAggregators, measuresRowAxis), rowsInfo.keys, columnsInfo.keys);
} else {
aggregatedData = columns = rows = [];
}
return {
axes: {
columns: { tuples: columns },
rows: { tuples: rows }
},
data: aggregatedData
};
}
});
var PivotTransport = Class.extend({
init: function(options, transport) {
this.transport = transport;
this.options = transport.options || {};
if (!this.transport.discover) {
if (isFunction(options.discover)) {
this.discover = options.discover;
}
}
},
read: function(options) {
return this.transport.read(options);
},
update: function(options) {
return this.transport.update(options);
},
create: function(options) {
return this.transport.create(options);
},
destroy: function(options) {
return this.transport.destroy(options);
},
discover: function(options) {
if (this.transport.discover) {
return this.transport.discover(options);
}
options.success({});
},
catalog: function(val) {
var options = this.options || {};
if (val === undefined) {
return (options.connection || {}).catalog;
}
var connection = options.connection || {};
connection.catalog = val;
this.options.connection = connection;
$.extend(this.transport.options, { connection: connection });
},
cube: function(val) {
var options = this.options || {};
if (val === undefined) {
return (options.connection || {}).cube;
}
var connection = options.connection || {};
connection.cube = val;
this.options.connection = connection;
extend(true, this.transport.options, { connection: connection });
}
});
var PivotDataSource = DataSource.extend({
init: function(options) {
var cube = ((options || {}).schema || {}).cube;
var measuresAxis = "columns";
var measures;
var schema = {
axes: identity,
cubes: identity,
catalogs: identity,
measures: identity,
dimensions: identity,
hierarchies: identity,
levels: identity,
members: identity
};
if (cube) {
schema = $.extend(schema, this._cubeSchema(cube));
this.cubeBuilder = new PivotCubeBuilder(cube);
}
DataSource.fn.init.call(this, extend(true, {}, {
schema: schema
}, options));
this.transport = new PivotTransport(this.options.transport || {}, this.transport);
this._columns = normalizeMembers(this.options.columns);
this._rows = normalizeMembers(this.options.rows);
measures = this.options.measures || [];
if (toString.call(measures) === "[object Object]") {
measuresAxis = measures.axis || "columns";
measures = measures.values || [];
}
this._measures = normalizeMeasures(measures);
this._measuresAxis = measuresAxis;
this._skipNormalize = 0;
this._axes = {};
},
_cubeSchema: function(cube) {
return {
dimensions: function() {
var result = [];
var dimensions = cube.dimensions;
for (var key in dimensions) {
result.push({
name: key,
caption: dimensions[key].caption || key,
uniqueName: key,
defaultHierarchy: key,
type: 1
});
}
if (cube.measures) {
result.push({
name: MEASURES,
caption: MEASURES,
uniqueName: MEASURES,
type: 2
});
}
return result;
},
hierarchies: function(){
return [];
},
measures: function() {
var result = [];
var measures = cube.measures;
for (var key in measures) {
result.push({
name: key,
caption: key,
uniqueName: key,
aggregator: key
});
}
return result;
},
members: $.proxy(function(response, restrictions) {
var name = restrictions.levelUniqueName || restrictions.memberUniqueName;
var schemaData = this.options.schema.data;
var dataGetter = isFunction(schemaData) ? schemaData : kendo.getter(schemaData, true);
var data = (this.options.data && dataGetter(this.options.data)) || this._rawData || [];
var result = [];
var getter;
var value;
var idx = 0;
var distinct = {};
if (name) {
name = name.split(".")[0];
}
if (!restrictions.treeOp) {
result.push({
caption: cube.dimensions[name].caption || name,
childrenCardinality: "1",
dimensionUniqueName: name,
hierarchyUniqueName: name,
levelUniqueName: name,
name: name,
uniqueName: name
});
return result;
}
getter = kendo.getter(normalizeName(name), true);
for (; idx < data.length; idx++) {
value = getter(data[idx]);
if ((value || value === 0) && !distinct[value]) {
distinct[value] = true;
result.push({
caption: value,
childrenCardinality: "0",
dimensionUniqueName: name,
hierarchyUniqueName: name,
levelUniqueName: name,
name: value,
uniqueName: value
});
}
}
return result;
}, this)
};
},
options: {
serverSorting: true,
serverPaging: true,
serverFiltering: true,
serverGrouping: true,
serverAggregates: true
},
catalog: function(val) {
if (val === undefined) {
return this.transport.catalog();
}
this.transport.catalog(val);
this._mergeState({});// clears current state
this._axes = {};
this.data([]);
},
cube: function(val) {
if (val === undefined) {
return this.transport.cube();
}
this.transport.cube(val);
this._axes = {};
this._mergeState({});// clears current state
this.data([]);
},
axes: function() {
return this._axes;
},
columns: function(val) {
if (val === undefined) {
return this._columns;
}
this._skipNormalize += 1;
this._clearAxesData = true;
this._columns = normalizeMembers(val);
this.query({
columns: val,
rows: this.rowsAxisDescriptors(),
measures: this.measures(),
sort: this.sort(),
filter: this.filter()
});
},
rows: function(val) {
if (val === undefined) {
return this._rows;
}
this._skipNormalize += 1;
this._clearAxesData = true;
this._rows = normalizeMembers(val);
this.query({
columns: this.columnsAxisDescriptors(),
rows: val,
measures: this.measures(),
sort: this.sort(),
filter: this.filter()
});
},
measures: function(val) {
if (val === undefined) {
return this._measures;
}
this._skipNormalize += 1;
this._clearAxesData = true;
this.query({
columns: this.columnsAxisDescriptors(),
rows: this.rowsAxisDescriptors(),
measures: normalizeMeasures(val),
sort: this.sort(),
filter: this.filter()
});
},
measuresAxis: function() {
return this._measuresAxis || "columns";
},
_expandPath: function(path, axis) {
var origin = axis === "columns" ? "columns" : "rows";
var other = axis === "columns" ? "rows" : "columns";
var members = normalizeMembers(path);
var memberToExpand = getName(members[members.length - 1]);
this._lastExpanded = origin;
members = descriptorsForMembers(this.axes()[origin], members, this.measures());
for (var idx = 0; idx < members.length; idx++) {
var memberName = getName(members[idx]);
if (memberName === memberToExpand) {
if (members[idx].expand) {
return;
}
members[idx].expand = true;
} else {
members[idx].expand = false;
}
}
var descriptors = {};
descriptors[origin] = members;
descriptors[other] = this._descriptorsForAxis(other);
this._query(descriptors);
},
_descriptorsForAxis: function(axis) {
var axes = this.axes();
var descriptors = this[axis]() || [];
if (axes && axes[axis] && axes[axis].tuples && axes[axis].tuples[0]) {
descriptors = descriptorsForAxes(axes[axis].tuples || []);
}
return descriptors;
},
columnsAxisDescriptors: function() {
return this._descriptorsForAxis("columns");
},
rowsAxisDescriptors: function() {
return this._descriptorsForAxis("rows");
},
_process: function (data, e) {
this._view = data;
e = e || {};
e.items = e.items || this._view;
this.trigger(CHANGE, e);
},
_query: function(options) {
var that = this;
if (!options) {
this._skipNormalize += 1;
this._clearAxesData = true;
}
return that.query(extend({}, {
page: that.page(),
pageSize: that.pageSize(),
sort: that.sort(),
filter: that.filter(),
group: that.group(),
aggregate: that.aggregate(),
columns: this.columnsAxisDescriptors(),
rows: this.rowsAxisDescriptors(),
measures: this.measures()
}, options));
},
query: function(options) {
var state = this._mergeState(options);
if (this._data.length && this.cubeBuilder) {
this._params(state);
this._updateLocalData(this._pristineData);
return $.Deferred().resolve().promise();
}
return this.read(state);
},
_mergeState: function(options) {
options = DataSource.fn._mergeState.call(this, options);
if (options !== undefined) {