diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d94289c..5e57ec4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,27 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.15.0](https://github.com/6pac/SlickGrid/compare/5.14.3...5.15.0) (2025-01-18) + +### Bug Fixes + +* add "frozen" class to all slick-pane for easier styling ([#1089](https://github.com/6pac/SlickGrid/issues/1089)) ([967c9d8](https://github.com/6pac/SlickGrid/commit/967c9d8caeb05b636343f2e1181285177eb92722)) +* add missing key shortcuts for grid navigation & cell selections ([#1093](https://github.com/6pac/SlickGrid/issues/1093)) ([91e7c8b](https://github.com/6pac/SlickGrid/commit/91e7c8b37949b7b75d01be76f362d27386adfc58)) +* never activate more than 1 cell, clear any previous active CSS class ([#1100](https://github.com/6pac/SlickGrid/issues/1100)) ([7ff7170](https://github.com/6pac/SlickGrid/commit/7ff71701c6171ed90e5d12978ea873841ecb87ce)) +* remove "active" CSS classes before navigating to another cell ([#1095](https://github.com/6pac/SlickGrid/issues/1095)) ([8a8d3f4](https://github.com/6pac/SlickGrid/commit/8a8d3f41b164a2ee5d2d18a1c3feae2316c3850d)) +* shift+mousewheel should scroll horizontally, fixes [#1094](https://github.com/6pac/SlickGrid/issues/1094) ([#1096](https://github.com/6pac/SlickGrid/issues/1096)) ([5003565](https://github.com/6pac/SlickGrid/commit/5003565a12d578b81aa30b04b785b0b33186bff3)) + +### Features + +* add Custom Global Item Data Provider, closes [#262](https://github.com/6pac/SlickGrid/issues/262) ([#1097](https://github.com/6pac/SlickGrid/issues/1097)) ([5be6fa0](https://github.com/6pac/SlickGrid/commit/5be6fa02f9a18a34715650c5829a410e5eb01142)) +* add final rowspan implementation ([#1101](https://github.com/6pac/SlickGrid/issues/1101)) ([2e65fa8](https://github.com/6pac/SlickGrid/commit/2e65fa8da2abcff5e279a0cf52afab6a537ba8d9)) + +# Change Log + +All notable changes to this project will be documented in this file. + +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + ## [5.14.3](https://github.com/6pac/SlickGrid/compare/5.14.2...5.14.3) (2024-11-28) ### Bug Fixes diff --git a/dist/browser/plugins/slick.cellselectionmodel.js b/dist/browser/plugins/slick.cellselectionmodel.js index e2864337..85df6b96 100644 --- a/dist/browser/plugins/slick.cellselectionmodel.js +++ b/dist/browser/plugins/slick.cellselectionmodel.js @@ -85,15 +85,17 @@ (_a = this._options) != null && _a.selectActiveCell && isRowDefined && isCellDefined ? this.setSelectedRanges([new SlickRange(args.row, args.cell)]) : (!((_b = this._options) != null && _b.selectActiveCell) || !isRowDefined && !isCellDefined) && this.setSelectedRanges([]); } isKeyAllowed(key) { - return ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "PageDown", "PageUp", "Home", "End"].some((k) => k === key); + return ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "PageDown", "PageUp", "Home", "End", "a", "A"].some((k) => k === key); } handleKeyDown(e) { - var _a; + var _a, _b; let ranges, last, colLn = this._grid.getColumns().length, active = this._grid.getActiveCell(), dataLn = 0; if (this._dataView && "getPagingInfo" in this._dataView ? dataLn = ((_a = this._dataView) == null ? void 0 : _a.getPagingInfo().pageSize) || this._dataView.getLength() : dataLn = this._grid.getDataLength(), active && (e.shiftKey || e.ctrlKey) && !e.altKey && this.isKeyAllowed(e.key)) { ranges = this.getSelectedRanges().slice(), ranges.length || ranges.push(new SlickRange(active.row, active.cell)), last = ranges.pop(), last.contains(active.row, active.cell) || (last = new SlickRange(active.row, active.cell)); - let dRow = last.toRow - last.fromRow, dCell = last.toCell - last.fromCell, dirRow = active.row === last.fromRow ? 1 : -1, dirCell = active.cell === last.fromCell ? 1 : -1, isSingleKeyMove = e.key.startsWith("Arrow"), toCell, toRow = 0; - isSingleKeyMove && !e.ctrlKey ? (e.key === "ArrowLeft" ? dCell -= dirCell : e.key === "ArrowRight" ? dCell += dirCell : e.key === "ArrowUp" ? dRow -= dirRow : e.key === "ArrowDown" && (dRow += dirRow), toRow = active.row + dirRow * dRow) : (this._cachedPageRowCount < 1 && (this._cachedPageRowCount = this._grid.getViewportRowCount()), this._prevSelectedRow === void 0 && (this._prevSelectedRow = active.row), e.shiftKey && !e.ctrlKey && e.key === "Home" ? (toCell = 0, toRow = active.row) : e.shiftKey && !e.ctrlKey && e.key === "End" ? (toCell = colLn - 1, toRow = active.row) : e.ctrlKey && e.shiftKey && e.key === "Home" ? (toCell = 0, toRow = 0) : e.ctrlKey && e.shiftKey && e.key === "End" ? (toCell = colLn - 1, toRow = dataLn - 1) : e.key === "PageUp" ? (this._prevSelectedRow >= 0 && (toRow = this._prevSelectedRow - this._cachedPageRowCount), toRow < 0 && (toRow = 0)) : e.key === "PageDown" && (this._prevSelectedRow <= dataLn - 1 && (toRow = this._prevSelectedRow + this._cachedPageRowCount), toRow > dataLn - 1 && (toRow = dataLn - 1)), this._prevSelectedRow = toRow), toCell != null || (toCell = active.cell + dirCell * dCell); + let dRow = last.toRow - last.fromRow, dCell = last.toCell - last.fromCell, toCell, toRow = 0; + e.ctrlKey && ((_b = e.key) == null ? void 0 : _b.toLowerCase()) === "a" && (this._grid.setActiveCell(0, 0, !1, !1, !0), active.row = 0, active.cell = 0, toCell = colLn - 1, toRow = dataLn - 1); + let dirRow = active.row === last.fromRow ? 1 : -1, dirCell = active.cell === last.fromCell ? 1 : -1, isSingleKeyMove = e.key.startsWith("Arrow"); + isSingleKeyMove && !e.ctrlKey ? (e.key === "ArrowLeft" ? dCell -= dirCell : e.key === "ArrowRight" ? dCell += dirCell : e.key === "ArrowUp" ? dRow -= dirRow : e.key === "ArrowDown" && (dRow += dirRow), toRow = active.row + dirRow * dRow) : (this._cachedPageRowCount < 1 && (this._cachedPageRowCount = this._grid.getViewportRowCount()), this._prevSelectedRow === void 0 && (this._prevSelectedRow = active.row), !e.ctrlKey && e.shiftKey && e.key === "Home" || e.ctrlKey && e.shiftKey && e.key === "ArrowLeft" ? (toCell = 0, toRow = active.row) : !e.ctrlKey && e.shiftKey && e.key === "End" || e.ctrlKey && e.shiftKey && e.key === "ArrowRight" ? (toCell = colLn - 1, toRow = active.row) : e.ctrlKey && e.shiftKey && e.key === "ArrowUp" ? toRow = 0 : e.ctrlKey && e.shiftKey && e.key === "ArrowDown" ? toRow = dataLn - 1 : e.ctrlKey && e.shiftKey && e.key === "Home" ? (toCell = 0, toRow = 0) : e.ctrlKey && e.shiftKey && e.key === "End" ? (toCell = colLn - 1, toRow = dataLn - 1) : e.key === "PageUp" ? (this._prevSelectedRow >= 0 && (toRow = this._prevSelectedRow - this._cachedPageRowCount), toRow < 0 && (toRow = 0)) : e.key === "PageDown" && (this._prevSelectedRow <= dataLn - 1 && (toRow = this._prevSelectedRow + this._cachedPageRowCount), toRow > dataLn - 1 && (toRow = dataLn - 1)), this._prevSelectedRow = toRow), toCell != null || (toCell = active.cell + dirCell * dCell); let new_last = new SlickRange(active.row, active.cell, toRow, toCell); if (this.removeInvalidRanges([new_last]).length) { ranges.push(new_last); diff --git a/dist/browser/plugins/slick.cellselectionmodel.js.map b/dist/browser/plugins/slick.cellselectionmodel.js.map index f29125c1..c8a68da8 100644 --- a/dist/browser/plugins/slick.cellselectionmodel.js.map +++ b/dist/browser/plugins/slick.cellselectionmodel.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../../src/plugins/slick.cellselectionmodel.ts"], - "sourcesContent": ["import { SlickEvent as SlickEvent_, SlickEventData as SlickEventData_, SlickRange as SlickRange_, Utils as Utils_ } from '../slick.core.js';\r\nimport { SlickCellRangeSelector as SlickCellRangeSelector_ } from './slick.cellrangeselector.js';\r\nimport type { CustomDataView, OnActiveCellChangedEventArgs } from '../models/index.js';\r\nimport type { SlickDataView } from '../slick.dataview.js';\r\nimport type { SlickGrid } from '../slick.grid.js';\r\n\r\n// for (iife) load Slick methods from global Slick object, or use imports for (esm)\r\nconst SlickEvent = IIFE_ONLY ? Slick.Event : SlickEvent_;\r\nconst SlickEventData = IIFE_ONLY ? Slick.EventData : SlickEventData_;\r\nconst SlickRange = IIFE_ONLY ? Slick.Range : SlickRange_;\r\nconst SlickCellRangeSelector = IIFE_ONLY ? Slick.CellRangeSelector : SlickCellRangeSelector_;\r\nconst Utils = IIFE_ONLY ? Slick.Utils : Utils_;\r\n\r\nexport interface CellSelectionModelOption {\r\n selectActiveCell: boolean;\r\n cellRangeSelector?: SlickCellRangeSelector_;\r\n}\r\n\r\nexport class SlickCellSelectionModel {\r\n // --\r\n // public API\r\n pluginName = 'CellSelectionModel' as const;\r\n onSelectedRangesChanged = new SlickEvent('onSelectedRangesChanged');\r\n\r\n // --\r\n // protected props\r\n protected _cachedPageRowCount = 0;\r\n protected _dataView?: CustomDataView | SlickDataView;\r\n protected _grid!: SlickGrid;\r\n protected _prevSelectedRow?: number;\r\n protected _prevKeyDown = '';\r\n protected _ranges: SlickRange_[] = [];\r\n protected _selector: SlickCellRangeSelector_;\r\n protected _options?: CellSelectionModelOption;\r\n protected _defaults: CellSelectionModelOption = {\r\n selectActiveCell: true\r\n };\r\n\r\n constructor(options?: { selectActiveCell: boolean; cellRangeSelector: SlickCellRangeSelector_; }) {\r\n if (options === undefined || options.cellRangeSelector === undefined) {\r\n this._selector = new SlickCellRangeSelector({ selectionCss: { border: '2px solid black' } as CSSStyleDeclaration });\r\n } else {\r\n this._selector = options.cellRangeSelector;\r\n }\r\n }\r\n\r\n init(grid: SlickGrid) {\r\n this._options = Utils.extend(true, {}, this._defaults, this._options);\r\n this._grid = grid;\r\n if (grid.hasDataView()) {\r\n this._dataView = grid.getData();\r\n }\r\n this._grid.onActiveCellChanged.subscribe(this.handleActiveCellChange.bind(this));\r\n this._grid.onKeyDown.subscribe(this.handleKeyDown.bind(this));\r\n grid.registerPlugin(this._selector);\r\n this._selector.onCellRangeSelected.subscribe(this.handleCellRangeSelected.bind(this));\r\n this._selector.onBeforeCellRangeSelected.subscribe(this.handleBeforeCellRangeSelected.bind(this));\r\n }\r\n\r\n destroy() {\r\n this._grid.onActiveCellChanged.unsubscribe(this.handleActiveCellChange.bind(this));\r\n this._grid.onKeyDown.unsubscribe(this.handleKeyDown.bind(this));\r\n this._selector.onCellRangeSelected.unsubscribe(this.handleCellRangeSelected.bind(this));\r\n this._selector.onBeforeCellRangeSelected.unsubscribe(this.handleBeforeCellRangeSelected.bind(this));\r\n this._grid.unregisterPlugin(this._selector);\r\n this._selector?.destroy();\r\n }\r\n\r\n protected removeInvalidRanges(ranges: SlickRange_[]) {\r\n const result: SlickRange_[] = [];\r\n\r\n for (let i = 0; i < ranges.length; i++) {\r\n const r = ranges[i];\r\n if (this._grid.canCellBeSelected(r.fromRow, r.fromCell) && this._grid.canCellBeSelected(r.toRow, r.toCell)) {\r\n result.push(r);\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n protected rangesAreEqual(range1: SlickRange_[], range2: SlickRange_[]) {\r\n let areDifferent = (range1.length !== range2.length);\r\n if (!areDifferent) {\r\n for (let i = 0; i < range1.length; i++) {\r\n if (\r\n range1[i].fromCell !== range2[i].fromCell\r\n || range1[i].fromRow !== range2[i].fromRow\r\n || range1[i].toCell !== range2[i].toCell\r\n || range1[i].toRow !== range2[i].toRow\r\n ) {\r\n areDifferent = true;\r\n break;\r\n }\r\n }\r\n }\r\n return !areDifferent;\r\n }\r\n\r\n /** Provide a way to force a recalculation of page row count (for example on grid resize) */\r\n resetPageRowCount() {\r\n this._cachedPageRowCount = 0;\r\n }\r\n\r\n setSelectedRanges(ranges: SlickRange_[], caller = 'SlickCellSelectionModel.setSelectedRanges') {\r\n // simple check for: empty selection didn't change, prevent firing onSelectedRangesChanged\r\n if ((!this._ranges || this._ranges.length === 0) && (!ranges || ranges.length === 0)) { return; }\r\n\r\n // if range has not changed, don't fire onSelectedRangesChanged\r\n const rangeHasChanged = !this.rangesAreEqual(this._ranges, ranges);\r\n\r\n this._ranges = this.removeInvalidRanges(ranges);\r\n if (rangeHasChanged) {\r\n // provide extra \"caller\" argument through SlickEventData event to avoid breaking the previous pubsub event structure\r\n // that only accepts an array of selected range `SlickRange[]`, the SlickEventData args will be merged and used later by `onSelectedRowsChanged`\r\n const eventData = new SlickEventData(new CustomEvent('click', { detail: { caller } }), this._ranges);\r\n this.onSelectedRangesChanged.notify(this._ranges, eventData);\r\n }\r\n }\r\n\r\n getSelectedRanges() {\r\n return this._ranges;\r\n }\r\n\r\n refreshSelections() {\r\n this.setSelectedRanges(this.getSelectedRanges());\r\n }\r\n\r\n protected handleBeforeCellRangeSelected(e: SlickEventData_): boolean | void {\r\n if (this._grid.getEditorLock().isActive()) {\r\n e.stopPropagation();\r\n return false;\r\n }\r\n }\r\n\r\n protected handleCellRangeSelected(_e: SlickEventData_, args: { range: SlickRange_; }) {\r\n this._grid.setActiveCell(args.range.fromRow, args.range.fromCell, false, false, true);\r\n this.setSelectedRanges([args.range]);\r\n }\r\n\r\n protected handleActiveCellChange(_e: SlickEventData_, args: OnActiveCellChangedEventArgs) {\r\n this._prevSelectedRow = undefined;\r\n const isCellDefined = Utils.isDefined(args.cell);\r\n const isRowDefined = Utils.isDefined(args.row);\r\n\r\n if (this._options?.selectActiveCell && isRowDefined && isCellDefined) {\r\n this.setSelectedRanges([new SlickRange(args.row, args.cell)]);\r\n } else if (!this._options?.selectActiveCell || (!isRowDefined && !isCellDefined)) {\r\n // clear the previous selection once the cell changes\r\n this.setSelectedRanges([]);\r\n }\r\n }\r\n\r\n protected isKeyAllowed(key: string) {\r\n return ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'PageDown', 'PageUp', 'Home', 'End'].some(k => k === key);\r\n }\r\n\r\n protected handleKeyDown(e: SlickEventData_) {\r\n let ranges: SlickRange_[], last: SlickRange_;\r\n const colLn = this._grid.getColumns().length;\r\n const active = this._grid.getActiveCell();\r\n let dataLn = 0;\r\n if (this._dataView && 'getPagingInfo' in this._dataView) {\r\n dataLn = this._dataView?.getPagingInfo().pageSize || this._dataView.getLength();\r\n } else {\r\n dataLn = this._grid.getDataLength();\r\n }\r\n\r\n if (active && (e.shiftKey || e.ctrlKey) && !e.altKey && this.isKeyAllowed(e.key as string)) {\r\n ranges = this.getSelectedRanges().slice();\r\n if (!ranges.length) {\r\n ranges.push(new SlickRange(active.row, active.cell));\r\n }\r\n // keyboard can work with last range only\r\n last = ranges.pop() as SlickRange_;\r\n\r\n // can't handle selection out of active cell\r\n if (!last.contains(active.row, active.cell)) {\r\n last = new SlickRange(active.row, active.cell);\r\n }\r\n\r\n let dRow = last.toRow - last.fromRow;\r\n let dCell = last.toCell - last.fromCell;\r\n\r\n // walking direction\r\n const dirRow = active.row === last.fromRow ? 1 : -1;\r\n const dirCell = active.cell === last.fromCell ? 1 : -1;\r\n const isSingleKeyMove = e.key!.startsWith('Arrow');\r\n let toCell: undefined | number = undefined;\r\n let toRow = 0;\r\n\r\n if (isSingleKeyMove && !e.ctrlKey) {\r\n // single cell move: (Arrow{Up/ArrowDown/ArrowLeft/ArrowRight})\r\n if (e.key === 'ArrowLeft') {\r\n dCell -= dirCell;\r\n } else if (e.key === 'ArrowRight') {\r\n dCell += dirCell;\r\n } else if (e.key === 'ArrowUp') {\r\n dRow -= dirRow;\r\n } else if (e.key === 'ArrowDown') {\r\n dRow += dirRow;\r\n }\r\n toRow = active.row + dirRow * dRow;\r\n } else {\r\n // multiple cell moves: (Home, End, Page{Up/Down})\r\n if (this._cachedPageRowCount < 1) {\r\n this._cachedPageRowCount = this._grid.getViewportRowCount();\r\n }\r\n if (this._prevSelectedRow === undefined) {\r\n this._prevSelectedRow = active.row;\r\n }\r\n\r\n if (e.shiftKey && !e.ctrlKey && e.key === 'Home') {\r\n toCell = 0;\r\n toRow = active.row;\r\n } else if (e.shiftKey && !e.ctrlKey && e.key === 'End') {\r\n toCell = colLn - 1;\r\n toRow = active.row;\r\n } else if (e.ctrlKey && e.shiftKey && e.key === 'Home') {\r\n toCell = 0;\r\n toRow = 0;\r\n } else if (e.ctrlKey && e.shiftKey && e.key === 'End') {\r\n toCell = colLn - 1;\r\n toRow = dataLn - 1;\r\n } else if (e.key === 'PageUp') {\r\n if (this._prevSelectedRow >= 0) {\r\n toRow = this._prevSelectedRow - this._cachedPageRowCount;\r\n }\r\n if (toRow < 0) {\r\n toRow = 0;\r\n }\r\n } else if (e.key === 'PageDown') {\r\n if (this._prevSelectedRow <= dataLn - 1) {\r\n toRow = this._prevSelectedRow + this._cachedPageRowCount;\r\n }\r\n if (toRow > dataLn - 1) {\r\n toRow = dataLn - 1;\r\n }\r\n }\r\n this._prevSelectedRow = toRow;\r\n }\r\n\r\n // define new selection range\r\n toCell ??= active.cell + dirCell * dCell;\r\n const new_last = new SlickRange(active.row, active.cell, toRow, toCell);\r\n if (this.removeInvalidRanges([new_last]).length) {\r\n ranges.push(new_last);\r\n const viewRow = dirRow > 0 ? new_last.toRow : new_last.fromRow;\r\n const viewCell = dirCell > 0 ? new_last.toCell : new_last.fromCell;\r\n\r\n if (isSingleKeyMove) {\r\n this._grid.scrollRowIntoView(viewRow);\r\n this._grid.scrollCellIntoView(viewRow, viewCell);\r\n } else {\r\n this._grid.scrollRowIntoView(toRow);\r\n this._grid.scrollCellIntoView(toRow, viewCell);\r\n }\r\n } else {\r\n ranges.push(last);\r\n }\r\n\r\n this.setSelectedRanges(ranges);\r\n\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this._prevKeyDown = e.key as string;\r\n }\r\n }\r\n}\r\n\r\n// extend Slick namespace on window object when building as iife\r\nif (IIFE_ONLY && window.Slick) {\r\n Utils.extend(true, window, {\r\n Slick: {\r\n CellSelectionModel: SlickCellSelectionModel\r\n }\r\n });\r\n}\r\n"], - "mappings": "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", + "sourcesContent": ["import { SlickEvent as SlickEvent_, SlickEventData as SlickEventData_, SlickRange as SlickRange_, Utils as Utils_ } from '../slick.core.js';\r\nimport { SlickCellRangeSelector as SlickCellRangeSelector_ } from './slick.cellrangeselector.js';\r\nimport type { CustomDataView, OnActiveCellChangedEventArgs } from '../models/index.js';\r\nimport type { SlickDataView } from '../slick.dataview.js';\r\nimport type { SlickGrid } from '../slick.grid.js';\r\n\r\n// for (iife) load Slick methods from global Slick object, or use imports for (esm)\r\nconst SlickEvent = IIFE_ONLY ? Slick.Event : SlickEvent_;\r\nconst SlickEventData = IIFE_ONLY ? Slick.EventData : SlickEventData_;\r\nconst SlickRange = IIFE_ONLY ? Slick.Range : SlickRange_;\r\nconst SlickCellRangeSelector = IIFE_ONLY ? Slick.CellRangeSelector : SlickCellRangeSelector_;\r\nconst Utils = IIFE_ONLY ? Slick.Utils : Utils_;\r\n\r\nexport interface CellSelectionModelOption {\r\n selectActiveCell: boolean;\r\n cellRangeSelector?: SlickCellRangeSelector_;\r\n}\r\n\r\nexport class SlickCellSelectionModel {\r\n // --\r\n // public API\r\n pluginName = 'CellSelectionModel' as const;\r\n onSelectedRangesChanged = new SlickEvent('onSelectedRangesChanged');\r\n\r\n // --\r\n // protected props\r\n protected _cachedPageRowCount = 0;\r\n protected _dataView?: CustomDataView | SlickDataView;\r\n protected _grid!: SlickGrid;\r\n protected _prevSelectedRow?: number;\r\n protected _prevKeyDown = '';\r\n protected _ranges: SlickRange_[] = [];\r\n protected _selector: SlickCellRangeSelector_;\r\n protected _options?: CellSelectionModelOption;\r\n protected _defaults: CellSelectionModelOption = {\r\n selectActiveCell: true\r\n };\r\n\r\n constructor(options?: { selectActiveCell: boolean; cellRangeSelector: SlickCellRangeSelector_; }) {\r\n if (options === undefined || options.cellRangeSelector === undefined) {\r\n this._selector = new SlickCellRangeSelector({ selectionCss: { border: '2px solid black' } as CSSStyleDeclaration });\r\n } else {\r\n this._selector = options.cellRangeSelector;\r\n }\r\n }\r\n\r\n init(grid: SlickGrid) {\r\n this._options = Utils.extend(true, {}, this._defaults, this._options);\r\n this._grid = grid;\r\n if (grid.hasDataView()) {\r\n this._dataView = grid.getData();\r\n }\r\n this._grid.onActiveCellChanged.subscribe(this.handleActiveCellChange.bind(this));\r\n this._grid.onKeyDown.subscribe(this.handleKeyDown.bind(this));\r\n grid.registerPlugin(this._selector);\r\n this._selector.onCellRangeSelected.subscribe(this.handleCellRangeSelected.bind(this));\r\n this._selector.onBeforeCellRangeSelected.subscribe(this.handleBeforeCellRangeSelected.bind(this));\r\n }\r\n\r\n destroy() {\r\n this._grid.onActiveCellChanged.unsubscribe(this.handleActiveCellChange.bind(this));\r\n this._grid.onKeyDown.unsubscribe(this.handleKeyDown.bind(this));\r\n this._selector.onCellRangeSelected.unsubscribe(this.handleCellRangeSelected.bind(this));\r\n this._selector.onBeforeCellRangeSelected.unsubscribe(this.handleBeforeCellRangeSelected.bind(this));\r\n this._grid.unregisterPlugin(this._selector);\r\n this._selector?.destroy();\r\n }\r\n\r\n protected removeInvalidRanges(ranges: SlickRange_[]) {\r\n const result: SlickRange_[] = [];\r\n\r\n for (let i = 0; i < ranges.length; i++) {\r\n const r = ranges[i];\r\n if (this._grid.canCellBeSelected(r.fromRow, r.fromCell) && this._grid.canCellBeSelected(r.toRow, r.toCell)) {\r\n result.push(r);\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n protected rangesAreEqual(range1: SlickRange_[], range2: SlickRange_[]) {\r\n let areDifferent = (range1.length !== range2.length);\r\n if (!areDifferent) {\r\n for (let i = 0; i < range1.length; i++) {\r\n if (\r\n range1[i].fromCell !== range2[i].fromCell\r\n || range1[i].fromRow !== range2[i].fromRow\r\n || range1[i].toCell !== range2[i].toCell\r\n || range1[i].toRow !== range2[i].toRow\r\n ) {\r\n areDifferent = true;\r\n break;\r\n }\r\n }\r\n }\r\n return !areDifferent;\r\n }\r\n\r\n /** Provide a way to force a recalculation of page row count (for example on grid resize) */\r\n resetPageRowCount() {\r\n this._cachedPageRowCount = 0;\r\n }\r\n\r\n setSelectedRanges(ranges: SlickRange_[], caller = 'SlickCellSelectionModel.setSelectedRanges') {\r\n // simple check for: empty selection didn't change, prevent firing onSelectedRangesChanged\r\n if ((!this._ranges || this._ranges.length === 0) && (!ranges || ranges.length === 0)) { return; }\r\n\r\n // if range has not changed, don't fire onSelectedRangesChanged\r\n const rangeHasChanged = !this.rangesAreEqual(this._ranges, ranges);\r\n\r\n this._ranges = this.removeInvalidRanges(ranges);\r\n if (rangeHasChanged) {\r\n // provide extra \"caller\" argument through SlickEventData event to avoid breaking the previous pubsub event structure\r\n // that only accepts an array of selected range `SlickRange[]`, the SlickEventData args will be merged and used later by `onSelectedRowsChanged`\r\n const eventData = new SlickEventData(new CustomEvent('click', { detail: { caller } }), this._ranges);\r\n this.onSelectedRangesChanged.notify(this._ranges, eventData);\r\n }\r\n }\r\n\r\n getSelectedRanges() {\r\n return this._ranges;\r\n }\r\n\r\n refreshSelections() {\r\n this.setSelectedRanges(this.getSelectedRanges());\r\n }\r\n\r\n protected handleBeforeCellRangeSelected(e: SlickEventData_): boolean | void {\r\n if (this._grid.getEditorLock().isActive()) {\r\n e.stopPropagation();\r\n return false;\r\n }\r\n }\r\n\r\n protected handleCellRangeSelected(_e: SlickEventData_, args: { range: SlickRange_; }) {\r\n this._grid.setActiveCell(args.range.fromRow, args.range.fromCell, false, false, true);\r\n this.setSelectedRanges([args.range]);\r\n }\r\n\r\n protected handleActiveCellChange(_e: SlickEventData_, args: OnActiveCellChangedEventArgs) {\r\n this._prevSelectedRow = undefined;\r\n const isCellDefined = Utils.isDefined(args.cell);\r\n const isRowDefined = Utils.isDefined(args.row);\r\n\r\n if (this._options?.selectActiveCell && isRowDefined && isCellDefined) {\r\n this.setSelectedRanges([new SlickRange(args.row, args.cell)]);\r\n } else if (!this._options?.selectActiveCell || (!isRowDefined && !isCellDefined)) {\r\n // clear the previous selection once the cell changes\r\n this.setSelectedRanges([]);\r\n }\r\n }\r\n\r\n protected isKeyAllowed(key: string) {\r\n return ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'PageDown', 'PageUp', 'Home', 'End', 'a', 'A'].some(k => k === key);\r\n }\r\n\r\n protected handleKeyDown(e: SlickEventData_) {\r\n let ranges: SlickRange_[], last: SlickRange_;\r\n const colLn = this._grid.getColumns().length;\r\n const active = this._grid.getActiveCell();\r\n let dataLn = 0;\r\n if (this._dataView && 'getPagingInfo' in this._dataView) {\r\n dataLn = this._dataView?.getPagingInfo().pageSize || this._dataView.getLength();\r\n } else {\r\n dataLn = this._grid.getDataLength();\r\n }\r\n\r\n if (active && (e.shiftKey || e.ctrlKey) && !e.altKey && this.isKeyAllowed(e.key as string)) {\r\n ranges = this.getSelectedRanges().slice();\r\n if (!ranges.length) {\r\n ranges.push(new SlickRange(active.row, active.cell));\r\n }\r\n // keyboard can work with last range only\r\n last = ranges.pop() as SlickRange_;\r\n\r\n // can't handle selection out of active cell\r\n if (!last.contains(active.row, active.cell)) {\r\n last = new SlickRange(active.row, active.cell);\r\n }\r\n\r\n let dRow = last.toRow - last.fromRow;\r\n let dCell = last.toCell - last.fromCell;\r\n let toCell: undefined | number;\r\n let toRow = 0;\r\n\r\n // when using Ctrl+{a, A} we will change our position to cell 0,0 and select all grid cells\r\n if (e.ctrlKey && e.key?.toLowerCase() === 'a') {\r\n this._grid.setActiveCell(0, 0, false, false, true);\r\n active.row = 0;\r\n active.cell = 0;\r\n toCell = colLn - 1;\r\n toRow = dataLn - 1;\r\n }\r\n\r\n // walking direction\r\n const dirRow = active.row === last.fromRow ? 1 : -1;\r\n const dirCell = active.cell === last.fromCell ? 1 : -1;\r\n const isSingleKeyMove = e.key!.startsWith('Arrow');\r\n\r\n if (isSingleKeyMove && !e.ctrlKey) {\r\n // single cell move: (Arrow{Up/ArrowDown/ArrowLeft/ArrowRight})\r\n if (e.key === 'ArrowLeft') {\r\n dCell -= dirCell;\r\n } else if (e.key === 'ArrowRight') {\r\n dCell += dirCell;\r\n } else if (e.key === 'ArrowUp') {\r\n dRow -= dirRow;\r\n } else if (e.key === 'ArrowDown') {\r\n dRow += dirRow;\r\n }\r\n toRow = active.row + dirRow * dRow;\r\n } else {\r\n // multiple cell moves: (Home, End, Page{Up/Down})\r\n if (this._cachedPageRowCount < 1) {\r\n this._cachedPageRowCount = this._grid.getViewportRowCount();\r\n }\r\n if (this._prevSelectedRow === undefined) {\r\n this._prevSelectedRow = active.row;\r\n }\r\n\r\n if ((!e.ctrlKey && e.shiftKey && e.key === 'Home') || (e.ctrlKey && e.shiftKey && e.key === 'ArrowLeft')) {\r\n toCell = 0;\r\n toRow = active.row;\r\n } else if ((!e.ctrlKey && e.shiftKey && e.key === 'End') || (e.ctrlKey && e.shiftKey && e.key === 'ArrowRight')) {\r\n toCell = colLn - 1;\r\n toRow = active.row;\r\n } else if (e.ctrlKey && e.shiftKey && e.key === 'ArrowUp') {\r\n toRow = 0;\r\n } else if (e.ctrlKey && e.shiftKey && e.key === 'ArrowDown') {\r\n toRow = dataLn - 1;\r\n } else if (e.ctrlKey && e.shiftKey && e.key === 'Home') {\r\n toCell = 0;\r\n toRow = 0;\r\n } else if (e.ctrlKey && e.shiftKey && e.key === 'End') {\r\n toCell = colLn - 1;\r\n toRow = dataLn - 1;\r\n } else if (e.key === 'PageUp') {\r\n if (this._prevSelectedRow >= 0) {\r\n toRow = this._prevSelectedRow - this._cachedPageRowCount;\r\n }\r\n if (toRow < 0) {\r\n toRow = 0;\r\n }\r\n } else if (e.key === 'PageDown') {\r\n if (this._prevSelectedRow <= dataLn - 1) {\r\n toRow = this._prevSelectedRow + this._cachedPageRowCount;\r\n }\r\n if (toRow > dataLn - 1) {\r\n toRow = dataLn - 1;\r\n }\r\n }\r\n this._prevSelectedRow = toRow;\r\n }\r\n\r\n // define new selection range\r\n toCell ??= active.cell + dirCell * dCell;\r\n const new_last = new SlickRange(active.row, active.cell, toRow, toCell);\r\n if (this.removeInvalidRanges([new_last]).length) {\r\n ranges.push(new_last);\r\n const viewRow = dirRow > 0 ? new_last.toRow : new_last.fromRow;\r\n const viewCell = dirCell > 0 ? new_last.toCell : new_last.fromCell;\r\n\r\n if (isSingleKeyMove) {\r\n this._grid.scrollRowIntoView(viewRow);\r\n this._grid.scrollCellIntoView(viewRow, viewCell);\r\n } else {\r\n this._grid.scrollRowIntoView(toRow);\r\n this._grid.scrollCellIntoView(toRow, viewCell);\r\n }\r\n } else {\r\n ranges.push(last);\r\n }\r\n\r\n this.setSelectedRanges(ranges);\r\n\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this._prevKeyDown = e.key as string;\r\n }\r\n }\r\n}\r\n\r\n// extend Slick namespace on window object when building as iife\r\nif (IIFE_ONLY && window.Slick) {\r\n Utils.extend(true, window, {\r\n Slick: {\r\n CellSelectionModel: SlickCellSelectionModel\r\n }\r\n });\r\n}"], + "mappings": "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", "names": [] } diff --git a/dist/browser/slick.compositeeditor.js.map b/dist/browser/slick.compositeeditor.js.map index ffa253fd..fc86b6ea 100644 --- a/dist/browser/slick.compositeeditor.js.map +++ b/dist/browser/slick.compositeeditor.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../src/slick.compositeeditor.ts"], - "sourcesContent": ["import type { Column, CompositeEditorOption, Editor, EditorArguments, HtmlElementPosition } from './models/index.js';\r\nimport { Utils as Utils_ } from './slick.core.js';\r\n\r\n// for (iife) load Slick methods from global Slick object, or use imports for (esm)\r\nconst Utils = IIFE_ONLY ? Slick.Utils : Utils_;\r\n\r\n/**\r\n * A composite SlickGrid editor factory.\r\n * Generates an editor that is composed of multiple editors for given columns.\r\n * Individual editors are provided given containers instead of the original cell.\r\n * Validation will be performed on all editors individually and the results will be aggregated into one\r\n * validation result.\r\n *\r\n *\r\n * The returned editor will have its prototype set to CompositeEditor, so you can use the \"instanceof\" check.\r\n *\r\n * NOTE: This doesn't work for detached editors since they will be created and positioned relative to the\r\n * active cell and not the provided container.\r\n *\r\n * @namespace Slick\r\n * @class CompositeEditor\r\n * @constructor\r\n * @param columns {Array} Column definitions from which editors will be pulled.\r\n * @param containers {Array} Container HTMLElements in which editors will be placed.\r\n * @param options {Object} Options hash:\r\n * validationFailedMsg - A generic failed validation message set on the aggregated validation resuls.\r\n * validationMsgPrefix - Add an optional prefix to each validation message (only the ones shown in the modal form, not the ones in the \"errors\")\r\n * modalType - Defaults to \"edit\", modal type can 1 of these 3: (create, edit, mass, mass-selection)\r\n * hide - A function to be called when the grid asks the editor to hide itself.\r\n * show - A function to be called when the grid asks the editor to show itself.\r\n * position - A function to be called when the grid asks the editor to reposition itself.\r\n * destroy - A function to be called when the editor is destroyed.\r\n */\r\nexport function SlickCompositeEditor(columns: Column[], containers: Array, options: CompositeEditorOption) {\r\n const defaultOptions = {\r\n modalType: 'edit', // available type (create, edit, mass)\r\n validationFailedMsg: 'Some of the fields have failed validation',\r\n validationMsgPrefix: null,\r\n show: null,\r\n hide: null,\r\n position: null,\r\n destroy: null,\r\n formValues: {},\r\n editors: {}\r\n };\r\n\r\n const noop = function () { };\r\n\r\n let firstInvalidEditor: Editor | null = null;\r\n\r\n options = Slick.Utils.extend({}, defaultOptions, options);\r\n\r\n function getContainerBox(i: number) {\r\n const c = containers[i];\r\n const offset = Slick.Utils.offset(c);\r\n const w = Slick.Utils.width(c);\r\n const h = Slick.Utils.height(c);\r\n\r\n return {\r\n top: (offset?.top ?? 0),\r\n left: (offset?.left ?? 0),\r\n bottom: (offset?.top ?? 0) + (h || 0),\r\n right: (offset?.left ?? 0) + (w || 0),\r\n width: w,\r\n height: h,\r\n visible: true\r\n };\r\n }\r\n\r\n function editor(args: any[]) {\r\n // @ts-ignore\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context: any = this;\r\n let editors: Array = [];\r\n\r\n function init() {\r\n let newArgs: any = {};\r\n let idx = 0;\r\n while (idx < columns.length) {\r\n if (columns[idx].editor) {\r\n const column = columns[idx];\r\n newArgs = Slick.Utils.extend(false, {}, args);\r\n newArgs.container = containers[idx];\r\n newArgs.column = column;\r\n newArgs.position = getContainerBox(idx);\r\n newArgs.commitChanges = noop;\r\n newArgs.cancelChanges = noop;\r\n newArgs.compositeEditorOptions = options;\r\n newArgs.formValues = {};\r\n\r\n const currentEditor = new (column.editor as any)(newArgs) as Editor & { args: EditorArguments };\r\n options.editors[column.id] = currentEditor; // add every Editor instance refs\r\n editors.push(currentEditor);\r\n }\r\n idx++;\r\n }\r\n\r\n // focus on first input\r\n window.setTimeout(() => {\r\n if (Array.isArray(editors) && editors.length > 0 && typeof editors[0].focus === 'function') {\r\n editors[0].focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n context.destroy = () => {\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n editors[idx].destroy();\r\n idx++;\r\n }\r\n\r\n options.destroy?.();\r\n editors = [];\r\n };\r\n\r\n\r\n context.focus = () => {\r\n // if validation has failed, set the focus to the first invalid editor\r\n (firstInvalidEditor || editors[0]).focus();\r\n };\r\n\r\n context.isValueChanged = () => {\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n if (editors[idx].isValueChanged()) {\r\n return true;\r\n }\r\n idx++;\r\n }\r\n return false;\r\n };\r\n\r\n context.serializeValue = () => {\r\n const serializedValue: any[] = [];\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n serializedValue[idx] = editors[idx].serializeValue();\r\n idx++;\r\n }\r\n return serializedValue;\r\n };\r\n\r\n context.applyValue = (item: any, state: any) => {\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n editors[idx].applyValue(item, state[idx]);\r\n idx++;\r\n }\r\n };\r\n\r\n context.loadValue = (item: any) => {\r\n let idx = 0;\r\n\r\n while (idx < editors.length) {\r\n editors[idx].loadValue(item);\r\n idx++;\r\n }\r\n };\r\n\r\n context.validate = (target: HTMLElement | null) => {\r\n let validationResults;\r\n const errors: any[] = [];\r\n let targetElm = target ? target : null;\r\n\r\n firstInvalidEditor = null;\r\n\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n const columnDef = editors[idx].args?.column ?? {};\r\n if (columnDef) {\r\n let validationElm = document.querySelector(`.item-details-validation.editor-${columnDef.id}`);\r\n let labelElm = document.querySelector(`.item-details-label.editor-${columnDef.id}`);\r\n let editorElm = document.querySelector(`[data-editorid=${columnDef.id}]`);\r\n const validationMsgPrefix = options?.validationMsgPrefix || '';\r\n\r\n if (!targetElm || Slick.Utils.contains(editorElm as HTMLElement, targetElm)) {\r\n validationResults = editors[idx].validate();\r\n\r\n if (!validationResults.valid) {\r\n firstInvalidEditor = editors[idx];\r\n errors.push({\r\n index: idx,\r\n editor: editors[idx],\r\n container: containers[idx],\r\n msg: validationResults.msg\r\n });\r\n\r\n if (validationElm) {\r\n validationElm.textContent = validationMsgPrefix + validationResults.msg;\r\n labelElm?.classList.add('invalid');\r\n editorElm?.classList.add('invalid');\r\n }\r\n } else if (validationElm) {\r\n validationElm.textContent = '';\r\n editorElm?.classList.remove('invalid');\r\n labelElm?.classList.remove('invalid');\r\n }\r\n }\r\n validationElm = null;\r\n labelElm = null;\r\n editorElm = null;\r\n }\r\n idx++;\r\n }\r\n targetElm = null;\r\n\r\n if (errors.length) {\r\n return {\r\n valid: false,\r\n msg: options.validationFailedMsg,\r\n errors\r\n };\r\n } else {\r\n return {\r\n valid: true,\r\n msg: ''\r\n };\r\n }\r\n };\r\n\r\n context.hide = () => {\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n editors[idx]?.hide?.();\r\n idx++;\r\n }\r\n options?.hide?.();\r\n };\r\n\r\n context.show = () => {\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n editors[idx]?.show?.();\r\n idx++;\r\n }\r\n options?.show?.();\r\n };\r\n\r\n context.position = (box: HtmlElementPosition) => {\r\n options?.position?.(box);\r\n };\r\n\r\n init();\r\n }\r\n\r\n // so we can do \"editor instanceof Slick.CompositeEditor\r\n // @ts-ignore\r\n editor.prototype = this;\r\n return editor;\r\n}\r\n\r\n// extend Slick namespace on window object when building as iife\r\nif (IIFE_ONLY && window.Slick) {\r\n Utils.extend(Slick, {\r\n CompositeEditor: SlickCompositeEditor\r\n });\r\n}\r\n"], - "mappings": "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", + "sourcesContent": ["import type { Column, CompositeEditorOption, Editor, EditorArguments, HtmlElementPosition } from './models/index.js';\r\nimport { Utils as Utils_ } from './slick.core.js';\r\n\r\n// for (iife) load Slick methods from global Slick object, or use imports for (esm)\r\nconst Utils = IIFE_ONLY ? Slick.Utils : Utils_;\r\n\r\n/**\r\n * A composite SlickGrid editor factory.\r\n * Generates an editor that is composed of multiple editors for given columns.\r\n * Individual editors are provided given containers instead of the original cell.\r\n * Validation will be performed on all editors individually and the results will be aggregated into one\r\n * validation result.\r\n *\r\n *\r\n * The returned editor will have its prototype set to CompositeEditor, so you can use the \"instanceof\" check.\r\n *\r\n * NOTE: This doesn't work for detached editors since they will be created and positioned relative to the\r\n * active cell and not the provided container.\r\n *\r\n * @namespace Slick\r\n * @class CompositeEditor\r\n * @constructor\r\n * @param columns {Array} Column definitions from which editors will be pulled.\r\n * @param containers {Array} Container HTMLElements in which editors will be placed.\r\n * @param options {Object} Options hash:\r\n * validationFailedMsg - A generic failed validation message set on the aggregated validation resuls.\r\n * validationMsgPrefix - Add an optional prefix to each validation message (only the ones shown in the modal form, not the ones in the \"errors\")\r\n * modalType - Defaults to \"edit\", modal type can 1 of these 3: (create, edit, mass, mass-selection)\r\n * hide - A function to be called when the grid asks the editor to hide itself.\r\n * show - A function to be called when the grid asks the editor to show itself.\r\n * position - A function to be called when the grid asks the editor to reposition itself.\r\n * destroy - A function to be called when the editor is destroyed.\r\n */\r\nexport function SlickCompositeEditor(columns: Column[], containers: Array, options: CompositeEditorOption) {\r\n const defaultOptions = {\r\n modalType: 'edit', // available type (create, edit, mass)\r\n validationFailedMsg: 'Some of the fields have failed validation',\r\n validationMsgPrefix: null,\r\n show: null,\r\n hide: null,\r\n position: null,\r\n destroy: null,\r\n formValues: {},\r\n editors: {}\r\n };\r\n\r\n const noop = function () { };\r\n\r\n let firstInvalidEditor: Editor | null = null;\r\n\r\n options = Slick.Utils.extend({}, defaultOptions, options);\r\n\r\n function getContainerBox(i: number) {\r\n const c = containers[i];\r\n const offset = Slick.Utils.offset(c);\r\n const w = Slick.Utils.width(c);\r\n const h = Slick.Utils.height(c);\r\n\r\n return {\r\n top: (offset?.top ?? 0),\r\n left: (offset?.left ?? 0),\r\n bottom: (offset?.top ?? 0) + (h || 0),\r\n right: (offset?.left ?? 0) + (w || 0),\r\n width: w,\r\n height: h,\r\n visible: true\r\n };\r\n }\r\n\r\n function editor(args: any[]) {\r\n // @ts-ignore\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context: any = this;\r\n let editors: Array = [];\r\n\r\n function init() {\r\n let newArgs: any = {};\r\n let idx = 0;\r\n while (idx < columns.length) {\r\n if (columns[idx].editor) {\r\n const column = columns[idx];\r\n newArgs = Slick.Utils.extend(false, {}, args);\r\n newArgs.container = containers[idx];\r\n newArgs.column = column;\r\n newArgs.position = getContainerBox(idx);\r\n newArgs.commitChanges = noop;\r\n newArgs.cancelChanges = noop;\r\n newArgs.compositeEditorOptions = options;\r\n newArgs.formValues = {};\r\n\r\n const currentEditor = new (column.editor as any)(newArgs) as Editor & { args: EditorArguments };\r\n options.editors[column.id] = currentEditor; // add every Editor instance refs\r\n editors.push(currentEditor);\r\n }\r\n idx++;\r\n }\r\n\r\n // focus on first input\r\n window.setTimeout(() => {\r\n if (Array.isArray(editors) && editors.length > 0 && typeof editors[0].focus === 'function') {\r\n editors[0].focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n context.destroy = () => {\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n editors[idx].destroy();\r\n idx++;\r\n }\r\n\r\n options.destroy?.();\r\n editors = [];\r\n };\r\n\r\n\r\n context.focus = () => {\r\n // if validation has failed, set the focus to the first invalid editor\r\n (firstInvalidEditor || editors[0]).focus();\r\n };\r\n\r\n context.isValueChanged = () => {\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n if (editors[idx].isValueChanged()) {\r\n return true;\r\n }\r\n idx++;\r\n }\r\n return false;\r\n };\r\n\r\n context.serializeValue = () => {\r\n const serializedValue: any[] = [];\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n serializedValue[idx] = editors[idx].serializeValue();\r\n idx++;\r\n }\r\n return serializedValue;\r\n };\r\n\r\n context.applyValue = (item: any, state: any) => {\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n editors[idx].applyValue(item, state[idx]);\r\n idx++;\r\n }\r\n };\r\n\r\n context.loadValue = (item: any) => {\r\n let idx = 0;\r\n\r\n while (idx < editors.length) {\r\n editors[idx].loadValue(item);\r\n idx++;\r\n }\r\n };\r\n\r\n context.validate = (target: HTMLElement | null) => {\r\n let validationResults;\r\n const errors: any[] = [];\r\n let targetElm = target ? target : null;\r\n\r\n firstInvalidEditor = null;\r\n\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n const columnDef = editors[idx].args?.column ?? {};\r\n if (columnDef) {\r\n let validationElm = document.querySelector(`.item-details-validation.editor-${columnDef.id}`);\r\n let labelElm = document.querySelector(`.item-details-label.editor-${columnDef.id}`);\r\n let editorElm = document.querySelector(`[data-editorid=${columnDef.id}]`);\r\n const validationMsgPrefix = options?.validationMsgPrefix || '';\r\n\r\n if (!targetElm || Slick.Utils.contains(editorElm as HTMLElement, targetElm)) {\r\n validationResults = editors[idx].validate();\r\n\r\n if (!validationResults.valid) {\r\n firstInvalidEditor = editors[idx];\r\n errors.push({\r\n index: idx,\r\n editor: editors[idx],\r\n container: containers[idx],\r\n msg: validationResults.msg\r\n });\r\n\r\n if (validationElm) {\r\n validationElm.textContent = validationMsgPrefix + validationResults.msg;\r\n labelElm?.classList.add('invalid');\r\n editorElm?.classList.add('invalid');\r\n }\r\n } else if (validationElm) {\r\n validationElm.textContent = '';\r\n editorElm?.classList.remove('invalid');\r\n labelElm?.classList.remove('invalid');\r\n }\r\n }\r\n validationElm = null;\r\n labelElm = null;\r\n editorElm = null;\r\n }\r\n idx++;\r\n }\r\n targetElm = null;\r\n\r\n if (errors.length) {\r\n return {\r\n valid: false,\r\n msg: options.validationFailedMsg,\r\n errors\r\n };\r\n }\r\n\r\n return {\r\n valid: true,\r\n msg: ''\r\n };\r\n };\r\n\r\n context.hide = () => {\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n editors[idx]?.hide?.();\r\n idx++;\r\n }\r\n options?.hide?.();\r\n };\r\n\r\n context.show = () => {\r\n let idx = 0;\r\n while (idx < editors.length) {\r\n editors[idx]?.show?.();\r\n idx++;\r\n }\r\n options?.show?.();\r\n };\r\n\r\n context.position = (box: HtmlElementPosition) => {\r\n options?.position?.(box);\r\n };\r\n\r\n init();\r\n }\r\n\r\n // so we can do \"editor instanceof Slick.CompositeEditor\r\n // @ts-ignore\r\n editor.prototype = this;\r\n return editor;\r\n}\r\n\r\n// extend Slick namespace on window object when building as iife\r\nif (IIFE_ONLY && window.Slick) {\r\n Utils.extend(Slick, {\r\n CompositeEditor: SlickCompositeEditor\r\n });\r\n}\r\n"], + "mappings": "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", "names": [] } diff --git a/dist/browser/slick.dataview.js b/dist/browser/slick.dataview.js index dc5f7c90..f54e31ec 100644 --- a/dist/browser/slick.dataview.js +++ b/dist/browser/slick.dataview.js @@ -9,6 +9,7 @@ constructor(options, externalPubSub) { this.externalPubSub = externalPubSub; __publicField(this, "defaults", { + globalItemMetadataProvider: null, groupItemMetadataProvider: null, inlineFilters: !1, useCSPSafeFilter: !1 @@ -452,9 +453,10 @@ } else item != null && item.__groupTotals && !item.initialized && this.calculateTotals(item); return item; } - getItemMetadata(i) { - let item = this.rows[i]; - return item === void 0 ? null : item.__group ? this._options.groupItemMetadataProvider.getGroupRowMetadata(item) : item.__groupTotals ? this._options.groupItemMetadataProvider.getTotalsRowMetadata(item) : null; + getItemMetadata(row) { + var _a2, _b2, _c; + let item = this.rows[row]; + return item === void 0 ? null : (_a2 = this._options.globalItemMetadataProvider) != null && _a2.getRowMetadata ? this._options.globalItemMetadataProvider.getRowMetadata(item, row) : item.__group && ((_b2 = this._options.groupItemMetadataProvider) != null && _b2.getGroupRowMetadata) ? this._options.groupItemMetadataProvider.getGroupRowMetadata(item, row) : item.__groupTotals && ((_c = this._options.groupItemMetadataProvider) != null && _c.getTotalsRowMetadata) ? this._options.groupItemMetadataProvider.getTotalsRowMetadata(item, row) : null; } expandCollapseAllGroups(level, collapse) { if (Utils.isDefined(level)) diff --git a/dist/browser/slick.dataview.js.map b/dist/browser/slick.dataview.js.map index 122349c5..d0ea48d5 100644 --- a/dist/browser/slick.dataview.js.map +++ b/dist/browser/slick.dataview.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../src/slick.dataview.ts"], - "sourcesContent": ["import type {\r\n Aggregator,\r\n AnyFunction,\r\n CssStyleHash,\r\n CustomDataView,\r\n DataViewHints,\r\n Grouping,\r\n GroupingFormatterItem,\r\n ItemMetadata,\r\n OnGroupCollapsedEventArgs,\r\n OnGroupExpandedEventArgs,\r\n OnRowCountChangedEventArgs,\r\n OnRowsChangedEventArgs,\r\n OnRowsOrCountChangedEventArgs,\r\n OnSelectedRowIdsChangedEventArgs,\r\n OnSetItemsCalledEventArgs,\r\n PagingInfo,\r\n SlickGridModel,\r\n} from './models/index.js';\r\nimport {\r\n type BasePubSub,\r\n SlickEvent as SlickEvent_,\r\n SlickEventData as SlickEventData_,\r\n SlickGroup as SlickGroup_,\r\n SlickGroupTotals as SlickGroupTotals_,\r\n Utils as Utils_,\r\n type SlickNonDataItem,\r\n} from './slick.core.js';\r\nimport { SlickGroupItemMetadataProvider as SlickGroupItemMetadataProvider_ } from './slick.groupitemmetadataprovider.js';\r\n\r\n// for (iife) load Slick methods from global Slick object, or use imports for (esm)\r\nconst SlickEvent = IIFE_ONLY ? Slick.Event : SlickEvent_;\r\nconst SlickEventData = IIFE_ONLY ? Slick.EventData : SlickEventData_;\r\nconst SlickGroup = IIFE_ONLY ? Slick.Group : SlickGroup_;\r\nconst SlickGroupTotals = IIFE_ONLY ? Slick.GroupTotals : SlickGroupTotals_;\r\nconst Utils = IIFE_ONLY ? Slick.Utils : Utils_;\r\nconst SlickGroupItemMetadataProvider = IIFE_ONLY ? Slick.Data?.GroupItemMetadataProvider ?? {} : SlickGroupItemMetadataProvider_;\r\n\r\nexport interface DataViewOption {\r\n /** Optionally provide a GroupItemMetadataProvider in order to use Grouping/DraggableGrouping features */\r\n groupItemMetadataProvider: SlickGroupItemMetadataProvider_ | null;\r\n\r\n /** defaults to false, are we using inline filters? */\r\n inlineFilters: boolean;\r\n\r\n /**\r\n * defaults to false, option to use CSP Safe approach,\r\n * Note: it is an opt-in option because it is slightly slower (perf impact) when compared to the non-CSP safe approach.\r\n */\r\n useCSPSafeFilter: boolean;\r\n}\r\nexport type FilterFn = (item: T, args: any) => boolean;\r\nexport type FilterCspFn = (item: T[], args: any) => T[];\r\nexport type FilterWithCspCachingFn = (item: T[], args: any, filterCache: any[]) => T[];\r\nexport type DataIdType = number | string;\r\nexport type SlickDataItem = SlickNonDataItem | SlickGroup_ | SlickGroupTotals_ | any;\r\nexport type GroupGetterFn = (val: any) => string | number;\r\n\r\n/**\r\n * A simple Model implementation.\r\n * Provides a filtered view of the underlying data.\r\n * Relies on the data item having an \"id\" property uniquely identifying it.\r\n */\r\nexport class SlickDataView implements CustomDataView {\r\n protected defaults: DataViewOption = {\r\n groupItemMetadataProvider: null,\r\n inlineFilters: false,\r\n useCSPSafeFilter: false,\r\n };\r\n\r\n // private\r\n protected idProperty = 'id'; // property holding a unique row id\r\n protected items: TData[] = []; // data by index\r\n protected rows: TData[] = []; // data by row\r\n protected idxById = new Map(); // indexes by id\r\n protected rowsById: { [id: DataIdType]: number } | undefined = undefined; // rows by id; lazy-calculated\r\n protected filter: FilterFn | null = null; // filter function\r\n protected filterCSPSafe: FilterFn | null = null; // filter function\r\n protected updated: ({ [id: DataIdType]: boolean }) | null = null; // updated item ids\r\n protected suspend = false; // suspends the recalculation\r\n protected isBulkSuspend = false; // delays protectedious operations like the\r\n // index update and delete to efficient\r\n // versions at endUpdate\r\n protected bulkDeleteIds = new Map();\r\n protected sortAsc: boolean | undefined = true;\r\n protected fastSortField?: string | null | (() => string);\r\n protected sortComparer!: ((a: TData, b: TData) => number);\r\n protected refreshHints: DataViewHints = {};\r\n protected prevRefreshHints: DataViewHints = {};\r\n protected filterArgs: any;\r\n protected filteredItems: TData[] = [];\r\n protected compiledFilter?: FilterFn | null;\r\n protected compiledFilterCSPSafe?: FilterCspFn | null;\r\n protected compiledFilterWithCaching?: FilterFn | null;\r\n protected compiledFilterWithCachingCSPSafe?: FilterWithCspCachingFn | null;\r\n protected filterCache: any[] = [];\r\n protected _grid?: SlickGridModel; // grid object will be defined only after using \"syncGridSelection()\" method\"\r\n\r\n // grouping\r\n protected groupingInfoDefaults: Grouping = {\r\n getter: undefined,\r\n formatter: undefined,\r\n comparer: (a: { value: any; }, b: { value: any; }) => (a.value === b.value ? 0 : (a.value > b.value ? 1 : -1)),\r\n predefinedValues: [],\r\n aggregators: [],\r\n aggregateEmpty: false,\r\n aggregateCollapsed: false,\r\n aggregateChildGroups: false,\r\n collapsed: false,\r\n displayTotalsRow: true,\r\n lazyTotalsCalculation: false\r\n };\r\n protected groupingInfos: Array = [];\r\n protected groups: SlickGroup_[] = [];\r\n protected toggledGroupsByLevel: any[] = [];\r\n protected groupingDelimiter = ':|:';\r\n protected selectedRowIds: DataIdType[] = [];\r\n protected preSelectedRowIdsChangeFn?: (args?: any) => void;\r\n\r\n protected pagesize = 0;\r\n protected pagenum = 0;\r\n protected totalRows = 0;\r\n protected _options: DataViewOption;\r\n protected _container?: HTMLElement;\r\n\r\n // public events\r\n onBeforePagingInfoChanged: SlickEvent_;\r\n onGroupExpanded: SlickEvent_;\r\n onGroupCollapsed: SlickEvent_;\r\n onPagingInfoChanged: SlickEvent_;\r\n onRowCountChanged: SlickEvent_;\r\n onRowsChanged: SlickEvent_;\r\n onRowsOrCountChanged: SlickEvent_;\r\n onSelectedRowIdsChanged: SlickEvent_;\r\n onSetItemsCalled: SlickEvent_;\r\n\r\n constructor(options?: Partial, protected externalPubSub?: BasePubSub) {\r\n this.onBeforePagingInfoChanged = new SlickEvent('onBeforePagingInfoChanged', externalPubSub);\r\n this.onGroupExpanded = new SlickEvent('onGroupExpanded', externalPubSub);\r\n this.onGroupCollapsed = new SlickEvent('onGroupCollapsed', externalPubSub);\r\n this.onPagingInfoChanged = new SlickEvent('onPagingInfoChanged', externalPubSub);\r\n this.onRowCountChanged = new SlickEvent('onRowCountChanged', externalPubSub);\r\n this.onRowsChanged = new SlickEvent('onRowsChanged', externalPubSub);\r\n this.onRowsOrCountChanged = new SlickEvent('onRowsOrCountChanged', externalPubSub);\r\n this.onSelectedRowIdsChanged = new SlickEvent('onSelectedRowIdsChanged', externalPubSub);\r\n this.onSetItemsCalled = new SlickEvent('onSetItemsCalled', externalPubSub);\r\n\r\n this._options = Utils.extend(true, {}, this.defaults, options);\r\n }\r\n\r\n /**\r\n * Begins a bached update of the items in the data view.\r\n * including deletes and the related events are postponed to the endUpdate call.\r\n * As certain operations are postponed during this update, some methods might not\r\n * deliver fully consistent information.\r\n * @param {Boolean} [bulkUpdate] - if set to true, most data view modifications\r\n */\r\n beginUpdate(bulkUpdate?: boolean) {\r\n this.suspend = true;\r\n this.isBulkSuspend = bulkUpdate === true;\r\n }\r\n\r\n endUpdate() {\r\n const wasBulkSuspend = this.isBulkSuspend;\r\n this.isBulkSuspend = false;\r\n this.suspend = false;\r\n if (wasBulkSuspend) {\r\n this.processBulkDelete();\r\n this.ensureIdUniqueness();\r\n }\r\n this.refresh();\r\n }\r\n\r\n destroy() {\r\n this.items = [];\r\n this.idxById = null as any;\r\n this.rowsById = null as any;\r\n this.filter = null as any;\r\n this.filterCSPSafe = null as any;\r\n this.updated = null as any;\r\n this.sortComparer = null as any;\r\n this.filterCache = [];\r\n this.filteredItems = [];\r\n this.compiledFilter = null;\r\n this.compiledFilterCSPSafe = null;\r\n this.compiledFilterWithCaching = null;\r\n this.compiledFilterWithCachingCSPSafe = null;\r\n\r\n if (this._grid && this._grid.onSelectedRowsChanged && this._grid.onCellCssStylesChanged) {\r\n this._grid.onSelectedRowsChanged.unsubscribe();\r\n this._grid.onCellCssStylesChanged.unsubscribe();\r\n }\r\n if (this.onRowsOrCountChanged) {\r\n this.onRowsOrCountChanged.unsubscribe();\r\n }\r\n }\r\n\r\n /** provide some refresh hints as to what to rows needs refresh */\r\n setRefreshHints(hints: DataViewHints) {\r\n this.refreshHints = hints;\r\n }\r\n\r\n /** get extra filter arguments of the filter method */\r\n getFilterArgs() {\r\n return this.filterArgs;\r\n }\r\n\r\n /** add extra filter arguments to the filter method */\r\n setFilterArgs(args: any) {\r\n this.filterArgs = args;\r\n }\r\n\r\n /**\r\n * Processes all delete requests placed during bulk update\r\n * by recomputing the items and idxById members.\r\n */\r\n protected processBulkDelete() {\r\n if (!this.idxById) { return; }\r\n\r\n // the bulk update is processed by\r\n // recomputing the whole items array and the index lookup in one go.\r\n // this is done by placing the not-deleted items\r\n // from left to right into the array and shrink the array the the new\r\n // size afterwards.\r\n // see https://github.com/6pac/SlickGrid/issues/571 for further details.\r\n\r\n let id: DataIdType, item, newIdx = 0;\r\n for (let i = 0, l = this.items.length; i < l; i++) {\r\n item = this.items[i];\r\n id = item[this.idProperty as keyof TData] as DataIdType;\r\n if (id === undefined) {\r\n throw new Error(`[SlickGrid DataView] Each data element must implement a unique 'id' property`);\r\n }\r\n\r\n // if items have been marked as deleted we skip them for the new final items array\r\n // and we remove them from the lookup table.\r\n if (this.bulkDeleteIds.has(id)) {\r\n this.idxById.delete(id);\r\n } else {\r\n // for items which are not deleted, we add them to the\r\n // next free position in the array and register the index in the lookup.\r\n this.items[newIdx] = item;\r\n this.idxById.set(id, newIdx);\r\n ++newIdx;\r\n }\r\n }\r\n\r\n // here we shrink down the full item array to the ones actually\r\n // inserted in the cleanup loop above.\r\n this.items.length = newIdx;\r\n // and finally cleanup the deleted ids to start cleanly on the next update.\r\n this.bulkDeleteIds = new Map();\r\n }\r\n\r\n protected updateIdxById(startingIndex?: number) {\r\n if (this.isBulkSuspend || !this.idxById) { // during bulk update we do not reorganize\r\n return;\r\n }\r\n startingIndex = startingIndex || 0;\r\n let id: DataIdType;\r\n for (let i = startingIndex, l = this.items.length; i < l; i++) {\r\n id = this.items[i][this.idProperty as keyof TData] as DataIdType;\r\n if (id === undefined) {\r\n throw new Error(`[SlickGrid DataView] Each data element must implement a unique 'id' property`);\r\n }\r\n this.idxById.set(id, i);\r\n }\r\n }\r\n\r\n protected ensureIdUniqueness() {\r\n if (this.isBulkSuspend || !this.idxById) { // during bulk update we do not reorganize\r\n return;\r\n }\r\n let id: DataIdType;\r\n for (let i = 0, l = this.items.length; i < l; i++) {\r\n id = this.items[i][this.idProperty as keyof TData] as DataIdType;\r\n if (id === undefined || this.idxById.get(id) !== i) {\r\n throw new Error(`[SlickGrid DataView] Each data element must implement a unique 'id' property`);\r\n }\r\n }\r\n }\r\n\r\n /** Get all DataView Items */\r\n getItems() {\r\n return this.items;\r\n }\r\n\r\n /** Get the DataView Id property name to use (defaults to \"Id\" but could be customized to something else when instantiating the DataView) */\r\n getIdPropertyName() {\r\n return this.idProperty;\r\n }\r\n\r\n /**\r\n * Set the Items with a new Dataset and optionally pass a different Id property name\r\n * @param {Array<*>} data - array of data\r\n * @param {String} [objectIdProperty] - optional id property to use as primary id\r\n */\r\n setItems(data: TData[], objectIdProperty?: string) {\r\n if (objectIdProperty !== undefined) {\r\n this.idProperty = objectIdProperty;\r\n }\r\n this.items = this.filteredItems = data;\r\n this.onSetItemsCalled.notify({ idProperty: this.idProperty, itemCount: this.items.length }, null, this);\r\n this.idxById = new Map();\r\n this.updateIdxById();\r\n this.ensureIdUniqueness();\r\n this.refresh();\r\n }\r\n\r\n /** Set Paging Options */\r\n setPagingOptions(args: Partial) {\r\n if (this.onBeforePagingInfoChanged.notify(this.getPagingInfo(), null, this).getReturnValue() !== false) {\r\n if (Utils.isDefined(args.pageSize)) {\r\n this.pagesize = args.pageSize;\r\n this.pagenum = this.pagesize ? Math.min(this.pagenum, Math.max(0, Math.ceil(this.totalRows / this.pagesize) - 1)) : 0;\r\n }\r\n\r\n if (Utils.isDefined(args.pageNum)) {\r\n this.pagenum = Math.min(args.pageNum, Math.max(0, Math.ceil(this.totalRows / this.pagesize) - 1));\r\n }\r\n\r\n this.onPagingInfoChanged.notify(this.getPagingInfo(), null, this);\r\n\r\n this.refresh();\r\n }\r\n }\r\n\r\n /** Get Paging Options */\r\n getPagingInfo(): PagingInfo {\r\n const totalPages = this.pagesize ? Math.max(1, Math.ceil(this.totalRows / this.pagesize)) : 1;\r\n return { pageSize: this.pagesize, pageNum: this.pagenum, totalRows: this.totalRows, totalPages, dataView: this as SlickDataView };\r\n }\r\n\r\n /** Sort Method to use by the DataView */\r\n sort(comparer: (a: TData, b: TData) => number, ascending?: boolean) {\r\n this.sortAsc = ascending;\r\n this.sortComparer = comparer;\r\n this.fastSortField = null;\r\n if (ascending === false) {\r\n this.items.reverse();\r\n }\r\n this.items.sort(comparer);\r\n if (ascending === false) {\r\n this.items.reverse();\r\n }\r\n this.idxById = new Map();\r\n this.updateIdxById();\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * @deprecated, to be more removed in next major since IE is no longer supported and this is no longer useful.\r\n * Provides a workaround for the extremely slow sorting in IE.\r\n * Does a [lexicographic] sort on a give column by temporarily overriding Object.prototype.toString\r\n * to return the value of that field and then doing a native Array.sort().\r\n */\r\n fastSort(field: string | (() => string), ascending?: boolean) {\r\n this.sortAsc = ascending;\r\n this.fastSortField = field;\r\n this.sortComparer = null as any;\r\n const oldToString = Object.prototype.toString;\r\n Object.prototype.toString = (typeof field === 'function') ? field : function () {\r\n // @ts-ignore\r\n return this[field];\r\n };\r\n // an extra reversal for descending sort keeps the sort stable\r\n // (assuming a stable native sort implementation, which isn't true in some cases)\r\n if (ascending === false) {\r\n this.items.reverse();\r\n }\r\n this.items.sort();\r\n Object.prototype.toString = oldToString;\r\n if (ascending === false) {\r\n this.items.reverse();\r\n }\r\n this.idxById = new Map();\r\n this.updateIdxById();\r\n this.refresh();\r\n }\r\n\r\n /** Re-Sort the dataset */\r\n reSort() {\r\n if (this.sortComparer) {\r\n this.sort(this.sortComparer, this.sortAsc);\r\n } else if (this.fastSortField) {\r\n this.fastSort(this.fastSortField, this.sortAsc);\r\n }\r\n }\r\n\r\n /** Get only the DataView filtered items */\r\n getFilteredItems() {\r\n return this.filteredItems as T[];\r\n }\r\n\r\n /** Get the array length (count) of only the DataView filtered items */\r\n getFilteredItemCount() {\r\n return this.filteredItems.length;\r\n }\r\n\r\n /** Get current Filter used by the DataView */\r\n getFilter() {\r\n return this._options.useCSPSafeFilter ? this.filterCSPSafe : this.filter;\r\n }\r\n\r\n /**\r\n * Set a Filter that will be used by the DataView\r\n * @param {Function} fn - filter callback function\r\n */\r\n setFilter(filterFn: FilterFn) {\r\n this.filterCSPSafe = filterFn;\r\n this.filter = filterFn;\r\n if (this._options.inlineFilters) {\r\n this.compiledFilterCSPSafe = this.compileFilterCSPSafe;\r\n this.compiledFilterWithCachingCSPSafe = this.compileFilterWithCachingCSPSafe;\r\n this.compiledFilter = this.compileFilter(this._options.useCSPSafeFilter);\r\n this.compiledFilterWithCaching = this.compileFilterWithCaching(this._options.useCSPSafeFilter);\r\n }\r\n this.refresh();\r\n }\r\n\r\n /** Get current Grouping info */\r\n getGrouping(): Grouping[] {\r\n return this.groupingInfos;\r\n }\r\n\r\n /** Set some Grouping */\r\n setGrouping(groupingInfo: Grouping | Grouping[]) {\r\n if (!this._options.groupItemMetadataProvider) {\r\n this._options.groupItemMetadataProvider = new SlickGroupItemMetadataProvider();\r\n }\r\n\r\n this.groups = [];\r\n this.toggledGroupsByLevel = [];\r\n groupingInfo = groupingInfo || [];\r\n this.groupingInfos = ((groupingInfo instanceof Array) ? groupingInfo : [groupingInfo]) as any;\r\n\r\n for (let i = 0; i < this.groupingInfos.length; i++) {\r\n const gi = this.groupingInfos[i] = Utils.extend(true, {}, this.groupingInfoDefaults, this.groupingInfos[i]);\r\n gi.getterIsAFn = typeof gi.getter === 'function';\r\n\r\n // pre-compile accumulator loops\r\n gi.compiledAccumulators = [];\r\n let idx = gi.aggregators.length;\r\n while (idx--) {\r\n gi.compiledAccumulators[idx] = this.compileAccumulatorLoopCSPSafe(gi.aggregators[idx]);\r\n }\r\n\r\n this.toggledGroupsByLevel[i] = {};\r\n }\r\n\r\n this.refresh();\r\n }\r\n\r\n /** Get an item in the DataView by its row index */\r\n getItemByIdx(i: number) {\r\n return this.items[i] as T;\r\n }\r\n\r\n /** Get row index in the DataView by its Id */\r\n getIdxById(id: DataIdType) {\r\n return this.idxById?.get(id);\r\n }\r\n\r\n protected ensureRowsByIdCache() {\r\n if (!this.rowsById) {\r\n this.rowsById = {};\r\n for (let i = 0, l = this.rows.length; i < l; i++) {\r\n this.rowsById[this.rows[i][this.idProperty as keyof TData] as DataIdType] = i;\r\n }\r\n }\r\n }\r\n\r\n /** Get row number in the grid by its item object */\r\n getRowByItem(item: TData) {\r\n this.ensureRowsByIdCache();\r\n return this.rowsById?.[item[this.idProperty as keyof TData] as DataIdType];\r\n }\r\n\r\n /** Get row number in the grid by its Id */\r\n getRowById(id: DataIdType) {\r\n this.ensureRowsByIdCache();\r\n return this.rowsById?.[id];\r\n }\r\n\r\n /** Get an item in the DataView by its Id */\r\n getItemById(id: DataIdType) {\r\n return this.items[(this.idxById.get(id) as number)] as T;\r\n }\r\n\r\n /** From the items array provided, return the mapped rows */\r\n mapItemsToRows(itemArray: TData[]) {\r\n const rows: number[] = [];\r\n this.ensureRowsByIdCache();\r\n for (let i = 0, l = itemArray.length; i < l; i++) {\r\n const row = this.rowsById?.[itemArray[i][this.idProperty as keyof TData] as DataIdType];\r\n if (Utils.isDefined(row)) {\r\n rows[rows.length] = row as number;\r\n }\r\n }\r\n return rows;\r\n }\r\n\r\n /** From the Ids array provided, return the mapped rows */\r\n mapIdsToRows(idArray: DataIdType[]) {\r\n const rows: number[] = [];\r\n this.ensureRowsByIdCache();\r\n for (let i = 0, l = idArray.length; i < l; i++) {\r\n const row = this.rowsById?.[idArray[i]];\r\n if (Utils.isDefined(row)) {\r\n rows[rows.length] = row as number;\r\n }\r\n }\r\n return rows;\r\n }\r\n\r\n /** From the rows array provided, return the mapped Ids */\r\n mapRowsToIds(rowArray: number[]) {\r\n const ids: DataIdType[] = [];\r\n for (let i = 0, l = rowArray.length; i < l; i++) {\r\n if (rowArray[i] < this.rows.length) {\r\n const rowItem = this.rows[rowArray[i]];\r\n ids[ids.length] = rowItem![this.idProperty as keyof TData] as DataIdType;\r\n }\r\n }\r\n return ids;\r\n }\r\n\r\n /**\r\n * Performs the update operations of a single item by id without\r\n * triggering any events or refresh operations.\r\n * @param id The new id of the item.\r\n * @param item The item which should be the new value for the given id.\r\n */\r\n updateSingleItem(id: DataIdType, item: TData) {\r\n if (!this.idxById) { return; }\r\n\r\n // see also https://github.com/mleibman/SlickGrid/issues/1082\r\n if (!this.idxById.has(id)) {\r\n throw new Error('[SlickGrid DataView] Invalid id');\r\n }\r\n\r\n // What if the specified item also has an updated idProperty?\r\n // Then we'll have to update the index as well, and possibly the `updated` cache too.\r\n if (id !== item[this.idProperty as keyof TData]) {\r\n // make sure the new id is unique:\r\n const newId = item[this.idProperty as keyof TData] as DataIdType;\r\n if (!Utils.isDefined(newId)) {\r\n throw new Error('[SlickGrid DataView] Cannot update item to associate with a null id');\r\n }\r\n if (this.idxById.has(newId)) {\r\n throw new Error('[SlickGrid DataView] Cannot update item to associate with a non-unique id');\r\n }\r\n this.idxById.set(newId, this.idxById.get(id) as number);\r\n this.idxById.delete(id);\r\n\r\n // Also update the `updated` hashtable/markercache? Yes, `recalc()` inside `refresh()` needs that one!\r\n if (this.updated?.[id]) {\r\n delete this.updated[id];\r\n }\r\n\r\n // Also update the row indexes? no need since the `refresh()`, further down, blows away the `rowsById[]` cache!\r\n\r\n id = newId;\r\n }\r\n this.items[this.idxById.get(id) as number] = item;\r\n\r\n // Also update the rows? no need since the `refresh()`, further down, blows away the `rows[]` cache and recalculates it via `recalc()`!\r\n\r\n if (!this.updated) {\r\n this.updated = {};\r\n }\r\n this.updated[id] = true;\r\n }\r\n\r\n /**\r\n * Updates a single item in the data view given the id and new value.\r\n * @param id The new id of the item.\r\n * @param item The item which should be the new value for the given id.\r\n */\r\n updateItem(id: DataIdType, item: T) {\r\n this.updateSingleItem(id, item);\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Updates multiple items in the data view given the new ids and new values.\r\n * @param id {Array} The array of new ids which is in the same order as the items.\r\n * @param newItems {Array} The new items that should be set in the data view for the given ids.\r\n */\r\n updateItems(ids: DataIdType[], newItems: T[]) {\r\n if (ids.length !== newItems.length) {\r\n throw new Error('[SlickGrid DataView] Mismatch on the length of ids and items provided to update');\r\n }\r\n for (let i = 0, l = newItems.length; i < l; i++) {\r\n this.updateSingleItem(ids[i], newItems[i]);\r\n }\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Inserts a single item into the data view at the given position.\r\n * @param insertBefore {Number} The 0-based index before which the item should be inserted.\r\n * @param item The item to insert.\r\n */\r\n insertItem(insertBefore: number, item: TData) {\r\n this.items.splice(insertBefore, 0, item);\r\n this.updateIdxById(insertBefore);\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Inserts multiple items into the data view at the given position.\r\n * @param insertBefore {Number} The 0-based index before which the items should be inserted.\r\n * @param newItems {Array} The items to insert.\r\n */\r\n insertItems(insertBefore: number, newItems: TData[]) {\r\n // @ts-ignore\r\n Array.prototype.splice.apply(this.items, [insertBefore, 0].concat(newItems));\r\n this.updateIdxById(insertBefore);\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Adds a single item at the end of the data view.\r\n * @param item The item to add at the end.\r\n */\r\n addItem(item: TData) {\r\n this.items.push(item);\r\n this.updateIdxById(this.items.length - 1);\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Adds multiple items at the end of the data view.\r\n * @param {Array} newItems The items to add at the end.\r\n */\r\n addItems(newItems: TData[]) {\r\n this.items = this.items.concat(newItems);\r\n this.updateIdxById(this.items.length - newItems.length);\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Deletes a single item identified by the given id from the data view.\r\n * @param {String|Number} id The id identifying the object to delete.\r\n */\r\n deleteItem(id: DataIdType) {\r\n if (!this.idxById) { return; }\r\n if (this.isBulkSuspend) {\r\n this.bulkDeleteIds.set(id, true);\r\n } else {\r\n const idx = this.idxById.get(id);\r\n if (idx === undefined) {\r\n throw new Error('[SlickGrid DataView] Invalid id');\r\n }\r\n this.idxById.delete(id);\r\n this.items.splice(idx, 1);\r\n this.updateIdxById(idx);\r\n this.refresh();\r\n }\r\n }\r\n\r\n /**\r\n * Deletes multiple item identified by the given ids from the data view.\r\n * @param {Array} ids The ids of the items to delete.\r\n */\r\n deleteItems(ids: DataIdType[]) {\r\n if (ids.length === 0 || !this.idxById) {\r\n return;\r\n }\r\n\r\n if (this.isBulkSuspend) {\r\n for (let i = 0, l = ids.length; i < l; i++) {\r\n const id = ids[i];\r\n const idx = this.idxById.get(id);\r\n if (idx === undefined) {\r\n throw new Error('[SlickGrid DataView] Invalid id');\r\n }\r\n this.bulkDeleteIds.set(id, true);\r\n }\r\n } else {\r\n // collect all indexes\r\n const indexesToDelete: number[] = [];\r\n for (let i = 0, l = ids.length; i < l; i++) {\r\n const id = ids[i];\r\n const idx = this.idxById.get(id);\r\n if (idx === undefined) {\r\n throw new Error('[SlickGrid DataView] Invalid id');\r\n }\r\n this.idxById.delete(id);\r\n indexesToDelete.push(idx);\r\n }\r\n\r\n // Remove from back to front\r\n indexesToDelete.sort();\r\n for (let i = indexesToDelete.length - 1; i >= 0; --i) {\r\n this.items.splice(indexesToDelete[i], 1);\r\n }\r\n\r\n // update lookup from front to back\r\n this.updateIdxById(indexesToDelete[0]);\r\n this.refresh();\r\n }\r\n }\r\n\r\n /** Add an item in a sorted dataset (a Sort function must be defined) */\r\n sortedAddItem(item: TData) {\r\n if (!this.sortComparer) {\r\n throw new Error('[SlickGrid DataView] sortedAddItem() requires a sort comparer, use sort()');\r\n }\r\n this.insertItem(this.sortedIndex(item), item);\r\n }\r\n\r\n /** Update an item in a sorted dataset (a Sort function must be defined) */\r\n sortedUpdateItem(id: string | number, item: TData) {\r\n if (!this.idxById) { return; }\r\n if (!this.idxById.has(id) || id !== item[this.idProperty as keyof TData]) {\r\n throw new Error('[SlickGrid DataView] Invalid or non-matching id ' + this.idxById.get(id));\r\n }\r\n if (!this.sortComparer) {\r\n throw new Error('[SlickGrid DataView] sortedUpdateItem() requires a sort comparer, use sort()');\r\n }\r\n const oldItem = this.getItemById(id);\r\n if (this.sortComparer(oldItem, item) !== 0) {\r\n // item affects sorting -> must use sorted add\r\n this.deleteItem(id);\r\n this.sortedAddItem(item);\r\n } else { // update does not affect sorting -> regular update works fine\r\n this.updateItem(id, item);\r\n }\r\n }\r\n\r\n protected sortedIndex(searchItem: TData) {\r\n let low = 0;\r\n let high = this.items.length;\r\n\r\n while (low < high) {\r\n const mid = low + high >>> 1;\r\n if (this.sortComparer(this.items[mid], searchItem) === -1) {\r\n low = mid + 1;\r\n } else {\r\n high = mid;\r\n }\r\n }\r\n return low;\r\n }\r\n\r\n /** Get item count, that is the full dataset lenght of the DataView */\r\n getItemCount() {\r\n return this.items.length;\r\n }\r\n\r\n /** Get row count (rows displayed in current page) */\r\n getLength() {\r\n return this.rows.length;\r\n }\r\n\r\n /** Retrieve an item from the DataView at specific index */\r\n getItem(i: number) {\r\n const item = this.rows[i] as T;\r\n\r\n // if this is a group row, make sure totals are calculated and update the title\r\n if ((item as SlickGroup_)?.__group && (item as SlickGroup_).totals && !(item as SlickGroup_).totals?.initialized) {\r\n const gi = this.groupingInfos[(item as SlickGroup_).level];\r\n if (!gi.displayTotalsRow) {\r\n this.calculateTotals((item as SlickGroup_).totals);\r\n (item as SlickGroup_).title = gi.formatter ? gi.formatter((item as SlickGroup_)) : (item as SlickGroup_).value;\r\n }\r\n }\r\n // if this is a totals row, make sure it's calculated\r\n else if ((item as SlickGroupTotals_)?.__groupTotals && !(item as SlickGroupTotals_).initialized) {\r\n this.calculateTotals(item as SlickGroupTotals_);\r\n }\r\n\r\n return item;\r\n }\r\n\r\n getItemMetadata(i: number): ItemMetadata | null {\r\n const item = this.rows[i];\r\n if (item === undefined) {\r\n return null;\r\n }\r\n\r\n // overrides for grouping rows\r\n if ((item as SlickGroup_).__group) {\r\n return this._options.groupItemMetadataProvider!.getGroupRowMetadata(item as GroupingFormatterItem);\r\n }\r\n\r\n // overrides for totals rows\r\n if ((item as SlickGroupTotals_).__groupTotals) {\r\n return this._options.groupItemMetadataProvider!.getTotalsRowMetadata(item as { group: GroupingFormatterItem });\r\n }\r\n\r\n return null;\r\n }\r\n\r\n protected expandCollapseAllGroups(level?: number, collapse?: boolean) {\r\n if (!Utils.isDefined(level)) {\r\n for (let i = 0; i < this.groupingInfos.length; i++) {\r\n this.toggledGroupsByLevel[i] = {};\r\n this.groupingInfos[i].collapsed = collapse;\r\n\r\n if (collapse === true) {\r\n this.onGroupCollapsed.notify({ level: i, groupingKey: null });\r\n } else {\r\n this.onGroupExpanded.notify({ level: i, groupingKey: null });\r\n }\r\n }\r\n } else {\r\n this.toggledGroupsByLevel[level] = {};\r\n this.groupingInfos[level].collapsed = collapse;\r\n\r\n if (collapse === true) {\r\n this.onGroupCollapsed.notify({ level, groupingKey: null });\r\n } else {\r\n this.onGroupExpanded.notify({ level, groupingKey: null });\r\n }\r\n }\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * @param {Number} [level] Optional level to collapse. If not specified, applies to all levels.\r\n */\r\n collapseAllGroups(level?: number) {\r\n this.expandCollapseAllGroups(level, true);\r\n }\r\n\r\n /**\r\n * @param {Number} [level] Optional level to expand. If not specified, applies to all levels.\r\n */\r\n expandAllGroups(level?: number) {\r\n this.expandCollapseAllGroups(level, false);\r\n }\r\n\r\n expandCollapseGroup(level: number, groupingKey: string, collapse?: boolean) {\r\n // @ts-ignore\r\n this.toggledGroupsByLevel[level][groupingKey] = this.groupingInfos[level].collapsed ^ collapse;\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * @param varArgs Either a Slick.Group's \"groupingKey\" property, or a\r\n * variable argument list of grouping values denoting a unique path to the row. For\r\n * example, calling collapseGroup('high', '10%') will collapse the '10%' subgroup of\r\n * the 'high' group.\r\n */\r\n collapseGroup(...args: any) {\r\n const calledArgs = Array.prototype.slice.call(args);\r\n const arg0 = calledArgs[0];\r\n let groupingKey: string;\r\n let level: number;\r\n\r\n if (args.length === 1 && arg0.indexOf(this.groupingDelimiter) !== -1) {\r\n groupingKey = arg0;\r\n level = arg0.split(this.groupingDelimiter).length - 1;\r\n } else {\r\n groupingKey = args.join(this.groupingDelimiter);\r\n level = args.length - 1;\r\n }\r\n\r\n this.expandCollapseGroup(level, groupingKey, true);\r\n this.onGroupCollapsed.notify({ level, groupingKey });\r\n }\r\n\r\n /**\r\n * @param varArgs Either a Slick.Group's \"groupingKey\" property, or a\r\n * variable argument list of grouping values denoting a unique path to the row. For\r\n * example, calling expandGroup('high', '10%') will expand the '10%' subgroup of\r\n * the 'high' group.\r\n */\r\n expandGroup(...args: any) {\r\n const calledArgs = Array.prototype.slice.call(args);\r\n const arg0 = calledArgs[0];\r\n let groupingKey: string;\r\n let level: number;\r\n\r\n if (args.length === 1 && arg0.indexOf(this.groupingDelimiter) !== -1) {\r\n level = arg0.split(this.groupingDelimiter).length - 1;\r\n groupingKey = arg0;\r\n } else {\r\n level = args.length - 1;\r\n groupingKey = args.join(this.groupingDelimiter);\r\n }\r\n\r\n this.expandCollapseGroup(level, groupingKey, false);\r\n this.onGroupExpanded.notify({ level, groupingKey });\r\n }\r\n\r\n getGroups() {\r\n return this.groups;\r\n }\r\n\r\n protected extractGroups(rows: any[], parentGroup?: SlickGroup_) {\r\n let group: SlickGroup_;\r\n let val: any;\r\n const groups: SlickGroup_[] = [];\r\n const groupsByVal: any = {};\r\n let r;\r\n const level = parentGroup ? parentGroup.level + 1 : 0;\r\n const gi = this.groupingInfos[level];\r\n\r\n for (let i = 0, l = gi.predefinedValues?.length ?? 0; i < l; i++) {\r\n val = gi.predefinedValues?.[i];\r\n group = groupsByVal[val];\r\n if (!group) {\r\n group = new SlickGroup();\r\n group.value = val;\r\n group.level = level;\r\n group.groupingKey = (parentGroup ? parentGroup.groupingKey + this.groupingDelimiter : '') + val;\r\n groups[groups.length] = group;\r\n groupsByVal[val] = group;\r\n }\r\n }\r\n\r\n for (let i = 0, l = rows.length; i < l; i++) {\r\n r = rows[i];\r\n val = gi.getterIsAFn ? (gi.getter as GroupGetterFn)(r) : r[gi.getter as keyof TData];\r\n group = groupsByVal[val];\r\n if (!group) {\r\n group = new SlickGroup();\r\n group.value = val;\r\n group.level = level;\r\n group.groupingKey = (parentGroup ? parentGroup.groupingKey + this.groupingDelimiter : '') + val;\r\n groups[groups.length] = group;\r\n groupsByVal[val] = group;\r\n }\r\n\r\n group.rows[group.count++] = r;\r\n }\r\n\r\n if (level < this.groupingInfos.length - 1) {\r\n for (let i = 0; i < groups.length; i++) {\r\n group = groups[i];\r\n group.groups = this.extractGroups(group.rows, group);\r\n }\r\n }\r\n\r\n if (groups.length) {\r\n this.addTotals(groups, level);\r\n }\r\n\r\n groups.sort(this.groupingInfos[level].comparer);\r\n\r\n return groups;\r\n }\r\n\r\n /** claculate Group Totals */\r\n protected calculateTotals(totals: SlickGroupTotals_) {\r\n const group = totals.group;\r\n const gi = this.groupingInfos[group.level ?? 0];\r\n const isLeafLevel = (group.level === this.groupingInfos.length);\r\n let agg: Aggregator;\r\n let idx = gi.aggregators.length;\r\n\r\n if (!isLeafLevel && gi.aggregateChildGroups) {\r\n // make sure all the subgroups are calculated\r\n let i = group.groups?.length ?? 0;\r\n while (i--) {\r\n if (!group.groups[i].totals.initialized) {\r\n this.calculateTotals(group.groups[i].totals);\r\n }\r\n }\r\n }\r\n\r\n while (idx--) {\r\n agg = gi.aggregators[idx];\r\n agg.init();\r\n if (!isLeafLevel && gi.aggregateChildGroups) {\r\n gi.compiledAccumulators[idx].call(agg, group.groups);\r\n } else {\r\n gi.compiledAccumulators[idx].call(agg, group.rows);\r\n }\r\n agg.storeResult(totals);\r\n }\r\n totals.initialized = true;\r\n }\r\n\r\n protected addGroupTotals(group: SlickGroup_) {\r\n const gi = this.groupingInfos[group.level];\r\n const totals = new SlickGroupTotals();\r\n totals.group = group;\r\n group.totals = totals;\r\n if (!gi.lazyTotalsCalculation) {\r\n this.calculateTotals(totals);\r\n }\r\n }\r\n\r\n protected addTotals(groups: SlickGroup_[], level?: number) {\r\n level = level || 0;\r\n const gi = this.groupingInfos[level];\r\n const groupCollapsed = gi.collapsed;\r\n const toggledGroups = this.toggledGroupsByLevel[level];\r\n let idx = groups.length, g;\r\n while (idx--) {\r\n g = groups[idx];\r\n\r\n if (g.collapsed && !gi.aggregateCollapsed) {\r\n continue;\r\n }\r\n\r\n // Do a depth-first aggregation so that parent group aggregators can access subgroup totals.\r\n if (g.groups) {\r\n this.addTotals(g.groups, level + 1);\r\n }\r\n\r\n if (gi.aggregators?.length && (\r\n gi.aggregateEmpty || g.rows.length || g.groups?.length)) {\r\n this.addGroupTotals(g);\r\n }\r\n\r\n g.collapsed = (groupCollapsed as any) ^ toggledGroups[g.groupingKey];\r\n g.title = gi.formatter ? gi.formatter(g) : g.value;\r\n }\r\n }\r\n\r\n protected flattenGroupedRows(groups: SlickGroup_[], level?: number) {\r\n level = level || 0;\r\n const gi = this.groupingInfos[level];\r\n const groupedRows: any[] = [];\r\n let rows: any[];\r\n let gl = 0;\r\n let g;\r\n for (let i = 0, l = groups.length; i < l; i++) {\r\n g = groups[i];\r\n groupedRows[gl++] = g;\r\n\r\n if (!g.collapsed) {\r\n rows = g.groups ? this.flattenGroupedRows(g.groups, level + 1) : g.rows;\r\n for (let j = 0, jj = rows.length; j < jj; j++) {\r\n groupedRows[gl++] = rows[j];\r\n }\r\n }\r\n\r\n if (g.totals && gi.displayTotalsRow && (!g.collapsed || gi.aggregateCollapsed)) {\r\n groupedRows[gl++] = g.totals;\r\n }\r\n }\r\n return groupedRows;\r\n }\r\n\r\n protected compileAccumulatorLoopCSPSafe(aggregator: Aggregator) {\r\n if (aggregator.accumulate) {\r\n return function (items: any[]) {\r\n let result;\r\n for (let i = 0; i < items.length; i++) {\r\n const item = items[i];\r\n result = aggregator.accumulate!.call(aggregator, item);\r\n }\r\n return result;\r\n };\r\n } else {\r\n return function noAccumulator() { };\r\n }\r\n }\r\n\r\n protected compileFilterCSPSafe(items: TData[], args: any): TData[] {\r\n if (typeof this.filterCSPSafe !== 'function') {\r\n return [];\r\n }\r\n const _retval: TData[] = [];\r\n const _il = items.length;\r\n\r\n for (let _i = 0; _i < _il; _i++) {\r\n if (this.filterCSPSafe(items[_i], args)) {\r\n _retval.push(items[_i]);\r\n }\r\n }\r\n\r\n return _retval;\r\n }\r\n\r\n protected compileFilter(stopRunningIfCSPSafeIsActive = false): FilterFn | null {\r\n if (stopRunningIfCSPSafeIsActive) {\r\n return null as any;\r\n }\r\n const filterInfo = Utils.getFunctionDetails(this.filter as FilterFn);\r\n\r\n const filterPath1 = '{ continue _coreloop; }$1';\r\n const filterPath2 = '{ _retval[_idx++] = $item$; continue _coreloop; }$1';\r\n // make some allowances for minification - there's only so far we can go with RegEx\r\n const filterBody = filterInfo.body\r\n .replace(/return false\\s*([;}]|\\}|$)/gi, filterPath1)\r\n .replace(/return!1([;}]|\\}|$)/gi, filterPath1)\r\n .replace(/return true\\s*([;}]|\\}|$)/gi, filterPath2)\r\n .replace(/return!0([;}]|\\}|$)/gi, filterPath2)\r\n .replace(/return ([^;}]+?)\\s*([;}]|$)/gi,\r\n '{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }$2');\r\n\r\n // This preserves the function template code after JS compression,\r\n // so that replace() commands still work as expected.\r\n let tpl = [\r\n // 'function(_items, _args) { ',\r\n 'var _retval = [], _idx = 0; ',\r\n 'var $item$, $args$ = _args; ',\r\n '_coreloop: ',\r\n 'for (var _i = 0, _il = _items.length; _i < _il; _i++) { ',\r\n '$item$ = _items[_i]; ',\r\n '$filter$; ',\r\n '} ',\r\n 'return _retval; '\r\n // '}'\r\n ].join('');\r\n tpl = tpl.replace(/\\$filter\\$/gi, filterBody);\r\n tpl = tpl.replace(/\\$item\\$/gi, filterInfo.params[0]);\r\n tpl = tpl.replace(/\\$args\\$/gi, filterInfo.params[1]);\r\n const fn: any = new Function('_items,_args', tpl);\r\n const fnName = 'compiledFilter';\r\n fn.displayName = fnName;\r\n fn.name = this.setFunctionName(fn, fnName);\r\n return fn;\r\n }\r\n\r\n protected compileFilterWithCaching(stopRunningIfCSPSafeIsActive = false) {\r\n if (stopRunningIfCSPSafeIsActive) {\r\n return null as any;\r\n }\r\n\r\n const filterInfo = Utils.getFunctionDetails(this.filter as FilterFn);\r\n\r\n const filterPath1 = '{ continue _coreloop; }$1';\r\n const filterPath2 = '{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }$1';\r\n // make some allowances for minification - there's only so far we can go with RegEx\r\n const filterBody = filterInfo.body\r\n .replace(/return false\\s*([;}]|\\}|$)/gi, filterPath1)\r\n .replace(/return!1([;}]|\\}|$)/gi, filterPath1)\r\n .replace(/return true\\s*([;}]|\\}|$)/gi, filterPath2)\r\n .replace(/return!0([;}]|\\}|$)/gi, filterPath2)\r\n .replace(/return ([^;}]+?)\\s*([;}]|$)/gi,\r\n '{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }$2');\r\n\r\n // This preserves the function template code after JS compression,\r\n // so that replace() commands still work as expected.\r\n let tpl = [\r\n // 'function(_items, _args, _cache) { ',\r\n 'var _retval = [], _idx = 0; ',\r\n 'var $item$, $args$ = _args; ',\r\n '_coreloop: ',\r\n 'for (var _i = 0, _il = _items.length; _i < _il; _i++) { ',\r\n '$item$ = _items[_i]; ',\r\n 'if (_cache[_i]) { ',\r\n '_retval[_idx++] = $item$; ',\r\n 'continue _coreloop; ',\r\n '} ',\r\n '$filter$; ',\r\n '} ',\r\n 'return _retval; '\r\n // '}'\r\n ].join('');\r\n tpl = tpl.replace(/\\$filter\\$/gi, filterBody);\r\n tpl = tpl.replace(/\\$item\\$/gi, filterInfo.params[0]);\r\n tpl = tpl.replace(/\\$args\\$/gi, filterInfo.params[1]);\r\n\r\n const fn: any = new Function('_items,_args,_cache', tpl);\r\n const fnName = 'compiledFilterWithCaching';\r\n fn.displayName = fnName;\r\n fn.name = this.setFunctionName(fn, fnName);\r\n return fn;\r\n }\r\n\r\n protected compileFilterWithCachingCSPSafe(items: TData[], args: any, filterCache: any[]): TData[] {\r\n if (typeof this.filterCSPSafe !== 'function') {\r\n return [];\r\n }\r\n\r\n const retval: TData[] = [];\r\n const il = items.length;\r\n\r\n for (let _i = 0; _i < il; _i++) {\r\n if (filterCache[_i] || this.filterCSPSafe(items[_i], args)) {\r\n retval.push(items[_i]);\r\n }\r\n }\r\n\r\n return retval;\r\n }\r\n\r\n /**\r\n * In ES5 we could set the function name on the fly but in ES6 this is forbidden and we need to set it through differently\r\n * We can use Object.defineProperty and set it the property to writable, see MDN for reference\r\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\r\n * @param {*} fn\r\n * @param {string} fnName\r\n */\r\n protected setFunctionName(fn: any, fnName: string) {\r\n try {\r\n Object.defineProperty(fn, 'name', { writable: true, value: fnName });\r\n } catch (err) {\r\n fn.name = fnName;\r\n }\r\n }\r\n\r\n protected uncompiledFilter(items: TData[], args: any) {\r\n const retval: any[] = [];\r\n let idx = 0;\r\n\r\n for (let i = 0, ii = items.length; i < ii; i++) {\r\n if (this.filter?.(items[i], args)) {\r\n retval[idx++] = items[i];\r\n }\r\n }\r\n\r\n return retval;\r\n }\r\n\r\n protected uncompiledFilterWithCaching(items: TData[], args: any, cache: any) {\r\n const retval: any[] = [];\r\n let idx = 0,\r\n item: TData;\r\n\r\n for (let i = 0, ii = items.length; i < ii; i++) {\r\n item = items[i];\r\n if (cache[i]) {\r\n retval[idx++] = item;\r\n } else if (this.filter?.(item, args)) {\r\n retval[idx++] = item;\r\n cache[i] = true;\r\n }\r\n }\r\n\r\n return retval;\r\n }\r\n\r\n protected getFilteredAndPagedItems(items: TData[]) {\r\n if (this._options.useCSPSafeFilter ? this.filterCSPSafe : this.filter) {\r\n let batchFilter: AnyFunction;\r\n let batchFilterWithCaching: AnyFunction;\r\n if (this._options.useCSPSafeFilter) {\r\n batchFilter = (this._options.inlineFilters ? this.compiledFilterCSPSafe : this.uncompiledFilter) as AnyFunction;\r\n batchFilterWithCaching = (this._options.inlineFilters ? this.compiledFilterWithCachingCSPSafe : this.uncompiledFilterWithCaching) as AnyFunction;\r\n } else {\r\n batchFilter = (this._options.inlineFilters ? this.compiledFilter : this.uncompiledFilter) as AnyFunction;\r\n batchFilterWithCaching = (this._options.inlineFilters ? this.compiledFilterWithCaching : this.uncompiledFilterWithCaching) as AnyFunction;\r\n }\r\n if (this.refreshHints.isFilterNarrowing) {\r\n this.filteredItems = batchFilter.call(this, this.filteredItems, this.filterArgs);\r\n } else if (this.refreshHints.isFilterExpanding) {\r\n this.filteredItems = batchFilterWithCaching.call(this, items, this.filterArgs, this.filterCache);\r\n } else if (!this.refreshHints.isFilterUnchanged) {\r\n this.filteredItems = batchFilter.call(this, items, this.filterArgs);\r\n }\r\n } else {\r\n // special case: if not filtering and not paging, the resulting\r\n // rows collection needs to be a copy so that changes due to sort\r\n // can be caught\r\n this.filteredItems = this.pagesize ? items : items.concat();\r\n }\r\n\r\n // get the current page\r\n let paged: TData[];\r\n if (this.pagesize) {\r\n if (this.filteredItems.length <= this.pagenum * this.pagesize) {\r\n if (this.filteredItems.length === 0) {\r\n this.pagenum = 0;\r\n } else {\r\n this.pagenum = Math.floor((this.filteredItems.length - 1) / this.pagesize);\r\n }\r\n }\r\n paged = this.filteredItems.slice(this.pagesize * this.pagenum, this.pagesize * this.pagenum + this.pagesize);\r\n } else {\r\n paged = this.filteredItems;\r\n }\r\n return { totalRows: this.filteredItems.length, rows: paged };\r\n }\r\n\r\n protected getRowDiffs(rows: TData[], newRows: TData[]) {\r\n let item: TData | SlickNonDataItem | SlickDataItem | SlickGroup_;\r\n let r;\r\n let eitherIsNonData;\r\n const diff: number[] = [];\r\n let from = 0;\r\n let to = Math.max(newRows.length, rows.length);\r\n\r\n if (this.refreshHints?.ignoreDiffsBefore) {\r\n from = Math.max(0,\r\n Math.min(newRows.length, this.refreshHints.ignoreDiffsBefore));\r\n }\r\n\r\n if (this.refreshHints?.ignoreDiffsAfter) {\r\n to = Math.min(newRows.length,\r\n Math.max(0, this.refreshHints.ignoreDiffsAfter));\r\n }\r\n\r\n for (let i = from, rl = rows.length; i < to; i++) {\r\n if (i >= rl) {\r\n diff[diff.length] = i;\r\n } else {\r\n item = newRows[i];\r\n r = rows[i];\r\n\r\n if (!item || (this.groupingInfos.length && (eitherIsNonData = ((item as SlickNonDataItem).__nonDataRow) || ((r as SlickNonDataItem).__nonDataRow)) &&\r\n (item as SlickGroup_).__group !== (r as SlickGroup_).__group ||\r\n (item as SlickGroup_).__group && !(item as SlickGroup_).equals(r as SlickGroup_))\r\n || (eitherIsNonData &&\r\n // no good way to compare totals since they are arbitrary DTOs\r\n // deep object comparison is pretty expensive\r\n // always considering them 'dirty' seems easier for the time being\r\n ((item as SlickGroupTotals_).__groupTotals || (r as SlickGroupTotals_).__groupTotals))\r\n || item[this.idProperty as keyof TData] !== r[this.idProperty as keyof TData]\r\n || (this.updated?.[item[this.idProperty as keyof TData]])\r\n ) {\r\n diff[diff.length] = i;\r\n }\r\n }\r\n }\r\n return diff;\r\n }\r\n\r\n protected recalc(_items: TData[]) {\r\n this.rowsById = undefined;\r\n\r\n if (this.refreshHints.isFilterNarrowing !== this.prevRefreshHints.isFilterNarrowing ||\r\n this.refreshHints.isFilterExpanding !== this.prevRefreshHints.isFilterExpanding) {\r\n this.filterCache = [];\r\n }\r\n\r\n const filteredItems = this.getFilteredAndPagedItems(_items);\r\n this.totalRows = filteredItems.totalRows;\r\n let newRows: TData[] = filteredItems.rows;\r\n\r\n this.groups = [];\r\n if (this.groupingInfos.length) {\r\n this.groups = this.extractGroups(newRows);\r\n if (this.groups.length) {\r\n newRows = this.flattenGroupedRows(this.groups);\r\n }\r\n }\r\n\r\n const diff = this.getRowDiffs(this.rows, newRows as TData[]);\r\n\r\n this.rows = newRows as TData[];\r\n\r\n return diff;\r\n }\r\n\r\n refresh() {\r\n if (this.suspend) {\r\n return;\r\n }\r\n\r\n const previousPagingInfo = Utils.extend(true, {}, this.getPagingInfo());\r\n\r\n const countBefore = this.rows.length;\r\n const totalRowsBefore = this.totalRows;\r\n\r\n let diff = this.recalc(this.items); // pass as direct refs to avoid closure perf hit\r\n\r\n // if the current page is no longer valid, go to last page and recalc\r\n // we suffer a performance penalty here, but the main loop (recalc) remains highly optimized\r\n if (this.pagesize && this.totalRows < this.pagenum * this.pagesize) {\r\n this.pagenum = Math.max(0, Math.ceil(this.totalRows / this.pagesize) - 1);\r\n diff = this.recalc(this.items);\r\n }\r\n\r\n this.updated = null;\r\n this.prevRefreshHints = this.refreshHints;\r\n this.refreshHints = {};\r\n\r\n if (totalRowsBefore !== this.totalRows) {\r\n // use the previously saved paging info\r\n if (this.onBeforePagingInfoChanged.notify(previousPagingInfo, null, this).getReturnValue() !== false) {\r\n this.onPagingInfoChanged.notify(this.getPagingInfo(), null, this);\r\n }\r\n }\r\n if (countBefore !== this.rows.length) {\r\n this.onRowCountChanged.notify({ previous: countBefore, current: this.rows.length, itemCount: this.items.length, dataView: this, callingOnRowsChanged: (diff.length > 0) }, null, this);\r\n }\r\n if (diff.length > 0) {\r\n this.onRowsChanged.notify({ rows: diff, itemCount: this.items.length, dataView: this, calledOnRowCountChanged: (countBefore !== this.rows.length) }, null, this);\r\n }\r\n if (countBefore !== this.rows.length || diff.length > 0) {\r\n this.onRowsOrCountChanged.notify({\r\n rowsDiff: diff, previousRowCount: countBefore, currentRowCount: this.rows.length, itemCount: this.items.length,\r\n rowCountChanged: countBefore !== this.rows.length, rowsChanged: diff.length > 0, dataView: this\r\n }, null, this);\r\n }\r\n }\r\n\r\n /**\r\n * Wires the grid and the DataView together to keep row selection tied to item ids.\r\n * This is useful since, without it, the grid only knows about rows, so if the items\r\n * move around, the same rows stay selected instead of the selection moving along\r\n * with the items.\r\n *\r\n * NOTE: This doesn't work with cell selection model.\r\n *\r\n * @param {SlickGrid} grid - The grid to sync selection with.\r\n * @param {Boolean} preserveHidden - Whether to keep selected items that go out of the\r\n * view due to them getting filtered out.\r\n * @param {Boolean} [preserveHiddenOnSelectionChange] - Whether to keep selected items\r\n * that are currently out of the view (see preserveHidden) as selected when selection\r\n * changes.\r\n * @return {Event} An event that notifies when an internal list of selected row ids\r\n * changes. This is useful since, in combination with the above two options, it allows\r\n * access to the full list selected row ids, and not just the ones visible to the grid.\r\n * @method syncGridSelection\r\n */\r\n syncGridSelection(grid: SlickGridModel, preserveHidden: boolean, preserveHiddenOnSelectionChange?: boolean) {\r\n this._grid = grid;\r\n let inHandler: boolean;\r\n this.selectedRowIds = this.mapRowsToIds(grid.getSelectedRows());\r\n\r\n /** @param {Array} rowIds */\r\n const setSelectedRowIds = (rowIds: DataIdType[] | false) => {\r\n if (rowIds === false) {\r\n this.selectedRowIds = [];\r\n } else {\r\n if (this.selectedRowIds!.sort().join(',') !== rowIds.sort().join(',')) {\r\n this.selectedRowIds = rowIds;\r\n }\r\n }\r\n };\r\n\r\n const update = () => {\r\n if ((this.selectedRowIds || []).length > 0 && !inHandler) {\r\n inHandler = true;\r\n const selectedRows = this.mapIdsToRows(this.selectedRowIds || []);\r\n if (!preserveHidden) {\r\n const selectedRowsChangedArgs = {\r\n grid: this._grid,\r\n ids: this.mapRowsToIds(selectedRows),\r\n rows: selectedRows,\r\n dataView: this\r\n };\r\n this.preSelectedRowIdsChangeFn!(selectedRowsChangedArgs);\r\n this.onSelectedRowIdsChanged.notify(Object.assign(selectedRowsChangedArgs, {\r\n selectedRowIds: this.selectedRowIds,\r\n filteredIds: this.getAllSelectedFilteredIds() as DataIdType[],\r\n }), new SlickEventData(), this);\r\n }\r\n grid.setSelectedRows(selectedRows);\r\n inHandler = false;\r\n }\r\n };\r\n\r\n grid.onSelectedRowsChanged.subscribe((_e: SlickEventData_, args: { rows: number[]; }) => {\r\n if (!inHandler) {\r\n const newSelectedRowIds = this.mapRowsToIds(args.rows);\r\n const selectedRowsChangedArgs = {\r\n grid: this._grid,\r\n ids: newSelectedRowIds,\r\n rows: args.rows,\r\n added: true,\r\n dataView: this\r\n };\r\n this.preSelectedRowIdsChangeFn!(selectedRowsChangedArgs);\r\n this.onSelectedRowIdsChanged.notify(Object.assign(selectedRowsChangedArgs, {\r\n selectedRowIds: this.selectedRowIds,\r\n filteredIds: this.getAllSelectedFilteredIds() as DataIdType[],\r\n }), new SlickEventData(), this);\r\n }\r\n });\r\n\r\n this.preSelectedRowIdsChangeFn = (args: { ids: DataIdType[]; added?: boolean; }) => {\r\n if (!inHandler) {\r\n inHandler = true;\r\n const overwrite = (typeof args.added === typeof undefined);\r\n\r\n if (overwrite) {\r\n setSelectedRowIds(args.ids);\r\n } else {\r\n let rowIds: DataIdType[];\r\n if (args.added) {\r\n if (preserveHiddenOnSelectionChange && grid.getOptions().multiSelect) {\r\n // find the ones that are hidden\r\n const hiddenSelectedRowIds = this.selectedRowIds?.filter((id) => this.getRowById(id) === undefined);\r\n // add the newly selected ones\r\n rowIds = hiddenSelectedRowIds!.concat(args.ids);\r\n } else {\r\n rowIds = args.ids;\r\n }\r\n } else {\r\n if (preserveHiddenOnSelectionChange && grid.getOptions().multiSelect) {\r\n // remove rows whose id is on the list\r\n const argsIdsSet = new Set(args.ids);\r\n rowIds = this.selectedRowIds?.filter((id) => !argsIdsSet.has(id));\r\n } else {\r\n rowIds = [];\r\n }\r\n }\r\n setSelectedRowIds(rowIds);\r\n }\r\n inHandler = false;\r\n }\r\n };\r\n\r\n this.onRowsOrCountChanged.subscribe(update.bind(this));\r\n\r\n return this.onSelectedRowIdsChanged;\r\n }\r\n\r\n /**\r\n * Get all selected IDs\r\n * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true.\r\n */\r\n getAllSelectedIds() {\r\n return this.selectedRowIds;\r\n }\r\n\r\n /**\r\n * Get all selected filtered IDs (similar to \"getAllSelectedIds\" but only return filtered data)\r\n * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true.\r\n */\r\n getAllSelectedFilteredIds() {\r\n return this.getAllSelectedFilteredItems().map((item) => item[this.idProperty as keyof TData]);\r\n }\r\n\r\n /**\r\n * Set current row selected IDs array (regardless of Pagination)\r\n * NOTE: This will NOT change the selection in the grid, if you need to do that then you still need to call\r\n * \"grid.setSelectedRows(rows)\"\r\n * @param {Array} selectedIds - list of IDs which have been selected for this action\r\n * @param {Object} options\r\n * - `isRowBeingAdded`: defaults to true, are the new selected IDs being added (or removed) as new row selections\r\n * - `shouldTriggerEvent`: defaults to true, should we trigger `onSelectedRowIdsChanged` event\r\n * - `applyRowSelectionToGrid`: defaults to true, should we apply the row selections to the grid in the UI\r\n */\r\n setSelectedIds(selectedIds: Array, options?: Partial<{ isRowBeingAdded: boolean; shouldTriggerEvent: boolean; applyRowSelectionToGrid: boolean; }>) {\r\n let isRowBeingAdded = options?.isRowBeingAdded;\r\n const shouldTriggerEvent = options?.shouldTriggerEvent;\r\n const applyRowSelectionToGrid = options?.applyRowSelectionToGrid;\r\n\r\n if (isRowBeingAdded !== false) {\r\n isRowBeingAdded = true;\r\n }\r\n const selectedRows = this.mapIdsToRows(selectedIds);\r\n const selectedRowsChangedArgs = {\r\n grid: this._grid,\r\n ids: selectedIds,\r\n rows: selectedRows,\r\n added: isRowBeingAdded,\r\n dataView: this\r\n };\r\n this.preSelectedRowIdsChangeFn?.(selectedRowsChangedArgs);\r\n\r\n if (shouldTriggerEvent !== false) {\r\n this.onSelectedRowIdsChanged.notify(Object.assign(selectedRowsChangedArgs, {\r\n selectedRowIds: this.selectedRowIds,\r\n filteredIds: this.getAllSelectedFilteredIds() as DataIdType[],\r\n }), new SlickEventData(), this);\r\n }\r\n\r\n // should we also apply the row selection in to the grid (UI) as well?\r\n if (applyRowSelectionToGrid !== false && this._grid) {\r\n this._grid.setSelectedRows(selectedRows);\r\n }\r\n }\r\n\r\n /**\r\n * Get all selected dataContext items\r\n * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true.\r\n */\r\n getAllSelectedItems() {\r\n const selectedData: TData[] = [];\r\n const selectedIds = this.getAllSelectedIds();\r\n selectedIds!.forEach((id) => {\r\n selectedData.push(this.getItemById(id));\r\n });\r\n return selectedData as T[];\r\n }\r\n\r\n /**\r\n * Get all selected filtered dataContext items (similar to \"getAllSelectedItems\" but only return filtered data)\r\n * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true.\r\n */\r\n getAllSelectedFilteredItems() {\r\n if (!Array.isArray(this.selectedRowIds)) {\r\n return [];\r\n }\r\n\r\n const selectedRowIdSet = new Set(this.selectedRowIds);\r\n const intersection = this.filteredItems.filter((a) => selectedRowIdSet.has(a[this.idProperty as keyof TData] as DataIdType));\r\n return (intersection || []) as T[];\r\n }\r\n\r\n syncGridCellCssStyles(grid: SlickGridModel, key: string) {\r\n let hashById: any;\r\n let inHandler: boolean;\r\n\r\n const storeCellCssStyles = (hash: CssStyleHash) => {\r\n hashById = {};\r\n if (typeof hash === 'object') {\r\n Object.keys(hash).forEach(row => {\r\n if (hash) {\r\n const id = this.rows[row as any][this.idProperty as keyof TData];\r\n hashById[id] = hash[row];\r\n }\r\n });\r\n }\r\n };\r\n\r\n // since this method can be called after the cell styles have been set,\r\n // get the existing ones right away\r\n storeCellCssStyles(grid.getCellCssStyles(key));\r\n\r\n const update = () => {\r\n if (typeof hashById === 'object') {\r\n inHandler = true;\r\n this.ensureRowsByIdCache();\r\n const newHash: CssStyleHash = {};\r\n Object.keys(hashById).forEach(id => {\r\n const row = this.rowsById?.[id];\r\n if (Utils.isDefined(row)) {\r\n newHash[row as number] = hashById[id];\r\n }\r\n });\r\n grid.setCellCssStyles(key, newHash);\r\n inHandler = false;\r\n }\r\n };\r\n\r\n grid.onCellCssStylesChanged.subscribe((_e: SlickEventData_, args: any) => {\r\n if (inHandler) { return; }\r\n if (key !== args.key) { return; }\r\n if (args.hash) {\r\n storeCellCssStyles(args.hash);\r\n } else {\r\n grid.onCellCssStylesChanged.unsubscribe();\r\n this.onRowsOrCountChanged.unsubscribe(update);\r\n }\r\n });\r\n\r\n this.onRowsOrCountChanged.subscribe(update.bind(this));\r\n }\r\n}\r\n\r\nexport class AvgAggregator implements Aggregator {\r\n private _nonNullCount = 0;\r\n private _sum = 0;\r\n private _field: number | string;\r\n private _type = 'avg' as const;\r\n\r\n constructor(field: number | string) {\r\n this._field = field;\r\n }\r\n\r\n get field(): number | string {\r\n return this._field;\r\n }\r\n\r\n get type(): string {\r\n return this._type;\r\n }\r\n\r\n init(): void {\r\n this._nonNullCount = 0;\r\n this._sum = 0;\r\n }\r\n\r\n accumulate(item: T) {\r\n const val: any = (item?.hasOwnProperty(this._field)) ? item[this._field as keyof T] : null;\r\n if (val !== null && val !== '' && !isNaN(val)) {\r\n this._nonNullCount++;\r\n this._sum += parseFloat(val);\r\n }\r\n }\r\n\r\n storeResult(groupTotals: SlickGroupTotals_ & { avg: Record; }) {\r\n if (!groupTotals || groupTotals[this._type] === undefined) {\r\n (groupTotals as any)[this._type] = {};\r\n }\r\n if (this._nonNullCount !== 0) {\r\n groupTotals[this._type][this._field] = this._sum / this._nonNullCount;\r\n }\r\n }\r\n}\r\n\r\nexport class MinAggregator implements Aggregator {\r\n private _min: number | null = null;\r\n private _field: number | string;\r\n private _type = 'min' as const;\r\n\r\n constructor(field: number | string) {\r\n this._field = field;\r\n }\r\n\r\n get field(): number | string {\r\n return this._field;\r\n }\r\n\r\n get type(): string {\r\n return this._type;\r\n }\r\n\r\n init() {\r\n this._min = null;\r\n }\r\n\r\n accumulate(item: T) {\r\n const val: any = (item?.hasOwnProperty(this._field)) ? item[this._field as keyof T] : null;\r\n if (val !== null && val !== '' && !isNaN(val)) {\r\n if (this._min === null || val < this._min) {\r\n this._min = parseFloat(val);\r\n }\r\n }\r\n }\r\n\r\n storeResult(groupTotals: SlickGroupTotals_ & { min: Record; }) {\r\n if (!groupTotals || groupTotals[this._type] === undefined) {\r\n groupTotals[this._type] = {};\r\n }\r\n groupTotals[this._type][this._field] = this._min;\r\n }\r\n}\r\n\r\nexport class MaxAggregator implements Aggregator {\r\n private _max: number | null = null;\r\n private _field: number | string;\r\n private _type = 'max' as const;\r\n\r\n constructor(field: number | string) {\r\n this._field = field;\r\n }\r\n\r\n get field(): number | string {\r\n return this._field;\r\n }\r\n\r\n get type(): string {\r\n return this._type;\r\n }\r\n\r\n init(): void {\r\n this._max = null;\r\n }\r\n\r\n accumulate(item: T) {\r\n const val: any = (item?.hasOwnProperty(this._field)) ? item[this._field as keyof T] : null;\r\n if (val !== null && val !== '' && !isNaN(val)) {\r\n if (this._max === null || val > this._max) {\r\n this._max = parseFloat(val);\r\n }\r\n }\r\n }\r\n\r\n storeResult(groupTotals: SlickGroupTotals_ & { max: Record; }) {\r\n if (!groupTotals || groupTotals[this._type] === undefined) {\r\n groupTotals[this._type] = {};\r\n }\r\n groupTotals[this._type][this._field] = this._max;\r\n }\r\n}\r\n\r\nexport class SumAggregator implements Aggregator {\r\n private _sum = 0;\r\n private _field: number | string;\r\n private _type = 'sum' as const;\r\n\r\n constructor(field: number | string) {\r\n this._field = field;\r\n }\r\n\r\n get field(): number | string {\r\n return this._field;\r\n }\r\n\r\n get type(): string {\r\n return this._type;\r\n }\r\n\r\n init() {\r\n this._sum = 0;\r\n }\r\n\r\n accumulate(item: T) {\r\n const val: any = (item?.hasOwnProperty(this._field)) ? item[this._field as keyof T] : null;\r\n if (val !== null && val !== '' && !isNaN(val)) {\r\n this._sum += parseFloat(val);\r\n }\r\n }\r\n\r\n storeResult(groupTotals: SlickGroupTotals_ & { sum: Record; }) {\r\n if (!groupTotals || groupTotals[this._type] === undefined) {\r\n groupTotals[this._type] = {};\r\n }\r\n groupTotals[this._type][this._field] = this._sum;\r\n }\r\n}\r\n\r\nexport class CountAggregator implements Aggregator {\r\n private _field: number | string;\r\n private _type = 'count' as const;\r\n\r\n constructor(field: number | string) {\r\n this._field = field;\r\n }\r\n\r\n get field(): number | string {\r\n return this._field;\r\n }\r\n\r\n get type(): string {\r\n return this._type;\r\n }\r\n\r\n init(): void {\r\n }\r\n\r\n storeResult(groupTotals: SlickGroupTotals_ & { count: Record; }) {\r\n if (!groupTotals || groupTotals[this._type] === undefined) {\r\n groupTotals[this._type] = {};\r\n }\r\n groupTotals[this._type][this._field] = groupTotals.group.rows.length;\r\n }\r\n}\r\n\r\n// TODO: add more built-in aggregators\r\n// TODO: merge common aggregators in one to prevent needless iterating\r\n\r\nexport const Aggregators = {\r\n Avg: AvgAggregator,\r\n Min: MinAggregator,\r\n Max: MaxAggregator,\r\n Sum: SumAggregator,\r\n Count: CountAggregator\r\n};\r\n\r\n// extend Slick namespace on window object when building as iife\r\nif (IIFE_ONLY && window.Slick) {\r\n window.Slick.Data = window.Slick.Data || {};\r\n window.Slick.Data.DataView = SlickDataView;\r\n window.Slick.Data.Aggregators = Aggregators;\r\n}\r\n"], - "mappings": "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", + "sourcesContent": ["import type {\r\n Aggregator,\r\n AnyFunction,\r\n CssStyleHash,\r\n CustomDataView,\r\n DataViewHints,\r\n Grouping,\r\n GroupingFormatterItem,\r\n ItemMetadata,\r\n ItemMetadataProvider,\r\n OnGroupCollapsedEventArgs,\r\n OnGroupExpandedEventArgs,\r\n OnRowCountChangedEventArgs,\r\n OnRowsChangedEventArgs,\r\n OnRowsOrCountChangedEventArgs,\r\n OnSelectedRowIdsChangedEventArgs,\r\n OnSetItemsCalledEventArgs,\r\n PagingInfo,\r\n SlickGridModel,\r\n} from './models/index.js';\r\nimport {\r\n type BasePubSub,\r\n SlickEvent as SlickEvent_,\r\n SlickEventData as SlickEventData_,\r\n SlickGroup as SlickGroup_,\r\n SlickGroupTotals as SlickGroupTotals_,\r\n Utils as Utils_,\r\n type SlickNonDataItem,\r\n} from './slick.core.js';\r\nimport { SlickGroupItemMetadataProvider as SlickGroupItemMetadataProvider_ } from './slick.groupitemmetadataprovider.js';\r\n\r\n// for (iife) load Slick methods from global Slick object, or use imports for (esm)\r\nconst SlickEvent = IIFE_ONLY ? Slick.Event : SlickEvent_;\r\nconst SlickEventData = IIFE_ONLY ? Slick.EventData : SlickEventData_;\r\nconst SlickGroup = IIFE_ONLY ? Slick.Group : SlickGroup_;\r\nconst SlickGroupTotals = IIFE_ONLY ? Slick.GroupTotals : SlickGroupTotals_;\r\nconst Utils = IIFE_ONLY ? Slick.Utils : Utils_;\r\nconst SlickGroupItemMetadataProvider = IIFE_ONLY ? Slick.Data?.GroupItemMetadataProvider ?? {} : SlickGroupItemMetadataProvider_;\r\n\r\nexport interface DataViewOption {\r\n /** global override for all rows */\r\n globalItemMetadataProvider: ItemMetadataProvider | null;\r\n\r\n /** Optionally provide a GroupItemMetadataProvider in order to use Grouping/DraggableGrouping features */\r\n groupItemMetadataProvider: SlickGroupItemMetadataProvider_ | null;\r\n\r\n /** defaults to false, are we using inline filters? */\r\n inlineFilters: boolean;\r\n\r\n /**\r\n * defaults to false, option to use CSP Safe approach,\r\n * Note: it is an opt-in option because it is slightly slower (perf impact) when compared to the non-CSP safe approach.\r\n */\r\n useCSPSafeFilter: boolean;\r\n}\r\nexport type FilterFn = (item: T, args: any) => boolean;\r\nexport type FilterCspFn = (item: T[], args: any) => T[];\r\nexport type FilterWithCspCachingFn = (item: T[], args: any, filterCache: any[]) => T[];\r\nexport type DataIdType = number | string;\r\nexport type SlickDataItem = SlickNonDataItem | SlickGroup_ | SlickGroupTotals_ | any;\r\nexport type GroupGetterFn = (val: any) => string | number;\r\n\r\n/**\r\n * A simple Model implementation.\r\n * Provides a filtered view of the underlying data.\r\n * Relies on the data item having an \"id\" property uniquely identifying it.\r\n */\r\nexport class SlickDataView implements CustomDataView {\r\n protected defaults: DataViewOption = {\r\n globalItemMetadataProvider: null,\r\n groupItemMetadataProvider: null,\r\n inlineFilters: false,\r\n useCSPSafeFilter: false,\r\n };\r\n\r\n // private\r\n protected idProperty = 'id'; // property holding a unique row id\r\n protected items: TData[] = []; // data by index\r\n protected rows: TData[] = []; // data by row\r\n protected idxById = new Map(); // indexes by id\r\n protected rowsById: { [id: DataIdType]: number } | undefined = undefined; // rows by id; lazy-calculated\r\n protected filter: FilterFn | null = null; // filter function\r\n protected filterCSPSafe: FilterFn | null = null; // filter function\r\n protected updated: ({ [id: DataIdType]: boolean }) | null = null; // updated item ids\r\n protected suspend = false; // suspends the recalculation\r\n protected isBulkSuspend = false; // delays protectedious operations like the\r\n // index update and delete to efficient\r\n // versions at endUpdate\r\n protected bulkDeleteIds = new Map();\r\n protected sortAsc: boolean | undefined = true;\r\n protected fastSortField?: string | null | (() => string);\r\n protected sortComparer!: ((a: TData, b: TData) => number);\r\n protected refreshHints: DataViewHints = {};\r\n protected prevRefreshHints: DataViewHints = {};\r\n protected filterArgs: any;\r\n protected filteredItems: TData[] = [];\r\n protected compiledFilter?: FilterFn | null;\r\n protected compiledFilterCSPSafe?: FilterCspFn | null;\r\n protected compiledFilterWithCaching?: FilterFn | null;\r\n protected compiledFilterWithCachingCSPSafe?: FilterWithCspCachingFn | null;\r\n protected filterCache: any[] = [];\r\n protected _grid?: SlickGridModel; // grid object will be defined only after using \"syncGridSelection()\" method\"\r\n\r\n // grouping\r\n protected groupingInfoDefaults: Grouping = {\r\n getter: undefined,\r\n formatter: undefined,\r\n comparer: (a: { value: any; }, b: { value: any; }) => (a.value === b.value ? 0 : (a.value > b.value ? 1 : -1)),\r\n predefinedValues: [],\r\n aggregators: [],\r\n aggregateEmpty: false,\r\n aggregateCollapsed: false,\r\n aggregateChildGroups: false,\r\n collapsed: false,\r\n displayTotalsRow: true,\r\n lazyTotalsCalculation: false\r\n };\r\n protected groupingInfos: Array = [];\r\n protected groups: SlickGroup_[] = [];\r\n protected toggledGroupsByLevel: any[] = [];\r\n protected groupingDelimiter = ':|:';\r\n protected selectedRowIds: DataIdType[] = [];\r\n protected preSelectedRowIdsChangeFn?: (args?: any) => void;\r\n\r\n protected pagesize = 0;\r\n protected pagenum = 0;\r\n protected totalRows = 0;\r\n protected _options: DataViewOption;\r\n protected _container?: HTMLElement;\r\n\r\n // public events\r\n onBeforePagingInfoChanged: SlickEvent_;\r\n onGroupExpanded: SlickEvent_;\r\n onGroupCollapsed: SlickEvent_;\r\n onPagingInfoChanged: SlickEvent_;\r\n onRowCountChanged: SlickEvent_;\r\n onRowsChanged: SlickEvent_;\r\n onRowsOrCountChanged: SlickEvent_;\r\n onSelectedRowIdsChanged: SlickEvent_;\r\n onSetItemsCalled: SlickEvent_;\r\n\r\n constructor(options?: Partial, protected externalPubSub?: BasePubSub) {\r\n this.onBeforePagingInfoChanged = new SlickEvent('onBeforePagingInfoChanged', externalPubSub);\r\n this.onGroupExpanded = new SlickEvent('onGroupExpanded', externalPubSub);\r\n this.onGroupCollapsed = new SlickEvent('onGroupCollapsed', externalPubSub);\r\n this.onPagingInfoChanged = new SlickEvent('onPagingInfoChanged', externalPubSub);\r\n this.onRowCountChanged = new SlickEvent('onRowCountChanged', externalPubSub);\r\n this.onRowsChanged = new SlickEvent('onRowsChanged', externalPubSub);\r\n this.onRowsOrCountChanged = new SlickEvent('onRowsOrCountChanged', externalPubSub);\r\n this.onSelectedRowIdsChanged = new SlickEvent('onSelectedRowIdsChanged', externalPubSub);\r\n this.onSetItemsCalled = new SlickEvent('onSetItemsCalled', externalPubSub);\r\n\r\n this._options = Utils.extend(true, {}, this.defaults, options);\r\n }\r\n\r\n /**\r\n * Begins a bached update of the items in the data view.\r\n * including deletes and the related events are postponed to the endUpdate call.\r\n * As certain operations are postponed during this update, some methods might not\r\n * deliver fully consistent information.\r\n * @param {Boolean} [bulkUpdate] - if set to true, most data view modifications\r\n */\r\n beginUpdate(bulkUpdate?: boolean) {\r\n this.suspend = true;\r\n this.isBulkSuspend = bulkUpdate === true;\r\n }\r\n\r\n endUpdate() {\r\n const wasBulkSuspend = this.isBulkSuspend;\r\n this.isBulkSuspend = false;\r\n this.suspend = false;\r\n if (wasBulkSuspend) {\r\n this.processBulkDelete();\r\n this.ensureIdUniqueness();\r\n }\r\n this.refresh();\r\n }\r\n\r\n destroy() {\r\n this.items = [];\r\n this.idxById = null as any;\r\n this.rowsById = null as any;\r\n this.filter = null as any;\r\n this.filterCSPSafe = null as any;\r\n this.updated = null as any;\r\n this.sortComparer = null as any;\r\n this.filterCache = [];\r\n this.filteredItems = [];\r\n this.compiledFilter = null;\r\n this.compiledFilterCSPSafe = null;\r\n this.compiledFilterWithCaching = null;\r\n this.compiledFilterWithCachingCSPSafe = null;\r\n\r\n if (this._grid && this._grid.onSelectedRowsChanged && this._grid.onCellCssStylesChanged) {\r\n this._grid.onSelectedRowsChanged.unsubscribe();\r\n this._grid.onCellCssStylesChanged.unsubscribe();\r\n }\r\n if (this.onRowsOrCountChanged) {\r\n this.onRowsOrCountChanged.unsubscribe();\r\n }\r\n }\r\n\r\n /** provide some refresh hints as to what to rows needs refresh */\r\n setRefreshHints(hints: DataViewHints) {\r\n this.refreshHints = hints;\r\n }\r\n\r\n /** get extra filter arguments of the filter method */\r\n getFilterArgs() {\r\n return this.filterArgs;\r\n }\r\n\r\n /** add extra filter arguments to the filter method */\r\n setFilterArgs(args: any) {\r\n this.filterArgs = args;\r\n }\r\n\r\n /**\r\n * Processes all delete requests placed during bulk update\r\n * by recomputing the items and idxById members.\r\n */\r\n protected processBulkDelete() {\r\n if (!this.idxById) { return; }\r\n\r\n // the bulk update is processed by\r\n // recomputing the whole items array and the index lookup in one go.\r\n // this is done by placing the not-deleted items\r\n // from left to right into the array and shrink the array the the new\r\n // size afterwards.\r\n // see https://github.com/6pac/SlickGrid/issues/571 for further details.\r\n\r\n let id: DataIdType, item, newIdx = 0;\r\n for (let i = 0, l = this.items.length; i < l; i++) {\r\n item = this.items[i];\r\n id = item[this.idProperty as keyof TData] as DataIdType;\r\n if (id === undefined) {\r\n throw new Error(`[SlickGrid DataView] Each data element must implement a unique 'id' property`);\r\n }\r\n\r\n // if items have been marked as deleted we skip them for the new final items array\r\n // and we remove them from the lookup table.\r\n if (this.bulkDeleteIds.has(id)) {\r\n this.idxById.delete(id);\r\n } else {\r\n // for items which are not deleted, we add them to the\r\n // next free position in the array and register the index in the lookup.\r\n this.items[newIdx] = item;\r\n this.idxById.set(id, newIdx);\r\n ++newIdx;\r\n }\r\n }\r\n\r\n // here we shrink down the full item array to the ones actually\r\n // inserted in the cleanup loop above.\r\n this.items.length = newIdx;\r\n // and finally cleanup the deleted ids to start cleanly on the next update.\r\n this.bulkDeleteIds = new Map();\r\n }\r\n\r\n protected updateIdxById(startingIndex?: number) {\r\n if (this.isBulkSuspend || !this.idxById) { // during bulk update we do not reorganize\r\n return;\r\n }\r\n startingIndex = startingIndex || 0;\r\n let id: DataIdType;\r\n for (let i = startingIndex, l = this.items.length; i < l; i++) {\r\n id = this.items[i][this.idProperty as keyof TData] as DataIdType;\r\n if (id === undefined) {\r\n throw new Error(`[SlickGrid DataView] Each data element must implement a unique 'id' property`);\r\n }\r\n this.idxById.set(id, i);\r\n }\r\n }\r\n\r\n protected ensureIdUniqueness() {\r\n if (this.isBulkSuspend || !this.idxById) { // during bulk update we do not reorganize\r\n return;\r\n }\r\n let id: DataIdType;\r\n for (let i = 0, l = this.items.length; i < l; i++) {\r\n id = this.items[i][this.idProperty as keyof TData] as DataIdType;\r\n if (id === undefined || this.idxById.get(id) !== i) {\r\n throw new Error(`[SlickGrid DataView] Each data element must implement a unique 'id' property`);\r\n }\r\n }\r\n }\r\n\r\n /** Get all DataView Items */\r\n getItems() {\r\n return this.items;\r\n }\r\n\r\n /** Get the DataView Id property name to use (defaults to \"Id\" but could be customized to something else when instantiating the DataView) */\r\n getIdPropertyName() {\r\n return this.idProperty;\r\n }\r\n\r\n /**\r\n * Set the Items with a new Dataset and optionally pass a different Id property name\r\n * @param {Array<*>} data - array of data\r\n * @param {String} [objectIdProperty] - optional id property to use as primary id\r\n */\r\n setItems(data: TData[], objectIdProperty?: string) {\r\n if (objectIdProperty !== undefined) {\r\n this.idProperty = objectIdProperty;\r\n }\r\n this.items = this.filteredItems = data;\r\n this.onSetItemsCalled.notify({ idProperty: this.idProperty, itemCount: this.items.length }, null, this);\r\n this.idxById = new Map();\r\n this.updateIdxById();\r\n this.ensureIdUniqueness();\r\n this.refresh();\r\n }\r\n\r\n /** Set Paging Options */\r\n setPagingOptions(args: Partial) {\r\n if (this.onBeforePagingInfoChanged.notify(this.getPagingInfo(), null, this).getReturnValue() !== false) {\r\n if (Utils.isDefined(args.pageSize)) {\r\n this.pagesize = args.pageSize;\r\n this.pagenum = this.pagesize ? Math.min(this.pagenum, Math.max(0, Math.ceil(this.totalRows / this.pagesize) - 1)) : 0;\r\n }\r\n\r\n if (Utils.isDefined(args.pageNum)) {\r\n this.pagenum = Math.min(args.pageNum, Math.max(0, Math.ceil(this.totalRows / this.pagesize) - 1));\r\n }\r\n\r\n this.onPagingInfoChanged.notify(this.getPagingInfo(), null, this);\r\n\r\n this.refresh();\r\n }\r\n }\r\n\r\n /** Get Paging Options */\r\n getPagingInfo(): PagingInfo {\r\n const totalPages = this.pagesize ? Math.max(1, Math.ceil(this.totalRows / this.pagesize)) : 1;\r\n return { pageSize: this.pagesize, pageNum: this.pagenum, totalRows: this.totalRows, totalPages, dataView: this as SlickDataView };\r\n }\r\n\r\n /** Sort Method to use by the DataView */\r\n sort(comparer: (a: TData, b: TData) => number, ascending?: boolean) {\r\n this.sortAsc = ascending;\r\n this.sortComparer = comparer;\r\n this.fastSortField = null;\r\n if (ascending === false) {\r\n this.items.reverse();\r\n }\r\n this.items.sort(comparer);\r\n if (ascending === false) {\r\n this.items.reverse();\r\n }\r\n this.idxById = new Map();\r\n this.updateIdxById();\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * @deprecated, to be more removed in next major since IE is no longer supported and this is no longer useful.\r\n * Provides a workaround for the extremely slow sorting in IE.\r\n * Does a [lexicographic] sort on a give column by temporarily overriding Object.prototype.toString\r\n * to return the value of that field and then doing a native Array.sort().\r\n */\r\n fastSort(field: string | (() => string), ascending?: boolean) {\r\n this.sortAsc = ascending;\r\n this.fastSortField = field;\r\n this.sortComparer = null as any;\r\n const oldToString = Object.prototype.toString;\r\n Object.prototype.toString = (typeof field === 'function') ? field : function () {\r\n // @ts-ignore\r\n return this[field];\r\n };\r\n // an extra reversal for descending sort keeps the sort stable\r\n // (assuming a stable native sort implementation, which isn't true in some cases)\r\n if (ascending === false) {\r\n this.items.reverse();\r\n }\r\n this.items.sort();\r\n Object.prototype.toString = oldToString;\r\n if (ascending === false) {\r\n this.items.reverse();\r\n }\r\n this.idxById = new Map();\r\n this.updateIdxById();\r\n this.refresh();\r\n }\r\n\r\n /** Re-Sort the dataset */\r\n reSort() {\r\n if (this.sortComparer) {\r\n this.sort(this.sortComparer, this.sortAsc);\r\n } else if (this.fastSortField) {\r\n this.fastSort(this.fastSortField, this.sortAsc);\r\n }\r\n }\r\n\r\n /** Get only the DataView filtered items */\r\n getFilteredItems() {\r\n return this.filteredItems as T[];\r\n }\r\n\r\n /** Get the array length (count) of only the DataView filtered items */\r\n getFilteredItemCount() {\r\n return this.filteredItems.length;\r\n }\r\n\r\n /** Get current Filter used by the DataView */\r\n getFilter() {\r\n return this._options.useCSPSafeFilter ? this.filterCSPSafe : this.filter;\r\n }\r\n\r\n /**\r\n * Set a Filter that will be used by the DataView\r\n * @param {Function} fn - filter callback function\r\n */\r\n setFilter(filterFn: FilterFn) {\r\n this.filterCSPSafe = filterFn;\r\n this.filter = filterFn;\r\n if (this._options.inlineFilters) {\r\n this.compiledFilterCSPSafe = this.compileFilterCSPSafe;\r\n this.compiledFilterWithCachingCSPSafe = this.compileFilterWithCachingCSPSafe;\r\n this.compiledFilter = this.compileFilter(this._options.useCSPSafeFilter);\r\n this.compiledFilterWithCaching = this.compileFilterWithCaching(this._options.useCSPSafeFilter);\r\n }\r\n this.refresh();\r\n }\r\n\r\n /** Get current Grouping info */\r\n getGrouping(): Grouping[] {\r\n return this.groupingInfos;\r\n }\r\n\r\n /** Set some Grouping */\r\n setGrouping(groupingInfo: Grouping | Grouping[]) {\r\n if (!this._options.groupItemMetadataProvider) {\r\n this._options.groupItemMetadataProvider = new SlickGroupItemMetadataProvider();\r\n }\r\n\r\n this.groups = [];\r\n this.toggledGroupsByLevel = [];\r\n groupingInfo = groupingInfo || [];\r\n this.groupingInfos = ((groupingInfo instanceof Array) ? groupingInfo : [groupingInfo]) as any;\r\n\r\n for (let i = 0; i < this.groupingInfos.length; i++) {\r\n const gi = this.groupingInfos[i] = Utils.extend(true, {}, this.groupingInfoDefaults, this.groupingInfos[i]);\r\n gi.getterIsAFn = typeof gi.getter === 'function';\r\n\r\n // pre-compile accumulator loops\r\n gi.compiledAccumulators = [];\r\n let idx = gi.aggregators.length;\r\n while (idx--) {\r\n gi.compiledAccumulators[idx] = this.compileAccumulatorLoopCSPSafe(gi.aggregators[idx]);\r\n }\r\n\r\n this.toggledGroupsByLevel[i] = {};\r\n }\r\n\r\n this.refresh();\r\n }\r\n\r\n /** Get an item in the DataView by its row index */\r\n getItemByIdx(i: number) {\r\n return this.items[i] as T;\r\n }\r\n\r\n /** Get row index in the DataView by its Id */\r\n getIdxById(id: DataIdType) {\r\n return this.idxById?.get(id);\r\n }\r\n\r\n protected ensureRowsByIdCache() {\r\n if (!this.rowsById) {\r\n this.rowsById = {};\r\n for (let i = 0, l = this.rows.length; i < l; i++) {\r\n this.rowsById[this.rows[i][this.idProperty as keyof TData] as DataIdType] = i;\r\n }\r\n }\r\n }\r\n\r\n /** Get row number in the grid by its item object */\r\n getRowByItem(item: TData) {\r\n this.ensureRowsByIdCache();\r\n return this.rowsById?.[item[this.idProperty as keyof TData] as DataIdType];\r\n }\r\n\r\n /** Get row number in the grid by its Id */\r\n getRowById(id: DataIdType) {\r\n this.ensureRowsByIdCache();\r\n return this.rowsById?.[id];\r\n }\r\n\r\n /** Get an item in the DataView by its Id */\r\n getItemById(id: DataIdType) {\r\n return this.items[(this.idxById.get(id) as number)] as T;\r\n }\r\n\r\n /** From the items array provided, return the mapped rows */\r\n mapItemsToRows(itemArray: TData[]) {\r\n const rows: number[] = [];\r\n this.ensureRowsByIdCache();\r\n for (let i = 0, l = itemArray.length; i < l; i++) {\r\n const row = this.rowsById?.[itemArray[i][this.idProperty as keyof TData] as DataIdType];\r\n if (Utils.isDefined(row)) {\r\n rows[rows.length] = row as number;\r\n }\r\n }\r\n return rows;\r\n }\r\n\r\n /** From the Ids array provided, return the mapped rows */\r\n mapIdsToRows(idArray: DataIdType[]) {\r\n const rows: number[] = [];\r\n this.ensureRowsByIdCache();\r\n for (let i = 0, l = idArray.length; i < l; i++) {\r\n const row = this.rowsById?.[idArray[i]];\r\n if (Utils.isDefined(row)) {\r\n rows[rows.length] = row as number;\r\n }\r\n }\r\n return rows;\r\n }\r\n\r\n /** From the rows array provided, return the mapped Ids */\r\n mapRowsToIds(rowArray: number[]) {\r\n const ids: DataIdType[] = [];\r\n for (let i = 0, l = rowArray.length; i < l; i++) {\r\n if (rowArray[i] < this.rows.length) {\r\n const rowItem = this.rows[rowArray[i]];\r\n ids[ids.length] = rowItem![this.idProperty as keyof TData] as DataIdType;\r\n }\r\n }\r\n return ids;\r\n }\r\n\r\n /**\r\n * Performs the update operations of a single item by id without\r\n * triggering any events or refresh operations.\r\n * @param id The new id of the item.\r\n * @param item The item which should be the new value for the given id.\r\n */\r\n updateSingleItem(id: DataIdType, item: TData) {\r\n if (!this.idxById) { return; }\r\n\r\n // see also https://github.com/mleibman/SlickGrid/issues/1082\r\n if (!this.idxById.has(id)) {\r\n throw new Error('[SlickGrid DataView] Invalid id');\r\n }\r\n\r\n // What if the specified item also has an updated idProperty?\r\n // Then we'll have to update the index as well, and possibly the `updated` cache too.\r\n if (id !== item[this.idProperty as keyof TData]) {\r\n // make sure the new id is unique:\r\n const newId = item[this.idProperty as keyof TData] as DataIdType;\r\n if (!Utils.isDefined(newId)) {\r\n throw new Error('[SlickGrid DataView] Cannot update item to associate with a null id');\r\n }\r\n if (this.idxById.has(newId)) {\r\n throw new Error('[SlickGrid DataView] Cannot update item to associate with a non-unique id');\r\n }\r\n this.idxById.set(newId, this.idxById.get(id) as number);\r\n this.idxById.delete(id);\r\n\r\n // Also update the `updated` hashtable/markercache? Yes, `recalc()` inside `refresh()` needs that one!\r\n if (this.updated?.[id]) {\r\n delete this.updated[id];\r\n }\r\n\r\n // Also update the row indexes? no need since the `refresh()`, further down, blows away the `rowsById[]` cache!\r\n\r\n id = newId;\r\n }\r\n this.items[this.idxById.get(id) as number] = item;\r\n\r\n // Also update the rows? no need since the `refresh()`, further down, blows away the `rows[]` cache and recalculates it via `recalc()`!\r\n\r\n if (!this.updated) {\r\n this.updated = {};\r\n }\r\n this.updated[id] = true;\r\n }\r\n\r\n /**\r\n * Updates a single item in the data view given the id and new value.\r\n * @param id The new id of the item.\r\n * @param item The item which should be the new value for the given id.\r\n */\r\n updateItem(id: DataIdType, item: T) {\r\n this.updateSingleItem(id, item);\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Updates multiple items in the data view given the new ids and new values.\r\n * @param id {Array} The array of new ids which is in the same order as the items.\r\n * @param newItems {Array} The new items that should be set in the data view for the given ids.\r\n */\r\n updateItems(ids: DataIdType[], newItems: T[]) {\r\n if (ids.length !== newItems.length) {\r\n throw new Error('[SlickGrid DataView] Mismatch on the length of ids and items provided to update');\r\n }\r\n for (let i = 0, l = newItems.length; i < l; i++) {\r\n this.updateSingleItem(ids[i], newItems[i]);\r\n }\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Inserts a single item into the data view at the given position.\r\n * @param insertBefore {Number} The 0-based index before which the item should be inserted.\r\n * @param item The item to insert.\r\n */\r\n insertItem(insertBefore: number, item: TData) {\r\n this.items.splice(insertBefore, 0, item);\r\n this.updateIdxById(insertBefore);\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Inserts multiple items into the data view at the given position.\r\n * @param insertBefore {Number} The 0-based index before which the items should be inserted.\r\n * @param newItems {Array} The items to insert.\r\n */\r\n insertItems(insertBefore: number, newItems: TData[]) {\r\n // @ts-ignore\r\n Array.prototype.splice.apply(this.items, [insertBefore, 0].concat(newItems));\r\n this.updateIdxById(insertBefore);\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Adds a single item at the end of the data view.\r\n * @param item The item to add at the end.\r\n */\r\n addItem(item: TData) {\r\n this.items.push(item);\r\n this.updateIdxById(this.items.length - 1);\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Adds multiple items at the end of the data view.\r\n * @param {Array} newItems The items to add at the end.\r\n */\r\n addItems(newItems: TData[]) {\r\n this.items = this.items.concat(newItems);\r\n this.updateIdxById(this.items.length - newItems.length);\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * Deletes a single item identified by the given id from the data view.\r\n * @param {String|Number} id The id identifying the object to delete.\r\n */\r\n deleteItem(id: DataIdType) {\r\n if (!this.idxById) { return; }\r\n if (this.isBulkSuspend) {\r\n this.bulkDeleteIds.set(id, true);\r\n } else {\r\n const idx = this.idxById.get(id);\r\n if (idx === undefined) {\r\n throw new Error('[SlickGrid DataView] Invalid id');\r\n }\r\n this.idxById.delete(id);\r\n this.items.splice(idx, 1);\r\n this.updateIdxById(idx);\r\n this.refresh();\r\n }\r\n }\r\n\r\n /**\r\n * Deletes multiple item identified by the given ids from the data view.\r\n * @param {Array} ids The ids of the items to delete.\r\n */\r\n deleteItems(ids: DataIdType[]) {\r\n if (ids.length === 0 || !this.idxById) {\r\n return;\r\n }\r\n\r\n if (this.isBulkSuspend) {\r\n for (let i = 0, l = ids.length; i < l; i++) {\r\n const id = ids[i];\r\n const idx = this.idxById.get(id);\r\n if (idx === undefined) {\r\n throw new Error('[SlickGrid DataView] Invalid id');\r\n }\r\n this.bulkDeleteIds.set(id, true);\r\n }\r\n } else {\r\n // collect all indexes\r\n const indexesToDelete: number[] = [];\r\n for (let i = 0, l = ids.length; i < l; i++) {\r\n const id = ids[i];\r\n const idx = this.idxById.get(id);\r\n if (idx === undefined) {\r\n throw new Error('[SlickGrid DataView] Invalid id');\r\n }\r\n this.idxById.delete(id);\r\n indexesToDelete.push(idx);\r\n }\r\n\r\n // Remove from back to front\r\n indexesToDelete.sort();\r\n for (let i = indexesToDelete.length - 1; i >= 0; --i) {\r\n this.items.splice(indexesToDelete[i], 1);\r\n }\r\n\r\n // update lookup from front to back\r\n this.updateIdxById(indexesToDelete[0]);\r\n this.refresh();\r\n }\r\n }\r\n\r\n /** Add an item in a sorted dataset (a Sort function must be defined) */\r\n sortedAddItem(item: TData) {\r\n if (!this.sortComparer) {\r\n throw new Error('[SlickGrid DataView] sortedAddItem() requires a sort comparer, use sort()');\r\n }\r\n this.insertItem(this.sortedIndex(item), item);\r\n }\r\n\r\n /** Update an item in a sorted dataset (a Sort function must be defined) */\r\n sortedUpdateItem(id: string | number, item: TData) {\r\n if (!this.idxById) { return; }\r\n if (!this.idxById.has(id) || id !== item[this.idProperty as keyof TData]) {\r\n throw new Error('[SlickGrid DataView] Invalid or non-matching id ' + this.idxById.get(id));\r\n }\r\n if (!this.sortComparer) {\r\n throw new Error('[SlickGrid DataView] sortedUpdateItem() requires a sort comparer, use sort()');\r\n }\r\n const oldItem = this.getItemById(id);\r\n if (this.sortComparer(oldItem, item) !== 0) {\r\n // item affects sorting -> must use sorted add\r\n this.deleteItem(id);\r\n this.sortedAddItem(item);\r\n } else { // update does not affect sorting -> regular update works fine\r\n this.updateItem(id, item);\r\n }\r\n }\r\n\r\n protected sortedIndex(searchItem: TData) {\r\n let low = 0;\r\n let high = this.items.length;\r\n\r\n while (low < high) {\r\n const mid = low + high >>> 1;\r\n if (this.sortComparer(this.items[mid], searchItem) === -1) {\r\n low = mid + 1;\r\n } else {\r\n high = mid;\r\n }\r\n }\r\n return low;\r\n }\r\n\r\n /** Get item count, that is the full dataset lenght of the DataView */\r\n getItemCount() {\r\n return this.items.length;\r\n }\r\n\r\n /** Get row count (rows displayed in current page) */\r\n getLength() {\r\n return this.rows.length;\r\n }\r\n\r\n /** Retrieve an item from the DataView at specific index */\r\n getItem(i: number) {\r\n const item = this.rows[i] as T;\r\n\r\n // if this is a group row, make sure totals are calculated and update the title\r\n if ((item as SlickGroup_)?.__group && (item as SlickGroup_).totals && !(item as SlickGroup_).totals?.initialized) {\r\n const gi = this.groupingInfos[(item as SlickGroup_).level];\r\n if (!gi.displayTotalsRow) {\r\n this.calculateTotals((item as SlickGroup_).totals);\r\n (item as SlickGroup_).title = gi.formatter ? gi.formatter((item as SlickGroup_)) : (item as SlickGroup_).value;\r\n }\r\n }\r\n // if this is a totals row, make sure it's calculated\r\n else if ((item as SlickGroupTotals_)?.__groupTotals && !(item as SlickGroupTotals_).initialized) {\r\n this.calculateTotals(item as SlickGroupTotals_);\r\n }\r\n\r\n return item;\r\n }\r\n\r\n getItemMetadata(row: number): ItemMetadata | null {\r\n const item = this.rows[row];\r\n if (item === undefined) {\r\n return null;\r\n }\r\n\r\n // global override for all regular rows\r\n if (this._options.globalItemMetadataProvider?.getRowMetadata) {\r\n return this._options.globalItemMetadataProvider.getRowMetadata(item, row);\r\n }\r\n\r\n // overrides for grouping rows\r\n if ((item as SlickGroup_).__group && this._options.groupItemMetadataProvider?.getGroupRowMetadata) {\r\n return this._options.groupItemMetadataProvider.getGroupRowMetadata(item as GroupingFormatterItem, row);\r\n }\r\n\r\n // overrides for totals rows\r\n if ((item as SlickGroupTotals_).__groupTotals && this._options.groupItemMetadataProvider?.getTotalsRowMetadata) {\r\n return this._options.groupItemMetadataProvider.getTotalsRowMetadata(item as { group: GroupingFormatterItem }, row);\r\n }\r\n\r\n return null;\r\n }\r\n\r\n protected expandCollapseAllGroups(level?: number, collapse?: boolean) {\r\n if (!Utils.isDefined(level)) {\r\n for (let i = 0; i < this.groupingInfos.length; i++) {\r\n this.toggledGroupsByLevel[i] = {};\r\n this.groupingInfos[i].collapsed = collapse;\r\n\r\n if (collapse === true) {\r\n this.onGroupCollapsed.notify({ level: i, groupingKey: null });\r\n } else {\r\n this.onGroupExpanded.notify({ level: i, groupingKey: null });\r\n }\r\n }\r\n } else {\r\n this.toggledGroupsByLevel[level] = {};\r\n this.groupingInfos[level].collapsed = collapse;\r\n\r\n if (collapse === true) {\r\n this.onGroupCollapsed.notify({ level, groupingKey: null });\r\n } else {\r\n this.onGroupExpanded.notify({ level, groupingKey: null });\r\n }\r\n }\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * @param {Number} [level] Optional level to collapse. If not specified, applies to all levels.\r\n */\r\n collapseAllGroups(level?: number) {\r\n this.expandCollapseAllGroups(level, true);\r\n }\r\n\r\n /**\r\n * @param {Number} [level] Optional level to expand. If not specified, applies to all levels.\r\n */\r\n expandAllGroups(level?: number) {\r\n this.expandCollapseAllGroups(level, false);\r\n }\r\n\r\n expandCollapseGroup(level: number, groupingKey: string, collapse?: boolean) {\r\n // @ts-ignore\r\n this.toggledGroupsByLevel[level][groupingKey] = this.groupingInfos[level].collapsed ^ collapse;\r\n this.refresh();\r\n }\r\n\r\n /**\r\n * @param varArgs Either a Slick.Group's \"groupingKey\" property, or a\r\n * variable argument list of grouping values denoting a unique path to the row. For\r\n * example, calling collapseGroup('high', '10%') will collapse the '10%' subgroup of\r\n * the 'high' group.\r\n */\r\n collapseGroup(...args: any) {\r\n const calledArgs = Array.prototype.slice.call(args);\r\n const arg0 = calledArgs[0];\r\n let groupingKey: string;\r\n let level: number;\r\n\r\n if (args.length === 1 && arg0.indexOf(this.groupingDelimiter) !== -1) {\r\n groupingKey = arg0;\r\n level = arg0.split(this.groupingDelimiter).length - 1;\r\n } else {\r\n groupingKey = args.join(this.groupingDelimiter);\r\n level = args.length - 1;\r\n }\r\n\r\n this.expandCollapseGroup(level, groupingKey, true);\r\n this.onGroupCollapsed.notify({ level, groupingKey });\r\n }\r\n\r\n /**\r\n * @param varArgs Either a Slick.Group's \"groupingKey\" property, or a\r\n * variable argument list of grouping values denoting a unique path to the row. For\r\n * example, calling expandGroup('high', '10%') will expand the '10%' subgroup of\r\n * the 'high' group.\r\n */\r\n expandGroup(...args: any) {\r\n const calledArgs = Array.prototype.slice.call(args);\r\n const arg0 = calledArgs[0];\r\n let groupingKey: string;\r\n let level: number;\r\n\r\n if (args.length === 1 && arg0.indexOf(this.groupingDelimiter) !== -1) {\r\n level = arg0.split(this.groupingDelimiter).length - 1;\r\n groupingKey = arg0;\r\n } else {\r\n level = args.length - 1;\r\n groupingKey = args.join(this.groupingDelimiter);\r\n }\r\n\r\n this.expandCollapseGroup(level, groupingKey, false);\r\n this.onGroupExpanded.notify({ level, groupingKey });\r\n }\r\n\r\n getGroups() {\r\n return this.groups;\r\n }\r\n\r\n protected extractGroups(rows: any[], parentGroup?: SlickGroup_) {\r\n let group: SlickGroup_;\r\n let val: any;\r\n const groups: SlickGroup_[] = [];\r\n const groupsByVal: any = {};\r\n let r;\r\n const level = parentGroup ? parentGroup.level + 1 : 0;\r\n const gi = this.groupingInfos[level];\r\n\r\n for (let i = 0, l = gi.predefinedValues?.length ?? 0; i < l; i++) {\r\n val = gi.predefinedValues?.[i];\r\n group = groupsByVal[val];\r\n if (!group) {\r\n group = new SlickGroup();\r\n group.value = val;\r\n group.level = level;\r\n group.groupingKey = (parentGroup ? parentGroup.groupingKey + this.groupingDelimiter : '') + val;\r\n groups[groups.length] = group;\r\n groupsByVal[val] = group;\r\n }\r\n }\r\n\r\n for (let i = 0, l = rows.length; i < l; i++) {\r\n r = rows[i];\r\n val = gi.getterIsAFn ? (gi.getter as GroupGetterFn)(r) : r[gi.getter as keyof TData];\r\n group = groupsByVal[val];\r\n if (!group) {\r\n group = new SlickGroup();\r\n group.value = val;\r\n group.level = level;\r\n group.groupingKey = (parentGroup ? parentGroup.groupingKey + this.groupingDelimiter : '') + val;\r\n groups[groups.length] = group;\r\n groupsByVal[val] = group;\r\n }\r\n\r\n group.rows[group.count++] = r;\r\n }\r\n\r\n if (level < this.groupingInfos.length - 1) {\r\n for (let i = 0; i < groups.length; i++) {\r\n group = groups[i];\r\n group.groups = this.extractGroups(group.rows, group);\r\n }\r\n }\r\n\r\n if (groups.length) {\r\n this.addTotals(groups, level);\r\n }\r\n\r\n groups.sort(this.groupingInfos[level].comparer);\r\n\r\n return groups;\r\n }\r\n\r\n /** claculate Group Totals */\r\n protected calculateTotals(totals: SlickGroupTotals_) {\r\n const group = totals.group;\r\n const gi = this.groupingInfos[group.level ?? 0];\r\n const isLeafLevel = (group.level === this.groupingInfos.length);\r\n let agg: Aggregator;\r\n let idx = gi.aggregators.length;\r\n\r\n if (!isLeafLevel && gi.aggregateChildGroups) {\r\n // make sure all the subgroups are calculated\r\n let i = group.groups?.length ?? 0;\r\n while (i--) {\r\n if (!group.groups[i].totals.initialized) {\r\n this.calculateTotals(group.groups[i].totals);\r\n }\r\n }\r\n }\r\n\r\n while (idx--) {\r\n agg = gi.aggregators[idx];\r\n agg.init();\r\n if (!isLeafLevel && gi.aggregateChildGroups) {\r\n gi.compiledAccumulators[idx].call(agg, group.groups);\r\n } else {\r\n gi.compiledAccumulators[idx].call(agg, group.rows);\r\n }\r\n agg.storeResult(totals);\r\n }\r\n totals.initialized = true;\r\n }\r\n\r\n protected addGroupTotals(group: SlickGroup_) {\r\n const gi = this.groupingInfos[group.level];\r\n const totals = new SlickGroupTotals();\r\n totals.group = group;\r\n group.totals = totals;\r\n if (!gi.lazyTotalsCalculation) {\r\n this.calculateTotals(totals);\r\n }\r\n }\r\n\r\n protected addTotals(groups: SlickGroup_[], level?: number) {\r\n level = level || 0;\r\n const gi = this.groupingInfos[level];\r\n const groupCollapsed = gi.collapsed;\r\n const toggledGroups = this.toggledGroupsByLevel[level];\r\n let idx = groups.length, g;\r\n while (idx--) {\r\n g = groups[idx];\r\n\r\n if (g.collapsed && !gi.aggregateCollapsed) {\r\n continue;\r\n }\r\n\r\n // Do a depth-first aggregation so that parent group aggregators can access subgroup totals.\r\n if (g.groups) {\r\n this.addTotals(g.groups, level + 1);\r\n }\r\n\r\n if (gi.aggregators?.length && (\r\n gi.aggregateEmpty || g.rows.length || g.groups?.length)) {\r\n this.addGroupTotals(g);\r\n }\r\n\r\n g.collapsed = (groupCollapsed as any) ^ toggledGroups[g.groupingKey];\r\n g.title = gi.formatter ? gi.formatter(g) : g.value;\r\n }\r\n }\r\n\r\n protected flattenGroupedRows(groups: SlickGroup_[], level?: number) {\r\n level = level || 0;\r\n const gi = this.groupingInfos[level];\r\n const groupedRows: any[] = [];\r\n let rows: any[];\r\n let gl = 0;\r\n let g;\r\n for (let i = 0, l = groups.length; i < l; i++) {\r\n g = groups[i];\r\n groupedRows[gl++] = g;\r\n\r\n if (!g.collapsed) {\r\n rows = g.groups ? this.flattenGroupedRows(g.groups, level + 1) : g.rows;\r\n for (let j = 0, jj = rows.length; j < jj; j++) {\r\n groupedRows[gl++] = rows[j];\r\n }\r\n }\r\n\r\n if (g.totals && gi.displayTotalsRow && (!g.collapsed || gi.aggregateCollapsed)) {\r\n groupedRows[gl++] = g.totals;\r\n }\r\n }\r\n return groupedRows;\r\n }\r\n\r\n protected compileAccumulatorLoopCSPSafe(aggregator: Aggregator) {\r\n if (aggregator.accumulate) {\r\n return function (items: any[]) {\r\n let result;\r\n for (let i = 0; i < items.length; i++) {\r\n const item = items[i];\r\n result = aggregator.accumulate!.call(aggregator, item);\r\n }\r\n return result;\r\n };\r\n } else {\r\n return function noAccumulator() { };\r\n }\r\n }\r\n\r\n protected compileFilterCSPSafe(items: TData[], args: any): TData[] {\r\n if (typeof this.filterCSPSafe !== 'function') {\r\n return [];\r\n }\r\n const _retval: TData[] = [];\r\n const _il = items.length;\r\n\r\n for (let _i = 0; _i < _il; _i++) {\r\n if (this.filterCSPSafe(items[_i], args)) {\r\n _retval.push(items[_i]);\r\n }\r\n }\r\n\r\n return _retval;\r\n }\r\n\r\n protected compileFilter(stopRunningIfCSPSafeIsActive = false): FilterFn | null {\r\n if (stopRunningIfCSPSafeIsActive) {\r\n return null as any;\r\n }\r\n const filterInfo = Utils.getFunctionDetails(this.filter as FilterFn);\r\n\r\n const filterPath1 = '{ continue _coreloop; }$1';\r\n const filterPath2 = '{ _retval[_idx++] = $item$; continue _coreloop; }$1';\r\n // make some allowances for minification - there's only so far we can go with RegEx\r\n const filterBody = filterInfo.body\r\n .replace(/return false\\s*([;}]|\\}|$)/gi, filterPath1)\r\n .replace(/return!1([;}]|\\}|$)/gi, filterPath1)\r\n .replace(/return true\\s*([;}]|\\}|$)/gi, filterPath2)\r\n .replace(/return!0([;}]|\\}|$)/gi, filterPath2)\r\n .replace(/return ([^;}]+?)\\s*([;}]|$)/gi,\r\n '{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }$2');\r\n\r\n // This preserves the function template code after JS compression,\r\n // so that replace() commands still work as expected.\r\n let tpl = [\r\n // 'function(_items, _args) { ',\r\n 'var _retval = [], _idx = 0; ',\r\n 'var $item$, $args$ = _args; ',\r\n '_coreloop: ',\r\n 'for (var _i = 0, _il = _items.length; _i < _il; _i++) { ',\r\n '$item$ = _items[_i]; ',\r\n '$filter$; ',\r\n '} ',\r\n 'return _retval; '\r\n // '}'\r\n ].join('');\r\n tpl = tpl.replace(/\\$filter\\$/gi, filterBody);\r\n tpl = tpl.replace(/\\$item\\$/gi, filterInfo.params[0]);\r\n tpl = tpl.replace(/\\$args\\$/gi, filterInfo.params[1]);\r\n const fn: any = new Function('_items,_args', tpl);\r\n const fnName = 'compiledFilter';\r\n fn.displayName = fnName;\r\n fn.name = this.setFunctionName(fn, fnName);\r\n return fn;\r\n }\r\n\r\n protected compileFilterWithCaching(stopRunningIfCSPSafeIsActive = false) {\r\n if (stopRunningIfCSPSafeIsActive) {\r\n return null as any;\r\n }\r\n\r\n const filterInfo = Utils.getFunctionDetails(this.filter as FilterFn);\r\n\r\n const filterPath1 = '{ continue _coreloop; }$1';\r\n const filterPath2 = '{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }$1';\r\n // make some allowances for minification - there's only so far we can go with RegEx\r\n const filterBody = filterInfo.body\r\n .replace(/return false\\s*([;}]|\\}|$)/gi, filterPath1)\r\n .replace(/return!1([;}]|\\}|$)/gi, filterPath1)\r\n .replace(/return true\\s*([;}]|\\}|$)/gi, filterPath2)\r\n .replace(/return!0([;}]|\\}|$)/gi, filterPath2)\r\n .replace(/return ([^;}]+?)\\s*([;}]|$)/gi,\r\n '{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }$2');\r\n\r\n // This preserves the function template code after JS compression,\r\n // so that replace() commands still work as expected.\r\n let tpl = [\r\n // 'function(_items, _args, _cache) { ',\r\n 'var _retval = [], _idx = 0; ',\r\n 'var $item$, $args$ = _args; ',\r\n '_coreloop: ',\r\n 'for (var _i = 0, _il = _items.length; _i < _il; _i++) { ',\r\n '$item$ = _items[_i]; ',\r\n 'if (_cache[_i]) { ',\r\n '_retval[_idx++] = $item$; ',\r\n 'continue _coreloop; ',\r\n '} ',\r\n '$filter$; ',\r\n '} ',\r\n 'return _retval; '\r\n // '}'\r\n ].join('');\r\n tpl = tpl.replace(/\\$filter\\$/gi, filterBody);\r\n tpl = tpl.replace(/\\$item\\$/gi, filterInfo.params[0]);\r\n tpl = tpl.replace(/\\$args\\$/gi, filterInfo.params[1]);\r\n\r\n const fn: any = new Function('_items,_args,_cache', tpl);\r\n const fnName = 'compiledFilterWithCaching';\r\n fn.displayName = fnName;\r\n fn.name = this.setFunctionName(fn, fnName);\r\n return fn;\r\n }\r\n\r\n protected compileFilterWithCachingCSPSafe(items: TData[], args: any, filterCache: any[]): TData[] {\r\n if (typeof this.filterCSPSafe !== 'function') {\r\n return [];\r\n }\r\n\r\n const retval: TData[] = [];\r\n const il = items.length;\r\n\r\n for (let _i = 0; _i < il; _i++) {\r\n if (filterCache[_i] || this.filterCSPSafe(items[_i], args)) {\r\n retval.push(items[_i]);\r\n }\r\n }\r\n\r\n return retval;\r\n }\r\n\r\n /**\r\n * In ES5 we could set the function name on the fly but in ES6 this is forbidden and we need to set it through differently\r\n * We can use Object.defineProperty and set it the property to writable, see MDN for reference\r\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\r\n * @param {*} fn\r\n * @param {string} fnName\r\n */\r\n protected setFunctionName(fn: any, fnName: string) {\r\n try {\r\n Object.defineProperty(fn, 'name', { writable: true, value: fnName });\r\n } catch (err) {\r\n fn.name = fnName;\r\n }\r\n }\r\n\r\n protected uncompiledFilter(items: TData[], args: any) {\r\n const retval: any[] = [];\r\n let idx = 0;\r\n\r\n for (let i = 0, ii = items.length; i < ii; i++) {\r\n if (this.filter?.(items[i], args)) {\r\n retval[idx++] = items[i];\r\n }\r\n }\r\n\r\n return retval;\r\n }\r\n\r\n protected uncompiledFilterWithCaching(items: TData[], args: any, cache: any) {\r\n const retval: any[] = [];\r\n let idx = 0,\r\n item: TData;\r\n\r\n for (let i = 0, ii = items.length; i < ii; i++) {\r\n item = items[i];\r\n if (cache[i]) {\r\n retval[idx++] = item;\r\n } else if (this.filter?.(item, args)) {\r\n retval[idx++] = item;\r\n cache[i] = true;\r\n }\r\n }\r\n\r\n return retval;\r\n }\r\n\r\n protected getFilteredAndPagedItems(items: TData[]) {\r\n if (this._options.useCSPSafeFilter ? this.filterCSPSafe : this.filter) {\r\n let batchFilter: AnyFunction;\r\n let batchFilterWithCaching: AnyFunction;\r\n if (this._options.useCSPSafeFilter) {\r\n batchFilter = (this._options.inlineFilters ? this.compiledFilterCSPSafe : this.uncompiledFilter) as AnyFunction;\r\n batchFilterWithCaching = (this._options.inlineFilters ? this.compiledFilterWithCachingCSPSafe : this.uncompiledFilterWithCaching) as AnyFunction;\r\n } else {\r\n batchFilter = (this._options.inlineFilters ? this.compiledFilter : this.uncompiledFilter) as AnyFunction;\r\n batchFilterWithCaching = (this._options.inlineFilters ? this.compiledFilterWithCaching : this.uncompiledFilterWithCaching) as AnyFunction;\r\n }\r\n if (this.refreshHints.isFilterNarrowing) {\r\n this.filteredItems = batchFilter.call(this, this.filteredItems, this.filterArgs);\r\n } else if (this.refreshHints.isFilterExpanding) {\r\n this.filteredItems = batchFilterWithCaching.call(this, items, this.filterArgs, this.filterCache);\r\n } else if (!this.refreshHints.isFilterUnchanged) {\r\n this.filteredItems = batchFilter.call(this, items, this.filterArgs);\r\n }\r\n } else {\r\n // special case: if not filtering and not paging, the resulting\r\n // rows collection needs to be a copy so that changes due to sort\r\n // can be caught\r\n this.filteredItems = this.pagesize ? items : items.concat();\r\n }\r\n\r\n // get the current page\r\n let paged: TData[];\r\n if (this.pagesize) {\r\n if (this.filteredItems.length <= this.pagenum * this.pagesize) {\r\n if (this.filteredItems.length === 0) {\r\n this.pagenum = 0;\r\n } else {\r\n this.pagenum = Math.floor((this.filteredItems.length - 1) / this.pagesize);\r\n }\r\n }\r\n paged = this.filteredItems.slice(this.pagesize * this.pagenum, this.pagesize * this.pagenum + this.pagesize);\r\n } else {\r\n paged = this.filteredItems;\r\n }\r\n return { totalRows: this.filteredItems.length, rows: paged };\r\n }\r\n\r\n protected getRowDiffs(rows: TData[], newRows: TData[]) {\r\n let item: TData | SlickNonDataItem | SlickDataItem | SlickGroup_;\r\n let r;\r\n let eitherIsNonData;\r\n const diff: number[] = [];\r\n let from = 0;\r\n let to = Math.max(newRows.length, rows.length);\r\n\r\n if (this.refreshHints?.ignoreDiffsBefore) {\r\n from = Math.max(0,\r\n Math.min(newRows.length, this.refreshHints.ignoreDiffsBefore));\r\n }\r\n\r\n if (this.refreshHints?.ignoreDiffsAfter) {\r\n to = Math.min(newRows.length,\r\n Math.max(0, this.refreshHints.ignoreDiffsAfter));\r\n }\r\n\r\n for (let i = from, rl = rows.length; i < to; i++) {\r\n if (i >= rl) {\r\n diff[diff.length] = i;\r\n } else {\r\n item = newRows[i];\r\n r = rows[i];\r\n\r\n if (!item || (this.groupingInfos.length && (eitherIsNonData = ((item as SlickNonDataItem).__nonDataRow) || ((r as SlickNonDataItem).__nonDataRow)) &&\r\n (item as SlickGroup_).__group !== (r as SlickGroup_).__group ||\r\n (item as SlickGroup_).__group && !(item as SlickGroup_).equals(r as SlickGroup_))\r\n || (eitherIsNonData &&\r\n // no good way to compare totals since they are arbitrary DTOs\r\n // deep object comparison is pretty expensive\r\n // always considering them 'dirty' seems easier for the time being\r\n ((item as SlickGroupTotals_).__groupTotals || (r as SlickGroupTotals_).__groupTotals))\r\n || item[this.idProperty as keyof TData] !== r[this.idProperty as keyof TData]\r\n || (this.updated?.[item[this.idProperty as keyof TData]])\r\n ) {\r\n diff[diff.length] = i;\r\n }\r\n }\r\n }\r\n return diff;\r\n }\r\n\r\n protected recalc(_items: TData[]) {\r\n this.rowsById = undefined;\r\n\r\n if (this.refreshHints.isFilterNarrowing !== this.prevRefreshHints.isFilterNarrowing ||\r\n this.refreshHints.isFilterExpanding !== this.prevRefreshHints.isFilterExpanding) {\r\n this.filterCache = [];\r\n }\r\n\r\n const filteredItems = this.getFilteredAndPagedItems(_items);\r\n this.totalRows = filteredItems.totalRows;\r\n let newRows: TData[] = filteredItems.rows;\r\n\r\n this.groups = [];\r\n if (this.groupingInfos.length) {\r\n this.groups = this.extractGroups(newRows);\r\n if (this.groups.length) {\r\n newRows = this.flattenGroupedRows(this.groups);\r\n }\r\n }\r\n\r\n const diff = this.getRowDiffs(this.rows, newRows as TData[]);\r\n\r\n this.rows = newRows as TData[];\r\n\r\n return diff;\r\n }\r\n\r\n refresh() {\r\n if (this.suspend) {\r\n return;\r\n }\r\n\r\n const previousPagingInfo = Utils.extend(true, {}, this.getPagingInfo());\r\n\r\n const countBefore = this.rows.length;\r\n const totalRowsBefore = this.totalRows;\r\n\r\n let diff = this.recalc(this.items); // pass as direct refs to avoid closure perf hit\r\n\r\n // if the current page is no longer valid, go to last page and recalc\r\n // we suffer a performance penalty here, but the main loop (recalc) remains highly optimized\r\n if (this.pagesize && this.totalRows < this.pagenum * this.pagesize) {\r\n this.pagenum = Math.max(0, Math.ceil(this.totalRows / this.pagesize) - 1);\r\n diff = this.recalc(this.items);\r\n }\r\n\r\n this.updated = null;\r\n this.prevRefreshHints = this.refreshHints;\r\n this.refreshHints = {};\r\n\r\n if (totalRowsBefore !== this.totalRows) {\r\n // use the previously saved paging info\r\n if (this.onBeforePagingInfoChanged.notify(previousPagingInfo, null, this).getReturnValue() !== false) {\r\n this.onPagingInfoChanged.notify(this.getPagingInfo(), null, this);\r\n }\r\n }\r\n if (countBefore !== this.rows.length) {\r\n this.onRowCountChanged.notify({ previous: countBefore, current: this.rows.length, itemCount: this.items.length, dataView: this, callingOnRowsChanged: (diff.length > 0) }, null, this);\r\n }\r\n if (diff.length > 0) {\r\n this.onRowsChanged.notify({ rows: diff, itemCount: this.items.length, dataView: this, calledOnRowCountChanged: (countBefore !== this.rows.length) }, null, this);\r\n }\r\n if (countBefore !== this.rows.length || diff.length > 0) {\r\n this.onRowsOrCountChanged.notify({\r\n rowsDiff: diff, previousRowCount: countBefore, currentRowCount: this.rows.length, itemCount: this.items.length,\r\n rowCountChanged: countBefore !== this.rows.length, rowsChanged: diff.length > 0, dataView: this\r\n }, null, this);\r\n }\r\n }\r\n\r\n /**\r\n * Wires the grid and the DataView together to keep row selection tied to item ids.\r\n * This is useful since, without it, the grid only knows about rows, so if the items\r\n * move around, the same rows stay selected instead of the selection moving along\r\n * with the items.\r\n *\r\n * NOTE: This doesn't work with cell selection model.\r\n *\r\n * @param {SlickGrid} grid - The grid to sync selection with.\r\n * @param {Boolean} preserveHidden - Whether to keep selected items that go out of the\r\n * view due to them getting filtered out.\r\n * @param {Boolean} [preserveHiddenOnSelectionChange] - Whether to keep selected items\r\n * that are currently out of the view (see preserveHidden) as selected when selection\r\n * changes.\r\n * @return {Event} An event that notifies when an internal list of selected row ids\r\n * changes. This is useful since, in combination with the above two options, it allows\r\n * access to the full list selected row ids, and not just the ones visible to the grid.\r\n * @method syncGridSelection\r\n */\r\n syncGridSelection(grid: SlickGridModel, preserveHidden: boolean, preserveHiddenOnSelectionChange?: boolean) {\r\n this._grid = grid;\r\n let inHandler: boolean;\r\n this.selectedRowIds = this.mapRowsToIds(grid.getSelectedRows());\r\n\r\n /** @param {Array} rowIds */\r\n const setSelectedRowIds = (rowIds: DataIdType[] | false) => {\r\n if (rowIds === false) {\r\n this.selectedRowIds = [];\r\n } else {\r\n if (this.selectedRowIds!.sort().join(',') !== rowIds.sort().join(',')) {\r\n this.selectedRowIds = rowIds;\r\n }\r\n }\r\n };\r\n\r\n const update = () => {\r\n if ((this.selectedRowIds || []).length > 0 && !inHandler) {\r\n inHandler = true;\r\n const selectedRows = this.mapIdsToRows(this.selectedRowIds || []);\r\n if (!preserveHidden) {\r\n const selectedRowsChangedArgs = {\r\n grid: this._grid,\r\n ids: this.mapRowsToIds(selectedRows),\r\n rows: selectedRows,\r\n dataView: this\r\n };\r\n this.preSelectedRowIdsChangeFn!(selectedRowsChangedArgs);\r\n this.onSelectedRowIdsChanged.notify(Object.assign(selectedRowsChangedArgs, {\r\n selectedRowIds: this.selectedRowIds,\r\n filteredIds: this.getAllSelectedFilteredIds() as DataIdType[],\r\n }), new SlickEventData(), this);\r\n }\r\n grid.setSelectedRows(selectedRows);\r\n inHandler = false;\r\n }\r\n };\r\n\r\n grid.onSelectedRowsChanged.subscribe((_e: SlickEventData_, args: { rows: number[]; }) => {\r\n if (!inHandler) {\r\n const newSelectedRowIds = this.mapRowsToIds(args.rows);\r\n const selectedRowsChangedArgs = {\r\n grid: this._grid,\r\n ids: newSelectedRowIds,\r\n rows: args.rows,\r\n added: true,\r\n dataView: this\r\n };\r\n this.preSelectedRowIdsChangeFn!(selectedRowsChangedArgs);\r\n this.onSelectedRowIdsChanged.notify(Object.assign(selectedRowsChangedArgs, {\r\n selectedRowIds: this.selectedRowIds,\r\n filteredIds: this.getAllSelectedFilteredIds() as DataIdType[],\r\n }), new SlickEventData(), this);\r\n }\r\n });\r\n\r\n this.preSelectedRowIdsChangeFn = (args: { ids: DataIdType[]; added?: boolean; }) => {\r\n if (!inHandler) {\r\n inHandler = true;\r\n const overwrite = (typeof args.added === typeof undefined);\r\n\r\n if (overwrite) {\r\n setSelectedRowIds(args.ids);\r\n } else {\r\n let rowIds: DataIdType[];\r\n if (args.added) {\r\n if (preserveHiddenOnSelectionChange && grid.getOptions().multiSelect) {\r\n // find the ones that are hidden\r\n const hiddenSelectedRowIds = this.selectedRowIds?.filter((id) => this.getRowById(id) === undefined);\r\n // add the newly selected ones\r\n rowIds = hiddenSelectedRowIds!.concat(args.ids);\r\n } else {\r\n rowIds = args.ids;\r\n }\r\n } else {\r\n if (preserveHiddenOnSelectionChange && grid.getOptions().multiSelect) {\r\n // remove rows whose id is on the list\r\n const argsIdsSet = new Set(args.ids);\r\n rowIds = this.selectedRowIds?.filter((id) => !argsIdsSet.has(id));\r\n } else {\r\n rowIds = [];\r\n }\r\n }\r\n setSelectedRowIds(rowIds);\r\n }\r\n inHandler = false;\r\n }\r\n };\r\n\r\n this.onRowsOrCountChanged.subscribe(update.bind(this));\r\n\r\n return this.onSelectedRowIdsChanged;\r\n }\r\n\r\n /**\r\n * Get all selected IDs\r\n * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true.\r\n */\r\n getAllSelectedIds() {\r\n return this.selectedRowIds;\r\n }\r\n\r\n /**\r\n * Get all selected filtered IDs (similar to \"getAllSelectedIds\" but only return filtered data)\r\n * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true.\r\n */\r\n getAllSelectedFilteredIds() {\r\n return this.getAllSelectedFilteredItems().map((item) => item[this.idProperty as keyof TData]);\r\n }\r\n\r\n /**\r\n * Set current row selected IDs array (regardless of Pagination)\r\n * NOTE: This will NOT change the selection in the grid, if you need to do that then you still need to call\r\n * \"grid.setSelectedRows(rows)\"\r\n * @param {Array} selectedIds - list of IDs which have been selected for this action\r\n * @param {Object} options\r\n * - `isRowBeingAdded`: defaults to true, are the new selected IDs being added (or removed) as new row selections\r\n * - `shouldTriggerEvent`: defaults to true, should we trigger `onSelectedRowIdsChanged` event\r\n * - `applyRowSelectionToGrid`: defaults to true, should we apply the row selections to the grid in the UI\r\n */\r\n setSelectedIds(selectedIds: Array, options?: Partial<{ isRowBeingAdded: boolean; shouldTriggerEvent: boolean; applyRowSelectionToGrid: boolean; }>) {\r\n let isRowBeingAdded = options?.isRowBeingAdded;\r\n const shouldTriggerEvent = options?.shouldTriggerEvent;\r\n const applyRowSelectionToGrid = options?.applyRowSelectionToGrid;\r\n\r\n if (isRowBeingAdded !== false) {\r\n isRowBeingAdded = true;\r\n }\r\n const selectedRows = this.mapIdsToRows(selectedIds);\r\n const selectedRowsChangedArgs = {\r\n grid: this._grid,\r\n ids: selectedIds,\r\n rows: selectedRows,\r\n added: isRowBeingAdded,\r\n dataView: this\r\n };\r\n this.preSelectedRowIdsChangeFn?.(selectedRowsChangedArgs);\r\n\r\n if (shouldTriggerEvent !== false) {\r\n this.onSelectedRowIdsChanged.notify(Object.assign(selectedRowsChangedArgs, {\r\n selectedRowIds: this.selectedRowIds,\r\n filteredIds: this.getAllSelectedFilteredIds() as DataIdType[],\r\n }), new SlickEventData(), this);\r\n }\r\n\r\n // should we also apply the row selection in to the grid (UI) as well?\r\n if (applyRowSelectionToGrid !== false && this._grid) {\r\n this._grid.setSelectedRows(selectedRows);\r\n }\r\n }\r\n\r\n /**\r\n * Get all selected dataContext items\r\n * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true.\r\n */\r\n getAllSelectedItems() {\r\n const selectedData: TData[] = [];\r\n const selectedIds = this.getAllSelectedIds();\r\n selectedIds!.forEach((id) => {\r\n selectedData.push(this.getItemById(id));\r\n });\r\n return selectedData as T[];\r\n }\r\n\r\n /**\r\n * Get all selected filtered dataContext items (similar to \"getAllSelectedItems\" but only return filtered data)\r\n * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true.\r\n */\r\n getAllSelectedFilteredItems() {\r\n if (!Array.isArray(this.selectedRowIds)) {\r\n return [];\r\n }\r\n\r\n const selectedRowIdSet = new Set(this.selectedRowIds);\r\n const intersection = this.filteredItems.filter((a) => selectedRowIdSet.has(a[this.idProperty as keyof TData] as DataIdType));\r\n return (intersection || []) as T[];\r\n }\r\n\r\n syncGridCellCssStyles(grid: SlickGridModel, key: string) {\r\n let hashById: any;\r\n let inHandler: boolean;\r\n\r\n const storeCellCssStyles = (hash: CssStyleHash) => {\r\n hashById = {};\r\n if (typeof hash === 'object') {\r\n Object.keys(hash).forEach(row => {\r\n if (hash) {\r\n const id = this.rows[row as any][this.idProperty as keyof TData];\r\n hashById[id] = hash[row];\r\n }\r\n });\r\n }\r\n };\r\n\r\n // since this method can be called after the cell styles have been set,\r\n // get the existing ones right away\r\n storeCellCssStyles(grid.getCellCssStyles(key));\r\n\r\n const update = () => {\r\n if (typeof hashById === 'object') {\r\n inHandler = true;\r\n this.ensureRowsByIdCache();\r\n const newHash: CssStyleHash = {};\r\n Object.keys(hashById).forEach(id => {\r\n const row = this.rowsById?.[id];\r\n if (Utils.isDefined(row)) {\r\n newHash[row as number] = hashById[id];\r\n }\r\n });\r\n grid.setCellCssStyles(key, newHash);\r\n inHandler = false;\r\n }\r\n };\r\n\r\n grid.onCellCssStylesChanged.subscribe((_e: SlickEventData_, args: any) => {\r\n if (inHandler) { return; }\r\n if (key !== args.key) { return; }\r\n if (args.hash) {\r\n storeCellCssStyles(args.hash);\r\n } else {\r\n grid.onCellCssStylesChanged.unsubscribe();\r\n this.onRowsOrCountChanged.unsubscribe(update);\r\n }\r\n });\r\n\r\n this.onRowsOrCountChanged.subscribe(update.bind(this));\r\n }\r\n}\r\n\r\nexport class AvgAggregator implements Aggregator {\r\n private _nonNullCount = 0;\r\n private _sum = 0;\r\n private _field: number | string;\r\n private _type = 'avg' as const;\r\n\r\n constructor(field: number | string) {\r\n this._field = field;\r\n }\r\n\r\n get field(): number | string {\r\n return this._field;\r\n }\r\n\r\n get type(): string {\r\n return this._type;\r\n }\r\n\r\n init(): void {\r\n this._nonNullCount = 0;\r\n this._sum = 0;\r\n }\r\n\r\n accumulate(item: T) {\r\n const val: any = (item?.hasOwnProperty(this._field)) ? item[this._field as keyof T] : null;\r\n if (val !== null && val !== '' && !isNaN(val)) {\r\n this._nonNullCount++;\r\n this._sum += parseFloat(val);\r\n }\r\n }\r\n\r\n storeResult(groupTotals: SlickGroupTotals_ & { avg: Record; }) {\r\n if (!groupTotals || groupTotals[this._type] === undefined) {\r\n (groupTotals as any)[this._type] = {};\r\n }\r\n if (this._nonNullCount !== 0) {\r\n groupTotals[this._type][this._field] = this._sum / this._nonNullCount;\r\n }\r\n }\r\n}\r\n\r\nexport class MinAggregator implements Aggregator {\r\n private _min: number | null = null;\r\n private _field: number | string;\r\n private _type = 'min' as const;\r\n\r\n constructor(field: number | string) {\r\n this._field = field;\r\n }\r\n\r\n get field(): number | string {\r\n return this._field;\r\n }\r\n\r\n get type(): string {\r\n return this._type;\r\n }\r\n\r\n init() {\r\n this._min = null;\r\n }\r\n\r\n accumulate(item: T) {\r\n const val: any = (item?.hasOwnProperty(this._field)) ? item[this._field as keyof T] : null;\r\n if (val !== null && val !== '' && !isNaN(val)) {\r\n if (this._min === null || val < this._min) {\r\n this._min = parseFloat(val);\r\n }\r\n }\r\n }\r\n\r\n storeResult(groupTotals: SlickGroupTotals_ & { min: Record; }) {\r\n if (!groupTotals || groupTotals[this._type] === undefined) {\r\n groupTotals[this._type] = {};\r\n }\r\n groupTotals[this._type][this._field] = this._min;\r\n }\r\n}\r\n\r\nexport class MaxAggregator implements Aggregator {\r\n private _max: number | null = null;\r\n private _field: number | string;\r\n private _type = 'max' as const;\r\n\r\n constructor(field: number | string) {\r\n this._field = field;\r\n }\r\n\r\n get field(): number | string {\r\n return this._field;\r\n }\r\n\r\n get type(): string {\r\n return this._type;\r\n }\r\n\r\n init(): void {\r\n this._max = null;\r\n }\r\n\r\n accumulate(item: T) {\r\n const val: any = (item?.hasOwnProperty(this._field)) ? item[this._field as keyof T] : null;\r\n if (val !== null && val !== '' && !isNaN(val)) {\r\n if (this._max === null || val > this._max) {\r\n this._max = parseFloat(val);\r\n }\r\n }\r\n }\r\n\r\n storeResult(groupTotals: SlickGroupTotals_ & { max: Record; }) {\r\n if (!groupTotals || groupTotals[this._type] === undefined) {\r\n groupTotals[this._type] = {};\r\n }\r\n groupTotals[this._type][this._field] = this._max;\r\n }\r\n}\r\n\r\nexport class SumAggregator implements Aggregator {\r\n private _sum = 0;\r\n private _field: number | string;\r\n private _type = 'sum' as const;\r\n\r\n constructor(field: number | string) {\r\n this._field = field;\r\n }\r\n\r\n get field(): number | string {\r\n return this._field;\r\n }\r\n\r\n get type(): string {\r\n return this._type;\r\n }\r\n\r\n init() {\r\n this._sum = 0;\r\n }\r\n\r\n accumulate(item: T) {\r\n const val: any = (item?.hasOwnProperty(this._field)) ? item[this._field as keyof T] : null;\r\n if (val !== null && val !== '' && !isNaN(val)) {\r\n this._sum += parseFloat(val);\r\n }\r\n }\r\n\r\n storeResult(groupTotals: SlickGroupTotals_ & { sum: Record; }) {\r\n if (!groupTotals || groupTotals[this._type] === undefined) {\r\n groupTotals[this._type] = {};\r\n }\r\n groupTotals[this._type][this._field] = this._sum;\r\n }\r\n}\r\n\r\nexport class CountAggregator implements Aggregator {\r\n private _field: number | string;\r\n private _type = 'count' as const;\r\n\r\n constructor(field: number | string) {\r\n this._field = field;\r\n }\r\n\r\n get field(): number | string {\r\n return this._field;\r\n }\r\n\r\n get type(): string {\r\n return this._type;\r\n }\r\n\r\n init(): void {\r\n }\r\n\r\n storeResult(groupTotals: SlickGroupTotals_ & { count: Record; }) {\r\n if (!groupTotals || groupTotals[this._type] === undefined) {\r\n groupTotals[this._type] = {};\r\n }\r\n groupTotals[this._type][this._field] = groupTotals.group.rows.length;\r\n }\r\n}\r\n\r\n// TODO: add more built-in aggregators\r\n// TODO: merge common aggregators in one to prevent needless iterating\r\n\r\nexport const Aggregators = {\r\n Avg: AvgAggregator,\r\n Min: MinAggregator,\r\n Max: MaxAggregator,\r\n Sum: SumAggregator,\r\n Count: CountAggregator\r\n};\r\n\r\n// extend Slick namespace on window object when building as iife\r\nif (IIFE_ONLY && window.Slick) {\r\n window.Slick.Data = window.Slick.Data || {};\r\n window.Slick.Data.DataView = SlickDataView;\r\n window.Slick.Data.Aggregators = Aggregators;\r\n}\r\n"], + "mappings": "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", "names": ["_a", "_b"] } diff --git a/dist/browser/slick.grid.js b/dist/browser/slick.grid.js index 238d55b2..88d8c6cb 100644 --- a/dist/browser/slick.grid.js +++ b/dist/browser/slick.grid.js @@ -24,7 +24,7 @@ this.externalPubSub = externalPubSub; ////////////////////////////////////////////////////////////////////////////////////////////// // Public API - __publicField(this, "slickGridVersion", "5.14.3"); + __publicField(this, "slickGridVersion", "5.15.0"); /** optional grid state clientId */ __publicField(this, "cid", ""); // Events @@ -143,6 +143,7 @@ rowHighlightDuration: 400, selectedCellCssClass: "selected", multiSelect: !0, + enableCellRowSpan: !1, enableTextSelectionOnCells: !1, dataItemColumnValueExtractor: null, frozenBottom: !1, @@ -179,6 +180,7 @@ suppressCssChangesOnHiddenInit: !1, ffMaxSupportedCssHeight: 6e6, maxSupportedCssHeight: 1e9, + maxPartialRowSpanRemap: 5e3, sanitizer: void 0, // sanitize function, built in basic sanitizer is: Slick.RegexSanitizer(dirtyHtml) logSanitizedHtml: !1, @@ -302,12 +304,17 @@ __publicField(this, "_activeCanvasNode"); __publicField(this, "_activeViewportNode"); __publicField(this, "activePosX"); + __publicField(this, "activePosY"); __publicField(this, "activeRow"); __publicField(this, "activeCell"); __publicField(this, "activeCellNode", null); __publicField(this, "currentEditor", null); __publicField(this, "serializedEditorValue"); __publicField(this, "editController"); + __publicField(this, "_prevDataLength", 0); + __publicField(this, "_prevInvalidatedRowsCount", 0); + __publicField(this, "_rowSpanIsCached", !1); + __publicField(this, "_colsWithRowSpanCache", {}); __publicField(this, "rowsCache", {}); __publicField(this, "renderedRows", 0); __publicField(this, "numVisibleRows", 0); @@ -331,7 +338,6 @@ __publicField(this, "scrollThrottle"); // async call handles __publicField(this, "h_editorLoader"); - __publicField(this, "h_render", null); __publicField(this, "h_postrender"); __publicField(this, "h_postrenderCleanup"); __publicField(this, "postProcessedRows", {}); @@ -452,7 +458,7 @@ this._bindingEventService.bind(view, "selectstart", (event) => { event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement; }); - }), this.setFrozenOptions(), this.setPaneVisibility(), this.setScroller(), this.setOverflow(), this.updateColumnCaches(), this.createColumnHeaders(), this.createColumnFooter(), this.setupColumnSort(), this.createCssRules(), this.resizeCanvas(), this.bindAncestorScrollEvents(), this._bindingEventService.bind(this._container, "resize", this.resizeCanvas.bind(this)), this._viewport.forEach((view) => { + }), this.setFrozenOptions(), this.setPaneFrozenClasses(), this.setPaneVisibility(), this.setScroller(), this.setOverflow(), this.updateColumnCaches(), this.createColumnHeaders(), this.createColumnFooter(), this.setupColumnSort(), this.createCssRules(), this.resizeCanvas(), this.bindAncestorScrollEvents(), this._bindingEventService.bind(this._container, "resize", this.resizeCanvas.bind(this)), this._viewport.forEach((view) => { this._bindingEventService.bind(view, "scroll", this.handleScroll.bind(this)); }), this._options.enableMouseWheelScrollHandler && this._viewport.forEach((view) => { this.slickMouseWheelInstances.push(MouseWheel({ @@ -1035,6 +1041,12 @@ } else this.hasFrozenRows = !1; } + /** add/remove frozen class to left headers/footer when defined */ + setPaneFrozenClasses() { + let classAction = this.hasFrozenColumns() ? "add" : "remove"; + for (let elm of [this._paneHeaderL, this._paneTopL, this._paneBottomL]) + elm.classList[classAction]("frozen"); + } setPaneVisibility() { this.hasFrozenColumns() ? (Utils.show(this._paneHeaderR), Utils.show(this._paneTopR), this.hasFrozenRows ? (Utils.show(this._paneBottomL), Utils.show(this._paneBottomR)) : (Utils.hide(this._paneBottomR), Utils.hide(this._paneBottomL))) : (Utils.hide(this._paneHeaderR), Utils.hide(this._paneTopR), Utils.hide(this._paneBottomR), this.hasFrozenRows ? Utils.show(this._paneBottomL) : (Utils.hide(this._paneBottomR), Utils.hide(this._paneBottomL))); } @@ -1526,7 +1538,7 @@ } updateColumnsInternal() { var _a; - this.updateColumnProps(), this.updateColumnCaches(), this.initialized && (this.setPaneVisibility(), this.setOverflow(), this.invalidateAllRows(), this.createColumnHeaders(), this.createColumnFooter(), this.removeCssRules(), this.createCssRules(), this.resizeCanvas(), this.updateCanvasWidth(), this.applyColumnHeaderWidths(), this.applyColumnWidths(), this.handleScroll(), (_a = this.getSelectionModel()) == null || _a.refreshSelections()); + this.updateColumnProps(), this.updateColumnCaches(), this.initialized && (this.setPaneFrozenClasses(), this.setPaneVisibility(), this.setOverflow(), this.invalidateAllRows(), this.createColumnHeaders(), this.createColumnFooter(), this.removeCssRules(), this.createCssRules(), this.resizeCanvas(), this.updateCanvasWidth(), this.applyColumnHeaderWidths(), this.applyColumnWidths(), this.handleScroll(), (_a = this.getSelectionModel()) == null || _a.refreshSelections()); } /** Returns an object containing all of the Grid options set on the grid. See a list of Grid Options here. */ getOptions() { @@ -1598,6 +1610,14 @@ getDataItem(i) { return this.data.getItem ? this.data.getItem(i) : this.data[i]; } + /** + * Returns item metadata by a row index when it exists + * @param {Number} row + * @returns {ItemMetadata | null} + */ + getItemMetadaWhenExists(row) { + return "getItemMetadata" in this.data ? this.data.getItemMetadata(row) : null; + } /** Get Top Panel DOM element */ getTopPanel() { return this._topPanels[0]; @@ -1680,9 +1700,15 @@ } ////////////////////////////////////////////////////////////////////////////////////////////// // Rendering / Scrolling + getRowHeight() { + return this._options.rowHeight; + } getRowTop(row) { return Math.round(this._options.rowHeight * row - this.offset); } + getRowBottom(row) { + return this.getRowTop(row) + this._options.rowHeight; + } getRowFromPosition(y) { return Math.floor((y + this.offset) / this._options.rowHeight); } @@ -1711,43 +1737,48 @@ return (columnOverrides == null ? void 0 : columnOverrides.formatter) || (rowMetadata == null ? void 0 : rowMetadata.formatter) || column.formatter || ((_c = this._options.formatterFactory) == null ? void 0 : _c.getFormatter(column)) || this._options.defaultFormatter; } getEditor(row, cell) { - var _a, _b, _c, _d, _e, _f; - let column = this.columns[cell], rowMetadata = (_b = (_a = this.data) == null ? void 0 : _a.getItemMetadata) == null ? void 0 : _b.call(_a, row), columnMetadata = rowMetadata == null ? void 0 : rowMetadata.columns; - return ((_c = columnMetadata == null ? void 0 : columnMetadata[column.id]) == null ? void 0 : _c.editor) !== void 0 ? columnMetadata[column.id].editor : ((_d = columnMetadata == null ? void 0 : columnMetadata[cell]) == null ? void 0 : _d.editor) !== void 0 ? columnMetadata[cell].editor : column.editor || ((_f = (_e = this._options) == null ? void 0 : _e.editorFactory) == null ? void 0 : _f.getEditor(column)); + var _a, _b, _c, _d; + let column = this.columns[cell], rowMetadata = this.getItemMetadaWhenExists(row), columnMetadata = rowMetadata == null ? void 0 : rowMetadata.columns; + return ((_a = columnMetadata == null ? void 0 : columnMetadata[column.id]) == null ? void 0 : _a.editor) !== void 0 ? columnMetadata[column.id].editor : ((_b = columnMetadata == null ? void 0 : columnMetadata[cell]) == null ? void 0 : _b.editor) !== void 0 ? columnMetadata[cell].editor : column.editor || ((_d = (_c = this._options) == null ? void 0 : _c.editorFactory) == null ? void 0 : _d.getEditor(column)); } getDataItemValueForColumn(item, columnDef) { return this._options.dataItemColumnValueExtractor ? this._options.dataItemColumnValueExtractor(item, columnDef) : item[columnDef.field]; } appendRowHtml(divArrayL, divArrayR, row, range, dataLength) { - var _a, _b; let d = this.getDataItem(row), dataLoading = row < dataLength && !d, rowCss = "slick-row" + (this.hasFrozenRows && row <= this._options.frozenRow ? " frozen" : "") + (dataLoading ? " loading" : "") + (row === this.activeRow && this._options.showCellSelection ? " active" : "") + (row % 2 === 1 ? " odd" : " even"); - d || (rowCss += " " + this._options.addNewRowCssClass); - let metadata = (_b = (_a = this.data) == null ? void 0 : _a.getItemMetadata) == null ? void 0 : _b.call(_a, row); - metadata != null && metadata.cssClasses && (rowCss += " " + metadata.cssClasses); - let rowDiv = Utils.createDomElement("div", { className: `ui-widget-content ${rowCss}`, role: "row" }), frozenRowOffset = this.getFrozenRowOffset(row), topOffset = this.getRowTop(row) - frozenRowOffset; + d || (rowCss += ` ${this._options.addNewRowCssClass}`); + let metadata = this.getItemMetadaWhenExists(row); + metadata != null && metadata.cssClasses && (rowCss += ` ${metadata.cssClasses}`); + let rowDiv = Utils.createDomElement("div", { + className: `ui-widget-content ${rowCss}`, + role: "row", + dataset: { row: `${row}` } + }), frozenRowOffset = this.getFrozenRowOffset(row), topOffset = this.getRowTop(row) - frozenRowOffset; this._options.rowTopOffsetRenderType === "transform" ? rowDiv.style.transform = `translateY(${topOffset}px)` : rowDiv.style.top = `${topOffset}px`; let rowDivR; divArrayL.push(rowDiv), this.hasFrozenColumns() && (rowDivR = rowDiv.cloneNode(!0), divArrayR.push(rowDivR)); - let colspan, m; - for (let i = 0, ii = this.columns.length; i < ii; i++) - if (m = this.columns[i], !(!m || m.hidden)) { - if (colspan = 1, metadata != null && metadata.columns) { - let columnData = metadata.columns[m.id] || metadata.columns[i]; - colspan = (columnData == null ? void 0 : columnData.colspan) || 1, colspan === "*" && (colspan = ii - i); - } - if (this.columnPosRight[Math.min(ii - 1, i + colspan - 1)] > range.leftPx) { - if (!m.alwaysRenderColumn && this.columnPosLeft[i] > range.rightPx) - break; - this.hasFrozenColumns() && i > this._options.frozenColumn ? this.appendCellHtml(rowDivR, row, i, colspan, d) : this.appendCellHtml(rowDiv, row, i, colspan, d); - } else (m.alwaysRenderColumn || this.hasFrozenColumns() && i <= this._options.frozenColumn) && this.appendCellHtml(rowDiv, row, i, colspan, d); - colspan > 1 && (i += colspan - 1); + let columnCount = this.columns.length, columnData, colspan, rowspan, m, isRenderCell = !0; + for (let i = 0, ii = columnCount; i < ii; i++) { + if (isRenderCell = !0, m = this.columns[i], !m || m.hidden) + continue; + colspan = 1, rowspan = 1, columnData = null, metadata != null && metadata.columns && (columnData = metadata.columns[m.id] || metadata.columns[i], colspan = (columnData == null ? void 0 : columnData.colspan) || 1, rowspan = (columnData == null ? void 0 : columnData.rowspan) || 1, colspan === "*" && (colspan = ii - i), rowspan > dataLength - row && (rowspan = dataLength - row)), !this._options.enableCellRowSpan && rowspan > 1 && console.warn('[SlickGrid] Cell "rowspan" is an opt-in grid option because of its small perf hit, you must enable it via the "enableCellRowSpan" grid option.'); + let ncolspan = colspan; + if (!this.getParentRowSpanByCell(row, i)) { + if (this.columnPosRight[Math.min(ii - 1, i + ncolspan - 1)] > range.leftPx) { + if (!m.alwaysRenderColumn && this.columnPosLeft[i] > range.rightPx && (isRenderCell = !1), isRenderCell) { + let targetedRowDiv = this.hasFrozenColumns() && i > this._options.frozenColumn ? rowDivR : rowDiv; + this.appendCellHtml(targetedRowDiv, row, i, ncolspan, rowspan, columnData, d); + } + } else (m.alwaysRenderColumn || this.hasFrozenColumns() && i <= this._options.frozenColumn) && this.appendCellHtml(rowDiv, row, i, ncolspan, rowspan, columnData, d); + ncolspan > 1 && (i += ncolspan - 1); } + } } - appendCellHtml(divRow, row, cell, colspan, item) { - let m = this.columns[cell], cellCss = "slick-cell l" + cell + " r" + Math.min(this.columns.length - 1, cell + colspan - 1) + (m.cssClass ? " " + m.cssClass : ""); + appendCellHtml(divRow, row, cell, colspan, rowspan, columnMetadata, item) { + let m = this.columns[cell], cellCss = `slick-cell l${cell} r${Math.min(this.columns.length - 1, cell + colspan - 1)}` + (m.cssClass ? ` ${m.cssClass}` : "") + (rowspan > 1 ? " rowspan" : "") + (columnMetadata != null && columnMetadata.cssClass ? ` ${columnMetadata.cssClass}` : ""); this.hasFrozenColumns() && cell <= this._options.frozenColumn && (cellCss += " frozen"), row === this.activeRow && cell === this.activeCell && this._options.showCellSelection && (cellCss += " active"), Object.keys(this.cellCssClasses).forEach((key) => { var _a; - (_a = this.cellCssClasses[key][row]) != null && _a[m.id] && (cellCss += " " + this.cellCssClasses[key][row][m.id]); + (_a = this.cellCssClasses[key][row]) != null && _a[m.id] && (cellCss += ` ${this.cellCssClasses[key][row][m.id]}`); }); let value = null, formatterResult = ""; item && (value = this.getDataItemValueForColumn(item, m), formatterResult = this.getFormatter(row, m)(row, cell, value, m, item, this), formatterResult == null && (formatterResult = "")); @@ -1758,7 +1789,9 @@ role: "gridcell", tabIndex: -1 }); - if (cellDiv.setAttribute("aria-describedby", this.uid + m.id), toolTipText && cellDiv.setAttribute("title", toolTipText), m.hasOwnProperty("cellAttrs") && m.cellAttrs instanceof Object && Object.keys(m.cellAttrs).forEach((key) => { + cellDiv.setAttribute("aria-describedby", this.uid + m.id), toolTipText && cellDiv.setAttribute("title", toolTipText); + let cellHeight = this.getCellHeight(row, rowspan); + if (rowspan > 1 && cellHeight !== this._options.rowHeight - this.cellHeightDiff && (cellDiv.style.height = `${cellHeight || 0}px`), m.hasOwnProperty("cellAttrs") && m.cellAttrs instanceof Object && Object.keys(m.cellAttrs).forEach((key) => { m.cellAttrs.hasOwnProperty(key) && cellDiv.setAttribute(key, m.cellAttrs[key]); }), item) { let cellResult = Object.prototype.toString.call(formatterResult) !== "[object Object]" ? formatterResult : formatterResult.html || formatterResult.text; @@ -1767,14 +1800,103 @@ divRow.appendChild(cellDiv), formatterResult.insertElementAfterTarget && Utils.insertAfterElement(cellDiv, formatterResult.insertElementAfterTarget), this.rowsCache[row].cellRenderQueue.push(cell), this.rowsCache[row].cellColSpans[cell] = colspan; } cleanupRows(rangeToKeep) { + let mandatoryRows = /* @__PURE__ */ new Set(); + if (this._options.enableCellRowSpan) + for (let i = rangeToKeep.top, ln = rangeToKeep.bottom; i <= ln; i++) { + let parentRowSpan = this.getRowSpanIntersect(i); + parentRowSpan !== null && mandatoryRows.add(parentRowSpan); + } Object.keys(this.rowsCache).forEach((rowId) => { if (this.rowsCache) { let i = +rowId, removeFrozenRow = !0; - this.hasFrozenRows && (this._options.frozenBottom && i >= this.actualFrozenRow || !this._options.frozenBottom && i <= this.actualFrozenRow) && (removeFrozenRow = !1), (i = parseInt(rowId, 10)) !== this.activeRow && (i < rangeToKeep.top || i > rangeToKeep.bottom) && removeFrozenRow && this.removeRowFromCache(i); + this.hasFrozenRows && (this._options.frozenBottom && i >= this.actualFrozenRow || !this._options.frozenBottom && i <= this.actualFrozenRow) && (removeFrozenRow = !1), (i = parseInt(rowId, 10)) !== this.activeRow && (i < rangeToKeep.top || i > rangeToKeep.bottom) && removeFrozenRow && !mandatoryRows.has(i) && this.removeRowFromCache(i); } }), this._options.enableAsyncPostRenderCleanup && this.startPostProcessingCleanup(); } - /** Invalidate all grid rows and re-render the grid rows */ + /** + * from a row number, return any column indexes that intersected with the grid row including the cell + * @param {Number} row - grid row index + */ + getRowSpanColumnIntersects(row) { + return this.getRowSpanIntersection(row, "columns"); + } + /** + * from a row number, verify if the rowspan is intersecting and return it when found, + * otherwise return `null` when nothing is found or when the rowspan feature is disabled. + * @param {Number} row - grid row index + */ + getRowSpanIntersect(row) { + return this.getRowSpanIntersection(row); + } + getRowSpanIntersection(row, outputType) { + let columnIntersects = [], rowStartIntersect = null; + for (let col = 0, cln = this.columns.length; col < cln; col++) { + let rmeta = this._colsWithRowSpanCache[col]; + if (rmeta) + for (let range of Array.from(rmeta)) { + let [start, end] = range.split(":").map(Number); + if (row >= start && row <= end) + if (outputType === "columns") + columnIntersects.push(col); + else { + rowStartIntersect = start; + break; + } + } + } + return outputType === "columns" ? columnIntersects : rowStartIntersect; + } + /** + * Returns the parent rowspan details when child cell are spanned from a rowspan or `null` when it's not spanned. + * By default it will exclude the parent cell that holds the rowspan, and return `null`, that initiated the rowspan unless the 3rd argument is disabled. + * The exclusion is helpful to find out when we're dealing with a child cell of a rowspan + * @param {Number} row - grid row index + * @param {Number} cell - grid cell/column index + * @param {Boolean} [excludeParentRow] - should we exclude the parent who initiated the rowspan in the search (defaults to true)? + */ + getParentRowSpanByCell(row, cell, excludeParentRow = !0) { + let spanDetail = null, rowspanRange = this._colsWithRowSpanCache[cell] || /* @__PURE__ */ new Set(); + for (let range of Array.from(rowspanRange)) { + let [start, end] = range.split(":").map(Number); + if ((excludeParentRow ? row > start : row >= start) && row <= end) { + spanDetail = { start, end, range }; + break; + } + } + return spanDetail; + } + /** + * Remap all the rowspan metadata by looping through all dataset rows and keep a cache of rowspan by column indexes + * For example: + * 1- if 2nd row of the 1st column has a metadata.rowspan of 3 then the cache will be: `{ 0: '1:4' }` + * 2- if 2nd row if the 1st column has a metadata.rowspan of 3 AND a colspan of 2 then the cache will be: `{ 0: '1:4', 1: '1:4' }` + */ + remapAllColumnsRowSpan() { + let ln = this.getDataLength(); + if (ln > 0) { + this._colsWithRowSpanCache = {}; + for (let row = 0; row < ln; row++) + this.remapRowSpanMetadataByRow(row); + this._rowSpanIsCached = !0; + } + } + remapRowSpanMetadataByRow(row) { + let colMeta = this.getItemMetadaWhenExists(row); + colMeta != null && colMeta.columns && Object.keys(colMeta.columns).forEach((col) => { + let colIdx = +col, columnMeta = colMeta.columns[colIdx], colspan = +((columnMeta == null ? void 0 : columnMeta.colspan) || 1), rowspan = +((columnMeta == null ? void 0 : columnMeta.rowspan) || 1); + this.remapRowSpanMetadata(row, colIdx, colspan, rowspan); + }); + } + remapRowSpanMetadata(row, cell, colspan, rowspan) { + var _a, _b, _c, _d, _e; + if (rowspan > 1) { + let rspan = `${row}:${row + rowspan - 1}`; + if ((_b = (_a = this._colsWithRowSpanCache)[cell]) != null || (_a[cell] = /* @__PURE__ */ new Set()), this._colsWithRowSpanCache[cell].add(rspan), colspan > 1) + for (let i = 1; i < colspan; i++) + (_e = (_c = this._colsWithRowSpanCache)[_d = cell + i]) != null || (_c[_d] = /* @__PURE__ */ new Set()), this._colsWithRowSpanCache[cell + i].add(rspan); + } + } + /** Invalidate all grid rows and re-render the visible grid rows */ invalidate() { this.updateRowCount(), this.invalidateAllRows(), this.render(); } @@ -1791,18 +1913,41 @@ invalidateRows(rows) { if (!rows || !rows.length) return; + let row; this.vScrollDir = 0; - let rl = rows.length; + let rl = rows.length, invalidatedRows = /* @__PURE__ */ new Set(), requiredRemapRows = /* @__PURE__ */ new Set(), isRowSpanFullRemap = rows.length > this._options.maxPartialRowSpanRemap || rows.length === this.getDataLength() || this._prevInvalidatedRowsCount + rows.length === this.getDataLength(); for (let i = 0; i < rl; i++) - this.currentEditor && this.activeRow === rows[i] && this.makeActiveCellNormal(), this.rowsCache[rows[i]] && this.removeRowFromCache(rows[i]); - this._options.enableAsyncPostRenderCleanup && this.startPostProcessingCleanup(); + if (row = rows[i], this.currentEditor && this.activeRow === row && this.makeActiveCellNormal(), this.rowsCache[row] && this.removeRowFromCache(row), this._options.enableCellRowSpan && !isRowSpanFullRemap) { + invalidatedRows.add(row); + let parentRowSpan = this.getRowSpanIntersect(row); + parentRowSpan !== null && invalidatedRows.add(parentRowSpan); + } + if (this._options.enableCellRowSpan && !isRowSpanFullRemap) { + for (let ir of Array.from(invalidatedRows)) { + let colIdxs = this.getRowSpanColumnIntersects(ir); + for (let cidx of colIdxs) { + let prs = this.getParentRowSpanByCell(ir, cidx); + prs && this._colsWithRowSpanCache[cidx] && (this._colsWithRowSpanCache[cidx].delete(prs.range), requiredRemapRows.add(prs.range.split(":").map(Number)[0])); + } + } + for (let row2 of Array.from(requiredRemapRows)) + this.remapRowSpanMetadataByRow(row2); + } + this._options.enableAsyncPostRenderCleanup && this.startPostProcessingCleanup(), this._prevInvalidatedRowsCount = rows.length; } /** * Invalidate a specific row number * @param {Number} row */ invalidateRow(row) { - !row && row !== 0 || this.invalidateRows([row]); + if (row >= 0) { + let rows = [row]; + if (this._options.enableCellRowSpan) { + let intersectedRow = this.getRowSpanIntersect(row); + intersectedRow !== null && rows.push(intersectedRow); + } + this.invalidateRows(rows); + } } queuePostProcessedRowForCleanup(cacheEntry, postProcessedRow, rowIdx) { var _a; @@ -1880,6 +2025,17 @@ row === this.activeRow && columnIdx === this.activeCell && this.currentEditor ? this.currentEditor.loadValue(d) : d ? (formatterResult = this.getFormatter(row, m)(row, columnIdx, this.getDataItemValueForColumn(d, m), m, d, this), this.applyFormatResultToCellNode(formatterResult, node)) : Utils.emptyElement(node); }), this.invalidatePostProcessingResults(row); } + getCellHeight(row, rowspan) { + let cellHeight = this._options.rowHeight || 0; + if (rowspan > 1) { + let rowSpanBottomIdx = row + rowspan - 1; + cellHeight = this.getRowBottom(rowSpanBottomIdx) - this.getRowTop(row); + } else { + let rowHeight = this.getRowHeight(); + rowHeight !== cellHeight - this.cellHeightDiff && (cellHeight = rowHeight); + } + return cellHeight -= this.cellHeightDiff, Math.ceil(cellHeight); + } /** * Get the number of rows displayed in the viewport * Note that the row count is an approximation because it is a calculated value using this formula (viewport / rowHeight = rowCount), @@ -1939,7 +2095,9 @@ var _a, _b, _c, _d; if (!this.initialized) return; - let dataLength = this.getDataLength(), dataLengthIncludingAddNew = this.getDataLengthIncludingAddNew(), numberOfRows = 0, oldH = this.hasFrozenRows && !this._options.frozenBottom ? Utils.height(this._canvasBottomL) : Utils.height(this._canvasTopL); + let dataLength = this.getDataLength(); + dataLength > 0 && dataLength !== this._prevDataLength && (this._rowSpanIsCached = !1), this._options.enableCellRowSpan && !this._rowSpanIsCached && this.remapAllColumnsRowSpan(), this._prevDataLength = dataLength; + let dataLengthIncludingAddNew = this.getDataLengthIncludingAddNew(), numberOfRows = 0, oldH = this.hasFrozenRows && !this._options.frozenBottom ? Utils.height(this._canvasBottomL) : Utils.height(this._canvasTopL); this.hasFrozenRows ? numberOfRows = this.getDataLength() - this._options.frozenRow : numberOfRows = dataLengthIncludingAddNew + (this._options.leaveSpaceForNewRows ? this.numVisibleRows - 1 : 0); let tempViewportH = Utils.height(this._viewportScrollContainerY), oldViewportHasVScroll = this.viewportHasVScroll; this.viewportHasVScroll = this._options.alwaysShowVerticalScroll || !this._options.autoHeight && numberOfRows * this._options.rowHeight > tempViewportH, this.makeActiveCellNormal(); @@ -1987,10 +2145,11 @@ return; let totalCellsRemoved = 0, cacheEntry = this.rowsCache[row], cellsToRemove = []; Object.keys(cacheEntry.cellNodesByColumnIdx).forEach((cellNodeIdx) => { + var _a2; if (!cacheEntry.cellNodesByColumnIdx.hasOwnProperty(cellNodeIdx)) return; let i = +cellNodeIdx; - if (i <= this._options.frozenColumn || Array.isArray(this.columns) && this.columns[i] && this.columns[i].alwaysRenderColumn) + if (i <= this._options.frozenColumn || Array.isArray(this.columns) && ((_a2 = this.columns[i]) != null && _a2.alwaysRenderColumn)) return; let colspan = cacheEntry.cellColSpans[i]; (this.columnPosLeft[i] > range.rightPx || this.columnPosRight[Math.min(this.columns.length - 1, (i || 0) + colspan - 1)] < range.leftPx) && (row === this.activeRow && Number(i) === this.activeCell || cellsToRemove.push(i)); @@ -2000,16 +2159,16 @@ cellNode = cacheEntry.cellNodesByColumnIdx[cellToRemove], this._options.enableAsyncPostRenderCleanup && ((_a = this.postProcessedRows[row]) != null && _a[cellToRemove]) ? this.queuePostProcessedCellForCleanup(cellNode, cellToRemove, row) : (_b = cellNode.parentElement) == null || _b.removeChild(cellNode), delete cacheEntry.cellColSpans[cellToRemove], delete cacheEntry.cellNodesByColumnIdx[cellToRemove], this.postProcessedRows[row] && delete this.postProcessedRows[row][cellToRemove], totalCellsRemoved++; } cleanUpAndRenderCells(range) { - var _a, _b, _c, _d; - let cacheEntry, divRow = document.createElement("div"), processedRows = [], cellsAdded, totalCellsAdded = 0, colspan; + var _a; + let cacheEntry, divRow = document.createElement("div"), processedRows = [], cellsAdded, totalCellsAdded = 0, colspan, columnData, columnCount = this.columns.length; for (let row = range.top, btm = range.bottom; row <= btm; row++) { if (cacheEntry = this.rowsCache[row], !cacheEntry) continue; - this.ensureCellNodesInRowsCache(row), this.cleanUpCells(range, row), cellsAdded = 0; - let metadata = (_c = (_b = (_a = this.data) == null ? void 0 : _a.getItemMetadata) == null ? void 0 : _b.call(_a, row)) != null ? _c : {}; + this.ensureCellNodesInRowsCache(row), (!this._options.enableCellRowSpan || this.getRowSpanIntersect(row) === null) && this.cleanUpCells(range, row), cellsAdded = 0; + let metadata = this.getItemMetadaWhenExists(row); metadata = metadata == null ? void 0 : metadata.columns; let d = this.getDataItem(row); - for (let i = 0, ii = this.columns.length; i < ii; i++) { + for (let i = 0, ii = columnCount; i < ii; i++) { if (!this.columns[i] || this.columns[i].hidden) continue; if (this.columnPosLeft[i] > range.rightPx) @@ -2018,12 +2177,15 @@ i += colspan > 1 ? colspan - 1 : 0; continue; } - if (colspan = 1, metadata) { - let columnData = metadata[this.columns[i].id] || metadata[i]; - colspan = (_d = columnData == null ? void 0 : columnData.colspan) != null ? _d : 1, colspan === "*" && (colspan = ii - i); + colspan = 1, columnData = null, metadata && (columnData = metadata[this.columns[i].id] || metadata[i], colspan = (_a = columnData == null ? void 0 : columnData.colspan) != null ? _a : 1, colspan === "*" && (colspan = ii - i)); + let ncolspan = colspan; + if (!this.getParentRowSpanByCell(row, i)) { + if (this.columnPosRight[Math.min(ii - 1, i + ncolspan - 1)] > range.leftPx) { + let rowspan = this.getRowspan(row, i); + this.appendCellHtml(divRow, row, i, ncolspan, rowspan, columnData, d), cellsAdded++; + } + i += ncolspan > 1 ? ncolspan - 1 : 0; } - let colspanNb = colspan; - this.columnPosRight[Math.min(ii - 1, i + colspanNb - 1)] > range.leftPx && (this.appendCellHtml(divRow, row, i, colspanNb, d), cellsAdded++), i += colspanNb > 1 ? colspanNb - 1 : 0; } cellsAdded && (totalCellsAdded += cellsAdded, processedRows.push(row)); } @@ -2037,29 +2199,45 @@ node = divRow.lastChild, node && (this.hasFrozenColumns() && columnIdx > this._options.frozenColumn ? cacheEntry.rowNode[1].appendChild(node) : cacheEntry.rowNode[0].appendChild(node), cacheEntry.cellNodesByColumnIdx[columnIdx] = node); } } + createEmptyCachingRow() { + return { + rowNode: null, + // ColSpans of rendered cells (by column idx). + // Can also be used for checking whether a cell has been rendered. + cellColSpans: [], + // Cell nodes (by column idx). Lazy-populated by ensureCellNodesInRowsCache(). + cellNodesByColumnIdx: [], + // Column indices of cell nodes that have been rendered, but not yet indexed in + // cellNodesByColumnIdx. These are in the same order as cell nodes added at the + // end of the row. + cellRenderQueue: [] + }; + } renderRows(range) { var _a, _b, _c, _d; - let divArrayL = [], divArrayR = [], rows = [], needToReselectCell = !1, dataLength = this.getDataLength(); + let divArrayL = [], divArrayR = [], rows = [], needToReselectCell = !1, dataLength = this.getDataLength(), mustRenderRows = /* @__PURE__ */ new Set(), renderingRows = /* @__PURE__ */ new Set(); for (let i = range.top, ii = range.bottom; i <= ii; i++) - this.rowsCache[i] || this.hasFrozenRows && this._options.frozenBottom && i === this.getDataLength() || (this.renderedRows++, rows.push(i), this.rowsCache[i] = { - rowNode: null, - // ColSpans of rendered cells (by column idx). - // Can also be used for checking whether a cell has been rendered. - cellColSpans: [], - // Cell nodes (by column idx). Lazy-populated by ensureCellNodesInRowsCache(). - cellNodesByColumnIdx: [], - // Column indices of cell nodes that have been rendered, but not yet indexed in - // cellNodesByColumnIdx. These are in the same order as cell nodes added at the - // end of the row. - cellRenderQueue: [] - }, this.appendRowHtml(divArrayL, divArrayR, i, range, dataLength), this.activeCellNode && this.activeRow === i && (needToReselectCell = !0), this.counter_rows_rendered++); - if (!rows.length) - return; - let x = document.createElement("div"), xRight = document.createElement("div"); - divArrayL.forEach((elm) => x.appendChild(elm)), divArrayR.forEach((elm) => xRight.appendChild(elm)); - for (let i = 0, ii = rows.length; i < ii; i++) - this.hasFrozenRows && rows[i] >= this.actualFrozenRow ? this.hasFrozenColumns() ? (_a = this.rowsCache) != null && _a.hasOwnProperty(rows[i]) && x.firstChild && xRight.firstChild && (this.rowsCache[rows[i]].rowNode = [x.firstChild, xRight.firstChild], this._canvasBottomL.appendChild(x.firstChild), this._canvasBottomR.appendChild(xRight.firstChild)) : (_b = this.rowsCache) != null && _b.hasOwnProperty(rows[i]) && x.firstChild && (this.rowsCache[rows[i]].rowNode = [x.firstChild], this._canvasBottomL.appendChild(x.firstChild)) : this.hasFrozenColumns() ? (_c = this.rowsCache) != null && _c.hasOwnProperty(rows[i]) && x.firstChild && xRight.firstChild && (this.rowsCache[rows[i]].rowNode = [x.firstChild, xRight.firstChild], this._canvasTopL.appendChild(x.firstChild), this._canvasTopR.appendChild(xRight.firstChild)) : (_d = this.rowsCache) != null && _d.hasOwnProperty(rows[i]) && x.firstChild && (this.rowsCache[rows[i]].rowNode = [x.firstChild], this._canvasTopL.appendChild(x.firstChild)); - needToReselectCell && (this.activeCellNode = this.getCellNode(this.activeRow, this.activeCell)); + if (!(this.rowsCache[i] || this.hasFrozenRows && this._options.frozenBottom && i === this.getDataLength())) { + if (this.renderedRows++, rows.push(i), renderingRows.add(i), this.rowsCache[i] = this.createEmptyCachingRow(), this._options.enableCellRowSpan) { + let parentRowSpan = this.getRowSpanIntersect(i); + parentRowSpan !== null && renderingRows.add(parentRowSpan); + } + this.appendRowHtml(divArrayL, divArrayR, i, range, dataLength), mustRenderRows.add(i), this.activeCellNode && this.activeRow === i && (needToReselectCell = !0), this.counter_rows_rendered++; + } + let mandatorySpanRows = this.setDifference(renderingRows, mustRenderRows); + if (mandatorySpanRows.size > 0 && mandatorySpanRows.forEach((r) => { + this.removeRowFromCache(r), rows.push(r), this.rowsCache[r] = this.createEmptyCachingRow(), this.appendRowHtml(divArrayL, divArrayR, r, range, dataLength); + }), rows.length) { + let x = document.createElement("div"), xRight = document.createElement("div"); + divArrayL.forEach((elm) => x.appendChild(elm)), divArrayR.forEach((elm) => xRight.appendChild(elm)); + for (let i = 0, ii = rows.length; i < ii; i++) + this.hasFrozenRows && rows[i] >= this.actualFrozenRow ? this.hasFrozenColumns() ? (_a = this.rowsCache) != null && _a.hasOwnProperty(rows[i]) && x.firstChild && xRight.firstChild && (this.rowsCache[rows[i]].rowNode = [x.firstChild, xRight.firstChild], this._canvasBottomL.appendChild(x.firstChild), this._canvasBottomR.appendChild(xRight.firstChild)) : (_b = this.rowsCache) != null && _b.hasOwnProperty(rows[i]) && x.firstChild && (this.rowsCache[rows[i]].rowNode = [x.firstChild], this._canvasBottomL.appendChild(x.firstChild)) : this.hasFrozenColumns() ? (_c = this.rowsCache) != null && _c.hasOwnProperty(rows[i]) && x.firstChild && xRight.firstChild && (this.rowsCache[rows[i]].rowNode = [x.firstChild, xRight.firstChild], this._canvasTopL.appendChild(x.firstChild), this._canvasTopR.appendChild(xRight.firstChild)) : (_d = this.rowsCache) != null && _d.hasOwnProperty(rows[i]) && x.firstChild && (this.rowsCache[rows[i]].rowNode = [x.firstChild], this._canvasTopL.appendChild(x.firstChild)); + needToReselectCell && (this.activeCellNode = this.getCellNode(this.activeRow, this.activeCell)); + } + } + /** polyfill if the new Set.difference() added in ES2024 */ + setDifference(a, b) { + return new Set(Array.from(a).filter((item) => !b.has(item))); } startPostProcessing() { this._options.enableAsyncPostRender && (window.clearTimeout(this.h_postrender), this.h_postrender = window.setTimeout(this.asyncPostProcessRows.bind(this), this._options.asyncPostRenderDelay)); @@ -2102,7 +2280,7 @@ bottom: this._options.frozenRow - 1, leftPx: rendered.leftPx, rightPx: rendered.rightPx - })), this.postProcessFromRow = visible.top, this.postProcessToRow = Math.min(this.getDataLengthIncludingAddNew() - 1, visible.bottom), this.startPostProcessing(), this.lastRenderedScrollTop = this.scrollTop, this.lastRenderedScrollLeft = this.scrollLeft, this.h_render = null, this.trigger(this.onRendered, { startRow: visible.top, endRow: visible.bottom, grid: this }); + })), this.postProcessFromRow = visible.top, this.postProcessToRow = Math.min(this.getDataLengthIncludingAddNew() - 1, visible.bottom), this.startPostProcessing(), this.lastRenderedScrollTop = this.scrollTop, this.lastRenderedScrollLeft = this.scrollLeft, this.trigger(this.onRendered, { startRow: visible.top, endRow: visible.bottom, grid: this }); } handleHeaderRowScroll() { let scrollLeft = this._headerRowScrollContainer.scrollLeft; @@ -2283,7 +2461,7 @@ ////////////////////////////////////////////////////////////////////////////////////////////// // Interactivity handleMouseWheel(e, _delta, deltaX, deltaY) { - this.scrollHeight = this._viewportScrollContainerY.scrollHeight, this.scrollTop = Math.max(0, this._viewportScrollContainerY.scrollTop - deltaY * this._options.rowHeight), this.scrollLeft = this._viewportScrollContainerX.scrollLeft + deltaX * 10, this._handleScroll("mousewheel") && e.preventDefault(); + this.scrollHeight = this._viewportScrollContainerY.scrollHeight, e.shiftKey ? this.scrollLeft = this._viewportScrollContainerX.scrollLeft + deltaX * 10 : (this.scrollTop = Math.max(0, this._viewportScrollContainerY.scrollTop - deltaY * this._options.rowHeight), this.scrollLeft = this._viewportScrollContainerX.scrollLeft + deltaX * 10), this._handleScroll("mousewheel") && e.preventDefault(); } handleDragInit(e, dd) { let cell = this.getCellFromEvent(e); @@ -2311,7 +2489,7 @@ if (!handled && !e.shiftKey && !e.altKey) { if (this._options.editable && ((_a = this.currentEditor) != null && _a.keyCaptureList) && this.currentEditor.keyCaptureList.indexOf(e.which) > -1) return; - e.which === keyCode.HOME ? handled = e.ctrlKey ? this.navigateTop() : this.navigateRowStart() : e.which === keyCode.END && (handled = e.ctrlKey ? this.navigateBottom() : this.navigateRowEnd()); + e.ctrlKey && e.key === "Home" ? this.navigateTopStart() : e.ctrlKey && e.key === "End" ? this.navigateBottomEnd() : e.ctrlKey && e.key === "ArrowUp" ? this.navigateTop() : e.ctrlKey && e.key === "ArrowDown" ? this.navigateBottom() : e.ctrlKey && e.key === "ArrowLeft" || !e.ctrlKey && e.key === "Home" ? this.navigateRowStart() : (e.ctrlKey && e.key === "ArrowRight" || !e.ctrlKey && e.key === "End") && this.navigateRowEnd(); } if (!handled) if (!e.shiftKey && !e.altKey && !e.ctrlKey) { @@ -2488,10 +2666,15 @@ } ////////////////////////////////////////////////////////////////////////////////////////////// // Cell switching - /** Resets active cell. */ + /** Resets active cell by making cell normal and other internal reset. */ resetActiveCell() { this.setActiveCellInternal(null, !1); } + /** Clear active cell by making cell normal & removing "active" CSS class. */ + unsetActiveCell() { + var _a, _b; + Utils.isDefined(this.activeCellNode) && (this.makeActiveCellNormal(), this.activeCellNode.classList.remove("active"), (_b = (_a = this.rowsCache[this.activeRow]) == null ? void 0 : _a.rowNode) == null || _b.forEach((node) => node.classList.remove("active"))); + } /** @alias `setFocus` */ focus() { this.setFocus(); @@ -2519,14 +2702,14 @@ this.internalScrollColumnIntoView(this.columnPosLeft[cell], this.columnPosRight[cell]); } setActiveCellInternal(newCell, opt_editMode, preClickModeOn, suppressActiveCellChangedEvent, e) { - var _a, _b, _c, _d; - if (Utils.isDefined(this.activeCellNode) && (this.makeActiveCellNormal(), this.activeCellNode.classList.remove("active"), (_b = (_a = this.rowsCache[this.activeRow]) == null ? void 0 : _a.rowNode) == null || _b.forEach((node) => node.classList.remove("active"))), this.activeCellNode = newCell, Utils.isDefined(this.activeCellNode)) { + var _a, _b; + if (this.unsetActiveCell(), this.activeCellNode = newCell, Utils.isDefined(this.activeCellNode)) { let activeCellOffset = Utils.offset(this.activeCellNode), rowOffset = Math.floor(Utils.offset(Utils.parents(this.activeCellNode, ".grid-canvas")[0]).top), isBottom = Utils.parents(this.activeCellNode, ".grid-canvas-bottom").length; this.hasFrozenRows && isBottom && (rowOffset -= this._options.frozenBottom ? Utils.height(this._canvasTopL) : this.frozenRowsHeight); let cell = this.getCellFromPoint(activeCellOffset.left, Math.ceil(activeCellOffset.top) - rowOffset); - this.activeRow = cell.row, this.activeCell = this.activePosX = this.activeCell = this.activePosX = this.getCellFromNode(this.activeCellNode), !Utils.isDefined(opt_editMode) && this._options.autoEditNewRow && (opt_editMode = this.activeRow === this.getDataLength() || this._options.autoEdit), this._options.showCellSelection && (this.activeCellNode.classList.add("active"), (_d = (_c = this.rowsCache[this.activeRow]) == null ? void 0 : _c.rowNode) == null || _d.forEach((node) => node.classList.add("active"))), this._options.editable && opt_editMode && this.isCellPotentiallyEditable(this.activeRow, this.activeCell) && (window.clearTimeout(this.h_editorLoader), this._options.asyncEditorLoading ? this.h_editorLoader = window.setTimeout(() => { + this.activeRow = cell.row, this.activePosY = cell.row, this.activeCell = this.activePosX = this.getCellFromNode(this.activeCellNode), !Utils.isDefined(opt_editMode) && this._options.autoEditNewRow && (opt_editMode = this.activeRow === this.getDataLength() || this._options.autoEdit), this._options.showCellSelection && (document.querySelectorAll(".slick-cell.active").forEach((node) => node.classList.remove("active")), this.activeCellNode.classList.add("active"), (_b = (_a = this.rowsCache[this.activeRow]) == null ? void 0 : _a.rowNode) == null || _b.forEach((node) => node.classList.add("active"))), this._options.editable && opt_editMode && this.isCellPotentiallyEditable(this.activeRow, this.activeCell) && (this._options.asyncEditorLoading ? (window.clearTimeout(this.h_editorLoader), this.h_editorLoader = window.setTimeout(() => { this.makeActiveCellEditable(void 0, preClickModeOn, e); - }, this._options.asyncEditorLoadDelay) : this.makeActiveCellEditable(void 0, preClickModeOn, e)); + }, this._options.asyncEditorLoadDelay)) : this.makeActiveCellEditable(void 0, preClickModeOn, e)); } else this.activeRow = this.activeCell = null; suppressActiveCellChangedEvent || this.trigger(this.onActiveCellChanged, this.getActiveCell()); @@ -2570,7 +2753,7 @@ this.makeActiveCellEditable(editor, preClickModeOn, e); } makeActiveCellEditable(editor, preClickModeOn, e) { - var _a, _b, _c, _d, _e, _f; + var _a, _b, _c, _d; if (!this.activeCellNode) return; if (!this._options.editable) @@ -2587,7 +2770,7 @@ if (!useEditor || typeof useEditor != "function") return; !editor && !useEditor.suppressClearOnEdit && Utils.emptyElement(this.activeCellNode); - let metadata = (_c = (_b = this.data) == null ? void 0 : _b.getItemMetadata) == null ? void 0 : _c.call(_b, this.activeRow); + let metadata = this.getItemMetadaWhenExists(this.activeRow); metadata = metadata == null ? void 0 : metadata.columns; let columnMetaData = metadata && (metadata[columnDef.id] || metadata[this.activeCell]), editorArgs = { grid: this, @@ -2601,7 +2784,7 @@ commitChanges: this.commitEditAndSetFocus.bind(this), cancelChanges: this.cancelEditAndSetFocus.bind(this) }; - this.currentEditor = new useEditor(editorArgs), item && this.currentEditor && (this.currentEditor.loadValue(item), preClickModeOn && ((_d = this.currentEditor) != null && _d.preClick) && this.currentEditor.preClick()), this.serializedEditorValue = (_e = this.currentEditor) == null ? void 0 : _e.serializeValue(), (_f = this.currentEditor) != null && _f.position && this.handleActiveCellPositionChange(); + this.currentEditor = new useEditor(editorArgs), item && this.currentEditor && (this.currentEditor.loadValue(item), preClickModeOn && ((_b = this.currentEditor) != null && _b.preClick) && this.currentEditor.preClick()), this.serializedEditorValue = (_c = this.currentEditor) == null ? void 0 : _c.serializeValue(), (_d = this.currentEditor) != null && _d.position && this.handleActiveCellPositionChange(); } commitEditAndSetFocus() { var _a; @@ -2699,10 +2882,8 @@ if (this.scrollTo((this.getRowFromPosition(bottomOfTopmostFullyVisibleRow) + deltaRows) * this._options.rowHeight), this.render(), this._options.enableCellNavigation && Utils.isDefined(this.activeRow)) { let row = this.activeRow + deltaRows, dataLengthIncludingAddNew = this.getDataLengthIncludingAddNew(); row >= dataLengthIncludingAddNew && (row = dataLengthIncludingAddNew - 1), row < 0 && (row = 0); - let cell = 0, prevCell = null, prevActivePosX = this.activePosX; - for (; cell <= this.activePosX; ) - this.canCellBeActive(row, cell) && (prevCell = cell), cell += this.getColspan(row, cell); - prevCell !== null ? (this.setActiveCellInternal(this.getCellNode(row, prevCell)), this.activePosX = prevActivePosX) : this.resetActiveCell(); + let pos = dir === 1 ? this.gotoDown(row - 1 || 0, this.activeCell, this.activePosY, this.activePosX) : this.gotoUp(row + 1, this.activeCell, this.activePosY, this.activePosX); + this.navigateToPos(pos); } } /** Navigate (scroll) by a page down */ @@ -2715,161 +2896,217 @@ } /** Navigate to the top of the grid */ navigateTop() { - this.navigateToRow(0); + this.unsetActiveCell(), this.navigateToRow(0); } /** Navigate to the bottom of the grid */ navigateBottom() { - this.navigateToRow(this.getDataLength() - 1); + var _a, _b; + let row = this.getDataLength() - 1, tmpRow = (_b = (_a = this.getParentRowSpanByCell(row, this.activeCell)) == null ? void 0 : _a.start) != null ? _b : row; + do + if (this._options.enableCellRowSpan && this.setActiveRow(tmpRow), this.navigateToRow(tmpRow) && this.activeCell === this.activePosX || !Utils.isDefined(this.activeCell)) + break; + while (--tmpRow > 0); } navigateToRow(row) { let num_rows = this.getDataLength(); if (!num_rows) - return !0; - if (row < 0 ? row = 0 : row >= num_rows && (row = num_rows - 1), this.scrollCellIntoView(row, 0, !0), this._options.enableCellNavigation && Utils.isDefined(this.activeRow)) { + return !1; + row < 0 ? row = 0 : row >= num_rows && (row = num_rows - 1), this.scrollCellIntoView(row, 0, !0); + let isValidMove = !Utils.isDefined(this.activeCell) || !Utils.isDefined(this.activeRow); + if (this._options.enableCellNavigation && Utils.isDefined(this.activeRow)) { let cell = 0, prevCell = null, prevActivePosX = this.activePosX; for (; cell <= this.activePosX; ) - this.canCellBeActive(row, cell) && (prevCell = cell), cell += this.getColspan(row, cell); + this.canCellBeActive(row, cell) && (prevCell = cell, (!Utils.isDefined(this.activeCell) || cell === this.activeCell) && (isValidMove = !0)), cell += this.getColspan(row, cell); prevCell !== null ? (this.setActiveCellInternal(this.getCellNode(row, prevCell)), this.activePosX = prevActivePosX) : this.resetActiveCell(); } - return !0; + return isValidMove; } getColspan(row, cell) { - var _a, _b; - let metadata = (_b = (_a = this.data) == null ? void 0 : _a.getItemMetadata) == null ? void 0 : _b.call(_a, row); + let metadata = this.getItemMetadaWhenExists(row); if (!metadata || !metadata.columns) return 1; + cell >= this.columns.length && (cell = this.columns.length - 1); let columnData = metadata.columns[this.columns[cell].id] || metadata.columns[cell], colspan = columnData == null ? void 0 : columnData.colspan; return colspan === "*" ? colspan = this.columns.length - cell : colspan = colspan || 1, colspan; } + getRowspan(row, cell) { + let rowspan = 1, metadata = this.getItemMetadaWhenExists(row); + return metadata != null && metadata.columns && Object.keys(metadata.columns).forEach((col) => { + let colIdx = Number(col); + if (colIdx === cell) { + let columnMeta = metadata.columns[colIdx]; + rowspan = Number((columnMeta == null ? void 0 : columnMeta.rowspan) || 1); + } + }), rowspan; + } + findFocusableRow(row, cell, dir) { + let r = row, rowRange = this._colsWithRowSpanCache[cell] || /* @__PURE__ */ new Set(), found = !1; + return Array.from(rowRange).forEach((rrange) => { + let [start, end] = rrange.split(":").map(Number); + !found && row >= start && row <= end && (r = dir === "up" ? start : end, this.canCellBeActive(r, cell) && (found = !0)); + }), r < 0 && (r = 0), r; + } findFirstFocusableCell(row) { - let cell = 0; + let cell = 0, focusableRow = row, ff = -1; for (; cell < this.columns.length; ) { - if (this.canCellBeActive(row, cell)) - return cell; - cell += this.getColspan(row, cell); + let prs = this.getParentRowSpanByCell(row, cell); + if (focusableRow = prs !== null && prs.start !== row ? prs.start : row, this.canCellBeActive(focusableRow, cell)) { + ff = cell; + break; + } + cell += this.getColspan(focusableRow, cell); } - return null; + return { cell: ff, row: focusableRow }; } findLastFocusableCell(row) { - let cell = 0, lastFocusableCell = null; - for (; cell < this.columns.length; ) - this.canCellBeActive(row, cell) && (lastFocusableCell = cell), cell += this.getColspan(row, cell); - return lastFocusableCell; + let cell = 0, focusableRow = row, lf = -1; + for (; cell < this.columns.length; ) { + let prs = this.getParentRowSpanByCell(row, cell); + focusableRow = prs !== null && prs.start !== row ? prs.start : row, this.canCellBeActive(focusableRow, cell) && (lf = cell), cell += this.getColspan(focusableRow, cell); + } + return { cell: lf, row: focusableRow }; + } + /** + * From any row/cell indexes that might have colspan/rowspan, find its starting indexes + * For example, if we start at 0,0 and we have colspan/rowspan of 4 for both and our indexes is row:2,cell:3 + * then our starting row/cell is 0,0. If a cell has no spanning at all then row/cell output is same as input + */ + findSpanStartingCell(row, cell) { + let prs = this.getParentRowSpanByCell(row, cell), focusableRow = prs !== null && prs.start !== row ? prs.start : row, fc = 0, prevCell = 0; + for (; fc < this.columns.length; ) { + if (fc += this.getColspan(focusableRow, fc), fc > cell) + return fc = prevCell, { cell: fc, row: focusableRow }; + prevCell = fc; + } + return { cell: fc, row: focusableRow }; } - gotoRight(row, cell, _posX) { + gotoRight(_row, cell, posY, _posX) { if (cell >= this.columns.length) return null; - do - cell += this.getColspan(row, cell); - while (cell < this.columns.length && !this.canCellBeActive(row, cell)); - return cell < this.columns.length ? { - row, - cell, - posX: cell + let fc = cell + 1, fr = posY; + do { + let sc = this.findSpanStartingCell(posY, fc); + if (fr = sc.row, fc = sc.cell, this.canCellBeActive(fr, fc) && fc > cell) + break; + fc += this.getColspan(fr, sc.cell); + } while (fc < this.columns.length); + return fc < this.columns.length ? { + row: fr, + cell: fc, + posX: fc, + posY } : null; } - gotoLeft(row, cell, _posX) { + gotoLeft(row, cell, posY, _posX) { if (cell <= 0) return null; - let firstFocusableCell = this.findFirstFocusableCell(row); - if (firstFocusableCell === null || firstFocusableCell >= cell) + let ff = this.findFirstFocusableCell(row); + if (ff.cell === null || ff.cell >= cell) return null; - let prev = { + let pos, prev = { row, - cell: firstFocusableCell, - posX: firstFocusableCell - }, pos; + cell: ff.cell, + posX: ff.cell, + posY + }; for (; ; ) { - if (pos = this.gotoRight(prev.row, prev.cell, prev.posX), !pos) + if (pos = this.gotoRight(prev.row, prev.cell, prev.posY, prev.posX), !pos) return null; - if (pos.cell >= cell) - return prev; + if (pos.cell >= cell) { + let nextRow = this.findFocusableRow(posY, prev.cell, "up"); + return nextRow !== prev.row && (prev.row = nextRow), prev; + } prev = pos; } } - gotoDown(row, cell, posX) { - let prevCell, dataLengthIncludingAddNew = this.getDataLengthIncludingAddNew(); - for (; ; ) { - if (++row >= dataLengthIncludingAddNew) - return null; - for (prevCell = cell = 0; cell <= posX; ) + gotoDown(row, cell, _posY, posX) { + let prevCell, ub = this.getDataLengthIncludingAddNew(); + do + for (row += this.getRowspan(row, posX), prevCell = cell = 0; cell <= posX; ) prevCell = cell, cell += this.getColspan(row, cell); - if (this.canCellBeActive(row, prevCell)) - return { - row, - cell: prevCell, - posX - }; - } + while (row <= ub && !this.canCellBeActive(row, prevCell)); + return row <= ub ? { + row, + cell: prevCell, + posX, + posY: row + } : null; } - gotoUp(row, cell, posX) { + gotoUp(row, cell, _posY, posX) { let prevCell; - for (; ; ) { - if (--row < 0) - return null; - for (prevCell = cell = 0; cell <= posX; ) + if (row <= 0) + return null; + do + for (row = this.findFocusableRow(row - 1, posX, "up"), prevCell = cell = 0; cell <= posX; ) prevCell = cell, cell += this.getColspan(row, cell); - if (this.canCellBeActive(row, prevCell)) - return { - row, - cell: prevCell, - posX - }; - } + while (row >= 0 && !this.canCellBeActive(row, prevCell)); + return cell <= this.columns.length ? { + row, + cell: prevCell, + posX, + posY: row + } : null; } - gotoNext(row, cell, posX) { - if (!Utils.isDefined(row) && !Utils.isDefined(cell) && (row = cell = posX = 0, this.canCellBeActive(row, cell))) + gotoNext(row, cell, posY, posX) { + var _a, _b; + if (!Utils.isDefined(row) && !Utils.isDefined(cell) && (row = cell = posY = posX = 0, this.canCellBeActive(row, cell))) return { row, cell, - posX: cell + posX: cell, + posY }; - let pos = this.gotoRight(row, cell, posX); - if (pos) - return pos; - let firstFocusableCell = null, dataLengthIncludingAddNew = this.getDataLengthIncludingAddNew(); - for (row === dataLengthIncludingAddNew - 1 && row--; ++row < dataLengthIncludingAddNew; ) - if (firstFocusableCell = this.findFirstFocusableCell(row), firstFocusableCell !== null) - return { + let pos = this.gotoRight(row, cell, posY, posX); + if (!pos) { + let ff; + for (; !pos && ++posY < this.getDataLength() + (this._options.enableAddRow ? 1 : 0); ) + ff = this.findFirstFocusableCell(posY), ff.cell !== null && (row = (_b = (_a = this.getParentRowSpanByCell(posY, ff.cell)) == null ? void 0 : _a.start) != null ? _b : posY, pos = { row, - cell: firstFocusableCell, - posX: firstFocusableCell - }; - return null; + cell: ff.cell, + posX: ff.cell, + posY + }); + } + return pos; } - gotoPrev(row, cell, posX) { - if (!Utils.isDefined(row) && !Utils.isDefined(cell) && (row = this.getDataLengthIncludingAddNew() - 1, cell = posX = this.columns.length - 1, this.canCellBeActive(row, cell))) + gotoPrev(row, cell, posY, posX) { + var _a, _b; + if (!Utils.isDefined(row) && !Utils.isDefined(cell) && (row = posY = this.getDataLengthIncludingAddNew() - 1, cell = posX = this.columns.length - 1, this.canCellBeActive(row, cell))) return { row, cell, - posX: cell + posX: cell, + posY }; - let pos, lastSelectableCell; - for (; !pos && (pos = this.gotoLeft(row, cell, posX), !pos); ) { - if (--row < 0) - return null; - cell = 0, lastSelectableCell = this.findLastFocusableCell(row), lastSelectableCell !== null && (pos = { - row, - cell: lastSelectableCell, - posX: lastSelectableCell - }); + let pos = this.gotoLeft(row, cell, posY, posX); + if (!pos) { + let lf; + for (; !pos && --posY >= 0; ) + lf = this.findLastFocusableCell(posY), lf.cell > -1 && (row = (_b = (_a = this.getParentRowSpanByCell(posY, lf.cell)) == null ? void 0 : _a.start) != null ? _b : posY, pos = { + row, + cell: lf.cell, + posX: lf.cell, + posY + }); } return pos; } - gotoRowStart(row, _cell, _posX) { - let newCell = this.findFirstFocusableCell(row); - return newCell === null ? null : { - row, - cell: newCell, - posX: newCell + gotoRowStart(row, _cell, _posY, _posX) { + let ff = this.findFirstFocusableCell(row); + return ff.cell === null ? null : { + row: ff.row, + cell: ff.cell, + posX: ff.cell, + posY: row }; } - gotoRowEnd(row, _cell, _posX) { - let newCell = this.findLastFocusableCell(row); - return newCell === null ? null : { - row, - cell: newCell, - posX: newCell + gotoRowEnd(row, _cell, _posY, _posX) { + let lf = this.findLastFocusableCell(row); + return lf.cell === -1 ? null : { + row: lf.row, + cell: lf.cell, + posX: lf.cell, + posY: row }; } /** Switches the active cell one cell right skipping unselectable cells. Unline navigateNext, navigateRight stops at the last cell of the row. Returns a boolean saying whether it was able to complete or not. */ @@ -2904,6 +3141,14 @@ navigateRowEnd() { return this.navigate("end"); } + /** Navigate to coordinate 0,0 (top left home) */ + navigateTopStart() { + return this.navigateToRow(0), this.navigate("home"); + } + /** Navigate to bottom row end (bottom right end) */ + navigateBottomEnd() { + return this.navigateBottom(), this.navigate("end"); + } /** * @param {string} dir Navigation direction. * @return {boolean} Whether navigation resulted in a change of active cell. @@ -2914,7 +3159,7 @@ return !1; if (!((_a = this.getEditorLock()) != null && _a.commitCurrentEdit())) return !0; - this.setFocus(); + this.setFocus(), this.unsetActiveCell(); let tabbingDirections = { up: -1, down: 1, @@ -2935,12 +3180,15 @@ next: this.gotoNext, home: this.gotoRowStart, end: this.gotoRowEnd - }[dir].call(this, this.activeRow, this.activeCell, this.activePosX); + }[dir].call(this, this.activeRow, this.activeCell, this.activePosY, this.activePosX); + return this.navigateToPos(pos); + } + navigateToPos(pos) { if (pos) { if (this.hasFrozenRows && this._options.frozenBottom && pos.row === this.getDataLength()) return; let isAddNewRow = pos.row === this.getDataLength(); - return (!this._options.frozenBottom && pos.row >= this.actualFrozenRow || this._options.frozenBottom && pos.row < this.actualFrozenRow) && this.scrollCellIntoView(pos.row, pos.cell, !isAddNewRow && this._options.emulatePagingWhenScrolling), this.setActiveCellInternal(this.getCellNode(pos.row, pos.cell)), this.activePosX = pos.posX, !0; + return (!this._options.frozenBottom && pos.row >= this.actualFrozenRow || this._options.frozenBottom && pos.row < this.actualFrozenRow) && this.scrollCellIntoView(pos.row, pos.cell, !isAddNewRow && this._options.emulatePagingWhenScrolling), this.setActiveCellInternal(this.getCellNode(pos.row, pos.cell)), this.activePosX = pos.posX, this.activePosY = pos.posY, !0; } else return this.setActiveCellInternal(this.getCellNode(this.activeRow, this.activeCell)), !1; } @@ -2987,9 +3235,9 @@ */ canCellBeActive(row, cell) { var _a, _b, _c, _d; - if (!this._options.enableCellNavigation || row >= this.getDataLengthIncludingAddNew() || row < 0 || cell >= this.columns.length || cell < 0 || !this.columns[cell] || this.columns[cell].hidden) + if (!this._options.enableCellNavigation || row >= this.getDataLengthIncludingAddNew() || row < 0 || cell >= this.columns.length || cell < 0 || !this.columns[cell] || this.columns[cell].hidden || ((_b = (_a = this.getParentRowSpanByCell(row, cell)) == null ? void 0 : _a.start) != null ? _b : row) !== row) return !1; - let rowMetadata = (_b = (_a = this.data) == null ? void 0 : _a.getItemMetadata) == null ? void 0 : _b.call(_a, row); + let rowMetadata = this.getItemMetadaWhenExists(row); if ((rowMetadata == null ? void 0 : rowMetadata.focusable) !== void 0) return !!rowMetadata.focusable; let columnMetadata = rowMetadata == null ? void 0 : rowMetadata.columns; @@ -3001,10 +3249,9 @@ * @param {number} col A column index. */ canCellBeSelected(row, cell) { - var _a, _b; if (row >= this.getDataLength() || row < 0 || cell >= this.columns.length || cell < 0 || !this.columns[cell] || this.columns[cell].hidden) return !1; - let rowMetadata = (_b = (_a = this.data) == null ? void 0 : _a.getItemMetadata) == null ? void 0 : _b.call(_a, row); + let rowMetadata = this.getItemMetadaWhenExists(row); if ((rowMetadata == null ? void 0 : rowMetadata.selectable) !== void 0) return !!rowMetadata.selectable; let columnMetadata = (rowMetadata == null ? void 0 : rowMetadata.columns) && (rowMetadata.columns[this.columns[cell].id] || rowMetadata.columns[cell]); @@ -3116,7 +3363,7 @@ * Distributed under MIT license. * All rights reserved. * - * SlickGrid v5.14.3 + * SlickGrid v5.15.0 * * NOTES: * Cell/row DOM manipulations are done directly bypassing JS DOM manipulation methods. diff --git a/dist/browser/slick.grid.js.map b/dist/browser/slick.grid.js.map index 4084bbc7..33d7bffa 100644 --- a/dist/browser/slick.grid.js.map +++ b/dist/browser/slick.grid.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../src/slick.grid.ts"], - "sourcesContent": ["// @ts-ignore\r\nimport type SortableInstance from 'sortablejs';\r\n\r\nimport type {\r\n AutoSize,\r\n CellViewportRange,\r\n Column,\r\n ColumnSort,\r\n CssStyleHash,\r\n CSSStyleDeclarationWritable,\r\n CustomDataView,\r\n DOMEvent,\r\n DragPosition,\r\n DragRowMove,\r\n Editor,\r\n EditorArguments,\r\n EditorConstructor,\r\n EditController,\r\n Formatter,\r\n FormatterOverrideCallback,\r\n FormatterResultObject,\r\n FormatterResultWithHtml,\r\n FormatterResultWithText,\r\n GridOption as BaseGridOption,\r\n InteractionBase,\r\n ItemMetadata,\r\n MenuCommandItemCallbackArgs,\r\n MultiColumnSort,\r\n OnActivateChangedOptionsEventArgs,\r\n OnActiveCellChangedEventArgs,\r\n OnAddNewRowEventArgs,\r\n OnAutosizeColumnsEventArgs,\r\n OnBeforeUpdateColumnsEventArgs,\r\n OnBeforeAppendCellEventArgs,\r\n OnBeforeCellEditorDestroyEventArgs,\r\n OnBeforeColumnsResizeEventArgs,\r\n OnBeforeEditCellEventArgs,\r\n OnBeforeHeaderCellDestroyEventArgs,\r\n OnBeforeHeaderRowCellDestroyEventArgs,\r\n OnBeforeFooterRowCellDestroyEventArgs,\r\n OnBeforeSetColumnsEventArgs,\r\n OnCellChangeEventArgs,\r\n OnCellCssStylesChangedEventArgs,\r\n OnClickEventArgs,\r\n OnColumnsDragEventArgs,\r\n OnColumnsReorderedEventArgs,\r\n OnColumnsResizedEventArgs,\r\n OnColumnsResizeDblClickEventArgs,\r\n OnCompositeEditorChangeEventArgs,\r\n OnDblClickEventArgs,\r\n OnFooterContextMenuEventArgs,\r\n OnFooterRowCellRenderedEventArgs,\r\n OnHeaderCellRenderedEventArgs,\r\n OnFooterClickEventArgs,\r\n OnHeaderClickEventArgs,\r\n OnHeaderContextMenuEventArgs,\r\n OnHeaderMouseEventArgs,\r\n OnHeaderRowCellRenderedEventArgs,\r\n OnKeyDownEventArgs,\r\n OnPreHeaderContextMenuEventArgs,\r\n OnPreHeaderClickEventArgs,\r\n OnRenderedEventArgs,\r\n OnSelectedRowsChangedEventArgs,\r\n OnSetOptionsEventArgs,\r\n OnScrollEventArgs,\r\n OnValidationErrorEventArgs,\r\n PagingInfo,\r\n RowInfo,\r\n SelectionModel,\r\n SingleColumnSort,\r\n SlickGridModel,\r\n SlickPlugin,\r\n} from './models/index.js';\r\nimport {\r\n type BasePubSub,\r\n BindingEventService as BindingEventService_,\r\n ColAutosizeMode as ColAutosizeMode_,\r\n GlobalEditorLock as GlobalEditorLock_,\r\n GridAutosizeColsMode as GridAutosizeColsMode_,\r\n keyCode as keyCode_,\r\n preClickClassName as preClickClassName_,\r\n RowSelectionMode as RowSelectionMode_,\r\n type SlickEditorLock,\r\n SlickEvent as SlickEvent_,\r\n SlickEventData as SlickEventData_,\r\n SlickRange as SlickRange_,\r\n Utils as Utils_,\r\n ValueFilterMode as ValueFilterMode_,\r\n WidthEvalMode as WidthEvalMode_,\r\n} from './slick.core.js';\r\nimport { Draggable as Draggable_, MouseWheel as MouseWheel_, Resizable as Resizable_ } from './slick.interactions.js';\r\n\r\n// for (iife) load Slick methods from global Slick object, or use imports for (esm)\r\nconst BindingEventService = IIFE_ONLY ? Slick.BindingEventService : BindingEventService_;\r\nconst ColAutosizeMode = IIFE_ONLY ? Slick.ColAutosizeMode : ColAutosizeMode_;\r\nconst SlickEvent = IIFE_ONLY ? Slick.Event : SlickEvent_;\r\nconst SlickEventData = IIFE_ONLY ? Slick.EventData : SlickEventData_;\r\nconst GlobalEditorLock = IIFE_ONLY ? Slick.GlobalEditorLock : GlobalEditorLock_;\r\nconst GridAutosizeColsMode = IIFE_ONLY ? Slick.GridAutosizeColsMode : GridAutosizeColsMode_;\r\nconst keyCode = IIFE_ONLY ? Slick.keyCode : keyCode_;\r\nconst preClickClassName = IIFE_ONLY ? Slick.preClickClassName : preClickClassName_;\r\nconst SlickRange = IIFE_ONLY ? Slick.Range : SlickRange_;\r\nconst RowSelectionMode = IIFE_ONLY ? Slick.RowSelectionMode : RowSelectionMode_;\r\nconst ValueFilterMode = IIFE_ONLY ? Slick.ValueFilterMode : ValueFilterMode_;\r\nconst Utils = IIFE_ONLY ? Slick.Utils : Utils_;\r\nconst WidthEvalMode = IIFE_ONLY ? Slick.WidthEvalMode : WidthEvalMode_;\r\nconst Draggable = IIFE_ONLY ? Slick.Draggable : Draggable_;\r\nconst MouseWheel = IIFE_ONLY ? Slick.MouseWheel : MouseWheel_;\r\nconst Resizable = IIFE_ONLY ? Slick.Resizable : Resizable_;\r\n\r\n/**\r\n * @license\r\n * (c) 2009-present Michael Leibman\r\n * michael{dot}leibman{at}gmail{dot}com\r\n * http://github.com/mleibman/slickgrid\r\n *\r\n * Distributed under MIT license.\r\n * All rights reserved.\r\n *\r\n * SlickGrid v5.14.3\r\n *\r\n * NOTES:\r\n * Cell/row DOM manipulations are done directly bypassing JS DOM manipulation methods.\r\n * This increases the speed dramatically, but can only be done safely because there are no event handlers\r\n * or data associated with any cell/row DOM nodes. Cell editors must make sure they implement .destroy()\r\n * and do proper cleanup.\r\n */\r\n\r\n//////////////////////////////////////////////////////////////////////////////////////////////\r\n// SlickGrid class implementation (available as SlickGrid)\r\n\r\ninterface RowCaching {\r\n rowNode: HTMLElement[] | null,\r\n cellColSpans: Array;\r\n cellNodesByColumnIdx: HTMLElement[];\r\n cellRenderQueue: any[];\r\n}\r\n\r\nexport class SlickGrid = Column, O extends BaseGridOption = BaseGridOption> {\r\n //////////////////////////////////////////////////////////////////////////////////////////////\r\n // Public API\r\n slickGridVersion = '5.14.3';\r\n\r\n /** optional grid state clientId */\r\n cid = '';\r\n\r\n // Events\r\n onActiveCellChanged: SlickEvent_;\r\n onActiveCellPositionChanged: SlickEvent_<{ grid: SlickGrid; }>;\r\n onAddNewRow: SlickEvent_;\r\n onAutosizeColumns: SlickEvent_;\r\n onBeforeAppendCell: SlickEvent_;\r\n onBeforeCellEditorDestroy: SlickEvent_;\r\n onBeforeColumnsResize: SlickEvent_;\r\n onBeforeDestroy: SlickEvent_<{ grid: SlickGrid; }>;\r\n onBeforeEditCell: SlickEvent_;\r\n onBeforeFooterRowCellDestroy: SlickEvent_;\r\n onBeforeHeaderCellDestroy: SlickEvent_;\r\n onBeforeHeaderRowCellDestroy: SlickEvent_;\r\n onBeforeSetColumns: SlickEvent_;\r\n onBeforeSort: SlickEvent_;\r\n onBeforeUpdateColumns: SlickEvent_;\r\n onCellChange: SlickEvent_;\r\n onCellCssStylesChanged: SlickEvent_;\r\n onClick: SlickEvent_;\r\n onColumnsReordered: SlickEvent_;\r\n onColumnsDrag: SlickEvent_;\r\n onColumnsResized: SlickEvent_;\r\n onColumnsResizeDblClick: SlickEvent_;\r\n onCompositeEditorChange: SlickEvent_;\r\n onContextMenu: SlickEvent_;\r\n onDrag: SlickEvent_;\r\n onDblClick: SlickEvent_;\r\n onDragInit: SlickEvent_;\r\n onDragStart: SlickEvent_;\r\n onDragEnd: SlickEvent_;\r\n onFooterClick: SlickEvent_;\r\n onFooterContextMenu: SlickEvent_;\r\n onFooterRowCellRendered: SlickEvent_;\r\n onHeaderCellRendered: SlickEvent_;\r\n onHeaderClick: SlickEvent_;\r\n onHeaderContextMenu: SlickEvent_;\r\n onHeaderMouseEnter: SlickEvent_;\r\n onHeaderMouseLeave: SlickEvent_;\r\n onHeaderRowCellRendered: SlickEvent_;\r\n onHeaderRowMouseEnter: SlickEvent_;\r\n onHeaderRowMouseLeave: SlickEvent_;\r\n onPreHeaderContextMenu: SlickEvent_;\r\n onPreHeaderClick: SlickEvent_;\r\n onKeyDown: SlickEvent_;\r\n onMouseEnter: SlickEvent_;\r\n onMouseLeave: SlickEvent_;\r\n onRendered: SlickEvent_;\r\n onScroll: SlickEvent_;\r\n onSelectedRowsChanged: SlickEvent_;\r\n onSetOptions: SlickEvent_;\r\n onActivateChangedOptions: SlickEvent_;\r\n onSort: SlickEvent_;\r\n onValidationError: SlickEvent_;\r\n onViewportChanged: SlickEvent_<{ grid: SlickGrid; }>;\r\n\r\n // ---\r\n // protected variables\r\n\r\n // shared across all grids on the page\r\n protected scrollbarDimensions?: { height: number; width: number; };\r\n protected maxSupportedCssHeight!: number; // browser's breaking point\r\n\r\n protected canvas: HTMLCanvasElement | null = null;\r\n protected canvas_context: CanvasRenderingContext2D | null = null;\r\n\r\n // settings\r\n protected _options!: O;\r\n protected _defaults: BaseGridOption = {\r\n alwaysShowVerticalScroll: false,\r\n alwaysAllowHorizontalScroll: false,\r\n explicitInitialization: false,\r\n rowHeight: 25,\r\n defaultColumnWidth: 80,\r\n enableHtmlRendering: true,\r\n enableAddRow: false,\r\n leaveSpaceForNewRows: false,\r\n editable: false,\r\n autoEdit: true,\r\n autoEditNewRow: true,\r\n autoCommitEdit: false,\r\n suppressActiveCellChangeOnEdit: false,\r\n enableCellNavigation: true,\r\n enableColumnReorder: true,\r\n unorderableColumnCssClass: 'unorderable',\r\n asyncEditorLoading: false,\r\n asyncEditorLoadDelay: 100,\r\n forceFitColumns: false,\r\n enableAsyncPostRender: false,\r\n asyncPostRenderDelay: 50,\r\n enableAsyncPostRenderCleanup: false,\r\n asyncPostRenderCleanupDelay: 40,\r\n auto: false,\r\n nonce: '',\r\n editorLock: GlobalEditorLock,\r\n showColumnHeader: true,\r\n showHeaderRow: false,\r\n headerRowHeight: 25,\r\n createFooterRow: false,\r\n showFooterRow: false,\r\n footerRowHeight: 25,\r\n createPreHeaderPanel: false,\r\n createTopHeaderPanel: false,\r\n showPreHeaderPanel: false,\r\n showTopHeaderPanel: false,\r\n preHeaderPanelHeight: 25,\r\n showTopPanel: false,\r\n topPanelHeight: 25,\r\n preHeaderPanelWidth: 'auto', // mostly useful for Draggable Grouping dropzone to take full width\r\n topHeaderPanelHeight: 25,\r\n topHeaderPanelWidth: 'auto', // mostly useful for Draggable Grouping dropzone to take full width\r\n formatterFactory: null,\r\n editorFactory: null,\r\n cellFlashingCssClass: 'flashing',\r\n rowHighlightCssClass: 'highlight-animate',\r\n rowHighlightDuration: 400,\r\n selectedCellCssClass: 'selected',\r\n multiSelect: true,\r\n enableTextSelectionOnCells: false,\r\n dataItemColumnValueExtractor: null,\r\n frozenBottom: false,\r\n frozenColumn: -1,\r\n frozenRow: -1,\r\n frozenRightViewportMinWidth: 100,\r\n throwWhenFrozenNotAllViewable: false,\r\n fullWidthRows: false,\r\n multiColumnSort: false,\r\n numberedMultiColumnSort: false,\r\n tristateMultiColumnSort: false,\r\n sortColNumberInSeparateSpan: false,\r\n defaultFormatter: this.defaultFormatter,\r\n forceSyncScrolling: false,\r\n addNewRowCssClass: 'new-row',\r\n preserveCopiedSelectionOnPaste: false,\r\n preventDragFromKeys: ['ctrlKey', 'metaKey'],\r\n showCellSelection: true,\r\n viewportClass: undefined,\r\n minRowBuffer: 3,\r\n emulatePagingWhenScrolling: true, // when scrolling off bottom of viewport, place new row at top of viewport\r\n editorCellNavOnLRKeys: false,\r\n enableMouseWheelScrollHandler: true,\r\n doPaging: true,\r\n autosizeColsMode: GridAutosizeColsMode.LegacyOff,\r\n autosizeColPaddingPx: 4,\r\n rowTopOffsetRenderType: 'top',\r\n scrollRenderThrottling: 10,\r\n autosizeTextAvgToMWidthRatio: 0.75,\r\n viewportSwitchToScrollModeWidthPercent: undefined,\r\n viewportMinWidthPx: undefined,\r\n viewportMaxWidthPx: undefined,\r\n suppressCssChangesOnHiddenInit: false,\r\n ffMaxSupportedCssHeight: 6000000,\r\n maxSupportedCssHeight: 1000000000,\r\n sanitizer: undefined, // sanitize function, built in basic sanitizer is: Slick.RegexSanitizer(dirtyHtml)\r\n logSanitizedHtml: false, // log to console when sanitised - recommend true for testing of dev and production\r\n mixinDefaults: true,\r\n shadowRoot: undefined\r\n };\r\n\r\n protected _columnDefaults = {\r\n name: '',\r\n headerCssClass: null,\r\n defaultSortAsc: true,\r\n focusable: true,\r\n hidden: false,\r\n minWidth: 30,\r\n maxWidth: undefined,\r\n rerenderOnResize: false,\r\n reorderable: true,\r\n resizable: true,\r\n sortable: false,\r\n selectable: true,\r\n } as Partial;\r\n\r\n protected _columnAutosizeDefaults: AutoSize = {\r\n ignoreHeaderText: false,\r\n colValueArray: undefined,\r\n allowAddlPercent: undefined,\r\n formatterOverride: undefined,\r\n autosizeMode: ColAutosizeMode.ContentIntelligent,\r\n rowSelectionModeOnInit: undefined,\r\n rowSelectionMode: RowSelectionMode.FirstNRows,\r\n rowSelectionCount: 100,\r\n valueFilterMode: ValueFilterMode.None,\r\n widthEvalMode: WidthEvalMode.Auto,\r\n sizeToRemaining: undefined,\r\n widthPx: undefined,\r\n contentSizePx: 0,\r\n headerWidthPx: 0,\r\n colDataTypeOf: undefined\r\n };\r\n\r\n protected _columnResizeTimer?: number;\r\n protected _executionBlockTimer?: number;\r\n protected _flashCellTimer?: number;\r\n protected _highlightRowTimer?: number;\r\n\r\n // scroller\r\n protected th!: number; // virtual height\r\n protected h!: number; // real scrollable height\r\n protected ph!: number; // page height\r\n protected n!: number; // number of pages\r\n protected cj!: number; // \"jumpiness\" coefficient\r\n\r\n protected page = 0; // current page\r\n protected offset = 0; // current page offset\r\n protected vScrollDir = 1;\r\n protected _bindingEventService = new BindingEventService();\r\n protected initialized = false;\r\n protected _container!: HTMLElement;\r\n protected uid = `slickgrid_${Math.round(1000000 * Math.random())}`;\r\n protected _focusSink!: HTMLDivElement;\r\n protected _focusSink2!: HTMLDivElement;\r\n protected _groupHeaders: HTMLDivElement[] = [];\r\n protected _headerScroller: HTMLDivElement[] = [];\r\n protected _headers: HTMLDivElement[] = [];\r\n protected _headerRows!: HTMLDivElement[];\r\n protected _headerRowScroller!: HTMLDivElement[];\r\n protected _headerRowSpacerL!: HTMLDivElement;\r\n protected _headerRowSpacerR!: HTMLDivElement;\r\n protected _footerRow!: HTMLDivElement[];\r\n protected _footerRowScroller!: HTMLDivElement[];\r\n protected _footerRowSpacerL!: HTMLDivElement;\r\n protected _footerRowSpacerR!: HTMLDivElement;\r\n protected _preHeaderPanel!: HTMLDivElement;\r\n protected _preHeaderPanelScroller!: HTMLDivElement;\r\n protected _preHeaderPanelSpacer!: HTMLDivElement;\r\n protected _preHeaderPanelR!: HTMLDivElement;\r\n protected _preHeaderPanelScrollerR!: HTMLDivElement;\r\n protected _preHeaderPanelSpacerR!: HTMLDivElement;\r\n protected _topHeaderPanel!: HTMLDivElement;\r\n protected _topHeaderPanelScroller!: HTMLDivElement;\r\n protected _topHeaderPanelSpacer!: HTMLDivElement;\r\n protected _topPanelScrollers!: HTMLDivElement[];\r\n protected _topPanels!: HTMLDivElement[];\r\n protected _viewport!: HTMLDivElement[];\r\n protected _canvas!: HTMLDivElement[];\r\n protected _style?: HTMLStyleElement;\r\n protected _boundAncestors: HTMLElement[] = [];\r\n protected stylesheet?: { cssRules: Array<{ selectorText: string; }>; rules: Array<{ selectorText: string; }>; } | null;\r\n protected columnCssRulesL?: Array<{ selectorText: string; }>;\r\n protected columnCssRulesR?: Array<{ selectorText: string; }>;\r\n protected viewportH = 0;\r\n protected viewportW = 0;\r\n protected canvasWidth = 0;\r\n protected canvasWidthL = 0;\r\n protected canvasWidthR = 0;\r\n protected headersWidth = 0;\r\n protected headersWidthL = 0;\r\n protected headersWidthR = 0;\r\n protected viewportHasHScroll = false;\r\n protected viewportHasVScroll = false;\r\n protected headerColumnWidthDiff = 0;\r\n protected headerColumnHeightDiff = 0; // border+padding\r\n protected cellWidthDiff = 0;\r\n protected cellHeightDiff = 0;\r\n protected absoluteColumnMinWidth!: number;\r\n protected hasFrozenRows = false;\r\n protected frozenRowsHeight = 0;\r\n protected actualFrozenRow = -1;\r\n protected paneTopH = 0;\r\n protected paneBottomH = 0;\r\n protected viewportTopH = 0;\r\n protected viewportBottomH = 0;\r\n protected topPanelH = 0;\r\n protected headerRowH = 0;\r\n protected footerRowH = 0;\r\n\r\n protected tabbingDirection = 1;\r\n protected _activeCanvasNode!: HTMLDivElement;\r\n protected _activeViewportNode!: HTMLDivElement;\r\n protected activePosX!: number;\r\n protected activeRow!: number;\r\n protected activeCell!: number;\r\n protected activeCellNode: HTMLDivElement | null = null;\r\n protected currentEditor: Editor | null = null;\r\n protected serializedEditorValue: any;\r\n protected editController?: EditController;\r\n\r\n protected rowsCache: Array = {} as any;\r\n protected renderedRows = 0;\r\n protected numVisibleRows = 0;\r\n protected prevScrollTop = 0;\r\n protected scrollHeight = 0;\r\n protected scrollTop = 0;\r\n protected lastRenderedScrollTop = 0;\r\n protected lastRenderedScrollLeft = 0;\r\n protected prevScrollLeft = 0;\r\n protected scrollLeft = 0;\r\n\r\n protected selectionModel?: SelectionModel;\r\n protected selectedRows: number[] = [];\r\n\r\n protected plugins: SlickPlugin[] = [];\r\n protected cellCssClasses: CssStyleHash = {};\r\n\r\n protected columnsById: Record = {};\r\n protected sortColumns: ColumnSort[] = [];\r\n protected columnPosLeft: number[] = [];\r\n protected columnPosRight: number[] = [];\r\n\r\n protected pagingActive = false;\r\n protected pagingIsLastPage = false;\r\n\r\n protected scrollThrottle!: { enqueue: () => void; dequeue: () => void; };\r\n\r\n // async call handles\r\n protected h_editorLoader?: number;\r\n protected h_render = null;\r\n protected h_postrender?: number;\r\n protected h_postrenderCleanup?: number;\r\n protected postProcessedRows: any = {};\r\n protected postProcessToRow: number = null as any;\r\n protected postProcessFromRow: number = null as any;\r\n protected postProcessedCleanupQueue: Array<{\r\n actionType: string;\r\n groupId: number;\r\n node: HTMLElement | HTMLElement[];\r\n columnIdx?: number;\r\n rowIdx?: number;\r\n }> = [];\r\n protected postProcessgroupId = 0;\r\n\r\n // perf counters\r\n protected counter_rows_rendered = 0;\r\n protected counter_rows_removed = 0;\r\n\r\n protected _paneHeaderL!: HTMLDivElement;\r\n protected _paneHeaderR!: HTMLDivElement;\r\n protected _paneTopL!: HTMLDivElement;\r\n protected _paneTopR!: HTMLDivElement;\r\n protected _paneBottomL!: HTMLDivElement;\r\n protected _paneBottomR!: HTMLDivElement;\r\n protected _headerScrollerL!: HTMLDivElement;\r\n protected _headerScrollerR!: HTMLDivElement;\r\n protected _headerL!: HTMLDivElement;\r\n protected _headerR!: HTMLDivElement;\r\n protected _groupHeadersL!: HTMLDivElement;\r\n protected _groupHeadersR!: HTMLDivElement;\r\n protected _headerRowScrollerL!: HTMLDivElement;\r\n protected _headerRowScrollerR!: HTMLDivElement;\r\n protected _footerRowScrollerL!: HTMLDivElement;\r\n protected _footerRowScrollerR!: HTMLDivElement;\r\n protected _headerRowL!: HTMLDivElement;\r\n protected _headerRowR!: HTMLDivElement;\r\n protected _footerRowL!: HTMLDivElement;\r\n protected _footerRowR!: HTMLDivElement;\r\n protected _topPanelScrollerL!: HTMLDivElement;\r\n protected _topPanelScrollerR!: HTMLDivElement;\r\n protected _topPanelL!: HTMLDivElement;\r\n protected _topPanelR!: HTMLDivElement;\r\n protected _viewportTopL!: HTMLDivElement;\r\n protected _viewportTopR!: HTMLDivElement;\r\n protected _viewportBottomL!: HTMLDivElement;\r\n protected _viewportBottomR!: HTMLDivElement;\r\n protected _canvasTopL!: HTMLDivElement;\r\n protected _canvasTopR!: HTMLDivElement;\r\n protected _canvasBottomL!: HTMLDivElement;\r\n protected _canvasBottomR!: HTMLDivElement;\r\n protected _viewportScrollContainerX!: HTMLDivElement;\r\n protected _viewportScrollContainerY!: HTMLDivElement;\r\n protected _headerScrollContainer!: HTMLDivElement;\r\n protected _headerRowScrollContainer!: HTMLDivElement;\r\n protected _footerRowScrollContainer!: HTMLDivElement;\r\n\r\n // store css attributes if display:none is active in container or parent\r\n protected cssShow = { position: 'absolute', visibility: 'hidden', display: 'block' };\r\n protected _hiddenParents: HTMLElement[] = [];\r\n protected oldProps: Array> = [];\r\n protected enforceFrozenRowHeightRecalc = false;\r\n protected columnResizeDragging = false;\r\n protected slickDraggableInstance: InteractionBase | null = null;\r\n protected slickMouseWheelInstances: Array = [];\r\n protected slickResizableInstances: Array = [];\r\n protected sortableSideLeftInstance?: SortableInstance;\r\n protected sortableSideRightInstance?: SortableInstance;\r\n protected logMessageCount = 0;\r\n protected logMessageMaxCount = 30;\r\n protected _pubSubService?: BasePubSub;\r\n\r\n /**\r\n * Creates a new instance of the grid.\r\n * @class SlickGrid\r\n * @constructor\r\n * @param {Node} container - Container node to create the grid in.\r\n * @param {Array|Object} data - An array of objects for databinding or an external DataView.\r\n * @param {Array} columns - An array of column definitions.\r\n * @param {Object} [options] - Grid Options\r\n * @param {Object} [externalPubSub] - optional External PubSub Service to use by SlickEvent\r\n **/\r\n constructor(protected readonly container: HTMLElement | string, protected data: CustomDataView | TData[], protected columns: C[], options: Partial, protected readonly externalPubSub?: BasePubSub) {\r\n this._container = typeof this.container === 'string'\r\n ? document.querySelector(this.container) as HTMLDivElement\r\n : this.container;\r\n\r\n if (!this._container) {\r\n throw new Error(`SlickGrid requires a valid container, ${this.container} does not exist in the DOM.`);\r\n }\r\n\r\n this._pubSubService = externalPubSub;\r\n this.onActiveCellChanged = new SlickEvent('onActiveCellChanged', externalPubSub);\r\n this.onActiveCellPositionChanged = new SlickEvent<{ grid: SlickGrid; }>('onActiveCellPositionChanged', externalPubSub);\r\n this.onAddNewRow = new SlickEvent('onAddNewRow', externalPubSub);\r\n this.onAutosizeColumns = new SlickEvent('onAutosizeColumns', externalPubSub);\r\n this.onBeforeAppendCell = new SlickEvent('onBeforeAppendCell', externalPubSub);\r\n this.onBeforeCellEditorDestroy = new SlickEvent('onBeforeCellEditorDestroy', externalPubSub);\r\n this.onBeforeColumnsResize = new SlickEvent('onBeforeColumnsResize', externalPubSub);\r\n this.onBeforeDestroy = new SlickEvent<{ grid: SlickGrid; }>('onBeforeDestroy', externalPubSub);\r\n this.onBeforeEditCell = new SlickEvent('onBeforeEditCell', externalPubSub);\r\n this.onBeforeFooterRowCellDestroy = new SlickEvent('onBeforeFooterRowCellDestroy', externalPubSub);\r\n this.onBeforeHeaderCellDestroy = new SlickEvent('onBeforeHeaderCellDestroy', externalPubSub);\r\n this.onBeforeHeaderRowCellDestroy = new SlickEvent('onBeforeHeaderRowCellDestroy', externalPubSub);\r\n this.onBeforeSetColumns = new SlickEvent('onBeforeSetColumns', externalPubSub);\r\n this.onBeforeSort = new SlickEvent('onBeforeSort', externalPubSub);\r\n this.onBeforeUpdateColumns = new SlickEvent('onBeforeUpdateColumns', externalPubSub);\r\n this.onCellChange = new SlickEvent('onCellChange', externalPubSub);\r\n this.onCellCssStylesChanged = new SlickEvent('onCellCssStylesChanged', externalPubSub);\r\n this.onClick = new SlickEvent('onClick', externalPubSub);\r\n this.onColumnsReordered = new SlickEvent('onColumnsReordered', externalPubSub);\r\n this.onColumnsDrag = new SlickEvent('onColumnsDrag', externalPubSub);\r\n this.onColumnsResized = new SlickEvent('onColumnsResized', externalPubSub);\r\n this.onColumnsResizeDblClick = new SlickEvent('onColumnsResizeDblClick', externalPubSub);\r\n this.onCompositeEditorChange = new SlickEvent('onCompositeEditorChange', externalPubSub);\r\n this.onContextMenu = new SlickEvent('onContextMenu', externalPubSub);\r\n this.onDrag = new SlickEvent('onDrag', externalPubSub);\r\n this.onDblClick = new SlickEvent('onDblClick', externalPubSub);\r\n this.onDragInit = new SlickEvent('onDragInit', externalPubSub);\r\n this.onDragStart = new SlickEvent('onDragStart', externalPubSub);\r\n this.onDragEnd = new SlickEvent('onDragEnd', externalPubSub);\r\n this.onFooterClick = new SlickEvent('onFooterClick', externalPubSub);\r\n this.onFooterContextMenu = new SlickEvent('onFooterContextMenu', externalPubSub);\r\n this.onFooterRowCellRendered = new SlickEvent('onFooterRowCellRendered', externalPubSub);\r\n this.onHeaderCellRendered = new SlickEvent('onHeaderCellRendered', externalPubSub);\r\n this.onHeaderClick = new SlickEvent('onHeaderClick', externalPubSub);\r\n this.onHeaderContextMenu = new SlickEvent('onHeaderContextMenu', externalPubSub);\r\n this.onHeaderMouseEnter = new SlickEvent('onHeaderMouseEnter', externalPubSub);\r\n this.onHeaderMouseLeave = new SlickEvent('onHeaderMouseLeave', externalPubSub);\r\n this.onHeaderRowCellRendered = new SlickEvent('onHeaderRowCellRendered', externalPubSub);\r\n this.onHeaderRowMouseEnter = new SlickEvent('onHeaderRowMouseEnter', externalPubSub);\r\n this.onHeaderRowMouseLeave = new SlickEvent('onHeaderRowMouseLeave', externalPubSub);\r\n this.onPreHeaderClick = new SlickEvent('onPreHeaderClick', externalPubSub);\r\n this.onPreHeaderContextMenu = new SlickEvent('onPreHeaderContextMenu', externalPubSub);\r\n this.onKeyDown = new SlickEvent('onKeyDown', externalPubSub);\r\n this.onMouseEnter = new SlickEvent('onMouseEnter', externalPubSub);\r\n this.onMouseLeave = new SlickEvent('onMouseLeave', externalPubSub);\r\n this.onRendered = new SlickEvent('onRendered', externalPubSub);\r\n this.onScroll = new SlickEvent('onScroll', externalPubSub);\r\n this.onSelectedRowsChanged = new SlickEvent('onSelectedRowsChanged', externalPubSub);\r\n this.onSetOptions = new SlickEvent('onSetOptions', externalPubSub);\r\n this.onActivateChangedOptions = new SlickEvent('onActivateChangedOptions', externalPubSub);\r\n this.onSort = new SlickEvent('onSort', externalPubSub);\r\n this.onValidationError = new SlickEvent('onValidationError', externalPubSub);\r\n this.onViewportChanged = new SlickEvent<{ grid: SlickGrid; }>('onViewportChanged', externalPubSub);\r\n\r\n this.initialize(options);\r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////////\r\n // Initialization\r\n\r\n /** Initializes the grid. */\r\n init() {\r\n this.finishInitialization();\r\n }\r\n\r\n /**\r\n * Apply HTML code by 3 different ways depending on what is provided as input and what options are enabled.\r\n * 1. value is an HTMLElement or DocumentFragment, then first empty the target and simply append the HTML to the target element.\r\n * 2. value is string and `enableHtmlRendering` is enabled, then use `target.innerHTML = value;`\r\n * 3. value is string and `enableHtmlRendering` is disabled, then use `target.textContent = value;`\r\n * @param target - target element to apply to\r\n * @param val - input value can be either a string or an HTMLElement\r\n * @param options -\r\n * `emptyTarget`, defaults to true, will empty the target.\r\n * `skipEmptyReassignment`, defaults to true, when enabled it will not try to reapply an empty value when the target is already empty\r\n */\r\n applyHtmlCode(target: HTMLElement, val: string | HTMLElement | DocumentFragment, options?: { emptyTarget?: boolean; skipEmptyReassignment?: boolean; }) {\r\n if (target) {\r\n if (val instanceof HTMLElement || val instanceof DocumentFragment) {\r\n // first empty target and then append new HTML element\r\n const emptyTarget = options?.emptyTarget !== false;\r\n if (emptyTarget) {\r\n Utils.emptyElement(target);\r\n }\r\n target.appendChild(val);\r\n } else {\r\n // when it's already empty and we try to reassign empty, it's probably ok to skip the assignment\r\n const skipEmptyReassignment = options?.skipEmptyReassignment !== false;\r\n if (skipEmptyReassignment && !Utils.isDefined(val) && !target.innerHTML) {\r\n return;\r\n }\r\n\r\n let sanitizedText = val;\r\n if (typeof sanitizedText === 'number' || typeof sanitizedText === 'boolean') {\r\n target.textContent = sanitizedText;\r\n } else {\r\n sanitizedText = this.sanitizeHtmlString(val as string);\r\n\r\n // apply HTML when enableHtmlRendering is enabled but make sure we do have a value (without a value, it will simply use `textContent` to clear text content)\r\n if (this._options.enableHtmlRendering && sanitizedText) {\r\n target.innerHTML = sanitizedText;\r\n } else {\r\n target.textContent = sanitizedText;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n protected initialize(options: Partial) {\r\n // calculate these only once and share between grid instances\r\n if (options?.mixinDefaults) {\r\n // use provided options and then assign defaults\r\n if (!this._options) { this._options = options as O; }\r\n Utils.applyDefaults(this._options, this._defaults);\r\n } else {\r\n this._options = Utils.extend(true, {}, this._defaults, options);\r\n }\r\n this.scrollThrottle = this.actionThrottle(this.render.bind(this), this._options.scrollRenderThrottling as number);\r\n this.maxSupportedCssHeight = this.maxSupportedCssHeight || this.getMaxSupportedCssHeight();\r\n this.validateAndEnforceOptions();\r\n this._columnDefaults.width = this._options.defaultColumnWidth;\r\n\r\n if (!this._options.suppressCssChangesOnHiddenInit) {\r\n this.cacheCssForHiddenInit();\r\n }\r\n\r\n this.updateColumnProps();\r\n\r\n // validate loaded JavaScript modules against requested options\r\n if (this._options.enableColumnReorder && (!Sortable || !Sortable.create)) {\r\n throw new Error('SlickGrid requires Sortable.js module to be loaded');\r\n }\r\n\r\n this.editController = {\r\n commitCurrentEdit: this.commitCurrentEdit.bind(this),\r\n cancelCurrentEdit: this.cancelCurrentEdit.bind(this),\r\n };\r\n\r\n Utils.emptyElement(this._container);\r\n this._container.style.outline = String(0);\r\n this._container.classList.add(this.uid);\r\n this._container.classList.add('ui-widget');\r\n this._container.setAttribute('role', 'grid');\r\n\r\n const containerStyles = window.getComputedStyle(this._container);\r\n if (!(/relative|absolute|fixed/).test(containerStyles.position)) {\r\n this._container.style.position = 'relative';\r\n }\r\n\r\n this._focusSink = Utils.createDomElement('div', { tabIndex: 0, style: { position: 'fixed', width: '0px', height: '0px', top: '0px', left: '0px', outline: '0px' } }, this._container);\r\n\r\n if (this._options.createTopHeaderPanel) {\r\n this._topHeaderPanelScroller = Utils.createDomElement('div', { className: 'slick-topheader-panel slick-state-default', style: { overflow: 'hidden', position: 'relative' } }, this._container);\r\n this._topHeaderPanelScroller.appendChild(document.createElement('div'));\r\n this._topHeaderPanel = Utils.createDomElement('div', null, this._topHeaderPanelScroller);\r\n this._topHeaderPanelSpacer = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._topHeaderPanelScroller);\r\n\r\n if (!this._options.showTopHeaderPanel) {\r\n Utils.hide(this._topHeaderPanelScroller);\r\n }\r\n }\r\n\r\n // Containers used for scrolling frozen columns and rows\r\n this._paneHeaderL = Utils.createDomElement('div', { className: 'slick-pane slick-pane-header slick-pane-left', tabIndex: 0 }, this._container);\r\n this._paneHeaderR = Utils.createDomElement('div', { className: 'slick-pane slick-pane-header slick-pane-right', tabIndex: 0 }, this._container);\r\n this._paneTopL = Utils.createDomElement('div', { className: 'slick-pane slick-pane-top slick-pane-left', tabIndex: 0 }, this._container);\r\n this._paneTopR = Utils.createDomElement('div', { className: 'slick-pane slick-pane-top slick-pane-right', tabIndex: 0 }, this._container);\r\n this._paneBottomL = Utils.createDomElement('div', { className: 'slick-pane slick-pane-bottom slick-pane-left', tabIndex: 0 }, this._container);\r\n this._paneBottomR = Utils.createDomElement('div', { className: 'slick-pane slick-pane-bottom slick-pane-right', tabIndex: 0 }, this._container);\r\n\r\n if (this._options.createPreHeaderPanel) {\r\n this._preHeaderPanelScroller = Utils.createDomElement('div', { className: 'slick-preheader-panel ui-state-default slick-state-default', style: { overflow: 'hidden', position: 'relative' } }, this._paneHeaderL);\r\n this._preHeaderPanelScroller.appendChild(document.createElement('div'));\r\n this._preHeaderPanel = Utils.createDomElement('div', null, this._preHeaderPanelScroller);\r\n this._preHeaderPanelSpacer = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._preHeaderPanelScroller);\r\n\r\n this._preHeaderPanelScrollerR = Utils.createDomElement('div', { className: 'slick-preheader-panel ui-state-default slick-state-default', style: { overflow: 'hidden', position: 'relative' } }, this._paneHeaderR);\r\n this._preHeaderPanelR = Utils.createDomElement('div', null, this._preHeaderPanelScrollerR);\r\n this._preHeaderPanelSpacerR = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._preHeaderPanelScrollerR);\r\n\r\n if (!this._options.showPreHeaderPanel) {\r\n Utils.hide(this._preHeaderPanelScroller);\r\n Utils.hide(this._preHeaderPanelScrollerR);\r\n }\r\n }\r\n\r\n // Append the header scroller containers\r\n this._headerScrollerL = Utils.createDomElement('div', { className: 'slick-header ui-state-default slick-state-default slick-header-left' }, this._paneHeaderL);\r\n this._headerScrollerR = Utils.createDomElement('div', { className: 'slick-header ui-state-default slick-state-default slick-header-right' }, this._paneHeaderR);\r\n\r\n // Cache the header scroller containers\r\n this._headerScroller.push(this._headerScrollerL);\r\n this._headerScroller.push(this._headerScrollerR);\r\n\r\n // Append the columnn containers to the headers\r\n this._headerL = Utils.createDomElement('div', { className: 'slick-header-columns slick-header-columns-left', role: 'row', style: { left: '-1000px' } }, this._headerScrollerL);\r\n this._headerR = Utils.createDomElement('div', { className: 'slick-header-columns slick-header-columns-right', role: 'row', style: { left: '-1000px' } }, this._headerScrollerR);\r\n\r\n // Cache the header columns\r\n this._headers = [this._headerL, this._headerR];\r\n\r\n this._headerRowScrollerL = Utils.createDomElement('div', { className: 'slick-headerrow ui-state-default slick-state-default' }, this._paneTopL);\r\n this._headerRowScrollerR = Utils.createDomElement('div', { className: 'slick-headerrow ui-state-default slick-state-default' }, this._paneTopR);\r\n\r\n this._headerRowScroller = [this._headerRowScrollerL, this._headerRowScrollerR];\r\n\r\n this._headerRowSpacerL = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._headerRowScrollerL);\r\n this._headerRowSpacerR = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._headerRowScrollerR);\r\n\r\n this._headerRowL = Utils.createDomElement('div', { className: 'slick-headerrow-columns slick-headerrow-columns-left' }, this._headerRowScrollerL);\r\n this._headerRowR = Utils.createDomElement('div', { className: 'slick-headerrow-columns slick-headerrow-columns-right' }, this._headerRowScrollerR);\r\n\r\n this._headerRows = [this._headerRowL, this._headerRowR];\r\n\r\n // Append the top panel scroller\r\n this._topPanelScrollerL = Utils.createDomElement('div', { className: 'slick-top-panel-scroller ui-state-default slick-state-default' }, this._paneTopL);\r\n this._topPanelScrollerR = Utils.createDomElement('div', { className: 'slick-top-panel-scroller ui-state-default slick-state-default' }, this._paneTopR);\r\n\r\n this._topPanelScrollers = [this._topPanelScrollerL, this._topPanelScrollerR];\r\n\r\n // Append the top panel\r\n this._topPanelL = Utils.createDomElement('div', { className: 'slick-top-panel', style: { width: '10000px' } }, this._topPanelScrollerL);\r\n this._topPanelR = Utils.createDomElement('div', { className: 'slick-top-panel', style: { width: '10000px' } }, this._topPanelScrollerR);\r\n\r\n this._topPanels = [this._topPanelL, this._topPanelR];\r\n\r\n if (!this._options.showColumnHeader) {\r\n this._headerScroller.forEach((el) => {\r\n Utils.hide(el);\r\n });\r\n }\r\n\r\n if (!this._options.showTopPanel) {\r\n this._topPanelScrollers.forEach((scroller) => {\r\n Utils.hide(scroller);\r\n });\r\n }\r\n\r\n if (!this._options.showHeaderRow) {\r\n this._headerRowScroller.forEach((scroller) => {\r\n Utils.hide(scroller);\r\n });\r\n }\r\n\r\n // Append the viewport containers\r\n this._viewportTopL = Utils.createDomElement('div', { className: 'slick-viewport slick-viewport-top slick-viewport-left', tabIndex: 0 }, this._paneTopL);\r\n this._viewportTopR = Utils.createDomElement('div', { className: 'slick-viewport slick-viewport-top slick-viewport-right', tabIndex: 0 }, this._paneTopR);\r\n this._viewportBottomL = Utils.createDomElement('div', { className: 'slick-viewport slick-viewport-bottom slick-viewport-left', tabIndex: 0 }, this._paneBottomL);\r\n this._viewportBottomR = Utils.createDomElement('div', { className: 'slick-viewport slick-viewport-bottom slick-viewport-right', tabIndex: 0 }, this._paneBottomR);\r\n\r\n // Cache the viewports\r\n this._viewport = [this._viewportTopL, this._viewportTopR, this._viewportBottomL, this._viewportBottomR];\r\n if (this._options.viewportClass) {\r\n this._viewport.forEach((view) => {\r\n view.classList.add(...Utils.classNameToList((this._options.viewportClass)));\r\n });\r\n }\r\n\r\n // Default the active viewport to the top left\r\n this._activeViewportNode = this._viewportTopL;\r\n\r\n // Append the canvas containers\r\n this._canvasTopL = Utils.createDomElement('div', { className: 'grid-canvas grid-canvas-top grid-canvas-left', tabIndex: 0 }, this._viewportTopL);\r\n this._canvasTopR = Utils.createDomElement('div', { className: 'grid-canvas grid-canvas-top grid-canvas-right', tabIndex: 0 }, this._viewportTopR);\r\n this._canvasBottomL = Utils.createDomElement('div', { className: 'grid-canvas grid-canvas-bottom grid-canvas-left', tabIndex: 0 }, this._viewportBottomL);\r\n this._canvasBottomR = Utils.createDomElement('div', { className: 'grid-canvas grid-canvas-bottom grid-canvas-right', tabIndex: 0 }, this._viewportBottomR);\r\n\r\n // Cache the canvases\r\n this._canvas = [this._canvasTopL, this._canvasTopR, this._canvasBottomL, this._canvasBottomR];\r\n\r\n this.scrollbarDimensions = this.scrollbarDimensions || this.measureScrollbar();\r\n\r\n // Default the active canvas to the top left\r\n this._activeCanvasNode = this._canvasTopL;\r\n\r\n // top-header\r\n if (this._topHeaderPanelSpacer) {\r\n Utils.width(this._topHeaderPanelSpacer, this.getCanvasWidth() + this.scrollbarDimensions.width);\r\n }\r\n\r\n // pre-header\r\n if (this._preHeaderPanelSpacer) {\r\n Utils.width(this._preHeaderPanelSpacer, this.getCanvasWidth() + this.scrollbarDimensions.width);\r\n }\r\n\r\n this._headers.forEach((el) => {\r\n Utils.width(el, this.getHeadersWidth());\r\n });\r\n\r\n Utils.width(this._headerRowSpacerL, this.getCanvasWidth() + this.scrollbarDimensions.width);\r\n Utils.width(this._headerRowSpacerR, this.getCanvasWidth() + this.scrollbarDimensions.width);\r\n\r\n // footer Row\r\n if (this._options.createFooterRow) {\r\n this._footerRowScrollerR = Utils.createDomElement('div', { className: 'slick-footerrow ui-state-default slick-state-default' }, this._paneTopR);\r\n this._footerRowScrollerL = Utils.createDomElement('div', { className: 'slick-footerrow ui-state-default slick-state-default' }, this._paneTopL);\r\n\r\n this._footerRowScroller = [this._footerRowScrollerL, this._footerRowScrollerR];\r\n\r\n this._footerRowSpacerL = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._footerRowScrollerL);\r\n Utils.width(this._footerRowSpacerL, this.getCanvasWidth() + this.scrollbarDimensions.width);\r\n this._footerRowSpacerR = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._footerRowScrollerR);\r\n Utils.width(this._footerRowSpacerR, this.getCanvasWidth() + this.scrollbarDimensions.width);\r\n\r\n this._footerRowL = Utils.createDomElement('div', { className: 'slick-footerrow-columns slick-footerrow-columns-left' }, this._footerRowScrollerL);\r\n this._footerRowR = Utils.createDomElement('div', { className: 'slick-footerrow-columns slick-footerrow-columns-right' }, this._footerRowScrollerR);\r\n\r\n this._footerRow = [this._footerRowL, this._footerRowR];\r\n\r\n if (!this._options.showFooterRow) {\r\n this._footerRowScroller.forEach((scroller) => {\r\n Utils.hide(scroller);\r\n });\r\n }\r\n }\r\n\r\n this._focusSink2 = this._focusSink.cloneNode(true) as HTMLDivElement;\r\n this._container.appendChild(this._focusSink2);\r\n\r\n if (!this._options.explicitInitialization) {\r\n this.finishInitialization();\r\n }\r\n }\r\n\r\n protected finishInitialization() {\r\n if (!this.initialized) {\r\n this.initialized = true;\r\n\r\n this.getViewportWidth();\r\n this.getViewportHeight();\r\n\r\n // header columns and cells may have different padding/border skewing width calculations (box-sizing, hello?)\r\n // calculate the diff so we can set consistent sizes\r\n this.measureCellPaddingAndBorder();\r\n\r\n // for usability reasons, all text selection in SlickGrid is disabled\r\n // with the exception of input and textarea elements (selection must\r\n // be enabled there so that editors work as expected); note that\r\n // selection in grid cells (grid body) is already unavailable in\r\n // all browsers except IE\r\n this.disableSelection(this._headers); // disable all text selection in header (including input and textarea)\r\n\r\n if (!this._options.enableTextSelectionOnCells) {\r\n // disable text selection in grid cells except in input and textarea elements\r\n // (this is IE-specific, because selectstart event will only fire in IE)\r\n this._viewport.forEach((view) => {\r\n this._bindingEventService.bind(view, 'selectstart', (event) => {\r\n if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) {\r\n return;\r\n }\r\n });\r\n });\r\n }\r\n\r\n this.setFrozenOptions();\r\n this.setPaneVisibility();\r\n this.setScroller();\r\n this.setOverflow();\r\n\r\n this.updateColumnCaches();\r\n this.createColumnHeaders();\r\n this.createColumnFooter();\r\n this.setupColumnSort();\r\n this.createCssRules();\r\n this.resizeCanvas();\r\n this.bindAncestorScrollEvents();\r\n\r\n this._bindingEventService.bind(this._container, 'resize', this.resizeCanvas.bind(this));\r\n this._viewport.forEach((view) => {\r\n this._bindingEventService.bind(view, 'scroll', this.handleScroll.bind(this));\r\n });\r\n\r\n if (this._options.enableMouseWheelScrollHandler) {\r\n this._viewport.forEach((view) => {\r\n this.slickMouseWheelInstances.push(MouseWheel({\r\n element: view,\r\n onMouseWheel: this.handleMouseWheel.bind(this)\r\n }));\r\n });\r\n }\r\n\r\n this._headerScroller.forEach((el) => {\r\n this._bindingEventService.bind(el, 'contextmenu', this.handleHeaderContextMenu.bind(this) as EventListener);\r\n this._bindingEventService.bind(el, 'click', this.handleHeaderClick.bind(this) as EventListener);\r\n });\r\n\r\n this._headerRowScroller.forEach((scroller) => {\r\n this._bindingEventService.bind(scroller, 'scroll', this.handleHeaderRowScroll.bind(this) as EventListener);\r\n });\r\n\r\n if (this._options.createFooterRow) {\r\n this._footerRow.forEach((footer) => {\r\n this._bindingEventService.bind(footer, 'contextmenu', this.handleFooterContextMenu.bind(this) as EventListener);\r\n this._bindingEventService.bind(footer, 'click', this.handleFooterClick.bind(this) as EventListener);\r\n });\r\n\r\n this._footerRowScroller.forEach((scroller) => {\r\n this._bindingEventService.bind(scroller, 'scroll', this.handleFooterRowScroll.bind(this) as EventListener);\r\n });\r\n }\r\n\r\n if (this._options.createTopHeaderPanel) {\r\n this._bindingEventService.bind(this._topHeaderPanelScroller, 'scroll', this.handleTopHeaderPanelScroll.bind(this) as EventListener);\r\n }\r\n\r\n if (this._options.createPreHeaderPanel) {\r\n this._bindingEventService.bind(this._preHeaderPanelScroller, 'scroll', this.handlePreHeaderPanelScroll.bind(this) as EventListener);\r\n this._bindingEventService.bind(this._preHeaderPanelScroller, 'contextmenu', this.handlePreHeaderContextMenu.bind(this) as EventListener);\r\n this._bindingEventService.bind(this._preHeaderPanelScrollerR, 'contextmenu', this.handlePreHeaderContextMenu.bind(this) as EventListener);\r\n this._bindingEventService.bind(this._preHeaderPanelScroller, 'click', this.handlePreHeaderClick.bind(this) as EventListener);\r\n this._bindingEventService.bind(this._preHeaderPanelScrollerR, 'click', this.handlePreHeaderClick.bind(this) as EventListener);\r\n }\r\n\r\n this._bindingEventService.bind(this._focusSink, 'keydown', this.handleKeyDown.bind(this) as EventListener);\r\n this._bindingEventService.bind(this._focusSink2, 'keydown', this.handleKeyDown.bind(this) as EventListener);\r\n\r\n this._canvas.forEach((element) => {\r\n this._bindingEventService.bind(element, 'keydown', this.handleKeyDown.bind(this) as EventListener);\r\n this._bindingEventService.bind(element, 'click', this.handleClick.bind(this) as EventListener);\r\n this._bindingEventService.bind(element, 'dblclick', this.handleDblClick.bind(this) as EventListener);\r\n this._bindingEventService.bind(element, 'contextmenu', this.handleContextMenu.bind(this) as EventListener);\r\n this._bindingEventService.bind(element, 'mouseover', this.handleCellMouseOver.bind(this) as EventListener);\r\n this._bindingEventService.bind(element, 'mouseout', this.handleCellMouseOut.bind(this) as EventListener);\r\n });\r\n\r\n if (Draggable) {\r\n this.slickDraggableInstance = Draggable({\r\n containerElement: this._container,\r\n allowDragFrom: 'div.slick-cell',\r\n // the slick cell parent must always contain `.dnd` and/or `.cell-reorder` class to be identified as draggable\r\n allowDragFromClosest: 'div.slick-cell.dnd, div.slick-cell.cell-reorder',\r\n preventDragFromKeys: this._options.preventDragFromKeys,\r\n onDragInit: this.handleDragInit.bind(this),\r\n onDragStart: this.handleDragStart.bind(this),\r\n onDrag: this.handleDrag.bind(this),\r\n onDragEnd: this.handleDragEnd.bind(this)\r\n });\r\n }\r\n\r\n if (!this._options.suppressCssChangesOnHiddenInit) {\r\n this.restoreCssFromHiddenInit();\r\n }\r\n }\r\n }\r\n\r\n /** handles \"display:none\" on container or container parents, related to issue: https://github.com/6pac/SlickGrid/issues/568 */\r\n cacheCssForHiddenInit() {\r\n this._hiddenParents = Utils.parents(this._container, ':hidden') as HTMLElement[];\r\n this.oldProps = [];\r\n this._hiddenParents.forEach(el => {\r\n const old: Partial = {};\r\n Object.keys(this.cssShow).forEach(name => {\r\n if (this.cssShow) {\r\n old[name as any] = el.style[name as 'position' | 'visibility' | 'display'];\r\n el.style[name as any] = this.cssShow[name as 'position' | 'visibility' | 'display'];\r\n }\r\n });\r\n this.oldProps.push(old);\r\n });\r\n }\r\n\r\n restoreCssFromHiddenInit() {\r\n // finish handle display:none on container or container parents\r\n // - put values back the way they were\r\n let i = 0;\r\n if (this._hiddenParents) {\r\n this._hiddenParents.forEach(el => {\r\n const old = this.oldProps[i++];\r\n Object.keys(this.cssShow).forEach(name => {\r\n if (this.cssShow) {\r\n el.style[name as CSSStyleDeclarationWritable] = (old as any)[name];\r\n }\r\n });\r\n });\r\n this._hiddenParents = [];\r\n }\r\n }\r\n\r\n protected hasFrozenColumns() {\r\n return this._options.frozenColumn! > -1;\r\n }\r\n\r\n /** Register an external Plugin */\r\n registerPlugin(plugin: T) {\r\n this.plugins.unshift(plugin);\r\n plugin.init(this as unknown as SlickGridModel);\r\n }\r\n\r\n /** Unregister (destroy) an external Plugin */\r\n unregisterPlugin(plugin: SlickPlugin) {\r\n for (let i = this.plugins.length; i >= 0; i--) {\r\n if (this.plugins[i] === plugin) {\r\n this.plugins[i]?.destroy();\r\n this.plugins.splice(i, 1);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n /** Get a Plugin (addon) by its name */\r\n getPluginByName

(name: string) {\r\n for (let i = this.plugins.length - 1; i >= 0; i--) {\r\n if (this.plugins[i]?.pluginName === name) {\r\n return this.plugins[i] as P;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Unregisters a current selection model and registers a new one. See the definition of SelectionModel for more information.\r\n * @param {Object} selectionModel A SelectionModel.\r\n */\r\n setSelectionModel(model: SelectionModel) {\r\n if (this.selectionModel) {\r\n this.selectionModel.onSelectedRangesChanged.unsubscribe(this.handleSelectedRangesChanged.bind(this));\r\n if (this.selectionModel.destroy) {\r\n this.selectionModel.destroy();\r\n }\r\n }\r\n\r\n this.selectionModel = model;\r\n if (this.selectionModel) {\r\n this.selectionModel.init(this as unknown as SlickGridModel);\r\n this.selectionModel.onSelectedRangesChanged.subscribe(this.handleSelectedRangesChanged.bind(this));\r\n }\r\n }\r\n\r\n /** Returns the current SelectionModel. See here for more information about SelectionModels. */\r\n getSelectionModel() {\r\n return this.selectionModel;\r\n }\r\n\r\n /** Get Grid Canvas Node DOM Element */\r\n getCanvasNode(columnIdOrIdx?: number | string, rowIndex?: number) {\r\n return this._getContainerElement(this.getCanvases(), columnIdOrIdx, rowIndex) as HTMLDivElement;\r\n }\r\n\r\n /** Get the canvas DOM element */\r\n getActiveCanvasNode(e?: Event | SlickEventData_) {\r\n if (e === undefined) {\r\n return this._activeCanvasNode;\r\n }\r\n\r\n if (e instanceof SlickEventData) {\r\n e = e.getNativeEvent();\r\n }\r\n\r\n this._activeCanvasNode = (e as any)?.target.closest('.grid-canvas');\r\n return this._activeCanvasNode;\r\n }\r\n\r\n /** Get the canvas DOM element */\r\n getCanvases() {\r\n return this._canvas;\r\n }\r\n\r\n /** Get the Viewport DOM node element */\r\n getViewportNode(columnIdOrIdx?: number | string, rowIndex?: number) {\r\n return this._getContainerElement(this.getViewports(), columnIdOrIdx, rowIndex);\r\n }\r\n\r\n /** Get all the Viewport node elements */\r\n getViewports() {\r\n return this._viewport;\r\n }\r\n\r\n getActiveViewportNode(e: Event | SlickEventData_) {\r\n this.setActiveViewportNode(e);\r\n\r\n return this._activeViewportNode;\r\n }\r\n\r\n /** Sets an active viewport node */\r\n setActiveViewportNode(e: Event | SlickEventData_) {\r\n if (e instanceof SlickEventData) {\r\n e = e.getNativeEvent();\r\n }\r\n this._activeViewportNode = (e as any)?.target.closest('.slick-viewport');\r\n return this._activeViewportNode;\r\n }\r\n\r\n protected _getContainerElement(targetContainers: HTMLElement[], columnIdOrIdx?: number | string, rowIndex?: number) {\r\n if (!targetContainers) { return; }\r\n if (!columnIdOrIdx) { columnIdOrIdx = 0; }\r\n if (!rowIndex) { rowIndex = 0; }\r\n\r\n const idx = (typeof columnIdOrIdx === 'number' ? columnIdOrIdx : this.getColumnIndex(columnIdOrIdx));\r\n\r\n const isBottomSide = this.hasFrozenRows && rowIndex >= this.actualFrozenRow + (this._options.frozenBottom ? 0 : 1);\r\n const isRightSide = this.hasFrozenColumns() && idx > this._options.frozenColumn!;\r\n\r\n return targetContainers[(isBottomSide ? 2 : 0) + (isRightSide ? 1 : 0)];\r\n }\r\n\r\n protected measureScrollbar() {\r\n let className = '';\r\n this._viewport.forEach(v => className += v.className);\r\n const outerdiv = Utils.createDomElement('div', { className, style: { position: 'absolute', top: '-10000px', left: '-10000px', overflow: 'auto', width: '100px', height: '100px' } }, document.body);\r\n const innerdiv = Utils.createDomElement('div', { style: { width: '200px', height: '200px', overflow: 'auto' } }, outerdiv);\r\n const dim = {\r\n width: outerdiv.offsetWidth - outerdiv.clientWidth,\r\n height: outerdiv.offsetHeight - outerdiv.clientHeight\r\n };\r\n innerdiv.remove();\r\n outerdiv.remove();\r\n return dim;\r\n }\r\n\r\n /** Get the headers width in pixel */\r\n getHeadersWidth() {\r\n this.headersWidth = this.headersWidthL = this.headersWidthR = 0;\r\n const includeScrollbar = !this._options.autoHeight;\r\n\r\n let i = 0;\r\n const ii = this.columns.length;\r\n for (i = 0; i < ii; i++) {\r\n if (!this.columns[i] || this.columns[i].hidden) { continue; }\r\n\r\n const width = this.columns[i].width;\r\n\r\n if ((this._options.frozenColumn!) > -1 && (i > this._options.frozenColumn!)) {\r\n this.headersWidthR += width || 0;\r\n } else {\r\n this.headersWidthL += width || 0;\r\n }\r\n }\r\n\r\n if (includeScrollbar) {\r\n if ((this._options.frozenColumn!) > -1 && (i > this._options.frozenColumn!)) {\r\n this.headersWidthR += this.scrollbarDimensions?.width ?? 0;\r\n } else {\r\n this.headersWidthL += this.scrollbarDimensions?.width ?? 0;\r\n }\r\n }\r\n\r\n if (this.hasFrozenColumns()) {\r\n this.headersWidthL = this.headersWidthL + 1000;\r\n\r\n this.headersWidthR = Math.max(this.headersWidthR, this.viewportW) + this.headersWidthL;\r\n this.headersWidthR += this.scrollbarDimensions?.width ?? 0;\r\n } else {\r\n this.headersWidthL += this.scrollbarDimensions?.width ?? 0;\r\n this.headersWidthL = Math.max(this.headersWidthL, this.viewportW) + 1000;\r\n }\r\n\r\n this.headersWidth = this.headersWidthL + this.headersWidthR;\r\n return Math.max(this.headersWidth, this.viewportW) + 1000;\r\n }\r\n\r\n /** Get the grid canvas width */\r\n getCanvasWidth(): number {\r\n const availableWidth = this.viewportHasVScroll ? this.viewportW - (this.scrollbarDimensions?.width ?? 0) : this.viewportW;\r\n let i = this.columns.length;\r\n\r\n this.canvasWidthL = this.canvasWidthR = 0;\r\n\r\n while (i--) {\r\n if (!this.columns[i] || this.columns[i].hidden) { continue; }\r\n\r\n if (this.hasFrozenColumns() && (i > this._options.frozenColumn!)) {\r\n this.canvasWidthR += this.columns[i].width || 0;\r\n } else {\r\n this.canvasWidthL += this.columns[i].width || 0;\r\n }\r\n }\r\n let totalRowWidth = this.canvasWidthL + this.canvasWidthR;\r\n if (this._options.fullWidthRows) {\r\n const extraWidth = Math.max(totalRowWidth, availableWidth) - totalRowWidth;\r\n if (extraWidth > 0) {\r\n totalRowWidth += extraWidth;\r\n if (this.hasFrozenColumns()) {\r\n this.canvasWidthR += extraWidth;\r\n } else {\r\n this.canvasWidthL += extraWidth;\r\n }\r\n }\r\n }\r\n return totalRowWidth;\r\n }\r\n\r\n protected updateCanvasWidth(forceColumnWidthsUpdate?: boolean) {\r\n const oldCanvasWidth = this.canvasWidth;\r\n const oldCanvasWidthL = this.canvasWidthL;\r\n const oldCanvasWidthR = this.canvasWidthR;\r\n this.canvasWidth = this.getCanvasWidth();\r\n\r\n if (this._options.createTopHeaderPanel) {\r\n Utils.width(this._topHeaderPanel, this._options.topHeaderPanelWidth ?? this.canvasWidth);\r\n }\r\n\r\n const widthChanged = this.canvasWidth !== oldCanvasWidth || this.canvasWidthL !== oldCanvasWidthL || this.canvasWidthR !== oldCanvasWidthR;\r\n\r\n if (widthChanged || this.hasFrozenColumns() || this.hasFrozenRows) {\r\n Utils.width(this._canvasTopL, this.canvasWidthL);\r\n\r\n this.getHeadersWidth();\r\n\r\n Utils.width(this._headerL, this.headersWidthL);\r\n Utils.width(this._headerR, this.headersWidthR);\r\n\r\n if (this.hasFrozenColumns()) {\r\n const cWidth = Utils.width(this._container) || 0;\r\n if (cWidth > 0 && this.canvasWidthL > cWidth && this._options.throwWhenFrozenNotAllViewable) {\r\n throw new Error('[SlickGrid] Frozen columns cannot be wider than the actual grid container width. '\r\n + 'Make sure to have less columns freezed or make your grid container wider');\r\n }\r\n Utils.width(this._canvasTopR, this.canvasWidthR);\r\n\r\n Utils.width(this._paneHeaderL, this.canvasWidthL);\r\n Utils.setStyleSize(this._paneHeaderR, 'left', this.canvasWidthL);\r\n Utils.setStyleSize(this._paneHeaderR, 'width', this.viewportW - this.canvasWidthL);\r\n\r\n Utils.width(this._paneTopL, this.canvasWidthL);\r\n Utils.setStyleSize(this._paneTopR, 'left', this.canvasWidthL);\r\n Utils.width(this._paneTopR, this.viewportW - this.canvasWidthL);\r\n\r\n Utils.width(this._headerRowScrollerL, this.canvasWidthL);\r\n Utils.width(this._headerRowScrollerR, this.viewportW - this.canvasWidthL);\r\n\r\n Utils.width(this._headerRowL, this.canvasWidthL);\r\n Utils.width(this._headerRowR, this.canvasWidthR);\r\n\r\n if (this._options.createFooterRow) {\r\n Utils.width(this._footerRowScrollerL, this.canvasWidthL);\r\n Utils.width(this._footerRowScrollerR, this.viewportW - this.canvasWidthL);\r\n\r\n Utils.width(this._footerRowL, this.canvasWidthL);\r\n Utils.width(this._footerRowR, this.canvasWidthR);\r\n }\r\n if (this._options.createPreHeaderPanel) {\r\n Utils.width(this._preHeaderPanel, this._options.preHeaderPanelWidth ?? this.canvasWidth);\r\n }\r\n Utils.width(this._viewportTopL, this.canvasWidthL);\r\n Utils.width(this._viewportTopR, this.viewportW - this.canvasWidthL);\r\n\r\n if (this.hasFrozenRows) {\r\n Utils.width(this._paneBottomL, this.canvasWidthL);\r\n Utils.setStyleSize(this._paneBottomR, 'left', this.canvasWidthL);\r\n\r\n Utils.width(this._viewportBottomL, this.canvasWidthL);\r\n Utils.width(this._viewportBottomR, this.viewportW - this.canvasWidthL);\r\n\r\n Utils.width(this._canvasBottomL, this.canvasWidthL);\r\n Utils.width(this._canvasBottomR, this.canvasWidthR);\r\n }\r\n } else {\r\n Utils.width(this._paneHeaderL, '100%');\r\n Utils.width(this._paneTopL, '100%');\r\n Utils.width(this._headerRowScrollerL, '100%');\r\n Utils.width(this._headerRowL, this.canvasWidth);\r\n\r\n if (this._options.createFooterRow) {\r\n Utils.width(this._footerRowScrollerL, '100%');\r\n Utils.width(this._footerRowL, this.canvasWidth);\r\n }\r\n\r\n if (this._options.createPreHeaderPanel) {\r\n Utils.width(this._preHeaderPanel, this._options.preHeaderPanelWidth ?? this.canvasWidth);\r\n }\r\n Utils.width(this._viewportTopL, '100%');\r\n\r\n if (this.hasFrozenRows) {\r\n Utils.width(this._viewportBottomL, '100%');\r\n Utils.width(this._canvasBottomL, this.canvasWidthL);\r\n }\r\n }\r\n }\r\n\r\n this.viewportHasHScroll = (this.canvasWidth >= this.viewportW - (this.scrollbarDimensions?.width ?? 0));\r\n\r\n Utils.width(this._headerRowSpacerL, this.canvasWidth + (this.viewportHasVScroll ? (this.scrollbarDimensions?.width ?? 0) : 0));\r\n Utils.width(this._headerRowSpacerR, this.canvasWidth + (this.viewportHasVScroll ? (this.scrollbarDimensions?.width ?? 0) : 0));\r\n\r\n if (this._options.createFooterRow) {\r\n Utils.width(this._footerRowSpacerL, this.canvasWidth + (this.viewportHasVScroll ? (this.scrollbarDimensions?.width ?? 0) : 0));\r\n Utils.width(this._footerRowSpacerR, this.canvasWidth + (this.viewportHasVScroll ? (this.scrollbarDimensions?.width ?? 0) : 0));\r\n }\r\n\r\n if (widthChanged || forceColumnWidthsUpdate) {\r\n this.applyColumnWidths();\r\n }\r\n }\r\n\r\n protected disableSelection(target: HTMLElement[]) {\r\n target.forEach((el) => {\r\n el.setAttribute('unselectable', 'on');\r\n (el.style as any).mozUserSelect = 'none';\r\n this._bindingEventService.bind(el, 'selectstart', () => false);\r\n });\r\n }\r\n\r\n protected getMaxSupportedCssHeight() {\r\n let supportedHeight = 1000000;\r\n // FF reports the height back but still renders blank after ~6M px\r\n // let testUpTo = navigator.userAgent.toLowerCase().match(/firefox/) ? 6000000 : 1000000000;\r\n const testUpTo = navigator.userAgent.toLowerCase().match(/firefox/) ? this._options.ffMaxSupportedCssHeight : this._options.maxSupportedCssHeight;\r\n const div = Utils.createDomElement('div', { style: { display: 'hidden' } }, document.body);\r\n\r\n while (true) {\r\n const test = supportedHeight * 2;\r\n Utils.height(div, test);\r\n const height = Utils.height(div);\r\n\r\n if (test > testUpTo! || height !== test) {\r\n break;\r\n } else {\r\n supportedHeight = test;\r\n }\r\n }\r\n\r\n div.remove();\r\n return supportedHeight;\r\n }\r\n\r\n /** Get grid unique identifier */\r\n getUID() {\r\n return this.uid;\r\n }\r\n\r\n /** Get Header Column Width Difference in pixel */\r\n getHeaderColumnWidthDiff() {\r\n return this.headerColumnWidthDiff;\r\n }\r\n\r\n /** Get scrollbar dimensions */\r\n getScrollbarDimensions() {\r\n return this.scrollbarDimensions;\r\n }\r\n\r\n /** Get the displayed scrollbar dimensions */\r\n getDisplayedScrollbarDimensions() {\r\n return {\r\n width: this.viewportHasVScroll ? (this.scrollbarDimensions?.width ?? 0) : 0,\r\n height: this.viewportHasHScroll ? (this.scrollbarDimensions?.height ?? 0) : 0\r\n };\r\n }\r\n\r\n /** Get the absolute column minimum width */\r\n getAbsoluteColumnMinWidth(): number {\r\n return this.absoluteColumnMinWidth;\r\n }\r\n\r\n getPubSubService(): BasePubSub | undefined {\r\n return this._pubSubService;\r\n }\r\n\r\n // TODO: this is static. need to handle page mutation.\r\n protected bindAncestorScrollEvents() {\r\n let elem: HTMLElement | null = (this.hasFrozenRows && !this._options.frozenBottom) ? this._canvasBottomL : this._canvasTopL;\r\n while ((elem = elem!.parentNode as HTMLElement) !== document.body && elem) {\r\n // bind to scroll containers only\r\n if (elem === this._viewportTopL || elem.scrollWidth !== elem.clientWidth || elem.scrollHeight !== elem.clientHeight) {\r\n this._boundAncestors.push(elem);\r\n this._bindingEventService.bind(elem, 'scroll', this.handleActiveCellPositionChange.bind(this));\r\n }\r\n }\r\n }\r\n\r\n protected unbindAncestorScrollEvents() {\r\n this._boundAncestors.forEach((ancestor) => {\r\n this._bindingEventService.unbindByEventName(ancestor, 'scroll');\r\n });\r\n this._boundAncestors = [];\r\n }\r\n\r\n /**\r\n * Updates an existing column definition and a corresponding header DOM element with the new title and tooltip.\r\n * @param {Number|String} columnId Column id.\r\n * @param {string | HTMLElement | DocumentFragment} [title] New column name.\r\n * @param {String} [toolTip] New column tooltip.\r\n */\r\n updateColumnHeader(columnId: number | string, title?: string | HTMLElement | DocumentFragment, toolTip?: string) {\r\n if (this.initialized) {\r\n const idx = this.getColumnIndex(columnId);\r\n if (!Utils.isDefined(idx)) {\r\n return;\r\n }\r\n\r\n const columnDef = this.columns[idx];\r\n const header: HTMLElement | undefined = this.getColumnByIndex(idx);\r\n if (header) {\r\n if (title !== undefined) {\r\n this.columns[idx].name = title;\r\n }\r\n if (toolTip !== undefined) {\r\n this.columns[idx].toolTip = toolTip;\r\n }\r\n\r\n this.trigger(this.onBeforeHeaderCellDestroy, {\r\n node: header,\r\n column: columnDef,\r\n grid: this\r\n });\r\n\r\n header.setAttribute('title', toolTip || '');\r\n if (title !== undefined) {\r\n this.applyHtmlCode(header.children[0] as HTMLElement, title);\r\n }\r\n\r\n this.trigger(this.onHeaderCellRendered, {\r\n node: header,\r\n column: columnDef,\r\n grid: this\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the Header DOM element\r\n * @param {C} columnDef - column definition\r\n */\r\n getHeader(columnDef: C) {\r\n if (!columnDef) {\r\n return this.hasFrozenColumns() ? this._headers : this._headerL;\r\n }\r\n const idx = this.getColumnIndex(columnDef.id);\r\n return this.hasFrozenColumns() ? ((idx <= this._options.frozenColumn!) ? this._headerL : this._headerR) : this._headerL;\r\n }\r\n\r\n /**\r\n * Get a specific Header Column DOM element by its column Id or index\r\n * @param {Number|String} columnIdOrIdx - column Id or index\r\n */\r\n getHeaderColumn(columnIdOrIdx: number | string) {\r\n const idx = (typeof columnIdOrIdx === 'number' ? columnIdOrIdx : this.getColumnIndex(columnIdOrIdx));\r\n const targetHeader = this.hasFrozenColumns() ? ((idx <= this._options.frozenColumn!) ? this._headerL : this._headerR) : this._headerL;\r\n const targetIndex = this.hasFrozenColumns() ? ((idx <= this._options.frozenColumn!) ? idx : idx - this._options.frozenColumn! - 1) : idx;\r\n\r\n return targetHeader.children[targetIndex] as HTMLDivElement;\r\n }\r\n\r\n /** Get the Header Row DOM element */\r\n getHeaderRow() {\r\n return this.hasFrozenColumns() ? this._headerRows : this._headerRows[0];\r\n }\r\n\r\n /** Get the Footer DOM element */\r\n getFooterRow() {\r\n return this.hasFrozenColumns() ? this._footerRow : this._footerRow[0];\r\n }\r\n\r\n /** @alias `getPreHeaderPanelLeft` */\r\n getPreHeaderPanel() {\r\n return this._preHeaderPanel;\r\n }\r\n\r\n /** Get the Pre-Header Panel Left DOM node element */\r\n getPreHeaderPanelLeft() {\r\n return this._preHeaderPanel;\r\n }\r\n\r\n /** Get the Pre-Header Panel Right DOM node element */\r\n getPreHeaderPanelRight() {\r\n return this._preHeaderPanelR;\r\n }\r\n\r\n /** Get the Top-Header Panel DOM node element */\r\n getTopHeaderPanel() {\r\n return this._topHeaderPanel;\r\n }\r\n\r\n /**\r\n * Get Header Row Column DOM element by its column Id or index\r\n * @param {Number|String} columnIdOrIdx - column Id or index\r\n */\r\n getHeaderRowColumn(columnIdOrIdx: number | string) {\r\n let idx = (typeof columnIdOrIdx === 'number' ? columnIdOrIdx : this.getColumnIndex(columnIdOrIdx));\r\n let headerRowTarget: HTMLDivElement;\r\n\r\n if (this.hasFrozenColumns()) {\r\n if (idx <= this._options.frozenColumn!) {\r\n headerRowTarget = this._headerRowL;\r\n } else {\r\n headerRowTarget = this._headerRowR;\r\n idx -= this._options.frozenColumn! + 1;\r\n }\r\n } else {\r\n headerRowTarget = this._headerRowL;\r\n }\r\n\r\n return headerRowTarget.children[idx] as HTMLDivElement;\r\n }\r\n\r\n /**\r\n * Get the Footer Row Column DOM element by its column Id or index\r\n * @param {Number|String} columnIdOrIdx - column Id or index\r\n */\r\n getFooterRowColumn(columnIdOrIdx: number | string) {\r\n let idx = (typeof columnIdOrIdx === 'number' ? columnIdOrIdx : this.getColumnIndex(columnIdOrIdx));\r\n let footerRowTarget: HTMLDivElement;\r\n\r\n if (this.hasFrozenColumns()) {\r\n if (idx <= this._options.frozenColumn!) {\r\n footerRowTarget = this._footerRowL;\r\n } else {\r\n footerRowTarget = this._footerRowR;\r\n\r\n idx -= this._options.frozenColumn! + 1;\r\n }\r\n } else {\r\n footerRowTarget = this._footerRowL;\r\n }\r\n\r\n return footerRowTarget.children[idx] as HTMLDivElement;\r\n }\r\n\r\n protected createColumnFooter() {\r\n if (this._options.createFooterRow) {\r\n this._footerRow.forEach((footer) => {\r\n const columnElements = footer.querySelectorAll('.slick-footerrow-column');\r\n columnElements.forEach((column) => {\r\n const columnDef = Utils.storage.get(column, 'column');\r\n this.trigger(this.onBeforeFooterRowCellDestroy, {\r\n node: column,\r\n column: columnDef,\r\n grid: this\r\n });\r\n });\r\n });\r\n\r\n Utils.emptyElement(this._footerRowL);\r\n Utils.emptyElement(this._footerRowR);\r\n\r\n for (let i = 0; i < this.columns.length; i++) {\r\n const m = this.columns[i];\r\n if (!m || m.hidden) { continue; }\r\n\r\n const footerRowCell = Utils.createDomElement('div', { className: `ui-state-default slick-state-default slick-footerrow-column l${i} r${i}` }, this.hasFrozenColumns() && (i > this._options.frozenColumn!) ? this._footerRowR : this._footerRowL);\r\n const className = this.hasFrozenColumns() && i <= this._options.frozenColumn! ? 'frozen' : null;\r\n if (className) {\r\n footerRowCell.classList.add(className);\r\n }\r\n\r\n Utils.storage.put(footerRowCell, 'column', m);\r\n\r\n this.trigger(this.onFooterRowCellRendered, {\r\n node: footerRowCell,\r\n column: m,\r\n grid: this\r\n });\r\n }\r\n }\r\n }\r\n\r\n protected handleHeaderMouseHoverOn(e: Event | SlickEventData_) {\r\n (e as any)?.target.classList.add('ui-state-hover', 'slick-state-hover');\r\n }\r\n\r\n protected handleHeaderMouseHoverOff(e: Event | SlickEventData_) {\r\n (e as any)?.target.classList.remove('ui-state-hover', 'slick-state-hover');\r\n }\r\n\r\n protected createColumnHeaders() {\r\n this._headers.forEach((header) => {\r\n const columnElements = header.querySelectorAll('.slick-header-column');\r\n columnElements.forEach((column) => {\r\n const columnDef = Utils.storage.get(column, 'column');\r\n if (columnDef) {\r\n this.trigger(this.onBeforeHeaderCellDestroy, {\r\n node: column,\r\n column: columnDef,\r\n grid: this\r\n });\r\n }\r\n });\r\n });\r\n\r\n Utils.emptyElement(this._headerL);\r\n Utils.emptyElement(this._headerR);\r\n\r\n this.getHeadersWidth();\r\n\r\n Utils.width(this._headerL, this.headersWidthL);\r\n Utils.width(this._headerR, this.headersWidthR);\r\n\r\n this._headerRows.forEach((row) => {\r\n const columnElements = row.querySelectorAll('.slick-headerrow-column');\r\n columnElements.forEach((column) => {\r\n const columnDef = Utils.storage.get(column, 'column');\r\n if (columnDef) {\r\n this.trigger(this.onBeforeHeaderRowCellDestroy, {\r\n node: this,\r\n column: columnDef,\r\n grid: this\r\n });\r\n }\r\n });\r\n });\r\n\r\n Utils.emptyElement(this._headerRowL);\r\n Utils.emptyElement(this._headerRowR);\r\n\r\n if (this._options.createFooterRow) {\r\n const footerRowLColumnElements = this._footerRowL.querySelectorAll('.slick-footerrow-column');\r\n footerRowLColumnElements.forEach((column) => {\r\n const columnDef = Utils.storage.get(column, 'column');\r\n if (columnDef) {\r\n this.trigger(this.onBeforeFooterRowCellDestroy, {\r\n node: this,\r\n column: columnDef,\r\n grid: this\r\n });\r\n }\r\n });\r\n Utils.emptyElement(this._footerRowL);\r\n\r\n if (this.hasFrozenColumns()) {\r\n const footerRowRColumnElements = this._footerRowR.querySelectorAll('.slick-footerrow-column');\r\n footerRowRColumnElements.forEach((column) => {\r\n const columnDef = Utils.storage.get(column, 'column');\r\n if (columnDef) {\r\n this.trigger(this.onBeforeFooterRowCellDestroy, {\r\n node: this,\r\n column: columnDef,\r\n grid: this\r\n });\r\n }\r\n });\r\n Utils.emptyElement(this._footerRowR);\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.columns.length; i++) {\r\n const m: C = this.columns[i];\r\n if (m.hidden) { continue; }\r\n\r\n const headerTarget = this.hasFrozenColumns() ? ((i <= this._options.frozenColumn!) ? this._headerL : this._headerR) : this._headerL;\r\n const headerRowTarget = this.hasFrozenColumns() ? ((i <= this._options.frozenColumn!) ? this._headerRowL : this._headerRowR) : this._headerRowL;\r\n\r\n const header = Utils.createDomElement('div', { id: `${this.uid + m.id}`, dataset: { id: String(m.id) }, role: 'columnheader', className: 'ui-state-default slick-state-default slick-header-column' }, headerTarget);\r\n if (m.toolTip) {\r\n header.title = m.toolTip;\r\n }\r\n if (!m.reorderable) {\r\n header.classList.add(this._options.unorderableColumnCssClass!);\r\n }\r\n const colNameElm = Utils.createDomElement('span', { className: 'slick-column-name' }, header);\r\n this.applyHtmlCode(colNameElm, m.name as string);\r\n\r\n Utils.width(header, m.width! - this.headerColumnWidthDiff);\r\n\r\n let classname = m.headerCssClass || null;\r\n if (classname) {\r\n header.classList.add(...Utils.classNameToList(classname));\r\n }\r\n classname = this.hasFrozenColumns() && i <= this._options.frozenColumn! ? 'frozen' : null;\r\n if (classname) {\r\n header.classList.add(classname);\r\n }\r\n\r\n this._bindingEventService.bind(header, 'mouseenter', this.handleHeaderMouseEnter.bind(this) as EventListener);\r\n this._bindingEventService.bind(header, 'mouseleave', this.handleHeaderMouseLeave.bind(this) as EventListener);\r\n\r\n Utils.storage.put(header, 'column', m);\r\n\r\n if (this._options.enableColumnReorder || m.sortable) {\r\n this._bindingEventService.bind(header, 'mouseenter', this.handleHeaderMouseHoverOn.bind(this) as EventListener);\r\n this._bindingEventService.bind(header, 'mouseleave', this.handleHeaderMouseHoverOff.bind(this) as EventListener);\r\n }\r\n\r\n if (m.hasOwnProperty('headerCellAttrs') && m.headerCellAttrs instanceof Object) {\r\n Object.keys(m.headerCellAttrs).forEach(key => {\r\n if (m.headerCellAttrs.hasOwnProperty(key)) {\r\n header.setAttribute(key, m.headerCellAttrs[key]);\r\n }\r\n });\r\n }\r\n\r\n if (m.sortable) {\r\n header.classList.add('slick-header-sortable');\r\n Utils.createDomElement('div', { className: `slick-sort-indicator ${this._options.numberedMultiColumnSort && !this._options.sortColNumberInSeparateSpan ? ' slick-sort-indicator-numbered' : ''}` }, header);\r\n if (this._options.numberedMultiColumnSort && this._options.sortColNumberInSeparateSpan) {\r\n Utils.createDomElement('div', { className: 'slick-sort-indicator-numbered' }, header);\r\n }\r\n }\r\n\r\n this.trigger(this.onHeaderCellRendered, {\r\n node: header,\r\n column: m,\r\n grid: this\r\n });\r\n\r\n if (this._options.showHeaderRow) {\r\n const headerRowCell = Utils.createDomElement('div', { className: `ui-state-default slick-state-default slick-headerrow-column l${i} r${i}` }, headerRowTarget);\r\n const frozenClasses = this.hasFrozenColumns() && i <= this._options.frozenColumn! ? 'frozen' : null;\r\n if (frozenClasses) {\r\n headerRowCell.classList.add(frozenClasses);\r\n }\r\n\r\n this._bindingEventService.bind(headerRowCell, 'mouseenter', this.handleHeaderRowMouseEnter.bind(this) as EventListener);\r\n this._bindingEventService.bind(headerRowCell, 'mouseleave', this.handleHeaderRowMouseLeave.bind(this) as EventListener);\r\n\r\n Utils.storage.put(headerRowCell, 'column', m);\r\n\r\n this.trigger(this.onHeaderRowCellRendered, {\r\n node: headerRowCell,\r\n column: m,\r\n grid: this\r\n });\r\n }\r\n if (this._options.createFooterRow && this._options.showFooterRow) {\r\n const footerRowTarget = this.hasFrozenColumns() ? ((i <= this._options.frozenColumn!) ? this._footerRow[0] : this._footerRow[1]) : this._footerRow[0];\r\n const footerRowCell = Utils.createDomElement('div', { className: `ui-state-default slick-state-default slick-footerrow-column l${i} r${i}` }, footerRowTarget);\r\n Utils.storage.put(footerRowCell, 'column', m);\r\n\r\n this.trigger(this.onFooterRowCellRendered, {\r\n node: footerRowCell,\r\n column: m,\r\n grid: this\r\n });\r\n }\r\n }\r\n\r\n this.setSortColumns(this.sortColumns);\r\n this.setupColumnResize();\r\n if (this._options.enableColumnReorder) {\r\n if (typeof this._options.enableColumnReorder === 'function') {\r\n this._options.enableColumnReorder(this as unknown as SlickGridModel, this._headers, this.headerColumnWidthDiff, this.setColumns as any, this.setupColumnResize, this.columns, this.getColumnIndex, this.uid, this.trigger);\r\n } else {\r\n this.setupColumnReorder();\r\n }\r\n }\r\n }\r\n\r\n protected setupColumnSort() {\r\n this._headers.forEach((header) => {\r\n this._bindingEventService.bind(header, 'click', (e: any) => {\r\n if (this.columnResizeDragging) {\r\n return;\r\n }\r\n\r\n if (e.target.classList.contains('slick-resizable-handle')) {\r\n return;\r\n }\r\n\r\n const coll = e.target.closest('.slick-header-column');\r\n if (!coll) {\r\n return;\r\n }\r\n\r\n const column = Utils.storage.get(coll, 'column');\r\n if (column.sortable) {\r\n if (!this.getEditorLock()?.commitCurrentEdit()) {\r\n return;\r\n }\r\n\r\n const previousSortColumns = this.sortColumns.slice();\r\n let sortColumn: ColumnSort | null = null;\r\n let i = 0;\r\n for (; i < this.sortColumns.length; i++) {\r\n if (this.sortColumns[i].columnId === column.id) {\r\n sortColumn = this.sortColumns[i];\r\n sortColumn.sortAsc = !sortColumn.sortAsc;\r\n break;\r\n }\r\n }\r\n const hadSortCol = !!sortColumn;\r\n\r\n if (this._options.tristateMultiColumnSort) {\r\n if (!sortColumn) {\r\n sortColumn = { columnId: column.id, sortAsc: column.defaultSortAsc, sortCol: column };\r\n }\r\n if (hadSortCol && sortColumn.sortAsc) {\r\n // three state: remove sort rather than go back to ASC\r\n this.sortColumns.splice(i, 1);\r\n sortColumn = null;\r\n }\r\n if (!this._options.multiColumnSort) {\r\n this.sortColumns = [];\r\n }\r\n if (sortColumn && (!hadSortCol || !this._options.multiColumnSort)) {\r\n this.sortColumns.push(sortColumn);\r\n }\r\n } else {\r\n // legacy behaviour\r\n if (e.metaKey && this._options.multiColumnSort) {\r\n if (sortColumn) {\r\n this.sortColumns.splice(i, 1);\r\n }\r\n } else {\r\n if ((!e.shiftKey && !e.metaKey) || !this._options.multiColumnSort) {\r\n this.sortColumns = [];\r\n }\r\n\r\n if (!sortColumn) {\r\n sortColumn = { columnId: column.id, sortAsc: column.defaultSortAsc, sortCol: column };\r\n this.sortColumns.push(sortColumn);\r\n } else if (this.sortColumns.length === 0) {\r\n this.sortColumns.push(sortColumn);\r\n }\r\n }\r\n }\r\n\r\n let onSortArgs;\r\n if (!this._options.multiColumnSort) {\r\n onSortArgs = {\r\n multiColumnSort: false,\r\n previousSortColumns,\r\n columnId: (this.sortColumns.length > 0 ? column.id : null),\r\n sortCol: (this.sortColumns.length > 0 ? column : null),\r\n sortAsc: (this.sortColumns.length > 0 ? this.sortColumns[0].sortAsc : true)\r\n };\r\n } else {\r\n onSortArgs = {\r\n multiColumnSort: true,\r\n previousSortColumns,\r\n sortCols: this.sortColumns.map((col) => {\r\n const tempCol = this.columns[this.getColumnIndex(col.columnId)];\r\n return !tempCol || tempCol.hidden ? null : { columnId: tempCol.id, sortCol: tempCol, sortAsc: col.sortAsc };\r\n }).filter((el) => el)\r\n };\r\n }\r\n\r\n if (this.trigger(this.onBeforeSort, onSortArgs, e).getReturnValue() !== false) {\r\n this.setSortColumns(this.sortColumns);\r\n this.trigger(this.onSort, onSortArgs, e);\r\n }\r\n }\r\n });\r\n });\r\n }\r\n\r\n protected setupColumnReorder() {\r\n this.sortableSideLeftInstance?.destroy();\r\n this.sortableSideRightInstance?.destroy();\r\n\r\n let columnScrollTimer: any = null;\r\n\r\n const scrollColumnsRight = () => this._viewportScrollContainerX.scrollLeft = this._viewportScrollContainerX.scrollLeft + 10;\r\n const scrollColumnsLeft = () => this._viewportScrollContainerX.scrollLeft = this._viewportScrollContainerX.scrollLeft - 10;\r\n\r\n let canDragScroll = false;\r\n const sortableOptions = {\r\n animation: 50,\r\n direction: 'horizontal',\r\n chosenClass: 'slick-header-column-active',\r\n ghostClass: 'slick-sortable-placeholder',\r\n draggable: '.slick-header-column',\r\n dragoverBubble: false,\r\n revertClone: true,\r\n scroll: !this.hasFrozenColumns(), // enable auto-scroll\r\n // lock unorderable columns by using a combo of filter + onMove\r\n filter: `.${this._options.unorderableColumnCssClass}`,\r\n onMove: (event: MouseEvent & { related: HTMLElement; }) => {\r\n return !event.related.classList.contains(this._options.unorderableColumnCssClass as string);\r\n },\r\n onStart: (e: { item: any; originalEvent: MouseEvent; }) => {\r\n canDragScroll = !this.hasFrozenColumns() ||\r\n Utils.offset(e.item)!.left > Utils.offset(this._viewportScrollContainerX)!.left;\r\n\r\n if (canDragScroll && e.originalEvent.pageX > this._container.clientWidth) {\r\n if (!(columnScrollTimer)) {\r\n columnScrollTimer = window.setInterval(scrollColumnsRight, 100);\r\n }\r\n } else if (canDragScroll && e.originalEvent.pageX < Utils.offset(this._viewportScrollContainerX)!.left) {\r\n if (!(columnScrollTimer)) {\r\n columnScrollTimer = window.setInterval(scrollColumnsLeft, 100);\r\n }\r\n } else {\r\n window.clearInterval(columnScrollTimer);\r\n columnScrollTimer = null;\r\n }\r\n },\r\n onEnd: (e: MouseEvent & { item: any; originalEvent: MouseEvent; }) => {\r\n window.clearInterval(columnScrollTimer);\r\n columnScrollTimer = null;\r\n\r\n if (!this.getEditorLock()?.commitCurrentEdit()) {\r\n return;\r\n }\r\n\r\n let reorderedIds = this.sortableSideLeftInstance?.toArray() ?? [];\r\n reorderedIds = reorderedIds.concat(this.sortableSideRightInstance?.toArray() ?? []);\r\n\r\n const reorderedColumns: C[] = [];\r\n for (let i = 0; i < reorderedIds.length; i++) {\r\n reorderedColumns.push(this.columns[this.getColumnIndex(reorderedIds[i])]);\r\n }\r\n this.setColumns(reorderedColumns);\r\n\r\n this.trigger(this.onColumnsReordered, { impactedColumns: this.columns });\r\n e.stopPropagation();\r\n this.setupColumnResize();\r\n if (this.activeCellNode) {\r\n this.setFocus(); // refocus on active cell\r\n }\r\n }\r\n };\r\n\r\n this.sortableSideLeftInstance = Sortable.create(this._headerL, sortableOptions);\r\n this.sortableSideRightInstance = Sortable.create(this._headerR, sortableOptions);\r\n }\r\n\r\n protected getHeaderChildren() {\r\n const a = Array.from(this._headers[0].children);\r\n const b = Array.from(this._headers[1].children);\r\n return a.concat(b) as HTMLElement[];\r\n }\r\n\r\n protected handleResizeableDoubleClick(evt: MouseEvent & { target: HTMLDivElement; }) {\r\n const triggeredByColumn = evt.target.parentElement!.id.replace(this.uid, '');\r\n this.trigger(this.onColumnsResizeDblClick, { triggeredByColumn });\r\n }\r\n\r\n protected setupColumnResize() {\r\n if (typeof Resizable === 'undefined') {\r\n throw new Error(`Slick.Resizable is undefined, make sure to import \"slick.interactions.js\"`);\r\n }\r\n\r\n let j: number;\r\n let k: number;\r\n let c: C;\r\n let pageX: number;\r\n let minPageX: number;\r\n let maxPageX: number;\r\n let firstResizable: number | undefined;\r\n let lastResizable = -1;\r\n let frozenLeftColMaxWidth = 0;\r\n\r\n const children: HTMLElement[] = this.getHeaderChildren();\r\n const vc = this.getVisibleColumns();\r\n for (let i = 0; i < children.length; i++) {\r\n const child = children[i];\r\n const handles = child.querySelectorAll('.slick-resizable-handle');\r\n handles.forEach((handle) => handle.remove());\r\n\r\n if (i >= vc.length || !vc[i]) {\r\n continue;\r\n }\r\n\r\n if (vc[i].resizable) {\r\n if (firstResizable === undefined) {\r\n firstResizable = i;\r\n }\r\n lastResizable = i;\r\n }\r\n }\r\n\r\n if (firstResizable === undefined) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < children.length; i++) {\r\n const colElm = children[i];\r\n\r\n if (i >= vc.length || !vc[i]) {\r\n continue;\r\n }\r\n if (i < firstResizable || (this._options.forceFitColumns && i >= lastResizable)) {\r\n continue;\r\n }\r\n\r\n const resizeableHandle = Utils.createDomElement('div', { className: 'slick-resizable-handle', role: 'separator', ariaOrientation: 'horizontal' }, colElm);\r\n this._bindingEventService.bind(resizeableHandle, 'dblclick', this.handleResizeableDoubleClick.bind(this) as EventListener);\r\n\r\n this.slickResizableInstances.push(\r\n Resizable({\r\n resizeableElement: colElm as HTMLElement,\r\n resizeableHandleElement: resizeableHandle,\r\n onResizeStart: (e, resizeElms): boolean | void => {\r\n const targetEvent = (e as TouchEvent).touches ? (e as TouchEvent).changedTouches[0] : e;\r\n if (!this.getEditorLock()?.commitCurrentEdit()) {\r\n return false;\r\n }\r\n pageX = (targetEvent as MouseEvent).pageX;\r\n frozenLeftColMaxWidth = 0;\r\n resizeElms.resizeableElement.classList.add('slick-header-column-active');\r\n let shrinkLeewayOnRight: number | null = null;\r\n let stretchLeewayOnRight: number | null = null;\r\n // lock each column's width option to current width\r\n for (let pw = 0; pw < children.length; pw++) {\r\n if (pw >= vc.length || !vc[pw]) {\r\n continue;\r\n }\r\n vc[pw].previousWidth = children[pw].offsetWidth;\r\n }\r\n if (this._options.forceFitColumns) {\r\n shrinkLeewayOnRight = 0;\r\n stretchLeewayOnRight = 0;\r\n // colums on right affect maxPageX/minPageX\r\n for (j = i + 1; j < vc.length; j++) {\r\n c = vc[j];\r\n if (c?.resizable) {\r\n if (stretchLeewayOnRight !== null) {\r\n if (c.maxWidth) {\r\n stretchLeewayOnRight += c.maxWidth - (c.previousWidth || 0);\r\n } else {\r\n stretchLeewayOnRight = null;\r\n }\r\n }\r\n shrinkLeewayOnRight += (c.previousWidth || 0) - Math.max(c.minWidth || 0, this.absoluteColumnMinWidth);\r\n }\r\n }\r\n }\r\n let shrinkLeewayOnLeft = 0;\r\n let stretchLeewayOnLeft: number | null = 0;\r\n for (j = 0; j <= i; j++) {\r\n // columns on left only affect minPageX\r\n c = vc[j];\r\n if (c?.resizable) {\r\n if (stretchLeewayOnLeft !== null) {\r\n if (c.maxWidth) {\r\n stretchLeewayOnLeft += c.maxWidth - (c.previousWidth || 0);\r\n } else {\r\n stretchLeewayOnLeft = null;\r\n }\r\n }\r\n shrinkLeewayOnLeft += (c.previousWidth || 0) - Math.max(c.minWidth || 0, this.absoluteColumnMinWidth);\r\n }\r\n }\r\n if (shrinkLeewayOnRight === null) {\r\n shrinkLeewayOnRight = 100000;\r\n }\r\n if (shrinkLeewayOnLeft === null) {\r\n shrinkLeewayOnLeft = 100000;\r\n }\r\n if (stretchLeewayOnRight === null) {\r\n stretchLeewayOnRight = 100000;\r\n }\r\n if (stretchLeewayOnLeft === null) {\r\n stretchLeewayOnLeft = 100000;\r\n }\r\n maxPageX = pageX + Math.min(shrinkLeewayOnRight, stretchLeewayOnLeft);\r\n minPageX = pageX - Math.min(shrinkLeewayOnLeft, stretchLeewayOnRight);\r\n },\r\n onResize: (e, resizeElms) => {\r\n const targetEvent = (e as TouchEvent).touches ? (e as TouchEvent).changedTouches[0] : e;\r\n this.columnResizeDragging = true;\r\n let actualMinWidth;\r\n const d = Math.min(maxPageX, Math.max(minPageX, (targetEvent as MouseEvent).pageX)) - pageX;\r\n let x;\r\n let newCanvasWidthL = 0;\r\n let newCanvasWidthR = 0;\r\n const viewportWidth = this.viewportHasVScroll ? this.viewportW - (this.scrollbarDimensions?.width ?? 0) : this.viewportW;\r\n\r\n if (d < 0) { // shrink column\r\n x = d;\r\n\r\n for (j = i; j >= 0; j--) {\r\n c = vc[j];\r\n if (c?.resizable && !c.hidden) {\r\n actualMinWidth = Math.max(c.minWidth || 0, this.absoluteColumnMinWidth);\r\n if (x && (c.previousWidth || 0) + x < actualMinWidth) {\r\n x += (c.previousWidth || 0) - actualMinWidth;\r\n c.width = actualMinWidth;\r\n } else {\r\n c.width = (c.previousWidth || 0) + x;\r\n x = 0;\r\n }\r\n }\r\n }\r\n\r\n for (k = 0; k <= i; k++) {\r\n c = vc[k];\r\n if (!c || c.hidden) { continue; }\r\n\r\n if (this.hasFrozenColumns() && (k > this._options.frozenColumn!)) {\r\n newCanvasWidthR += c.width || 0;\r\n } else {\r\n newCanvasWidthL += c.width || 0;\r\n }\r\n }\r\n\r\n if (this._options.forceFitColumns) {\r\n x = -d;\r\n for (j = i + 1; j < vc.length; j++) {\r\n c = vc[j];\r\n if (!c || c.hidden) { continue; }\r\n if (c.resizable) {\r\n if (x && c.maxWidth && (c.maxWidth - (c.previousWidth || 0) < x)) {\r\n x -= c.maxWidth - (c.previousWidth || 0);\r\n c.width = c.maxWidth;\r\n } else {\r\n c.width = (c.previousWidth || 0) + x;\r\n x = 0;\r\n }\r\n\r\n if (this.hasFrozenColumns() && (j > this._options.frozenColumn!)) {\r\n newCanvasWidthR += c.width || 0;\r\n } else {\r\n newCanvasWidthL += c.width || 0;\r\n }\r\n }\r\n }\r\n } else {\r\n for (j = i + 1; j < vc.length; j++) {\r\n c = vc[j];\r\n if (!c || c.hidden) { continue; }\r\n\r\n if (this.hasFrozenColumns() && (j > this._options.frozenColumn!)) {\r\n newCanvasWidthR += c.width || 0;\r\n } else {\r\n newCanvasWidthL += c.width || 0;\r\n }\r\n }\r\n }\r\n\r\n if (this._options.forceFitColumns) {\r\n x = -d;\r\n for (j = i + 1; j < vc.length; j++) {\r\n c = vc[j];\r\n if (!c || c.hidden) { continue; }\r\n if (c.resizable) {\r\n if (x && c.maxWidth && (c.maxWidth - (c.previousWidth || 0) < x)) {\r\n x -= c.maxWidth - (c.previousWidth || 0);\r\n c.width = c.maxWidth;\r\n } else {\r\n c.width = (c.previousWidth || 0) + x;\r\n x = 0;\r\n }\r\n }\r\n }\r\n }\r\n } else { // stretch column\r\n x = d;\r\n\r\n newCanvasWidthL = 0;\r\n newCanvasWidthR = 0;\r\n\r\n for (j = i; j >= 0; j--) {\r\n c = vc[j];\r\n if (!c || c.hidden) { continue; }\r\n if (c.resizable) {\r\n if (x && c.maxWidth && (c.maxWidth - (c.previousWidth || 0) < x)) {\r\n x -= c.maxWidth - (c.previousWidth || 0);\r\n c.width = c.maxWidth;\r\n } else {\r\n const newWidth = (c.previousWidth || 0) + x;\r\n const resizedCanvasWidthL = this.canvasWidthL + x;\r\n\r\n if (this.hasFrozenColumns() && (j <= this._options.frozenColumn!)) {\r\n // if we're on the left frozen side, we need to make sure that our left section width never goes over the total viewport width\r\n if (newWidth > frozenLeftColMaxWidth && resizedCanvasWidthL < (viewportWidth - this._options.frozenRightViewportMinWidth!)) {\r\n frozenLeftColMaxWidth = newWidth; // keep max column width ref, if we go over the limit this number will stop increasing\r\n }\r\n c.width = ((resizedCanvasWidthL + this._options.frozenRightViewportMinWidth!) > viewportWidth) ? frozenLeftColMaxWidth : newWidth;\r\n } else {\r\n c.width = newWidth;\r\n }\r\n x = 0;\r\n }\r\n }\r\n }\r\n\r\n for (k = 0; k <= i; k++) {\r\n c = vc[k];\r\n if (!c || c.hidden) { continue; }\r\n\r\n if (this.hasFrozenColumns() && (k > this._options.frozenColumn!)) {\r\n newCanvasWidthR += c.width || 0;\r\n } else {\r\n newCanvasWidthL += c.width || 0;\r\n }\r\n }\r\n\r\n if (this._options.forceFitColumns) {\r\n x = -d;\r\n for (j = i + 1; j < vc.length; j++) {\r\n c = vc[j];\r\n if (!c || c.hidden) { continue; }\r\n if (c.resizable) {\r\n actualMinWidth = Math.max(c.minWidth || 0, this.absoluteColumnMinWidth);\r\n if (x && (c.previousWidth || 0) + x < actualMinWidth) {\r\n x += (c.previousWidth || 0) - actualMinWidth;\r\n c.width = actualMinWidth;\r\n } else {\r\n c.width = (c.previousWidth || 0) + x;\r\n x = 0;\r\n }\r\n\r\n if (this.hasFrozenColumns() && (j > this._options.frozenColumn!)) {\r\n newCanvasWidthR += c.width || 0;\r\n } else {\r\n newCanvasWidthL += c.width || 0;\r\n }\r\n }\r\n }\r\n } else {\r\n for (j = i + 1; j < vc.length; j++) {\r\n c = vc[j];\r\n if (!c || c.hidden) { continue; }\r\n\r\n if (this.hasFrozenColumns() && (j > this._options.frozenColumn!)) {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n newCanvasWidthR += c.width || 0;\r\n } else {\r\n newCanvasWidthL += c.width || 0;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (this.hasFrozenColumns() && newCanvasWidthL !== this.canvasWidthL) {\r\n Utils.width(this._headerL, newCanvasWidthL + 1000);\r\n Utils.setStyleSize(this._paneHeaderR, 'left', newCanvasWidthL);\r\n }\r\n\r\n this.applyColumnHeaderWidths();\r\n if (this._options.syncColumnCellResize) {\r\n this.applyColumnWidths();\r\n }\r\n this.trigger(this.onColumnsDrag, {\r\n triggeredByColumn: resizeElms.resizeableElement,\r\n resizeHandle: resizeElms.resizeableHandleElement\r\n });\r\n },\r\n onResizeEnd: (_e, resizeElms) => {\r\n resizeElms.resizeableElement.classList.remove('slick-header-column-active');\r\n\r\n const triggeredByColumn = resizeElms.resizeableElement.id.replace(this.uid, '');\r\n if (this.trigger(this.onBeforeColumnsResize, { triggeredByColumn }).getReturnValue() === true) {\r\n this.applyColumnHeaderWidths();\r\n }\r\n let newWidth;\r\n for (j = 0; j < vc.length; j++) {\r\n c = vc[j];\r\n if (!c || c.hidden) { continue; }\r\n newWidth = children[j].offsetWidth;\r\n\r\n if (c.previousWidth !== newWidth && c.rerenderOnResize) {\r\n this.invalidateAllRows();\r\n }\r\n }\r\n this.updateCanvasWidth(true);\r\n this.render();\r\n this.trigger(this.onColumnsResized, { triggeredByColumn });\r\n window.clearTimeout(this._columnResizeTimer);\r\n this._columnResizeTimer = window.setTimeout(() => { this.columnResizeDragging = false; }, 300);\r\n }\r\n })\r\n );\r\n }\r\n }\r\n\r\n protected getVBoxDelta(el: HTMLElement) {\r\n const p = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];\r\n const styles = getComputedStyle(el);\r\n let delta = 0;\r\n p.forEach((val) => delta += Utils.toFloat(styles[val as any]));\r\n return delta;\r\n }\r\n\r\n protected setFrozenOptions() {\r\n this._options.frozenColumn = (this._options.frozenColumn! >= 0 && this._options.frozenColumn! < this.columns.length)\r\n ? parseInt(this._options.frozenColumn as unknown as string, 10)\r\n : -1;\r\n\r\n if (this._options.frozenRow! > -1) {\r\n this.hasFrozenRows = true;\r\n this.frozenRowsHeight = (this._options.frozenRow!) * this._options.rowHeight!;\r\n const dataLength = this.getDataLength();\r\n\r\n this.actualFrozenRow = (this._options.frozenBottom)\r\n ? (dataLength - this._options.frozenRow!)\r\n : this._options.frozenRow!;\r\n } else {\r\n this.hasFrozenRows = false;\r\n }\r\n }\r\n\r\n protected setPaneVisibility() {\r\n if (this.hasFrozenColumns()) {\r\n Utils.show(this._paneHeaderR);\r\n Utils.show(this._paneTopR);\r\n\r\n if (this.hasFrozenRows) {\r\n Utils.show(this._paneBottomL);\r\n Utils.show(this._paneBottomR);\r\n } else {\r\n Utils.hide(this._paneBottomR);\r\n Utils.hide(this._paneBottomL);\r\n }\r\n } else {\r\n Utils.hide(this._paneHeaderR);\r\n Utils.hide(this._paneTopR);\r\n Utils.hide(this._paneBottomR);\r\n\r\n if (this.hasFrozenRows) {\r\n Utils.show(this._paneBottomL);\r\n } else {\r\n Utils.hide(this._paneBottomR);\r\n Utils.hide(this._paneBottomL);\r\n }\r\n }\r\n }\r\n\r\n protected setOverflow() {\r\n this._viewportTopL.style.overflowX = (this.hasFrozenColumns()) ? (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'hidden' : 'scroll') : (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'hidden' : 'auto');\r\n this._viewportTopL.style.overflowY = (!this.hasFrozenColumns() && this._options.alwaysShowVerticalScroll) ? 'scroll' : ((this.hasFrozenColumns()) ? (this.hasFrozenRows ? 'hidden' : 'hidden') : (this.hasFrozenRows ? 'scroll' : 'auto'));\r\n\r\n this._viewportTopR.style.overflowX = (this.hasFrozenColumns()) ? (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'hidden' : 'scroll') : (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'hidden' : 'auto');\r\n this._viewportTopR.style.overflowY = this._options.alwaysShowVerticalScroll ? 'scroll' : ((this.hasFrozenColumns()) ? (this.hasFrozenRows ? 'scroll' : 'auto') : (this.hasFrozenRows ? 'scroll' : 'auto'));\r\n\r\n this._viewportBottomL.style.overflowX = (this.hasFrozenColumns()) ? (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'scroll' : 'auto') : (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'auto' : 'auto');\r\n this._viewportBottomL.style.overflowY = (!this.hasFrozenColumns() && this._options.alwaysShowVerticalScroll) ? 'scroll' : ((this.hasFrozenColumns()) ? (this.hasFrozenRows ? 'hidden' : 'hidden') : (this.hasFrozenRows ? 'scroll' : 'auto'));\r\n\r\n this._viewportBottomR.style.overflowX = (this.hasFrozenColumns()) ? (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'scroll' : 'auto') : (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'auto' : 'auto');\r\n this._viewportBottomR.style.overflowY = this._options.alwaysShowVerticalScroll ? 'scroll' : ((this.hasFrozenColumns()) ? (this.hasFrozenRows ? 'auto' : 'auto') : (this.hasFrozenRows ? 'auto' : 'auto'));\r\n\r\n if (this._options.viewportClass) {\r\n const viewportClassList = Utils.classNameToList(this._options.viewportClass);\r\n this._viewportTopL.classList.add(...viewportClassList);\r\n this._viewportTopR.classList.add(...viewportClassList);\r\n this._viewportBottomL.classList.add(...viewportClassList);\r\n this._viewportBottomR.classList.add(...viewportClassList);\r\n }\r\n }\r\n\r\n protected setScroller() {\r\n if (this.hasFrozenColumns()) {\r\n this._headerScrollContainer = this._headerScrollerR;\r\n this._headerRowScrollContainer = this._headerRowScrollerR;\r\n this._footerRowScrollContainer = this._footerRowScrollerR;\r\n\r\n if (this.hasFrozenRows) {\r\n if (this._options.frozenBottom) {\r\n this._viewportScrollContainerX = this._viewportBottomR;\r\n this._viewportScrollContainerY = this._viewportTopR;\r\n } else {\r\n this._viewportScrollContainerX = this._viewportScrollContainerY = this._viewportBottomR;\r\n }\r\n } else {\r\n this._viewportScrollContainerX = this._viewportScrollContainerY = this._viewportTopR;\r\n }\r\n } else {\r\n this._headerScrollContainer = this._headerScrollerL;\r\n this._headerRowScrollContainer = this._headerRowScrollerL;\r\n this._footerRowScrollContainer = this._footerRowScrollerL;\r\n\r\n if (this.hasFrozenRows) {\r\n if (this._options.frozenBottom) {\r\n this._viewportScrollContainerX = this._viewportBottomL;\r\n this._viewportScrollContainerY = this._viewportTopL;\r\n } else {\r\n this._viewportScrollContainerX = this._viewportScrollContainerY = this._viewportBottomL;\r\n }\r\n } else {\r\n this._viewportScrollContainerX = this._viewportScrollContainerY = this._viewportTopL;\r\n }\r\n }\r\n }\r\n\r\n protected measureCellPaddingAndBorder() {\r\n const h = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];\r\n const v = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];\r\n const header = this._headers[0];\r\n\r\n this.headerColumnWidthDiff = this.headerColumnHeightDiff = 0;\r\n this.cellWidthDiff = this.cellHeightDiff = 0;\r\n\r\n let el = Utils.createDomElement('div', { className: 'ui-state-default slick-state-default slick-header-column', style: { visibility: 'hidden' }, textContent: '-' }, header);\r\n let style = getComputedStyle(el);\r\n if (style.boxSizing !== 'border-box') {\r\n h.forEach((val) => this.headerColumnWidthDiff += Utils.toFloat(style[val as any]));\r\n v.forEach((val) => this.headerColumnHeightDiff += Utils.toFloat(style[val as any]));\r\n }\r\n el.remove();\r\n\r\n const r = Utils.createDomElement('div', { className: 'slick-row' }, this._canvas[0]);\r\n el = Utils.createDomElement('div', { className: 'slick-cell', id: '', style: { visibility: 'hidden' }, textContent: '-' }, r);\r\n style = getComputedStyle(el);\r\n if (style.boxSizing !== 'border-box') {\r\n h.forEach((val) => this.cellWidthDiff += Utils.toFloat(style[val as any]));\r\n v.forEach((val) => this.cellHeightDiff += Utils.toFloat(style[val as any]));\r\n }\r\n r.remove();\r\n\r\n this.absoluteColumnMinWidth = Math.max(this.headerColumnWidthDiff, this.cellWidthDiff);\r\n }\r\n\r\n protected createCssRules() {\r\n this._style = document.createElement('style');\r\n this._style.nonce = this._options.nonce || '';\r\n (this._options.shadowRoot || document.head).appendChild(this._style);\r\n\r\n const rowHeight = (this._options.rowHeight! - this.cellHeightDiff);\r\n const rules = [\r\n `.${this.uid} .slick-group-header-column { left: 1000px; }`,\r\n `.${this.uid} .slick-header-column { left: 1000px; }`,\r\n `.${this.uid} .slick-top-panel { height: ${this._options.topPanelHeight}px; }`,\r\n `.${this.uid} .slick-preheader-panel { height: ${this._options.preHeaderPanelHeight}px; }`,\r\n `.${this.uid} .slick-topheader-panel { height: ${this._options.topHeaderPanelHeight}px; }`,\r\n `.${this.uid} .slick-headerrow-columns { height: ${this._options.headerRowHeight}px; }`,\r\n `.${this.uid} .slick-footerrow-columns { height: ${this._options.footerRowHeight}px; }`,\r\n `.${this.uid} .slick-cell { height: ${rowHeight}px; }`,\r\n `.${this.uid} .slick-row { height: ${this._options.rowHeight}px; }`,\r\n ];\r\n\r\n const sheet = this._style.sheet;\r\n if (sheet) {\r\n rules.forEach(rule => {\r\n sheet.insertRule(rule);\r\n });\r\n\r\n for (let i = 0; i < this.columns.length; i++) {\r\n if (!this.columns[i] || this.columns[i].hidden) { continue; }\r\n\r\n sheet.insertRule(`.${this.uid} .l${i} { }`);\r\n sheet.insertRule(`.${this.uid} .r${i} { }`);\r\n }\r\n } else {\r\n // fallback in case the 1st approach doesn't work, let's use our previous way of creating the css rules which is what works in Salesforce :(\r\n this.createCssRulesAlternative(rules);\r\n }\r\n }\r\n\r\n /** Create CSS rules via template in case the first approach with createElement('style') doesn't work */\r\n protected createCssRulesAlternative(rules: string[]) {\r\n const template = document.createElement('template');\r\n template.innerHTML = '