UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

657 lines (655 loc) • 29.1 kB
/** * DevExtreme (cjs/ui/collection/ui.collection_widget.edit.js) * Version: 23.2.6 * Build date: Wed May 01 2024 * * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; exports.default = void 0; var _renderer = _interopRequireDefault(require("../../core/renderer")); var _events_engine = _interopRequireDefault(require("../../events/core/events_engine")); var _uiCollection_widget = _interopRequireDefault(require("./ui.collection_widget.base")); var _ui = _interopRequireDefault(require("../widget/ui.errors")); var _extend = require("../../core/utils/extend"); var _iterator = require("../../core/utils/iterator"); var _common = require("../../core/utils/common"); var _type = require("../../core/utils/type"); var _uiCollection_widgetEditStrategy = _interopRequireDefault(require("./ui.collection_widget.edit.strategy.plain")); var _data = require("../../core/utils/data"); var _data_source = require("../../data/data_source/data_source"); var _utils = require("../../data/data_source/utils"); var _selection = _interopRequireDefault(require("../selection/selection")); var _deferred = require("../../core/utils/deferred"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } } const ITEM_DELETING_DATA_KEY = "dxItemDeleting"; const NOT_EXISTING_INDEX = -1; const indexExists = function(index) { return -1 !== index }; const CollectionWidget = _uiCollection_widget.default.inherit({ _setOptionsByReference: function() { this.callBase(); (0, _extend.extend)(this._optionsByReference, { selectedItem: true }) }, _getDefaultOptions: function() { return (0, _extend.extend)(this.callBase(), { selectionMode: "none", selectionRequired: false, selectByClick: true, selectedItems: [], selectedItemKeys: [], maxFilterLengthInRequest: 1500, keyExpr: null, selectedIndex: -1, selectedItem: null, onSelectionChanged: null, onItemReordered: null, onItemDeleting: null, onItemDeleted: null }) }, ctor: function(element, options) { this._userOptions = options || {}; this.callBase(element, options) }, _init: function() { this._initEditStrategy(); this.callBase(); this._initKeyGetter(); this._initSelectionModule() }, _initKeyGetter: function() { this._keyGetter = (0, _data.compileGetter)(this.option("keyExpr")) }, _getKeysByItems: function(selectedItems) { return this._editStrategy.getKeysByItems(selectedItems) }, _getItemsByKeys: function(selectedItemKeys, selectedItems) { return this._editStrategy.getItemsByKeys(selectedItemKeys, selectedItems) }, _getKeyByIndex: function(index) { return this._editStrategy.getKeyByIndex(index) }, _getIndexByKey: function(key) { return this._editStrategy.getIndexByKey(key) }, _getIndexByItemData: function(itemData) { return this._editStrategy.getIndexByItemData(itemData) }, _isKeySpecified: function() { return !!this._dataController.key() }, _getCombinedFilter: function() { return this._dataController.filter() }, key: function() { if (this.option("keyExpr")) { return this.option("keyExpr") } return this._dataController.key() }, keyOf: function(item) { let key = item; if (this.option("keyExpr")) { key = this._keyGetter(item) } else if (this._dataController.store()) { key = this._dataController.keyOf(item) } return key }, _nullValueSelectionSupported: function() { return false }, _initSelectionModule: function() { const that = this; const itemsGetter = that._editStrategy.itemsGetter; this._selection = new _selection.default({ allowNullValue: this._nullValueSelectionSupported(), mode: this.option("selectionMode"), maxFilterLengthInRequest: this.option("maxFilterLengthInRequest"), equalByReference: !this._isKeySpecified(), onSelectionChanged: function(args) { if (args.addedItemKeys.length || args.removedItemKeys.length) { that.option("selectedItems", that._getItemsByKeys(args.selectedItemKeys, args.selectedItems)); that._updateSelectedItems(args) } }, filter: that._getCombinedFilter.bind(that), totalCount: function() { const items = that.option("items"); const totalCount = that._dataController.totalCount(); return totalCount >= 0 ? totalCount : that._getItemsCount(items) }, key: that.key.bind(that), keyOf: that.keyOf.bind(that), load: function(options) { var _dataController$loadO; const dataController = that._dataController; options.customQueryParams = null === (_dataController$loadO = dataController.loadOptions()) || void 0 === _dataController$loadO ? void 0 : _dataController$loadO.customQueryParams; options.userData = dataController.userData(); if (dataController.store()) { return dataController.loadFromStore(options).done((function(loadResult) { if (that._disposed) { return } const items = (0, _utils.normalizeLoadResult)(loadResult).data; dataController.applyMapFunction(items) })) } else { return (new _deferred.Deferred).resolve(this.plainItems()) } }, dataFields: function() { return that._dataController.select() }, plainItems: itemsGetter.bind(that._editStrategy) }) }, _getItemsCount: function(items) { return items.reduce((itemsCount, item) => itemsCount + (item.items ? this._getItemsCount(item.items) : 1), 0) }, _initEditStrategy: function() { const Strategy = _uiCollection_widgetEditStrategy.default; this._editStrategy = new Strategy(this) }, _getSelectedItemIndices: function(keys) { const that = this; const indices = []; keys = keys || this._selection.getSelectedItemKeys(); that._editStrategy.beginCache(); (0, _iterator.each)(keys, (function(_, key) { const selectedIndex = that._getIndexByKey(key); if (indexExists(selectedIndex)) { indices.push(selectedIndex) } })); that._editStrategy.endCache(); return indices }, _initMarkup: function() { this._rendering = true; if (!this._dataController.isLoading()) { this._syncSelectionOptions().done(() => this._normalizeSelectedItems()) } this.callBase() }, _render: function() { this.callBase(); this._rendering = false }, _fireContentReadyAction: function() { this._rendering = false; this._rendered = true; this.callBase.apply(this, arguments) }, _syncSelectionOptions: function(byOption) { byOption = byOption || this._chooseSelectOption(); let selectedItem; let selectedIndex; let selectedItemKeys; let selectedItems; switch (byOption) { case "selectedIndex": selectedItem = this._editStrategy.getItemDataByIndex(this.option("selectedIndex")); if ((0, _type.isDefined)(selectedItem)) { this._setOptionWithoutOptionChange("selectedItems", [selectedItem]); this._setOptionWithoutOptionChange("selectedItem", selectedItem); this._setOptionWithoutOptionChange("selectedItemKeys", this._editStrategy.getKeysByItems([selectedItem])) } else { this._setOptionWithoutOptionChange("selectedItems", []); this._setOptionWithoutOptionChange("selectedItemKeys", []); this._setOptionWithoutOptionChange("selectedItem", null) } break; case "selectedItems": selectedItems = this.option("selectedItems") || []; selectedIndex = selectedItems.length ? this._editStrategy.getIndexByItemData(selectedItems[0]) : -1; if (this.option("selectionRequired") && !indexExists(selectedIndex)) { return this._syncSelectionOptions("selectedIndex") } this._setOptionWithoutOptionChange("selectedItem", selectedItems[0]); this._setOptionWithoutOptionChange("selectedIndex", selectedIndex); this._setOptionWithoutOptionChange("selectedItemKeys", this._editStrategy.getKeysByItems(selectedItems)); break; case "selectedItem": selectedItem = this.option("selectedItem"); selectedIndex = this._editStrategy.getIndexByItemData(selectedItem); if (this.option("selectionRequired") && !indexExists(selectedIndex)) { return this._syncSelectionOptions("selectedIndex") } if ((0, _type.isDefined)(selectedItem)) { this._setOptionWithoutOptionChange("selectedItems", [selectedItem]); this._setOptionWithoutOptionChange("selectedIndex", selectedIndex); this._setOptionWithoutOptionChange("selectedItemKeys", this._editStrategy.getKeysByItems([selectedItem])) } else { this._setOptionWithoutOptionChange("selectedItems", []); this._setOptionWithoutOptionChange("selectedItemKeys", []); this._setOptionWithoutOptionChange("selectedIndex", -1) } break; case "selectedItemKeys": selectedItemKeys = this.option("selectedItemKeys"); if (this.option("selectionRequired")) { const selectedItemIndex = this._getIndexByKey(selectedItemKeys[0]); if (!indexExists(selectedItemIndex)) { return this._syncSelectionOptions("selectedIndex") } } return this._selection.setSelection(selectedItemKeys) } return (new _deferred.Deferred).resolve().promise() }, _chooseSelectOption: function() { let optionName = "selectedIndex"; const isOptionDefined = function(optionName) { const optionValue = this.option(optionName); const length = (0, _type.isDefined)(optionValue) && optionValue.length; return length || optionName in this._userOptions }.bind(this); if (isOptionDefined("selectedItems")) { optionName = "selectedItems" } else if (isOptionDefined("selectedItem")) { optionName = "selectedItem" } else if (isOptionDefined("selectedItemKeys")) { optionName = "selectedItemKeys" } return optionName }, _compareKeys: function(oldKeys, newKeys) { if (oldKeys.length !== newKeys.length) { return false } for (let i = 0; i < newKeys.length; i++) { if (oldKeys[i] !== newKeys[i]) { return false } } return true }, _normalizeSelectedItems: function() { if ("none" === this.option("selectionMode")) { this._setOptionWithoutOptionChange("selectedItems", []); this._syncSelectionOptions("selectedItems") } else if ("single" === this.option("selectionMode")) { const newSelection = this.option("selectedItems"); if (newSelection.length > 1 || !newSelection.length && this.option("selectionRequired") && this.option("items") && this.option("items").length) { const currentSelection = this._selection.getSelectedItems(); let normalizedSelection = void 0 === newSelection[0] ? currentSelection[0] : newSelection[0]; if (void 0 === normalizedSelection) { normalizedSelection = this._editStrategy.itemsGetter()[0] } if (this.option("grouped") && normalizedSelection && normalizedSelection.items) { normalizedSelection.items = [normalizedSelection.items[0]] } this._selection.setSelection(this._getKeysByItems([normalizedSelection])); this._setOptionWithoutOptionChange("selectedItems", [normalizedSelection]); return this._syncSelectionOptions("selectedItems") } else { this._selection.setSelection(this._getKeysByItems(newSelection)) } } else { const newKeys = this._getKeysByItems(this.option("selectedItems")); const oldKeys = this._selection.getSelectedItemKeys(); if (!this._compareKeys(oldKeys, newKeys)) { this._selection.setSelection(newKeys) } } return (new _deferred.Deferred).resolve().promise() }, _itemClickHandler: function(e) { let itemSelectPromise = (new _deferred.Deferred).resolve(); const callBase = this.callBase; this._createAction(function(e) { var _this$_itemSelectHand; itemSelectPromise = null !== (_this$_itemSelectHand = this._itemSelectHandler(e.event)) && void 0 !== _this$_itemSelectHand ? _this$_itemSelectHand : itemSelectPromise }.bind(this), { validatingTargetName: "itemElement" })({ itemElement: (0, _renderer.default)(e.currentTarget), event: e }); itemSelectPromise.always(() => { callBase.apply(this, arguments) }) }, _itemSelectHandler: function(e) { var _itemSelectPromise; let itemSelectPromise; if (!this.option("selectByClick")) { return } const $itemElement = e.currentTarget; if (this.isItemSelected($itemElement)) { this.unselectItem(e.currentTarget) } else { itemSelectPromise = this.selectItem(e.currentTarget) } return null === (_itemSelectPromise = itemSelectPromise) || void 0 === _itemSelectPromise ? void 0 : _itemSelectPromise.promise() }, _selectedItemElement: function(index) { return this._itemElements().eq(index) }, _postprocessRenderItem: function(args) { if ("none" !== this.option("selectionMode")) { const $itemElement = (0, _renderer.default)(args.itemElement); const normalizedItemIndex = this._editStrategy.getNormalizedIndex($itemElement); const isItemSelected = this._isItemSelected(normalizedItemIndex); this._processSelectableItem($itemElement, isItemSelected) } }, _processSelectableItem: function($itemElement, isSelected) { $itemElement.toggleClass(this._selectedItemClass(), isSelected); this._setAriaSelectionAttribute($itemElement, String(isSelected)) }, _updateSelectedItems: function(args) { const that = this; const addedItemKeys = args.addedItemKeys; const removedItemKeys = args.removedItemKeys; if (that._rendered && (addedItemKeys.length || removedItemKeys.length)) { const selectionChangePromise = that._selectionChangePromise; if (!that._rendering) { const addedSelection = []; let normalizedIndex; const removedSelection = []; that._editStrategy.beginCache(); for (let i = 0; i < addedItemKeys.length; i++) { normalizedIndex = that._getIndexByKey(addedItemKeys[i]); addedSelection.push(normalizedIndex); that._addSelection(normalizedIndex) } for (let i = 0; i < removedItemKeys.length; i++) { normalizedIndex = that._getIndexByKey(removedItemKeys[i]); removedSelection.push(normalizedIndex); that._removeSelection(normalizedIndex) } that._editStrategy.endCache(); that._updateSelection(addedSelection, removedSelection) }(0, _deferred.when)(selectionChangePromise).done((function() { that._fireSelectionChangeEvent(args.addedItems, args.removedItems) })) } }, _fireSelectionChangeEvent: function(addedItems, removedItems) { this._createActionByOption("onSelectionChanged", { excludeValidators: ["disabled", "readOnly"] })({ addedItems: addedItems, removedItems: removedItems }) }, _updateSelection: _common.noop, _setAriaSelectionAttribute: function($target, value) { this.setAria("selected", value, $target) }, _removeSelection: function(normalizedIndex) { const $itemElement = this._editStrategy.getItemElement(normalizedIndex); if (indexExists(normalizedIndex)) { this._processSelectableItem($itemElement, false); _events_engine.default.triggerHandler($itemElement, "stateChanged", false) } }, _addSelection: function(normalizedIndex) { const $itemElement = this._editStrategy.getItemElement(normalizedIndex); if (indexExists(normalizedIndex)) { this._processSelectableItem($itemElement, true); _events_engine.default.triggerHandler($itemElement, "stateChanged", true) } }, _isItemSelected: function(index) { const key = this._getKeyByIndex(index); return this._selection.isItemSelected(key, { checkPending: true }) }, _optionChanged: function(args) { switch (args.name) { case "selectionMode": this._invalidate(); break; case "dataSource": if (!args.value || Array.isArray(args.value) && !args.value.length) { this.option("selectedItemKeys", []) } this.callBase(args); break; case "selectedIndex": case "selectedItem": case "selectedItems": case "selectedItemKeys": this._syncSelectionOptions(args.name).done(() => this._normalizeSelectedItems()); break; case "keyExpr": this._initKeyGetter(); break; case "selectionRequired": this._normalizeSelectedItems(); break; case "selectByClick": case "onSelectionChanged": case "onItemDeleting": case "onItemDeleted": case "onItemReordered": case "maxFilterLengthInRequest": break; default: this.callBase(args) } }, _clearSelectedItems: function() { this._setOptionWithoutOptionChange("selectedItems", []); this._syncSelectionOptions("selectedItems") }, _waitDeletingPrepare: function($itemElement) { if ($itemElement.data("dxItemDeleting")) { return (new _deferred.Deferred).resolve().promise() } $itemElement.data("dxItemDeleting", true); const deferred = new _deferred.Deferred; const deletingActionArgs = { cancel: false }; const deletePromise = this._itemEventHandler($itemElement, "onItemDeleting", deletingActionArgs, { excludeValidators: ["disabled", "readOnly"] }); (0, _deferred.when)(deletePromise).always(function(value) { const deletePromiseExists = !deletePromise; const deletePromiseResolved = !deletePromiseExists && "resolved" === deletePromise.state(); const argumentsSpecified = !!arguments.length; const shouldDelete = deletePromiseExists || deletePromiseResolved && !argumentsSpecified || deletePromiseResolved && value; (0, _deferred.when)((0, _deferred.fromPromise)(deletingActionArgs.cancel)).always((function() { $itemElement.data("dxItemDeleting", false) })).done((function(cancel) { shouldDelete && !cancel ? deferred.resolve() : deferred.reject() })).fail(deferred.reject) }.bind(this)); return deferred.promise() }, _deleteItemFromDS: function($item) { const dataController = this._dataController; const deferred = new _deferred.Deferred; const disabledState = this.option("disabled"); const dataStore = dataController.store(); if (!dataStore) { return (new _deferred.Deferred).resolve().promise() } if (!dataStore.remove) { throw _ui.default.Error("E1011") } this.option("disabled", true); dataStore.remove(dataController.keyOf(this._getItemData($item))).done((function(key) { if (void 0 !== key) { deferred.resolve() } else { deferred.reject() } })).fail((function() { deferred.reject() })); deferred.always(function() { this.option("disabled", disabledState) }.bind(this)); return deferred }, _tryRefreshLastPage: function() { const deferred = new _deferred.Deferred; if (this._isLastPage() || this.option("grouped")) { deferred.resolve() } else { this._refreshLastPage().done((function() { deferred.resolve() })) } return deferred.promise() }, _refreshLastPage: function() { this._expectLastItemLoading(); return this._dataController.load() }, _updateSelectionAfterDelete: function(index) { const key = this._getKeyByIndex(index); this._selection.deselect([key]) }, _updateIndicesAfterIndex: function(index) { const itemElements = this._itemElements(); for (let i = index + 1; i < itemElements.length; i++) { (0, _renderer.default)(itemElements[i]).data(this._itemIndexKey(), i - 1) } }, _simulateOptionChange: function(optionName) { const optionValue = this.option(optionName); if (optionValue instanceof _data_source.DataSource) { return } this._optionChangedAction({ name: optionName, fullName: optionName, value: optionValue }) }, isItemSelected: function(itemElement) { return this._isItemSelected(this._editStrategy.getNormalizedIndex(itemElement)) }, selectItem: function(itemElement) { if ("none" === this.option("selectionMode")) { return } const itemIndex = this._editStrategy.getNormalizedIndex(itemElement); if (!indexExists(itemIndex)) { return } const key = this._getKeyByIndex(itemIndex); if (this._selection.isItemSelected(key)) { return } if ("single" === this.option("selectionMode")) { return this._selection.setSelection([key]) } else { const selectedItemKeys = this.option("selectedItemKeys") || []; return this._selection.setSelection([...selectedItemKeys, key], [key]) } }, unselectItem: function(itemElement) { const itemIndex = this._editStrategy.getNormalizedIndex(itemElement); if (!indexExists(itemIndex)) { return } const selectedItemKeys = this._selection.getSelectedItemKeys(); if (this.option("selectionRequired") && selectedItemKeys.length <= 1) { return } const key = this._getKeyByIndex(itemIndex); if (!this._selection.isItemSelected(key, { checkPending: true })) { return } this._selection.deselect([key]) }, _deleteItemElementByIndex: function(index) { this._updateSelectionAfterDelete(index); this._updateIndicesAfterIndex(index); this._editStrategy.deleteItemAtIndex(index) }, _afterItemElementDeleted: function($item, deletedActionArgs) { const changingOption = this._dataController.getDataSource() ? "dataSource" : "items"; this._simulateOptionChange(changingOption); this._itemEventHandler($item, "onItemDeleted", deletedActionArgs, { beforeExecute: function() { $item.remove() }, excludeValidators: ["disabled", "readOnly"] }); this._renderEmptyMessage() }, deleteItem: function(itemElement) { const that = this; const deferred = new _deferred.Deferred; const $item = this._editStrategy.getItemElement(itemElement); const index = this._editStrategy.getNormalizedIndex(itemElement); const itemResponseWaitClass = this._itemResponseWaitClass(); if (indexExists(index)) { this._waitDeletingPrepare($item).done((function() { $item.addClass(itemResponseWaitClass); const deletedActionArgs = that._extendActionArgs($item); that._deleteItemFromDS($item).done((function() { that._deleteItemElementByIndex(index); that._afterItemElementDeleted($item, deletedActionArgs); that._tryRefreshLastPage().done((function() { deferred.resolveWith(that) })) })).fail((function() { $item.removeClass(itemResponseWaitClass); deferred.rejectWith(that) })) })).fail((function() { deferred.rejectWith(that) })) } else { deferred.rejectWith(that) } return deferred.promise() }, reorderItem: function(itemElement, toItemElement) { const deferred = new _deferred.Deferred; const that = this; const strategy = this._editStrategy; const $movingItem = strategy.getItemElement(itemElement); const $destinationItem = strategy.getItemElement(toItemElement); const movingIndex = strategy.getNormalizedIndex(itemElement); const destinationIndex = strategy.getNormalizedIndex(toItemElement); const changingOption = this._dataController.getDataSource() ? "dataSource" : "items"; const canMoveItems = indexExists(movingIndex) && indexExists(destinationIndex) && movingIndex !== destinationIndex; if (canMoveItems) { deferred.resolveWith(this) } else { deferred.rejectWith(this) } return deferred.promise().done((function() { $destinationItem[strategy.itemPlacementFunc(movingIndex, destinationIndex)]($movingItem); strategy.moveItemAtIndexToIndex(movingIndex, destinationIndex); this._updateIndicesAfterIndex(movingIndex); that.option("selectedItems", that._getItemsByKeys(that._selection.getSelectedItemKeys(), that._selection.getSelectedItems())); if ("items" === changingOption) { that._simulateOptionChange(changingOption) } that._itemEventHandler($movingItem, "onItemReordered", { fromIndex: strategy.getIndex(movingIndex), toIndex: strategy.getIndex(destinationIndex) }, { excludeValidators: ["disabled", "readOnly"] }) })) } }); var _default = CollectionWidget; exports.default = _default; module.exports = exports.default; module.exports.default = exports.default;