@syncfusion/ej2-treegrid
Version:
Essential JS 2 TreeGrid Component
1,176 lines (1,166 loc) • 725 kB
JavaScript
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';
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, RowRenderer } from '@syncfusion/ej2-grids';
import { createCheckBox } from '@syncfusion/ej2-buttons';
import { DataManager, ODataAdaptor, WebApiAdaptor, WebMethodAdaptor, CacheAdaptor, UrlAdaptor, Query, DataUtil, RemoteSaveAdaptor, Deferred, JsonAdaptor, Predicate as Predicate$1 } from '@syncfusion/ej2-data';
import { showSpinner, hideSpinner, createSpinner } from '@syncfusion/ej2-popups';
var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/**
* Represents the "Column" model class for TreeGrid, defining essential properties and functionalities of a column.
*/
class Column {
constructor(options) {
/**
* Allows or disallows editing of the column. Set to `false` to make a column non-editable.
* By default, all columns are editable.
*
* @default true
*/
this.allowEditing = true;
/**
* Customization options for the edit cell.
*
* @default {}
*/
this.edit = {};
/**
* When set to `true`, encodes HTML content in headers and cells to prevent HTML injection.
*
* @default true
*/
this.disableHtmlEncode = true;
/**
* Disables column reordering if set to `false`. By default, columns can be reordered.
*
* @default true
*/
this.allowReordering = true;
/**
* Disables column menu for the column if set to `false`. By default, column menus are enabled for all columns.
*
* @default true
*/
this.showColumnMenu = true;
/**
* Disables filtering for the column if set to `false`. By default, columns are filterable.
*
* @default true
*/
this.allowFiltering = true;
/**
* Disables sorting for the column if set to `false`. By default, columns are sortable.
*
* @default true
*/
this.allowSorting = true;
/**
* Disables resizing for the column if set to `false`. By default, columns can be resized.
*
* @default true
*/
this.allowResizing = true;
/**
* Customize default filter options for a specific column, providing types and UI definitions for custom components.
*
* @default null
*/
this.filter = {};
merge(this, options);
}
/**
* Reflects state changes for TreeGrid column directives, particularly in React.
*
* @param {Column} column - The column to update.
* @returns {void}
* @hidden
*/
setProperties(column) {
const keys = Object.keys(column);
for (let i = 0; i < keys.length; i++) {
this[keys[parseInt(i.toString(), 10)]] = column[keys[parseInt(i.toString(), 10)]];
if (this.parent && this.parent['isReact'] && keys[parseInt(i.toString(), 10)] === 'template') {
const refreshReactColumnTemplateByUid = 'refreshReactColumnTemplateByUid';
this.parent.clipboardModule['treeGridParent'].renderModule[`${refreshReactColumnTemplateByUid}`](this.uid);
}
}
}
}
/**
* Defines TreeGrid column
*/
class TreeGridColumn extends Column {
}
__decorate([
Property(null)
], TreeGridColumn.prototype, "columns", void 0);
/**
* Defines stacked tree grid column
*/
class StackedColumn extends TreeGridColumn {
}
var __decorate$1 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/**
* Configures the loading indicator for the Tree Grid, allowing you to display a visual indicator during data loading operations to enhance user experience.
*/
class LoadingIndicator extends ChildProperty {
}
__decorate$1([
Property('Spinner')
], LoadingIndicator.prototype, "indicatorType", void 0);
var __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/**
* Represents the filter configuration for a column in the TreeGrid.
*/
class Predicate extends ChildProperty {
}
__decorate$2([
Property()
], Predicate.prototype, "field", void 0);
__decorate$2([
Property()
], Predicate.prototype, "operator", void 0);
__decorate$2([
Property()
], Predicate.prototype, "value", void 0);
__decorate$2([
Property()
], Predicate.prototype, "matchCase", void 0);
__decorate$2([
Property()
], Predicate.prototype, "ignoreAccent", void 0);
__decorate$2([
Property()
], Predicate.prototype, "predicate", void 0);
__decorate$2([
Property({})
], Predicate.prototype, "actualFilterValue", void 0);
__decorate$2([
Property({})
], Predicate.prototype, "actualOperator", void 0);
__decorate$2([
Property()
], Predicate.prototype, "type", void 0);
__decorate$2([
Property()
], Predicate.prototype, "ejpredicate", void 0);
__decorate$2([
Property()
], Predicate.prototype, "uid", void 0);
__decorate$2([
Property()
], Predicate.prototype, "isForeignKey", void 0);
/**
* Configures the filtering behavior of the TreeGrid, enabling complex data filtering capabilities.
*/
class FilterSettings extends ChildProperty {
}
__decorate$2([
Collection([], Predicate)
], FilterSettings.prototype, "columns", void 0);
__decorate$2([
Property('FilterBar')
], FilterSettings.prototype, "type", void 0);
__decorate$2([
Property()
], FilterSettings.prototype, "mode", void 0);
__decorate$2([
Property(true)
], FilterSettings.prototype, "showFilterBarStatus", void 0);
__decorate$2([
Property(1500)
], FilterSettings.prototype, "immediateModeDelay", void 0);
__decorate$2([
Property()
], FilterSettings.prototype, "operators", void 0);
__decorate$2([
Property(false)
], FilterSettings.prototype, "ignoreAccent", void 0);
__decorate$2([
Property('Parent')
], FilterSettings.prototype, "hierarchyMode", void 0);
var __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/**
* Configures the text wrapping behavior of the TreeGrid.
*/
class TextWrapSettings extends ChildProperty {
}
__decorate$3([
Property('Both')
], TextWrapSettings.prototype, "wrapMode", void 0);
/**
* Logger module for TreeGrid
*
* @hidden
*/
const DOC_URL = 'https://ej2.syncfusion.com/documentation/treegrid';
const BASE_DOC_URL = 'https://ej2.syncfusion.com/documentation';
const ERROR = '[EJ2TreeGrid.Error]';
let IsRowDDEnabled = false;
class Logger extends Logger$1 {
constructor(parent) {
Grid.Inject(Logger$1);
super(parent);
}
/**
* For internal use only - Get the module name.
*
* @private
* @returns {string} - Returns Logger module name
*/
getModuleName() {
return 'logger';
}
log(types, args) {
if (!(types instanceof Array)) {
types = [types];
}
const type = types;
for (let i = 0; i < type.length; i++) {
const item = detailLists[type[parseInt(i.toString(), 10)]];
const cOp = item.check(args, this.parent);
if (cOp.success) {
let message = item.generateMessage(args, this.parent, cOp.options);
message = message.replace('EJ2Grid', 'EJ2TreeGrid').replace('* Hierarchy Grid', '').replace('* Grouping', '');
if (IsRowDDEnabled && type[parseInt(i.toString(), 10)] === 'primary_column_missing') {
message = message.replace('Editing', 'Row DragAndDrop');
IsRowDDEnabled = false;
}
const index = message.indexOf('https');
const gridurl = message.substring(index);
if (type[parseInt(i.toString(), 10)] === 'module_missing') {
message = message.replace(gridurl, DOC_URL + '/modules');
}
else if (type[parseInt(i.toString(), 10)] === 'primary_column_missing' || type[parseInt(i.toString(), 10)] === 'selection_key_missing') {
message = message.replace(gridurl, BASE_DOC_URL + '/api/treegrid/column/#isprimarykey');
}
else if (type[parseInt(i.toString(), 10)] === 'grid_remote_edit') {
message = message.replace(gridurl, DOC_URL + '/edit');
}
else if (type[parseInt(i.toString(), 10)] === 'virtual_height') {
message = message.replace(gridurl, DOC_URL + '/virtual');
}
else if (type[parseInt(i.toString(), 10)] === 'check_datasource_columns') {
message = message.replace(gridurl, DOC_URL + '/columns');
}
else if (type[parseInt(i.toString(), 10)] === 'locale_missing') {
message = message.replace(gridurl, DOC_URL + '/global-local/#localization');
}
if (type[parseInt(i.toString(), 10)] === 'datasource_syntax_mismatch') {
if (!isNullOrUndefined(this.treeGridObj) && !isNullOrUndefined(this.treeGridObj.dataStateChange)) {
// eslint-disable-next-line no-console
console[item.logType](message);
}
}
else {
// eslint-disable-next-line no-console
console[item.logType](message);
}
}
}
}
treeLog(types, args, treeGrid) {
this.treeGridObj = treeGrid;
if (!(types instanceof Array)) {
types = [types];
}
const type = types;
if (treeGrid.allowRowDragAndDrop && !treeGrid.columns.filter((column) => column.isPrimaryKey).length) {
IsRowDDEnabled = true;
this.log('primary_column_missing', args);
}
for (let i = 0; i < type.length; i++) {
const item = treeGridDetails[type[parseInt(i.toString(), 10)]];
const cOp = item.check(args, treeGrid);
if (cOp.success) {
const message = item.generateMessage(args, treeGrid, cOp.options);
// eslint-disable-next-line no-console
console[item.logType](message);
}
}
}
}
const treeGridDetails = {
// eslint-disable-next-line camelcase
mapping_fields_missing: {
type: 'mapping_fields_missing',
logType: 'error',
check(args, parent) {
let opt = { success: false };
if ((isNullOrUndefined(parent.idMapping) && isNullOrUndefined(parent.childMapping)
&& isNullOrUndefined(parent.parentIdMapping)) ||
(!isNullOrUndefined(parent.idMapping) && isNullOrUndefined(parent.parentIdMapping)) ||
(isNullOrUndefined(parent.idMapping) && !isNullOrUndefined(parent.parentIdMapping))) {
opt = { success: true };
}
return opt;
},
generateMessage() {
return ERROR + ':' + ' MAPPING FIELDS MISSING \n' + 'One of the following fields is missing. It is ' +
'required for the hierarchical relationship of records in TreeGrid:\n' +
'* childMapping\n' + '* idMapping\n' + '* parentIdMapping\n' +
'Refer to the following documentation links for more details.\n' +
`${BASE_DOC_URL}/api/treegrid#childmapping` + '\n' +
`${BASE_DOC_URL}/api/treegrid#idmapping` + '\n' +
`${BASE_DOC_URL}/api/treegrid#$parentidmapping`;
}
}
};
/**
* @hidden
*/
const load = 'load';
/** @hidden */
const rowDataBound = 'rowDataBound';
/** @hidden */
const dataBound = 'dataBound';
/** @hidden */
const queryCellInfo = 'queryCellInfo';
/** @hidden */
const beforeDataBound = 'beforeDataBound';
/** @hidden */
const actionBegin = 'actionBegin';
/** @hidden */
const dataStateChange = 'dataStateChange';
/** @hidden */
const actionComplete = 'actionComplete';
/** @hidden */
const rowSelecting = 'rowSelecting';
/** @hidden */
const rowSelected = 'rowSelected';
/** @hidden */
const checkboxChange = 'checkboxChange';
/** @hidden */
const rowDeselected = 'rowDeselected';
/** @hidden */
const toolbarClick = 'toolbarClick';
/** @hidden */
const beforeExcelExport = 'beforeExcelExport';
/** @hidden */
const beforePdfExport = 'beforePdfExport';
/** @hidden */
const resizeStop = 'resizeStop';
/** @hidden */
const expanded = 'expanded';
/** @hidden */
const expanding = 'expanding';
/** @hidden */
const collapsed = 'collapsed';
/** @hidden */
const collapsing = 'collapsing';
/** @hidden */
const remoteExpand = 'remoteExpand';
/** @hidden */
const localPagedExpandCollapse = 'localPagedExpandCollapse';
/** @hidden */
const pagingActions = 'pagingActions';
/** @hidden */
const printGridInit = 'printGrid-Init';
/** @hidden */
const contextMenuOpen = 'contextMenuOpen';
/** @hidden */
const contextMenuClick = 'contextMenuClick';
/** @hidden */
const beforeCopy = 'beforeCopy';
/** @hidden */
const beforePaste = 'beforePaste';
/** @hidden */
const savePreviousRowPosition = 'savePreviousRowPosition';
/** @hidden */
const crudAction = 'crudAction';
/** @hidden */
const beginEdit = 'beginEdit';
/** @hidden */
const beginAdd = 'beginAdd';
/** @hidden */
const recordDoubleClick = 'recordDoubleClick';
/** @hidden */
const cellSave = 'cellSave';
/** @hidden */
const cellSaved = 'cellSaved';
/** @hidden */
const cellEdit = 'cellEdit';
/** @hidden */
const batchDelete = 'batchDelete';
/** @hidden */
const batchCancel = 'batchCancel';
/** @hidden */
const batchAdd = 'batchAdd';
/** @hidden */
const beforeBatchDelete = 'beforeBatchDelete';
/** @hidden */
const beforeBatchAdd = 'beforeBatchAdd';
/** @hidden */
const beforeBatchSave = 'beforeBatchSave';
/** @hidden */
const batchSave = 'batchSave';
/** @hidden */
const keyPressed = 'key-pressed';
/** @hidden */
const updateData = 'update-data';
/** @hidden */
const doubleTap = 'double-tap';
/** @hidden */
const virtualColumnIndex = 'virtualColumnIndex';
/** @hidden */
const virtualActionArgs = 'virtual-action-args';
/** @hidden */
const destroy = 'destroy';
/** @hidden */
const dataListener = 'data-listener';
/** @hidden */
const indexModifier = 'index-modifier';
/** @hidden */
const beforeStartEdit = 'edit-form';
/** @hidden */
const beforeBatchCancel = 'before-batch-cancel';
/** @hidden */
const batchEditFormRendered = 'batcheditform-rendered';
/** @hidden */
const detailDataBound = 'detailDataBound';
/** @hidden */
const rowDrag = 'rowDrag';
/** @hidden */
const rowDragStartHelper = 'rowDragStartHelper';
/** @hidden */
const rowDrop = 'rowDrop';
/** @hidden */
const rowDragStart = 'rowDragStart';
/** @hidden */
const rowsAdd = 'rows-add';
/** @hidden */
const rowsRemove = 'rows-remove';
/** @hidden */
const rowdraging = 'row-draging';
/** @hidden */
const rowDropped = 'row-dropped';
/** @hidden */
const autoCol = 'auto-col';
/** @hidden */
const rowDeselecting = 'rowDeselecting';
/** @hidden */
const headerContent = 'e-headercontent';
/** @hidden */
const movableContent = 'e-movablecontent';
/** @hidden */
const movableHeader = 'e-movableheader';
/** @hidden */
const frozenContent = 'e-frozencontent';
/** @hidden */
const frozenHeader = 'e-frozenheader';
/** @hidden */
const content = 'e-content';
/** @hidden */
const table = 'e-table';
/** @hidden */
const leftRight = 'Left-Right';
/** @hidden */
const frozenRight = 'frozen-right';
/** @hidden */
const frozenLeft = 'frozen-left';
/** @hidden */
const ariaColIndex = 'aria-colindex';
/** @hidden */
const ariaRowIndex = 'aria-rowindex';
/** @hidden */
const actionFailure = 'actionFailure';
/**
* The `Clipboard` module is used to handle clipboard copy action.
*
* @hidden
*/
class TreeClipboard extends Clipboard {
constructor(parent, serviceLocator) {
super(parent.grid, serviceLocator);
this.treeCopyContent = '';
this.copiedUniqueIdCollection = [];
this.treeGridParent = parent;
this.serviceLocator = serviceLocator;
}
setCopyData(withHeader) {
const copyContent = 'copyContent';
const getCopyData = 'getCopyData';
const isSelect = 'isSelect';
const uniqueID = 'uniqueID';
const currentRecords = this.treeGridParent.getCurrentViewRecords();
if (window.getSelection().toString() === '') {
this.clipBoardTextArea.value = this[`${copyContent}`] = '';
const rows = this.treeGridParent.grid.getRows();
if (this.treeGridParent.selectionSettings.mode !== 'Cell') {
const selectedIndexes = this.treeGridParent.getSelectedRowIndexes().sort((a, b) => {
return a - b;
});
for (let i = 0; i < selectedIndexes.length; i++) {
if (i > 0) {
this.treeCopyContent += '\n';
}
const selectedRowIndex = selectedIndexes[parseInt(i.toString(), 10)];
if (!rows[selectedRowIndex].classList.contains('e-summaryrow')) {
const cells = [].slice.call(rows[selectedRowIndex].querySelectorAll('.e-rowcell'));
const uniqueid = this.treeGridParent.getSelectedRecords()[parseInt(i.toString(), 10)][`${uniqueID}`];
if (this.copiedUniqueIdCollection.indexOf(uniqueid) === -1) {
if (this.treeGridParent.copyHierarchyMode === 'Parent' || this.treeGridParent.copyHierarchyMode === 'Both') {
this.parentContentData(currentRecords, selectedRowIndex, rows, withHeader, i);
}
this[`${getCopyData}`](cells, false, '\t', withHeader);
this.treeCopyContent += this[`${copyContent}`];
this.copiedUniqueIdCollection.push(uniqueid);
this[`${copyContent}`] = '';
if (this.treeGridParent.copyHierarchyMode === 'Child' || this.treeGridParent.copyHierarchyMode === 'Both') {
this.childContentData(currentRecords, selectedIndexes[parseInt(i.toString(), 10)], rows, withHeader);
}
}
}
}
if (withHeader) {
const headerTextArray = this.treeGridParent.getVisibleColumns().map((col) => col.headerText);
this[`${getCopyData}`](headerTextArray, false, '\t', withHeader);
this.treeCopyContent = this[`${copyContent}`] + '\n' + this.treeCopyContent;
}
const args = {
data: this.treeCopyContent,
cancel: false
};
this.treeGridParent.trigger(beforeCopy, args);
if (args.cancel) {
return;
}
this.clipBoardTextArea.value = this[`${copyContent}`] = args.data;
if (!Browser.userAgent.match(/ipad|ipod|iphone/i)) {
this.clipBoardTextArea.select();
}
else {
this.clipBoardTextArea.setSelectionRange(0, this.clipBoardTextArea.value.length);
}
this[`${isSelect}`] = true;
this.copiedUniqueIdCollection = [];
this.treeCopyContent = '';
}
else {
super.setCopyData(withHeader);
}
}
}
parentContentData(currentRecords, selectedIndex, rows, withHeader, index) {
const getCopyData = 'getCopyData';
const copyContent = 'copyContent';
const parentItem = 'parentItem';
const uniqueID = 'uniqueID';
const level = 'level';
if (!isNullOrUndefined(currentRecords[parseInt(selectedIndex.toString(), 10)][`${parentItem}`])) {
const treeLevel = currentRecords[parseInt(selectedIndex.toString(), 10)][`${parentItem}`][`${level}`];
for (let i = 0; i < treeLevel + 1; i++) {
for (let j = 0; j < currentRecords.length; j++) {
if (!isNullOrUndefined(currentRecords[parseInt(selectedIndex.toString(), 10)][`${parentItem}`]) &&
currentRecords[parseInt(j.toString(), 10)][`${uniqueID}`] === currentRecords[parseInt(selectedIndex.toString(), 10)][`${parentItem}`][`${uniqueID}`]) {
selectedIndex = j;
const cells = [].slice.call(rows[parseInt(selectedIndex.toString(), 10)].querySelectorAll('.e-rowcell'));
const uniqueid = currentRecords[parseInt(j.toString(), 10)][`${uniqueID}`];
if (this.copiedUniqueIdCollection.indexOf(uniqueid) === -1) {
this[`${getCopyData}`](cells, false, '\t', withHeader);
if (index > 0) {
this.treeCopyContent = this.treeCopyContent + this[`${copyContent}`] + '\n';
}
else {
this.treeCopyContent = this[`${copyContent}`] + '\n' + this.treeCopyContent;
}
this.copiedUniqueIdCollection.push(uniqueid);
this[`${copyContent}`] = '';
break;
}
}
}
}
}
}
copy(withHeader) {
super.copy(withHeader);
}
paste(data, rowIndex, colIndex) {
super.paste(data, rowIndex, colIndex);
}
/**
* For internal use only - Get the module name.
*
* @private
* @returns {string} Returns clipboard module name
*/
getModuleName() {
return 'clipboard';
}
/**
* To destroy the clipboard
*
* @returns {void}
* @hidden
*/
destroy() {
super.destroy();
}
childContentData(currentRecords, selectedIndex, rows, withHeader) {
const getCopyData = 'getCopyData';
const copyContent = 'copyContent';
const childRecords = 'childRecords';
const hasChildRecords = 'hasChildRecords';
const uniqueID = 'uniqueID';
if (currentRecords[parseInt(selectedIndex.toString(), 10)][`${hasChildRecords}`]) {
const childData = currentRecords[parseInt(selectedIndex.toString(), 10)][`${childRecords}`];
for (let i = 0; i < childData.length; i++) {
for (let j = 0; j < currentRecords.length; j++) {
if (!isNullOrUndefined(childData[parseInt(i.toString(), 10)][`${uniqueID}`]) && currentRecords[parseInt(j.toString(), 10)][`${uniqueID}`] === childData[parseInt(i.toString(), 10)][`${uniqueID}`]) {
if ((!isNullOrUndefined(rows[parseInt(j.toString(), 10)])) && !rows[parseInt(j.toString(), 10)].classList.contains('e-summaryrow')) {
const cells = [].slice.call(rows[parseInt(j.toString(), 10)].querySelectorAll('.e-rowcell'));
const uniqueid = currentRecords[parseInt(j.toString(), 10)][`${uniqueID}`];
if (this.copiedUniqueIdCollection.indexOf(uniqueid) === -1) {
this[`${getCopyData}`](cells, false, '\t', withHeader);
this.treeCopyContent += ('\n' + this[`${copyContent}`]);
this[`${copyContent}`] = '';
this.copiedUniqueIdCollection.push(uniqueid);
this.childContentData(currentRecords, j, rows, withHeader);
}
}
break;
}
}
}
}
}
}
/**
* @param {TreeGrid} parent - Tree Grid instance
* @returns {boolean} - Specifies whether remote data binding
*/
function isRemoteData(parent) {
if (parent.dataSource instanceof DataManager) {
const adaptor = parent.dataSource.adaptor;
return (adaptor instanceof ODataAdaptor ||
(adaptor instanceof WebApiAdaptor) || (adaptor instanceof WebMethodAdaptor) ||
(adaptor instanceof CacheAdaptor) || adaptor instanceof UrlAdaptor);
}
return false;
}
/**
* @param {TreeGrid | IGrid} parent - Tree Grid or Grid instance
* @returns {boolean} - Returns whether custom binding
*/
function isCountRequired(parent) {
if (parent.dataSource && 'result' in parent.dataSource) {
return true;
}
return false;
}
/**
* @param {TreeGrid} parent - Tree Grid instance
* @returns {boolean} - Returns whether checkbox column is enabled
*/
function isCheckboxcolumn(parent) {
for (let i = 0; i < parent.columns.length; i++) {
if (parent.columns[parseInt(i.toString(), 10)].showCheckbox) {
return true;
}
}
return false;
}
/**
* @param {TreeGrid} parent - Tree Grid instance
* @returns {boolean} - Returns whether filtering and searching done
*/
function isFilterChildHierarchy(parent) {
if ((!isNullOrUndefined(parent.grid.searchSettings.key) && parent.grid.searchSettings.key !== '' &&
(parent.searchSettings.hierarchyMode === 'Child' || parent.searchSettings.hierarchyMode === 'None')) ||
(parent.allowFiltering && parent.grid.filterSettings.columns.length &&
(parent.filterSettings.hierarchyMode === 'Child' || parent.filterSettings.hierarchyMode === 'None'))) {
return true;
}
return false;
}
/**
* @param {Object} records - Define records for which parent records has to be found
* @hidden
* @returns {Object} - Returns parent records collection
*/
function findParentRecords(records) {
const datas = [];
const recordsLength = Object.keys(records).length;
for (let i = 0, len = recordsLength; i < len; i++) {
const hasChild = getObject('hasChildRecords', records[parseInt(i.toString(), 10)]);
if (hasChild) {
datas.push(records[parseInt(i.toString(), 10)]);
}
}
return datas;
}
/**
* @param {TreeGrid} parent - Tree Grid instance
* @returns {boolean} - Returns the expand status of record
* @param {ITreeData} record - Define the record for which expand status has be found
* @param {ITreeData[]} parents - Parent Data collection
* @hidden
*/
function getExpandStatus(parent, record, parents) {
const parentRecord = isNullOrUndefined(record.parentItem) ? null :
getParentData(parent, record.parentItem.uniqueID);
let childParent;
if (parentRecord != null) {
if (parent.initialRender && !isNullOrUndefined(parentRecord[parent.expandStateMapping])
&& !parentRecord[parent.expandStateMapping]) {
parentRecord.expanded = false;
return false;
}
else if (parentRecord.expanded === false) {
return false;
}
else if (parentRecord.parentItem) {
childParent = getParentData(parent, parentRecord.parentItem.uniqueID);
if (childParent && parent.initialRender && !isNullOrUndefined(childParent[parent.expandStateMapping])
&& !childParent[parent.expandStateMapping]) {
childParent.expanded = false;
return false;
}
if (childParent && childParent.expanded === false) {
return false;
}
else if (childParent) {
return getExpandStatus(parent, childParent);
}
return true;
}
else {
return true;
}
}
else {
return true;
}
}
/**
* @param {ITreeData} records - Define the record for which child records has to be found
* @returns {Object[]} - Returns child records collection
* @hidden
*/
function findChildrenRecords(records) {
let datas = [];
if (isNullOrUndefined(records) || (!records.hasChildRecords && !isNullOrUndefined(records.childRecords)
&& !records.childRecords.length)) {
return [];
}
if (!isNullOrUndefined(records.childRecords)) {
const childRecords = records.childRecords.filter((item) => !item.isSummaryRow);
const keys = Object.keys(childRecords);
for (let i = 0, len = keys.length; i < len; i++) {
datas.push(childRecords[parseInt(i.toString(), 10)]);
if (childRecords[parseInt(i.toString(), 10)].hasChildRecords ||
(!isNullOrUndefined(childRecords[parseInt(i.toString(), 10)].childRecords) &&
childRecords[parseInt(i.toString(), 10)].childRecords.length)) {
datas = [...datas, ...findChildrenRecords(childRecords[parseInt(i.toString(), 10)])];
}
}
}
return datas;
}
/**
* @param {TreeGrid} parent - Tree Grid instance
* @returns {boolean} - Returns whether local data binding
*/
function isOffline(parent) {
if (isRemoteData(parent)) {
const dm = parent.dataSource;
return !isNullOrUndefined(dm.ready);
}
return true;
}
/**
* @param {Object[]} array - Defines the array to be cloned
* @returns {Object[]} - Returns cloned array collection
*/
function extendArray(array) {
const objArr = [];
let obj;
let keys;
for (let i = 0; array && i < array.length; i++) {
keys = Object.keys(array[parseInt(i.toString(), 10)]);
obj = {};
for (let j = 0; j < keys.length; j++) {
obj[keys[parseInt(j.toString(), 10)]] = array[parseInt(i.toString(), 10)][keys[parseInt(j.toString(), 10)]];
}
objArr.push(obj);
}
return objArr;
}
/**
* @param {ITreeData} value - Defined the dirty data to be cleaned
* @returns {ITreeData} - Returns cleaned original data
*/
function getPlainData(value) {
delete value.hasChildRecords;
delete value.childRecords;
delete value.index;
delete value.parentItem;
delete value.level;
delete value.taskData;
delete value.uniqueID;
return value;
}
/**
* @param {TreeGrid} parent - TreeGrid instance
* @param {string} value - IdMapping field name
* @param {boolean} requireFilter - Specified whether treegrid data is filtered
* @returns {ITreeData} - Returns IdMapping matched record
*/
function getParentData(parent, value, requireFilter) {
if (requireFilter) {
const idFilter = 'uniqueIDFilterCollection';
return parent[`${idFilter}`][`${value}`];
}
else {
const id = 'uniqueIDCollection';
return parent[`${id}`][`${value}`];
}
}
/**
* @param {HTMLTableRowElement} el - Row element
* @returns {boolean} - Returns whether hidden
*/
function isHidden(el) {
const style = window.getComputedStyle(el);
return ((style.display === 'none') || (style.visibility === 'hidden'));
}
/**
* TreeGrid Selection module
*
* @hidden
*/
class Selection {
/**
* Constructor for Selection module
*
* @param {TreeGrid} parent - Tree Grid instance
*/
constructor(parent) {
this.parent = parent;
this.selectedItems = [];
this.selectedIndexes = [];
this.filteredList = [];
this.searchingRecords = [];
this.addEventListener();
}
/**
* For internal use only - Get the module name.
*
* @private
* @returns {string} Returns Selection module name
*/
getModuleName() {
return 'selection';
}
addEventListener() {
this.parent.on('dataBoundArg', this.headerCheckbox, this);
this.parent.on('columnCheckbox', this.columnCheckbox, this);
this.parent.on('updateGridActions', this.updateGridActions, this);
this.parent.grid.on('colgroup-refresh', this.headerCheckbox, this);
this.parent.on('checkboxSelection', this.checkboxSelection, this);
}
removeEventListener() {
if (this.parent.isDestroyed) {
return;
}
this.parent.off('dataBoundArg', this.headerCheckbox);
this.parent.off('columnCheckbox', this.columnCheckbox);
this.parent.grid.off('colgroup-refresh', this.headerCheckbox);
this.parent.off('checkboxSelection', this.checkboxSelection);
this.parent.off('updateGridActions', this.updateGridActions);
}
/**
* To destroy the Selection
*
* @returns {void}
* @hidden
*/
destroy() {
this.removeEventListener();
}
checkboxSelection(args) {
const target = getObject('target', args);
const checkWrap = parentsUntil(target, 'e-checkbox-wrapper');
let checkBox;
if (checkWrap && checkWrap.querySelectorAll('.e-treecheckselect').length > 0) {
checkBox = checkWrap.querySelector('input[type="checkbox"]');
const rowIndex = [];
rowIndex.push(target.closest('tr').rowIndex);
this.selectCheckboxes(rowIndex);
this.triggerChkChangeEvent(checkBox, checkBox.nextElementSibling.classList.contains('e-check'), target.closest('tr'));
}
else if (checkWrap && checkWrap.querySelectorAll('.e-treeselectall').length > 0 && this.parent.autoCheckHierarchy) {
const checkBoxvalue = !checkWrap.querySelector('.e-frame').classList.contains('e-check')
&& !checkWrap.querySelector('.e-frame').classList.contains('e-stop');
this.headerSelection(checkBoxvalue);
checkBox = checkWrap.querySelector('input[type="checkbox"]');
this.triggerChkChangeEvent(checkBox, checkBoxvalue, target.closest('tr'));
}
if (!isNullOrUndefined(this.parent['parentQuery']) && this.parent.selectionSettings.persistSelection
&& this.parent['columnModel'].filter((col) => { return col.type === 'checkbox'; }).length > 0
&& isRemoteData(this.parent)) {
if (this.parent['parentQuery'].length > 0) {
this.parent.query.queries.push(...this.parent['parentQuery']);
this.parent['parentQuery'] = [];
}
}
}
triggerChkChangeEvent(checkBox, checkState, rowElement) {
const data = this.parent.getCurrentViewRecords()[rowElement.rowIndex];
const args = { checked: checkState, target: checkBox, rowElement: rowElement,
rowData: checkBox.classList.contains('e-treeselectall')
? this.parent.getCheckedRecords() : data };
this.parent.trigger(checkboxChange, args);
}
getCheckboxcolumnIndex() {
let mappingUid;
let columnIndex;
const stackedHeader = 'stackedHeader';
const columnModel = 'columnModel';
const columns = this.parent[`${stackedHeader}`] ? this.parent[`${columnModel}`] : (this.parent.columns);
for (let col = 0; col < columns.length; col++) {
if (columns[parseInt(col.toString(), 10)].showCheckbox) {
mappingUid = columns[parseInt(col.toString(), 10)].uid;
}
}
const headerCelllength = this.parent.getHeaderContent().querySelectorAll('.e-headercelldiv').length;
for (let j = 0; j < headerCelllength; j++) {
const headercell = this.parent.getHeaderContent().querySelectorAll('.e-headercelldiv')[parseInt(j.toString(), 10)];
if (headercell.getAttribute('e-mappinguid') === mappingUid) {
columnIndex = j;
}
}
return columnIndex;
}
headerCheckbox() {
this.columnIndex = this.getCheckboxcolumnIndex();
if (this.columnIndex > -1 && this.parent.getHeaderContent().querySelectorAll('.e-treeselectall').length === 0) {
const headerElement = this.parent.getHeaderContent().querySelectorAll('.e-headercelldiv')[this.columnIndex];
const value = false;
const rowChkBox = this.parent.createElement('input', { className: 'e-treeselectall', attrs: { 'type': 'checkbox' } });
const checkWrap = createCheckBox(this.parent.createElement, false, { checked: value, label: ' ' });
checkWrap.classList.add('e-hierarchycheckbox');
checkWrap.insertBefore(rowChkBox.cloneNode(), checkWrap.firstChild);
if (!isNullOrUndefined(headerElement)) {
headerElement.insertBefore(checkWrap, headerElement.firstChild);
}
if (this.parent.autoCheckHierarchy) {
this.headerSelection();
}
}
else if (this.columnIndex > -1 && this.parent.getHeaderContent().querySelectorAll('.e-treeselectall').length > 0) {
const checkWrap = this.parent.getHeaderContent().querySelectorAll('.e-checkbox-wrapper')[0];
const checkBoxvalue = checkWrap.querySelector('.e-frame').classList.contains('e-check');
if (this.parent.autoCheckHierarchy && checkBoxvalue) {
this.headerSelection(checkBoxvalue);
}
}
}
renderColumnCheckbox(args) {
const rowChkBox = this.parent.createElement('input', { className: 'e-treecheckselect', attrs: { 'type': 'checkbox', 'aria-label': 'checkbox' } });
const data = args.data;
args.cell.classList.add('e-treegridcheckbox');
args.cell.setAttribute('aria-label', 'checkbox');
const value = (isNullOrUndefined(data.checkboxState) || data.checkboxState === 'uncheck') ? false : true;
const checkWrap = createCheckBox(this.parent.createElement, false, { checked: value, label: ' ' });
checkWrap.classList.add('e-hierarchycheckbox');
if (this.parent.allowTextWrap) {
checkWrap.querySelector('.e-frame').style.width = '18px';
}
if (data.checkboxState === 'indeterminate') {
const checkbox = checkWrap.querySelectorAll('.e-frame')[0];
removeClass([checkbox], ['e-check', 'e-stop', 'e-uncheck']);
checkWrap.querySelector('.e-frame').classList.add('e-stop');
}
checkWrap.insertBefore(rowChkBox.cloneNode(), checkWrap.firstChild);
return checkWrap;
}
columnCheckbox(container) {
const checkWrap = this.renderColumnCheckbox(container);
const containerELe = container.cell.querySelector('.e-treecolumn-container');
if (!isNullOrUndefined(containerELe)) {
if (!container.cell.querySelector('.e-hierarchycheckbox')) {
containerELe.insertBefore(checkWrap, containerELe.querySelectorAll('.e-treecell')[0]);
}
}
else {
const spanEle = this.parent.createElement('span', { className: 'e-treecheckbox' });
const data = container.cell.innerHTML;
container.cell.innerHTML = '';
spanEle.innerHTML = data;
const divEle = this.parent.createElement('div', { className: 'e-treecheckbox-container' });
divEle.appendChild(checkWrap);
divEle.appendChild(spanEle);
container.cell.appendChild(divEle);
}
}
selectCheckboxes(rowIndexes) {
if (isNullOrUndefined(rowIndexes)) {
const error = 'The provided value for the rowIndexes is undefined. Please ensure the rowIndexes contains number.';
this.parent.trigger(actionFailure, { error: error });
}
for (let i = 0; i < rowIndexes.length; i++) {
let record = this.parent.getCurrentViewRecords()[rowIndexes[parseInt(i.toString(), 10)]];
const flatRecord = getParentData(this.parent, record.uniqueID);
record = flatRecord;
const checkboxState = (record.checkboxState === 'uncheck') ? 'check' : 'uncheck';
record.checkboxState = checkboxState;
const keys = Object.keys(record);
for (let j = 0; j < keys.length; j++) {
if (Object.prototype.hasOwnProperty.call(flatRecord, keys[parseInt(j.toString(), 10)])) {
flatRecord[keys[parseInt(j.toString(), 10)]] = record[keys[parseInt(j.toString(), 10)]];
}
}
this.traverSelection(record, checkboxState, false);
if (this.parent.autoCheckHierarchy) {
this.headerSelection();
}
}
}
traverSelection(record, checkboxState, ischildItem) {
let length = 0;
this.updateSelectedItems(record, checkboxState);
if (!ischildItem && record.parentItem && this.parent.autoCheckHierarchy) {
this.updateParentSelection(record.parentItem);
}
if (record.childRecords && this.parent.autoCheckHierarchy) {
let childRecords = record.childRecords;
if (!isNullOrUndefined(this.parent.filterModule) &&
this.parent.filterModule.filteredResult.length > 0 && this.parent.autoCheckHierarchy) {
childRecords = this.getFilteredChildRecords(childRecords);
}
length = childRecords.length;
for (let count = 0; count < length; count++) {
if (!childRecords[parseInt(count.toString(), 10)].isSummaryRow) {
if (childRecords[parseInt(count.toString(), 10)].hasChildRecords) {
this.traverSelection(childRecords[parseInt(count.toString(), 10)], checkboxState, true);
}
else {
this.updateSelectedItems(childRecords[parseInt(count.toString(), 10)], checkboxState);
}
}
}
}
}
getFilteredChildRecords(childRecords) {
const filteredChildRecords = childRecords.filter((e) => {
return this.parent.filterModule.filteredResult.indexOf(e) > -1;
});
return filteredChildRecords;
}
updateParentSelection(parentRecord) {
let length = 0;
let childRecords = [];
const record = getParentData(this.parent, parentRecord.uniqueID);
if (record && record.childRecords) {
childRecords = record.childRecords;
}
if (!isNullOrUndefined(this.parent.filterModule) &&
this.parent.filterModule.filteredResult.length > 0 && this.parent.autoCheckHierarchy) {
childRecords = this.getFilteredChildRecords(childRecords);
}
length = childRecords && childRecords.length;
let indeter = 0;
let checkChildRecords = 0;
if (!isNullOrUndefined(record)) {
for (let i = 0; i < childRecords.length; i++) {
const currentRecord = getParentData(this.parent, childRecords[parseInt(i.toString(), 10)].uniqueID);
const checkBoxRecord = currentRecord;
if (!isNullOrUndefined(checkBoxRecord)) {
if (checkBoxRecord.checkboxState === 'indeterminate') {
indeter++;
}
else if (checkBoxRecord.checkboxState === 'check') {
checkChildRecords++;
}
}
}
if (indeter > 0 || (checkChildRecords > 0 && checkChildRecords !== length)) {
record.checkboxState = 'indeterminate';
}
else if (checkChildRecords === 0 && (!record.hasFilteredChildRecords || isNullOrUndefined(record.hasFilteredChildRecords)) && !isNullOrUndefined(this.parent['dataResults']['actionArgs']) &&
(this.parent['dataResults']['actionArgs'].requestType === 'searching' || this.parent['dataResults']['actionArgs'].requestType === 'filtering') && record.checkboxState === 'check') {
record.checkboxState = 'check';
}
else if ((checkChildRecords === 0 && indeter === 0) || (checkChildRecords === 0 && record.hasFilteredChildRecords && !isNullOrUndefined(this.parent['dataResults']['actionArgs']) &&
(this.parent['dataResults']['actionArgs'].requestType === 'searching' || this.parent['dataResults']['actionArgs'].requestType === 'filtering') && record.checkboxState === 'check')) {
record.checkboxState = 'uncheck';
}
else {
record.checkboxState = 'check';
}
this.updateSelectedItems(record, record.checkboxState);
if (record.parentItem) {
this.updateParentSelection(record.parentItem);
}
}
}
headerSelection(checkAll) {
let index = -1;
let length = 0;
//This property used to maintain the check state of the currentview data after clear filtering
let multiFilterCheckState = false;
if (!isNullOrUndefined(this.parent.filterModule) && this.parent.filterModule.filteredResult.length > 0) {
const filterResult = this.parent.filterModule.filteredResult;
if (this.filteredList.length === 0) {
this.filteredList = filterResult;
}
if (this.parent.grid.searchSettings.key.length) {
this.searchingRecords = filterResult;
}
else {
if (this.filteredList !== filterResult) {
this.filteredList = filterResult;
multiFilterCheckState = true;
}
else {
multiFilterCheckState = false;
}
}
}
if (this.filteredList.length > 0) {
if (!this.parent.filterSettings.columns.length && this.filteredList.length && !this.parent.grid.searchSettings.key.length) {
this.filteredList = [];
}
if (this.searchingRecords.length && !isNullOrUndefined(checkAll)) {
this.filteredList = this.searchingRecords;
}
}
let data;
if (!(isNullOrUndefined(this.parent.filterModule)) &&
this.parent.filterModule.filteredResult.length === 0 && this.parent.getCurrentViewRecords().length === 0 &&
this.parent.filterSettings.columns.length > 0) {
data = this.filteredList;
}
else {
data = (!isNullOrUndefined(this.parent.filterModule) &&
(this.filteredList.length > 0)) ? this.filteredList : this.parent.flatData;
}
data = isRemoteData(this.parent) ? this.parent.getCurrentViewRecords() : data;
if (!isNullOrUndefined(checkAll)) {
for (let i = 0; i < data.length; i++) {
if (checkAll) {
if (data[parseInt(i.toString(), 10)].checkboxState === 'check') {
continue;
}
if (multiFilterCheckState) {
continue;