devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
1,145 lines (1,144 loc) • 106 kB
JavaScript
/**
* DevExtreme (esm/ui/grid_core/ui.grid_core.editing.js)
* Version: 22.1.9
* Build date: Tue Apr 18 2023
*
* Copyright (c) 2012 - 2023 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import _extends from "@babel/runtime/helpers/esm/extends";
import $ from "../../core/renderer";
import domAdapter from "../../core/dom_adapter";
import eventsEngine from "../../events/core/events_engine";
import Guid from "../../core/guid";
import {
resetActiveElement
} from "../../core/utils/dom";
import {
isDefined,
isObject,
isFunction,
isEmptyObject
} from "../../core/utils/type";
import {
each
} from "../../core/utils/iterator";
import {
extend
} from "../../core/utils/extend";
import modules from "./ui.grid_core.modules";
import {
name as clickEventName
} from "../../events/click";
import pointerEvents from "../../events/pointer";
import gridCoreUtils from "./ui.grid_core.utils";
import {
createObjectWithChanges
} from "../../data/array_utils";
import {
addNamespace
} from "../../events/utils/index";
import {
confirm
} from "../dialog";
import messageLocalization from "../../localization/message";
import devices from "../../core/devices";
import {
when,
Deferred,
fromPromise
} from "../../core/utils/deferred";
import {
equalByValue,
noop
} from "../../core/utils/common";
import * as iconUtils from "../../core/utils/icon";
import {
EDITOR_CELL_CLASS,
ROW_CLASS,
EDIT_FORM_CLASS,
DATA_EDIT_DATA_INSERT_TYPE,
DATA_EDIT_DATA_REMOVE_TYPE,
EDITING_POPUP_OPTION_NAME,
EDITING_EDITROWKEY_OPTION_NAME,
EDITING_EDITCOLUMNNAME_OPTION_NAME,
TARGET_COMPONENT_NAME,
EDITORS_INPUT_SELECTOR,
FOCUSABLE_ELEMENT_SELECTOR,
EDIT_MODE_ROW,
EDIT_MODES,
ROW_BASED_MODES,
FIRST_NEW_ROW_POSITION,
LAST_NEW_ROW_POSITION,
PAGE_BOTTOM_NEW_ROW_POSITION,
PAGE_TOP_NEW_ROW_POSITION,
VIEWPORT_BOTTOM_NEW_ROW_POSITION,
VIEWPORT_TOP_NEW_ROW_POSITION
} from "./ui.grid_core.editing_constants";
import {
deepExtendArraySafe
} from "../../core/utils/object";
var READONLY_CLASS = "readonly";
var LINK_CLASS = "dx-link";
var ROW_SELECTED = "dx-selection";
var EDIT_BUTTON_CLASS = "dx-edit-button";
var COMMAND_EDIT_CLASS = "dx-command-edit";
var COMMAND_EDIT_WITH_ICONS_CLASS = COMMAND_EDIT_CLASS + "-with-icons";
var INSERT_INDEX = "__DX_INSERT_INDEX__";
var ROW_INSERTED = "dx-row-inserted";
var ROW_MODIFIED = "dx-row-modified";
var CELL_MODIFIED = "dx-cell-modified";
var EDITING_NAMESPACE = "dxDataGridEditing";
var CELL_FOCUS_DISABLED_CLASS = "dx-cell-focus-disabled";
var DATA_EDIT_DATA_UPDATE_TYPE = "update";
var DEFAULT_START_EDIT_ACTION = "click";
var EDIT_LINK_CLASS = {
save: "dx-link-save",
cancel: "dx-link-cancel",
edit: "dx-link-edit",
undelete: "dx-link-undelete",
delete: "dx-link-delete",
add: "dx-link-add"
};
var EDIT_ICON_CLASS = {
save: "save",
cancel: "revert",
edit: "edit",
undelete: "revert",
delete: "trash",
add: "add"
};
var METHOD_NAMES = {
edit: "editRow",
delete: "deleteRow",
undelete: "undeleteRow",
save: "saveEditData",
cancel: "cancelEditData",
add: "addRowByRowIndex"
};
var ACTION_OPTION_NAMES = {
add: "allowAdding",
edit: "allowUpdating",
delete: "allowDeleting"
};
var BUTTON_NAMES = ["edit", "save", "cancel", "delete", "undelete"];
var EDITING_CHANGES_OPTION_NAME = "editing.changes";
var createFailureHandler = function(deferred) {
return function(arg) {
var error = arg instanceof Error ? arg : new Error(arg && String(arg) || "Unknown error");
deferred.reject(error)
}
};
var isEditingCell = function(isEditRow, cellOptions) {
return cellOptions.isEditing || isEditRow && cellOptions.column.allowEditing
};
var isEditingOrShowEditorAlwaysDataCell = function(isEditRow, cellOptions) {
var isCommandCell = !!cellOptions.column.command;
var isEditing = isEditingCell(isEditRow, cellOptions);
var isEditorCell = !isCommandCell && (isEditing || cellOptions.column.showEditorAlways);
return "data" === cellOptions.rowType && isEditorCell
};
var EditingController = modules.ViewController.inherit(function() {
var getButtonIndex = (buttons, name) => {
var result = -1;
buttons.some((button, index) => {
if (getButtonName(button) === name) {
result = index;
return true
}
});
return result
};
function getButtonName(button) {
return isObject(button) ? button.name : button
}
return {
init: function() {
this._columnsController = this.getController("columns");
this._dataController = this.getController("data");
this._rowsView = this.getView("rowsView");
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 = []
}
this.component._optionsByReference[EDITING_EDITROWKEY_OPTION_NAME] = true;
this.component._optionsByReference[EDITING_CHANGES_OPTION_NAME] = true
},
getEditMode: function() {
var editMode = this.option("editing.mode");
if (-1 !== EDIT_MODES.indexOf(editMode)) {
return editMode
}
return EDIT_MODE_ROW
},
_getDefaultEditorTemplate: function() {
return (container, options) => {
var $editor = $("<div>").appendTo(container);
this.getController("editorFactory").createEditor($editor, 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
}))
}
},
_getNewRowPosition: function() {
var newRowPosition = this.option("editing.newRowPosition");
var scrollingMode = this.option("scrolling.mode");
if ("virtual" === scrollingMode) {
switch (newRowPosition) {
case PAGE_TOP_NEW_ROW_POSITION:
return VIEWPORT_TOP_NEW_ROW_POSITION;
case PAGE_BOTTOM_NEW_ROW_POSITION:
return VIEWPORT_BOTTOM_NEW_ROW_POSITION;
default:
return newRowPosition
}
}
return newRowPosition
},
getChanges: function() {
return this.option(EDITING_CHANGES_OPTION_NAME)
},
getInsertRowCount: function() {
var changes = this.option(EDITING_CHANGES_OPTION_NAME);
return changes.filter(change => "insert" === change.type).length
},
resetChanges: function() {
var changes = this.getChanges();
var needReset = null === changes || void 0 === changes ? void 0 : changes.length;
if (needReset) {
this._silentOption(EDITING_CHANGES_OPTION_NAME, [])
}
},
_getInternalData: function(key) {
return this._internalState.filter(item => equalByValue(item.key, key))[0]
},
_addInternalData: function(params) {
var internalData = this._getInternalData(params.key);
if (internalData) {
return extend(internalData, params)
}
this._internalState.push(params);
return params
},
_getOldData: function(key) {
var _this$_getInternalDat;
return null === (_this$_getInternalDat = this._getInternalData(key)) || void 0 === _this$_getInternalDat ? void 0 : _this$_getInternalDat.oldData
},
getUpdatedData: function(data) {
var key = this._dataController.keyOf(data);
var changes = this.getChanges();
var editIndex = gridCoreUtils.getIndexByKey(key, changes);
if (changes[editIndex]) {
return createObjectWithChanges(data, changes[editIndex].data)
}
return data
},
getInsertedData: function() {
return this.getChanges().filter(change => change.data && change.type === DATA_EDIT_DATA_INSERT_TYPE).map(change => change.data)
},
getRemovedData: function() {
return this.getChanges().filter(change => this._getOldData(change.key) && change.type === DATA_EDIT_DATA_REMOVE_TYPE).map(change => this._getOldData(change.key))
},
_fireDataErrorOccurred: function(arg) {
if ("cancel" === arg) {
return
}
var $popupContent = this.getPopupContent();
this._dataController.dataErrorOccurred.fire(arg, $popupContent)
},
_needToCloseEditableCell: noop,
_closeEditItem: noop,
_handleDataChanged: noop,
_isDefaultButtonVisible: function(button, options) {
var result = true;
switch (button.name) {
case "delete":
result = this.allowDeleting(options);
break;
case "undelete":
result = false
}
return result
},
_isButtonVisible: function(button, options) {
var visible = button.visible;
if (!isDefined(visible)) {
return this._isDefaultButtonVisible(button, options)
}
return isFunction(visible) ? visible.call(button, {
component: options.component,
row: options.row,
column: options.column
}) : visible
},
_isButtonDisabled: function(button, options) {
var disabled = button.disabled;
return isFunction(disabled) ? disabled.call(button, {
component: options.component,
row: options.row,
column: options.column
}) : !!disabled
},
_getButtonConfig: function(button, options) {
var config = isObject(button) ? button : {};
var buttonName = getButtonName(button);
var editingTexts = (options => {
var editingTexts = options.component.option("editing.texts") || {};
return {
save: editingTexts.saveRowChanges,
cancel: editingTexts.cancelRowChanges,
edit: editingTexts.editRow,
undelete: editingTexts.undeleteRow,
delete: editingTexts.deleteRow,
add: editingTexts.addRowToNode
}
})(options);
var methodName = METHOD_NAMES[buttonName];
var editingOptions = this.option("editing");
var actionName = ACTION_OPTION_NAMES[buttonName];
var allowAction = actionName ? editingOptions[actionName] : true;
return extend({
name: buttonName,
text: editingTexts[buttonName],
cssClass: EDIT_LINK_CLASS[buttonName]
}, {
onClick: methodName && (e => {
var event = e.event;
event.stopPropagation();
event.preventDefault();
setTimeout(() => {
options.row && allowAction && this[methodName] && this[methodName](options.row.rowIndex)
})
})
}, config)
},
_getEditingButtons: function(options) {
var buttonIndex;
var haveCustomButtons = !!options.column.buttons;
var buttons = (options.column.buttons || []).slice();
if (haveCustomButtons) {
buttonIndex = getButtonIndex(buttons, "edit");
if (buttonIndex >= 0) {
if (getButtonIndex(buttons, "save") < 0) {
buttons.splice(buttonIndex + 1, 0, "save")
}
if (getButtonIndex(buttons, "cancel") < 0) {
buttons.splice(getButtonIndex(buttons, "save") + 1, 0, "cancel")
}
}
buttonIndex = getButtonIndex(buttons, "delete");
if (buttonIndex >= 0 && getButtonIndex(buttons, "undelete") < 0) {
buttons.splice(buttonIndex + 1, 0, "undelete")
}
} else {
buttons = BUTTON_NAMES.slice()
}
return buttons.map(button => this._getButtonConfig(button, options))
},
_renderEditingButtons: function($container, buttons, options, change) {
buttons.forEach(button => {
if (this._isButtonVisible(button, options)) {
this._createButton($container, button, options, change)
}
})
},
_getEditCommandCellTemplate: function() {
return (container, options, change) => {
var $container = $(container);
if ("data" === options.rowType) {
var buttons = this._getEditingButtons(options);
this._renderEditingButtons($container, buttons, options, change);
options.watch && options.watch(() => buttons.map(button => this._isButtonVisible(button, options)), () => {
$container.empty();
this._renderEditingButtons($container, buttons, options)
})
} else {
gridCoreUtils.setEmptyText($container)
}
}
},
isRowBasedEditMode: function() {
var editMode = this.getEditMode();
return -1 !== ROW_BASED_MODES.indexOf(editMode)
},
getFirstEditableColumnIndex: function() {
var columnsController = this.getController("columns");
var columnIndex;
var visibleColumns = columnsController.getVisibleColumns();
each(visibleColumns, (function(index, column) {
if (column.allowEditing) {
columnIndex = index;
return false
}
}));
return columnIndex
},
getFirstEditableCellInRow: function(rowIndex) {
var rowsView = this.getView("rowsView");
return rowsView && rowsView._getCellElement(rowIndex ? rowIndex : 0, this.getFirstEditableColumnIndex())
},
getFocusedCellInRow: function(rowIndex) {
return this.getFirstEditableCellInRow(rowIndex)
},
getIndexByKey: function(key, items) {
return gridCoreUtils.getIndexByKey(key, items)
},
hasChanges: function(rowIndex) {
var changes = this.getChanges();
var result = false;
for (var i = 0; i < (null === changes || void 0 === changes ? void 0 : changes.length); i++) {
if (changes[i].type && (!isDefined(rowIndex) || this._dataController.getRowIndexByKey(changes[i].key) === rowIndex)) {
result = true;
break
}
}
return result
},
dispose: function() {
this.callBase();
clearTimeout(this._inputFocusTimeoutID);
eventsEngine.off(domAdapter.getDocument(), pointerEvents.up, this._pointerUpEditorHandler);
eventsEngine.off(domAdapter.getDocument(), pointerEvents.down, this._pointerDownEditorHandler);
eventsEngine.off(domAdapter.getDocument(), clickEventName, this._saveEditorHandler)
},
_silentOption: function(name, value) {
if ("editing.changes" === name) {
this._changes = deepExtendArraySafe([], value)
}
this.callBase.apply(this, arguments)
},
optionChanged: function(args) {
if ("editing" === args.name) {
var fullName = args.fullName;
if (fullName === EDITING_EDITROWKEY_OPTION_NAME) {
this._handleEditRowKeyChange(args)
} else if (fullName === EDITING_CHANGES_OPTION_NAME) {
var isEqual = equalByValue(args.value, this._changes, -1);
if (!isEqual) {
this._changes = 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 {
this.callBase(args)
}
},
_handleEditRowKeyChange: function(args) {
var rowIndex = this._dataController.getRowIndexByKey(args.value);
var oldRowIndexCorrection = this._getEditRowIndexCorrection();
var oldRowIndex = this._dataController.getRowIndexByKey(args.previousValue) + oldRowIndexCorrection;
if (isDefined(args.value)) {
if (args.value !== args.previousValue) {
this._editRowFromOptionChanged(rowIndex, oldRowIndex)
}
} else {
this.cancelEditData()
}
},
_handleChangesChange: function(args) {
var dataController = this._dataController;
var changes = args.value;
if (!args.value.length && !args.previousValue.length) {
return
}
changes.forEach(change => {
if ("insert" === change.type) {
this._addInsertInfo(change)
} else {
var _items$rowIndex;
var items = dataController.items();
var rowIndex = dataController.getRowIndexByKey(change.key);
this._addInternalData({
key: change.key,
oldData: null === (_items$rowIndex = items[rowIndex]) || void 0 === _items$rowIndex ? void 0 : _items$rowIndex.data
})
}
});
dataController.updateItems({
repaintChangesOnly: true,
isLiveUpdate: false,
isOptionChanged: true
})
},
publicMethods: function() {
return ["addRow", "deleteRow", "undeleteRow", "editRow", "saveEditData", "cancelEditData", "hasEditData"]
},
refresh: function() {
if (!isDefined(this._pageIndex)) {
return
}
this._refreshCore.apply(this, arguments)
},
_refreshCore: noop,
isEditing: function() {
var isEditRowKeyDefined = isDefined(this.option(EDITING_EDITROWKEY_OPTION_NAME));
return isEditRowKeyDefined
},
isEditRow: function() {
return false
},
_setEditRowKey: function(value, silent) {
if (silent) {
this._silentOption(EDITING_EDITROWKEY_OPTION_NAME, value)
} else {
this.option(EDITING_EDITROWKEY_OPTION_NAME, value)
}
if (this._refocusEditCell) {
this._refocusEditCell = false;
this._focusEditingCell()
}
},
_setEditRowKeyByIndex: function(rowIndex, silent) {
var key = this._dataController.getKeyByRowIndex(rowIndex);
if (void 0 === key) {
this._dataController.fireError("E1043");
return
}
this._setEditRowKey(key, silent)
},
getEditRowIndex: function() {
return this._getVisibleEditRowIndex()
},
getEditFormRowIndex: function() {
return -1
},
isEditRowByIndex(rowIndex) {
var key = this._dataController.getKeyByRowIndex(rowIndex);
var isKeyEqual = isDefined(key) && equalByValue(this.option(EDITING_EDITROWKEY_OPTION_NAME), key);
if (isKeyEqual) {
return this._getVisibleEditRowIndex() === rowIndex
}
return isKeyEqual
},
isEditCell: function(visibleRowIndex, columnIndex) {
return this.isEditRowByIndex(visibleRowIndex) && this._getVisibleEditColumnIndex() === columnIndex
},
getPopupContent: noop,
_isProcessedItem: function(item) {
return false
},
_getInsertRowIndex: function(items, change, isProcessedItems) {
var result = -1;
var dataController = this._dataController;
var key = this._getInsertAfterOrBeforeKey(change);
if (!isDefined(key) && 0 === items.length) {
result = 0
} else if (isDefined(key)) {
items.some((item, index) => {
var isProcessedItem = isProcessedItems || this._isProcessedItem(item);
if (isObject(item)) {
if (isProcessedItem || isDefined(item[INSERT_INDEX])) {
if (equalByValue(item.key, key)) {
result = index
}
} else if (equalByValue(dataController.keyOf(item), key)) {
result = index
}
}
if (result >= 0) {
var nextItem = items[result + 1];
if (nextItem && ("detail" === nextItem.rowType || "detailAdaptive" === nextItem.rowType) && isDefined(change.insertAfterKey)) {
return
}
if (isDefined(change.insertAfterKey)) {
result += 1
}
return true
}
})
}
return result
},
_generateNewItem: function(key) {
var _this$_getInternalDat2;
var item = {
key: key
};
var insertInfo = null === (_this$_getInternalDat2 = this._getInternalData(key)) || void 0 === _this$_getInternalDat2 ? void 0 : _this$_getInternalDat2.insertInfo;
if (null !== insertInfo && void 0 !== insertInfo && insertInfo[INSERT_INDEX]) {
item[INSERT_INDEX] = insertInfo[INSERT_INDEX]
}
return item
},
_getLoadedRowIndex: function(items, change, isProcessedItems) {
var loadedRowIndex = this._getInsertRowIndex(items, change, isProcessedItems);
var dataController = this._dataController;
if (loadedRowIndex < 0) {
var newRowPosition = this._getNewRowPosition();
var pageIndex = dataController.pageIndex();
var insertAfterOrBeforeKey = this._getInsertAfterOrBeforeKey(change);
if (newRowPosition !== LAST_NEW_ROW_POSITION && 0 === pageIndex && !isDefined(insertAfterOrBeforeKey)) {
loadedRowIndex = 0
} else if (newRowPosition === LAST_NEW_ROW_POSITION && dataController.isLastPageLoaded()) {
loadedRowIndex = items.length
}
}
return loadedRowIndex
},
processItems: function(items, e) {
var changeType = e.changeType;
this.update(changeType);
var changes = this.getChanges();
changes.forEach(change => {
var _this$_getInternalDat3;
var isInsert = change.type === DATA_EDIT_DATA_INSERT_TYPE;
if (!isInsert) {
return
}
var key = change.key;
var insertInfo = null === (_this$_getInternalDat3 = this._getInternalData(key)) || void 0 === _this$_getInternalDat3 ? void 0 : _this$_getInternalDat3.insertInfo;
if (!isDefined(key) || !isDefined(insertInfo)) {
insertInfo = this._addInsertInfo(change);
key = insertInfo.key
}
var loadedRowIndex = this._getLoadedRowIndex(items, change);
var item = this._generateNewItem(key);
if (loadedRowIndex >= 0) {
items.splice(loadedRowIndex, 0, item)
}
});
return items
},
processDataItem: function(item, options, generateDataValues) {
var columns = options.visibleColumns;
var key = item.data[INSERT_INDEX] ? item.data.key : item.key;
var changes = this.getChanges();
var editIndex = gridCoreUtils.getIndexByKey(key, changes);
item.isEditing = false;
if (editIndex >= 0) {
this._processDataItemCore(item, changes[editIndex], key, columns, generateDataValues)
}
},
_processDataItemCore: function(item, change, key, columns, generateDataValues) {
var {
data: data,
type: type
} = change;
switch (type) {
case DATA_EDIT_DATA_INSERT_TYPE:
item.isNewRow = true;
item.key = key;
item.data = data;
break;
case DATA_EDIT_DATA_UPDATE_TYPE:
item.modified = true;
item.oldData = item.data;
item.data = createObjectWithChanges(item.data, data);
item.modifiedValues = generateDataValues(data, columns, true);
break;
case DATA_EDIT_DATA_REMOVE_TYPE:
item.removed = true
}
},
_initNewRow: function(options) {
this.executeAction("onInitNewRow", options);
if (options.promise) {
var deferred = new Deferred;
when(fromPromise(options.promise)).done(deferred.resolve).fail(createFailureHandler(deferred)).fail(arg => this._fireDataErrorOccurred(arg));
return deferred
}
},
_createInsertInfo: function() {
var insertInfo = {};
insertInfo[INSERT_INDEX] = this._getInsertIndex();
return insertInfo
},
_addInsertInfo: function(change, parentKey) {
var _this$_getInternalDat4;
var insertInfo;
var {
key: key
} = change;
if (!isDefined(key)) {
key = String(new Guid);
change.key = key
}
insertInfo = null === (_this$_getInternalDat4 = this._getInternalData(key)) || void 0 === _this$_getInternalDat4 ? void 0 : _this$_getInternalDat4.insertInfo;
if (!isDefined(insertInfo)) {
var insertAfterOrBeforeKey = this._getInsertAfterOrBeforeKey(change);
insertInfo = this._createInsertInfo();
if (!isDefined(insertAfterOrBeforeKey)) {
this._setInsertAfterOrBeforeKey(change, parentKey)
}
}
this._addInternalData({
insertInfo: insertInfo,
key: key
});
return {
insertInfo: insertInfo,
key: key
}
},
_setInsertAfterOrBeforeKey: function(change, parentKey) {
var dataController = this._dataController;
var allItems = dataController.items(true);
var rowsView = this.getView("rowsView");
var newRowPosition = this._getNewRowPosition();
switch (newRowPosition) {
case FIRST_NEW_ROW_POSITION:
case LAST_NEW_ROW_POSITION:
break;
case PAGE_TOP_NEW_ROW_POSITION:
case PAGE_BOTTOM_NEW_ROW_POSITION:
if (allItems.length) {
var itemIndex = newRowPosition === PAGE_TOP_NEW_ROW_POSITION ? 0 : allItems.length - 1;
change[0 === itemIndex ? "insertBeforeKey" : "insertAfterKey"] = allItems[itemIndex].key
}
break;
default:
var isViewportBottom = newRowPosition === VIEWPORT_BOTTOM_NEW_ROW_POSITION;
var visibleItemIndex = isViewportBottom ? null === rowsView || void 0 === rowsView ? void 0 : rowsView.getBottomVisibleItemIndex() : null === rowsView || void 0 === rowsView ? void 0 : rowsView.getTopVisibleItemIndex();
var row = dataController.getVisibleRows()[visibleItemIndex];
if (row && (!row.isEditing && "detail" === row.rowType || "detailAdaptive" === row.rowType)) {
visibleItemIndex++
}
var insertKey = dataController.getKeyByRowIndex(visibleItemIndex);
if (isDefined(insertKey)) {
change.insertBeforeKey = insertKey
}
}
},
_getInsertIndex: function() {
var maxInsertIndex = 0;
this.getChanges().forEach(editItem => {
var _this$_getInternalDat5;
var insertInfo = null === (_this$_getInternalDat5 = this._getInternalData(editItem.key)) || void 0 === _this$_getInternalDat5 ? void 0 : _this$_getInternalDat5.insertInfo;
if (isDefined(insertInfo) && editItem.type === DATA_EDIT_DATA_INSERT_TYPE && insertInfo[INSERT_INDEX] > maxInsertIndex) {
maxInsertIndex = insertInfo[INSERT_INDEX]
}
});
return maxInsertIndex + 1
},
_getInsertAfterOrBeforeKey: function(insertChange) {
var _insertChange$insertA;
return null !== (_insertChange$insertA = insertChange.insertAfterKey) && void 0 !== _insertChange$insertA ? _insertChange$insertA : insertChange.insertBeforeKey
},
_getPageIndexToInsertRow: function() {
var newRowPosition = this._getNewRowPosition();
var dataController = this._dataController;
var pageIndex = dataController.pageIndex();
var lastPageIndex = dataController.pageCount() - 1;
if (newRowPosition === FIRST_NEW_ROW_POSITION && 0 !== pageIndex) {
return 0
} else if (newRowPosition === LAST_NEW_ROW_POSITION && pageIndex !== lastPageIndex) {
return lastPageIndex
}
return -1
},
addRow: function(parentKey) {
var dataController = this._dataController;
var store = dataController.store();
if (!store) {
dataController.fireError("E1052", this.component.NAME);
return (new Deferred).reject()
}
return this._addRow(parentKey)
},
_addRow: function(parentKey) {
var dataController = this._dataController;
var store = dataController.store();
var key = store && store.key();
var param = {
data: {}
};
var oldEditRowIndex = this._getVisibleEditRowIndex();
var deferred = new Deferred;
this.refresh({
allowCancelEditing: true
});
if (!this._allowRowAdding()) {
when(this._navigateToNewRow(oldEditRowIndex)).done(deferred.resolve).fail(deferred.reject);
return deferred.promise()
}
if (!key) {
param.data.__KEY__ = String(new Guid)
}
when(this._initNewRow(param, parentKey)).done(() => {
if (this._allowRowAdding()) {
when(this._addRowCore(param.data, parentKey, oldEditRowIndex)).done(deferred.resolve).fail(deferred.reject)
} else {
deferred.reject("cancel")
}
}).fail(deferred.reject);
return deferred.promise()
},
_allowRowAdding: function() {
var insertIndex = this._getInsertIndex();
if (insertIndex > 1) {
return false
}
return true
},
_addRowCore: function(data, parentKey, initialOldEditRowIndex) {
var change = {
data: data,
type: DATA_EDIT_DATA_INSERT_TYPE
};
var editRowIndex = this._getVisibleEditRowIndex();
var insertInfo = this._addInsertInfo(change, parentKey);
var key = insertInfo.key;
this._setEditRowKey(key, true);
this._addChange(change);
return this._navigateToNewRow(initialOldEditRowIndex, change, editRowIndex)
},
_navigateToNewRow: function(oldEditRowIndex, change, editRowIndex) {
var _editRowIndex, _change;
var d = new Deferred;
var dataController = this._dataController;
var focusController = this.getController("focus");
editRowIndex = null !== (_editRowIndex = editRowIndex) && void 0 !== _editRowIndex ? _editRowIndex : -1;
change = null !== (_change = change) && void 0 !== _change ? _change : this.getChanges().filter(c => c.type === DATA_EDIT_DATA_INSERT_TYPE)[0];
if (!change) {
return d.reject("cancel").promise()
}
var pageIndexToInsertRow = this._getPageIndexToInsertRow();
var rowIndex = this._getLoadedRowIndex(dataController.items(), change, true);
var navigateToRowByKey = key => {
when(null === focusController || void 0 === focusController ? void 0 : focusController.navigateToRow(key)).done(() => {
rowIndex = dataController.getRowIndexByKey(change.key);
d.resolve()
})
};
var insertAfterOrBeforeKey = this._getInsertAfterOrBeforeKey(change);
if (pageIndexToInsertRow >= 0) {
dataController.pageIndex(pageIndexToInsertRow).done(() => {
navigateToRowByKey(change.key)
}).fail(d.reject)
} else if (rowIndex < 0 && 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$_rowsView;
null === (_this$_rowsView = this._rowsView) || void 0 === _this$_rowsView ? void 0 : _this$_rowsView.waitAsyncTemplates(true).done(() => {
this._showAddedRow(rowIndex);
this._afterInsertRow(change.key)
})
});
return d.promise()
},
_showAddedRow: function(rowIndex) {
this._focusFirstEditableCellInRow(rowIndex)
},
_beforeFocusElementInRow: noop,
_focusFirstEditableCellInRow: function(rowIndex) {
var dataController = this._dataController;
var key = dataController.getKeyByRowIndex(rowIndex);
var $firstCell = this.getFirstEditableCellInRow(rowIndex);
this._editCellInProgress = true;
this._delayedInputFocus($firstCell, () => {
rowIndex = dataController.getRowIndexByKey(key);
this._editCellInProgress = false;
this._beforeFocusElementInRow(rowIndex)
})
},
_isEditingStart: function(options) {
this.executeAction("onEditingStart", options);
return options.cancel
},
_beforeUpdateItems: noop,
_getVisibleEditColumnIndex: function() {
var editColumnName = this.option(EDITING_EDITCOLUMNNAME_OPTION_NAME);
if (!isDefined(editColumnName)) {
return -1
}
return this._columnsController.getVisibleColumnIndex(editColumnName)
},
_setEditColumnNameByIndex: function(index, silent) {
var _visibleColumns$index;
var visibleColumns = this._columnsController.getVisibleColumns();
this._setEditColumnName(null === (_visibleColumns$index = visibleColumns[index]) || void 0 === _visibleColumns$index ? void 0 : _visibleColumns$index.name, silent)
},
_setEditColumnName: function(name, silent) {
if (silent) {
this._silentOption(EDITING_EDITCOLUMNNAME_OPTION_NAME, name)
} else {
this.option(EDITING_EDITCOLUMNNAME_OPTION_NAME, name)
}
},
_resetEditColumnName: function() {
this._setEditColumnName(null, true)
},
_getEditColumn: function() {
var editColumnName = this.option(EDITING_EDITCOLUMNNAME_OPTION_NAME);
return this._getColumnByName(editColumnName)
},
_getColumnByName: function(name) {
var visibleColumns = this._columnsController.getVisibleColumns();
var editColumn;
isDefined(name) && visibleColumns.some(column => {
if (column.name === name) {
editColumn = column;
return true
}
});
return editColumn
},
_getVisibleEditRowIndex: function(columnName) {
var dataController = this._dataController;
var editRowKey = this.option(EDITING_EDITROWKEY_OPTION_NAME);
var rowIndex = dataController.getRowIndexByKey(editRowKey);
if (-1 === rowIndex) {
return rowIndex
}
return rowIndex + this._getEditRowIndexCorrection(columnName)
},
_getEditRowIndexCorrection: function(columnName) {
var editColumn = columnName ? this._getColumnByName(columnName) : this._getEditColumn();
var isColumnHidden = "adaptiveHidden" === (null === editColumn || void 0 === editColumn ? void 0 : editColumn.visibleWidth);
return isColumnHidden ? 1 : 0
},
_resetEditRowKey: function() {
this._setEditRowKey(null, true)
},
_resetEditIndices: function() {
this._resetEditColumnName();
this._resetEditRowKey()
},
editRow: function(rowIndex) {
var _item$oldData;
var dataController = this._dataController;
var items = dataController.items();
var item = items[rowIndex];
var params = {
data: item && item.data,
cancel: false
};
var 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: null !== (_item$oldData = item.oldData) && void 0 !== _item$oldData ? _item$oldData : item.data
});
this._setEditRowKey(item.key)
},
_editRowFromOptionChanged: function(rowIndex, oldRowIndex) {
var rowIndices = [oldRowIndex, rowIndex];
this._beforeUpdateItems(rowIndices, rowIndex, oldRowIndex);
this._editRowFromOptionChangedCore(rowIndices, rowIndex)
},
_editRowFromOptionChangedCore: function(rowIndices, rowIndex, preventRendering) {
this._needFocusEditor = true;
this._dataController.updateItems({
changeType: "update",
rowIndices: rowIndices,
cancel: preventRendering
})
},
_focusEditorIfNeed: noop,
_showEditPopup: noop,
_repaintEditPopup: noop,
_getEditPopupHiddenHandler: function() {
return e => {
if (this.isEditing()) {
this.cancelEditData()
}
}
},
_getPopupEditFormTemplate: noop,
_getSaveButtonConfig: function() {
return {
text: this.option("editing.texts.saveRowChanges"),
onClick: this.saveEditData.bind(this)
}
},
_getCancelButtonConfig: function() {
return {
text: this.option("editing.texts.cancelRowChanges"),
onClick: this.cancelEditData.bind(this)
}
},
_removeInternalData: function(key) {
var internalData = this._getInternalData(key);
var index = this._internalState.indexOf(internalData);
if (index > -1) {
this._internalState.splice(index, 1)
}
},
_updateInsertAfterOrBeforeKeys: function(changes, index) {
var removeChange = changes[index];
changes.forEach(change => {
var insertAfterOrBeforeKey = this._getInsertAfterOrBeforeKey(change);
if (equalByValue(insertAfterOrBeforeKey, removeChange.key)) {
change[isDefined(change.insertAfterKey) ? "insertAfterKey" : "insertBeforeKey"] = this._getInsertAfterOrBeforeKey(removeChange)
}
})
},
_removeChange: function(index) {
if (index >= 0) {
var changes = [...this.getChanges()];
var key = changes[index].key;
this._removeInternalData(key);
this._updateInsertAfterOrBeforeKeys(changes, index);
changes.splice(index, 1);
this._silentOption(EDITING_CHANGES_OPTION_NAME, changes);
if (equalByValue(this.option(EDITING_EDITROWKEY_OPTION_NAME), key)) {
this._resetEditIndices()
}
}
},
executeOperation: function(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: function() {
return when(...this._deferreds)
},
_processCanceledEditingCell: noop,
_repaintEditCell: function(column, oldColumn, oldEditRowIndex) {
this._needFocusEditor = true;
if (!column || !column.showEditorAlways || oldColumn && !oldColumn.showEditorAlways) {
this._editCellInProgress = true;
this.getController("editorFactory").loseFocus();
this._dataController.updateItems({
changeType: "update",
rowIndices: [oldEditRowIndex, this._getVisibleEditRowIndex()]
})
} else if (column !== oldColumn) {
this._dataController.updateItems({
changeType: "update",
rowIndices: []
})
}
},
_delayedInputFocus: function($cell, beforeFocusCallback, callBeforeFocusCallbackAlways) {
var inputFocus = () => {
if (beforeFocusCallback) {
beforeFocusCallback()
}
if ($cell) {
var $focusableElement = $cell.find(FOCUSABLE_ELEMENT_SELECTOR).first();
gridCoreUtils.focusAndSelectElement(this, $focusableElement)
}
this._beforeFocusCallback = null
};
if (devices.real().ios || devices.real().android) {
inputFocus()
} else {
if (this._beforeFocusCallback) {
this._beforeFocusCallback()
}
clearTimeout(this._inputFocusTimeoutID);
if (callBeforeFocusCallbackAlways) {
this._beforeFocusCallback = beforeFocusCallback
}
this._inputFocusTimeoutID = setTimeout(inputFocus)
}
},
_focusEditingCell: function(beforeFocusCallback, $editCell, callBeforeFocusCallbackAlways) {
var rowsView = this.getView("rowsView");
var editColumnIndex = this._getVisibleEditColumnIndex();
$editCell = $editCell || rowsView && rowsView._getCellElement(this._getVisibleEditRowIndex(), editColumnIndex);
if ($editCell) {
this._delayedInputFocus($editCell, beforeFocusCallback, callBeforeFocusCallbackAlways)
}
},
deleteRow: function(rowIndex) {
this._checkAndDeleteRow(rowIndex)
},
_checkAndDeleteRow: function(rowIndex) {
var editingOptions = this.option("editing");
var editingTexts = null === editingOptions || void 0 === editingOptions ? void 0 : editingOptions.texts;
var confirmDelete = null === editingOptions || void 0 === editingOptions ?