@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
1,581 lines (1,261 loc) • 258 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__(1357);
/***/ }),
/***/ 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");
/***/ }),
/***/ 1030:
/***/ (function(module, exports) {
module.exports = require("./kendo.selectable");
/***/ }),
/***/ 1043:
/***/ (function(module, exports) {
module.exports = require("./kendo.filtermenu");
/***/ }),
/***/ 1142:
/***/ (function(module, exports) {
module.exports = require("./kendo.resizable");
/***/ }),
/***/ 1143:
/***/ (function(module, exports) {
module.exports = require("./kendo.window");
/***/ }),
/***/ 1196:
/***/ (function(module, exports) {
module.exports = require("./kendo.columnsorter");
/***/ }),
/***/ 1198:
/***/ (function(module, exports) {
module.exports = require("./kendo.editable");
/***/ }),
/***/ 1203:
/***/ (function(module, exports) {
module.exports = require("./kendo.pager");
/***/ }),
/***/ 1357:
/***/ (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_require__(1196),
__webpack_require__(1198),
__webpack_require__(1143),
__webpack_require__(1043),
__webpack_require__(1030),
__webpack_require__(1142),
__webpack_require__(1358),
__webpack_require__(1203)
], __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: "treelist",
name: "TreeList",
category: "web",
description: "The TreeList widget displays self-referencing data and offers rich support for interacting with data, sorting, filtering, and selection.",
depends: [ "dom", "data", "pager" ],
features: [ {
id: "treelist-sorting",
name: "Sorting",
description: "Support for column sorting",
depends: [ "columnsorter" ]
}, {
id: "treelist-filtering",
name: "Filtering",
description: "Support for record filtering",
depends: [ "filtermenu" ]
}, {
id: "treelist-editing",
name: "Editing",
description: "Support for record editing",
depends: [ "editable", "window" ]
}, {
id: "treelist-selection",
name: "Selection",
description: "Support for row selection",
depends: [ "selectable" ]
}, {
id: "treelist-column-resize",
name: "Column resizing",
description: "Support for column resizing",
depends: [ "resizable" ]
}, {
id: "treelist-dragging",
name: "Drag & Drop",
description: "Support for drag & drop of rows",
depends: [ "treeview.draganddrop" ]
}, {
id: "treelist-excel-export",
name: "Excel export",
description: "Export data as Excel spreadsheet",
depends: [ "excel" ]
}, {
id: "treelist-pdf-export",
name: "PDF export",
description: "Export data as PDF",
depends: [ "pdf", "drawing" ]
}, {
id: "treelist-paging",
name: "Paging",
description: "Support for treelist paging",
depends: [ "pager" ]
} ]
};
(function($, undefined) {
var data = kendo.data;
var kendoDom = kendo.dom;
var kendoDomElement = kendoDom.element;
var kendoTextElement = kendoDom.text;
var kendoHtmlElement = kendoDom.html;
var outerWidth = kendo._outerWidth;
var keys = kendo.keys;
var outerHeight = kendo._outerHeight;
var ui = kendo.ui;
var DataBoundWidget = ui.DataBoundWidget;
var DataSource = data.DataSource;
var ObservableArray = data.ObservableArray;
var Query = data.Query;
var Model = data.Model;
var browser = kendo.support.browser;
var kendoTemplate = kendo.template;
var activeElement = kendo._activeElement;
var isArray = $.isArray;
var extend = $.extend;
var proxy = $.proxy;
var map = $.map;
var grep = $.grep;
var inArray = $.inArray;
var isPlainObject = $.isPlainObject;
var push = Array.prototype.push;
var STRING = "string";
var CHANGE = "change";
var ITEM_CHANGE = "itemChange";
var ERROR = "error";
var PROGRESS = "progress";
var DOT = ".";
var NS = ".kendoTreeList";
var CLICK = "click";
var MOUSEDOWN = "mousedown";
var BEFORE_EDIT = "beforeEdit";
var EDIT = "edit";
var PAGE = "page";
var PAGE_CHANGE = "pageChange";
var SAVE = "save";
var SAVE_CHANGES = "saveChanges";
var EXPAND = "expand";
var COLLAPSE = "collapse";
var CELL_CLOSE = "cellClose";
var REMOVE = "remove";
var DATA_CELL = "td:not(.k-group-cell):not(.k-hierarchy-cell):visible";
var DATABINDING = "dataBinding";
var DATABOUND = "dataBound";
var CANCEL = "cancel";
var TABINDEX = "tabIndex";
var FILTERMENUINIT = "filterMenuInit";
var FILTERMENUOPEN = "filterMenuOpen";
var COLUMNHIDE = "columnHide";
var COLUMNSHOW = "columnShow";
var HEADERCELLS = "th.k-header";
var COLUMNREORDER = "columnReorder";
var COLUMNRESIZE = "columnResize";
var COLUMNMENUINIT = "columnMenuInit";
var COLUMNMENUOPEN = "columnMenuOpen";
var COLUMNLOCK = "columnLock";
var COLUMNUNLOCK = "columnUnlock";
var PARENTIDFIELD = "parentId";
var DRAGSTART = "dragstart";
var DRAG = "drag";
var DROP = "drop";
var DRAGEND = "dragend";
var NAVROW = "tr:visible";
var NAVCELL = "td:visible";
var NAVHEADER = "th:visible";
var NORECORDSCLASS = "k-grid-norecords";
var ITEMROW = "tr:not(.k-footer-template):visible";
var FIRSTNAVITEM = NAVROW + " > td:first:visible";
var LASTITEMROW = ITEMROW + ":last";
var isRtl = false;
var HEIGHT = "height";
var INCELL = "incell";
var INLINE = "inline";
var POPUP = "popup";
var TABLE = "table";
var classNames = {
wrapper: "k-treelist k-grid k-widget k-display-block",
header: "k-header",
button: "k-button",
alt: "k-alt",
editCell: "k-edit-cell",
editRow: "k-grid-edit-row",
dirtyCell: "k-dirty-cell",
group: "k-treelist-group",
gridToolbar: "k-grid-toolbar",
gridHeader: "k-grid-header",
gridHeaderWrap: "k-grid-header-wrap",
gridContent: "k-grid-content",
gridContentWrap: "k-grid-content",
gridFilter: "k-grid-filter",
footerTemplate: "k-footer-template",
focused: "k-state-focused",
loading: "k-i-loading",
refresh: "k-i-reload",
retry: "k-request-retry",
selected: "k-state-selected",
status: "k-status",
link: "k-link",
withIcon: "k-with-icon",
filterable: "k-filterable",
icon: "k-icon",
iconFilter: "k-i-filter",
iconCollapse: "k-i-collapse",
iconExpand: "k-i-expand",
iconHidden: "k-i-none",
iconPlaceHolder: "k-icon k-i-none",
input: "k-input",
dropPositions: "k-i-insert-up k-i-insert-down k-i-plus k-i-insert-middle",
dropTop: "k-i-insert-up",
dropBottom: "k-i-insert-down",
dropAdd: "k-i-plus",
dropMiddle: "k-i-insert-middle",
dropDenied: "k-i-cancel",
dragStatus: "k-drag-status",
dragClue: "k-drag-clue",
dragClueText: "k-clue-text"
};
var defaultCommands = {
create: {
imageClass: "k-i-plus",
className: "k-grid-add",
methodName: "addRow"
},
createchild: {
imageClass: "k-i-plus",
className: "k-grid-add",
methodName: "addRow"
},
destroy: {
imageClass: "k-i-close",
className: "k-grid-delete",
methodName: "removeRow"
},
edit: {
imageClass: "k-i-edit",
className: "k-grid-edit",
methodName: "editRow"
},
update: {
imageClass: "k-i-check",
className: "k-primary k-grid-update",
methodName: "saveRow"
},
canceledit: {
imageClass: "k-i-cancel",
className: "k-grid-cancel",
methodName: "_cancelEdit"
},
cancel: {
imageClass: "k-icon k-i-cancel",
text: "Cancel changes",
className: "k-grid-cancel-changes",
methodName: "cancelChanges"
},
save: {
imageClass: "k-icon k-i-check",
text: "Save changes",
className: "k-grid-save-changes",
methodName: "saveChanges"
},
excel: {
imageClass: "k-i-file-excel",
className: "k-grid-excel",
methodName: "saveAsExcel"
},
pdf: {
imageClass: "k-i-file-pdf",
className: "k-grid-pdf",
methodName: "saveAsPDF"
}
};
var TreeView = kendo.Class.extend({
init: function(data, options) {
var that = this;
that.data = data || [];
that.options = extend(that.options, options);
},
options: {
defaultParentId: null,
idField: "id",
parentIdField: PARENTIDFIELD
},
childrenMap: function() {
var that = this;
var childrenMap = {};
var dataLength = that.data.length;
var dataItem;
var dataItemId;
var dataItemParentId;
var idField = that.options.idField;
var parentIdField = that.options.parentIdField;
if (that._childrenMap) {
return that._childrenMap;
}
for (var i = 0; i < dataLength; i++) {
dataItem = this.data[i];
dataItemId = dataItem[idField];
dataItemParentId = dataItem[parentIdField];
childrenMap[dataItemId] = childrenMap[dataItemId] || [];
childrenMap[dataItemParentId] = childrenMap[dataItemParentId] || [];
childrenMap[dataItemParentId].push(dataItem);
}
that._childrenMap = childrenMap;
return childrenMap;
},
idsMap: function() {
var that = this;
var idsMap = {};
var data = that.data;
var dataLength = data.length;
var dataItem;
var idField = that.options.idField;
if (that._idMap) {
return that._idMap;
}
for (var i = 0; i < dataLength; i++) {
dataItem = data[i];
idsMap[dataItem[idField]] = dataItem;
}
that.idsMap = idsMap;
return idsMap;
},
dataMaps: function() {
var that = this;
var childrenMap = {};
var data = that.data;
var dataLength = data.length;
var idsMap = {};
var dataItem;
var dataItemId;
var dataItemParentId;
var idField = that.options.idField;
var parentIdField = that.options.parentIdField;
if (that._dataMaps) {
return that._dataMaps;
}
for (var i = 0; i < dataLength; i++) {
dataItem = data[i];
dataItemId = dataItem[idField];
dataItemParentId = dataItem[parentIdField];
idsMap[dataItemId] = dataItem;
childrenMap[dataItemId] = childrenMap[dataItemId] || [];
childrenMap[dataItemParentId] = childrenMap[dataItemParentId] || [];
childrenMap[dataItemParentId].push(dataItem);
}
that._dataMaps = {
children: childrenMap,
ids: idsMap
};
return that._dataMaps;
},
rootNodes: function() {
var that = this;
var data = that.data;
var defaultParentId = that.options.defaultParentId;
var dataLength = data.length;
var rootNodes = [];
var dataItem;
var parentIdField = that.options.parentIdField;
for (var i = 0; i < dataLength; i++) {
dataItem = data[i];
if (dataItem[parentIdField] === defaultParentId) {
rootNodes.push(dataItem);
}
}
return rootNodes;
},
removeCollapsedSubtreesFromRootNodes: function(options) {
options = options || {};
var that = this;
var rootNodes = that.rootNodes();
var result = [];
var prunedTree;
that._childrenMap = options.childrenMap = options.childrenMap || that.childrenMap();
options.maxDepth = options.maxDepth || Infinity;
for (var i = 0; i < rootNodes.length; i++) {
prunedTree = that.removeCollapsedSubtrees(rootNodes[i], options);
result = result.concat(prunedTree);
}
return result;
},
removeCollapsedSubtrees: function(rootNode, options) {
options = options || {};
var that = this;
var result = [];
var childIdx;
var prunedTree;
var childrenMap = options.childrenMap || {};
var maxDepth = options.maxDepth || Infinity;
var idField = that.options.idField;
var children = childrenMap[rootNode[idField]] || [];
var expanded = isUndefined(rootNode.expanded) ? options.expanded : rootNode.expanded;
result.push(rootNode);
if (children && expanded) {
for (childIdx = 0; childIdx < children.length; childIdx++) {
if (result.length >= maxDepth) {
break;
}
prunedTree = that.removeCollapsedSubtrees(children[childIdx], options);
result = result.concat(prunedTree);
}
}
return result;
}
});
var TreeQuery = function(data) {
this.data = data || [];
};
TreeQuery.prototype = new Query();
TreeQuery.prototype.constructor = TreeQuery;
TreeQuery.process = function(data, options, inPlace) {
options = options || {};
var query = new TreeQuery(data);
var group = options.group;
var sort = Query.normalizeGroup(group || []).concat(Query.normalizeSort(options.sort || []));
var filterCallback = options.filterCallback;
var filter = options.filter;
var skip = options.skip;
var take = options.take;
var total;
var childrenMap;
var filteredChildrenMap;
var view;
var prunedData;
if (sort && inPlace) {
query = query.sort(sort, undefined, undefined, inPlace);
}
if (filter) {
query = query.filter(filter);
if (filterCallback) {
query = filterCallback(query);
}
total = query.toArray().length;
}
if (sort && !inPlace) {
query = query.sort(sort);
if (group) {
data = query.toArray();
}
}
if (options.processFromRootNodes) {
view = new TreeView(query.toArray(), options);
if (filter) {
filteredChildrenMap = view.childrenMap();
}
prunedData = view.removeCollapsedSubtreesFromRootNodes({
// filtering or sorting requires changes to childrenMap
childrenMap: filter || (sort && sort.length) ? undefined : options.childrenMap,
expanded: options.expanded,
maxDepth: (skip + take) || Infinity
});
childrenMap = view.childrenMap();
query = new TreeQuery(prunedData);
}
if (skip !== undefined && take !== undefined) {
query = query.range(skip, take);
}
if (group) {
query = query.group(group, data);
}
return {
total: total,
data: query.toArray(),
childrenMap: childrenMap,
filteredChildrenMap: filteredChildrenMap
};
};
var TreeListModel = Model.define({
id: "id",
parentId: PARENTIDFIELD,
fields: {
id: { type: "number" },
parentId: { type: "number", nullable: true }
},
init: function(value) {
Model.fn.init.call(this, value);
this._loaded = false;
if (!this.parentIdField) {
this.parentIdField = PARENTIDFIELD;
}
this.parentId = this.get(this.parentIdField);
},
accept: function(data) {
Model.fn.accept.call(this, data);
this.parentId = this.get(this.parentIdField);
},
set: function(field, value, initiator) {
if (field == PARENTIDFIELD && this.parentIdField != PARENTIDFIELD) {
this[this.parentIdField] = value;
}
Model.fn.set.call(this, field, value, initiator);
if (field == this.parentIdField) {
this.parentId = this.get(this.parentIdField);
}
},
loaded: function(value) {
if (value !== undefined) {
this._loaded = value;
} else {
return this._loaded;
}
},
shouldSerialize: function(field) {
return Model.fn.shouldSerialize.call(this, field) && field !== "_loaded" && field != "_error" && field != "_edit" && !(this.parentIdField !== "parentId" && field === "parentId");
}
});
TreeListModel.parentIdField = PARENTIDFIELD;
TreeListModel.define = function(base, options) {
if (options === undefined) {
options = base;
base = TreeListModel;
}
var parentId = options.parentId || PARENTIDFIELD;
options.parentIdField = parentId;
var model = Model.define(base, options);
if (parentId) {
model.parentIdField = parentId;
}
return model;
};
function is(field) {
return function(object) {
return object[field];
};
}
function not(func) {
return function(object) {
return !func(object);
};
}
var TreeListDataSource = DataSource.extend({
init: function(options) {
options = options || {};
var that = this;
that._dataMaps = that._getDataMaps();
options.schema = extend(true, {}, {
modelBase: TreeListModel,
model: TreeListModel
}, options.schema);
DataSource.fn.init.call(this, options);
},
_addRange: function() {
// empty override for performance - the treelist does not support virtualization
},
_createNewModel: function(data) {
var that = this;
var model = {};
var fromModel = data instanceof Model;
var parentIdField = this._modelParentIdField();
if (fromModel) {
model = data;
}
model = DataSource.fn._createNewModel.call(this, model);
if (!fromModel) {
if (data.parentId) {
data[model.parentIdField] = data.parentId;
} else if (that._isPageable() && data[parentIdField]) {
data[model.parentIdField] = data[parentIdField];
}
model.accept(data);
}
return model;
},
_shouldWrap: function() {
return true;
},
_push: function(result, operation) {
var data = DataSource.fn._readData.call(this, result);
if (!data) {
data = result;
}
this[operation](data);
},
_getData: function() {
// do not use .data(), which wraps the data items
return this._data || [];
},
_readData: function(newData) {
var that = this;
var data = that._isPageable() ? that._getData().toJSON() : that.data();
newData = DataSource.fn._readData.call(this, newData);
this._replaceData(((data.toJSON ? data.toJSON() : data)).concat(newData), data);
if (newData instanceof ObservableArray) {
return newData;
}
return data;
},
_replaceData: function(source, target) {
var sourceLength = source.length;
for (var i = 0; i < sourceLength; i++) {
target[i] = source[i];
}
target.length = sourceLength;
},
_readAggregates: function(data) {
var result = extend(this._aggregateResult, this.reader.aggregates(data));
if ("" in result) {
result[this._defaultParentId()] = result[""];
delete result[""];
}
return result;
},
read: function(data) {
var that = this;
if (that._isPageable()) {
that._dataMaps = {};
if (!that._modelOptions().expanded) {
that._skip = 0;
that._page = 1;
that._collapsedTotal = undefined;
}
}
return DataSource.fn.read.call(that, data);
},
remove: function(root) {
this._removeChildData(root);
this._removeFromDataMaps(root);
DataSource.fn.remove.call(this, root);
},
_removeChildData: function(model, removePristine) {
var that = this;
var pageable = that._isPageable();
var data = pageable ? this._getData() : this.data();
var childrenMap = pageable ? that._getChildrenMap() || that.childrenMap(data) : that._childrenMap(data);
var items = this._subtree(childrenMap, model.id);
var shouldRemovePristine = isUndefined(removePristine) ? false : removePristine;
var removedItems = this._removeItems(items, shouldRemovePristine);
that._removeFromDataMaps(removedItems);
},
pushDestroy: function(items) {
var that = this;
if (!isArray(items)) {
items = [items];
}
for (var i = 0; i < items.length; i++) {
that._removeChildData(items[i], true);
that._removeFromDataMaps(items[i]);
}
DataSource.fn.pushDestroy.call(that, items);
},
insert: function(index, model) {
var that = this;
var newModel = that._createNewModel(model);
that._insertInDataMaps(newModel);
return DataSource.fn.insert.call(that, index, newModel);
},
_filterCallback: function(query) {
var that = this;
var i, item;
var map = {};
var result = [];
var data = query.toArray();
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var pageable = that._isPageable();
var parentSubtree = [];
var parent;
for (i = 0; i < data.length; i++) {
item = data[i];
if (pageable) {
// return view from root nodes to child nodes
parentSubtree = [];
if (!map[item[idField]]) {
map[item[idField]] = true;
parentSubtree.push(item);
}
parent = that._parentNode(item);
while (parent) {
if (!map[parent[idField]]) {
map[parent[idField]] = true;
parentSubtree.unshift(parent);
parent = that._parentNode(parent);
} else {
// the parent chain is already processed
break;
}
}
if (parentSubtree.length) {
result = result.concat(parentSubtree);
}
} else {
while (item) {
if (!map[item[idField]]) {
map[item[idField]] = true;
result.push(item);
}
if (!map[item[parentIdField]]) {
map[item[parentIdField]] = true;
item = this.parentNode(item);
if (item) {
result.push(item);
}
} else {
break;
}
}
}
}
return new Query(result);
},
_subtree: function(map, id) {
var that = this;
var result = map[id] || [];
var defaultParentId = that._defaultParentId();
var idField = that._modelIdField();
for (var i = 0, len = result.length; i < len; i++) {
if (result[i][idField] !== defaultParentId) {
result = result.concat(that._subtree(map, result[i][idField]));
}
}
return result;
},
// builds hash id -> children
_childrenMap: function(data) {
var map = {};
var i, item, id, parentId;
data = this._observeView(data);
for (i = 0; i < data.length; i++) {
item = data[i];
id = item.id;
parentId = item.parentId;
map[id] = map[id] || [];
map[parentId] = map[parentId] || [];
map[parentId].push(item);
}
return map;
},
childrenMap: function(data) {
var view = this._createTreeView(data);
var map = view.childrenMap();
return map;
},
_getChildrenMap: function() {
var that = this;
var dataMaps = that._getDataMaps();
return dataMaps.children;
},
_initIdsMap: function(data) {
var that = this;
var dataMaps = that._getDataMaps();
if (isUndefined(dataMaps.ids)) {
dataMaps.ids = that._idsMap(data);
}
return dataMaps.ids;
},
_idsMap: function(data) {
var view = this._createTreeView(data);
var map = view.idsMap();
return map;
},
_getIdsMap: function() {
var that = this;
var dataMaps = that._getDataMaps();
return dataMaps.ids || {};
},
_getFilteredChildrenMap: function() {
var that = this;
var dataMaps = that._getDataMaps();
return dataMaps.filteredChildren;
},
_setFilteredChildrenMap: function(map) {
var that = this;
var dataMaps = that._getDataMaps();
dataMaps.filteredChildren = map;
},
_initDataMaps: function(data) {
var that = this;
var view = that._createTreeView(data);
that._dataMaps = view.dataMaps();
return that._dataMaps;
},
_initChildrenMapForParent: function(parent) {
var that = this;
var data = that._getData();
var childrenMap = that._getChildrenMap();
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var parentId = (parent || {})[idField];
if (childrenMap && parent) {
childrenMap[parentId] = [];
for (var i = 0; i < data.length; i++) {
if (data[i][parentIdField] === parentId) {
childrenMap[parentId].push(data[i]);
}
}
}
},
_getDataMaps: function() {
var that = this;
that._dataMaps = that._dataMaps || {};
return that._dataMaps;
},
_createTreeView: function(data, options) {
var view = new TreeView(data, extend(options, this._defaultTreeModelOptions()));
return view;
},
_defaultTreeModelOptions: function() {
var that = this;
var modelOptions = that._modelOptions();
return {
defaultParentId: that._defaultParentId(),
idField: that._modelIdField(),
parentIdField: that._modelParentIdField(),
expanded: modelOptions.expanded
};
},
_defaultDataItemType: function() {
return this.reader.model || kendo.data.ObservableObject;
},
_calculateAggregates: function(data, options) {
options = options || {};
var that = this;
var result = {};
var item, subtree, i;
var filter = options.filter;
var skip = options.skip;
var take = options.take;
var maxDepth = !isUndefined(skip) && !isUndefined(take) ? (skip + take) : Infinity;
var pageable = that._isPageable();
var filteredChildrenMap = options.filteredChildrenMap;
var childrenMap = options.childrenMap;
var pageableChildrenMap;
if (pageable) {
if (isUndefined(options.aggregate)) {
return result;
}
if (filteredChildrenMap) {
pageableChildrenMap = filteredChildrenMap;
} else if (childrenMap) {
pageableChildrenMap = childrenMap;
} else {
pageableChildrenMap = that.childrenMap(that._getData());
}
}
if (!pageable && filter) {
data = Query.process(data, {
filter: filter,
filterCallback: proxy(this._filterCallback, this)
}).data;
}
var map = pageable ? pageableChildrenMap : that._childrenMap(data);
// calculate aggregates for each subtree
result[this._defaultParentId()] = new Query(this._subtree(map, this._defaultParentId())).aggregate(options.aggregate);
for (i = 0; i < data.length; i++) {
if (i >= maxDepth) {
break;
}
item = data[i];
subtree = this._subtree(map, item.id);
result[item.id] = new Query(subtree).aggregate(options.aggregate);
}
return result;
},
_queryProcess: function(data, options) {
var that = this;
var result = {};
options = options || {};
options.filterCallback = proxy(this._filterCallback, this);
if (that._isPageable()) {
return that._processPageableQuery(data, options);
} else {
var defaultParentId = this._defaultParentId();
result = Query.process(data, options);
var map = this._childrenMap(result.data);
var hasLoadedChildren, i, item, children;
data = map[defaultParentId] || [];
for (i = 0; i < data.length; i++) {
item = data[i];
if (item.id === defaultParentId) {
continue;
}
children = map[item.id];
hasLoadedChildren = !!(children && children.length);
if (!item.loaded()) {
item.loaded(hasLoadedChildren || !item.hasChildren);
}
if (item.loaded() || item.hasChildren !== true) {
item.hasChildren = hasLoadedChildren;
}
if (hasLoadedChildren) {
//cannot use splice due to IE8 bug
data = data.slice(0, i + 1).concat(children, data.slice(i + 1));
}
}
result.data = data;
}
return result;
},
_processPageableQuery: function(data, options) {
var that = this;
var dataMaps = that._getDataMaps();
var result;
var filteredChildrenMap;
if (that._getData() !== data || !dataMaps.children || !dataMaps.ids) {
dataMaps = that._initDataMaps(that._getData());
}
options.childrenMap = dataMaps.children || {};
options.idsMap = dataMaps.ids || {};
result = that._processTreeQuery(data, options);
that._replaceWithObservedData(result.data, data);
that._processDataItemsState(result.data, result.childrenMap);
that._replaceItemsInDataMaps(result.data);
result.dataToAggregate = that._dataToAggregate(result.data, options);
if (options.filter) {
filteredChildrenMap = result.filteredChildrenMap;
that._replaceInMapWithObservedData(filteredChildrenMap, data);
that._setFilteredChildrenMap(filteredChildrenMap);
options.filteredChildrenMap = filteredChildrenMap;
}
return result;
},
_dataToAggregate: function(data) {
var that = this;
var firstDataItem = data[0] || {};
var firstItemParents = that._parentNodes(firstDataItem);
var dataToAggregate = firstItemParents.concat(data);
return dataToAggregate;
},
_replaceItemsInDataMaps: function(observableArray) {
var that = this;
var view = isArray(observableArray) ? observableArray : [observableArray];
var itemType = that._defaultDataItemType();
var defaultParentId = that._defaultParentId();
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var dataMaps = that._getDataMaps();
var item;
var parents;
var directParent;
for (var viewIndex = 0; viewIndex < view.length; viewIndex++) {
item = view[viewIndex];
if (!(item instanceof itemType)) {
continue;
}
that._insertInIdsMap(item);
parents = that._parentNodes(item);
directParent = parents && parents.length ? parents[parents.length - 1] : undefined;
if (item[parentIdField] === defaultParentId) {
that._replaceInMap(dataMaps.children, defaultParentId, item, itemType);
} else if (directParent) {
that._replaceInMap(dataMaps.children, directParent[idField], item, itemType);
}
}
},
_replaceInMap: function(map, id, replacement, itemType) {
var idField = this._modelIdField();
map[id] = map[id] || [];
itemType = itemType || this._defaultDataItemType();
var itemInArray = map[id].filter(function(element) {
return replacement[idField] === element[idField];
})[0];
var itemIndex = itemInArray ? map[id].indexOf(itemInArray) : -1;
if (itemIndex !== -1 && !(itemInArray instanceof itemType)) {
map[id][itemIndex] = replacement;
}
},
_replaceWithObservedData: function(dataToReplace, replacementArray) {
var that = this;
var idsMap = that._getDataMaps().ids || {};
var idField = that._modelIdField();
var itemType = that._defaultDataItemType();
var itemToReplace;
var itemToReplaceId;
var dataItem;
var dataItemIndex;
var observableItem;
for (var i = 0; i < dataToReplace.length; i++) {
itemToReplace = dataToReplace[i];
itemToReplaceId = itemToReplace[idField];
if (!(itemToReplace instanceof itemType)) {
if (!(idsMap[itemToReplaceId] instanceof itemType)) {
dataItem = that._getById(itemToReplaceId);
dataItemIndex = replacementArray.indexOf(dataItem);
if (dataItem && dataItemIndex !== -1) {
observableItem = replacementArray.at(dataItemIndex);
dataToReplace[i] = observableItem;
}
} else {
dataToReplace[i] = idsMap[itemToReplaceId];
}
}
}
},
_replaceInMapWithObservedData: function(map, replacementArray) {
var that = this;
for (var key in map) {
that._replaceWithObservedData(map[key], replacementArray);
}
},
_insertInDataMaps: function(item) {
var that = this;
if (that._isPageable()) {
that._insertInIdsMap(item);
that._insertInChildrenMap(item);
}
},
_insertInIdsMap: function(item) {
var that = this;
var idsMap = that._getIdsMap();
var idField = that._modelIdField();
if (!isUndefined(item[idField])) {
idsMap[item[idField]] = item;
}
},
_insertInChildrenMap: function(item, index) {
var that = this;
var childrenMap = that._getChildrenMap() || {};
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var itemId = item[idField];
var parentId = item[parentIdField];
index = index || 0;
childrenMap[itemId] = childrenMap[itemId] || [];
childrenMap[parentId] = childrenMap[parentId] || [];
childrenMap[parentId].splice(index, 0, item);
},
_removeFromDataMaps: function(items) {
var that = this;
items = isArray(items) ? items : [items];
if (that._isPageable()) {
for (var i = 0; i < items.length; i++) {
that._removeFromIdsMap(items[i]);
that._removeFromChildrenMap(items[i]);
}
}
},
_removeFromIdsMap: function(item) {
var that = this;
var idsMap = that._getIdsMap();
var idField = that._modelIdField();
if (!isUndefined(item[idField])) {
idsMap[item[idField]] = undefined;
}
},
_removeFromChildrenMap: function(item) {
var that = this;
var childrenMap = that._getChildrenMap() || {};
var parentIdField = that._modelParentIdField();
var parentId = item[parentIdField];
childrenMap[parentId] = childrenMap[parentId] || [];
var itemIndex = that._indexInChildrenMap(item);
if (itemIndex !== -1) {
childrenMap[parentId].splice(itemIndex, 1);
}
},
_indexInChildrenMap: function(item) {
var that = this;
return that._itemIndexInMap(item, that._getChildrenMap());
},
_itemIndexInMap: function(item, dataMap) {
var that = this;
var map = dataMap || {};
var parentIdField = that._modelParentIdField();
var parentId = item[parentIdField];
map[parentId] = map[parentId] || [];
var itemInArray = map[parentId].filter(function(element) {
return item.uid === element.uid;
})[0];
var itemIndex = itemInArray ? map[parentId].indexOf(itemInArray) : -1;
return itemIndex;
},
_getById: function(id) {
var that = this;
var idField = that._modelIdField();
var data = that._getData();
for (var i = 0; i < data.length; i++) {
if (data[i][idField] === id) {
return data[i];
}
}
},
_isLastItemInView: function(dataItem) {
var view = this.view();
return view.length && view[view.length - 1] === dataItem;
},
_defaultPageableQueryOptions: function() {
var that = this;
var dataMaps = that._getDataMaps();
var options = {
skip: that.skip(),
take: that.take(),
page: that.page(),
pageSize: that.pageSize(),
sort: that.sort(),
filter: that.filter(),
group: that.group(),
aggregate: that.aggregate(),
filterCallback: proxy(that._filterCallback, that),
childrenMap: dataMaps.children,
idsMap: dataMaps.ids
};
return options;
},
_isPageable: function() {
var pageSize = this.pageSize();
return (!isUndefined(pageSize) && pageSize > 0 && !this.options.serverPaging);
},
_updateTotalForAction: function(action, items) {
var that = this;
DataSource.fn._updateTotalForAction.call(that, action, items);
if (that._isPageable()) {
that._updateCollapsedTotalForAction(action, items);
}
},
_updateCollapsedTotalForAction: function(action, items) {
var that = this;
var total = parseInt(that._collapsedTotal, 10);
if (!isNumber(that._collapsedTotal)) {
that._calculateCollapsedTotal();
return;
}
if (action === "add") {
total += items.length;
} else if (action === "remove") {
total -= items.length;
} else if (action !== "itemchange" && action !== "sync" && !that.options.serverPaging) {
total = that._calculateCollapsedTotal();
} else if (action === "sync") {
total = that._calculateCollapsedTotal();
}
that._collapsedTotal = total;
},
_setFilterTotal: function(filterTotal, setDefaultValue) {
var that = this;
DataSource.fn._setFilterTotal.call(that, filterTotal, setDefaultValue);
that._setFilterCollapsedTotal(filterTotal);
},
_setFilterCollapsedTotal: function(filterTotal) {
var that = this;
if (!that.options.serverFiltering) {
if (filterTotal !== undefined) {
that._collapsedTotal = filterTotal;
} else {
if (that._getFilteredChildrenMap()) {
that._calculateCollapsedTotal();
}
that._setFilteredChildrenMap(undefined);
}
}
},
collapsedTotal: function() {
var that = this;
if (!isUndefined(that._collapsedTotal)) {
return that._collapsedTotal;
}
return that._calculateCollapsedTotal();
},
_calculateCollapsedTotal: function() {
var that = this;
var data = that._dataWithoutCollapsedSubtrees();
if (data.length) {
that._collapsedTotal = data.length;
}
return that._collapsedTotal;
},
_dataWithoutCollapsedSubtrees: function() {
return this._removeCollapsedSubtrees(this._getData());
},
_removeCollapsedSubtrees: function(data) {
var that = this;
var view = that._createTreeView(data);
var result = view.removeCollapsedSubtreesFromRootNodes({
expanded: that._modelOptions().expanded,
childrenMap: that._getChildrenMap()
});
return result;
},
_processTreeQuery: function(data, options) {
var result = TreeQuery.process(data, extend(options, this._defaultTreeModelOptions(), {
processFromRootNodes: true
}));
return result;
},
_processDataItemsState: function(data, childrenMap) {
var dataLength = data.length;
var i;
for (i = 0; i < dataLength; i++) {
this._processDataItemState(data[i], childrenMap);
}
},
_processDataItemState: function(dataItem, childrenMap) {
var defaultParentId = this._defaultParentId();
if (dataItem.id === defaultParentId) {
return;
}
var children = childrenMap[dataItem.id] || [];
var hasLoadedChildren = !!(children && children.length);
if (!dataItem.loaded) {
return;
}
if (!dataItem.loaded()) {
dataItem.loaded(hasLoadedChildren || !dataItem.hasChildren);
}
if (dataItem.loaded() || dataItem.hasChildren !== true) {
dataItem.hasChildren = hasLoadedChildren;
}
},
_queueRequest: function(options, callback) {
// allow simultaneous requests (loading multiple items at the same time)
callback.call(this);
},
_modelLoaded: function(id) {
var model = this.get(id);
model.loaded(true);
model.hasChildren = this.childNodes(model).length > 0;
},
_modelError: function(id, e) {
this.get(id)._error = e;
},
success: function(data, requestParams) {
if (!requestParams || typeof requestParams.id == "undefined") {