@syncfusion/ej2-treegrid 32.2.7 → 33.1.44

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.
@@ -1,5 +1,5 @@
1
1
  import { merge, Property, ChildProperty, Collection, isNullOrUndefined, Browser, removeClass, addClass, getValue, createElement, setValue, extend as extend$1, Internationalization, getEnumValue, compile, Component, L10n, EventHandler, KeyboardEvents, SanitizeHtmlHelper, Complex, Event, NotifyPropertyChanges, closest, setStyleAttribute, select, classList, debounce, remove } from '@syncfusion/ej2-base';
2
- import { Logger as Logger$1, Grid, detailLists, Clipboard, getObject, parentsUntil, Print as Print$1, templateCompiler, appendChildren, extend, CellRenderer, getUid, CellType, Freeze as Freeze$1, getNumberFormat, getActualProperties, iterateArrayOrObject, RowDropSettings as RowDropSettings$1, Reorder as Reorder$1, Resize as Resize$1, RowDD as RowDD$1, Scroll, VirtualRowModelGenerator, Filter as Filter$1, ExcelExport as ExcelExport$1, Data, ExportHelper, PdfExport as PdfExport$1, Page as Page$1, Toolbar as Toolbar$1, Aggregate as Aggregate$1, calculateAggregate, Sort as Sort$1, ColumnMenu as ColumnMenu$1, ContextMenu as ContextMenu$1, Edit as Edit$1, resetRowIndex, CommandColumn as CommandColumn$1, DetailRow as DetailRow$1, VirtualContentRenderer, Cell, getVisiblePage, InterSectionObserver, getTransformValues, VirtualScroll as VirtualScroll$1, RenderType, VirtualHeaderRenderer, ColumnChooser as ColumnChooser$1, InfiniteScroll as InfiniteScroll$1, getRowIndexFromElement, RowRenderer } from '@syncfusion/ej2-grids';
2
+ import { Logger as Logger$1, Grid, detailLists, Clipboard, getObject, parentsUntil, Print as Print$1, templateCompiler, appendChildren, extend, CellRenderer, getUid, CellType, Freeze as Freeze$1, getNumberFormat, setEnableSeamlessScrolling, getActualProperties, iterateArrayOrObject, RowDropSettings as RowDropSettings$1, Reorder as Reorder$1, Resize as Resize$1, RowDD as RowDD$1, Scroll, VirtualRowModelGenerator, Filter as Filter$1, ExcelExport as ExcelExport$1, Data, ExportHelper, PdfExport as PdfExport$1, Page as Page$1, Toolbar as Toolbar$1, Aggregate as Aggregate$1, calculateAggregate, Sort as Sort$1, ColumnMenu as ColumnMenu$1, ContextMenu as ContextMenu$1, Edit as Edit$1, resetRowIndex, CommandColumn as CommandColumn$1, DetailRow as DetailRow$1, VirtualContentRenderer, Cell, getVisiblePage, InterSectionObserver, getTransformValues, VirtualScroll as VirtualScroll$1, RenderType, VirtualHeaderRenderer, ColumnChooser as ColumnChooser$1, InfiniteScroll as InfiniteScroll$1, getRowIndexFromElement, RowRenderer } from '@syncfusion/ej2-grids';
3
3
  import { createCheckBox } from '@syncfusion/ej2-buttons';
4
4
  import { DataManager, ODataAdaptor, WebApiAdaptor, WebMethodAdaptor, CacheAdaptor, UrlAdaptor, Query, DataUtil, RemoteSaveAdaptor, Deferred, JsonAdaptor, Predicate as Predicate$1 } from '@syncfusion/ej2-data';
5
5
  import { showSpinner, hideSpinner, createSpinner } from '@syncfusion/ej2-popups';
@@ -3136,7 +3136,6 @@ class DataManipulation {
3136
3136
  let results = dataObj instanceof DataManager ? dataObj.dataSource.json : dataObj;
3137
3137
  let count = isCountRequired(this.parent) ? getValue('count', this.parent.dataSource)
3138
3138
  : results.length;
3139
- const qry = new Query();
3140
3139
  let gridQuery = getObject('query', args);
3141
3140
  let filterQuery;
3142
3141
  let searchQuery;
@@ -3152,11 +3151,7 @@ class DataManipulation {
3152
3151
  gridQuery = getValue('grid.renderModule.data', this.parent).filterQuery(gridQuery);
3153
3152
  gridQuery = getValue('grid.renderModule.data', this.parent).searchQuery(gridQuery);
3154
3153
  }
3155
- const fltrQuery = gridQuery.queries.filter((q) => q.fn === 'onWhere');
3156
- const srchQuery = gridQuery.queries.filter((q) => q.fn === 'onSearch');
3157
- qry.queries = fltrQuery.concat(srchQuery);
3158
- const filteredData = new DataManager(results).executeLocal(qry);
3159
- this.parent.notify('updateFilterRecs', { data: filteredData });
3154
+ this.parent.getData({ query: gridQuery, isFilter: true });
3160
3155
  results = this.dataResults.result;
3161
3156
  this.dataResults.result = null;
3162
3157
  if (this.parent.grid.aggregates.length > 0) {
@@ -3181,34 +3176,8 @@ class DataManipulation {
3181
3176
  }
3182
3177
  if (this.parent.grid.sortSettings.columns.length > 0 || this.isSortAction) {
3183
3178
  this.isSortAction = false;
3184
- const parentData = this.parent.parentData;
3185
3179
  const query = getObject('query', args);
3186
- const srtQry = new Query();
3187
- for (let srt = this.parent.grid.sortSettings.columns.length - 1; srt >= 0; srt--) {
3188
- const getColumnByField = 'getColumnByField';
3189
- const col = this.parent.grid.renderModule.data[`${getColumnByField}`](this.parent.grid.
3190
- sortSettings.columns[parseInt(srt.toString(), 10)].field);
3191
- const compFun = col.sortComparer && isOffline(this.parent) ?
3192
- col.sortComparer.bind(col) :
3193
- this.parent.grid.sortSettings.columns[parseInt(srt.toString(), 10)].direction;
3194
- srtQry.sortBy(this.parent.grid.sortSettings.columns[parseInt(srt.toString(), 10)].field, compFun);
3195
- }
3196
- const modifiedData = new DataManager(parentData).executeLocal(srtQry);
3197
- if (this.parent.allowRowDragAndDrop && !isNullOrUndefined(this.parent.rowDragAndDropModule['draggedRecord']) &&
3198
- this.parent.rowDragAndDropModule['droppedRecord'].hasChildRecords && this.parent.rowDragAndDropModule['dropPosition'] !== 'middleSegment') {
3199
- const dragdIndex = modifiedData.indexOf(this.parent.rowDragAndDropModule['draggedRecord']);
3200
- modifiedData.splice(dragdIndex, 1);
3201
- const dropdIndex = modifiedData.indexOf(this.parent.rowDragAndDropModule['droppedRecord']);
3202
- if (this.parent.rowDragAndDropModule['droppedRecord'].hasChildRecords && this.parent.rowDragAndDropModule['dropPosition'] === 'topSegment') {
3203
- modifiedData.splice(dropdIndex, 0, this.parent.rowDragAndDropModule['draggedRecord']);
3204
- }
3205
- else if (this.parent.rowDragAndDropModule['dropPosition'] === 'bottomSegment') {
3206
- modifiedData.splice(dropdIndex + 1, 0, this.parent.rowDragAndDropModule['draggedRecord']);
3207
- }
3208
- }
3209
- const sortArgs = { modifiedData: modifiedData, filteredData: results, srtQry: srtQry };
3210
- this.parent.notify('createSort', sortArgs);
3211
- results = sortArgs.modifiedData;
3180
+ results = this.parent.getData({ query: query, isSort: true });
3212
3181
  this.dataResults.result = null;
3213
3182
  this.sortedData = results;
3214
3183
  this.parent.notify('updateModel', {});
@@ -4038,6 +4007,8 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
4038
4007
  this.isComponentRefresh = false;
4039
4008
  this.isVirtualExpandCollapse = false;
4040
4009
  this.isInfiniteCollapse = false;
4010
+ /** @hidden */
4011
+ this.enableSeamlessScrolling = false;
4041
4012
  this.objectEqualityChecker = (old, current) => {
4042
4013
  if (old) {
4043
4014
  const keys = Object.keys(old);
@@ -4781,7 +4752,15 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
4781
4752
  this.renderModule = new Render(this);
4782
4753
  this.dataModule = new DataManipulation(this);
4783
4754
  this.printModule = new Print(this);
4784
- this.trigger(load);
4755
+ if (this.enableVirtualization || this.enableColumnVirtualization) {
4756
+ const args = { enableSeamlessScrolling: this.enableSeamlessScrolling };
4757
+ this.trigger(load, args);
4758
+ this.enableSeamlessScrolling = args.enableSeamlessScrolling;
4759
+ setEnableSeamlessScrolling(this.enableSeamlessScrolling);
4760
+ }
4761
+ else {
4762
+ this.trigger(load);
4763
+ }
4785
4764
  this.autoGenerateColumns();
4786
4765
  this.initialRender = true;
4787
4766
  if (!isNullOrUndefined(this.dataSource)) {
@@ -5047,6 +5026,7 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
5047
5026
  this.grid.clipMode = getActualProperties(this.clipMode);
5048
5027
  this.grid.enableColumnSpan = this.enableColumnSpan;
5049
5028
  this.grid.enableRowSpan = this.enableRowSpan;
5029
+ this.grid.enableSeamlessScrolling = this.enableSeamlessScrolling;
5050
5030
  const templateInstance = 'templateDotnetInstance';
5051
5031
  this.grid[`${templateInstance}`] = this[`${templateInstance}`];
5052
5032
  const isJsComponent = 'isJsComponent';
@@ -5518,7 +5498,7 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
5518
5498
  }
5519
5499
  this.notify('updateGridActions', args);
5520
5500
  this.isVirtualExpandCollapse = false;
5521
- if (args.requestType === 'save' && this.aggregates.map((ag) => ag.showChildSummary === true).length) {
5501
+ if (args.requestType === 'save' && this.aggregates.some((ag) => ag.showChildSummary === true)) {
5522
5502
  this.grid.refresh();
5523
5503
  }
5524
5504
  if ((args.action === 'clearFilter' || args.action === 'clear-filter' || args.requestType === 'sorting') && this.enableInfiniteScrolling) {
@@ -6257,6 +6237,114 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
6257
6237
  }
6258
6238
  }
6259
6239
  }
6240
+ /**
6241
+ * Retrieves all records that match the current search criteria and are sorted according to the active sort settings.
6242
+ *
6243
+ * This method processes the data source by applying search filters and sort operations,
6244
+ * returning the searched and sorted records excluding summary rows.
6245
+ *
6246
+ * @param {Object} args - Optional arguments object to control query execution behavior.
6247
+ * @param {Query} args.query - Optional custom Query object to override the default generated query.
6248
+ * @param {boolean} args.isFilter - Optional flag to include only filtered records without sorting (default: false).
6249
+ * @param {boolean} args.isSort - Optional flag to apply only sorting without filtering (default: false).
6250
+ *
6251
+ * @returns {ITreeData[]} - Array of searched and sorted TreeGrid records with summary rows excluded.
6252
+ * @hidden
6253
+ */
6254
+ getData(args) {
6255
+ const dataObj = isCountRequired(this) ? getValue('result', this.grid.dataSource)
6256
+ : this.grid.dataSource;
6257
+ let results = dataObj instanceof DataManager ? dataObj.dataSource.json : dataObj;
6258
+ const gridQuery = (!isNullOrUndefined(args) && args.query) ? args.query : this.getDataModule().baseModule.generateQuery();
6259
+ let filterQuery;
6260
+ let searchQuery;
6261
+ if (!isNullOrUndefined(gridQuery)) {
6262
+ filterQuery = gridQuery.queries.filter((q) => q.fn === 'onWhere');
6263
+ searchQuery = gridQuery.queries.filter((q) => q.fn === 'onSearch');
6264
+ }
6265
+ const skipFilterSearch = (!isNullOrUndefined(args) && args.isSort);
6266
+ if (!skipFilterSearch && (this.grid.allowFiltering && this.grid.filterSettings.columns.length) ||
6267
+ (this.grid.searchSettings.key.length > 0) && (!isNullOrUndefined(gridQuery))
6268
+ || ((filterQuery && filterQuery.length > 0) || (searchQuery && searchQuery.length > 0))) {
6269
+ const filterQuery = gridQuery.queries.filter((q) => q.fn === 'onWhere');
6270
+ const searchQuery = gridQuery.queries.filter((q) => q.fn === 'onSearch');
6271
+ const query = new Query();
6272
+ query.queries = filterQuery.concat(searchQuery);
6273
+ const filteredData = new DataManager(results).executeLocal(query);
6274
+ this.notify('updateFilterRecs', { data: filteredData });
6275
+ results = isRemoteData(this) ? this.dataResults : this.filterModule.filteredResult;
6276
+ if (!isNullOrUndefined(args) && args.isFilter) {
6277
+ return isRemoteData(this) ? results.result.filter((item) => !item.isSummaryRow)
6278
+ : results.filter((item) => !item.isSummaryRow);
6279
+ }
6280
+ }
6281
+ const sortQuery = gridQuery.queries.filter((q) => q.fn === 'onSortBy');
6282
+ if (this.grid.sortSettings.columns.length > 0 || sortQuery.length) {
6283
+ const parentData = this.parentData;
6284
+ const query = new Query();
6285
+ query.queries = sortQuery;
6286
+ const modifiedData = new DataManager(parentData).executeLocal(query);
6287
+ if (this.allowRowDragAndDrop && !isNullOrUndefined(this.rowDragAndDropModule['draggedRecord']) &&
6288
+ this.rowDragAndDropModule['droppedRecord'].hasChildRecords && this.rowDragAndDropModule['dropPosition'] !== 'middleSegment') {
6289
+ const dragdIndex = modifiedData.indexOf(this.rowDragAndDropModule['draggedRecord']);
6290
+ modifiedData.splice(dragdIndex, 1);
6291
+ const dropdIndex = modifiedData.indexOf(this.rowDragAndDropModule['droppedRecord']);
6292
+ if (this.rowDragAndDropModule['droppedRecord'].hasChildRecords && this.rowDragAndDropModule['dropPosition'] === 'topSegment') {
6293
+ modifiedData.splice(dropdIndex, 0, this.rowDragAndDropModule['draggedRecord']);
6294
+ }
6295
+ else if (this.rowDragAndDropModule['dropPosition'] === 'bottomSegment') {
6296
+ modifiedData.splice(dropdIndex + 1, 0, this.rowDragAndDropModule['draggedRecord']);
6297
+ }
6298
+ }
6299
+ const sortArgs = { modifiedData: modifiedData, filteredData: results, srtQry: query };
6300
+ this.notify('createSort', sortArgs);
6301
+ results = isRemoteData(this) ? this.dataResults : sortArgs.modifiedData;
6302
+ }
6303
+ return isRemoteData(this) ? this.dataResults.result.filter((item) => !item.isSummaryRow)
6304
+ : results.filter((item) => !item.isSummaryRow);
6305
+ }
6306
+ /**
6307
+ * Retrieves the processed Tree Grid data based on current operations such as
6308
+ * sorting, filtering, and searching. Maintains hierarchy and current structure.
6309
+ *
6310
+ * For local data: when skipPage is true (the default), it returns all available records;
6311
+ * when skipPage is false, it returns only the records for the current page.
6312
+ * For remote data: it always returns only the records for the current page.
6313
+ *
6314
+ * @param {boolean} skipPage - if set to false, returns only the records for the current page.
6315
+ * @returns {ITreeData[]} - Array of tree records (summary rows excluded).
6316
+ * @hidden
6317
+ */
6318
+ getProcessedRecords(skipPage) {
6319
+ let result;
6320
+ if (skipPage !== true || isRemoteData(this)) {
6321
+ result = this.getData();
6322
+ const dm = new DataManager(result);
6323
+ const expanded = new Predicate$1('expanded', 'notequal', null).or('expanded', 'notequal', undefined);
6324
+ const parents = dm.executeLocal(new Query().where(expanded));
6325
+ const visualData = parents.filter((e) => {
6326
+ return getExpandStatus(this, e);
6327
+ });
6328
+ let query = new Query();
6329
+ if (this.allowPaging || this.enableVirtualization || this.enableInfiniteScrolling) {
6330
+ const pageSize = this.grid.pageSettings.pageSize;
6331
+ let currentPage = this.grid.pageSettings.currentPage;
6332
+ if (visualData.length < (currentPage * pageSize)) {
6333
+ currentPage = (Math.floor(visualData.length / pageSize)) + ((visualData.length % pageSize) ? 1 : 0);
6334
+ currentPage = currentPage ? currentPage : 1;
6335
+ this.grid.setProperties({ pageSettings: { currentPage: currentPage } }, true);
6336
+ }
6337
+ const skip = pageSize * (currentPage - 1);
6338
+ query = query.skip(skip).take(pageSize);
6339
+ }
6340
+ dm.dataSource.json = visualData;
6341
+ result = dm.executeLocal(query);
6342
+ }
6343
+ else {
6344
+ result = this.getData();
6345
+ }
6346
+ return result;
6347
+ }
6260
6348
  /**
6261
6349
  * Retrieves all the TreeGrid row elements.
6262
6350
  *
@@ -6513,11 +6601,6 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
6513
6601
  rowData.hasChildRecords = record.hasChildRecords;
6514
6602
  rowData.parentUniqueID = record.parentUniqueID;
6515
6603
  rowData.expanded = record.expanded;
6516
- if (this.enableVirtualization) {
6517
- this.grid.selectionModule.selectedRowIndexes = this.grid.selectionModule.selectedRowIndexes.indexOf(record.index) === -1
6518
- && (this.selectedRowIndex >= 0 && this.selectedRowIndex !== record.index) ? [record.index] :
6519
- this.grid.selectionModule.selectedRowIndexes;
6520
- }
6521
6604
  this.grid.setRowData(key, rowData);
6522
6605
  const visibleRecords = this.getVisibleRecords();
6523
6606
  if (visibleRecords.length > 0 && key === (visibleRecords[visibleRecords.length - 1])[`${primaryKey}`]) {
@@ -10453,7 +10536,13 @@ class RowDD {
10453
10536
  const rowIndex = tObj.selectedRowIndex === -1 ?
10454
10537
  (this.parent.grid.getRowIndexByPrimaryKey(args.data[0][`${primaryKeyField}`])) - 1
10455
10538
  : tObj.getSelectedRowIndexes()[0] - 1;
10456
- const record = tObj.getCurrentViewRecords()[parseInt(rowIndex.toString(), 10)];
10539
+ let record;
10540
+ if (this.parent.enableVirtualization) {
10541
+ record = tObj.getCurrentViewRecords().find((e) => e.index === rowIndex);
10542
+ }
10543
+ else {
10544
+ record = tObj.getCurrentViewRecords()[parseInt(rowIndex.toString(), 10)];
10545
+ }
10457
10546
  this.getParentData(record, args.data);
10458
10547
  }
10459
10548
  else {
@@ -11446,11 +11535,22 @@ class ExcelExport {
11446
11535
  let query = new Query();
11447
11536
  if (!this.isLocal()) {
11448
11537
  query = this.generateQuery(query);
11449
- query.queries = this.parent.grid.getDataModule().generateQuery().queries;
11450
- query = ExportHelper.getQuery(this.parent.grid, data);
11451
- if (isNullOrUndefined(this.parent.filterModule)) {
11452
- query.queries = query.queries.slice(1, 2);
11453
- query.params = query.params.slice(0, 0);
11538
+ const hasFilter = this.parent.grid.filterSettings &&
11539
+ Array.isArray(this.parent.grid.filterSettings.columns) &&
11540
+ this.parent.grid.filterSettings.columns.length > 0;
11541
+ const hasSearch = this.parent.grid.searchSettings &&
11542
+ typeof this.parent.grid.searchSettings.key === 'string' &&
11543
+ this.parent.grid.searchSettings.key.trim().length > 0;
11544
+ const hasSorting = this.parent.grid.sortSettings &&
11545
+ Array.isArray(this.parent.grid.sortSettings.columns) &&
11546
+ this.parent.grid.sortSettings.columns.length > 0;
11547
+ if (hasFilter || hasSearch || hasSorting) {
11548
+ query.queries = this.parent.grid.getDataModule().generateQuery().queries;
11549
+ query = ExportHelper.getQuery(this.parent.grid, data);
11550
+ if (isNullOrUndefined(this.parent.filterModule)) {
11551
+ query.queries = query.queries.slice(1, 2);
11552
+ query.params = query.params.slice(0, 0);
11553
+ }
11454
11554
  }
11455
11555
  setValue('query', query, property);
11456
11556
  }
@@ -11492,6 +11592,24 @@ class ExcelExport {
11492
11592
  if (!isNullOrUndefined(this.parent.grid.getDataModule())) {
11493
11593
  setValue('query', this.parent.grid.getDataModule().generateQuery(true), args);
11494
11594
  }
11595
+ if (!this.isLocal() && !isNullOrUndefined(property) &&
11596
+ !isNullOrUndefined(property.isCollapsedStatePersist) &&
11597
+ property.isCollapsedStatePersist === false) {
11598
+ if (args.query && args.query.queries && args.query.queries.length) {
11599
+ args.query.queries = args.query.queries.filter((q) => {
11600
+ if (q.fn === 'onWhere' && q.e) {
11601
+ const preds = q.e;
11602
+ if (preds && preds.field === this.parent.parentIdMapping && (preds.value === null || preds.value === 'null')) {
11603
+ return false;
11604
+ }
11605
+ }
11606
+ return true;
11607
+ });
11608
+ }
11609
+ if (args.query && args.query.params && args.query.params.length) {
11610
+ args.query.params = args.query.params.filter((param) => param.key !== 'IdMapping');
11611
+ }
11612
+ }
11495
11613
  setValue('isExport', true, args);
11496
11614
  if (!isNullOrUndefined(property) && !isNullOrUndefined(property.exportType)) {
11497
11615
  setValue('exportType', property.exportType, args);
@@ -11704,7 +11822,7 @@ class PdfExport {
11704
11822
  return query;
11705
11823
  }
11706
11824
  manipulatePdfProperties(prop, dtSrc, queryResult) {
11707
- let args = {};
11825
+ let args = Object();
11708
11826
  //count not required for this query
11709
11827
  const isLocal = !isRemoteData(this.parent) && isOffline(this.parent);
11710
11828
  setValue('query', this.parent.grid.getDataModule().generateQuery(true), args);
@@ -14783,7 +14901,11 @@ class VirtualTreeContentRenderer extends VirtualContentRenderer {
14783
14901
  && this.parent.dataSource.dataSource.offline && this.parent.dataSource.dataSource.url !== '') || !isCountRequired(this.parent)) {
14784
14902
  this.parent[`${action}`]('data-ready', this.onDataReady, this);
14785
14903
  this.parent[`${action}`]('refresh-virtual-block', this.refreshContentRows, this);
14904
+ this.parent.on(destroy, this.destroy, this);
14786
14905
  this.fn = () => {
14906
+ if (this.parent.root.enableSeamlessScrolling) {
14907
+ window.addEventListener('resize', this.updateScrollbar.bind(this));
14908
+ }
14787
14909
  this.observers.observes((scrollArgs) => this.scrollListeners(scrollArgs), this.onEnteredAction(), this.parent);
14788
14910
  const gObj = this.parent;
14789
14911
  if (gObj.root.enablePersistence && gObj.root.scrollPosition) {
@@ -14833,6 +14955,10 @@ class VirtualTreeContentRenderer extends VirtualContentRenderer {
14833
14955
  const virtualCellFocus = 'virtualCellFocus';
14834
14956
  super[`${virtualCellFocus}`](e);
14835
14957
  }
14958
+ updateScrollbar() {
14959
+ const updateScrollbarOnResize = 'updateScrollbarOnResize';
14960
+ super[`${updateScrollbarOnResize}`]();
14961
+ }
14836
14962
  /**
14837
14963
  * Handles the data ready event for the virtual tree grid content renderer.
14838
14964
  *
@@ -14873,9 +14999,6 @@ class VirtualTreeContentRenderer extends VirtualContentRenderer {
14873
14999
  super.renderTable();
14874
15000
  if (!(this.parent.dataSource instanceof DataManager && this.parent.dataSource.dataSource.url !== undefined
14875
15001
  && this.parent.dataSource.dataSource.offline && this.parent.dataSource.dataSource.url !== '') || !isCountRequired(this.parent)) {
14876
- if (this.observers) {
14877
- this.observers.disconnect();
14878
- }
14879
15002
  getValue('observer', this).options.debounceEvent = false;
14880
15003
  this.observers = new TreeInterSectionObserver(getValue('observer', this).element, getValue('observer', this).options);
14881
15004
  this.contents = this.getPanel().firstChild;
@@ -14956,7 +15079,7 @@ class VirtualTreeContentRenderer extends VirtualContentRenderer {
14956
15079
  }
14957
15080
  const treeGridParent = this.parent.clipboardModule['treeGridParent'];
14958
15081
  if (isNullOrUndefined(treeGridParent.editModule) ||
14959
- isNullOrUndefined(treeGridParent.editModule['addRowIndex']) || args.selectedIndex !== 0) {
15082
+ isNullOrUndefined(treeGridParent.editModule['addRowIndex']) || args.selectedIndex !== -1) {
14960
15083
  if (!isNullOrUndefined(treeGridParent.grid.sortModule) && treeGridParent.grid.sortModule['sortedColumns'].length > 0) {
14961
15084
  const sortedData = treeGridParent.dataModule['sortedData'];
14962
15085
  if (!isNullOrUndefined(sortedData) && sortedData.length > 0) {
@@ -15255,16 +15378,28 @@ class VirtualTreeContentRenderer extends VirtualContentRenderer {
15255
15378
  const maxLeft = this.vgenerator.cOffsets[idx - 1];
15256
15379
  x = x > maxLeft ? maxLeft : x; //TODO: This fix horizontal scrollbar jumping issue in column virtualization.
15257
15380
  }
15258
- let y = this.getTranslateY(e.top, height, xAxis && top === e.top ? this.prevInfo : undefined, true);
15381
+ const isRowScrollAction = this.prevInfo && this.prevInfo.page === 1 &&
15382
+ (direction !== this.prevInfo.direction || direction !== this.prevInfo.direction);
15383
+ let translateY = this.getTranslateY(e.top, height, xAxis && top === e.top ? this.prevInfo : undefined, isRowScrollAction ? false : true);
15259
15384
  if (!this.parent.isFrozenGrid() || this.parent.enableVirtualMaskRow) {
15260
15385
  if (this.parent.enableVirtualMaskRow) {
15261
15386
  const upScroll = (e.top - this.translateY) < 0;
15262
- y = (Math.round(this.translateY) > y && !upScroll) ? Math.round(this.translateY) : y;
15263
- this.virtualEle.adjustTable(x, y);
15387
+ translateY = (Math.round(this.translateY) > translateY && !upScroll) ? Math.round(this.translateY) : translateY;
15388
+ this.virtualEle.adjustTable(x, translateY);
15264
15389
  }
15265
15390
  else {
15266
15391
  this.virtualEle.adjustTable(x, this.translateY);
15267
15392
  }
15393
+ const wrapperBottom = this.virtualEle.wrapper.getBoundingClientRect().bottom;
15394
+ const contentBottom = this.virtualEle.content.getBoundingClientRect().bottom;
15395
+ if (direction === 'up' && this.prevInfo.page === Math.ceil(this.getTotalBlocks() / 2) &&
15396
+ Math.round(wrapperBottom) < Math.round(contentBottom)) {
15397
+ const bottomGap = Math.round(contentBottom) - Math.round(wrapperBottom);
15398
+ const adjustedTranslateY = Math.min(translateY + bottomGap, this.offsets[this['maxBlock']]);
15399
+ if (adjustedTranslateY !== translateY) {
15400
+ this.virtualEle.adjustTable(x, adjustedTranslateY);
15401
+ }
15402
+ }
15268
15403
  if (this.parent.enableColumnVirtualization) {
15269
15404
  this.header.virtualEle.adjustTable(x, 0);
15270
15405
  if (this.parent.isFrozenGrid()) {
@@ -15381,6 +15516,9 @@ class VirtualTreeContentRenderer extends VirtualContentRenderer {
15381
15516
  (this.parent.pageSettings.pageSize / 2) && (this.endIndex - nextSetResIndex) < (this.parent.pageSettings.pageSize / 2)) {
15382
15517
  this.startIndex = lastIndex - (this.parent.pageSettings.pageSize / 2);
15383
15518
  }
15519
+ if (this.totalRecords < this.parent.pageSettings.pageSize) {
15520
+ this.startIndex = 0;
15521
+ }
15384
15522
  if (scrollArgs.offset.top > (rowHeight * this.totalRecords)) {
15385
15523
  this.translateY = this.getTranslateY(scrollArgs.offset.top, content.getBoundingClientRect().height);
15386
15524
  }
@@ -15590,9 +15728,16 @@ class VirtualTreeContentRenderer extends VirtualContentRenderer {
15590
15728
  this.parent.off('refresh-virtual-editform-cells', this.refreshCell);
15591
15729
  this.parent.off('virtaul-cell-focus', this.cellFocus);
15592
15730
  this.parent.off('virtual-scroll-edit', this.restoreEditState);
15593
- if (this.observers) {
15594
- this.observers.disconnect();
15731
+ this.parent.off(destroy, this.destroy);
15732
+ if (this.parent.root.enableSeamlessScrolling) {
15733
+ window.removeEventListener('resize', this.updateScrollbar);
15734
+ }
15735
+ }
15736
+ destroy() {
15737
+ if (this.parent.isDestroyed) {
15738
+ return;
15595
15739
  }
15740
+ this.removeEventListener();
15596
15741
  }
15597
15742
  }
15598
15743
  class TreeInterSectionObserver extends InterSectionObserver {
@@ -15603,6 +15748,9 @@ class TreeInterSectionObserver extends InterSectionObserver {
15603
15748
  this.lastPos = 0;
15604
15749
  this.timer = 0;
15605
15750
  }
15751
+ onWheelEvent() {
15752
+ this.isWheeling = true;
15753
+ }
15606
15754
  /**
15607
15755
  * Sets up observers to monitor scroll events on a given container
15608
15756
  * and its movable companion within a virtual grid setup.
@@ -15615,28 +15763,27 @@ class TreeInterSectionObserver extends InterSectionObserver {
15615
15763
  observes(callback, onEnterCallback, instance) {
15616
15764
  const containerRect = 'containerRect';
15617
15765
  super[`${containerRect}`] = getValue('options', this).container.getBoundingClientRect();
15618
- this.containerEl = getValue('options', this).container;
15619
- this.containerScrollHandler = this.virtualScrollHandlers(callback, onEnterCallback, instance);
15620
- EventHandler.add(this.containerEl, 'scroll', this.containerScrollHandler, this);
15621
- if (getValue('options', this).movableContainer) {
15622
- const movableContainerRect = 'movableContainerRect';
15623
- super[`${movableContainerRect}`] = getValue('options', this).movableContainer.getBoundingClientRect();
15624
- this.movableContainerEl = getValue('options', this).movableContainer;
15625
- this.movableScrollHandler = this.virtualScrollHandlers(callback, onEnterCallback, instance);
15626
- EventHandler.add(this.movableContainerEl, 'scroll', this.movableScrollHandler, this);
15627
- }
15628
- }
15629
- disconnect() {
15630
- if (this.containerEl && this.containerScrollHandler) {
15631
- EventHandler.remove(this.containerEl, 'scroll', this.containerScrollHandler);
15632
- this.containerScrollHandler = null;
15766
+ const options = getValue('options', this);
15767
+ EventHandler.add(options.container, 'wheel', this.onWheelEvent, this);
15768
+ if (!isNullOrUndefined(options.horizontalScrollbar)) {
15769
+ EventHandler.add(options.horizontalScrollbar, 'wheel', this.onWheelEvent, this);
15770
+ EventHandler.add(options.horizontalScrollbar, 'scroll', this.onVirtualContentScrolling(), this);
15633
15771
  }
15634
- if (this.movableContainerEl && this.movableScrollHandler) {
15635
- EventHandler.remove(this.movableContainerEl, 'scroll', this.movableScrollHandler);
15636
- this.movableScrollHandler = null;
15772
+ if (!isNullOrUndefined(options.verticalScrollbar)) {
15773
+ EventHandler.add(options.verticalScrollbar, 'wheel', this.onWheelEvent, this);
15774
+ EventHandler.add(options.verticalScrollbar, 'scroll', this.onVirtualContentScrolling(), this);
15637
15775
  }
15638
- this.containerEl = null;
15639
- this.movableContainerEl = null;
15776
+ EventHandler.add(options.container, 'scroll', this.virtualScrollHandlers(callback, onEnterCallback, instance), this);
15777
+ }
15778
+ onVirtualContentScrolling() {
15779
+ return (e) => {
15780
+ if (e.target.classList.contains('e-virtual-vertical-scrollbar')) {
15781
+ getValue('options', this).container.scrollTop = e.target.scrollTop;
15782
+ }
15783
+ if (e.target.classList.contains('e-virtual-horizontal-scrollbar')) {
15784
+ getValue('options', this).container.scrollLeft = e.target.scrollLeft;
15785
+ }
15786
+ };
15640
15787
  }
15641
15788
  /**
15642
15789
  * Clears the last known position.
@@ -15681,6 +15828,12 @@ class TreeInterSectionObserver extends InterSectionObserver {
15681
15828
  direction = this[`${options}`].prevLeft === left ? direction : this[`${options}`].prevLeft < left ? 'right' : 'left';
15682
15829
  this[`${options}`].prevTop = top;
15683
15830
  this[`${options}`].prevLeft = left;
15831
+ if (!isNullOrUndefined(this[`${options}`].verticalScrollbar)) {
15832
+ this[`${options}`].verticalScrollbar.scrollTop = this[`${options}`].container.scrollTop;
15833
+ }
15834
+ if (!isNullOrUndefined(this[`${options}`].horizontalScrollbar)) {
15835
+ this[`${options}`].horizontalScrollbar.scrollLeft = this[`${options}`].container.scrollLeft;
15836
+ }
15684
15837
  const current = this.sentinelInfo[`${direction}`];
15685
15838
  let delta = 0;
15686
15839
  this.newPos = top;