@syncfusion/ej2-treegrid 30.1.38 → 31.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/aceconfig.js +17 -0
  2. package/dist/ej2-treegrid.min.js +2 -2
  3. package/dist/ej2-treegrid.umd.min.js +2 -2
  4. package/dist/ej2-treegrid.umd.min.js.map +1 -1
  5. package/dist/es6/ej2-treegrid.es2015.js +265 -159
  6. package/dist/es6/ej2-treegrid.es2015.js.map +1 -1
  7. package/dist/es6/ej2-treegrid.es5.js +293 -169
  8. package/dist/es6/ej2-treegrid.es5.js.map +1 -1
  9. package/dist/global/ej2-treegrid.min.js +2 -2
  10. package/dist/global/ej2-treegrid.min.js.map +1 -1
  11. package/dist/global/index.d.ts +1 -1
  12. package/dist/ts/index.d.ts +4 -0
  13. package/dist/ts/index.ts +4 -0
  14. package/dist/ts/treegrid/actions/batch-edit.d.ts +74 -0
  15. package/dist/ts/treegrid/actions/batch-edit.ts +627 -0
  16. package/dist/ts/treegrid/actions/clipboard.d.ts +36 -0
  17. package/dist/ts/treegrid/actions/clipboard.ts +174 -0
  18. package/dist/ts/treegrid/actions/column-chooser.d.ts +37 -0
  19. package/dist/ts/treegrid/actions/column-chooser.ts +55 -0
  20. package/dist/ts/treegrid/actions/column-menu.d.ts +24 -0
  21. package/dist/ts/treegrid/actions/column-menu.ts +39 -0
  22. package/dist/ts/treegrid/actions/command-column.d.ts +24 -0
  23. package/dist/ts/treegrid/actions/command-column.ts +32 -0
  24. package/dist/ts/treegrid/actions/context-menu.d.ts +42 -0
  25. package/dist/ts/treegrid/actions/context-menu.ts +149 -0
  26. package/dist/ts/treegrid/actions/crud-actions.d.ts +66 -0
  27. package/dist/ts/treegrid/actions/crud-actions.ts +388 -0
  28. package/dist/ts/treegrid/actions/detail-row.d.ts +39 -0
  29. package/dist/ts/treegrid/actions/detail-row.ts +124 -0
  30. package/dist/ts/treegrid/actions/edit.d.ts +121 -0
  31. package/dist/ts/treegrid/actions/edit.ts +1083 -0
  32. package/dist/ts/treegrid/actions/excel-export.d.ts +67 -0
  33. package/dist/ts/treegrid/actions/excel-export.ts +240 -0
  34. package/dist/ts/treegrid/actions/filter.d.ts +57 -0
  35. package/dist/ts/treegrid/actions/filter.ts +231 -0
  36. package/dist/ts/treegrid/actions/freeze-column.d.ts +28 -0
  37. package/dist/ts/treegrid/actions/freeze-column.ts +119 -0
  38. package/dist/ts/treegrid/actions/index.d.ts +24 -0
  39. package/dist/ts/treegrid/actions/index.ts +24 -0
  40. package/dist/ts/treegrid/actions/infinite-scroll.d.ts +96 -0
  41. package/dist/ts/treegrid/actions/infinite-scroll.ts +320 -0
  42. package/dist/ts/treegrid/actions/logger.d.ts +25 -0
  43. package/dist/ts/treegrid/actions/logger.ts +136 -0
  44. package/dist/ts/treegrid/actions/page.d.ts +67 -0
  45. package/dist/ts/treegrid/actions/page.ts +212 -0
  46. package/dist/ts/treegrid/actions/pdf-export.d.ts +63 -0
  47. package/dist/ts/treegrid/actions/pdf-export.ts +182 -0
  48. package/dist/ts/treegrid/actions/print.d.ts +37 -0
  49. package/dist/ts/treegrid/actions/print.ts +69 -0
  50. package/dist/ts/treegrid/actions/reorder.d.ts +36 -0
  51. package/dist/ts/treegrid/actions/reorder.ts +60 -0
  52. package/dist/ts/treegrid/actions/resize.d.ts +36 -0
  53. package/dist/ts/treegrid/actions/resize.ts +54 -0
  54. package/dist/ts/treegrid/actions/rowdragdrop.d.ts +405 -0
  55. package/dist/ts/treegrid/actions/rowdragdrop.ts +1896 -0
  56. package/dist/ts/treegrid/actions/selection.d.ts +51 -0
  57. package/dist/ts/treegrid/actions/selection.ts +530 -0
  58. package/dist/ts/treegrid/actions/sort.d.ts +63 -0
  59. package/dist/ts/treegrid/actions/sort.ts +149 -0
  60. package/dist/ts/treegrid/actions/summary.d.ts +47 -0
  61. package/dist/ts/treegrid/actions/summary.ts +231 -0
  62. package/dist/ts/treegrid/actions/toolbar.d.ts +52 -0
  63. package/dist/ts/treegrid/actions/toolbar.ts +154 -0
  64. package/dist/ts/treegrid/actions/virtual-scroll.d.ts +90 -0
  65. package/dist/ts/treegrid/actions/virtual-scroll.ts +306 -0
  66. package/dist/ts/treegrid/base/constant.d.ts +158 -0
  67. package/dist/ts/treegrid/base/constant.ts +158 -0
  68. package/dist/ts/treegrid/base/data.d.ts +90 -0
  69. package/dist/ts/treegrid/base/data.ts +904 -0
  70. package/dist/ts/treegrid/base/index.d.ts +11 -0
  71. package/dist/ts/treegrid/base/index.ts +11 -0
  72. package/dist/ts/treegrid/base/interface.d.ts +186 -0
  73. package/dist/ts/treegrid/base/interface.ts +191 -0
  74. package/dist/ts/treegrid/base/treegrid-model.d.ts +1100 -0
  75. package/dist/ts/treegrid/base/treegrid.d.ts +2422 -0
  76. package/dist/ts/treegrid/base/treegrid.ts +5962 -0
  77. package/dist/ts/treegrid/enum.d.ts +152 -0
  78. package/dist/ts/treegrid/enum.ts +217 -0
  79. package/dist/ts/treegrid/index.d.ts +9 -0
  80. package/dist/ts/treegrid/index.ts +9 -0
  81. package/dist/ts/treegrid/models/column-chooser-settings-model.d.ts +62 -0
  82. package/dist/ts/treegrid/models/column-chooser-settings.d.ts +53 -0
  83. package/dist/ts/treegrid/models/column-chooser-settings.ts +67 -0
  84. package/dist/ts/treegrid/models/column-model.d.ts +30 -0
  85. package/dist/ts/treegrid/models/column.d.ts +697 -0
  86. package/dist/ts/treegrid/models/column.ts +800 -0
  87. package/dist/ts/treegrid/models/edit-settings-model.d.ts +100 -0
  88. package/dist/ts/treegrid/models/edit-settings.d.ts +89 -0
  89. package/dist/ts/treegrid/models/edit-settings.ts +111 -0
  90. package/dist/ts/treegrid/models/filter-settings-model.d.ts +216 -0
  91. package/dist/ts/treegrid/models/filter-settings.d.ts +195 -0
  92. package/dist/ts/treegrid/models/filter-settings.ts +237 -0
  93. package/dist/ts/treegrid/models/index.d.ts +24 -0
  94. package/dist/ts/treegrid/models/index.ts +24 -0
  95. package/dist/ts/treegrid/models/infinite-scroll-settings-model.d.ts +29 -0
  96. package/dist/ts/treegrid/models/infinite-scroll-settings.d.ts +25 -0
  97. package/dist/ts/treegrid/models/infinite-scroll-settings.ts +31 -0
  98. package/dist/ts/treegrid/models/loading-indicator-model.d.ts +21 -0
  99. package/dist/ts/treegrid/models/loading-indicator.d.ts +19 -0
  100. package/dist/ts/treegrid/models/loading-indicator.ts +21 -0
  101. package/dist/ts/treegrid/models/page-settings-model.d.ts +66 -0
  102. package/dist/ts/treegrid/models/page-settings.d.ts +57 -0
  103. package/dist/ts/treegrid/models/page-settings.ts +73 -0
  104. package/dist/ts/treegrid/models/rowdrop-settings-model.d.ts +15 -0
  105. package/dist/ts/treegrid/models/rowdrop-settings.d.ts +34 -0
  106. package/dist/ts/treegrid/models/rowdrop-settings.ts +37 -0
  107. package/dist/ts/treegrid/models/search-settings-model.d.ts +79 -0
  108. package/dist/ts/treegrid/models/search-settings.d.ts +73 -0
  109. package/dist/ts/treegrid/models/search-settings.ts +83 -0
  110. package/dist/ts/treegrid/models/selection-settings-model.d.ts +76 -0
  111. package/dist/ts/treegrid/models/selection-settings.d.ts +68 -0
  112. package/dist/ts/treegrid/models/selection-settings.ts +82 -0
  113. package/dist/ts/treegrid/models/sort-settings-model.d.ts +49 -0
  114. package/dist/ts/treegrid/models/sort-settings.d.ts +43 -0
  115. package/dist/ts/treegrid/models/sort-settings.ts +51 -0
  116. package/dist/ts/treegrid/models/summary-model.d.ts +93 -0
  117. package/dist/ts/treegrid/models/summary.d.ts +126 -0
  118. package/dist/ts/treegrid/models/summary.ts +170 -0
  119. package/dist/ts/treegrid/models/textwrap-settings-model.d.ts +21 -0
  120. package/dist/ts/treegrid/models/textwrap-settings.d.ts +19 -0
  121. package/dist/ts/treegrid/models/textwrap-settings.ts +21 -0
  122. package/dist/ts/treegrid/renderer/index.d.ts +5 -0
  123. package/dist/ts/treegrid/renderer/index.ts +5 -0
  124. package/dist/ts/treegrid/renderer/render.d.ts +41 -0
  125. package/dist/ts/treegrid/renderer/render.ts +379 -0
  126. package/dist/ts/treegrid/renderer/virtual-row-model-generator.d.ts +16 -0
  127. package/dist/ts/treegrid/renderer/virtual-row-model-generator.ts +90 -0
  128. package/dist/ts/treegrid/renderer/virtual-tree-content-render.d.ts +353 -0
  129. package/dist/ts/treegrid/renderer/virtual-tree-content-render.ts +1125 -0
  130. package/dist/ts/treegrid/utils.d.ts +70 -0
  131. package/dist/ts/treegrid/utils.ts +217 -0
  132. package/package.json +51 -15
  133. package/src/treegrid/actions/context-menu.js +3 -1
  134. package/src/treegrid/actions/excel-export.d.ts +8 -0
  135. package/src/treegrid/actions/excel-export.js +13 -1
  136. package/src/treegrid/actions/freeze-column.js +1 -1
  137. package/src/treegrid/actions/pdf-export.d.ts +8 -0
  138. package/src/treegrid/actions/pdf-export.js +12 -0
  139. package/src/treegrid/actions/selection.js +1 -1
  140. package/src/treegrid/actions/virtual-scroll.js +2 -2
  141. package/src/treegrid/base/data.js +1 -1
  142. package/src/treegrid/base/treegrid-model.d.ts +32 -2
  143. package/src/treegrid/base/treegrid.d.ts +29 -2
  144. package/src/treegrid/base/treegrid.js +39 -2
  145. package/src/treegrid/models/column-chooser-settings-model.d.ts +62 -0
  146. package/src/treegrid/models/column-chooser-settings.d.ts +53 -0
  147. package/src/treegrid/models/column-chooser-settings.js +52 -0
  148. package/src/treegrid/renderer/virtual-tree-content-render.js +4 -9
  149. package/src/treegrid/utils.js +22 -6
@@ -0,0 +1,1083 @@
1
+ import { Grid, Edit as GridEdit, SaveEventArgs, CellSaveArgs, CellEditArgs, getUid, getObject,
2
+ NotifyArgs, Row, ActionEventArgs, resetRowIndex, BatchChanges} from '@syncfusion/ej2-grids';
3
+ import { Column, RecordDoubleClickEventArgs, RowInfo, parentsUntil } from '@syncfusion/ej2-grids';
4
+ import { TreeGrid } from '../base/treegrid';
5
+ import { ITreeData, CellSaveEventArgs } from '../base/interface';
6
+ import * as events from '../base/constant';
7
+ import { isNullOrUndefined, extend, setValue, removeClass, KeyboardEventArgs, addClass, getValue } from '@syncfusion/ej2-base';
8
+ import { DataManager, Deferred, RemoteSaveAdaptor, AdaptorOptions, Query } from '@syncfusion/ej2-data';
9
+ import { findChildrenRecords, getParentData, isCountRequired, isRemoteData } from '../utils';
10
+ import { editAction, updateParentRow } from './crud-actions';
11
+ import { RowPosition } from '../enum';
12
+ import { BatchEdit } from './batch-edit';
13
+ import { AggregateRow } from '../models/summary';
14
+
15
+ /**
16
+ * TreeGrid Edit Module
17
+ * The `Edit` module is used to handle editing actions.
18
+ */
19
+ export class Edit {
20
+ private parent: TreeGrid;
21
+ private isSelfReference: boolean;
22
+ private addedRecords: string = 'addedRecords';
23
+ private deletedRecords: string = 'deletedRecords';
24
+ private addRowIndex: number;
25
+ private addRowRecord: ITreeData;
26
+ private isOnBatch: boolean;
27
+ private keyPress: string;
28
+ private selectedIndex: number;
29
+ private doubleClickTarget: Element;
30
+ private internalProperties: ITreeData;
31
+ private previousNewRowPosition : RowPosition;
32
+ private batchEditModule: BatchEdit;
33
+ private isTabLastRow: boolean;
34
+ private prevAriaRowIndex: string = '-1';
35
+ private isAddedRowByMethod: boolean = false;
36
+ private isAddedRowByContextMenu: boolean = false;
37
+ private editedRowIndex: number;
38
+ private isScrollByFocus : boolean;
39
+ private isIndexUndefined : boolean = false;
40
+ /**
41
+ * Constructor for Edit module
42
+ *
43
+ * @param {TreeGrid} parent - Tree Grid instance
44
+ */
45
+ constructor(parent: TreeGrid) {
46
+ Grid.Inject(GridEdit);
47
+
48
+ this.parent = parent;
49
+ this.isSelfReference = !isNullOrUndefined(parent.parentIdMapping);
50
+ this.previousNewRowPosition = null;
51
+ this.internalProperties = {};
52
+ this.batchEditModule = new BatchEdit(this.parent);
53
+ this.addEventListener();
54
+ }
55
+ /**
56
+ * For internal use only - Get the module name.
57
+ *
58
+ * @private
59
+ * @returns {string} Returns Edit module name
60
+ */
61
+ protected getModuleName(): string {
62
+ return 'edit';
63
+ }
64
+
65
+ /**
66
+ * @hidden
67
+ * @returns {void}
68
+ */
69
+ public addEventListener(): void {
70
+ this.parent.on(events.crudAction, this.crudAction, this);
71
+ this.parent.on(events.beginEdit, this.beginEdit, this);
72
+ this.parent.on(events.beginAdd, this.beginAdd, this);
73
+ this.parent.on(events.recordDoubleClick, this.recordDoubleClick, this);
74
+ this.parent.on(events.cellSave, this.cellSave, this);
75
+ this.parent.on(events.batchCancel, this.batchCancel, this);
76
+ this.parent.grid.on(events.keyPressed, this.keyPressed, this);
77
+ this.parent.grid.on('batchedit-form', this.lastCellTab, this);
78
+ this.parent.grid.on('content-ready', this.contentready, this);
79
+ this.parent.on(events.cellEdit, this.cellEdit, this);
80
+ this.parent.on('actionBegin', this.editActionEvents, this);
81
+ this.parent.on('actionComplete', this.editActionEvents, this);
82
+ this.parent.grid.on(events.doubleTap, this.recordDoubleClick, this);
83
+ this.parent.grid.on('dblclick', this.gridDblClick, this);
84
+ this.parent.grid.on('recordAdded', this.customCellSave, this);
85
+ this.parent.on('savePreviousRowPosition', this.savePreviousRowPosition, this);
86
+ // this.parent.on(events.beforeDataBound, this.beforeDataBound, this);
87
+ this.parent.grid.on(events.beforeStartEdit, this.beforeStartEdit, this);
88
+ this.parent.grid.on(events.beforeBatchCancel, this.beforeBatchCancel, this);
89
+ this.parent.grid.on('reset-edit-props', this.resetIsOnBatch, this);
90
+ this.parent.grid.on('get-row-position', this.getRowPosition, this);
91
+ }
92
+ private gridDblClick(e: MouseEvent): void {
93
+ this.doubleClickTarget = e.target as HTMLElement;
94
+ if ((e.target as HTMLElement).classList.contains('e-frame') && this.parent.getCurrentViewRecords().length === 0)
95
+ {
96
+ this.doubleClickTarget = null;
97
+ }
98
+ if ((e.target as HTMLElement).classList.contains('e-treegridcollapse') || (e.target as HTMLElement).classList.contains('e-treegridexpand')) {
99
+ const tr: Element = parentsUntil(e.target as Element, 'e-row');
100
+ const rowIndex: number = tr && parseInt(tr.getAttribute('aria-rowindex'), 10) - 1;
101
+ if (!isNullOrUndefined(rowIndex) && rowIndex >= 0 && this.parent.allowPaging) {
102
+ /* eslint-disable-next-line */
103
+ (this.parent.grid.getDataRows()[rowIndex]as HTMLTableRowElement).dataset.uid = (this.parent.grid.contentModule.getRows()[rowIndex] as any).uid;
104
+ }
105
+ }
106
+ }
107
+ private getRowPosition(addArgs: { newRowPosition: RowPosition, addRowIndex: number, dataRowIndex: number }): void {
108
+ addArgs.newRowPosition = this.parent.editSettings.newRowPosition;
109
+ addArgs.addRowIndex = this.addRowIndex;
110
+ addArgs.dataRowIndex = +this.prevAriaRowIndex;
111
+ }
112
+ private beforeStartEdit(args: Object) : void {
113
+ if (this.parent.editSettings.mode === 'Cell') {
114
+ this.parent.trigger(events.actionBegin, args);
115
+ }
116
+ }
117
+ private beforeBatchCancel(args: Object) : void {
118
+ if (this.parent.editSettings.mode === 'Cell') {
119
+ args['requestType'] = 'cancel';
120
+ this.parent.trigger(events.actionComplete, args);
121
+ }
122
+ }
123
+ /**
124
+ * @hidden
125
+ * @returns {void}
126
+ */
127
+ public removeEventListener(): void {
128
+ if (this.parent.isDestroyed) { return; }
129
+ this.parent.off(events.crudAction, this.crudAction);
130
+ this.parent.off(events.beginEdit, this.beginEdit);
131
+ this.parent.off(events.beginAdd, this.beginAdd);
132
+ this.parent.off(events.recordDoubleClick, this.recordDoubleClick);
133
+ this.parent.off(events.batchCancel, this.batchCancel);
134
+ this.parent.grid.off(events.keyPressed, this.keyPressed);
135
+ this.parent.grid.off('batchedit-form', this.lastCellTab);
136
+ this.parent.grid.off('content-ready', this.contentready);
137
+ this.parent.off(events.cellEdit, this.cellEdit);
138
+ this.parent.off('actionBegin', this.editActionEvents);
139
+ this.parent.off('actionComplete', this.editActionEvents);
140
+ this.parent.grid.off('recordAdded', this.customCellSave);
141
+ this.parent.grid.off(events.doubleTap, this.recordDoubleClick);
142
+ this.parent.off('savePreviousRowPosition', this.savePreviousRowPosition);
143
+ this.parent.grid.off(events.beforeStartEdit, this.beforeStartEdit);
144
+ this.parent.grid.off(events.beforeBatchCancel, this.beforeBatchCancel);
145
+ this.parent.grid.off('dblclick', this.gridDblClick);
146
+ this.parent.grid.off('reset-edit-props', this.resetIsOnBatch);
147
+ this.parent.grid.off('get-row-position', this.getRowPosition);
148
+ //this.parent.grid.off('click', this.gridSingleClick);
149
+ }
150
+ /**
151
+ * To destroy the editModule
152
+ *
153
+ * @returns {void}
154
+ * @hidden
155
+ */
156
+ public destroy(): void {
157
+ this.removeEventListener();
158
+ }
159
+
160
+ /**
161
+ * @param {Column[]} cols - Column property Collection
162
+ * @hidden
163
+ * @returns {void}
164
+ */
165
+ public applyFormValidation(cols?: Column[]): void {
166
+ this.parent.grid.editModule.applyFormValidation(cols);
167
+ }
168
+ private editActionEvents(args: Object): void {
169
+ const eventArgs: ActionEventArgs | CellSaveEventArgs = getObject('editAction', args);
170
+ const eventName: string = getObject('name', eventArgs);
171
+ const treeObj: TreeGrid = this.parent;
172
+ const adaptor: AdaptorOptions = !isNullOrUndefined((treeObj.dataSource as DataManager))
173
+ && (treeObj.dataSource as DataManager).adaptor;
174
+ if (!isNullOrUndefined(adaptor) && (isRemoteData(treeObj) || adaptor instanceof RemoteSaveAdaptor) &&
175
+ (eventArgs.requestType === 'save' && eventArgs.action === 'add') &&
176
+ (treeObj.editSettings.newRowPosition === 'Child' || treeObj.editSettings.newRowPosition === 'Below'
177
+ || treeObj.editSettings.newRowPosition === 'Above')) {
178
+ if (eventName === 'actionBegin') {
179
+ const rowIndex: number = isNullOrUndefined(eventArgs.row) || !Object.keys(eventArgs.row).length ? this.selectedIndex :
180
+ (<HTMLTableRowElement>eventArgs.row).rowIndex - 1;
181
+ const keyData: string = (!isNullOrUndefined(rowIndex) && rowIndex !== -1) ?
182
+ treeObj.getCurrentViewRecords()[parseInt(rowIndex.toString(), 10)][treeObj.getPrimaryKeyFieldNames()[0]] : -1;
183
+ treeObj.grid.query.addParams('relationalKey', keyData);
184
+ } else if (eventName === 'actionComplete') {
185
+ const paramsLength: number = treeObj.grid.query.params.length;
186
+ for (let i: number = 0; i < paramsLength; i++) {
187
+ if (treeObj.grid.query.params[parseInt(i.toString(), 10)].key === 'relationalKey') {
188
+ treeObj.grid.query.params.splice(i);
189
+ }
190
+ }
191
+ }
192
+ }
193
+ if (this.parent.enableInfiniteScrolling && eventName === 'actionComplete') {
194
+ this.infiniteAddAction(eventArgs);
195
+ }
196
+ if (this.parent.editSettings.mode === 'Batch' && eventArgs.requestType === 'paging') {
197
+ this.parent.notify('batchPageAction', {});
198
+ }
199
+ }
200
+ private infiniteAddAction(args: ActionEventArgs | CellSaveEventArgs): void {
201
+ if ((args.requestType === 'save' && args.action === 'add') || args.requestType === 'delete') {
202
+ if (this.parent.editSettings.newRowPosition !== 'Top' && this.selectedIndex !== -1
203
+ && (args.requestType === 'save' && args.action === 'add')) {
204
+ const rowObjects: Row<Column>[] = this.parent.grid.getRowsObject();
205
+ const newRowObject: Row<Column> = rowObjects.splice(0, 1)[0];
206
+ let newRowObjectIndex: number = this.addRowIndex;
207
+ const currentData: ITreeData[] = this.parent.getCurrentViewRecords();
208
+ if (this.parent.editSettings.newRowPosition === 'Below' || this.parent.editSettings.newRowPosition === 'Child') {
209
+ newRowObjectIndex += findChildrenRecords(currentData[newRowObjectIndex + 1]).length;
210
+ }
211
+ newRowObjectIndex = this.parent.editSettings.newRowPosition === 'Below' ? newRowObjectIndex + 1 : newRowObjectIndex;
212
+ rowObjects.splice(newRowObjectIndex, 0, newRowObject);
213
+ const newRecord: ITreeData = currentData.splice(0, 1)[0];
214
+ currentData.splice(newRowObjectIndex, 0, newRecord);
215
+ this.updateInfiniteCurrentViewData(newRecord, this.addRowIndex);
216
+ }
217
+ const movableRows: Element[] = this.parent.grid.getRows();
218
+ const movableRowsObject: Row<Column>[] = this.parent.grid.getRowsObject();
219
+ const isCache: boolean = this.parent.infiniteScrollSettings.enableCache;
220
+ if (!isCache) {
221
+ resetRowIndex(this.parent.grid, this.parent.grid.getRowsObject(), this.parent.grid.getRows() as HTMLTableRowElement[], 0);
222
+ this.updateIndex(this.parent.grid.dataSource, this.parent.getRows(), this.parent.getCurrentViewRecords());
223
+ }
224
+ if (!isCache && this.parent.getFrozenColumns() > 0) {
225
+ resetRowIndex(this.parent.grid, movableRowsObject, movableRows as HTMLTableRowElement[], 0);
226
+ this.updateIndex(this.parent.grid.dataSource, movableRows, this.parent.getCurrentViewRecords());
227
+ }
228
+ }
229
+ }
230
+
231
+ private updateInfiniteCurrentViewData(newRecord: ITreeData, newRowIndex: number): void {
232
+ const infiniteData: string = 'infiniteCurrentViewData'; const updateCurrentViewData: string = 'updateCurrentViewData';
233
+ const size: number = Math.ceil(newRowIndex / this.parent.grid.pageSettings.pageSize);
234
+ let page: number = size > 0 ? size : 1;
235
+ let dataIndex: number = newRowIndex - ((page - 1) * this.parent.pageSettings.pageSize);
236
+ const infiniteCurrentViewData: { [x: number]: Object[] } = this.parent.grid.infiniteScrollModule[`${infiniteData}`];
237
+ infiniteCurrentViewData[1].splice(0, 1);
238
+ let data: Object[] = infiniteCurrentViewData[parseInt(page.toString(), 10)];
239
+ if (!isNullOrUndefined(this.addRowRecord)) {
240
+ data.filter((e: ITreeData, index: number): void => {
241
+ if (e.uniqueID === this.addRowRecord.uniqueID) {
242
+ dataIndex = index;
243
+ }
244
+ });
245
+ if (this.addRowRecord.hasChildRecords && this.addRowRecord.childRecords.length &&
246
+ this.parent.editSettings.newRowPosition === 'Below' || this.parent.editSettings.newRowPosition === 'Child') {
247
+ dataIndex += findChildrenRecords(this.addRowRecord).length;
248
+ }
249
+ }
250
+ if (dataIndex >= this.parent.pageSettings.pageSize) {
251
+ page += 1;
252
+ data = infiniteCurrentViewData[parseInt(page.toString(), 10)];
253
+ dataIndex = dataIndex - this.parent.pageSettings.pageSize >= 0 ? dataIndex - this.parent.pageSettings.pageSize : 0;
254
+ }
255
+ dataIndex = this.parent.editSettings.newRowPosition === 'Below' ? dataIndex + 1 : dataIndex;
256
+ data.splice(dataIndex, 0, newRecord);
257
+ this.parent.grid.infiniteScrollModule[`${updateCurrentViewData}`]();
258
+ }
259
+
260
+ private recordDoubleClick(args: RecordDoubleClickEventArgs): void {
261
+ const target: HTMLElement = <HTMLElement>args.target;
262
+ if (isNullOrUndefined(target.closest('td.e-rowcell'))) {
263
+ return;
264
+ }
265
+ if (!(this.parent.grid.editSettings.allowEditing) || this.parent.grid.isEdit) {
266
+ return;
267
+ }
268
+ const column: Column = this.parent.grid.getColumnByIndex(+target.closest('td.e-rowcell').getAttribute('aria-colindex') - 1);
269
+ if (this.parent.editSettings.mode === 'Cell' && !this.isOnBatch && column && !column.isPrimaryKey &&
270
+ this.parent.editSettings.allowEditing && column.allowEditing && !(target.classList.contains('e-treegridexpand') ||
271
+ target.classList.contains('e-treegridcollapse')) && this.parent.editSettings.allowEditOnDblClick) {
272
+ this.isOnBatch = true;
273
+ this.parent.grid.setProperties({ selectedRowIndex: args.rowIndex }, true);
274
+ if (this.parent.enableVirtualization) {
275
+ const tr: HTMLTableRowElement = <HTMLTableRowElement>parentsUntil(args.target as Element, 'e-row');
276
+ this.prevAriaRowIndex = tr.getAttribute('aria-rowindex');
277
+ tr.setAttribute('aria-rowindex', (tr.rowIndex + 1) + '');
278
+ }
279
+ this.updateGridEditMode('Batch');
280
+ }
281
+ else if (this.parent.editSettings.mode === 'Cell' && (!column.allowEditing || column.isPrimaryKey)){
282
+ this.isOnBatch = true;
283
+ this.updateGridEditMode('Batch');
284
+ }
285
+ }
286
+ private updateGridEditMode(mode: string): void {
287
+ this.parent.grid.setProperties({editSettings: {mode: mode}}, true);
288
+ const updateMethod: Function = getObject('updateEditObj', this.parent.grid.editModule) as Function;
289
+ updateMethod.apply(this.parent.grid.editModule);
290
+ this.parent.grid.isEdit = false;
291
+ }
292
+
293
+ private resetIsOnBatch(): void {
294
+ if (this.parent.enableVirtualization && this.parent.editSettings.mode === 'Cell') {
295
+ this.isOnBatch = false;
296
+ this.updateGridEditMode('Normal');
297
+ }
298
+ }
299
+
300
+ private keyPressed(args: KeyboardEventArgs): void {
301
+ if (this.isOnBatch || args.action === 'tab' || args.action === 'shiftTab') {
302
+ this.keyPress = args.action;
303
+ }
304
+ if (args.action === 'f2') {
305
+ this.recordDoubleClick(args as Object);
306
+ }
307
+ if (args.action === 'escape') {
308
+ this.closeEdit();
309
+ }
310
+ }
311
+
312
+ private deleteUniqueID( value: string) : void {
313
+ const idFilter: string = 'uniqueIDFilterCollection';
314
+ delete this.parent[`${idFilter}`][`${value}`];
315
+ const id: string = 'uniqueIDCollection';
316
+ delete this.parent[`${id}`][`${value}`];
317
+ }
318
+
319
+ private cellEdit(args: CellEditArgs): Deferred | void {
320
+ const promise: string = 'promise';
321
+ const prom: Deferred = args[`${promise}`];
322
+ delete args[`${promise}`];
323
+ if (this.parent.enableVirtualization && !isNullOrUndefined(this.prevAriaRowIndex) && this.prevAriaRowIndex !== '-1') {
324
+ args.row.setAttribute('aria-rowindex', this.prevAriaRowIndex);
325
+ this.prevAriaRowIndex = undefined;
326
+ }
327
+ if (this.keyPress !== 'enter') {
328
+ this.parent.trigger(events.cellEdit, args, (celleditArgs: CellEditArgs) => {
329
+ if (!celleditArgs.cancel && this.parent.editSettings.mode === 'Cell') {
330
+ this.enableToolbarItems('edit');
331
+ } else if (celleditArgs.cancel && this.parent.editSettings.mode === 'Cell') {
332
+ this.isOnBatch = false;
333
+ this.updateGridEditMode('Normal');
334
+ }
335
+ if (!isNullOrUndefined(prom)) {
336
+ prom.resolve(celleditArgs);
337
+ }
338
+ });
339
+ }
340
+ if (this.doubleClickTarget && (this.doubleClickTarget.classList.contains('e-treegridexpand') ||
341
+ this.doubleClickTarget.classList.contains('e-treegridcollapse') || this.doubleClickTarget.classList.contains('e-summarycell'))) {
342
+ args.cancel = true; this.doubleClickTarget = null;
343
+ return;
344
+ }
345
+ if (this.parent.editSettings.mode === 'Cell') {
346
+ if (this.keyPress === 'tab' || this.keyPress === 'shiftTab') {
347
+ this.keyPress = null;
348
+ } else if (this.keyPress === 'enter') {
349
+ args.cancel = true;
350
+ this.keyPress = null;
351
+ setValue('isEditCollapse', false, this.parent);
352
+ }
353
+ if (!args.columnObject.allowEditing) {
354
+ args.cancel = true;
355
+ }
356
+ }
357
+ if (this.parent.enableVirtualization) {
358
+ this.parent.grid.contentModule['editedRowIndex'] = this.parent.grid.editModule.editModule['index'];
359
+ }
360
+ // if (this.isAdd && this.parent.editSettings.mode === 'Batch' && !args.cell.parentElement.classList.contains('e-insertedrow')) {
361
+ // this.isAdd = false;
362
+ // }
363
+ }
364
+
365
+ private enableToolbarItems(request: string): void {
366
+ if (!isNullOrUndefined(this.parent.grid.toolbarModule)) {
367
+ const toolbarID: string = this.parent.element.id + '_gridcontrol_';
368
+ this.parent.grid.toolbarModule.enableItems([toolbarID + 'add', toolbarID + 'edit', toolbarID + 'delete'], request === 'save');
369
+ this.parent.grid.toolbarModule.enableItems([toolbarID + 'update', toolbarID + 'cancel'], request === 'edit' );
370
+ }
371
+ }
372
+
373
+ private batchCancel(): void {
374
+ if (this.parent.editSettings.mode === 'Cell') {
375
+ const cellDetails: RowInfo = getValue('editModule.cellDetails', this.parent.grid.editModule);
376
+ if (!isNullOrUndefined(this.editedRowIndex)) {
377
+ cellDetails.rowIndex = this.editedRowIndex;
378
+ }
379
+ const treeCell: HTMLElement = this.parent.getCellFromIndex(cellDetails.rowIndex, this.parent.treeColumnIndex) as HTMLElement;
380
+ this.parent.renderModule.cellRender({
381
+ data: cellDetails.rowData,
382
+ cell: treeCell,
383
+ column: this.parent.grid.getColumns()[this.parent.treeColumnIndex]
384
+ });
385
+ this.updateGridEditMode('Normal');
386
+ this.isOnBatch = false;
387
+ }
388
+ if (this.parent.editSettings.mode === 'Batch') {
389
+ this.parent.notify('batchCancelAction', {});
390
+ }
391
+ }
392
+
393
+
394
+ private customCellSave(args: ActionEventArgs): void {
395
+ if (isCountRequired(this.parent) && this.parent.editSettings.mode === 'Cell' && args.action === 'edit') {
396
+ this.updateCell(args, args.rowIndex);
397
+ this.afterCellSave(args, args.row as HTMLTableRowElement);
398
+ }
399
+ }
400
+
401
+ private cellSave(args: CellSaveArgs): void {
402
+ if (this.parent.editSettings.mode === 'Cell' && this.parent.element.querySelector('form')) {
403
+ args.cancel = true;
404
+ const editModule: string = 'editModule';
405
+ setValue('isEditCollapse', true, this.parent);
406
+ args.rowData[args.columnName] = args.value;
407
+ let row: HTMLTableRowElement;
408
+ if (isNullOrUndefined(args.cell)) {
409
+ row = this.parent.grid.editModule[`${editModule}`].form.parentElement.parentNode;
410
+ } else {
411
+ row = <HTMLTableRowElement>args.cell.parentNode;
412
+ }
413
+ let rowIndex: number;
414
+ const primaryKeys: string[] = this.parent.getPrimaryKeyFieldNames();
415
+ if (isNullOrUndefined(row)) {
416
+ this.parent.grid.getCurrentViewRecords().filter((e: ITreeData, i: number) => {
417
+ if (e[primaryKeys[0]] === args.rowData[primaryKeys[0]]) { rowIndex = i; return; }
418
+ });
419
+ } else {
420
+ const freeze: boolean = (this.parent.getFrozenLeftColumnsCount() > 0 ||
421
+ this.parent.getFrozenRightColumnsCount() > 0 ) ? true : false;
422
+ if (freeze) {
423
+ if (this.parent.getRows().indexOf(row) !== -1) {
424
+ rowIndex = this.parent.getRows().indexOf(row);
425
+ } else {
426
+ rowIndex = this.parent.getRows().indexOf(row);
427
+ }
428
+ } else {
429
+ rowIndex = (this.parent.getRows().indexOf(row) === -1 && (this.parent.getFrozenColumns() > 0)) ?
430
+ this.parent.grid.getRows().indexOf(row) : this.parent.getRows().indexOf(row);
431
+ }
432
+ }
433
+ const arg: CellSaveEventArgs = {};
434
+ extend(arg, args);
435
+ arg.cancel = false;
436
+ arg.type = 'save';
437
+ row = <HTMLTableRowElement>this.parent.grid.getRows()[row.rowIndex];
438
+ this.parent.trigger(events.actionBegin, arg);
439
+ if (!arg.cancel) {
440
+ if ((row.rowIndex === this.parent.getCurrentViewRecords().length - 1) && this.keyPress === 'tab') {
441
+ this.isTabLastRow = true;
442
+ }
443
+ if (!isRemoteData(this.parent) &&
444
+ !(this.parent.dataSource instanceof DataManager && this.parent.dataSource.adaptor instanceof RemoteSaveAdaptor )) {
445
+ if (isCountRequired(this.parent)) {
446
+ const eventPromise: string = 'eventPromise';
447
+ const editArgs: ActionEventArgs = { requestType : 'save', data : args.rowData, action : 'edit', row : row,
448
+ rowIndex : rowIndex, rowData : args.rowData, columnName : args.columnName,
449
+ filterChoiceCount: null, excelSearchOperator: null };
450
+ this.parent.grid.getDataModule()[`${eventPromise}`](editArgs, this.parent.grid.query);
451
+ } else {
452
+ this.updateCell(args, rowIndex);
453
+ setValue('isEdit', false, this.parent.grid);
454
+ this.afterCellSave(args, row);
455
+ }
456
+ } else if (isRemoteData(this.parent) ||
457
+ (this.parent.dataSource instanceof DataManager && this.parent.dataSource.adaptor instanceof RemoteSaveAdaptor )) {
458
+ const query: Query = this.parent.grid.query;
459
+ if (this.parent['isGantt'] && this.parent.loadChildOnDemand) {
460
+ this.updateCell(args, rowIndex);
461
+ setValue('isEdit', false, this.parent.grid);
462
+ this.afterCellSave(args, row);
463
+ }
464
+ else {
465
+ let crud: Promise<Object> = null;
466
+ crud = <Promise<Object>>(this.parent.grid.dataSource as DataManager).update(primaryKeys[0], args.rowData,
467
+ query.fromTable,
468
+ query, args.previousValue);
469
+ crud.then((e: Object) => {
470
+ if (!isNullOrUndefined(e)) {
471
+ args.rowData[args.columnName] = e[args.columnName];
472
+ }
473
+ this.updateCell(args, rowIndex);
474
+ setValue('isEdit', false, this.parent.grid);
475
+ this.afterCellSave(args, row);
476
+ });
477
+ }
478
+ }
479
+ } else {
480
+ this.parent.grid.isEdit = true;
481
+ }
482
+ }
483
+ if (this.parent.enableVirtualization) {
484
+ this.parent.grid.contentModule['virtualData'] = {};
485
+ }
486
+ }
487
+
488
+ private afterCellSave(args: CellSaveArgs, row: HTMLTableRowElement ): void {
489
+ if (this.parent.grid.aggregateModule) {
490
+ this.parent.grid.aggregateModule.refresh(args.rowData);
491
+ }
492
+ this.parent.grid.editModule.destroyWidgets([this.parent.grid.getColumnByField(args.columnName)]);
493
+ this.parent.grid.editModule.formObj.destroy();
494
+ if (this.keyPress !== 'tab' && this.keyPress !== 'shiftTab') {
495
+ this.updateGridEditMode('Normal');
496
+ this.isOnBatch = false;
497
+ }
498
+ this.enableToolbarItems('save');
499
+ removeClass([row], ['e-editedrow', 'e-batchrow']);
500
+ removeClass(row.querySelectorAll('.e-rowcell'), ['e-editedbatchcell', 'e-updatedtd']);
501
+ if (this.parent['isCellSaveFocus'] !== false) {
502
+ this.parent.grid.focusModule.restoreFocus();
503
+ }
504
+ editAction({ value: <ITreeData>args.rowData, action: 'edit' }, this.parent, this.isSelfReference,
505
+ this.addRowIndex, this.selectedIndex, args.columnName);
506
+ if ((row.rowIndex === this.parent.getCurrentViewRecords().length - 1) && this.keyPress === 'enter') {
507
+ this.keyPress = null;
508
+ }
509
+ const saveArgs: CellSaveEventArgs = {
510
+ type: 'save', column: this.parent.getColumnByField(args.columnName), data: args.rowData,
511
+ previousData: args.previousValue, row: row, target: (args.cell as HTMLElement)
512
+ };
513
+ if (this.parent.aggregates.map((ag: AggregateRow) => ag.showChildSummary === true).length) {
514
+ this.parent.grid.refresh();
515
+ }
516
+ this.parent.trigger(events.actionComplete, saveArgs);
517
+ }
518
+
519
+ private lastCellTab(): void {
520
+ if (!this.parent.grid.isEdit && this.isOnBatch && this.keyPress === 'tab' && this.parent.editSettings.mode === 'Cell') {
521
+ if (!this.parent.editSettings.allowNextRowEdit) {
522
+ this.updateGridEditMode('Normal');
523
+ this.isOnBatch = false;
524
+ this.keyPress = null;
525
+ } else {
526
+ this.enableToolbarItems('edit');
527
+ }
528
+ }
529
+ }
530
+
531
+ private updateCell(args: CellSaveArgs, rowIndex: number): void {
532
+ this.parent.grid.editModule.updateCell(rowIndex, args.columnName, args.rowData[args.columnName]);
533
+ this.parent.grid.getRowsObject()[parseInt(rowIndex.toString(), 10)].data = args.rowData;
534
+ }
535
+ private crudAction(details: { value: ITreeData, action: string }, columnName?: string): void {
536
+ editAction(details, this.parent, this.isSelfReference, this.addRowIndex, this.selectedIndex, columnName, this.addRowRecord);
537
+ this.parent.parentData = [];
538
+ const data: Object = this.parent.grid.dataSource instanceof DataManager ?
539
+ this.parent.grid.dataSource.dataSource.json : this.parent.grid.dataSource;
540
+ for (let i: number = 0; i < (<Object[]>data).length; i++) {
541
+ data[parseInt(i.toString(), 10)].index = i;
542
+ const key: string = this.parent.grid.getPrimaryKeyFieldNames()[0];
543
+ if (details.value[`${key}`] === data[parseInt(i.toString(), 10)][`${key}`]) {
544
+ if (details.action === 'add') {
545
+ data[parseInt(i.toString(), 10)].level = this.internalProperties.level;
546
+ data[parseInt(i.toString(), 10)].taskData = this.internalProperties.taskData;
547
+ data[parseInt(i.toString(), 10)].uniqueID = this.internalProperties.uniqueID;
548
+ if (!isNullOrUndefined(this.internalProperties.parentItem)) {
549
+ data[parseInt(i.toString(), 10)].parentItem = this.internalProperties.parentItem;
550
+ data[parseInt(i.toString(), 10)].parentUniqueID = this.internalProperties.parentUniqueID;
551
+ }
552
+ data[parseInt(i.toString(), 10)].childRecords = this.internalProperties.childRecords;
553
+ }
554
+ }
555
+ setValue('uniqueIDCollection.' + data[parseInt(i.toString(), 10)].uniqueID + '.index', i, this.parent);
556
+ const adaptor: AdaptorOptions = (this.parent.dataSource as DataManager).adaptor;
557
+ if ((isRemoteData(this.parent) || adaptor instanceof RemoteSaveAdaptor)) {
558
+ setValue('uniqueIDCollection.' + data[parseInt(i.toString(), 10)].uniqueID, data[parseInt(i.toString(), 10)], this.parent);
559
+ }
560
+ if (!data[parseInt(i.toString(), 10)].level) {
561
+ this.parent.parentData.push(data[parseInt(i.toString(), 10)]);
562
+ }
563
+ }
564
+ if (!this.parent.enableInfiniteScrolling) {
565
+ if (details.action === 'add' && this.previousNewRowPosition != null) {
566
+ this.parent.setProperties({editSettings: {newRowPosition: this.previousNewRowPosition}}, true);
567
+ this.previousNewRowPosition = null;
568
+ }}
569
+ }
570
+ private updateIndex (data: Object, rows: Object, records: Object): void {
571
+ for (let j: number = 0; j < this.parent.getDataRows().length; j++ ) {
572
+ const data1: ITreeData = records[parseInt(j.toString(), 10)];
573
+ if (!isNullOrUndefined(data1)) {
574
+ const index: number = getValue('uniqueIDCollection.' + data1.uniqueID + '.index', this.parent);
575
+ data1.index = index;
576
+ if (!isNullOrUndefined(data1.parentItem)) {
577
+ const parentIndex: number = getValue('uniqueIDCollection.' + data1.parentItem.uniqueID + '.index', this.parent);
578
+ data1.parentItem.index = parentIndex;
579
+ }
580
+ }
581
+ }
582
+ let count: number = -1;
583
+ let treeColIndex: number = this.parent.treeColumnIndex;
584
+ if (this.parent.getFrozenColumns() > 0) {
585
+ const cells: NodeListOf<Element> = (rows[0] as Element).querySelectorAll('.e-rowcell');
586
+ for (let l: number = 0; l < cells.length; l++) {
587
+ if (cells[parseInt(l.toString(), 10)].classList.contains('e-gridrowindex0level0')) {
588
+ treeColIndex = l;
589
+ break;
590
+ }
591
+ }
592
+ }
593
+ for (let k: number = 0; k < this.parent.getRows().length; k++) {
594
+ if (!rows[parseInt(k.toString(), 10)].classList.contains('e-detailrow')) {
595
+ count++;
596
+ }
597
+ const data2: ITreeData = records[parseInt(count.toString(), 10)];
598
+ if (!isNullOrUndefined(data2)) {
599
+ let index: number = data2.index;
600
+ const level: number = data2.level;
601
+ const row: Element = rows[parseInt(k.toString(), 10)];
602
+ if (!isNullOrUndefined(data2.parentItem)) {
603
+ index = getValue('uniqueIDCollection.' + data2.parentItem.uniqueID + '.index', this.parent);
604
+ }
605
+ const treecell: HTMLElement = (row as HTMLTableRowElement).cells[parseInt(treeColIndex.toString(), 10)];
606
+ if (!isNullOrUndefined(treecell)) {
607
+ for (let l: number = 0; l < treecell.classList.length; l++) {
608
+ const value: string = treecell.classList[parseInt(l.toString(), 10)];
609
+ const remove: RegExp = /e-gridrowindex/i;
610
+ const removed: RegExp = /e-griddetailrowindex/i;
611
+ const result: RegExpMatchArray = value.match(remove);
612
+ const results: RegExpMatchArray = value.match(removed);
613
+ if (result != null) {
614
+ removeClass([treecell], value);
615
+ }
616
+ if (results != null) {
617
+ removeClass([treecell], value);
618
+ }
619
+ }
620
+ if (!rows[parseInt(k.toString(), 10)].classList.contains('e-detailrow')) {
621
+ addClass([treecell], 'e-gridrowindex' + index + 'level' + level);
622
+ }else {
623
+ addClass([treecell], 'e-griddetailrowindex' + index + 'level' + level);
624
+ }
625
+ }
626
+ }
627
+ }
628
+ }
629
+ private beginAdd(): void {
630
+ let position: string;
631
+ let index: number = this.addRowIndex;
632
+ let records: Object[] = this.parent.grid.getCurrentViewRecords();
633
+ if (this.parent.editSettings.mode === 'Batch') {
634
+ index = this.batchEditModule.getAddRowIndex();
635
+ this.selectedIndex = this.batchEditModule.getSelectedIndex();
636
+ if (this.parent.getBatchChanges()[this.addedRecords].length > 1
637
+ || this.parent.getBatchChanges()[this.deletedRecords].length) {
638
+ records = this.batchEditModule.getBatchRecords();
639
+ }
640
+ }
641
+ const rows: Element[] = this.parent.grid.getDataRows();
642
+ const firstAriaIndex: number = rows.length ? +rows[0].getAttribute('aria-rowindex') - 1 : 0;
643
+ const lastAriaIndex: number = rows.length ? +rows[rows.length - 1].getAttribute('aria-rowindex') - 1 : 0;
644
+ const withinRange: boolean = this.selectedIndex >= firstAriaIndex && this.selectedIndex <= lastAriaIndex;
645
+ const isVirtualization: boolean = this.parent.enableVirtualization && this.addRowIndex > -1 && this.prevAriaRowIndex !== '-1';
646
+ if (this.parent.editSettings.mode !== 'Dialog') {
647
+ if (this.parent.editSettings.newRowPosition === 'Above') {
648
+ position = 'before';
649
+ } else if ((this.parent.editSettings.newRowPosition === 'Below' || this.parent.editSettings.newRowPosition === 'Child')
650
+ && (this.selectedIndex > -1 || isVirtualization) && withinRange) {
651
+ position = 'after';
652
+ if (!isNullOrUndefined(records[parseInt(index.toString(), 10)]) &&
653
+ (records[parseInt(index.toString(), 10)] as ITreeData).expanded) {
654
+ if (this.parent.editSettings.mode === 'Batch' && (this.parent.getBatchChanges()[this.addedRecords].length > 1
655
+ || this.parent.getBatchChanges()[this.deletedRecords].length)) {
656
+ index += findChildrenRecords(records[parseInt(index.toString(), 10)]).length;
657
+ if (this.parent.editSettings.newRowPosition !== 'Child') {
658
+ const batchChildCount: number = this.batchEditModule.getBatchChildCount();
659
+ index = index + batchChildCount;
660
+ }
661
+ } else if (!this.parent.enableVirtualization) {
662
+ index += findChildrenRecords(records[parseInt(index.toString(), 10)]).length;
663
+ }
664
+ }
665
+ }
666
+ if ((this.selectedIndex > -1 || isVirtualization) && withinRange
667
+ && (index || (this.parent.editSettings.newRowPosition === 'Child'
668
+ || this.parent.editSettings.newRowPosition === 'Below'))) {
669
+ if (index >= rows.length - 1) {
670
+ index = rows.length - 2;
671
+ }
672
+ const r: string = 'rows';
673
+ const newRowObject: Row<Column> = this.parent.grid.contentModule[`${r}`][0];
674
+ const focussedElement: HTMLInputElement = <HTMLInputElement>document.activeElement;
675
+ rows[index + 1][`${position}`](rows[0]);
676
+ setValue('batchIndex', index + 1, this.batchEditModule);
677
+ const rowObjectIndex: number = this.parent.editSettings.newRowPosition === 'Above' ? index : index + 1;
678
+ if (this.parent.editSettings.mode === 'Batch') {
679
+ this.parent.grid.contentModule[`${r}`].splice(0, 1);
680
+ this.parent.grid.contentModule[`${r}`].splice(rowObjectIndex, 0, newRowObject);
681
+ }
682
+ if (this.parent.editSettings.mode === 'Row' || this.parent.editSettings.mode === 'Cell') {
683
+ const errors: NodeListOf<Element> = this.parent.grid.getContentTable().querySelectorAll('.e-griderror');
684
+ for (let i: number = 0; i < errors.length; i++) {
685
+ errors[parseInt(i.toString(), 10)].remove();
686
+ }
687
+ setValue('errorRules', [], this.parent.grid.editModule.formObj);
688
+ }
689
+ if (isVirtualization) {
690
+ this.prevAriaRowIndex = '-1';
691
+ }
692
+ if (!this.parent.enableVirtualization || this.parent.enableVirtualization) {
693
+ this.isScrollByFocus = true;
694
+ focussedElement.focus();
695
+ }
696
+ if (this.parent.enableVirtualization && !Object.keys(this.parent.grid.contentModule['emptyRowData']).length) {
697
+ this.parent.grid.contentModule['createEmptyRowdata']();
698
+ }
699
+ }
700
+ }
701
+ if (this.parent.editSettings.mode === 'Batch' && !isNullOrUndefined(this.addRowIndex) && this.addRowIndex !== -1 && this['isAddedRowByMethod'] && !this.isAddedRowByContextMenu) {
702
+ index = this.batchEditModule.getAddRowIndex();
703
+ this.selectedIndex = this.batchEditModule.getSelectedIndex();
704
+ const batchAddedRecords: ITreeData[] = this.parent.getBatchChanges()['addedRecords'];
705
+ let newlyAddedRecord: ITreeData;
706
+ if (batchAddedRecords.length) {
707
+ for (let i: number = 0; i < batchAddedRecords.length; i++) {
708
+ if (isNullOrUndefined(batchAddedRecords[parseInt(i.toString(), 10)].uniqueID)) {
709
+ newlyAddedRecord = batchAddedRecords[parseInt(i.toString(), 10)];
710
+ }
711
+ }
712
+ }
713
+ const args: Object = {
714
+ action : 'add',
715
+ data: newlyAddedRecord,
716
+ index: index,
717
+ seletedRow: 0
718
+ };
719
+ this.beginAddEdit(args);
720
+ this.batchEditModule['batchAddRowRecord'].push(this.batchEditModule['addRowRecord']);
721
+ this.batchEditModule['batchAddedRecords'].push(args['data']);
722
+ }
723
+ }
724
+ // private beforeDataBound(args: BeforeDataBoundArgs): void {
725
+ // if (this.parent.grid.isEdit && this.parent.dataSource instanceof DataManager &&
726
+ // this.parent.dataSource.adaptor instanceof RemoteSaveAdaptor) {
727
+ // let action: string = getValue('action', args);
728
+ // let data: Object = getValue('data', args);
729
+ // if (action === 'edit' && !isNullOrUndefined(this.editedData)) {
730
+ // data = extend(this.editedData, data);
731
+ // this.editedData = null;
732
+ // }
733
+ // if (!isNullOrUndefined(this.addedData)) {
734
+ // let addedData: Object = args.result[args.result.length - 1];
735
+ // addedData = extend(this.addedData, addedData);
736
+ // this.addedData = null;
737
+ // args.result.splice(this.addedIndex, 0, addedData);
738
+ // args.result.splice(args.result.length, 1);
739
+ // }
740
+ // }
741
+ // }
742
+ private beginEdit(args: SaveEventArgs): void {
743
+ if (args.requestType === 'refresh' && this.isOnBatch) {
744
+ args.cancel = true; return;
745
+ }
746
+ if (this.parent.editSettings.mode === 'Cell' && args.requestType === 'beginEdit') {
747
+ args.cancel = true; return;
748
+ }
749
+ if (this.doubleClickTarget && args.requestType !== 'delete' && (this.doubleClickTarget.classList.contains('e-treegridexpand') ||
750
+ this.doubleClickTarget.classList.contains('e-treegridcollapse') || this.doubleClickTarget.classList.contains('e-frame'))) {
751
+ args.cancel = true; this.doubleClickTarget = null;
752
+ return;
753
+ }
754
+ if (args.requestType === 'delete') {
755
+ const data: ITreeData[] = <ITreeData[]>args.data;
756
+ if (isNullOrUndefined((args.data[0] as ITreeData).uniqueID)) {
757
+ const primaryKeys: string[] = this.parent.getPrimaryKeyFieldNames();
758
+ for (let i: number = 0; i < data.length; i++) {
759
+ this.parent.flatData.filter((e: ITreeData) => {
760
+ if (e[`${primaryKeys[0]}`] === args.data[parseInt(i.toString(), 10)][primaryKeys[0]]) {
761
+ data[parseInt(i.toString(), 10)] = e;
762
+ }
763
+ });
764
+ }
765
+ }
766
+ for (let i: number = 0; i < data.length; i++) {
767
+ this.deleteUniqueID(data[parseInt(i.toString(), 10)].uniqueID);
768
+ const childs: ITreeData[] = findChildrenRecords(data[parseInt(i.toString(), 10)]);
769
+ for (let c: number = 0; c < childs.length; c++) {
770
+ this.deleteUniqueID(childs[parseInt(c.toString(), 10)].uniqueID);
771
+ }
772
+ args.data = [...args.data as object[], ...childs];
773
+ }
774
+ }
775
+ if (args.requestType === 'add' || (this.isAddedRowByMethod && (this.parent.enableVirtualization || this.parent.enableInfiniteScrolling))) {
776
+ if (!(this.parent.grid.selectedRowIndex === -1 && this.isAddedRowByMethod)
777
+ && args.index === this.parent.grid.selectedRowIndex || args.index === 0 ) {
778
+ this.selectedIndex = this.parent.grid.selectedRowIndex;
779
+ }
780
+ if (this.parent.enableVirtualization) {
781
+ let selector: string = '.e-row[aria-rowindex="' + (this.selectedIndex + 1) + '"]';
782
+ let row: HTMLTableRowElement;
783
+ if (this.selectedIndex > -1 && this.parent.editSettings.newRowPosition !== 'Top' &&
784
+ this.parent.editSettings.newRowPosition !== 'Bottom') {
785
+ this.prevAriaRowIndex = this.selectedIndex.toString();
786
+ row = <HTMLTableRowElement>this.parent.getContent().querySelector(selector);
787
+ this.addRowIndex = row ? row.rowIndex : 0;
788
+ } else {
789
+ if (this.prevAriaRowIndex && this.prevAriaRowIndex !== '-1') {
790
+ selector = '.e-row[aria-rowindex="' + (this.prevAriaRowIndex + 1) + '"]';
791
+ row = <HTMLTableRowElement>this.parent.getContent().querySelector(selector);
792
+ this.addRowIndex = row ? row.rowIndex : 0;
793
+ } else {
794
+ this.addRowIndex = 0;
795
+ }
796
+ }
797
+ } else {
798
+ if (this.isAddedRowByMethod && (this.parent.enableVirtualization || this.parent.enableInfiniteScrolling)) {
799
+ if (args.index !== 0) {
800
+ this.addRowIndex = args.index;
801
+ } else {
802
+ this.addRowIndex = this.parent.grid.selectedRowIndex;
803
+ }
804
+ } else {
805
+ this.addRowIndex = this.parent.grid.selectedRowIndex > -1 ? this.parent.grid.selectedRowIndex : 0;
806
+ }
807
+ }
808
+ const selectedRecords: any = this.parent.getSelectedRecords()[0];
809
+ if ((this.isAddedRowByMethod || (this.isAddedRowByContextMenu && this.parent.grid.selectedRowIndex !== -1)) &&
810
+ (this.parent.enableVirtualization || this.parent.enableInfiniteScrolling)) {
811
+ this.addRowRecord = this.parent.flatData[this.parent.grid.selectedRowIndex];
812
+ if (this.parent.enableVirtualization && this.isAddedRowByContextMenu) {
813
+ this.addRowRecord = this.parent.getCurrentViewRecords()[this.addRowIndex];
814
+ }
815
+ }
816
+ else if (!isNullOrUndefined(selectedRecords)) {
817
+ this.addRowRecord = selectedRecords;
818
+ }
819
+ }
820
+ if (this.isAddedRowByMethod && args.index !== 0) {
821
+ this.addRowRecord = this.parent.flatData[args.index];
822
+ this.addRowIndex = args.index;
823
+ }
824
+ if (this.parent.editSettings.newRowPosition === 'Child' && this.isIndexUndefined &&
825
+ !isNullOrUndefined(this.parent.getSelectedRecords()[0])) {
826
+ this.addRowRecord = this.parent.getSelectedRecords()[0];
827
+ this.isIndexUndefined = false;
828
+ }
829
+ if (isNullOrUndefined(this.addRowRecord) && this.parent.getCurrentViewRecords().length > this.addRowIndex &&
830
+ args.requestType === 'save' && this.parent.getSelectedRecords().length !== 0)
831
+ {
832
+ this.addRowRecord = this.parent.getCurrentViewRecords()[this.addRowIndex];
833
+ }
834
+ this.isAddedRowByMethod = false;
835
+ args = this.beginAddEdit(args);
836
+ // if (args.requestType === 'save' &&
837
+ // ((this.parent.dataSource instanceof DataManager && this.parent.dataSource.adaptor instanceof RemoteSaveAdaptor))) {
838
+ // if (args.action === 'edit') {
839
+ // this.editedData = args.data;
840
+ // } else if (args.action === 'add') {
841
+ // this.addedData = value;
842
+ // }
843
+
844
+ // }
845
+ }
846
+ private savePreviousRowPosition(): void {
847
+ if (this.previousNewRowPosition === null) {
848
+ this.previousNewRowPosition = this.parent.editSettings.newRowPosition;
849
+ }
850
+ }
851
+ private beginAddEdit(args: SaveEventArgs): SaveEventArgs {
852
+ const value: ITreeData = args.data;
853
+ if (args.action === 'add') {
854
+ const key: string = this.parent.grid.getPrimaryKeyFieldNames()[0];
855
+ let position: string = null;
856
+ value.taskData = isNullOrUndefined(value.taskData) ? extend({}, args.data) : value.taskData;
857
+ let currentData: ITreeData[];
858
+
859
+ if (this.parent.enableVirtualization && args.index !== 0) {
860
+ currentData = this.parent.flatData;
861
+ }
862
+ else if (this.parent.editSettings.mode === 'Batch' && this['isAddedRowByMethod'] && !isNullOrUndefined(this.addRowIndex)) {
863
+ currentData = this.batchEditModule['batchRecords'];
864
+ }
865
+ else {
866
+ currentData = <ITreeData[]>this.parent.grid.getCurrentViewRecords();
867
+ }
868
+ if (this.parent.enableVirtualization && args.index !== 0) {
869
+ this.addRowIndex = this.parent.flatData.indexOf( this.addRowRecord);
870
+ this.selectedIndex = this.addRowIndex;
871
+ }
872
+ let index: number = this.addRowIndex;
873
+ value.uniqueID = getUid(this.parent.element.id + '_data_');
874
+ setValue('uniqueIDCollection.' + value.uniqueID , value, this.parent);
875
+ let level: number = 0; let idMapping: Object;
876
+ let parentUniqueID: string; let parentItem: Object; let parentIdMapping: string;
877
+ const isVirtualization: boolean = this.parent.enableVirtualization && this.addRowIndex > -1 && this.prevAriaRowIndex !== '-1';
878
+ const rows: HTMLTableRowElement[] = this.parent.getRows();
879
+ const firstAriaIndex: number = rows.length ? currentData.indexOf(currentData[0]) : 0;
880
+ const lastAriaIndex: number = rows.length ? +rows[rows.length - 1].getAttribute('aria-rowindex') - 1 : 0;
881
+ const withinRange: boolean = this.parent.enableVirtualization && args.index !== 0 ? true :
882
+ this.selectedIndex >= firstAriaIndex && this.selectedIndex <= lastAriaIndex;
883
+ if (currentData.length && !isNullOrUndefined(index)) {
884
+ idMapping = currentData[this.addRowIndex][this.parent.idMapping];
885
+ parentIdMapping = currentData[this.addRowIndex][this.parent.parentIdMapping];
886
+ if (currentData[this.addRowIndex].parentItem) {
887
+ parentUniqueID = currentData[this.addRowIndex].parentItem.uniqueID;
888
+ }
889
+ parentItem = currentData[this.addRowIndex].parentItem;
890
+ }
891
+ if (this.parent.editSettings.newRowPosition !== 'Top' && currentData.length && !isNullOrUndefined(index)) {
892
+ level = currentData[this.addRowIndex].level;
893
+ if (this.parent.editSettings.newRowPosition === 'Above') {
894
+ position = 'before'; index = currentData[this.addRowIndex].index;
895
+ } else if (this.parent.editSettings.newRowPosition === 'Below') {
896
+ position = 'after';
897
+ const childRecordCount: number = findChildrenRecords(currentData[this.addRowIndex]).length;
898
+ const currentDataIndex: number = currentData[this.addRowIndex].index;
899
+ index = (childRecordCount > 0) ? ( currentDataIndex + childRecordCount) : (currentDataIndex);
900
+ } else if (this.parent.editSettings.newRowPosition === 'Child') {
901
+ position = 'after';
902
+ if ((this.selectedIndex > -1 || isVirtualization) && withinRange) {
903
+ value.parentItem = extend({}, currentData[this.addRowIndex]);
904
+ value.parentUniqueID = value.parentItem.uniqueID;
905
+ delete value.parentItem.childRecords; delete value.parentItem[this.parent.childMapping];
906
+ }
907
+ const childRecordCount1: number = findChildrenRecords(currentData[this.addRowIndex]).length;
908
+ const currentDataIndex1: number = currentData[this.addRowIndex].index;
909
+ if (this.selectedIndex >= 0) {
910
+ value.level = level + 1;
911
+ }
912
+ index = (childRecordCount1 > 0) ? ( currentDataIndex1 + childRecordCount1) : (currentDataIndex1);
913
+ if (this.isSelfReference) {
914
+ if (!this.parent.isLocalData && this.parent.editModule.selectedIndex === -1) {
915
+ value.taskData[this.parent.parentIdMapping] = value[this.parent.parentIdMapping] = null;
916
+ }
917
+ else {
918
+ value.taskData[this.parent.parentIdMapping] = value[this.parent.parentIdMapping] = idMapping;
919
+ }
920
+ if (!isNullOrUndefined(value.parentItem)) {
921
+ updateParentRow(key, value.parentItem, 'add', this.parent, this.isSelfReference, value);
922
+ }
923
+ }
924
+ }
925
+ if (this.parent.editSettings.newRowPosition === 'Above' || this.parent.editSettings.newRowPosition === 'Below') {
926
+ if ((this.selectedIndex > -1 || isVirtualization) && level && withinRange) {
927
+ value.parentUniqueID = parentUniqueID; value.parentItem = extend({}, parentItem);
928
+ delete value.parentItem.childRecords; delete value.parentItem[this.parent.childMapping];
929
+ }
930
+ value.level = level;
931
+ if (this.isSelfReference) {
932
+ value.taskData[this.parent.parentIdMapping] = value[this.parent.parentIdMapping] = parentIdMapping;
933
+ if (!isNullOrUndefined(value.parentItem)) {
934
+ updateParentRow(key, value.parentItem, 'add', this.parent, this.isSelfReference, value);
935
+ }
936
+ }
937
+ }
938
+ if (position != null && (this.selectedIndex > -1 || isVirtualization) && withinRange) {
939
+ args.index = position === 'before' ? index : index + 1;
940
+ }
941
+ if (this.parent.editSettings.newRowPosition === 'Bottom') {
942
+ level = 0;
943
+ const dataSource: Object[] = <Object[]>(this.parent.grid.dataSource instanceof DataManager ?
944
+ this.parent.grid.dataSource.dataSource.json : this.parent.grid.dataSource);
945
+ args.index = dataSource.length;
946
+ }
947
+ }
948
+ if (isNullOrUndefined(value.level)) {
949
+ value.level = level;
950
+ }
951
+ value.hasChildRecords = false; value.childRecords = []; value.index = 0;
952
+ }
953
+ if (args.action === 'add') {
954
+ this.internalProperties = { level: value.level, parentItem: value.parentItem, uniqueID: value.uniqueID,
955
+ taskData: value.taskData, parentUniqueID: isNullOrUndefined(value.parentItem) ? undefined : value.parentItem.uniqueID,
956
+ childRecords: value.childRecords };
957
+ }
958
+ if (args.requestType === 'delete') {
959
+ const deletedValues: ITreeData[] = args.data as Object[];
960
+ const primaryKeyField: string[] = this.parent.getPrimaryKeyFieldNames();
961
+ if (!isNullOrUndefined(primaryKeyField) && primaryKeyField.length > 0) {
962
+ for (let i: number = 0; i < deletedValues.length; i++) {
963
+ const deletevalue: any = deletedValues[parseInt(i.toString(), 10)].parentItem;
964
+ if (deletevalue) {
965
+ const parentItem: ITreeData = getParentData(this.parent, deletevalue.uniqueID);
966
+ if (!isNullOrUndefined(parentItem) && parentItem.hasChildRecords) {
967
+ const childIndex: number = parentItem.childRecords.findIndex((child: any) =>
968
+ (deletedValues[parseInt(i.toString(), 10)] as any)[primaryKeyField[0]] === child[primaryKeyField[0]]);
969
+ parentItem.childRecords.splice(childIndex, 1);
970
+ }
971
+ }
972
+ }
973
+ }
974
+ }
975
+ return args;
976
+ }
977
+
978
+
979
+ /**
980
+ * If the data,index and position given, Adds the record to treegrid rows otherwise it will create edit form.
981
+ *
982
+ * @returns {void}
983
+ */
984
+
985
+ public addRecord(data?: Object, index?: number, position?: RowPosition): void {
986
+ if (this.parent.editSettings.newRowPosition === this.previousNewRowPosition || this.previousNewRowPosition === null) {
987
+ this.previousNewRowPosition = this.parent.editSettings.newRowPosition;
988
+ }
989
+ if (isNullOrUndefined(index)) {
990
+ this.isIndexUndefined = true;
991
+ }
992
+ if (!this.isSelfReference && !isNullOrUndefined(data) && Object.hasOwnProperty.call(data, this.parent.childMapping)) {
993
+ const addRecords: ITreeData[] = [];
994
+ const previousEditMode: string = this.parent.editSettings.mode;
995
+ const previousGridEditMode: string = this.parent.grid.editSettings.mode;
996
+ addRecords.push(data);
997
+ this.parent.setProperties({ editSettings: { mode: 'Batch' } }, true);
998
+ this.parent.grid.setProperties({ editSettings: { mode: 'Batch' } }, true);
999
+ if (!isNullOrUndefined(position)) { this.parent.setProperties({ editSettings: { newRowPosition: position } }, true); }
1000
+ const updatedRecords: BatchChanges = { addedRecords: addRecords, changedRecords: [], deletedRecords: [] };
1001
+ this.parent.notify(events.batchSave, { updatedRecords, index });
1002
+ this.parent.setProperties({ editSettings: { mode: previousEditMode } }, true);
1003
+ this.parent.grid.setProperties({ editSettings: { mode: previousGridEditMode } }, true);
1004
+ this.parent.refresh();
1005
+ }
1006
+ else {
1007
+ if (data) {
1008
+ if (index > -1) {
1009
+ this.selectedIndex = index;
1010
+ this.addRowIndex = index;
1011
+ } else {
1012
+ this.selectedIndex = this.parent.selectedRowIndex;
1013
+ this.addRowIndex = this.parent.selectedRowIndex;
1014
+ }
1015
+ if (position) {
1016
+ this.parent.setProperties({ editSettings: { newRowPosition: position } }, true);
1017
+ }
1018
+ this.parent.grid.editModule.addRecord(data, index);
1019
+ } else {
1020
+ this.parent.grid.editModule.addRecord(data, index);
1021
+ }
1022
+ }
1023
+ }
1024
+
1025
+ /**
1026
+ * Checks the status of validation at the time of editing. If validation is passed, it returns true.
1027
+ *
1028
+ * @returns {boolean} Returns form validation results
1029
+ */
1030
+ public editFormValidate(): boolean {
1031
+ return this.parent.grid.editModule.editFormValidate();
1032
+ }
1033
+
1034
+ /**
1035
+ * @hidden
1036
+ * @returns {void}
1037
+ */
1038
+ public destroyForm(): void {
1039
+ this.parent.grid.editModule.destroyForm();
1040
+ }
1041
+
1042
+ private contentready (e: { rows: Row<Column>[], args?: NotifyArgs }): void {
1043
+ if (!isNullOrUndefined(e.args.requestType)
1044
+ && (e.args.requestType.toString() === 'delete' || e.args.requestType.toString() === 'save'
1045
+ || (this.parent.editSettings.mode === 'Batch' && e.args.requestType.toString() === 'batchsave'))) {
1046
+ this.updateIndex(this.parent.grid.dataSource, this.parent.getRows(), this.parent.getCurrentViewRecords());
1047
+ if (this.parent.frozenRows || this.parent.getFrozenColumns() || this.parent.frozenColumns) {
1048
+ if ((this.parent.grid.dataSource as Object[]).length === this.parent.getDataRows().length) {
1049
+ this.updateIndex(this.parent.grid.dataSource, this.parent.getDataRows(), this.parent.getCurrentViewRecords());
1050
+ }
1051
+ }
1052
+ }
1053
+ }
1054
+
1055
+ /**
1056
+ * If the row index and field is given, edits the particular cell in a row.
1057
+ *
1058
+ * @returns {void}
1059
+ */
1060
+
1061
+ public editCell(rowIndex?: number, field?: string): void {
1062
+ if (this.parent.editSettings.mode === 'Cell' || this.parent.editSettings.mode === 'Batch') {
1063
+ if (this.parent.editSettings.mode !== 'Batch') {
1064
+ this.isOnBatch = true;
1065
+ this.updateGridEditMode('Batch');
1066
+ }
1067
+ this.parent.grid.editModule.editCell(rowIndex, field);
1068
+ }
1069
+ }
1070
+
1071
+ /**
1072
+ * Cancels edited state.
1073
+ *
1074
+ * @returns {void}
1075
+ */
1076
+ private closeEdit(): void {
1077
+ if (this.parent.enableVirtualization && this.parent.grid.editSettings.mode === 'Batch' && this.parent.grid.pageSettings.currentPage > 1) {
1078
+ this.editedRowIndex = this.parent.grid.editModule.editModule['cellDetails'].rowIndex;
1079
+ this.parent.grid.editModule.editModule['cellDetails'].rowIndex = parseInt(this.parent.getRows()[this.parent.grid.editModule.editModule['cellDetails'].rowIndex].getAttribute('aria-rowIndex'), 10) - 1;
1080
+ }
1081
+ this.parent.grid.editModule.closeEdit();
1082
+ }
1083
+ }