UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

651 lines (649 loc) • 29.2 kB
/** * DevExtreme (ui/tree_list/ui.tree_list.data_source_adapter.js) * Version: 18.2.18 * Build date: Tue Oct 18 2022 * * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; var _uiTree_list = require("./ui.tree_list.core"); var _uiTree_list2 = _interopRequireDefault(_uiTree_list); var _ui = require("../widget/ui.errors"); var _ui2 = _interopRequireDefault(_ui); var _common = require("../../core/utils/common"); var _common2 = _interopRequireDefault(_common); var _type = require("../../core/utils/type"); var _type2 = _interopRequireDefault(_type); var _iterator = require("../../core/utils/iterator"); var _data = require("../../core/utils/data"); var _data2 = _interopRequireDefault(_data); var _extend = require("../../core/utils/extend"); var _uiGrid_core = require("../grid_core/ui.grid_core.utils"); var _uiGrid_core2 = _interopRequireDefault(_uiGrid_core); var _array_store = require("../../data/array_store"); var _array_store2 = _interopRequireDefault(_array_store); var _query = require("../../data/query"); var _query2 = _interopRequireDefault(_query); var _uiGrid_core3 = require("../grid_core/ui.grid_core.data_source_adapter"); var _uiGrid_core4 = _interopRequireDefault(_uiGrid_core3); var _deferred = require("../../core/utils/deferred"); var _store_helper = require("../../data/store_helper"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj } } var DEFAULT_KEY_EXPRESSION = "id"; var DataSourceAdapterTreeList = _uiGrid_core4.default.inherit(function() { var getChildKeys = function(that, keys) { var childKeys = []; keys.forEach(function(key) { var node = that.getNodeByKey(key); node && node.children.forEach(function(child) { childKeys.push(child.key) }) }); return childKeys }; return { _createKeyGetter: function() { var keyExpr = this.getKeyExpr(); return _data2.default.compileGetter(keyExpr) }, _createKeySetter: function() { var keyExpr = this.getKeyExpr(); if (_type2.default.isFunction(keyExpr)) { return keyExpr } return _data2.default.compileSetter(keyExpr) }, _createParentIdGetter: function() { return _data2.default.compileGetter(this.option("parentIdExpr")) }, createParentIdSetter: function() { var parentIdExpr = this.option("parentIdExpr"); if (_type2.default.isFunction(parentIdExpr)) { return parentIdExpr } return _data2.default.compileSetter(parentIdExpr) }, _createItemsGetter: function() { return _data2.default.compileGetter(this.option("itemsExpr")) }, _createHasItemsGetter: function() { var hasItemsExpr = this.option("hasItemsExpr"); return hasItemsExpr && _data2.default.compileGetter(hasItemsExpr) }, _createHasItemsSetter: function() { var hasItemsExpr = this.option("hasItemsExpr"); if (_type2.default.isFunction(hasItemsExpr)) { return hasItemsExpr } return hasItemsExpr && _data2.default.compileSetter(hasItemsExpr) }, _updateIndexByKeyObject: function(items) { var that = this; that._indexByKey = {}; (0, _iterator.each)(items, function(index, item) { that._indexByKey[item.key] = index }) }, _calculateHasItems: function(node, options) { var hasItems, that = this, parentIds = options.storeLoadOptions.parentIds; if (that._hasItemsGetter && (parentIds || !options.storeLoadOptions.filter)) { hasItems = that._hasItemsGetter(node.data) } if (void 0 === hasItems) { if (!that._isChildrenLoaded[node.key] && options.remoteOperations.filtering && parentIds) { hasItems = true } else { hasItems = node.hasChildren } } return !!hasItems }, _createVisibleItemsByNodes: function(nodes, options) { var that = this, result = []; for (var i = 0; i < nodes.length; i++) { if (nodes[i].visible) { result.push(nodes[i]) } if ((that.isRowExpanded(nodes[i].key, options) || !nodes[i].visible) && nodes[i].hasChildren && nodes[i].children.length) { result = result.concat(that._createVisibleItemsByNodes(nodes[i].children, options)) } } return result }, _convertItemToNode: function(item, rootValue, nodeByKey) { var parentNode, node, key = this._keyGetter(item), parentId = this._parentIdGetter(item); parentId = _type2.default.isDefined(parentId) ? parentId : rootValue; parentNode = nodeByKey[parentId] = nodeByKey[parentId] || { key: parentId, children: [] }; node = nodeByKey[key] = nodeByKey[key] || { key: key, children: [] }; node.data = item; node.parent = parentNode; return node }, _createNodesByItems: function(items, visibleItems) { var i, that = this, rootValue = that.option("rootValue"), visibleByKey = {}, nodeByKey = that._nodeByKey = {}; if (visibleItems) { for (i = 0; i < visibleItems.length; i++) { visibleByKey[this._keyGetter(visibleItems[i])] = true } } for (i = 0; i < items.length; i++) { var node = that._convertItemToNode(items[i], rootValue, nodeByKey); if (void 0 === node.key) { return } node.visible = !visibleItems || !!visibleByKey[node.key]; if (node.parent) { node.parent.children.push(node) } } var rootNode = nodeByKey[rootValue] || { key: rootValue, children: [] }; rootNode.level = -1; return rootNode }, _convertDataToPlainStructure: function(data, parentId, result) { var key, item, itemsExpr, childItems; if (this._itemsGetter && !data.isConverted) { result = result || []; for (var i = 0; i < data.length; i++) { item = _uiGrid_core2.default.createObjectWithChanges(data[i]); key = this._keyGetter(item); if (void 0 === key) { key = result.length + 1; this._keySetter(item, key) } this._parentIdSetter(item, void 0 === parentId ? this.option("rootValue") : parentId); result.push(item); childItems = this._itemsGetter(item); if (childItems && childItems.length) { this._convertDataToPlainStructure(childItems, key, result); itemsExpr = this.option("itemsExpr"); if (!_type2.default.isFunction(itemsExpr)) { delete item[itemsExpr] } } } result.isConverted = true; return result } return data }, _createIdFilter: function(field, keys) { var parentIdFilters = []; for (var i = 0; i < keys.length; i++) { parentIdFilters.push([field, "=", keys[i]]) } return _uiGrid_core2.default.combineFilters(parentIdFilters, "or") }, _customizeRemoteOperations: function(options, isReload, operationTypes) { this.callBase.apply(this, arguments); options.remoteOperations.paging = false; var expandVisibleNodes = false; if (this.option("autoExpandAll")) { options.remoteOperations.sorting = false; options.remoteOperations.filtering = false; if ((!this._lastLoadOptions || operationTypes.filtering && !options.storeLoadOptions.filter) && !options.isCustomLoading) { expandVisibleNodes = true } } if (!options.isCustomLoading) { this._isReload = this._isReload || isReload || operationTypes.reload; if (!options.cachedStoreData) { this._isChildrenLoaded = {} } if (this.option("expandNodesOnFiltering") && (operationTypes.filtering || this._isReload && options.storeLoadOptions.filter)) { if (options.storeLoadOptions.filter) { expandVisibleNodes = true } else { options.collapseVisibleNodes = true } } } options.expandVisibleNodes = expandVisibleNodes }, _getParentIdsToLoad: function(parentIds) { var parentIdsToLoad = []; for (var i = 0; i < parentIds.length; i++) { var node = this.getNodeByKey(parentIds[i]); if (node && node.hasChildren && !node.children.length) { parentIdsToLoad.push(parentIds[i]) } } return parentIdsToLoad }, _handleDataLoading: function(options) { var expandedRowKeys, combinedParentIdFilter, parentIdsToLoad, rootValue = this.option("rootValue"), parentIdExpr = this.option("parentIdExpr"), filterMode = this.option("filterMode"), parentIds = options.storeLoadOptions.parentIds; if (parentIds) { options.isCustomLoading = false } this.callBase.apply(this, arguments); if (options.remoteOperations.filtering && !options.isCustomLoading) { if ("standard" === filterMode || !options.storeLoadOptions.filter) { expandedRowKeys = options.collapseVisibleNodes ? [] : this.option("expandedRowKeys"); parentIds = [rootValue].concat(expandedRowKeys).concat(parentIds || []); parentIdsToLoad = options.data ? this._getParentIdsToLoad(parentIds) : parentIds; if (parentIdsToLoad.length) { options.cachedPagingData = void 0; options.data = void 0; options.mergeStoreLoadData = true } options.storeLoadOptions.parentIds = parentIdsToLoad; combinedParentIdFilter = this._createIdFilter(parentIdExpr, parentIdsToLoad); options.storeLoadOptions.filter = _uiGrid_core2.default.combineFilters([combinedParentIdFilter, options.storeLoadOptions.filter]) } } }, _generateParentInfoToLoad: function(data) { var i, that = this, keyMap = {}, parentIdMap = {}, parentIds = [], rootValue = that.option("rootValue"); for (i = 0; i < data.length; i++) { keyMap[that._keyGetter(data[i])] = true } for (i = 0; i < data.length; i++) { var parentId = that._parentIdGetter(data[i]); if (!parentIdMap[parentId] && !keyMap[parentId] && parentId !== rootValue) { parentIdMap[parentId] = true; parentIds.push(parentId) } } return { parentIdMap: parentIdMap, parentIds: parentIds } }, _loadParents: function(data, options) { var _this = this; var store, filter, filterLength, needLocalFiltering, that = this, parentInfo = that._generateParentInfoToLoad(data), parentIds = parentInfo.parentIds, parentIdMap = parentInfo.parentIdMap, d = new _deferred.Deferred, isRemoteFiltering = options.remoteOperations.filtering, maxFilterLengthInRequest = that.option("maxFilterLengthInRequest"), loadOptions = isRemoteFiltering ? options.storeLoadOptions : options.loadOptions; if (!parentIds.length) { return d.resolve(data) } var parentIdNodes = parentIds.map(function(id) { return _this.getNodeByKey(id) }).filter(function(node) { return node }); if (parentIdNodes.length === parentIds.length) { return that._loadParents(data.concat(parentIdNodes.map(function(node) { return node.data })), options) } filter = that._createIdFilter(that.getKeyExpr(), parentIds); filterLength = encodeURI(JSON.stringify(filter)).length; if (filterLength > maxFilterLengthInRequest) { filter = function(itemData) { return parentIdMap[that._keyGetter(itemData)] }; needLocalFiltering = isRemoteFiltering } loadOptions = (0, _extend.extend)({}, loadOptions, { filter: !needLocalFiltering ? filter : null }); store = options.fullData ? new _array_store2.default(options.fullData) : that._dataSource.store(); store.load(loadOptions).done(function(loadedData) { if (loadedData.length) { if (needLocalFiltering) { loadedData = (0, _query2.default)(loadedData).filter(filter).toArray() } that._loadParents(data.concat(loadedData), options).done(d.resolve).fail(d.reject) } else { d.resolve(data) } }).fail(d.reject); return d }, _updateHasItemsMap: function(options) { var parentIds = options.storeLoadOptions.parentIds; if (parentIds) { for (var i = 0; i < parentIds.length; i++) { this._isChildrenLoaded[parentIds[i]] = true } } }, _getKeyInfo: function() { return { key: function() { return "key" }, keyOf: function(data) { return data.key } } }, _applyBatch: function(changes) { var _this2 = this; var baseChanges = []; changes.forEach(function(change) { if ("insert" === change.type) { baseChanges = baseChanges.concat(_this2._applyInsert(change)) } else { if ("remove" === change.type) { baseChanges = baseChanges.concat(_this2._applyRemove(change)) } else { if ("update" === change.type) { baseChanges.push({ type: change.type, key: change.key, data: { data: change.data } }) } } } }); this.callBase(baseChanges) }, _setHasItems: function(node, value) { var hasItemsSetter = this._hasItemsSetter; node.hasChildren = value; if (hasItemsSetter && node.data) { hasItemsSetter(node.data, value) } }, _applyInsert: function(change) { var that = this, baseChanges = [], parentId = that.parentKeyOf(change.data), parentNode = that.getNodeByKey(parentId); if (parentNode) { var rootValue = that.option("rootValue"), node = that._convertItemToNode(change.data, rootValue, that._nodeByKey); node.hasChildren = false; node.level = parentNode.level + 1; node.visible = true; parentNode.children.push(node); that._isChildrenLoaded[node.key] = true; that._setHasItems(parentNode, true); if ((!parentNode.parent || that.isRowExpanded(parentNode.key)) && void 0 !== change.index) { var index = that.items().indexOf(parentNode) + 1; index += change.index >= 0 ? Math.min(change.index, parentNode.children.length) : parentNode.children.length; baseChanges.push({ type: change.type, data: node, index: index }) } } return baseChanges }, _applyRemove: function(change) { var baseChanges = []; var node = this.getNodeByKey(change.key); var parentNode = node.parent; if (parentNode) { var index = parentNode.children.indexOf(node); if (index >= 0) { parentNode.children.splice(index, 1); if (!parentNode.children.length) { this._setHasItems(parentNode, false) } baseChanges.push(change); baseChanges = baseChanges.concat(this.getChildNodeKeys(change.key).map(function(key) { return { type: change.type, key: key } })) } } return baseChanges }, _handleDataLoaded: function(options) { var data = options.data = this._convertDataToPlainStructure(options.data); if (!options.remoteOperations.filtering && options.loadOptions.filter) { options.fullData = (0, _store_helper.queryByOptions)((0, _query2.default)(options.data), { sort: options.loadOptions && options.loadOptions.sort }).toArray() } this._updateHasItemsMap(options); this.callBase(options); if (data.isConverted && this._cachedStoreData) { this._cachedStoreData.isConverted = true } }, _fillNodes: function(nodes, options, expandedRowKeys, level) { level = level || 0; for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; this._fillNodes(nodes[i].children, options, expandedRowKeys, level + 1); node.level = level; node.hasChildren = this._calculateHasItems(node, options); if (node.visible && node.hasChildren && options.expandVisibleNodes) { expandedRowKeys.push(node.key) } if (node.visible || node.hasChildren) { node.parent.hasChildren = true } } }, _processTreeStructure: function(options, visibleItems) { var data = options.data, parentIds = options.storeLoadOptions.parentIds, expandedRowKeys = []; if (parentIds && parentIds.length || this._isReload) { if (options.fullData && options.fullData.length > options.data.length) { data = options.fullData; visibleItems = visibleItems || options.data } this._rootNode = this._createNodesByItems(data, visibleItems); if (!this._rootNode) { options.data = (new _deferred.Deferred).reject(_ui2.default.Error("E1046", this.getKeyExpr())); return } this._fillNodes(this._rootNode.children, options, expandedRowKeys); this._isNodesInitializing = true; if (options.collapseVisibleNodes || expandedRowKeys.length) { this.option("expandedRowKeys", expandedRowKeys) } this.executeAction("onNodesInitialized", { root: this._rootNode }); this._isNodesInitializing = false; this._isReload = false } data = this._createVisibleItemsByNodes(this._rootNode.children, options); options.data = data; this._totalItemsCount = data.length }, _handleDataLoadedCore: function(options) { var visibleItems, that = this, data = options.data, callBase = that.callBase, filter = options.storeLoadOptions.filter || options.loadOptions.filter, filterMode = that.option("filterMode"), parentIds = options.storeLoadOptions.parentIds, needLoadParents = filter && (!parentIds || !parentIds.length) && "standard" !== filterMode; if (!options.isCustomLoading) { if (needLoadParents) { var d = options.data = new _deferred.Deferred; if ("smart" === filterMode) { visibleItems = data } return that._loadParents(data, options).done(function(data) { options.data = data; that._processTreeStructure(options, visibleItems); callBase.call(that, options); d.resolve(options.data) }).fail(d.reject) } else { that._processTreeStructure(options) } } that.callBase(options) }, init: function(dataSource, remoteOperations) { this.callBase.apply(this, arguments); var dataStructure = this.option("dataStructure"); this._keyGetter = this._createKeyGetter(); this._parentIdGetter = this._createParentIdGetter(); this._hasItemsGetter = this._createHasItemsGetter(); this._hasItemsSetter = this._createHasItemsSetter(); if ("tree" === dataStructure) { this._itemsGetter = this._createItemsGetter(); this._keySetter = this._createKeySetter(); this._parentIdSetter = this.createParentIdSetter() } this._nodeByKey = {}; this._isChildrenLoaded = {}; this._totalItemsCount = 0; this.createAction("onNodesInitialized") }, getKeyExpr: function() { var store = this.store(), key = store && store.key(), keyExpr = this.option("keyExpr"); if (_type2.default.isDefined(key) && _type2.default.isDefined(keyExpr)) { if (!_common2.default.equalByValue(key, keyExpr)) { throw _ui2.default.Error("E1044") } } return key || keyExpr || DEFAULT_KEY_EXPRESSION }, keyOf: function(data) { return this._keyGetter && this._keyGetter(data) }, parentKeyOf: function(data) { return this._parentIdGetter && this._parentIdGetter(data) }, getRootNode: function() { return this._rootNode }, totalItemsCount: function() { return this._totalItemsCount }, isRowExpanded: function(key, cache) { if (cache) { var isExpandedByKey = cache.isExpandedByKey; if (!isExpandedByKey) { isExpandedByKey = cache.isExpandedByKey = {}; this.option("expandedRowKeys").forEach(function(key) { isExpandedByKey[key] = true }) } return !!isExpandedByKey[key] } var indexExpandedNodeKey = _uiGrid_core2.default.getIndexByKey(key, this.option("expandedRowKeys"), null); return indexExpandedNodeKey >= 0 }, _changeRowExpandCore: function(key) { var expandedRowKeys = this.option("expandedRowKeys"), indexExpandedNodeKey = _uiGrid_core2.default.getIndexByKey(key, expandedRowKeys, null); if (indexExpandedNodeKey < 0) { expandedRowKeys.push(key) } else { expandedRowKeys.splice(indexExpandedNodeKey, 1) } this.option("expandedRowKeys", expandedRowKeys) }, changeRowExpand: function(key) { this._changeRowExpandCore(key); return this._isNodesInitializing ? (new _deferred.Deferred).resolve() : this.load() }, getNodeByKey: function(key) { if (this._nodeByKey) { return this._nodeByKey[key] } }, getNodeLeafKeys: function() { var node, that = this, result = [], keys = that._rootNode ? [that._rootNode.key] : []; keys.forEach(function(key) { node = that.getNodeByKey(key); node && _uiTree_list2.default.foreachNodes([node], function(childNode) { !childNode.children.length && result.push(childNode.key) }) }); return result }, getChildNodeKeys: function(parentKey) { var node = this.getNodeByKey(parentKey), childrenKeys = []; node && _uiTree_list2.default.foreachNodes(node.children, function(childNode) { childrenKeys.push(childNode.key) }); return childrenKeys }, loadDescendants: function(keys, childrenOnly) { var loadOptions, that = this, d = new _deferred.Deferred, remoteOperations = that.remoteOperations(); if (_type2.default.isDefined(keys)) { keys = Array.isArray(keys) ? keys : [keys] } else { keys = that.getNodeLeafKeys() } if (!remoteOperations.filtering || !keys.length) { return d.resolve() } loadOptions = that._dataSource._createStoreLoadOptions(); loadOptions.parentIds = keys; that.load(loadOptions).done(function() { if (!childrenOnly) { var childKeys = getChildKeys(that, keys); if (childKeys.length) { that.loadDescendants(childKeys, childrenOnly).done(d.resolve).fail(d.reject); return } } d.resolve() }).fail(d.reject); return d.promise() }, forEachNode: function() { var callback, rootNode, nodes = []; if (1 === arguments.length) { callback = arguments[0]; rootNode = this.getRootNode(); nodes = rootNode && rootNode.children || [] } else { if (2 === arguments.length) { callback = arguments[1]; nodes = arguments[0]; nodes = Array.isArray(nodes) ? nodes : [nodes] } } _uiTree_list2.default.foreachNodes(nodes, callback) } } }()); module.exports = { extend: function(extender) { DataSourceAdapterTreeList = DataSourceAdapterTreeList.inherit(extender) }, create: function(component) { return new DataSourceAdapterTreeList(component) } };