UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

444 lines (443 loc) • 17.3 kB
/** * DevExtreme (esm/ui/hierarchical_collection/ui.data_adapter.js) * Version: 21.1.4 * Build date: Mon Jun 21 2021 * * Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import Class from "../../core/class"; import { noop } from "../../core/utils/common"; import { each } from "../../core/utils/iterator"; import { isFunction, isDefined } from "../../core/utils/type"; import { extend } from "../../core/utils/extend"; import errors from "../../ui/widget/ui.errors"; import uiSearchBoxMixin from "../../ui/widget/ui.search_box_mixin"; import { inArray } from "../../core/utils/array"; import query from "../../data/query"; import storeHelper from "../../data/store_helper"; import HierarchicalDataConverter from "./ui.data_converter"; var EXPANDED = "expanded"; var SELECTED = "selected"; var DISABLED = "disabled"; var DataAdapter = Class.inherit({ ctor: function(options) { this.options = {}; extend(this.options, this._defaultOptions(), options); this.options.dataConverter.setDataAccessors(this.options.dataAccessors); this._selectedNodesKeys = []; this._expandedNodesKeys = []; this._dataStructure = []; this._createInternalDataStructure(); this.getTreeNodes() }, setOption: function(name, value) { this.options[name] = value; if ("recursiveSelection" === name) { this._updateSelection() } }, _defaultOptions: function() { return { dataAccessors: void 0, items: [], multipleSelection: true, recursiveSelection: false, recursiveExpansion: false, rootValue: 0, searchValue: "", dataType: "tree", searchMode: "contains", dataConverter: new HierarchicalDataConverter, onNodeChanged: noop, sort: null } }, _createInternalDataStructure: function() { this._initialDataStructure = this.options.dataConverter.createPlainStructure(this.options.items, this.options.rootValue, this.options.dataType); this._dataStructure = this.options.searchValue.length ? this.search(this.options.searchValue) : this._initialDataStructure; this.options.dataConverter._dataStructure = this._dataStructure; this._updateSelection(); this._updateExpansion() }, _updateSelection: function() { if (this.options.recursiveSelection) { this._setChildrenSelection(); this._setParentSelection() } this._selectedNodesKeys = this._updateNodesKeysArray(SELECTED) }, _updateExpansion: function(key) { if (this.options.recursiveExpansion) { key ? this._updateOneBranch(key) : this._setParentExpansion() } this._expandedNodesKeys = this._updateNodesKeysArray(EXPANDED) }, _updateNodesKeysArray: function(property) { var that = this; var array = []; each(that._getDataBySelectionMode(), (function(_, node) { if (!that._isNodeVisible(node)) { return } if (node.internalFields[property]) { if (property === EXPANDED || that.options.multipleSelection) { array.push(node.internalFields.key) } else { array.length && that.toggleSelection(array[0], false, true); array = [node.internalFields.key] } } })); return array }, _getDataBySelectionMode: function() { return this.options.multipleSelection ? this.getData() : this.getFullData() }, _isNodeVisible: function(node) { return false !== node.internalFields.item.visible }, _getByKey: function(data, key) { return data === this._dataStructure ? this.options.dataConverter._getByKey(key) : this.options.dataConverter.getByKey(data, key) }, _setChildrenSelection: function() { var that = this; each(this._dataStructure, (function(_, node) { if (!node.internalFields.childrenKeys.length) { return } var isSelected = node.internalFields.selected; true === isSelected && that._toggleChildrenSelection(node, isSelected) })) }, _setParentSelection: function() { var that = this; each(this._dataStructure, (function(_, node) { var parent = that.options.dataConverter.getParentNode(node); if (parent && node.internalFields.parentKey !== that.options.rootValue) { that._iterateParents(node, (function(parent) { var newParentState = that._calculateSelectedState(parent); that._setFieldState(parent, SELECTED, newParentState) })) } })) }, _setParentExpansion: function() { var that = this; each(this._dataStructure, (function(_, node) { if (!node.internalFields.expanded) { return } that._updateOneBranch(node.internalFields.key) })) }, _updateOneBranch: function(key) { var that = this; var node = this.getNodeByKey(key); that._iterateParents(node, (function(parent) { that._setFieldState(parent, EXPANDED, true) })) }, _iterateChildren: function(node, recursive, callback, processedKeys) { if (!isFunction(callback)) { return } var that = this; var nodeKey = node.internalFields.key; processedKeys = processedKeys || []; if (-1 === processedKeys.indexOf(nodeKey)) { processedKeys.push(nodeKey); each(node.internalFields.childrenKeys, (function(_, key) { var child = that.getNodeByKey(key); callback(child); if (child.internalFields.childrenKeys.length && recursive) { that._iterateChildren(child, recursive, callback, processedKeys) } })) } }, _iterateParents: function(node, callback, processedKeys) { if (node.internalFields.parentKey === this.options.rootValue || !isFunction(callback)) { return } processedKeys = processedKeys || []; var key = node.internalFields.key; if (-1 === processedKeys.indexOf(key)) { processedKeys.push(key); var parent = this.options.dataConverter.getParentNode(node); if (parent) { callback(parent); if (parent.internalFields.parentKey !== this.options.rootValue) { this._iterateParents(parent, callback, processedKeys) } } } }, _calculateSelectedState: function(node) { var itemsCount = node.internalFields.childrenKeys.length; var selectedItemsCount = 0; var invisibleItemsCount = 0; var result = false; for (var i = 0; i <= itemsCount - 1; i++) { var childNode = this.getNodeByKey(node.internalFields.childrenKeys[i]); var isChildInvisible = false === childNode.internalFields.item.visible; var childState = childNode.internalFields.selected; if (isChildInvisible) { invisibleItemsCount++; continue } if (childState) { selectedItemsCount++ } else if (void 0 === childState) { selectedItemsCount += .5 } } if (selectedItemsCount) { result = selectedItemsCount === itemsCount - invisibleItemsCount ? true : void 0 } return result }, _toggleChildrenSelection: function(node, state) { var that = this; this._iterateChildren(node, true, (function(child) { if (that._isNodeVisible(child)) { that._setFieldState(child, SELECTED, state) } })) }, _setFieldState: function(node, field, state) { if (node.internalFields[field] === state) { return } node.internalFields[field] = state; if (node.internalFields.publicNode) { node.internalFields.publicNode[field] = state } this.options.dataAccessors.setters[field](node.internalFields.item, state); this.options.onNodeChanged(node) }, _markChildren: function(keys) { var that = this; each(keys, (function(_, key) { var index = that.getIndexByKey(key); var node = that.getNodeByKey(key); that._dataStructure[index] = 0; node.internalFields.childrenKeys.length && that._markChildren(node.internalFields.childrenKeys) })) }, _removeNode: function(key) { var node = this.getNodeByKey(key); this._dataStructure[this.getIndexByKey(key)] = 0; this._markChildren(node.internalFields.childrenKeys); var that = this; var counter = 0; var items = extend([], this._dataStructure); each(items, (function(index, item) { if (!item) { that._dataStructure.splice(index - counter, 1); counter++ } })) }, _addNode: function(item) { var dataConverter = this.options.dataConverter; var node = dataConverter._convertItemToNode(item, this.options.dataAccessors.getters.parentKey(item)); this._dataStructure = this._dataStructure.concat(node); this._initialDataStructure = this._initialDataStructure.concat(node); dataConverter._dataStructure = dataConverter._dataStructure.concat(node) }, _updateFields: function() { this.options.dataConverter.updateChildrenKeys(); this._updateSelection(); this._updateExpansion() }, getSelectedNodesKeys: function() { return this._selectedNodesKeys }, getExpandedNodesKeys: function() { return this._expandedNodesKeys }, getData: function() { return this._dataStructure }, getFullData: function() { return this._initialDataStructure }, getNodeByItem: function(item) { var result = null; each(this._dataStructure, (function(_, node) { if (node.internalFields.item === item) { result = node; return false } })); return result }, getNodesByItems: function(items) { var that = this; var nodes = []; each(items, (function(_, item) { var node = that.getNodeByItem(item); node && nodes.push(node) })); return nodes }, getNodeByKey: function(key, data) { return this._getByKey(data || this._getDataBySelectionMode(), key) }, getTreeNodes: function() { return this.options.dataConverter.convertToPublicNodes(this.getRootNodes()) }, getItemsCount: function() { return this.options.dataConverter.getItemsCount() }, getVisibleItemsCount: function() { return this.options.dataConverter.getVisibleItemsCount() }, getPublicNode: function(node) { return node.internalFields.publicNode }, getRootNodes: function() { return this.getChildrenNodes(this.options.rootValue) }, getChildrenNodes: function(parentKey) { return query(this._dataStructure).filter(["internalFields.parentKey", parentKey]).toArray() }, getIndexByKey: function(key) { return this.options.dataConverter.getIndexByKey(key) }, addItem: function(item) { this._addNode(item); this._updateFields() }, removeItem: function(key) { this._removeNode(key); this._updateFields() }, toggleSelection: function(key, state, selectRecursive) { var isSingleModeUnselect = this._isSingleModeUnselect(state); var node = this._getByKey(selectRecursive || isSingleModeUnselect ? this._initialDataStructure : this._dataStructure, key); this._setFieldState(node, SELECTED, state); if (this.options.recursiveSelection && !selectRecursive) { state ? this._setChildrenSelection() : this._toggleChildrenSelection(node, state); this._setParentSelection() } this._selectedNodesKeys = this._updateNodesKeysArray(SELECTED) }, _isSingleModeUnselect: function(selectionState) { return !this.options.multipleSelection && !selectionState }, toggleNodeDisabledState: function(key, state) { var node = this.getNodeByKey(key); this._setFieldState(node, DISABLED, state) }, toggleSelectAll: function(state) { if (!isDefined(state)) { return } var that = this; var lastSelectedKey = that._selectedNodesKeys[that._selectedNodesKeys.length - 1]; var dataStructure = that._isSingleModeUnselect(state) ? this._initialDataStructure : this._dataStructure; each(dataStructure, (function(index, node) { if (!that._isNodeVisible(node)) { return } that._setFieldState(node, SELECTED, state) })); that._selectedNodesKeys = that._updateNodesKeysArray(SELECTED); if (!state && that.options.selectionRequired) { that.toggleSelection(lastSelectedKey, true) } }, isAllSelected: function() { if (this.getSelectedNodesKeys().length) { return this.getSelectedNodesKeys().length === this.getVisibleItemsCount() ? true : void 0 } else { return false } }, toggleExpansion: function(key, state) { var node = this.getNodeByKey(key); this._setFieldState(node, EXPANDED, state); if (state) { this._updateExpansion(key) } this._expandedNodesKeys = this._updateNodesKeysArray(EXPANDED) }, isFiltered: function(item) { return !this.options.searchValue.length || !!this._filterDataStructure(this.options.searchValue, [item]).length }, _createCriteria: function(selector, value, operation) { var searchFilter = []; if (!Array.isArray(selector)) { return [selector, operation, value] } each(selector, (function(i, item) { searchFilter.push([item, operation, value], "or") })); searchFilter.pop(); return searchFilter }, _filterDataStructure: function(filterValue, dataStructure) { var selector = this.options.searchExpr || this.options.dataAccessors.getters.display; var operation = uiSearchBoxMixin.getOperationBySearchMode(this.options.searchMode); var criteria = this._createCriteria(selector, filterValue, operation); dataStructure = dataStructure || this._initialDataStructure; return query(dataStructure).filter(criteria).toArray() }, search: function(searchValue) { var that = this; var matches = this._filterDataStructure(searchValue); var dataConverter = this.options.dataConverter; ! function lookForParents(matches, index) { var length = matches.length; while (index < length) { var node = matches[index]; if (node.internalFields.parentKey === that.options.rootValue) { index++; continue } var parent = dataConverter.getParentNode(node); if (!parent) { errors.log("W1007", node.internalFields.parentKey, node.internalFields.key); index++; continue } if (!parent.internalFields.expanded) { that._setFieldState(parent, EXPANDED, true) } if (inArray(parent, matches) > -1) { index++; continue } matches.splice(index, 0, parent); lookForParents(matches, index) } }(matches, 0); if (this.options.sort) { matches = storeHelper.queryByOptions(query(matches), { sort: this.options.sort }).toArray() } dataConverter._indexByKey = {}; each(matches, (function(index, node) { node.internalFields.childrenKeys = []; dataConverter._indexByKey[node.internalFields.key] = index })); dataConverter._dataStructure = matches; dataConverter.setChildrenKeys(); return dataConverter._dataStructure } }); export default DataAdapter;