UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

1,185 lines (1,181 loc) • 100 kB
/** * DevExtreme (cjs/__internal/grids/grid_core/editing/m_editing.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.editingModule = exports.dataControllerEditingExtenderMixin = void 0; var _click = require("../../../../common/core/events/click"); var _events_engine = _interopRequireDefault(require("../../../../common/core/events/core/events_engine")); var _pointer = _interopRequireDefault(require("../../../../common/core/events/pointer")); var _remove = require("../../../../common/core/events/remove"); var _index = require("../../../../common/core/events/utils/index"); var _message = _interopRequireDefault(require("../../../../common/core/localization/message")); var _array_utils = require("../../../../common/data/array_utils"); var _devices = _interopRequireDefault(require("../../../../core/devices")); var _dom_adapter = _interopRequireDefault(require("../../../../core/dom_adapter")); var _guid = _interopRequireDefault(require("../../../../core/guid")); var _renderer = _interopRequireDefault(require("../../../../core/renderer")); var _common = require("../../../../core/utils/common"); var _deferred = require("../../../../core/utils/deferred"); var _extend = require("../../../../core/utils/extend"); var iconUtils = _interopRequireWildcard(require("../../../../core/utils/icon")); var _iterator = require("../../../../core/utils/iterator"); var _object = require("../../../../core/utils/object"); var _type = require("../../../../core/utils/type"); var _dialog = require("../../../../ui/dialog"); var _themes = require("../../../../ui/themes"); var _m_dom = _interopRequireDefault(require("../../../core/utils/m_dom")); var _m_modules = _interopRequireDefault(require("../m_modules")); var _m_utils = _interopRequireDefault(require("../m_utils")); var _const = require("./const"); var _m_editing_utils = require("./m_editing_utils"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) { return null } var r = new WeakMap, t = new WeakMap; return (_getRequireWildcardCache = function(e) { return e ? t : r })(e) } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) { return e } if (null === e || "object" != typeof e && "function" != typeof e) { return { default: e } } var t = _getRequireWildcardCache(r); if (t && t.has(e)) { return t.get(e) } var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) { if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u] } } return n.default = e, t && t.set(e, n), n } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e } } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function(n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) { ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]) } } return n }, _extends.apply(null, arguments) } class EditingControllerImpl extends _m_modules.default.ViewController { init() { this._columnsController = this.getController("columns"); this._dataController = this.getController("data"); this._adaptiveColumnsController = this.getController("adaptiveColumns"); this._validatingController = this.getController("validating"); this._editorFactoryController = this.getController("editorFactory"); this._focusController = this.getController("focus"); this._keyboardNavigationController = this.getController("keyboardNavigation"); this._columnsResizerController = this.getController("columnsResizer"); this._errorHandlingController = this.getController("errorHandling"); this._rowsView = this.getView("rowsView"); this._headerPanelView = this.getView("headerPanel"); this._lastOperation = null; this._changes = []; if (this._deferreds) { this._deferreds.forEach((d => { d.reject("cancel") })) } this._deferreds = []; if (!this._dataChangedHandler) { this._dataChangedHandler = this._handleDataChanged.bind(this); this._dataController.changed.add(this._dataChangedHandler) } if (!this._saveEditorHandler) { this.createAction("onInitNewRow", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onRowInserting", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onRowInserted", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onEditingStart", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onRowUpdating", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onRowUpdated", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onRowRemoving", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onRowRemoved", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onSaved", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onSaving", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onEditCanceling", { excludeValidators: ["disabled", "readOnly"] }); this.createAction("onEditCanceled", { excludeValidators: ["disabled", "readOnly"] }) } this._updateEditColumn(); this._updateEditButtons(); if (!this._internalState) { this._internalState = new Map } this.component._optionsByReference[_const.EDITING_EDITROWKEY_OPTION_NAME] = true; this.component._optionsByReference[_const.EDITING_CHANGES_OPTION_NAME] = true } getEditMode() { const editMode = this.option("editing.mode") ?? _const.EDIT_MODE_ROW; if (_const.EDIT_MODES.includes(editMode)) { return editMode } return _const.EDIT_MODE_ROW } isCellBasedEditMode() { const editMode = this.getEditMode(); return _const.CELL_BASED_MODES.includes(editMode) } _getDefaultEditorTemplate() { return (container, options) => { const $editor = (0, _renderer.default)("<div>").appendTo(container); const editorOptions = (0, _extend.extend)({}, options.column, { value: options.value, setValue: options.setValue, row: options.row, parentType: "dataRow", width: null, readOnly: !options.setValue, isOnForm: options.isOnForm, id: options.id }); const needLabel = _const.REQUIRED_EDITOR_LABELLEDBY_MODES.includes(this.getEditMode()); if (needLabel) { editorOptions["aria-labelledby"] = options.column.headerId } this._editorFactoryController.createEditor($editor, editorOptions) } } _getNewRowPosition() { const newRowPosition = this.option("editing.newRowPosition"); const scrollingMode = this.option("scrolling.mode"); if ("virtual" === scrollingMode) { switch (newRowPosition) { case _const.PAGE_TOP_NEW_ROW_POSITION: return _const.VIEWPORT_TOP_NEW_ROW_POSITION; case _const.PAGE_BOTTOM_NEW_ROW_POSITION: return _const.VIEWPORT_BOTTOM_NEW_ROW_POSITION; default: return newRowPosition } } return newRowPosition } getChanges() { return this.option(_const.EDITING_CHANGES_OPTION_NAME) } getInsertRowCount() { const changes = this.option(_const.EDITING_CHANGES_OPTION_NAME); return changes.filter((change => "insert" === change.type)).length } resetChanges() { const changes = this.getChanges(); const needReset = null === changes || void 0 === changes ? void 0 : changes.length; if (needReset) { this._silentOption(_const.EDITING_CHANGES_OPTION_NAME, []); this._internalState.clear() } } _getInternalData(key) { return this._internalState.get((0, _common.getKeyHash)(key)) } _addInternalData(params) { const internalData = this._getInternalData(params.key); if (internalData) { return (0, _extend.extend)(internalData, params) } this._internalState.set((0, _common.getKeyHash)(params.key), params); return params } _getOldData(key) { var _this$_getInternalDat; return null === (_this$_getInternalDat = this._getInternalData(key)) || void 0 === _this$_getInternalDat ? void 0 : _this$_getInternalDat.oldData } getUpdatedData(data) { const key = this._dataController.keyOf(data); const changes = this.getChanges(); const editIndex = _m_utils.default.getIndexByKey(key, changes); if (changes[editIndex]) { return (0, _array_utils.createObjectWithChanges)(data, changes[editIndex].data) } return data } getInsertedData() { return this.getChanges().filter((change => change.data && change.type === _const.DATA_EDIT_DATA_INSERT_TYPE)).map((change => change.data)) } getRemovedData() { return this.getChanges().filter((change => this._getOldData(change.key) && change.type === _const.DATA_EDIT_DATA_REMOVE_TYPE)).map((change => this._getOldData(change.key))) } _fireDataErrorOccurred(arg) { if ("cancel" === arg) { return } const $popupContent = this.getPopupContent(); this._dataController.dataErrorOccurred.fire(arg, $popupContent) } _needToCloseEditableCell($targetElement) {} _closeEditItem($targetElement) {} _handleDataChanged(args) {} _isDefaultButtonVisible(button, options) { let result = true; switch (button.name) { case "delete": result = this.allowDeleting(options); break; case "undelete": result = false } return result } isPopupEditMode() { const editMode = this.option("editing.mode"); return editMode === _const.EDIT_MODE_POPUP } _isButtonVisible(button, options) { const { visible: visible } = button; if (!(0, _type.isDefined)(visible)) { return this._isDefaultButtonVisible(button, options) } return (0, _type.isFunction)(visible) ? visible.call(button, { component: options.component, row: options.row, column: options.column }) : visible } _isButtonDisabled(button, options) { const { disabled: disabled } = button; return (0, _type.isFunction)(disabled) ? disabled.call(button, { component: options.component, row: options.row, column: options.column }) : !!disabled } _getButtonConfig(button, options) { const config = (0, _type.isObject)(button) ? button : {}; const buttonName = (0, _m_editing_utils.getButtonName)(button); const editingTexts = (0, _m_editing_utils.getEditingTexts)(options); const methodName = _const.METHOD_NAMES[buttonName]; const editingOptions = this.option("editing"); const actionName = _const.ACTION_OPTION_NAMES[buttonName]; const allowAction = actionName ? editingOptions[actionName] : true; return (0, _extend.extend)({ name: buttonName, text: editingTexts[buttonName], cssClass: _const.EDIT_LINK_CLASS[buttonName] }, { onClick: methodName && (e => { const { event: event } = e; event.stopPropagation(); event.preventDefault(); setTimeout((() => { options.row && allowAction && this[methodName] && this[methodName](options.row.rowIndex) })) }) }, config) } _getEditingButtons(options) { let buttonIndex; const haveCustomButtons = !!options.column.buttons; let buttons = (options.column.buttons || []).slice(); if (haveCustomButtons) { buttonIndex = (0, _m_editing_utils.getButtonIndex)(buttons, "edit"); if (buttonIndex >= 0) { if ((0, _m_editing_utils.getButtonIndex)(buttons, "save") < 0) { buttons.splice(buttonIndex + 1, 0, "save") } if ((0, _m_editing_utils.getButtonIndex)(buttons, "cancel") < 0) { buttons.splice((0, _m_editing_utils.getButtonIndex)(buttons, "save") + 1, 0, "cancel") } } buttonIndex = (0, _m_editing_utils.getButtonIndex)(buttons, "delete"); if (buttonIndex >= 0 && (0, _m_editing_utils.getButtonIndex)(buttons, "undelete") < 0) { buttons.splice(buttonIndex + 1, 0, "undelete") } } else { buttons = _const.BUTTON_NAMES.slice() } return buttons.map((button => this._getButtonConfig(button, options))) } _renderEditingButtons($container, buttons, options, change) { buttons.forEach((button => { if (this._isButtonVisible(button, options)) { this._createButton($container, button, options, change) } })) } _getEditCommandCellTemplate() { return (container, options, change) => { const $container = (0, _renderer.default)(container); if ("data" === options.rowType) { const buttons = this._getEditingButtons(options); this._renderEditingButtons($container, buttons, options, change); if (options.watch) { const dispose = options.watch((() => buttons.map((button => ({ visible: this._isButtonVisible(button, options), disabled: this._isButtonDisabled(button, options) })))), (() => { $container.empty(); this._renderEditingButtons($container, buttons, options) })); _events_engine.default.on($container, _remove.removeEvent, dispose) } } else { _m_utils.default.setEmptyText($container) } } } isRowBasedEditMode() { const editMode = this.getEditMode(); return _const.ROW_BASED_MODES.includes(editMode) } getFirstEditableColumnIndex() { let columnIndex; const visibleColumns = this._columnsController.getVisibleColumns(); (0, _iterator.each)(visibleColumns, ((index, column) => { if (column.allowEditing) { columnIndex = index; return false } })); return columnIndex } getFirstEditableCellInRow(rowIndex) { var _this$_rowsView; const columnIndex = this.getFirstEditableColumnIndex(); return null === (_this$_rowsView = this._rowsView) || void 0 === _this$_rowsView ? void 0 : _this$_rowsView._getCellElement(rowIndex || 0, columnIndex) } getFocusedCellInRow(rowIndex) { return this.getFirstEditableCellInRow(rowIndex) } getIndexByKey(key, items) { return _m_utils.default.getIndexByKey(key, items) } hasChanges(rowIndex) { const changes = this.getChanges(); let result = false; for (let i = 0; i < (null === changes || void 0 === changes ? void 0 : changes.length); i++) { if (changes[i].type && (!(0, _type.isDefined)(rowIndex) || this._dataController.getRowIndexByKey(changes[i].key) === rowIndex)) { result = true; break } } return result } dispose() { super.dispose(); clearTimeout(this._inputFocusTimeoutID); _events_engine.default.off(_dom_adapter.default.getDocument(), _pointer.default.up, this._pointerUpEditorHandler); _events_engine.default.off(_dom_adapter.default.getDocument(), _pointer.default.down, this._pointerDownEditorHandler); _events_engine.default.off(_dom_adapter.default.getDocument(), _click.name, this._saveEditorHandler) } _silentOption(name, value) { if ("editing.changes" === name) { this._changes = (0, _object.deepExtendArraySafe)([], value) } super._silentOption(name, value) } optionChanged(args) { if ("editing" === args.name) { const { fullName: fullName } = args; if (fullName === _const.EDITING_EDITROWKEY_OPTION_NAME) { this._handleEditRowKeyChange(args) } else if (fullName === _const.EDITING_CHANGES_OPTION_NAME) { const isEqual = (0, _common.equalByValue)(args.value, this._changes, { maxDepth: 4 }); if (!isEqual) { this._changes = (0, _object.deepExtendArraySafe)([], args.value); this._handleChangesChange(args) } } else if (!args.handled) { this._columnsController.reinit(); this.init(); this.resetChanges(); this._resetEditColumnName(); this._resetEditRowKey() } args.handled = true } else { super.optionChanged(args) } } _handleEditRowKeyChange(args) { const rowIndex = this._dataController.getRowIndexByKey(args.value); const oldRowIndexCorrection = this._getEditRowIndexCorrection(); const oldRowIndex = this._dataController.getRowIndexByKey(args.previousValue) + oldRowIndexCorrection; if ((0, _type.isDefined)(args.value)) { if (args.value !== args.previousValue) { this._editRowFromOptionChanged(rowIndex, oldRowIndex) } } else { this.cancelEditData() } } _handleChangesChange(args) { const dataController = this._dataController; const changes = args.value; if (!args.value.length && !args.previousValue.length) { return } changes.forEach((change => { if ("insert" === change.type) { this._addInsertInfo(change) } else { var _dataController$items; const items = dataController.getCachedStoreData() || (null === (_dataController$items = dataController.items()) || void 0 === _dataController$items ? void 0 : _dataController$items.map((item => item.data))); const rowIndex = _m_utils.default.getIndexByKey(change.key, items, dataController.key()); this._addInternalData({ key: change.key, oldData: items[rowIndex] }) } })); dataController.updateItems({ repaintChangesOnly: true, isLiveUpdate: false, isOptionChanged: true }) } publicMethods() { return ["addRow", "deleteRow", "undeleteRow", "editRow", "saveEditData", "cancelEditData", "hasEditData"] } refresh() { if (!(0, _type.isDefined)(this._pageIndex)) { return } this._refreshCore.apply(this, arguments) } _refreshCore(params) {} isEditing() { const isEditRowKeyDefined = (0, _type.isDefined)(this.option(_const.EDITING_EDITROWKEY_OPTION_NAME)); return isEditRowKeyDefined } isEditRow(rowIndex) { return false } _setEditRowKey(value, silent) { if (silent) { this._silentOption(_const.EDITING_EDITROWKEY_OPTION_NAME, value) } else { this.option(_const.EDITING_EDITROWKEY_OPTION_NAME, value) } if (this._refocusEditCell) { this._refocusEditCell = false; this._focusEditingCell() } } _setEditRowKeyByIndex(rowIndex, silent) { const key = this._dataController.getKeyByRowIndex(rowIndex); if (void 0 === key) { this._dataController.fireError("E1043"); return } this._setEditRowKey(key, silent) } getEditRowIndex() { return this._getVisibleEditRowIndex() } getEditFormRowIndex() { return -1 } isEditRowByIndex(rowIndex) { const key = this._dataController.getKeyByRowIndex(rowIndex); const isKeyEqual = (0, _type.isDefined)(key) && (0, _common.equalByValue)(this.option(_const.EDITING_EDITROWKEY_OPTION_NAME), key); if (isKeyEqual) { return this._getVisibleEditRowIndex() === rowIndex } return isKeyEqual } isEditCell(visibleRowIndex, columnIndex) { return this.isEditRowByIndex(visibleRowIndex) && this._getVisibleEditColumnIndex() === columnIndex } getPopupContent() {} _isProcessedItem(item) { return false } _getInsertRowIndex(items, change, isProcessedItems) { let result = -1; const dataController = this._dataController; const key = this._getInsertAfterOrBeforeKey(change); if (!(0, _type.isDefined)(key) && 0 === items.length) { result = 0 } else if ((0, _type.isDefined)(key)) { items.some(((item, index) => { const isProcessedItem = isProcessedItems || this._isProcessedItem(item); if ((0, _type.isObject)(item)) { if (isProcessedItem || (0, _type.isDefined)(item[_const.INSERT_INDEX])) { if ((0, _common.equalByValue)(item.key, key)) { result = index } } else if ((0, _common.equalByValue)(dataController.keyOf(item), key)) { result = index } } if (result >= 0) { const nextItem = items[result + 1]; if (nextItem && ("detail" === nextItem.rowType || "detailAdaptive" === nextItem.rowType) && (0, _type.isDefined)(change.insertAfterKey)) { return } if ((0, _type.isDefined)(change.insertAfterKey)) { result += 1 } return true } })) } return result } _generateNewItem(key) { var _this$_getInternalDat2; const item = { key: key }; const insertInfo = null === (_this$_getInternalDat2 = this._getInternalData(key)) || void 0 === _this$_getInternalDat2 ? void 0 : _this$_getInternalDat2.insertInfo; if (null !== insertInfo && void 0 !== insertInfo && insertInfo[_const.INSERT_INDEX]) { item[_const.INSERT_INDEX] = insertInfo[_const.INSERT_INDEX] } return item } _getLoadedRowIndex(items, change, isProcessedItems) { let loadedRowIndex = this._getInsertRowIndex(items, change, isProcessedItems); const dataController = this._dataController; if (loadedRowIndex < 0) { const newRowPosition = this._getNewRowPosition(); const pageIndex = dataController.pageIndex(); const insertAfterOrBeforeKey = this._getInsertAfterOrBeforeKey(change); if (newRowPosition !== _const.LAST_NEW_ROW_POSITION && 0 === pageIndex && !(0, _type.isDefined)(insertAfterOrBeforeKey)) { loadedRowIndex = 0 } else if (newRowPosition === _const.LAST_NEW_ROW_POSITION && dataController.isLastPageLoaded()) { loadedRowIndex = items.length } } return loadedRowIndex } processItems(items, e) { const { changeType: changeType } = e; this.update(changeType); const changes = this.getChanges(); changes.forEach((change => { var _this$_getInternalDat3; const isInsert = change.type === _const.DATA_EDIT_DATA_INSERT_TYPE; if (!isInsert) { return } let { key: key } = change; let insertInfo = null === (_this$_getInternalDat3 = this._getInternalData(key)) || void 0 === _this$_getInternalDat3 ? void 0 : _this$_getInternalDat3.insertInfo; if (!(0, _type.isDefined)(key) || !(0, _type.isDefined)(insertInfo)) { insertInfo = this._addInsertInfo(change); key = insertInfo.key } const loadedRowIndex = this._getLoadedRowIndex(items, change); const item = this._generateNewItem(key); if (loadedRowIndex >= 0) { items.splice(loadedRowIndex, 0, item) } })); return items } processDataItem(item, options, generateDataValues) { const columns = options.visibleColumns; const key = item.data[_const.INSERT_INDEX] ? item.data.key : item.key; const changes = this.getChanges(); const editIndex = _m_utils.default.getIndexByKey(key, changes); item.isEditing = false; if (editIndex >= 0) { this._processDataItemCore(item, changes[editIndex], key, columns, generateDataValues) } } _processDataItemCore(item, change, key, columns, generateDataValues) { const { data: data, type: type } = change; switch (type) { case _const.DATA_EDIT_DATA_INSERT_TYPE: item.isNewRow = true; item.key = key; item.data = data; break; case _const.DATA_EDIT_DATA_UPDATE_TYPE: item.modified = true; item.oldData = item.data; item.data = (0, _array_utils.createObjectWithChanges)(item.data, data); item.modifiedValues = generateDataValues(data, columns, true); break; case _const.DATA_EDIT_DATA_REMOVE_TYPE: item.removed = true } } _initNewRow(options) { this.executeAction("onInitNewRow", options); if (options.promise) { const deferred = new _deferred.Deferred; (0, _deferred.when)((0, _deferred.fromPromise)(options.promise)).done(deferred.resolve).fail((0, _m_editing_utils.createFailureHandler)(deferred)).fail((arg => this._fireDataErrorOccurred(arg))); return deferred } } _createInsertInfo() { const insertInfo = {}; insertInfo[_const.INSERT_INDEX] = this._getInsertIndex(); return insertInfo } _addInsertInfo(change, parentKey) { var _this$_getInternalDat4; let insertInfo; change.key = this.getChangeKeyValue(change); const { key: key } = change; insertInfo = null === (_this$_getInternalDat4 = this._getInternalData(key)) || void 0 === _this$_getInternalDat4 ? void 0 : _this$_getInternalDat4.insertInfo; if (!(0, _type.isDefined)(insertInfo)) { const insertAfterOrBeforeKey = this._getInsertAfterOrBeforeKey(change); insertInfo = this._createInsertInfo(); if (!(0, _type.isDefined)(insertAfterOrBeforeKey)) { this._setInsertAfterOrBeforeKey(change, parentKey) } } this._addInternalData({ insertInfo: insertInfo, key: key }); return { insertInfo: insertInfo, key: key } } getChangeKeyValue(change) { if ((0, _type.isDefined)(change.key)) { return change.key } const keyExpr = this._dataController.key(); let keyValue; if (change.data && keyExpr && !Array.isArray(keyExpr)) { keyValue = change.data[keyExpr] } if (!(0, _type.isDefined)(keyValue)) { keyValue = (0, _m_editing_utils.generateNewRowTempKey)() } return keyValue } _setInsertAfterOrBeforeKey(change, parentKey) { const rowsView = this.getView("rowsView"); const dataController = this._dataController; const allItems = dataController.items(true); const newRowPosition = this._getNewRowPosition(); switch (newRowPosition) { case _const.FIRST_NEW_ROW_POSITION: case _const.LAST_NEW_ROW_POSITION: break; case _const.PAGE_TOP_NEW_ROW_POSITION: case _const.PAGE_BOTTOM_NEW_ROW_POSITION: if (allItems.length) { const itemIndex = newRowPosition === _const.PAGE_TOP_NEW_ROW_POSITION ? 0 : allItems.length - 1; change[0 === itemIndex ? "insertBeforeKey" : "insertAfterKey"] = allItems[itemIndex].key } break; default: { const isViewportBottom = newRowPosition === _const.VIEWPORT_BOTTOM_NEW_ROW_POSITION; let visibleItemIndex = isViewportBottom ? null === rowsView || void 0 === rowsView ? void 0 : rowsView.getBottomVisibleItemIndex() : null === rowsView || void 0 === rowsView ? void 0 : rowsView.getTopVisibleItemIndex(); const row = dataController.getVisibleRows()[visibleItemIndex]; if (row && (!row.isEditing && "detail" === row.rowType || "detailAdaptive" === row.rowType)) { visibleItemIndex++ } const insertKey = dataController.getKeyByRowIndex(visibleItemIndex); if ((0, _type.isDefined)(insertKey)) { change.insertBeforeKey = insertKey } } } } _getInsertIndex() { let maxInsertIndex = 0; this.getChanges().forEach((editItem => { var _this$_getInternalDat5; const insertInfo = null === (_this$_getInternalDat5 = this._getInternalData(editItem.key)) || void 0 === _this$_getInternalDat5 ? void 0 : _this$_getInternalDat5.insertInfo; if ((0, _type.isDefined)(insertInfo) && editItem.type === _const.DATA_EDIT_DATA_INSERT_TYPE && insertInfo[_const.INSERT_INDEX] > maxInsertIndex) { maxInsertIndex = insertInfo[_const.INSERT_INDEX] } })); return maxInsertIndex + 1 } _getInsertAfterOrBeforeKey(insertChange) { return insertChange.insertAfterKey ?? insertChange.insertBeforeKey } _getPageIndexToInsertRow() { const newRowPosition = this._getNewRowPosition(); const dataController = this._dataController; const pageIndex = dataController.pageIndex(); const lastPageIndex = dataController.pageCount() - 1; if (newRowPosition === _const.FIRST_NEW_ROW_POSITION && 0 !== pageIndex) { return 0 } if (newRowPosition === _const.LAST_NEW_ROW_POSITION && pageIndex !== lastPageIndex) { return lastPageIndex } return -1 } addRow(parentKey) { const dataController = this._dataController; const store = dataController.store(); if (!store) { dataController.fireError("E1052", this.component.NAME); return (new _deferred.Deferred).reject() } return this._addRow(parentKey) } _addRow(parentKey) { const dataController = this._dataController; const store = dataController.store(); const key = store && store.key(); const param = { data: {} }; const oldEditRowIndex = this._getVisibleEditRowIndex(); const deferred = new _deferred.Deferred; this.refresh({ allowCancelEditing: true }); if (!this._allowRowAdding()) { (0, _deferred.when)(this._navigateToNewRow(oldEditRowIndex)).done(deferred.resolve).fail(deferred.reject); return deferred.promise() } if (!key) { param.data.__KEY__ = String(new _guid.default) }(0, _deferred.when)(this._initNewRow(param, parentKey)).done((() => { if (this._allowRowAdding()) { (0, _deferred.when)(this._addRowCore(param.data, parentKey, oldEditRowIndex)).done(deferred.resolve).fail(deferred.reject) } else { deferred.reject("cancel") } })).fail(deferred.reject); return deferred.promise() } _allowRowAdding(params) { const insertIndex = this._getInsertIndex(); if (insertIndex > 1) { return false } return true } _addRowCore(data, parentKey, initialOldEditRowIndex) { const change = { data: data, type: _const.DATA_EDIT_DATA_INSERT_TYPE }; const editRowIndex = this._getVisibleEditRowIndex(); const insertInfo = this._addInsertInfo(change, parentKey); const { key: key } = insertInfo; this._setEditRowKey(key, true); this._addChange(change); return this._navigateToNewRow(initialOldEditRowIndex, change, editRowIndex) } _navigateToNewRow(oldEditRowIndex, change, editRowIndex) { const d = new _deferred.Deferred; const dataController = this._dataController; editRowIndex = editRowIndex ?? -1; change = change ?? this.getChanges().filter((c => c.type === _const.DATA_EDIT_DATA_INSERT_TYPE))[0]; if (!change) { return d.reject("cancel").promise() } const pageIndexToInsertRow = this._getPageIndexToInsertRow(); let rowIndex = this._getLoadedRowIndex(dataController.items(), change, true); const navigateToRowByKey = key => { var _this$_focusControlle; (0, _deferred.when)(null === (_this$_focusControlle = this._focusController) || void 0 === _this$_focusControlle ? void 0 : _this$_focusControlle.navigateToRow(key)).done((() => { rowIndex = dataController.getRowIndexByKey(change.key); d.resolve() })) }; const insertAfterOrBeforeKey = this._getInsertAfterOrBeforeKey(change); if (pageIndexToInsertRow >= 0) { dataController.pageIndex(pageIndexToInsertRow).done((() => { navigateToRowByKey(change.key) })).fail(d.reject) } else if (rowIndex < 0 && (0, _type.isDefined)(insertAfterOrBeforeKey)) { navigateToRowByKey(insertAfterOrBeforeKey) } else { dataController.updateItems({ changeType: "update", rowIndices: [oldEditRowIndex, editRowIndex, rowIndex] }); rowIndex = dataController.getRowIndexByKey(change.key); if (rowIndex < 0) { navigateToRowByKey(change.key) } else { d.resolve() } } d.done((() => { var _this$_rowsView2; null === (_this$_rowsView2 = this._rowsView) || void 0 === _this$_rowsView2 || _this$_rowsView2.waitAsyncTemplates(true).done((() => { this._showAddedRow(rowIndex); this._afterInsertRow(change.key) })) })); return d.promise() } _showAddedRow(rowIndex) { this._focusFirstEditableCellInRow(rowIndex) } _beforeFocusElementInRow(rowIndex) {} _focusFirstEditableCellInRow(rowIndex) { var _this$_keyboardNaviga; const dataController = this._dataController; const key = dataController.getKeyByRowIndex(rowIndex); const $firstCell = this.getFirstEditableCellInRow(rowIndex); null === (_this$_keyboardNaviga = this._keyboardNavigationController) || void 0 === _this$_keyboardNaviga || _this$_keyboardNaviga.focus($firstCell); this.option("focusedRowKey", key); this._editCellInProgress = true; this._delayedInputFocus($firstCell, (() => { rowIndex = dataController.getRowIndexByKey(key); this._editCellInProgress = false; this._beforeFocusElementInRow(rowIndex) })) } _isEditingStart(options) { this.executeAction("onEditingStart", options); return options.cancel } _beforeUpdateItems(rowIndices, rowIndex) {} _getVisibleEditColumnIndex() { const editColumnName = this.option(_const.EDITING_EDITCOLUMNNAME_OPTION_NAME); if (!(0, _type.isDefined)(editColumnName)) { return -1 } return this._columnsController.getVisibleColumnIndex(editColumnName) } _setEditColumnNameByIndex(index, silent) { var _visibleColumns$index; const visibleColumns = this._columnsController.getVisibleColumns(); this._setEditColumnName(null === (_visibleColumns$index = visibleColumns[index]) || void 0 === _visibleColumns$index ? void 0 : _visibleColumns$index.name, silent) } _setEditColumnName(name, silent) { if (silent) { this._silentOption(_const.EDITING_EDITCOLUMNNAME_OPTION_NAME, name) } else { this.option(_const.EDITING_EDITCOLUMNNAME_OPTION_NAME, name) } } _resetEditColumnName() { this._setEditColumnName(null, true) } _getEditColumn() { const editColumnName = this.option(_const.EDITING_EDITCOLUMNNAME_OPTION_NAME); return this._getColumnByName(editColumnName) } _getColumnByName(name) { const visibleColumns = this._columnsController.getVisibleColumns(); let editColumn; (0, _type.isDefined)(name) && visibleColumns.some((column => { if (column.name === name) { editColumn = column; return true } })); return editColumn } _getVisibleEditRowIndex(columnName) { const dataController = this._dataController; const editRowKey = this.option(_const.EDITING_EDITROWKEY_OPTION_NAME); const rowIndex = dataController.getRowIndexByKey(editRowKey); if (-1 === rowIndex) { return rowIndex } return rowIndex + this._getEditRowIndexCorrection(columnName) } _getEditRowIndexCorrection(columnName) { const editColumn = columnName ? this._getColumnByName(columnName) : this._getEditColumn(); const isColumnHidden = "adaptiveHidden" === (null === editColumn || void 0 === editColumn ? void 0 : editColumn.visibleWidth); return isColumnHidden ? 1 : 0 } _resetEditRowKey() { this._refocusEditCell = false; this._setEditRowKey(null, true) } _resetEditIndices() { this._resetEditColumnName(); this._resetEditRowKey() } editRow(rowIndex) { const dataController = this._dataController; const items = dataController.items(); const item = items[rowIndex]; const params = { data: item && item.data, cancel: false }; const oldRowIndex = this._getVisibleEditRowIndex(); if (!item) { return } if (rowIndex === oldRowIndex) { return true } if (void 0 === item.key) { this._dataController.fireError("E1043"); return } if (!item.isNewRow) { params.key = item.key } if (this._isEditingStart(params)) { return } this.resetChanges(); this.init(); this._resetEditColumnName(); this._pageIndex = dataController.pageIndex(); this._addInternalData({ key: item.key, oldData: item.oldData ?? item.data }); this._setEditRowKey(item.key) } _editRowFromOptionChanged(rowIndex, oldRowIndex) { const rowIndices = [oldRowIndex, rowIndex]; this._beforeUpdateItems(rowIndices, rowIndex, oldRowIndex); this._editRowFromOptionChangedCore(rowIndices, rowIndex) } _editRowFromOptionChangedCore(rowIndices, rowIndex, preventRendering) { this._needFocusEditor = true; this._dataController.updateItems({ changeType: "update", rowIndices: rowIndices, cancel: preventRendering }) } _focusEditorIfNeed() {} _showEditPopup(rowIndex, repaintForm) {} _repaintEditPopup() {} _getEditPopupHiddenHandler() { return e => { if (this.isEditing()) { this.cancelEditData() } } } _getPopupEditFormTemplate(rowIndex) {} _getSaveButtonConfig() { const buttonConfig = { text: this.option("editing.texts.saveRowChanges"), onClick: this.saveEditData.bind(this) }; if ((0, _themes.isFluent)((0, _themes.current)())) { buttonConfig.stylingMode = "contained"; buttonConfig.type = "default" } return buttonConfig } _getCancelButtonConfig() { const buttonConfig = { text: this.option("editing.texts.cancelRowChanges"), onClick: this.cancelEditData.bind(this) }; if ((0, _themes.isFluent)((0, _themes.current)())) { buttonConfig.stylingMode = "outlined" } return buttonConfig } _removeInternalData(key) { this._internalState.delete((0, _common.getKeyHash)(key)) } _updateInsertAfterOrBeforeKeys(changes, index) { const removeChange = changes[index]; changes.forEach((change => { if (change.type === _const.DATA_EDIT_DATA_INSERT_TYPE) { const insertAfterOrBeforeKey = this._getInsertAfterOrBeforeKey(change); if ((0, _common.equalByValue)(insertAfterOrBeforeKey, removeChange.key)) { change[(0, _type.isDefined)(change.insertAfterKey) ? "insertAfterKey" : "insertBeforeKey"] = this._getInsertAfterOrBeforeKey(removeChange) } } })) } _removeChange(index) { if (index >= 0) { const changes = [...this.getChanges()]; const { key: key } = changes[index]; this._removeInternalData(key); this._updateInsertAfterOrBeforeKeys(changes, index); changes.splice(index, 1); this._silentOption(_const.EDITING_CHANGES_OPTION_NAME, changes); if ((0, _common.equalByValue)(this.option(_const.EDITING_EDITROWKEY_OPTION_NAME), key)) { this._resetEditIndices() } } } executeOperation(deferred, func) { this._lastOperation && this._lastOperation.reject(); this._lastOperation = deferred; this.waitForDeferredOperations().done((() => { if ("rejected" === deferred.state()) { return } func(); this._lastOperation = null })).fail((() => { deferred.reject(); this._lastOperation = null })) } waitForDeferredOperations() { return (0, _deferred.when)(...this._deferreds) } _processCanceledEditingCell() {} _repaintEditCell(column, oldColumn, oldEditRowIndex) { if (!column || !column.showEditorAlways || oldColumn && !oldColumn.showEditorAlways) { this._editCellInProgress = true; this._needFocusEditor = true; this._editorFactoryController.loseFocus(); this._dataController.updateItems({ changeType: "update", rowIndices: [oldEditRowIndex, this._getVisibleEditRowIndex()] }) } else if (column !== oldColumn) { this._needFocusEditor = true; this._dataController.updateItems({ changeType: "update", rowIndices: [] }) } } _delayedInputFocus($cell, beforeFocusCallback, callBeforeFocusCallbackAlways) { const inputFocus = () => { if (beforeFocusCallback) { beforeFocusCallback() } if ($cell) { const $focusableElement = $cell.find(_const.FOCUSABLE_ELEMENT_SELECTOR).first(); _m_utils.default.focusAndSelectElement(this, $focusableElement) } this._beforeFocusCallback = null }; if (_devices.default.real().ios || _devices.default.real().android) { inputFocus() } else { if (this._beforeFocusCallback) { this._beforeFocusCallback() } clearTimeout(this._inputFocusTimeoutID); if (callBeforeFocusCallbackAlways) { this._beforeFocusCallback = beforeFocusCallback } this._inputFocusTimeoutID = setTimeout(inputFocus) } } _focusEditingCell(beforeFocusCallback, $editCell, callBeforeFocusCallbackAlways) { const editColumnIndex = this._getVisibleEditColumnIndex(); $editCell = $editCell || this._rowsView && this._rowsView._getCellElement(this._getVisibleEditRowIndex(), editColumnIndex); if ($editCell) { this._delayedInputFocus($editCell, beforeFocusCallback, callBeforeFocusCallbackAlways) } } deleteRow(rowIndex) { this._checkAndDeleteRow(rowIndex) } _checkAndDeleteRow(rowIndex) { const editingOptions = this.option("editing"); const editingTexts = null === editingOptions || void 0 === editingOptions ? void 0 : editingOptions.texts; const confirmDelete = null === editingOptions || void 0 === editingOptions ? void 0 : editingOptions.confirmDelete; const confirmDeleteMessage = null === editingTexts || void 0 === editingTexts ? void 0 : editingTexts.confirmDeleteMessage; const item = this._dataController.items()[rowIndex]; const allowDeleting = !this.isEditing() || item.isNewRow; if (item && allowDeleting) { if (!confirmDelete || !confirmDeleteMessage) { this._deleteRowCore(rowIndex) } else { const confirmDeleteTitle = editingTexts && editingTexts.confirmDeleteTitle; const showDialogTitle = (0, _type.isDefined)(confirmDeleteTitle) && confirmDeleteTitle.length > 0; (0, _dialog.confirm)(confirmDeleteMessage, confirmDeleteTitle, showDialogTitle).done((confirmResult => { if (confirmResult) { this._deleteRowCore(rowIndex) } })) } } } _deleteRowCore(rowIndex) { const dataController = this._dataController; const item = dataController.items()[rowIndex]; const key = item && item.key; const oldEditRowIndex = this._getVisibleEditRowIndex(); this.refresh(); const changes = this.getChanges(); const editIndex = _m_utils.default.getIndexByKey(key, changes); if (editIndex >= 0) { if (changes[editIndex].type === _const.DATA_EDIT_DATA_INSERT_TYPE) { this._removeChange(editIndex) } else { this._addChange({ key: key, type: _const.DATA_EDIT_DATA_REMOVE_TYPE }) } } else { this._addChange({ key: key, oldData: item.data, type: _const.DATA_EDIT_DATA_REMOVE_TYPE }) } return this._afterDeleteRow(rowIndex, oldEditRowIndex) } _afterDeleteRow(rowInd