devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
450 lines (448 loc) • 17.8 kB
JavaScript
/**
* DevExtreme (cjs/__internal/ui/hierarchical_collection/m_data_adapter.js)
* Version: 24.2.6
* Build date: Mon Mar 17 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _query = _interopRequireDefault(require("../../../common/data/query"));
var _store_helper = _interopRequireDefault(require("../../../common/data/store_helper"));
var _class = _interopRequireDefault(require("../../../core/class"));
var _common = require("../../../core/utils/common");
var _extend = require("../../../core/utils/extend");
var _iterator = require("../../../core/utils/iterator");
var _type = require("../../../core/utils/type");
var _text_box = _interopRequireDefault(require("../../../ui/text_box"));
var _ui = _interopRequireDefault(require("../../../ui/widget/ui.errors"));
var _ui2 = _interopRequireDefault(require("../../../ui/widget/ui.search_box_mixin"));
var _m_data_converter = _interopRequireDefault(require("./m_data_converter"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : {
default: e
}
}
const EXPANDED = "expanded";
const SELECTED = "selected";
const DISABLED = "disabled";
_ui2.default.setEditorClass(_text_box.default);
const DataAdapter = _class.default.inherit({
ctor(options) {
this.options = {};
(0, _extend.extend)(this.options, this._defaultOptions(), options);
this.options.dataConverter.setDataAccessors(this.options.dataAccessors);
this._selectedNodesKeys = [];
this._expandedNodesKeys = [];
this._dataStructure = [];
this._createInternalDataStructure();
this.getTreeNodes()
},
setOption(name, value) {
this.options[name] = value;
if ("recursiveSelection" === name) {
this._updateSelection()
}
},
_defaultOptions: () => ({
dataAccessors: void 0,
items: [],
multipleSelection: true,
recursiveSelection: false,
recursiveExpansion: false,
rootValue: 0,
searchValue: "",
dataType: "tree",
searchMode: "contains",
dataConverter: new _m_data_converter.default,
onNodeChanged: _common.noop,
sort: null
}),
_createInternalDataStructure() {
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() {
if (this.options.recursiveSelection) {
this._setChildrenSelection();
this._setParentSelection()
}
this._selectedNodesKeys = this._updateNodesKeysArray(SELECTED)
},
_updateExpansion(key) {
if (this.options.recursiveExpansion) {
key ? this._updateOneBranch(key) : this._setParentExpansion()
}
this._expandedNodesKeys = this._updateNodesKeysArray(EXPANDED)
},
_updateNodesKeysArray(property) {
const that = this;
let array = [];
(0, _iterator.each)(that._getDataBySelectionMode(), ((_, 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() {
return this.options.multipleSelection ? this.getData() : this.getFullData()
},
_isNodeVisible: node => false !== node.internalFields.item.visible,
_getByKey(data, key) {
return data === this._dataStructure ? this.options.dataConverter._getByKey(key) : this.options.dataConverter.getByKey(data, key)
},
_setChildrenSelection() {
const that = this;
(0, _iterator.each)(this._dataStructure, ((_, node) => {
if (!node.internalFields.childrenKeys.length) {
return
}
const isSelected = node.internalFields.selected;
true === isSelected && that._toggleChildrenSelection(node, isSelected)
}))
},
_setParentSelection() {
const that = this;
(0, _iterator.each)(this._dataStructure, ((_, node) => {
const parent = that.options.dataConverter.getParentNode(node);
if (parent && node.internalFields.parentKey !== that.options.rootValue) {
that._iterateParents(node, (parent => {
const newParentState = that._calculateSelectedState(parent);
that._setFieldState(parent, SELECTED, newParentState)
}))
}
}))
},
_setParentExpansion() {
const that = this;
(0, _iterator.each)(this._dataStructure, ((_, node) => {
if (!node.internalFields.expanded) {
return
}
that._updateOneBranch(node.internalFields.key)
}))
},
_updateOneBranch(key) {
const that = this;
const node = this.getNodeByKey(key);
that._iterateParents(node, (parent => {
that._setFieldState(parent, EXPANDED, true)
}))
},
_iterateChildren(node, recursive, callback, processedKeys) {
if (!(0, _type.isFunction)(callback)) {
return
}
const that = this;
const nodeKey = node.internalFields.key;
processedKeys = processedKeys || [];
if (-1 === processedKeys.indexOf(nodeKey)) {
processedKeys.push(nodeKey);
(0, _iterator.each)(node.internalFields.childrenKeys, ((_, key) => {
const child = that.getNodeByKey(key);
callback(child);
if (child.internalFields.childrenKeys.length && recursive) {
that._iterateChildren(child, recursive, callback, processedKeys)
}
}))
}
},
_iterateParents(node, callback, processedKeys) {
if (node.internalFields.parentKey === this.options.rootValue || !(0, _type.isFunction)(callback)) {
return
}
processedKeys = processedKeys || [];
const {
key: key
} = node.internalFields;
if (-1 === processedKeys.indexOf(key)) {
processedKeys.push(key);
const parent = this.options.dataConverter.getParentNode(node);
if (parent) {
callback(parent);
if (parent.internalFields.parentKey !== this.options.rootValue) {
this._iterateParents(parent, callback, processedKeys)
}
}
}
},
_calculateSelectedState(node) {
const itemsCount = node.internalFields.childrenKeys.length;
let selectedItemsCount = 0;
let invisibleItemsCount = 0;
let result = false;
for (let i = 0; i <= itemsCount - 1; i++) {
const childNode = this.getNodeByKey(node.internalFields.childrenKeys[i]);
const isChildInvisible = false === childNode.internalFields.item.visible;
const 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(node, state) {
const that = this;
this._iterateChildren(node, true, (child => {
if (that._isNodeVisible(child)) {
that._setFieldState(child, SELECTED, state)
}
}))
},
_setFieldState(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(keys) {
const that = this;
(0, _iterator.each)(keys, ((_, key) => {
const index = that.getIndexByKey(key);
const node = that.getNodeByKey(key);
that._dataStructure[index] = 0;
node.internalFields.childrenKeys.length && that._markChildren(node.internalFields.childrenKeys)
}))
},
_removeNode(key) {
const node = this.getNodeByKey(key);
this._dataStructure[this.getIndexByKey(key)] = 0;
this._markChildren(node.internalFields.childrenKeys);
const that = this;
let counter = 0;
const items = (0, _extend.extend)([], this._dataStructure);
(0, _iterator.each)(items, ((index, item) => {
if (!item) {
that._dataStructure.splice(index - counter, 1);
counter++
}
}))
},
_addNode(item) {
const {
dataConverter: dataConverter
} = this.options;
const 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() {
this.options.dataConverter.updateChildrenKeys();
this._updateSelection();
this._updateExpansion()
},
getSelectedNodesKeys() {
return this._selectedNodesKeys
},
getExpandedNodesKeys() {
return this._expandedNodesKeys
},
getData() {
return this._dataStructure
},
getFullData() {
return this._initialDataStructure
},
getNodeByItem(item) {
let result = null;
(0, _iterator.each)(this._dataStructure, ((_, node) => {
if (node.internalFields.item === item) {
result = node;
return false
}
}));
return result
},
getNodesByItems(items) {
const that = this;
const nodes = [];
(0, _iterator.each)(items, ((_, item) => {
const node = that.getNodeByItem(item);
node && nodes.push(node)
}));
return nodes
},
getNodeByKey(key, data) {
return this._getByKey(data || this._getDataBySelectionMode(), key)
},
getTreeNodes() {
return this.options.dataConverter.convertToPublicNodes(this.getRootNodes())
},
getItemsCount() {
return this.options.dataConverter.getItemsCount()
},
getVisibleItemsCount() {
return this.options.dataConverter.getVisibleItemsCount()
},
getPublicNode: node => node.internalFields.publicNode,
getRootNodes() {
return this.getChildrenNodes(this.options.rootValue)
},
getChildrenNodes(parentKey) {
return (0, _query.default)(this._dataStructure, {
langParams: this.options.langParams
}).filter(["internalFields.parentKey", parentKey]).toArray()
},
getIndexByKey(key) {
return this.options.dataConverter.getIndexByKey(key)
},
addItem(item) {
this._addNode(item);
this._updateFields()
},
removeItem(key) {
this._removeNode(key);
this._updateFields()
},
toggleSelection(key, state, selectRecursive) {
const isSingleModeUnselect = this._isSingleModeUnselect(state);
const 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(selectionState) {
return !this.options.multipleSelection && !selectionState
},
toggleNodeDisabledState(key, state) {
const node = this.getNodeByKey(key);
this._setFieldState(node, DISABLED, state)
},
toggleSelectAll(state) {
if (!(0, _type.isDefined)(state)) {
return
}
const that = this;
const lastSelectedKey = that._selectedNodesKeys[that._selectedNodesKeys.length - 1];
const dataStructure = that._isSingleModeUnselect(state) ? this._initialDataStructure : this._dataStructure;
(0, _iterator.each)(dataStructure, ((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() {
if (this.getSelectedNodesKeys().length) {
return this.getSelectedNodesKeys().length === this.getVisibleItemsCount() ? true : void 0
}
return false
},
toggleExpansion(key, state) {
const node = this.getNodeByKey(key);
this._setFieldState(node, EXPANDED, state);
if (state) {
this._updateExpansion(key)
}
this._expandedNodesKeys = this._updateNodesKeysArray(EXPANDED)
},
isFiltered(item) {
return !this.options.searchValue.length || !!this._filterDataStructure(this.options.searchValue, [item]).length
},
_createCriteria(selector, value, operation) {
const searchFilter = [];
if (!Array.isArray(selector)) {
return [selector, operation, value]
}(0, _iterator.each)(selector, ((i, item) => {
searchFilter.push([item, operation, value], "or")
}));
searchFilter.pop();
return searchFilter
},
_filterDataStructure(filterValue, dataStructure) {
const selector = this.options.searchExpr || this.options.dataAccessors.getters.display;
const operation = _ui2.default.getOperationBySearchMode(this.options.searchMode);
const criteria = this._createCriteria(selector, filterValue, operation);
dataStructure = dataStructure || this._initialDataStructure;
return (0, _query.default)(dataStructure, {
langParams: this.options.langParams
}).filter(criteria).toArray()
},
search(searchValue) {
const that = this;
let matches = this._filterDataStructure(searchValue);
const {
dataConverter: dataConverter
} = this.options;
! function lookForParents(matches, index) {
const {
length: length
} = matches;
while (index < length) {
const node = matches[index];
if (node.internalFields.parentKey === that.options.rootValue) {
index++;
continue
}
const parent = dataConverter.getParentNode(node);
if (!parent) {
_ui.default.log("W1007", node.internalFields.parentKey, node.internalFields.key);
index++;
continue
}
if (!parent.internalFields.expanded) {
that._setFieldState(parent, EXPANDED, true)
}
if (matches.includes(parent)) {
index++;
continue
}
matches.splice(index, 0, parent);
lookForParents(matches, index)
}
}(matches, 0);
if (this.options.sort) {
matches = _store_helper.default.queryByOptions((0, _query.default)(matches), {
sort: this.options.sort,
langParams: this.options.langParams
}).toArray()
}
dataConverter._indexByKey = {};
(0, _iterator.each)(matches, ((index, node) => {
node.internalFields.childrenKeys = [];
dataConverter._indexByKey[node.internalFields.key] = index
}));
dataConverter._dataStructure = matches;
dataConverter.setChildrenKeys();
return dataConverter._dataStructure
}
});
var _default = exports.default = DataAdapter;