@syncfusion/ej2-treegrid
Version:
Essential JS 2 TreeGrid Component
900 lines • 61.3 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import { Cell, CellType, getVisiblePage } from '@syncfusion/ej2-grids';
import { VirtualContentRenderer } from '@syncfusion/ej2-grids';
import * as literals from '../base/constant';
import { InterSectionObserver } from '@syncfusion/ej2-grids';
import { TreeVirtualRowModelGenerator } from '../renderer/virtual-row-model-generator';
import * as events from '../base/constant';
import { isNullOrUndefined, EventHandler, getValue, setValue, Browser, debounce } from '@syncfusion/ej2-base';
import { DataManager } from '@syncfusion/ej2-data';
import { isCountRequired, isRemoteData } from '../utils';
/**
* VirtualTreeContentRenderer
*
* @hidden
*/
var VirtualTreeContentRenderer = /** @class */ (function (_super) {
__extends(VirtualTreeContentRenderer, _super);
function VirtualTreeContentRenderer(parent, locator) {
var _this = _super.call(this, parent, locator) || this;
_this.isExpandCollapse = false;
_this.translateY = 0;
_this.maxiPage = 0;
_this.recordAdded = false;
/** @hidden */
_this.startIndex = -1;
_this.endIndex = -1;
_this.preTranslate = 0;
_this.isRemoteExpand = false;
/** @hidden */
_this.isDataSourceChanged = false;
_this.addEventListener();
return _this;
}
VirtualTreeContentRenderer.prototype.getModelGenerator = function () {
return new TreeVirtualRowModelGenerator(this.parent);
};
/**
* Retrieves the row element for a given row index.
*
* @param {number} index - The index of the row to retrieve.
* @returns {Element} The row element at the specified index.
*/
VirtualTreeContentRenderer.prototype.getRowByIndex = function (index) {
if (this.parent.enableVirtualization && this.parent.isFrozenGrid()) {
return this.getRowCollection(index, true);
}
var dataRows = this.parent.getDataRows();
var targetRow = dataRows.find(function (e) { return parseInt(e.getAttribute('aria-rowindex'), 10) - 1 === index; });
if (!targetRow && this.parent.isEdit && this.parent.editSettings.mode === 'Batch') {
return index != null ? this.parent.getRows()[parseInt(index.toString(), 10)] : undefined;
}
return targetRow;
};
/**
* Retrieves the frozen right virtual row element by its index.
*
* @param {number} index - The index of the row to be retrieved.
* @returns {Element} The DOM element representing the frozen right virtual row.
*/
VirtualTreeContentRenderer.prototype.getFrozenRightVirtualRowByIndex = function (index) {
return this.getRowCollection(index, false, false, true);
};
/**
* Retrieves the row or record from the virtual tree grid based on the provided index.
* Considers conditions such as frozen rows and pagination for accurate retrieval.
*
* @param {number} index - The index of the desired row or record.
* @param {boolean} isMovable - Specifies if the content is movable.
* @param {boolean} [isRowObject] - Optional. Determines if the return value should be a row object.
* @param {boolean} [isFrozenRight] - Optional. Used for determining frozen right rows.
* @returns {Element | Object} - The HTML element or row object.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
VirtualTreeContentRenderer.prototype.getRowCollection = function (index, isMovable, isRowObject, isFrozenRight) {
var startIdx = parseInt(this.parent.getRows()[0].getAttribute(literals.ariaRowIndex), 10) - 1;
var rowCollection = this.parent.getDataRows();
var collection = isRowObject ? this.parent.getCurrentViewRecords() : rowCollection;
var selectedRow = collection[index - startIdx];
if (this.parent.frozenRows && this.parent.pageSettings.currentPage > 1) {
if (!isRowObject) {
selectedRow = index <= this.parent.frozenRows ? rowCollection[parseInt(index.toString(), 10)]
: rowCollection[(index - startIdx) + this.parent.frozenRows];
}
else {
selectedRow = index <= this.parent.frozenRows ?
this.parent.getRowsObject()[parseInt(index.toString(), 10)].data : selectedRow;
}
}
if (selectedRow == null && index != null && this.parent.editSettings.mode === 'Batch' && this.parent.isEdit && isMovable) {
selectedRow = rowCollection[parseInt(index.toString(), 10)];
}
return selectedRow;
};
/**
* @hidden
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.addEventListener = function () {
this.parent.on(events.virtualActionArgs, this.virtualOtherAction, this);
this.parent.on(events.indexModifier, this.indexModifier, this);
};
/**
* Handles virtual scrolling actions based on the provided arguments.
*
* @param {Object} args - The argument object.
* @param {boolean} args.setTop - Determines if the virtual scroll position should reset to top.
* @param {boolean} args.isExpandCollapse - Determines if the action is part of an expand/collapse operation.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.virtualOtherAction = function (args) {
if (args.setTop) {
this.translateY = 0;
this.startIndex = 0;
this.endIndex = this.parent.pageSettings.pageSize - 1;
}
else if (args.isExpandCollapse) {
this.isExpandCollapse = true;
}
};
/**
* Modifies the index based on various conditions such as record addition, deletion, or data source changes.
*
* @private
* @param {Object} args - Contains parameters for the current operation.
* @param {number} args.startIndex - The starting index for the modification.
* @param {number} args.endIndex - The ending index for the modification.
* @param {number} args.count - The number of items affected in the operation.
* @param {string} args.requestType - The type of request, such as 'insert', 'delete', or 'update'.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.indexModifier = function (args) {
var content = this.parent.getContent().querySelector('.e-content');
var pageSize = this.parent.pageSettings.pageSize;
if ((this.recordAdded || args.requestType === 'delete' && this.endIndex > args.count - this.parent.pageSettings.pageSize) && this.startIndex > -1 && this.endIndex > -1) {
if (this.endIndex > args.count - pageSize) {
var nextSetResIndex = ~~(content.scrollTop / this.parent.getRowHeight());
var lastIndex = nextSetResIndex + this.parent.getRows().length;
if (lastIndex > args.count) {
lastIndex = nextSetResIndex +
(args.count - nextSetResIndex);
}
this.startIndex = lastIndex - this.parent.getRows().length;
this.endIndex = lastIndex;
}
else if (this.parent.root.editSettings.newRowPosition !== 'Top' && this.parent.root.editModule.selectedIndex !== -1 || this.parent.root.editModule.selectedIndex !== -1) {
this.startIndex += 1;
this.endIndex += 1;
}
this.recordAdded = false;
}
if (this.isDataSourceChanged) {
this.startIndex = 0;
this.endIndex = pageSize - 1;
}
if ((this.endIndex - this.startIndex !== pageSize) &&
(this.totalRecords > pageSize)
&& (this.endIndex === this.totalRecords)) {
args.startIndex = this.endIndex - pageSize;
args.endIndex = this.endIndex;
}
else {
args.startIndex = this.startIndex;
args.endIndex = this.endIndex;
}
};
/**
* Handles the addition or removal of event listeners for virtual scrolling in a TreeGrid.
*
* @param {string} action - The action to perform, either 'on' or 'off'.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.eventListener = function (action) {
var _this = this;
if (!(this.parent.dataSource instanceof DataManager && this.parent.dataSource.dataSource.url !== undefined
&& this.parent.dataSource.dataSource.offline && this.parent.dataSource.dataSource.url !== '') || !isCountRequired(this.parent)) {
this.parent["" + action]('data-ready', this.onDataReady, this);
this.parent["" + action]('refresh-virtual-block', this.refreshContentRows, this);
this.fn = function () {
_this.observers.observes(function (scrollArgs) { return _this.scrollListeners(scrollArgs); }, _this.onEnteredAction(), _this.parent);
var gObj = _this.parent;
if (gObj.root.enablePersistence && gObj.root.scrollPosition) {
_this.content.scrollTop = gObj.root.scrollPosition.top;
if (gObj.root.enableColumnVirtualization) {
_this.content.scrollLeft = gObj.root.scrollPosition.left;
}
var scrollValues = {
direction: 'down', sentinel: _this.observer.sentinelInfo.down,
offset: gObj.root.scrollPosition, focusElement: gObj.element
};
_this.scrollListeners(scrollValues);
}
_this.parent.off('content-ready', _this.fn);
};
this.parent.addEventListener('dataBound', this.dataBoundEvent.bind(this));
this.parent.addEventListener('rowSelected', this.rowSelectedEvent.bind(this));
this.parent["" + action]('select-virtual-Row', this.toSelectVirtualRow, this);
this.parent.on('content-ready', this.fn, this);
this.parent.addEventListener(events.actionBegin, this.handleActionBegin.bind(this));
this.parent.addEventListener(events.actionComplete, this.onActionComplete.bind(this));
this.parent["" + action]('virtual-scroll-edit-action-begin', this.beginEdit, this);
this.parent["" + action]('virtual-scroll-add-action-begin', this.beginAdd, this);
this.parent["" + action]('virtual-scroll-edit-success', this.virtualEditSuccess, this);
this.parent["" + action]('edit-reset', this.resetIseditValue, this);
this.parent["" + action]('get-virtual-data', this.getData, this);
this.parent["" + action]('virtual-scroll-edit-cancel', this.cancelEdit, this);
this.parent["" + action]('select-row-on-context-open', this.toSelectRowOnContextOpen, this);
this.parent["" + action]('refresh-virtual-editform-cells', this.refreshCell, this);
this.parent["" + action]('virtaul-cell-focus', this.cellFocus, this);
this.parent["" + action]('virtual-scroll-edit', this.restoreEditState, this);
this.parent["" + action]('set-virtual-page-query', this.SetVirtualPageQury, this);
}
else {
_super.prototype.eventListener.call(this, 'on');
}
};
/**
* Handles cell focus transitions in a virtualized tree grid component
* when a keyboard event is triggered.
*
* @param {KeyboardEventArgs} e - The keyboard event arguments that contain
* information about the key action.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.cellFocus = function (e) {
var virtualCellFocus = 'virtualCellFocus';
_super.prototype["" + virtualCellFocus].call(this, e);
};
/**
* Handles the data ready event for the virtual tree grid content renderer.
*
* @param {NotifyArgs} [e] - The notification arguments that contain information about the data.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.onDataReady = function (e) {
_super.prototype.onDataReady.call(this, e);
if (!(this.parent.dataSource instanceof DataManager && this.parent.dataSource.dataSource.url !== undefined
&& this.parent.dataSource.dataSource.offline && this.parent.dataSource.dataSource.url !== '') || !isCountRequired(this.parent)) {
if (!isNullOrUndefined(e.count)) {
this.totalRecords = e.count;
// To overcome the white space issue in last page when records collapsed
if (this.parent.isFrozenGrid() && e.count < Object.keys(this.parent.dataSource).length) {
var width = this.parent.enableColumnVirtualization ?
this.getColumnOffset(this.parent.columns.length - 1) + 'px' : '100%';
var height = (this.parent.getRowHeight() * e.count) -
(this.parent.getRowHeight() * this.parent.pageSettings.pageSize);
getValue('virtualEle', this).setVirtualHeight(height, width);
}
if (!this.parent.enableColumnVirtualization && !this.parent.isFrozenGrid()) {
getValue('virtualEle', this).setVirtualHeight(this.parent.getRowHeight() * e.count, '100%');
}
}
if ((!isNullOrUndefined(e.requestType) && e.requestType.toString() === 'collapseAll') || (this.isDataSourceChanged && (this.startIndex === -1 || this.startIndex === 0 && this['preStartIndex'] === 0))) {
this.contents.scrollTop = 0;
this.isDataSourceChanged = false;
}
}
};
/**
* Renders the table for the virtual tree content. It sets up a new `TreeInterSectionObserver`
* based on certain conditions regarding the data source and counting requirements.
*
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.renderTable = function () {
_super.prototype.renderTable.call(this);
if (!(this.parent.dataSource instanceof DataManager && this.parent.dataSource.dataSource.url !== undefined
&& this.parent.dataSource.dataSource.offline && this.parent.dataSource.dataSource.url !== '') || !isCountRequired(this.parent)) {
getValue('observer', this).options.debounceEvent = false;
this.observers = new TreeInterSectionObserver(getValue('observer', this).element, getValue('observer', this).options);
this.contents = this.getPanel().firstChild;
}
};
/**
* Calculates the translateY value for a virtual tree grid based on the scroll top, container height,
* and additional virtual scrolling information. This method specifically handles logic for remote
* data sources and ensures smooth scrolling with respect to expansion states.
*
* @param {number} sTop - The scroll top position.
* @param {number} cHeight - The height of the container.
* @param {VirtualInfo} [info] - Optional virtual scrolling information.
* @param {boolean} [isOnenter] - Flag indicating if the scroll event is on enter.
* @returns {number} The calculated translateY value.
*/
VirtualTreeContentRenderer.prototype.getTranslateY = function (sTop, cHeight, info, isOnenter) {
if ((this.parent.dataSource instanceof DataManager && this.parent.dataSource.dataSource.url !== undefined
&& !this.parent.dataSource.dataSource.offline && this.parent.dataSource.dataSource.url !== '') || isCountRequired(this.parent)) {
if (this.isRemoteExpand) {
this.isRemoteExpand = false;
return this.preTranslate;
}
this.preTranslate = _super.prototype.getTranslateY.call(this, sTop, cHeight, info, isOnenter);
}
return _super.prototype.getTranslateY.call(this, sTop, cHeight, info, isOnenter);
};
/**
* Handles the dataBound event to calculate and set the initial row top position for the grid.
*
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.dataBoundEvent = function () {
var dataBoundEve = 'dataBound';
var initialRowTop = 'initialRowTop';
if (!isNullOrUndefined(this.parent.getRows()) && this.parent.getRows().length && !isNullOrUndefined(this.parent.getRowByIndex(0)) && !this["" + initialRowTop]) {
var rowTop = this.parent.getRowByIndex(0).getBoundingClientRect().top;
var gridTop = this.parent.element.getBoundingClientRect().top;
if (rowTop > 0) {
this["" + initialRowTop] = this.parent.getRowByIndex(0).getBoundingClientRect().top - gridTop;
}
else if (this.parent.selectedRowIndex === -1) {
this["" + initialRowTop] = this.content.getBoundingClientRect().top -
this.parent.getRowByIndex(0).getBoundingClientRect().height;
}
}
_super.prototype["" + dataBoundEve].call(this);
};
/**
* Handles the row selection event for virtual tree grid rows.
* It invokes the base class's rowSelected method and notifies
* the parent component about a virtual transformation change.
*
* @param {RowSelectEventArgs} args - The arguments related to the row selection event.
* @returns {void} This method does not return a value.
*/
VirtualTreeContentRenderer.prototype.rowSelectedEvent = function (args) {
var rowSelected = 'rowSelected';
_super.prototype["" + rowSelected].call(this, args);
this.parent.notify('virtualTransform', { requestType: 'transformChange' });
};
/**
* Handles virtual row selection in TreeGrid.
*
* @param {Object} args - The argument object containing the selected index.
* @param {number} args.selectedIndex - The index of the row to be selected.
*
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.toSelectVirtualRow = function (args) {
if (this.parent.isEdit) {
return;
}
var selectVirtualRow = 'selectVirtualRow';
var containerRect = 'containerRect';
if (isNullOrUndefined(this.observer["" + containerRect])) {
this.observer["" + containerRect] = this.observers["" + containerRect];
}
var treeGridParent = this.parent.clipboardModule['treeGridParent'];
if (isNullOrUndefined(treeGridParent.editModule) ||
isNullOrUndefined(treeGridParent.editModule['addRowIndex']) || args.selectedIndex !== 0) {
if (!isNullOrUndefined(treeGridParent.grid.sortModule) && treeGridParent.grid.sortModule['sortedColumns'].length > 0) {
var sortedData = treeGridParent.dataModule['sortedData'];
if (!isNullOrUndefined(sortedData) && sortedData.length > 0) {
var targetIndex = sortedData.findIndex(function (record) { return record.index === args.selectedIndex; });
args.selectedIndex = targetIndex;
}
}
_super.prototype["" + selectVirtualRow].call(this, args);
}
};
/**
* Refreshes the cells for the given row object by regenerating them.
*
* @param {Row<Column>} rowObj - The row object for which the cells need to be refreshed.
* @returns {void} This method does not return any value.
*/
VirtualTreeContentRenderer.prototype.refreshCell = function (rowObj) {
rowObj.cells = this.generateCells();
};
/**
* Generates an array of cells for each column in the parent.
*
* @returns {Cell<Column>[]} An array of cells for the corresponding columns.
*/
VirtualTreeContentRenderer.prototype.generateCells = function () {
var cells = [];
for (var i = 0; i < this.parent.columns.length; i++) {
cells.push(this.generateCell(this.parent.columns[parseInt(i.toString(), 10)]));
}
return cells;
};
/**
* Generates a cell object with provided column and row configurations.
*
* @param {Column} col - The Column object which holds the column configuration.
* @param {string} [rowId] - An optional string that represents the row ID.
* @param {CellType} [cellType] - An optional CellType enum to specify the type of the cell.
* @param {number} [colSpan] - An optional number to specify the column span of the cell.
* @param {number} [oIndex] - An optional number for the order index of the cell.
* @param {Object} [foreignKeyData] - An optional object for foreign key data associated with the column.
*
* @returns {Cell<Column>} Returns a newly created Cell object of type Column.
*/
VirtualTreeContentRenderer.prototype.generateCell = function (col, rowId, cellType, colSpan, oIndex, foreignKeyData) {
var opt = {
'visible': col.visible,
'isDataCell': !isNullOrUndefined(col.field || col.template),
'isTemplate': !isNullOrUndefined(col.template),
'rowID': rowId,
'column': col,
'cellType': !isNullOrUndefined(cellType) ? cellType : CellType.Data,
'colSpan': colSpan,
'commands': col.commands,
'isForeignKey': col.isForeignColumn && col.isForeignColumn(),
'foreignKeyData': col.isForeignColumn && col.isForeignColumn() && getValue(col.field, foreignKeyData)
};
if (opt.isDataCell || opt.column.type === 'checkbox' || opt.commands) {
opt.index = oIndex;
}
return new Cell(opt);
};
/**
* Begins the edit operation for a specified row in the grid.
* Updates the `editedRowIndex` and assigns row data to the event data.
*
* @param {{ data: Object, index: number }} e - An object containing the row data and index.
* @param {Object} e.data - The data of the row to be edited.
* @param {number} e.index - The index of the row to be edited.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.beginEdit = function (e) {
this['editedRowIndex'] = e.index;
var selector = '.e-row[aria-rowindex="' + (e.index + 1) + '"]';
var index = this.parent.getContent().querySelector(selector).rowIndex;
var rowData = this.parent.getCurrentViewRecords()[parseInt(index.toString(), 10)];
e.data = rowData;
};
/**
* Begins the process of adding a new row in the tree grid.
*
* @param {Object} args - The arguments for adding a new row.
* @param {boolean} args.startEdit - A flag indicating whether to start editing.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.beginAdd = function (args) {
var addAction = 'addActionBegin';
var isAdd = 'isAdd';
var addArgs = { newRowPosition: this.rowPosition, addRowIndex: this.addRowIndex, dataRowIndex: this.dataRowIndex };
this.parent.notify('get-row-position', addArgs);
this.rowPosition = addArgs.newRowPosition;
this.addRowIndex = addArgs.addRowIndex;
this.dataRowIndex = addArgs.dataRowIndex;
var rows = this.parent.getRows();
var firstAriaIndex = rows.length ? +rows[0].getAttribute('aria-rowindex') - 1 : 0;
var lastAriaIndex = rows.length ? +rows[rows.length - 1].getAttribute('aria-rowindex') - 1 : 0;
var withInRange = this.parent.selectedRowIndex >= firstAriaIndex && this.parent.selectedRowIndex <= lastAriaIndex;
if (!(this.rowPosition === 'Top' || this.rowPosition === 'Bottom')) {
this["" + isAdd] = true;
}
if (this.rowPosition === 'Top' || this.rowPosition === 'Bottom' ||
((!this.addRowIndex || this.addRowIndex === -1) && (this.parent.selectedRowIndex === -1 || !withInRange))) {
_super.prototype["" + addAction].call(this, args);
}
};
/**
* Restores the edit state of the tree grid content. This method calls the
* base class method to handle the restoration logic.
*
* @returns {void} This method does not return any value.
*/
VirtualTreeContentRenderer.prototype.restoreEditState = function () {
var restoreEdit = 'restoreEdit';
_super.prototype["" + restoreEdit].call(this);
};
VirtualTreeContentRenderer.prototype.SetVirtualPageQury = function (args) {
var visiblePage = [];
if (this.prevInfo && this.prevInfo.blockIndexes) {
visiblePage = getVisiblePage(this.prevInfo.blockIndexes);
}
if ((this.requestType === 'refresh') && visiblePage.length) {
args.query.skip(this.parent.pageSettings.pageSize * (visiblePage[0] - 1));
args.query.take(this.parent.pageSettings.pageSize * visiblePage.length);
args.skipPage = true;
return;
}
};
/**
* Resets the edit state if certain conditions are met.
*
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.resetIseditValue = function () {
var resetIsEdit = 'resetIsedit';
var isAdd = 'isAdd';
this.parent.notify('reset-edit-props', {});
if ((this.rowPosition === 'Top' || this.rowPosition === 'Bottom') && this["" + isAdd]) {
_super.prototype["" + resetIsEdit].call(this);
}
};
/**
* Handles the successful editing operation when virtual scrolling is enabled.
* Checks if a row has been added to the tree grid and sets the `recordAdded` flag accordingly.
*
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.virtualEditSuccess = function () {
var isAdd = 'isAdd';
var content = this.parent.getContent().querySelector('.e-content');
if (this["" + isAdd] && content.querySelector('.e-addedrow')) {
this.recordAdded = true;
}
};
/**
* Cancels the edit operation for the provided data.
*
* @param {Object} args - The arguments containing the data to cancel edit for.
* @param {Object} args.data - The specific data object for which the edit operation needs to be canceled.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.cancelEdit = function (args) {
var editCancel = 'editCancel';
_super.prototype["" + editCancel].call(this, args);
};
/**
* Handles the action of selecting a row when the context menu is opened.
*
* @param {Object} args - An object containing related parameters.
* @param {boolean} args.isOpen - A flag indicating whether the context menu is open.
* @returns {void} This method does not return any value.
*/
VirtualTreeContentRenderer.prototype.toSelectRowOnContextOpen = function (args) {
var selectRowOnContextOpen = 'selectRowOnContextOpen';
_super.prototype["" + selectRowOnContextOpen].call(this, args);
};
/**
* Restores a new row in the grid when necessary by adding it back to the content.
*
* @returns {void} This method does not return any value.
*/
VirtualTreeContentRenderer.prototype.restoreNewRow = function () {
var isAdd = 'isAdd';
var content = this.parent.getContent().querySelector('.e-content');
if (this["" + isAdd] && !content.querySelector('.e-addedrow')) {
this.parent.isEdit = false;
this.parent.editModule.addRecord(null, this.parent.root.editModule.selectedIndex);
}
};
/**
* Retrieves virtual data for operations like adding or canceling rows in the grid.
*
* @param {Object} data - An object containing properties to determine the virtual data processing.
* @param {Object} data.virtualData - The virtual data object to be processed.
* @param {boolean} data.isAdd - A boolean indicating if the operation is an addition.
* @param {boolean} data.isCancel - A boolean indicating if the operation is a cancellation.
* @returns {void} This method does not return any value.
*/
VirtualTreeContentRenderer.prototype.getData = function (data) {
var getVirtualData = 'getVirtualData';
_super.prototype["" + getVirtualData].call(this, data);
};
/**
* Initiates the beginning of an action within the tree grid component.
* This method is invoked before any action is performed, allowing for
* any necessary modifications or cancellations of the upcoming action.
*
* @param {NotifyArgs} args - The arguments associated with the action,
* providing context and specifics about what is being commenced.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.handleActionBegin = function (args) {
var actionBegin = 'actionBegin';
_super.prototype["" + actionBegin].call(this, args);
};
/**
* Handles the completion of various actions, such as adding a new row.
* Updates row positions and indexes based on the action completed.
*
* @param {NotifyArgs} args - An object containing the details of the completed action.
* Specifically, it includes the `requestType` which determines the type
* of action that was completed.
* @returns {void} This method does not return any value.
*/
VirtualTreeContentRenderer.prototype.onActionComplete = function (args) {
if (args.requestType === 'add') {
var addArgs = { newRowPosition: this.rowPosition, addRowIndex: this.addRowIndex, dataRowIndex: this.dataRowIndex };
this.parent.notify('get-row-position', addArgs);
this.rowPosition = addArgs.newRowPosition;
this.addRowIndex = addArgs.addRowIndex;
this.dataRowIndex = this.parent.root.editModule.selectedIndex;
}
var actionComplete = 'actionComplete';
_super.prototype["" + actionComplete].call(this, args);
};
/**
* Creates a callback function to be executed during virtual scrolling actions.
* This function handles the adjustment of virtual elements and rendering logic,
* particularly optimizing for non-IE browsers, wheel events, and virtual masks.
*
* @returns {Function} A function that handles scrolling and adjusts table rendering.
* @param {HTMLElement} element - The HTML element involved in the action.
* @param {SentinelType} current - The type of sentinel indicating the scroll.
* @param {string} direction - The scroll direction.
* @param {Offsets} e - The offset values indicating the current scroll position.
* @param {boolean} isWheel - Indicates if the scrolling was initiated by a mouse wheel.
* @param {boolean} check - A boolean flag for additional control logic.
*/
VirtualTreeContentRenderer.prototype.onEnteredAction = function () {
var _this = this;
return function (element, current, direction, e, isWheel, check) {
var directVirtualRender = 'directVirtualRender';
if (!_this.parent["" + directVirtualRender]) { // with this property, columns are rendered without debouncing on horizontal scroll.
var preventEvent = 'preventEvent';
if (Browser.isIE && !isWheel && check && !_this["" + preventEvent] && !_this.parent.enableVirtualMaskRow) {
_this.parent.showSpinner();
}
if (_this.parent.enableVirtualMaskRow && !_this["" + preventEvent]) {
setTimeout(function () {
_this.parent.showMaskRow(current.axis);
_this.parent.notify('showGanttShimmer', { requestType: 'showShimmer' });
}, 0);
}
var height = _this.content.getBoundingClientRect().height;
var top_1 = _this.prevInfo.offsets ? _this.prevInfo.offsets.top : null;
var xAxis = current.axis === 'X';
var x = _this.getColumnOffset(xAxis ? _this.vgenerator.getColumnIndexes()[0] - 1 : _this.prevInfo.columnIndexes[0]
- 1);
if (_this.parent.isFrozenGrid() && _this.parent.enableColumnVirtualization && _this.currentInfo &&
_this.currentInfo.columnIndexes) {
var cBlock = _this.currentInfo.columnIndexes[0] - 1;
var frzLeftWidth_1 = 0;
_this.parent.getColumns().filter(function (col) {
if (col.visible && col.freeze === 'Left') {
frzLeftWidth_1 += parseInt(col.width.toString(), 10);
}
});
if (cBlock > _this.parent.getVisibleFrozenLeftCount()) {
x = x - frzLeftWidth_1;
}
}
if (xAxis) {
var idx = Object.keys(_this.vgenerator.cOffsets).length - _this.prevInfo.columnIndexes.length;
var maxLeft = _this.vgenerator.cOffsets[idx - 1];
x = x > maxLeft ? maxLeft : x; //TODO: This fix horizontal scrollbar jumping issue in column virtualization.
}
var y = _this.getTranslateY(e.top, height, xAxis && top_1 === e.top ? _this.prevInfo : undefined, true);
if (!_this.parent.isFrozenGrid() || _this.parent.enableVirtualMaskRow) {
if (_this.parent.enableVirtualMaskRow) {
var upScroll = (e.top - _this.translateY) < 0;
y = (Math.round(_this.translateY) > y && !upScroll) ? Math.round(_this.translateY) : y;
_this.virtualEle.adjustTable(x, y);
}
else {
_this.virtualEle.adjustTable(x, _this.translateY);
}
if (_this.parent.enableColumnVirtualization) {
_this.header.virtualEle.adjustTable(x, 0);
if (_this.parent.isFrozenGrid()) {
_this.parent.contentModule['resetStickyLeftPos'](x);
}
}
}
}
};
};
/**
* Handles scroll events to manage virtual scrolling and row rendering.
* Adjusts view information, row indexes, and translates viewport positioning
* based on the given scroll arguments.
*
* @param {ScrollArg} scrollArgs - Contains the scroll offsets, sentinel information, direction of scroll, and other related details.
* @returns {void} - No return value. It adjusts scrolling state internally.
*/
VirtualTreeContentRenderer.prototype.scrollListeners = function (scrollArgs) {
this['scrollAfterEdit']();
this.shouldPreventScrolling(scrollArgs);
if (this.parent.root.enablePersistence) {
this.parent.root.scrollPosition = scrollArgs.offset;
}
var info = scrollArgs.sentinel;
var rowHeight = this.parent.getRowHeight();
var outBuffer = this.parent.pageSettings.pageSize - Math.ceil(this.parent.pageSettings.pageSize / 2);
var content;
if (!isNullOrUndefined(this.parent.contentModule)) {
content = this.parent.getContent().querySelector('.e-content');
}
var scrollHeight = outBuffer * rowHeight;
var upScroll = (scrollArgs.offset.top - this.translateY) < 0 && this.activeKey !== 'downArrow';
var downScroll = Math.ceil(scrollArgs.offset.top - this.translateY) + rowHeight >= scrollHeight;
var selectedRowIndex = 'selectedRowIndex';
var currentViewData = this.parent.currentViewData;
var indexValue = 'index';
if (upScroll && (scrollArgs.direction !== 'right' && scrollArgs.direction !== 'left') && !isNullOrUndefined(content)) {
var vHeight = +(this.parent.height.toString().indexOf('%') < 0 ? parseInt(this.parent.height.toString(), 10) :
this.parent.element.getBoundingClientRect().height);
// Calculate the integer number of rows that are scrolled past plus the number of rows that fit within the visible height
var scrolledRows = Math.floor(content.scrollTop / rowHeight);
var visibleRows = Math.ceil(vHeight / rowHeight);
// Calculate the index by subtracting the page size from the total rows taken into account
var index = scrolledRows + visibleRows - this.parent.pageSettings.pageSize;
index = (index > 0) ? index : 0;
if (!isNullOrUndefined(this["" + selectedRowIndex]) && this["" + selectedRowIndex] !== -1 && index !== this["" + selectedRowIndex] &&
((this.parent.rowHeight * this.parent.pageSettings.pageSize) < content.scrollTop) && !this.parent.allowRowDragAndDrop) {
index = this["" + selectedRowIndex];
}
this.startIndex = index;
this.endIndex = index + this.parent.pageSettings.pageSize;
if (this.endIndex > this.totalRecords) {
var lastInx = this.totalRecords;
var remains = this.endIndex % lastInx;
this.endIndex = lastInx;
this.startIndex = (this.startIndex - remains) < 0 ? 0 : (this.startIndex - remains);
}
if (currentViewData.length && (currentViewData[0]["" + indexValue] >= this.parent.pageSettings.pageSize / 2) &&
((currentViewData[0]["" + indexValue] - this.startIndex) < (this.parent.pageSettings.pageSize / 2)) &&
this.parent.selectionModule && this.parent.selectionModule.isRowSelected) {
this.startIndex = currentViewData[0]["" + indexValue] - (this.parent.pageSettings.pageSize / 2);
this.endIndex = this.startIndex + this.parent.pageSettings.pageSize;
}
//var firsttdinx = parseInt(this.parent.getContent().querySelector('.e-content td').getAttribute('index'), 0);
var rowPt = Math.ceil(scrollArgs.offset.top / rowHeight);
rowPt = rowPt % this.parent.pageSettings.pageSize;
var firsttdinx = 0;
if (!isNullOrUndefined(this.parent.getRows()[parseInt(rowPt.toString(), 10)]) &&
!isNullOrUndefined(this.parent.getContent().querySelectorAll('.e-content tr')[parseInt(rowPt.toString(), 10)])) {
var attr = this.parent.getContent().querySelectorAll('.e-content tr')[parseInt(rowPt.toString(), 10)]
.querySelector('td').getAttribute('index');
firsttdinx = +attr; // this.parent.getContent().querySelector('.e-content tr').getAttribute('data-rowindex');
}
if (firsttdinx === 0) {
if (this.endIndex - this.startIndex < this.parent.pageSettings.pageSize) {
this.translateY = !isNullOrUndefined(this.endIndex) ?
(this.endIndex - this.parent.pageSettings.pageSize) * (this.parent.rowHeight ?
this.parent.rowHeight : this.parent.getRowHeight()) : 0;
}
else if (this.startIndex === this["" + selectedRowIndex]) {
this.translateY = scrollArgs.offset.top;
}
else {
this.translateY = (scrollArgs.offset.top - (outBuffer * rowHeight) > 0) ?
scrollArgs.offset.top - (outBuffer * rowHeight) + rowHeight : 0;
}
}
else if (this.parent.getFrozenColumns() > 0) {
scrollArgs.offset.top = scrollArgs.offset.top + 80;
this.translateY = (scrollArgs.offset.top - (outBuffer * rowHeight) > 0) ?
scrollArgs.offset.top - (outBuffer * rowHeight) + 10 : 0;
}
else {
this.translateY = (scrollArgs.offset.top - (outBuffer * rowHeight) > 0) ?
scrollArgs.offset.top - (outBuffer * rowHeight) + 10 : 0;
}
}
else if (downScroll && (scrollArgs.direction !== 'right' && scrollArgs.direction !== 'left') && !isNullOrUndefined(content)) {
var nextSetResIndex = ~~(content.scrollTop / rowHeight);
var isLastBlock = (this["" + selectedRowIndex] + this.parent.pageSettings.pageSize) < this.totalRecords ? false : true;
if (!isNullOrUndefined(this["" + selectedRowIndex]) && this["" + selectedRowIndex] !== -1 &&
nextSetResIndex !== this["" + selectedRowIndex] && !isLastBlock && !this.parent.allowRowDragAndDrop) {
nextSetResIndex = this["" + selectedRowIndex];
}
var lastIndex = nextSetResIndex + this.parent.pageSettings.pageSize;
if (lastIndex > this.totalRecords) {
lastIndex = nextSetResIndex +
(this.totalRecords - nextSetResIndex);
}
this.startIndex = !isLastBlock || isNullOrUndefined(this['' + selectedRowIndex]) ? lastIndex - this.parent.pageSettings.pageSize : nextSetResIndex;
this.endIndex = lastIndex;
if ((nextSetResIndex + this.parent.pageSettings.pageSize) > this.totalRecords && (this.endIndex - this.startIndex) <
(this.parent.pageSettings.pageSize / 2) && (this.endIndex - nextSetResIndex) < (this.parent.pageSettings.pageSize / 2)) {
this.startIndex = lastIndex - (this.parent.pageSettings.pageSize / 2);
}
if (currentViewData.length && this.startIndex > currentViewData[0]["" + indexValue] &&
((this.startIndex - currentViewData[0]["" + indexValue]) < (this.parent.pageSettings.pageSize / 2)) &&
this.parent.selectionModule && this.parent.selectionModule.isRowSelected) {
this.startIndex = currentViewData[0]["" + indexValue] + (this.parent.pageSettings.pageSize / 2);
}
if (scrollArgs.offset.top > (rowHeight * this.totalRecords)) {
this.translateY = this.getTranslateY(scrollArgs.offset.top, content.getBoundingClientRect().height);
}
else {
if (this.totalRecords === this.endIndex) {
if (this.totalRecords === this.endIndex) {
if (this.parent.isEdit) {
this.translateY = ((this.totalRecords * rowHeight) - (this.parent.pageSettings.pageSize * rowHeight))
+ rowHeight;
}
else {
this.translateY = (this.totalRecords * rowHeight) - (this.parent.pageSettings.pageSize * rowHeight);
}
}
}
else {
if (this.parent.getFrozenColumns() > 0) {
this.translateY = scrollArgs.offset.top - ((rowHeight * 2) + this.parent.pageSettings.pageSize);
}
else {
this.translateY = scrollArgs.offset.top;
}
}
}
}
if (((downScroll && scrollArgs.direction !== 'up' && (scrollArgs.offset.top < (rowHeight * this.totalRecords)))
|| (upScroll)) || (scrollArgs.direction === 'right' || scrollArgs.direction === 'left') ||
((this.parent.dataSource instanceof DataManager && this.parent.dataSource.dataSource.url !== undefined
&& !this.parent.dataSource.dataSource.offline && this.parent.dataSource.dataSource.url !== ''))) {
var viewInfo = this.currentInfo = getValue('getInfoFromView', this).apply(this, [scrollArgs.direction, info, scrollArgs.offset]);
this.previousInfo = viewInfo;
if (this.prevInfo && ((info.axis === 'Y' && this.prevInfo.blockIndexes.toString() === viewInfo.blockIndexes.toString())
|| ((info.axis === 'X' && this.prevInfo.columnIndexes.toString() === viewInfo.columnIndexes.toString())
|| (this.parent.isFrozenGrid() && this.parent.getVisibleFrozenLeftCount() >= viewInfo.columnIndexes[0]
&& this.prevInfo.columnIndexes.toString().includes(viewInfo.columnIndexes.toString()))))) {
this.parent.removeMaskRow();
this.parent.notify('removeGanttShimmer', { requestType: 'hideShimmer' });
if (Browser.isIE) {
this.parent.hideSpinner();
}
this.requestType = this.requestType === 'virtualscroll' ? this['empty'] : this.requestType;
if (info.axis === 'Y') {
this.restoreEditState();
}
return;
}
this.parent.setColumnIndexesInView(this.parent.enableColumnVirtualization ? viewInfo.columnIndexes : []);
var page = viewInfo.loadNext && !viewInfo.loadSelf ? viewInfo.nextInfo.page : viewInfo.page;
this.parent.setProperties({ pageSettings: { currentPage: page } }, true);
if (downScroll && this.endIndex === this.totalRecords && viewInfo.loadNext) {
viewInfo.loadNext = false;
}
this.requestType = 'virtualscroll';
if (scrollArgs.direction !== 'right' && scrollArgs.direction !== 'left' && !isRemoteData(this.parent.root)) {
viewInfo.event = viewInfo.event === 'refresh-virtual-block' ? 'model-changed' : viewInfo.event;
}
if (this.parent.enableVirtualMaskRow) {
this.parent.showMaskRow(info.axis);
this.parent.addShimmerEffect();
this.parent.notify('showGanttShimmer', { requestType: 'showShimmer' });
}
this.parent.notify(viewInfo.event, { requestType: 'virtualscroll', virtualInfo: viewInfo, focusElement: scrollArgs.focusElement });
}
else {
if (this.parent.enableVirtualMaskRow) {
this.parent.removeMaskRow();
this.parent.notify('removeGanttShimmer', { requestType: 'hideShimmer' });
}
}
};
/**
* Prevents scrolling under specific conditions related to adding a new row.
*
* @param {ScrollArg} scrollArgs - The scroll event arguments containing offset details.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.shouldPreventScrolling = function (scrollArgs) {
var addedRow = this.parent.element.querySelector('.e-addedrow');
if (addedRow && this.rowPosition !== 'Top' && this.rowPosition !== 'Bottom' && scrollArgs.offset.top !== 0) {
this.parent.closeEdit();
return;
}
};
/**
* Appends content to the target element. Handles dynamic adjustments for remote data sources,
* frozen columns, and virtual scrolling.
*
* @param {HTMLElement} target - The target HTML element where content is to be appended.
* @param {DocumentFragment} newChild - The new content as a DocumentFragment to append.
* @param {NotifyArgs} e - Object containing information about the operation.
* @returns {void}
*/
VirtualTreeContentRenderer.prototype.appendContent = function (target, newChild, e) {
if ((this.parent.dataSource instanceof DataManager && this.parent.dataSource.dataSource.url !== undefined
&& !this.parent.dataSource.dataSource.offline && this.parent.dataSource.dataSource.url !== '') || isCountRequired(this.parent)
|| (this.parent.isFrozenGrid() && (e.requestType === undefined || !isNullOrUndefined(e.virtualInfo) && (e.virtualInfo.direction === 'right' || e.virtualInfo.direction === 'left')))) {
if (getValue('isExpandCollapse', e)) {
this.isRemoteExpand = true;
}
_super.prototype.appendContent.call(this, target, newChild, e);
if (getValue('requestTypes', this).indexOf('isFrozen') !== -1) {
getValue('requestTypes', this).splice(getValue('requestTypes', this).indexOf('isFrozen'), 1);
this.requestType = this.requestType === 'isFrozen' ? undefined : this.requestType;
}
}
else {
var info = e.virtualInfo.sentinelInfo && e.virtualInfo.sentinelInfo.axis === 'Y' &&
getValue('currentInfo', this).page && getValue('currentInfo', this).page !== e.virtualInfo.page ?
getValue('currentInfo', this) : e.virtualInfo;
var cBlock = (info.columnIndexes[0]) - 1;
var cOffset = this.getColumnOffset(cBlock);
var width = void 0;
if (this.parent.enableColumnVirtualization) {
this.header.virtualEle.adjustTable(cOffset, 0);
var cIndex = info.columnIndexes;
width = this.getColumnOffset(cIndex[cIndex.length - 1]) - this.getColumnOffset(cIndex[0] - 1) + '';
this.header.virtualEle.setWrapperWidth(width);
}
this.virtualEle.setWrapperWidth(width, (Browser.isIE || Browser.info.name === 'edge'));
target = this.parent.createElement('tbody');
target.appendChild(newChild);
var replace = 'replaceWith';
this.getTable().querySelector('tbody')["" + replace](target);
if (e.requestType === 'virtualscroll' && e.virtualInfo.sentinelInfo.axis === 'Y') {
thi