UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,404 lines (1,155 loc) 250 kB
import './kendo.dom.js'; import './kendo.data.js'; import './kendo.icons.js'; import './kendo.loader.js'; import './kendo.html.loadercontainer.js'; import './kendo.sortable.js'; import { fetchDiscover, fetchData, createDataState, PivotGridNavigation, headersReducer, toData, toTree, toColumns, toRows, sumAggregate, setSort, setFilter, rootFields, readData, parseResponse, minAggregate, mergeTrees, maxAggregate, discoverCommands, createTuples, createRequestBody, createLocalDataState, createFlatSchemaDimensions, createDiscoverBody, createDataTree, createAxisDescriptors, configuratorReducer, compareAxes, cloneDataTree, buildKPIMeasures, averageAggregate, addMultipleMeasures, addKPI, countAggregate } from '@progress/kendo-pivotgrid-common'; import { u as useLoaderContainer } from './loaderContainer-CKYFB4vJ.js'; import './kendo.core.js'; import './kendo.licensing.js'; import '@progress/kendo-licensing'; import './kendo.data.odata.js'; import './kendo.data.xml.js'; import './kendo.html.icon.js'; import './kendo.html.base.js'; import '@progress/kendo-svg-icons'; import './kendo.draganddrop.js'; import './kendo.userevents.js'; const __meta__ = { id: "pivotgrid", name: "PivotGrid", category: "web", description: "The PivotGrid widget is a data summarization tool.", depends: [ "dom", "data", "data.xml", "sortable", "icons", "loader", "html.loadercontainer" ], 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" ] }] }; (function($, undefined$1) { var kendo = window.kendo, ui = kendo.ui, encode = kendo.htmlEncode, Class = kendo.Class, Comparer = kendo.data.Comparer, Widget = ui.Widget, DataSource = kendo.data.DataSource, outerWidth = kendo._outerWidth, outerHeight = kendo._outerHeight, normalizeFilter = kendo.data.Query.normalizeFilter, normalizeSort = kendo.data.Query.normalizeSort, toString = {}.toString, identity = function(o) { return o; }, map = $.map, extend = $.extend, keys = kendo.keys, isFunction = kendo.isFunction, RESIZE = "resize", READ = "read", CHANGE = "change", ERROR = "error", REQUESTSTART = "requestStart", PROGRESS = "progress", REQUESTEND = "requestEnd", MEASURES = "Measures", STATERESET = "stateReset", AUTO = "auto", DIV = "<div></div>", NS = ".kendoPivotGrid", ROW_TOTAL_KEY = "__row_total__", DATABINDING = "dataBinding", DATABOUND = "dataBound", EXPANDMEMBER = "expandMember", HEADERTEMPLATE = ({ id, key, headerClass, colspan, rowspan, expandable, iconClass, role, expanded }) => `<th id="${id}" role="${role}" ${expandable ? `aria-expanded="${expanded}"` : ''} data-key="${encode(key)}" class="${encode(headerClass)}" ${colspan ? 'colspan="' + encode(colspan) + '"' : ''} ${rowspan ? 'rowspan="' + encode(rowspan) + '"' : ''}>` + `${expandable ? kendo.ui.icon($('<span role="presentation" class="k-pivotgrid-toggle"></span>'), { icon: `chevron-${encode(iconClass)}` }) : ''}` + '</th>', COLLAPSEMEMBER = "collapseMember", STATE_EXPANDED_ICONNAME = "caret-alt-down", STATE_EXPANDED_SELECTOR = `.k-i-${STATE_EXPANDED_ICONNAME},.k-svg-i-${STATE_EXPANDED_ICONNAME}`, STATE_COLLAPSED_ICONNAME = "caret-alt-right", HEADER_TEMPLATE = ({ member }) => `<span>${encode(member.caption || member.name)}</span>`, PIVOTGRID_TREND_ICONS_MAP = { "kpi-trend-decrease": "caret-alt-down", "kpi-trend-increase": "caret-alt-up", "kpi-trend-equal": "minus", }, KPISTATUS_TEMPLATE = ({ dataItem }) => kendo.ui.icon($(`<span title="${encode(dataItem.value)}"></span>`), { icon: `kpi-status-${dataItem.value > 0 ? "open" : dataItem.value < 0 ? "deny" : "hold"}` }), KPITREND_TEMPLATE = ({ dataItem }) => kendo.ui.icon($(`<span title="${encode(dataItem.value)}"></span>`), { icon: PIVOTGRID_TREND_ICONS_MAP[`kpi-trend-${dataItem.value > 0 ? "increase" : dataItem.value < 0 ? "decrease" : "equal"}`] }), DATACELL_TEMPLATE = ({ dataItem }) => (dataItem ? dataItem.fmtValue || dataItem.value ? `<span class="k-pivotgrid-content">${encode(dataItem.fmtValue || dataItem.value)}</span>` : "&nbsp;" : "&nbsp;"), LAYOUT_TABLE = '<table class="k-pivot-layout">' + '<tr>' + '<td>' + '<div class="k-pivot-rowheaders"></div>' + '</td>' + '<td>' + '<div class="k-pivot-table"></div>' + '</td>' + '</tr>' + '</table>'; var AXIS_ROWS = "rows"; var AXIS_COLUMNS = "columns"; var tableStyles = { tableRow: "k-table-row", header: "k-header k-table-th", headerTable: "k-grid-header-table k-table k-table-md", table: "k-table k-table-md", contentTable: "k-grid-table k-table k-table-md", tbody: "k-table-tbody", tableCell: "k-table-td" }; function normalizeMeasures(measure) { var descriptor = typeof measure === "string" ? [{ name: measure }] : measure; var descriptors = toString.call(descriptor) === "[object Array]" ? descriptor : (descriptor !== undefined$1 ? [descriptor] : []); return map(descriptors, function(d) { if (typeof d === "string") { return { name: d }; } return $.extend(true, d, { 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$1 ? [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: JSON.parse(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; } function getScollWidth() { var scrollbar = 0; var div; if (document && document.createElement) { div = document.createElement('div'); div.style.cssText = 'overflow:scroll;overflow-x:hidden;zoom:1;clear:both;display:block'; div.innerHTML = '&nbsp;'; document.body.appendChild(div); scrollbar = div.offsetWidth - div.scrollWidth; document.body.removeChild(div); } return scrollbar; } function loadLocalData(data, params, deferred) { const that = this; const originalData = (that.reader.data(data) || []).slice(0); if (originalData && !that._pristineData) { that._pristineData = originalData; } const columnSettings = that._createSettings(params.columnAxes); const rowSettings = that._createSettings(params.rowAxes); const measures = that.measures(); const dataTree = createDataTree(originalData, rowSettings, columnSettings, measures, { dataField: "aggregate", columnsData: "columns" }, that.filter() || []); const stateArgs = { dataTree: dataTree, columnSettings: columnSettings, rowSettings: rowSettings, columnAxes: params.columnAxes, rowAxes: params.rowAxes, measures: measures.map(function(item) { return item; }), fields: { dataField: "aggregate", columnsData: "columns" }, sort: flattenSortDescriptors(params.sort || []) }; that._saveState(createLocalDataState(stateArgs)); that.trigger(CHANGE); deferred.resolve(); } function flattenSortDescriptors(descriptors) { var result = []; for (var i = 0; i < descriptors.length; i++) { result.push({ dir: descriptors[i].dir, field: descriptors[i].field.split(".").pop() }); } return result; } function createLocalMeasure(field, key, format, aggregate) { var formatFunc = function(value) { return kendo.format(this.format, value); }; var measureMap = { "sum": sumAggregate, "average": averageAggregate, "min": minAggregate, "max": maxAggregate, "count": countAggregate, }; var valueFunc = function(item) { return item[this.field]; }; var measure = { value: valueFunc.bind({ field: field }), aggregate: measureMap[aggregate], caption: key, uniqueName: key, type: 2, name: [key] }; if (format) { measure.aggregate.format = formatFunc.bind({ format: format }); } return measure; } function getIcons(sortIcon, options, pivotOptions) { var sortable = options.sortable, filterable = options.filterable, reorderable = pivotOptions.reorderable, result = ""; if (sortable) { result += sortIcon ? `<span class="k-chip-action">${kendo.ui.icon(sortIcon + "-sm")}</span>` : ''; } if (filterable || sortable) { result += `<span class="k-setting-fieldmenu k-chip-action">${kendo.ui.icon("more-vertical")}</span>`; } if (reorderable) { result += `<span class="k-setting-delete k-chip-action">${kendo.ui.icon("x")}</span>`; } return result; } 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$1) { 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$1, 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$1, hierarchy: "MEASURES" }; } result[result.length] = root; } keys.push(ROW_TOTAL_KEY); } return { keys: keys, tuples: result }; }, _sortMap: function(map, sortDescriptors) { var sortedMaps = []; var sortTree = []; var flattenTree = []; var mapItem; var key; for (key in map) { if (!map[key].directParentName) { sortTree.push($.extend({}, { name: key, parentName: map[key].parentName })); } } //if there are no root this means that something is expanding //and we should only sort that part of the tree if (!sortTree.length) { for (key in map) { sortTree.push($.extend({}, { name: key, parentName: map[key].parentName })); } } fillSortTree(sortTree, map); // fill tree recursive for (var i = 0; i < sortDescriptors.length; i++) { sortItemsTree(sortDescriptors[i].field.split(".").pop(), sortTree, Comparer.create({ field: "name", dir: sortDescriptors[i].dir })); } flattenTree = flatColumns(sortTree); //we need to flatten the structure so the tuples can build correctly for (var j = 0; j < flattenTree.length; j++) { mapItem = map[flattenTree[j].name]; mapItem.index = j; sortedMaps[j] = mapItem; } return sortedMaps; }, _expandedTuples: function(map, expanded, measureAggregators, sortDescriptors) { 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; if (sortDescriptors && sortDescriptors.length && !$.isEmptyObject(map)) { map = this._sortMap(map, sortDescriptors); } 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$1, 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$1, 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, sortDescriptors) { measureAggregators = measureAggregators || []; var rootInfo = this._rootTuples(descriptor.root, measureAggregators); var expandedInfo = this._expandedTuples(map, descriptor.expanded, measureAggregators, sortDescriptors); 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$1 && 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$1 && value !== null) ? value.toString() : value; parentName = name; name = name + "&" + value; key = path + name; column = columns[key] || { index: state.columnIndex, parentName: parentName, name: name, directParentName: path.indexOf("&") !== -1 ? path : "", uniquePath: path + parentName, childrenMap: {}, value: value }; if (path && columns[path] && !columns[path].childrenMap[path + parentName + "&" + value]) { columns[path].childrenMap[path + parentName + "&" + value] = true; } 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$1 ? 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, options.sort ? options.sort : []); rowsInfo = this._asTuples(rows, rowDescriptors, measuresRowAxis ? measureAggregators : [], options.sort ? options.sort : []); 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$1) { 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$1) { return (options.connection || {}).cube; } var connection = options.connection || {}; connection.cube = val; this.options.connection = connection; extend(true, this.transport.options, { connection: connection }); } }); var PivotDataSourceV2 = DataSource.extend({ init: function(options) { var cube = ((options || {}).schema || {}).cube; var schema = { axes: identity, cubes: identity, catalogs: identity, measures: identity, dimensions: identity, hierarchies: identity, levels: identity, members: identity }; if (cube) { this.cubeSchema = $.extend(schema, this._cubeSchema(cube)); } DataSource.fn.init.call(this, extend(true, {}, { schema: this.cubeSchema }, options)); var transportOptions = this.options.transport || {}; if ((this.options.type || "xmla").toLowerCase() === "xmla") { this._online = true; this.transport = new XmlaTransportV2(transportOptions); } else { this.transport = new PivotTransport(this.options.transport || {}, this.transport); } this._columns = normalizeMembers(this.options.columns); this._rows = normalizeMembers(this.options.rows); var measures = this.cubeSchema ? this.cubeSchema.measures() : this.options.measures || []; if (toString.call(measures) === "[object Object]") { this._measuresAxis = measures.axis || "columns"; measures = measures.values || []; } this._measures = normalizeMeasures(measures); }, options: { serverSorting: true, serverPaging: true, serverFiltering: true, serverGrouping: true, serverAggregates: true }, axes: function() { return { columns: normalizeAxis(this.columns()), rows: normalizeAxis(this.rows()) }; }, catalog: function(val) { if (val === undefined$1) { return this.transport.catalog(); } this.transport.catalog(val); this._mergeState({});// clears current state this.read(); }, cube: function(val) { if (val === undefined$1) { return this.transport.cube(); } this.transport.cube(val); this._mergeState({});// clears current state this.read(); }, measuresAxis: function() { return this._measuresAxis || "columns"; }, fetch: function(callback) { var that = this; if (this._data === undefined$1 || this._data.length === 0) { var fn = function() { if (isFunction(callback)) { callback.call(that); } }; return this._query().done(fn); } }, _createSettings: function(axes) { var settings = []; var key; var dimensions = this.cubeSchema.dimensionsSettings(); var displayValueFunc = function(item) { return item[this.key]; }; var sortValueFunc = function(value) { return value; }; for (var i = 0; i < axes.length; i++) { key = axes[i].name[0]; settings.push({ key: key, displayValue: displayValueFunc.bind({ key: key }), sortValue: sortValueFunc, caption: (dimensions[key] || {}).caption || key }); } return settings; }, _cubeSchema: function(cube) { return { dimensionsSettings: function() { return cube.dimensions; }, 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; }, restoreMeasure: function(measures, measure) { for (var i = 0; i < measures.length; i++) { if (!measures[i].aggregate) { measures[i].aggregate = measure.aggregate; measures[i].value = measure.value; measures[i].caption = measure.caption; measures[i].uniqueName = measure.uniqueName; measures[i].type = 2; } } }, measures: function() { var result = []; var measures = cube.measures; for (var key in measures) { result.push(createLocalMeasure(measures[key].field, key, measures[key].format, measures[key].aggregate)); } retu