devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
1,185 lines (1,181 loc) • 100 kB
JavaScript
/**
* 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