@syncfusion/ej2-spreadsheet
Version:
Feature-rich JavaScript Spreadsheet (Excel) control with built-in support for selection, editing, formatting, importing and exporting to Excel
996 lines (995 loc) • 143 kB
JavaScript
import { locale, dialog, mouseDown, renderFilterCell, initiateFilterUI, getStartEvent, focus, getChartsIndexes, refreshChartCellModel, readonlyAlert } from '../index';
import { reapplyFilter, filterCellKeyDown, refreshFilterRange, createNoteIndicator } from '../index';
import { getFilteredColumn, cMenuBeforeOpen, filterByCellValue, clearFilter, getFilterRange, applySort } from '../index';
import { applyPredicates, isHiddenRow, isReadOnlyCells } from '../../workbook/index';
import { checkIsNumberAndGetNumber } from '../../workbook/common/internalization';
import { filterRangeAlert, setFilteredCollection, beforeDelete, sheetsDestroyed, initiateFilter, duplicateSheetFilterHandler, moveSheetHandler, updateSortCollection, checkNumberFormat } from '../../workbook/common/event';
import { getRangeIndexes, beforeInsert, parseLocaleNumber } from '../../workbook/index';
import { getIndexesFromAddress, getSwapRange, getColumnHeaderText, getDataRange, isCustomDateTime } from '../../workbook/index';
import { getData, getTypeFromFormat, getCell, getCellIndexes, getRangeAddress, getSheet, inRange } from '../../workbook/index';
import { sortImport, clear, getColIndex, setRow, hideShow } from '../../workbook/index';
import { beginAction, getValueFromFormat } from '../../workbook/index';
import { isFilterHidden, isNumber, checkDateFormat, isDateTime, dateToInt, getFormatFromType } from '../../workbook/index';
import { getComponent, EventHandler, isUndefined, isNullOrUndefined, Browser, removeClass, IntlBase, cldrData, getNumberDependable, defaultCurrencyCode } from '@syncfusion/ej2-base';
import { detach, classList, getNumericObject } from '@syncfusion/ej2-base';
import { Internationalization } from '@syncfusion/ej2-base';
import { refreshFilterCellsOnResize, updateWrapCell, isTouchStart } from '../common/index';
import { ExcelFilterBase, beforeFltrcMenuOpen, CheckBoxFilterBase, getUid } from '@syncfusion/ej2-grids';
import { filterCmenuSelect, filterCboxValue, filterDialogCreated, filterDialogClose, createCboxWithWrap } from '@syncfusion/ej2-grids';
import { parentsUntil, toogleCheckbox, fltrPrevent, customFilterOpen } from '@syncfusion/ej2-grids';
import { Query, DataManager, Predicate, Deferred } from '@syncfusion/ej2-data';
import { TreeView } from '@syncfusion/ej2-navigations';
import { TextBox } from '@syncfusion/ej2-inputs';
import { completeAction, contentLoaded, beforeCheckboxRender, refreshCheckbox } from '../../spreadsheet/index';
/**
* `Filter` module is used to handle the filter action in Spreadsheet.
*/
var Filter = /** @class */ (function () {
/**
* Constructor for filter module.
*
* @param {Spreadsheet} parent - Specifies the Spreadsheet.
*/
function Filter(parent) {
this.parent = parent;
this.filterCollection = new Map();
this.filterRange = new Map();
this.filterBtn = parent.createElement('div', {
className: 'e-filter-btn e-control e-btn e-lib e-filter-iconbtn e-icon-btn' + (this.parent.enableRtl ? ' e-rtl' : '')
});
this.filterBtn.appendChild(parent.createElement('span', { className: 'e-btn-icon e-icons e-filter-icon' }));
this.addEventListener();
}
/**
* To destroy the filter module.
*
* @returns {void} - To destroy the filter module.
*/
Filter.prototype.destroy = function () {
var _this = this;
this.removeEventListener();
if (this.parent.refreshing && this.filterRange.size) {
this.parent.filterCollection = [];
this.filterRange.forEach(function (_value, sheetIdx) {
_this.setFilteredCollection({ sheetIdx: sheetIdx, saveJson: { filterCollection: _this.parent.filterCollection } });
});
}
this.filterRange = null;
this.filterCollection = null;
if (this.filterBtn) {
this.filterBtn.remove();
}
this.filterBtn = null;
if (this.treeViewObj) {
this.treeViewObj.destroy();
}
this.treeViewObj = null;
if (this.treeViewEle) {
this.treeViewEle.remove();
}
this.treeViewEle = null;
if (this.cBox) {
this.cBox.remove();
this.cBox = null;
}
var filterPopupElement = document.querySelectorAll('.e-filter-popup');
if (filterPopupElement) {
filterPopupElement.forEach(function (element) {
element.remove();
});
}
this.parent = null;
};
Filter.prototype.addEventListener = function () {
this.parent.on(filterRangeAlert, this.filterRangeAlertHandler, this);
this.parent.on(initiateFilterUI, this.initiateFilterUIHandler, this);
this.parent.on(mouseDown, this.filterMouseDownHandler, this);
this.parent.on(renderFilterCell, this.renderFilterCellHandler, this);
this.parent.on(refreshFilterRange, this.refreshFilterRange, this);
this.parent.on(updateSortCollection, this.updateSortCollectionHandler, this);
this.parent.on(beforeFltrcMenuOpen, this.beforeFilterMenuOpenHandler, this);
this.parent.on(filterCmenuSelect, this.closeDialog, this);
this.parent.on(reapplyFilter, this.reapplyFilterHandler, this);
this.parent.on(filterByCellValue, this.filterByCellValueHandler, this);
this.parent.on(clearFilter, this.clearFilterHandler, this);
this.parent.on(getFilteredColumn, this.getFilteredColumnHandler, this);
this.parent.on(cMenuBeforeOpen, this.cMenuBeforeOpenHandler, this);
this.parent.on(filterCboxValue, this.filterCboxValueHandler, this);
this.parent.on(getFilterRange, this.getFilterRangeHandler, this);
this.parent.on(filterCellKeyDown, this.filterCellKeyDownHandler, this);
this.parent.on(setFilteredCollection, this.setFilteredCollection, this);
this.parent.on(contentLoaded, this.updateFilter, this);
this.parent.on(beforeInsert, this.beforeInsertHandler, this);
this.parent.on(beforeDelete, this.beforeDeleteHandler, this);
this.parent.on(sheetsDestroyed, this.deleteSheetHandler, this);
this.parent.on(clear, this.clearHandler, this);
this.parent.on(filterDialogCreated, this.filterDialogCreatedHandler, this);
this.parent.on(filterDialogClose, this.removeFilterClass, this);
this.parent.on(duplicateSheetFilterHandler, this.duplicateSheetFilterHandler, this);
this.parent.on(fltrPrevent, this.beforeFilteringHandler, this);
this.parent.on(customFilterOpen, this.customFilterOpen, this);
this.parent.on(moveSheetHandler, this.moveSheetHandler, this);
this.parent.on(refreshFilterCellsOnResize, this.refreshFilterCellsOnResize, this);
};
Filter.prototype.removeEventListener = function () {
if (!this.parent.isDestroyed) {
this.parent.off(filterRangeAlert, this.filterRangeAlertHandler);
this.parent.off(initiateFilterUI, this.initiateFilterUIHandler);
this.parent.off(mouseDown, this.filterMouseDownHandler);
this.parent.off(renderFilterCell, this.renderFilterCellHandler);
this.parent.off(refreshFilterRange, this.refreshFilterRange);
this.parent.off(updateSortCollection, this.updateSortCollectionHandler);
this.parent.off(beforeFltrcMenuOpen, this.beforeFilterMenuOpenHandler);
this.parent.off(filterCmenuSelect, this.closeDialog);
this.parent.off(reapplyFilter, this.reapplyFilterHandler);
this.parent.off(filterByCellValue, this.filterByCellValueHandler);
this.parent.off(clearFilter, this.clearFilterHandler);
this.parent.off(getFilteredColumn, this.getFilteredColumnHandler);
this.parent.off(cMenuBeforeOpen, this.cMenuBeforeOpenHandler);
this.parent.off(filterCboxValue, this.filterCboxValueHandler);
this.parent.off(getFilterRange, this.getFilterRangeHandler);
this.parent.off(filterCellKeyDown, this.filterCellKeyDownHandler);
this.parent.off(setFilteredCollection, this.setFilteredCollection);
this.parent.off(contentLoaded, this.updateFilter);
this.parent.off(beforeInsert, this.beforeInsertHandler);
this.parent.off(beforeDelete, this.beforeDeleteHandler);
this.parent.off(sheetsDestroyed, this.deleteSheetHandler);
this.parent.off(clear, this.clearHandler);
this.parent.off(filterDialogCreated, this.filterDialogCreatedHandler);
this.parent.off(filterDialogClose, this.removeFilterClass);
this.parent.off(duplicateSheetFilterHandler, this.duplicateSheetFilterHandler);
this.parent.off(fltrPrevent, this.beforeFilteringHandler);
this.parent.off(customFilterOpen, this.customFilterOpen);
this.parent.off(moveSheetHandler, this.moveSheetHandler);
this.parent.off(refreshFilterCellsOnResize, this.refreshFilterCellsOnResize);
}
};
/**
* Gets the module name.
*
* @returns {string} - Gets the module name.
*/
Filter.prototype.getModuleName = function () {
return 'filter';
};
/**
* Validates the range and returns false when invalid.
*
* @param {SheetModel} sheet - Specify the sheet.
* @param {string} range - Specify the range.
* @returns {void} - Validates the range and returns false when invalid.
*/
Filter.prototype.isInValidFilterRange = function (sheet, range) {
var selectedRange = range ? getSwapRange(getIndexesFromAddress(range)) :
getSwapRange(getIndexesFromAddress(sheet.selectedRange));
var isEmptySheet = false;
if (sheet.usedRange.colIndex === 0 && sheet.usedRange.rowIndex === 0 && isNullOrUndefined(sheet.rows[sheet.usedRange.rowIndex])) {
isEmptySheet = true; // For Filtering Empty sheet's A1 cell.
}
return selectedRange[0] > sheet.usedRange.rowIndex || selectedRange[1] > sheet.usedRange.colIndex || isEmptySheet;
};
/**
* Shows the range error alert dialog.
*
* @param {any} args - Specifies the args
* @param {string} args.error - range error string.
* @returns {void} - Shows the range error alert dialog.
*/
Filter.prototype.filterRangeAlertHandler = function (args) {
var _this = this;
var dialogInst = this.parent.serviceLocator.getService(dialog);
dialogInst.show({
content: args.error, isModal: true,
height: 180, width: 400, showCloseIcon: true,
beforeOpen: function (args) {
var dlgArgs = {
dialogName: 'FilterRangeDialog',
element: args.element, target: args.target, cancel: args.cancel
};
_this.parent.trigger('dialogBeforeOpen', dlgArgs);
if (dlgArgs.cancel) {
args.cancel = true;
}
else {
focus(_this.parent.element);
}
}
});
this.parent.hideSpinner();
};
/**
* Triggers before filter context menu opened and used to add sorting items.
*
* @param {any} args - Specifies the args
* @param {HTMLElement} args.element - Specify the element
* @returns {void} - Triggers before filter context menu opened and used to add sorting items.
*/
Filter.prototype.beforeFilterMenuOpenHandler = function (args) {
var l10n = this.parent.serviceLocator.getService(locale);
args.element.classList.add('e-spreadsheet-contextmenu'); // to show sort icons
var ul = args.element.querySelector('ul');
this.addMenuItem(ul, l10n.getConstant('SortDescending'), 'e-filter-sortdesc', 'e-sort-desc');
this.addMenuItem(ul, l10n.getConstant('SortAscending'), 'e-filter-sortasc', 'e-sort-asc');
args.element.appendChild(ul);
};
/**
* Creates new menu item element
*
* @param {Element} ul - Specify the element.
* @param {string} text - Specify the text.
* @param {string} className - Specify the className
* @param {string} iconCss - Specify the iconCss
* @returns {void} - Creates new menu item element
*/
Filter.prototype.addMenuItem = function (ul, text, className, iconCss) {
var li = this.parent.createElement('li', { className: className + ' e-menu-item' });
if (!this.parent.allowSorting) {
li.classList.add('e-disabled');
}
li.innerText = text;
li.insertBefore(this.parent.createElement('span', { className: 'e-menu-icon e-icons ' + iconCss }), li.firstChild);
ul.insertBefore(li, ul.firstChild);
};
/**
* Initiates the filter UI for the selected range.
*
* @param {any} args - Specifies the args
* @param {PredicateModel[]} args.predicates - Specify the predicates.
* @param {number} args.range - Specify the range.
* @param {Promise<FilterEventArgs>} args.promise - Spefify the promise.
* @param {number} args.sIdx - Specify the sIdx
* @param {boolean} args.isCut - Specify the bool value
* @param {boolean} args.isUndoRedo - Specify the bool value
* @param {boolean} args.isInternal - Specify the isInternal.
* @param {boolean} args.useFilterRange - Specify the use Filter Range.
* @param {boolean} args.isOpen - Specify the isOpen.
* @param {boolean} args.allowHeaderFilter - Specify the allow header filter.
* @returns {void} - Initiates the filter UI for the selected range.
*/
Filter.prototype.initiateFilterUIHandler = function (args) {
var _this = this;
var predicates = args ? args.predicates : null;
var sheetIdx = args.sIdx;
if (!sheetIdx && sheetIdx !== 0) {
sheetIdx = args.isOpen ? 0 : this.parent.activeSheetIndex;
}
var deferred;
if (args.promise) {
deferred = new Deferred();
args.promise = deferred.promise;
}
var resolveFn = function () {
if (deferred) {
deferred.resolve();
}
};
var isInternal = args.isInternal || args.isCut;
if (this.filterRange.size > 0 && this.filterRange.has(sheetIdx) && !this.parent.isOpen && !predicates) { //disable filter
this.removeFilter(sheetIdx, isInternal, false);
resolveFn();
return;
}
var sheet = getSheet(this.parent, sheetIdx);
if (this.isInValidFilterRange(sheet, args.range)) {
var l10n = this.parent.serviceLocator.getService(locale);
this.filterRangeAlertHandler({ error: l10n.getConstant('FilterOutOfRangeError') });
resolveFn();
return;
}
var selectedRange = args.range || sheet.selectedRange;
var eventArgs;
var actionArgs;
if (!isInternal) {
eventArgs = { range: selectedRange, sheetIndex: sheetIdx, cancel: false, allowHeaderFilter: false };
if (args.predicates) {
eventArgs.predicates = args.predicates;
eventArgs.previousPredicates = this.filterCollection.get(sheetIdx) && [].slice.call(this.filterCollection.get(sheetIdx));
}
else {
eventArgs.filterOptions = { predicates: args.predicates };
}
eventArgs.useFilterRange = false;
actionArgs = { action: 'filter', eventArgs: eventArgs };
this.parent.notify(beginAction, actionArgs);
if (eventArgs.cancel) {
resolveFn();
return;
}
delete eventArgs.cancel;
args.useFilterRange = eventArgs.useFilterRange;
args.allowHeaderFilter = eventArgs.allowHeaderFilter;
}
if (!args.range && (isInternal || selectedRange === eventArgs.range)) {
var rangeIdx = getRangeIndexes(selectedRange);
if (rangeIdx[0] === rangeIdx[2] && rangeIdx[1] === rangeIdx[3]) {
rangeIdx = getDataRange(rangeIdx[0], rangeIdx[1], sheet);
selectedRange = getRangeAddress(rangeIdx);
if (!isInternal) {
eventArgs.range = selectedRange;
}
}
}
else if (!isInternal) {
selectedRange = eventArgs.range;
}
if (predicates) {
if (predicates.length) {
var filterRange = this.filterRange.get(sheetIdx);
if (filterRange) {
args.useFilterRange = filterRange.useFilterRange;
args.allowHeaderFilter = filterRange.allowHeaderFilter;
}
this.processRange(sheet, sheetIdx, selectedRange, true, args.useFilterRange, args.allowHeaderFilter);
var range = this.filterRange.get(sheetIdx).range.slice();
if (!args.allowHeaderFilter) {
range[0] = range[0] + 1; // to skip first row.
}
if (!args.useFilterRange) {
range[2] = sheet.usedRange.rowIndex; //filter range should be till used range.
}
range[1] = range[3] = getColIndex(predicates[0].field);
var addr = sheet.name + "!" + this.getPredicateRange(range, predicates.slice(1, predicates.length));
var fullAddr = getRangeAddress(range);
getData(this.parent, addr, true, true, null, true, null, null, false, fullAddr).then(function (jsonData) {
_this.filterSuccessHandler(new DataManager(jsonData), { action: 'filtering', filterCollection: predicates, field: predicates[0].field, sIdx: args.sIdx,
isInternal: isInternal, isOpen: args.isOpen, prevPredicates: eventArgs && eventArgs.previousPredicates });
resolveFn();
});
return;
}
else {
this.clearFilterHandler({ sheetIndex: sheetIdx });
resolveFn();
}
}
else {
this.processRange(sheet, sheetIdx, selectedRange, false, args.useFilterRange, args.allowHeaderFilter);
resolveFn();
}
if (!isInternal) {
this.parent.notify(completeAction, actionArgs);
focus(this.parent.element);
}
};
/**
* Processes the range if no filter applied.
*
* @param {SheetModel} sheet - Specify the sheet.
* @param {number} sheetIdx - Specify the sheet index.
* @param {string} filterRange - Specify the filterRange.
* @param {boolean} preventRefresh - To prevent refreshing the filter buttons.
* @param {boolean} useFilterRange - Specifies whether to consider filtering range or used range during filering.
* @param {boolean} allowHeaderFilter - Specifies whether to consider first row during filtering.
* @returns {void} - Processes the range if no filter applied.
*/
Filter.prototype.processRange = function (sheet, sheetIdx, filterRange, preventRefresh, useFilterRange, allowHeaderFilter) {
var range = getSwapRange(getIndexesFromAddress(filterRange || sheet.selectedRange));
if (range[0] === range[2] && range[1] === range[3]) { //if selected range is a single cell
range[0] = 0;
range[1] = 0;
range[2] = sheet.usedRange.rowIndex;
range[3] = sheet.usedRange.colIndex;
}
else if (range[3] > sheet.usedRange.colIndex) {
range[3] = sheet.usedRange.colIndex;
}
var filterOption = { useFilterRange: useFilterRange,
range: range };
if (allowHeaderFilter) {
filterOption.allowHeaderFilter = allowHeaderFilter;
}
this.filterRange.set(sheetIdx, filterOption);
this.filterCollection.set(sheetIdx, []);
if (!preventRefresh) {
this.refreshFilterRange(range, false, sheetIdx);
}
};
/**
* Removes all the filter related collections for the active sheet.
*
* @param {number} sheetIdx - Specify the sheet index.
* @param {boolean} isCut - Specify the bool value.
* @param {boolean} preventRefresh - Specify the preventRefresh.
* @param {boolean} clearAction - Specify the current action is clear or not.
* @returns {void} - Removes all the filter related collections for the active sheet.
*/
Filter.prototype.removeFilter = function (sheetIdx, isCut, preventRefresh, clearAction) {
var filterOption = this.filterRange.get(sheetIdx);
var range = filterOption.range.slice();
var allowHeaderFilter = filterOption.allowHeaderFilter;
var rangeAddr = getRangeAddress(range);
var args;
if (!isCut) {
args = { action: 'filter', eventArgs: { range: rangeAddr, sheetIndex: sheetIdx, cancel: false }, isClearAction: clearAction };
this.parent.notify(beginAction, args);
if (args.eventArgs.cancel) {
return;
}
delete args.eventArgs.cancel;
}
if (this.filterCollection.get(sheetIdx).length || preventRefresh) {
if (this.filterCollection.get(sheetIdx).length && clearAction) {
var newArgs = {
action: 'filter',
eventArgs: {
range: rangeAddr, sheetIndex: sheetIdx, predicates: [], previousPredicates: this.filterCollection.get(sheetIdx)
}, isClearAction: clearAction
};
this.parent.notify(completeAction, newArgs);
}
this.clearFilterHandler({ preventRefresh: preventRefresh, sheetIndex: sheetIdx });
}
this.filterRange.delete(sheetIdx);
this.filterCollection.delete(sheetIdx);
this.refreshFilterRange(range, true, sheetIdx, allowHeaderFilter);
if (!isCut) {
this.parent.notify(completeAction, args);
}
};
/**
* Handles filtering cell value based on context menu.
*
* @returns {void} - Handles filtering cell value based on context menu.
*/
Filter.prototype.filterByCellValueHandler = function () {
var _this = this;
var sheetIdx = this.parent.activeSheetIndex;
var sheet = this.parent.getActiveSheet();
if (this.isInValidFilterRange(sheet)) {
var l10n = this.parent.serviceLocator.getService(locale);
this.filterRangeAlertHandler({ error: l10n.getConstant('FilterOutOfRangeError') });
return;
}
var cell = getRangeIndexes(sheet.activeCell);
var isNotFilterRange;
if (!this.isFilterRange(sheetIdx, cell[0], cell[1])) {
isNotFilterRange = true;
this.processRange(sheet, sheetIdx);
}
var filterOption = this.filterRange.get(sheetIdx);
var range = filterOption.range.slice();
var filterRange = getRangeAddress(range);
range[0] = range[0] + 1; // to skip first row.
range[2] = sheet.usedRange.rowIndex; //filter range should be till used range.
range[1] = range[3] = cell[1];
var field = getColumnHeaderText(cell[1] + 1);
var selectedCell = getCell(cell[0], cell[1], sheet);
var cellVal = getValueFromFormat(this.parent, selectedCell, cell[0], cell[1], sheetIdx);
var predicates = [{ field: field, operator: 'equal', type: this.getColumnType(sheet, cell[1], cell).type,
matchCase: false, value: cellVal }];
var prevPredicates = [].slice.call(this.filterCollection.get(sheetIdx));
if (!prevPredicates.length) {
prevPredicates = undefined;
}
var eventArgs = { range: filterRange, predicates: predicates,
previousPredicates: prevPredicates, sheetIndex: sheetIdx, cancel: false, allowHeaderFilter: false };
this.parent.notify(beginAction, { action: 'filter', eventArgs: eventArgs });
if (eventArgs.cancel) {
if (isNotFilterRange) {
this.removeFilter(sheetIdx, true);
}
return;
}
if (eventArgs.allowHeaderFilter) {
filterOption.allowHeaderFilter = eventArgs.allowHeaderFilter;
range[0]--;
}
var addr = sheet.name + "!" + this.getPredicateRange(range, this.filterCollection.get(sheetIdx));
var fullAddr = getRangeAddress(range);
getData(this.parent, addr, true, true, null, true, null, null, false, fullAddr).then(function (jsonData) {
_this.filterSuccessHandler(new DataManager(jsonData), { action: 'filtering', filterCollection: predicates, field: field, isFilterByValue: true });
});
};
/**
* Creates filter buttons and renders the filter applied cells.
*
* @param { any} args - Specifies the args
* @param { HTMLElement} args.td - specify the element
* @param { number} args.rowIndex - specify the rowIndex
* @param { number} args.colIndex - specify the colIndex
* @param { number} args.sIdx - specify the sIdx
* @param { boolean} args.isAction - specify the apply filter action.
* @returns {void} - Creates filter buttons and renders the filter applied cells.
*/
Filter.prototype.renderFilterCellHandler = function (args) {
var sheetIdx = !isNullOrUndefined(args.sIdx) ? args.sIdx : this.parent.activeSheetIndex;
if (sheetIdx === this.parent.activeSheetIndex) {
var option = this.filterRange.get(sheetIdx) &&
this.filterRange.get(sheetIdx);
var range = option && option.range;
if (range && (range[0] === args.rowIndex || option.allowHeaderFilter) && range[1] <= args.colIndex &&
range[3] >= args.colIndex) {
if (!args.td || args.td.classList.contains(option.allowHeaderFilter ? 'e-cell' : 'e-header-cell')) {
return;
}
var filterButton = args.td.querySelector('.e-filter-icon');
var filterSortCls = '';
var sortCollection = this.parent.sortCollection;
var field = getColumnHeaderText(args.colIndex + 1);
var predicates = this.filterCollection.get(sheetIdx);
for (var i = 0; i < predicates.length; i++) {
if (predicates[i].field === field) {
filterSortCls = ' e-filtered';
break;
}
}
if (sortCollection) {
for (var i = 0; i < sortCollection.length; i++) {
if (sortCollection[i].sheetIndex === sheetIdx &&
sortCollection[i].columnIndex === args.colIndex) {
filterSortCls += sortCollection[i].order === 'Ascending' ? ' e-sortasc-filter' : ' e-sortdesc-filter';
break;
}
}
}
if (filterButton) {
filterButton.className = "e-btn-icon e-icons e-filter-icon" + filterSortCls;
}
else {
var isNoteAvailable = false;
filterButton = this.filterBtn.cloneNode(true);
if (args.td.children.length > 0 && args.td.children[args.td.childElementCount - 1].className.indexOf('e-addNoteIndicator') > -1) {
args.td.removeChild(args.td.children[args.td.childElementCount - 1]);
isNoteAvailable = true;
}
filterButton.firstElementChild.className = "e-btn-icon e-icons e-filter-icon" + filterSortCls;
args.td.insertBefore(filterButton, args.td.firstChild);
if (args.isAction) {
var sheet = getSheet(this.parent, sheetIdx);
if (getCell(args.rowIndex, args.colIndex, sheet, false, true).wrap) {
this.parent.notify(updateWrapCell, { rowIdx: args.rowIndex, colIdx: args.colIndex, sheet: sheet, ele: args.td });
}
}
if (isNoteAvailable) {
this.parent.notify(createNoteIndicator, { targetElement: args.td, rowIndex: args.rowIndex, columnIndex: args.colIndex });
}
}
}
}
};
/**
* Refreshes the filter header range.
*
* @param {number[]} filterRange - Specify the filterRange.
* @param {boolean} remove - Specify the bool value
* @param {number} sIdx - Specify the index.
* @param {boolean} allowHeaderFilter - Specifies whether to consider first row during filtering.
* @returns {void} - Refreshes the filter header range.
*/
Filter.prototype.refreshFilterRange = function (filterRange, remove, sIdx, allowHeaderFilter) {
var sheetIdx = sIdx;
if (!sheetIdx && sheetIdx !== 0) {
sheetIdx = this.parent.activeSheetIndex;
}
var filterOption = this.filterRange && this.filterRange.get(sheetIdx);
if (!filterOption) {
if (!filterRange) {
filterRange = [0, 0, 0, 0];
}
}
else {
filterRange = filterRange || filterOption.range.slice();
allowHeaderFilter = filterOption.allowHeaderFilter;
}
var range = filterRange;
var cell;
var sheet = getSheet(this.parent, sheetIdx);
var frozenCol = this.parent.frozenColCount(sheet);
for (var index = range[1]; index <= range[3]; index++) {
if (allowHeaderFilter) {
var table = index < frozenCol ? this.parent.sheetModule.getSelectAllTable() :
this.parent.getColHeaderTable();
var headerRow = table && this.parent.getRow(0, table);
cell = headerRow && this.parent.getCell(0, index, headerRow);
}
else {
if (!isHiddenRow(sheet, range[0])) {
cell = this.parent.getCell(range[0], index);
}
else {
cell = null;
}
}
if (remove) {
if (cell) {
var filterBtn = cell.querySelector('.e-filter-btn');
if (filterBtn) {
var isNoteAvailable = false;
if (cell.children.length > 0 && cell.children[cell.childElementCount - 1].className.indexOf('e-addNoteIndicator') > -1) {
cell.removeChild(cell.children[cell.childElementCount - 1]);
isNoteAvailable = true;
}
filterBtn.parentElement.removeChild(filterBtn);
if (isNoteAvailable) {
this.parent.notify(createNoteIndicator, { targetElement: cell, rowIndex: range[0], columnIndex: index });
}
}
}
}
else {
this.renderFilterCellHandler({ td: cell, rowIndex: range[0], colIndex: index, sIdx: sheetIdx, isAction: true });
}
}
if (this.parent.sortCollection) {
this.parent.notify(sortImport, null);
}
};
/**
* Checks whether the provided cell is a filter cell.
*
* @param {number} sheetIdx - Specify the sheet index.
* @param {number} rowIndex - Specify the row index
* @param {number} colIndex - Specify the col index.
* @returns {boolean} - Checks whether the provided cell is a filter cell.
*/
Filter.prototype.isFilterCell = function (sheetIdx, rowIndex, colIndex) {
var range = this.filterRange.has(sheetIdx) && this.filterRange.get(sheetIdx).range;
return (range && range[0] === rowIndex && range[1] <= colIndex && range[3] >= colIndex);
};
/**
* Checks whether the provided cell is in a filter range
*
* @param {number} sheetIdx - Specify the sheet index.
* @param {number} rowIndex - Specify the row index
* @param {number} colIndex - Specify the col index.
* @returns {boolean} - Checks whether the provided cell is in a filter range
*/
Filter.prototype.isFilterRange = function (sheetIdx, rowIndex, colIndex) {
var range = this.filterRange.get(sheetIdx) && this.filterRange.get(sheetIdx).range;
return (range && range[0] <= rowIndex && range[2] >= rowIndex && range[1] <= colIndex && range[3] >= colIndex);
};
/**
* Gets the filter information from active cell
*
* @param {any} args - Specifies the args
* @param {string} args.field - Specify the field
* @param {string} args.clearFilterText - Specify the clearFilterText
* @param {boolean} args.isFiltered - Specify the isFiltered
* @param {boolean} args.isClearAll - Specify the isClearAll
* @param {number} args.sheetIndex - Specify the sheet index value.
* @returns {void} - Triggers before context menu created to enable or disable items.
*/
Filter.prototype.getFilteredColumnHandler = function (args) {
var sheetIdx = isUndefined(args.sheetIndex) ? this.parent.activeSheetIndex : args.sheetIndex;
var l10n = this.parent.serviceLocator.getService(locale);
args.clearFilterText = l10n.getConstant('ClearFilter');
if (this.filterRange.has(sheetIdx)) {
var filterCollection = this.filterCollection.get(sheetIdx);
if (args.isClearAll) {
args.isFiltered = filterCollection && filterCollection.length > 0;
return;
}
var range = this.filterRange.get(sheetIdx).range.slice();
var sheet = getSheet(this.parent, sheetIdx);
var cell = getCellIndexes(sheet.activeCell);
if (this.isFilterRange(sheetIdx, cell[0], cell[1])) {
args.field = getColumnHeaderText(cell[1] + 1);
var headerCell = getCell(range[0], cell[1], sheet);
var cellValue = this.parent.getDisplayText(headerCell);
args.clearFilterText = l10n.getConstant('ClearFilterFrom') + '"'
+ (cellValue ? cellValue.toString() : 'Column ' + args.field) + '"';
filterCollection.some(function (value) {
args.isFiltered = value.field === args.field;
return args.isFiltered;
});
}
}
};
/**
* Triggers before context menu created to enable or disable items.
*
* @param {any} e - Specifies the args
* @param {HTMLElement} e.element - Specify the element
* @param {MenuItemModel[]} e.items - Specify the items
* @param {MenuItemModel} e.parentItem - Specify the parentItem
* @param {string} e.target - Specify the target
* @returns {void} - Triggers before context menu created to enable or disable items.
*/
Filter.prototype.cMenuBeforeOpenHandler = function (e) {
var id = this.parent.element.id + '_cmenu';
if (e.parentItem && e.parentItem.id === id + '_filter' && e.target === '') {
var args = { isFiltered: false };
this.getFilteredColumnHandler(args);
this.parent.enableContextMenuItems([id + '_clearfilter', id + '_reapplyfilter'], !!args.isFiltered, true);
}
};
/**
* Closes the filter popup.
*
* @returns {void} - Closes the filter popup.
*/
Filter.prototype.closeDialog = function () {
var filterPopup = document.querySelector('.e-filter-popup');
if (filterPopup && filterPopup.id.includes(this.parent.element.id)) {
var excelFilter = getComponent(filterPopup, 'dialog');
EventHandler.remove(filterPopup, getStartEvent(), this.filterMouseDownHandler);
if (excelFilter) {
excelFilter.hide();
}
this.parent.notify(filterDialogClose, null);
}
};
Filter.prototype.removeFilterClass = function () {
if (this.parent.element.style.position === 'relative') {
this.parent.element.style.position = '';
}
if (this.parent.element.classList.contains('e-filter-open')) {
this.parent.element.classList.remove('e-filter-open');
}
};
/**
* Returns true if the filter popup is opened.
*
* @returns {boolean} - Returns true if the filter popup is opened.
*/
Filter.prototype.isPopupOpened = function () {
var filterPopup = document.getElementsByClassName('e-filter-popup')[0];
return filterPopup && filterPopup.id.includes(this.parent.element.id) && filterPopup.style.display !== 'none';
};
Filter.prototype.filterCellKeyDownHandler = function (args) {
var sheet = this.parent.getActiveSheet();
var indexes = getCellIndexes(sheet.activeCell);
if (this.isFilterCell(this.parent.activeSheetIndex, indexes[0], indexes[1])) {
if (args.closePopup) {
this.closeDialog();
}
else {
args.isFilterCell = true;
if (!this.isPopupOpened()) {
var target = this.parent.getCell(indexes[0], indexes[1]);
if (target) {
this.openDialog(target);
}
}
}
}
};
Filter.prototype.filterMouseDownHandler = function (e) {
if ((Browser.isDevice && e.type === 'mousedown') || this.parent.getActiveSheet().isProtected) {
return;
}
var target = e.target;
if (target.classList.contains('e-filter-icon') || target.classList.contains('e-filter-btn')) {
if (Browser.isDevice && isTouchStart(e)) {
e.preventDefault();
}
if (this.isPopupOpened()) {
this.closeDialog();
}
this.openDialog((parentsUntil(target, 'e-cell') || parentsUntil(target, 'e-header-cell')));
}
else if (this.isPopupOpened()) {
var offsetEle = target.offsetParent;
if (!target.classList.contains('e-searchinput') && !target.classList.contains('e-searchclear') && (offsetEle &&
!offsetEle.classList.contains('e-filter-popup') && !offsetEle.classList.contains('e-text-content') &&
!offsetEle.classList.contains('e-checkboxtree') && !offsetEle.classList.contains('e-checkbox-wrapper'))) {
this.closeDialog();
}
else {
this.selectSortItemHandler(target);
}
}
};
Filter.prototype.cboxListSelected = function (args, selectedList, listCount, e, searched) {
var wrapper = parentsUntil(e.target, 'e-ftrchk');
if (wrapper) {
var addCurCbox = searched && wrapper.querySelector('.e-add-current');
if (addCurCbox) {
if (addCurCbox.classList.contains('e-check')) {
classList(addCurCbox, ['e-uncheck'], ['e-check']);
if (!selectedList.length) {
args.btnObj.element.disabled = true;
}
return false;
}
else {
classList(addCurCbox, ['e-check'], ['e-uncheck']);
args.btnObj.element.disabled = false;
return true;
}
}
var selectAll = wrapper.querySelector('.e-selectall');
if (selectAll) {
wrapper.querySelector('.e-chk-hidden').indeterminate = false;
var uncheck = wrapper.querySelector('.e-frame').classList.contains('e-check');
var checkBoxFrame = void 0;
var text = void 0;
for (var idx = searched ? 2 : 1, len = args.element.childElementCount; idx < len; idx++) {
checkBoxFrame = args.element.children[idx].querySelector('.e-frame');
removeClass([checkBoxFrame], ['e-check', 'e-stop', 'e-uncheck']);
if (uncheck) {
args.element.children[idx].querySelector('.e-chk-hidden').checked = false;
checkBoxFrame.classList.add('e-uncheck');
selectedList.splice(0, 1);
}
else {
args.element.children[idx].querySelector('.e-chk-hidden').checked = true;
checkBoxFrame.classList.add('e-check');
text = args.element.children[idx].querySelector('.e-checkboxfiltertext').textContent;
if (selectedList.indexOf(text) === -1) {
selectedList.push(text);
}
}
}
}
else {
var text = wrapper.querySelector('.e-checkboxfiltertext').textContent;
if (wrapper.querySelector('.e-frame').classList.contains('e-check')) {
selectedList.splice(selectedList.indexOf(text), 1);
}
else {
selectedList.push(text);
}
toogleCheckbox(wrapper);
selectAll = args.element.querySelector('.e-selectall');
}
this.updateState(args, selectAll, selectAll.parentElement.querySelector('.e-chk-hidden'), selectedList.length !== listCount, selectedList.length);
}
return null;
};
Filter.prototype.initCboxList = function (args, excelFilter, filterData) {
var _this = this;
var field = args.column.field;
var sortedData = new DataManager(args.dataSource).executeLocal(new Query().sortBy(field + '_value', 'ascending'));
var listData = [];
var sheet = this.parent.getActiveSheet();
var l10n = this.parent.serviceLocator.getService(locale);
var cBoxFrag = document.createDocumentFragment();
var selectAll = this.createSelectAll(args, excelFilter);
cBoxFrag.appendChild(selectAll);
var idCol = {};
var hidden;
var initSelectedList = [];
var selectedList = [];
var dataVal;
sortedData.forEach(function (data) {
if (data[field] === '') {
if (!idCol['isBlank']) {
idCol['isBlank'] = true;
var blankObj = {};
blankObj[field] = l10n.getConstant('Blanks');
hidden = isFilterHidden(sheet, Number(data['__rowIndex']) - 1);
var blankCbox = createCboxWithWrap(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getUid('cbox'), excelFilter.createCheckbox(blankObj[field], !hidden, blankObj), 'e-ftrchk');
if (cBoxFrag.childElementCount === 1) {
cBoxFrag.appendChild(blankCbox);
}
else {
cBoxFrag.insertBefore(blankCbox, cBoxFrag.children[1]);
}
listData.splice(0, 0, blankObj[field]);
if (!hidden) {
initSelectedList.push(blankObj[field]);
selectedList.push(blankObj[field]);
}
}
}
else if (!idCol[data[field]]) {
idCol[data[field]] = true;
hidden = isFilterHidden(sheet, Number(data['__rowIndex']) - 1);
dataVal = data[field];
cBoxFrag.appendChild(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createCboxWithWrap(getUid('cbox'), excelFilter.createCheckbox(dataVal, !hidden, data), 'e-ftrchk'));
listData.push(dataVal);
if (!hidden) {
initSelectedList.push(dataVal);
selectedList.push(dataVal);
}
}
});
args.element.appendChild(cBoxFrag);
var cBoxFrame = selectAll.querySelector('.e-frame');
cBoxFrame.classList.add('e-selectall');
var cBox = selectAll.querySelector('.e-chk-hidden');
this.updateState(args, cBoxFrame, cBox, selectedList.length !== listData.length, selectedList.length);
var mainCboxList = [].slice.call(args.element.childNodes);
var searchedSelectedList;
var searchedList;
var addCurCboxSelected;
args.element.addEventListener('click', function (e) {
if (searchedSelectedList) {
var isCurSelect = _this.cboxListSelected(args, searchedSelectedList, args.element.childElementCount - 2, e, true);
if (isCurSelect !== null) {
addCurCboxSelected = isCurSelect;
}
}
else {
_this.cboxListSelected(args, selectedList, listData.length, e);
}
});
var sortedFullData;
var searchValue;
var updateSearchedList = function (val) {
if (val.toLowerCase().includes(searchValue)) {
var obj = {};
obj[args.column.field] = val;
cBoxFrag.appendChild(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createCboxWithWrap(getUid('cbox'), excelFilter.createCheckbox(val, true, obj), 'e-ftrchk'));
searchedList.push(val);
searchedSelectedList.push(val);
}
};
var performSearchOnData;
var filterDataCount = args.dataSource.length > 1000 ? args.dataSource.length : 1000;
var fullListData = listData;
if (filterData.length <= filterDataCount) {
performSearchOnData = function () {
listData.forEach(function (val) {
updateSearchedList(val);
});
};
}
else {
performSearchOnData = function () {
if (!sortedFullData) {
fullListData = [];
initSelectedList = [];
selectedList = [];
sortedFullData = new DataManager(filterData).executeLocal(new Query().sortBy(field + '_value', 'ascending'));
idCol = {};
sortedFullData.forEach(function (data) {
if (data[field] === '') {
if (!idCol['isBlank']) {
idCol['isBlank'] = true;
dataVal = l10n.getConstant('Blanks');
fullListData.splice(0, 0, dataVal);
if (!isFilterHidden(sheet, Number(data['__rowIndex']) - 1)) {
initSelectedList.push(dataVal);
selectedList.push(dataVal);
}
}
}
else if (!idCol[data[field]]) {
dataVal = data[field];
idCol[dataVal] = true;
fullListData.push(data[field]);
if (!isFilterHidden(sheet, Number(data['__rowIndex']) - 1)) {
selectedList.push(dataVal);
initSelectedList.push(dataVal);
}
}
});
}
for (var filterIdx = 0, len = fullListData.length; filterIdx < len; filterIdx++) {
if (searchedList.length < filterDataCount) {
updateSearchedList(fullListData[filterIdx]);
}
else {
break;
}
}
};
}
var refreshCheckbox = function (e) {
if (e.event.type === 'keyup') {
searchValue = e.event.target.value.toLowerCase();
}
else if (e.event.target.classList.contains('e-search-icon')) {
return;
}
cBoxFrag = document.createDocumentFragment();
cBoxFrag.appendChild(selectAll);
if (searchValue) {
searchedList = [];
searchedSelectedList = [];
performSearchOnData();
if (searchedSelectedList.length) {
_this.updateState(args, cBoxFrame, cBox, false, 0);
selectAll.classList.remove('e-hide');
var obj = {};
obj[field] = l10n.getConstant('AddCurrentSelection');
var addCurrentCbox = createCboxWithWrap(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getUid('cbox'), excelFilter.createCheckbox(obj[field], false, obj), 'e-ftrchk');
cBoxFrag.insertBefore(addCurrentCbox, cBoxFrag.children[1]);
addCurrentCbox.querySelector('.e-frame').classList.add('e-add-current');
}
else {
selectAll.classList.add('e-hide');
var noRecordEle = _this.parent.createElement('div', { className: 'e-checkfltrnmdiv' });
var noRecordText = _this.parent.createElement('span');
noRecordText.innerText = l10n.getConstant('NoResult');
noRecordEle.appendChild(noRecordText);