UNPKG

slickgrid

Version:

A lightning fast JavaScript grid/spreadsheet

622 lines (621 loc) 300 kB
"use strict"; (() => { var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key != "symbol" ? key + "" : key, value); // src/slick.grid.ts var BindingEventService = Slick.BindingEventService, ColAutosizeMode = Slick.ColAutosizeMode, SlickEvent = Slick.Event, SlickEventData = Slick.EventData, GlobalEditorLock = Slick.GlobalEditorLock, GridAutosizeColsMode = Slick.GridAutosizeColsMode, keyCode = Slick.keyCode, preClickClassName = Slick.preClickClassName, SlickRange = Slick.Range, RowSelectionMode = Slick.RowSelectionMode, ValueFilterMode = Slick.ValueFilterMode, Utils = Slick.Utils, WidthEvalMode = Slick.WidthEvalMode, Draggable = Slick.Draggable, MouseWheel = Slick.MouseWheel, Resizable = Slick.Resizable; var SlickGrid = class { /** * Creates a new instance of the grid. * @class SlickGrid * @constructor * @param {Node} container - Container node to create the grid in. * @param {Array|Object} data - An array of objects for databinding or an external DataView. * @param {Array<C>} columns - An array of column definitions. * @param {Object} [options] - Grid Options * @param {Object} [externalPubSub] - optional External PubSub Service to use by SlickEvent **/ constructor(container, data, columns, options, externalPubSub) { this.container = container; this.data = data; this.columns = columns; this.externalPubSub = externalPubSub; ////////////////////////////////////////////////////////////////////////////////////////////// // Public API __publicField(this, "slickGridVersion", "5.15.5"); /** optional grid state clientId */ __publicField(this, "cid", ""); // Events __publicField(this, "onActiveCellChanged"); __publicField(this, "onActiveCellPositionChanged"); __publicField(this, "onAddNewRow"); __publicField(this, "onAfterSetColumns"); __publicField(this, "onAutosizeColumns"); __publicField(this, "onBeforeAppendCell"); __publicField(this, "onBeforeCellEditorDestroy"); __publicField(this, "onBeforeColumnsResize"); __publicField(this, "onBeforeDestroy"); __publicField(this, "onBeforeEditCell"); __publicField(this, "onBeforeFooterRowCellDestroy"); __publicField(this, "onBeforeHeaderCellDestroy"); __publicField(this, "onBeforeHeaderRowCellDestroy"); __publicField(this, "onBeforeRemoveCachedRow"); __publicField(this, "onBeforeSetColumns"); __publicField(this, "onBeforeSort"); __publicField(this, "onBeforeUpdateColumns"); __publicField(this, "onCellChange"); __publicField(this, "onCellCssStylesChanged"); __publicField(this, "onClick"); __publicField(this, "onColumnsReordered"); __publicField(this, "onColumnsDrag"); __publicField(this, "onColumnsResized"); __publicField(this, "onColumnsResizeDblClick"); __publicField(this, "onCompositeEditorChange"); __publicField(this, "onContextMenu"); __publicField(this, "onDrag"); __publicField(this, "onDblClick"); __publicField(this, "onDragInit"); __publicField(this, "onDragStart"); __publicField(this, "onDragEnd"); __publicField(this, "onFooterClick"); __publicField(this, "onFooterContextMenu"); __publicField(this, "onFooterRowCellRendered"); __publicField(this, "onHeaderCellRendered"); __publicField(this, "onHeaderClick"); __publicField(this, "onHeaderContextMenu"); __publicField(this, "onHeaderMouseEnter"); __publicField(this, "onHeaderMouseLeave"); __publicField(this, "onHeaderRowCellRendered"); __publicField(this, "onHeaderRowMouseEnter"); __publicField(this, "onHeaderRowMouseLeave"); __publicField(this, "onPreHeaderContextMenu"); __publicField(this, "onPreHeaderClick"); __publicField(this, "onKeyDown"); __publicField(this, "onMouseEnter"); __publicField(this, "onMouseLeave"); __publicField(this, "onRendered"); __publicField(this, "onScroll"); __publicField(this, "onSelectedRowsChanged"); __publicField(this, "onSetOptions"); __publicField(this, "onActivateChangedOptions"); __publicField(this, "onSort"); __publicField(this, "onValidationError"); __publicField(this, "onViewportChanged"); // --- // protected variables // shared across all grids on the page __publicField(this, "scrollbarDimensions"); __publicField(this, "maxSupportedCssHeight"); // browser's breaking point __publicField(this, "canvas", null); __publicField(this, "canvas_context", null); // settings __publicField(this, "_options"); __publicField(this, "_defaults", { alwaysShowVerticalScroll: !1, alwaysAllowHorizontalScroll: !1, explicitInitialization: !1, rowHeight: 25, defaultColumnWidth: 80, enableHtmlRendering: !0, enableAddRow: !1, leaveSpaceForNewRows: !1, editable: !1, autoEdit: !0, autoEditNewRow: !0, autoCommitEdit: !1, suppressActiveCellChangeOnEdit: !1, enableCellNavigation: !0, enableColumnReorder: !0, unorderableColumnCssClass: "unorderable", asyncEditorLoading: !1, asyncEditorLoadDelay: 100, forceFitColumns: !1, enableAsyncPostRender: !1, asyncPostRenderDelay: 50, enableAsyncPostRenderCleanup: !1, asyncPostRenderCleanupDelay: 40, auto: !1, nonce: "", editorLock: GlobalEditorLock, showColumnHeader: !0, showHeaderRow: !1, headerRowHeight: 25, createFooterRow: !1, showFooterRow: !1, footerRowHeight: 25, createPreHeaderPanel: !1, createTopHeaderPanel: !1, showPreHeaderPanel: !1, showTopHeaderPanel: !1, preHeaderPanelHeight: 25, showTopPanel: !1, topPanelHeight: 25, preHeaderPanelWidth: "auto", // mostly useful for Draggable Grouping dropzone to take full width topHeaderPanelHeight: 25, topHeaderPanelWidth: "auto", // mostly useful for Draggable Grouping dropzone to take full width formatterFactory: null, editorFactory: null, cellFlashingCssClass: "flashing", rowHighlightCssClass: "highlight-animate", rowHighlightDuration: 400, selectedCellCssClass: "selected", multiSelect: !0, enableCellRowSpan: !1, enableTextSelectionOnCells: !1, dataItemColumnValueExtractor: null, frozenBottom: !1, frozenColumn: -1, frozenRow: -1, frozenRightViewportMinWidth: 100, throwWhenFrozenNotAllViewable: !1, fullWidthRows: !1, multiColumnSort: !1, numberedMultiColumnSort: !1, tristateMultiColumnSort: !1, sortColNumberInSeparateSpan: !1, defaultFormatter: this.defaultFormatter, forceSyncScrolling: !1, addNewRowCssClass: "new-row", preserveCopiedSelectionOnPaste: !1, preventDragFromKeys: ["ctrlKey", "metaKey"], showCellSelection: !0, viewportClass: void 0, minRowBuffer: 3, emulatePagingWhenScrolling: !0, // when scrolling off bottom of viewport, place new row at top of viewport editorCellNavOnLRKeys: !1, enableMouseWheelScrollHandler: !0, doPaging: !0, autosizeColsMode: GridAutosizeColsMode.LegacyOff, autosizeColPaddingPx: 4, rowTopOffsetRenderType: "top", scrollRenderThrottling: 10, autosizeTextAvgToMWidthRatio: 0.75, viewportSwitchToScrollModeWidthPercent: void 0, viewportMinWidthPx: void 0, viewportMaxWidthPx: void 0, suppressCssChangesOnHiddenInit: !1, ffMaxSupportedCssHeight: 6e6, maxSupportedCssHeight: 1e9, maxPartialRowSpanRemap: 5e3, sanitizer: void 0, // sanitize function, built in basic sanitizer is: Slick.RegexSanitizer(dirtyHtml) logSanitizedHtml: !1, // log to console when sanitised - recommend true for testing of dev and production mixinDefaults: !0, shadowRoot: void 0 }); __publicField(this, "_columnDefaults", { name: "", headerCssClass: null, defaultSortAsc: !0, focusable: !0, hidden: !1, minWidth: 30, maxWidth: void 0, rerenderOnResize: !1, reorderable: !0, resizable: !0, sortable: !1, selectable: !0 }); __publicField(this, "_columnAutosizeDefaults", { ignoreHeaderText: !1, colValueArray: void 0, allowAddlPercent: void 0, formatterOverride: void 0, autosizeMode: ColAutosizeMode.ContentIntelligent, rowSelectionModeOnInit: void 0, rowSelectionMode: RowSelectionMode.FirstNRows, rowSelectionCount: 100, valueFilterMode: ValueFilterMode.None, widthEvalMode: WidthEvalMode.Auto, sizeToRemaining: void 0, widthPx: void 0, contentSizePx: 0, headerWidthPx: 0, colDataTypeOf: void 0 }); __publicField(this, "_columnResizeTimer"); __publicField(this, "_executionBlockTimer"); __publicField(this, "_flashCellTimer"); __publicField(this, "_highlightRowTimer"); // scroller __publicField(this, "th"); // virtual height __publicField(this, "h"); // real scrollable height __publicField(this, "ph"); // page height __publicField(this, "n"); // number of pages __publicField(this, "cj"); // "jumpiness" coefficient __publicField(this, "page", 0); // current page __publicField(this, "offset", 0); // current page offset __publicField(this, "vScrollDir", 1); __publicField(this, "_bindingEventService", new BindingEventService()); __publicField(this, "initialized", !1); __publicField(this, "_container"); __publicField(this, "uid", `slickgrid_${Math.round(1e6 * Math.random())}`); __publicField(this, "_focusSink"); __publicField(this, "_focusSink2"); __publicField(this, "_groupHeaders", []); __publicField(this, "_headerScroller", []); __publicField(this, "_headers", []); __publicField(this, "_headerRows"); __publicField(this, "_headerRowScroller"); __publicField(this, "_headerRowSpacerL"); __publicField(this, "_headerRowSpacerR"); __publicField(this, "_footerRow"); __publicField(this, "_footerRowScroller"); __publicField(this, "_footerRowSpacerL"); __publicField(this, "_footerRowSpacerR"); __publicField(this, "_preHeaderPanel"); __publicField(this, "_preHeaderPanelScroller"); __publicField(this, "_preHeaderPanelSpacer"); __publicField(this, "_preHeaderPanelR"); __publicField(this, "_preHeaderPanelScrollerR"); __publicField(this, "_preHeaderPanelSpacerR"); __publicField(this, "_topHeaderPanel"); __publicField(this, "_topHeaderPanelScroller"); __publicField(this, "_topHeaderPanelSpacer"); __publicField(this, "_topPanelScrollers"); __publicField(this, "_topPanels"); __publicField(this, "_viewport"); __publicField(this, "_canvas"); __publicField(this, "_style"); __publicField(this, "_boundAncestors", []); __publicField(this, "stylesheet"); __publicField(this, "columnCssRulesL"); __publicField(this, "columnCssRulesR"); __publicField(this, "viewportH", 0); __publicField(this, "viewportW", 0); __publicField(this, "canvasWidth", 0); __publicField(this, "canvasWidthL", 0); __publicField(this, "canvasWidthR", 0); __publicField(this, "headersWidth", 0); __publicField(this, "headersWidthL", 0); __publicField(this, "headersWidthR", 0); __publicField(this, "viewportHasHScroll", !1); __publicField(this, "viewportHasVScroll", !1); __publicField(this, "headerColumnWidthDiff", 0); __publicField(this, "headerColumnHeightDiff", 0); // border+padding __publicField(this, "cellWidthDiff", 0); __publicField(this, "cellHeightDiff", 0); __publicField(this, "absoluteColumnMinWidth"); __publicField(this, "hasFrozenRows", !1); __publicField(this, "frozenRowsHeight", 0); __publicField(this, "actualFrozenRow", -1); __publicField(this, "paneTopH", 0); __publicField(this, "paneBottomH", 0); __publicField(this, "viewportTopH", 0); __publicField(this, "viewportBottomH", 0); __publicField(this, "topPanelH", 0); __publicField(this, "headerRowH", 0); __publicField(this, "footerRowH", 0); __publicField(this, "tabbingDirection", 1); __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); __publicField(this, "prevScrollTop", 0); __publicField(this, "scrollHeight", 0); __publicField(this, "scrollTop", 0); __publicField(this, "lastRenderedScrollTop", 0); __publicField(this, "lastRenderedScrollLeft", 0); __publicField(this, "prevScrollLeft", 0); __publicField(this, "scrollLeft", 0); __publicField(this, "selectionModel"); __publicField(this, "selectedRows", []); __publicField(this, "plugins", []); __publicField(this, "cellCssClasses", {}); __publicField(this, "columnsById", {}); __publicField(this, "sortColumns", []); __publicField(this, "columnPosLeft", []); __publicField(this, "columnPosRight", []); __publicField(this, "pagingActive", !1); __publicField(this, "pagingIsLastPage", !1); __publicField(this, "scrollThrottle"); // async call handles __publicField(this, "h_editorLoader"); __publicField(this, "h_postrender"); __publicField(this, "h_postrenderCleanup"); __publicField(this, "postProcessedRows", {}); __publicField(this, "postProcessToRow", null); __publicField(this, "postProcessFromRow", null); __publicField(this, "postProcessedCleanupQueue", []); __publicField(this, "postProcessgroupId", 0); // perf counters __publicField(this, "counter_rows_rendered", 0); __publicField(this, "counter_rows_removed", 0); __publicField(this, "_paneHeaderL"); __publicField(this, "_paneHeaderR"); __publicField(this, "_paneTopL"); __publicField(this, "_paneTopR"); __publicField(this, "_paneBottomL"); __publicField(this, "_paneBottomR"); __publicField(this, "_headerScrollerL"); __publicField(this, "_headerScrollerR"); __publicField(this, "_headerL"); __publicField(this, "_headerR"); __publicField(this, "_groupHeadersL"); __publicField(this, "_groupHeadersR"); __publicField(this, "_headerRowScrollerL"); __publicField(this, "_headerRowScrollerR"); __publicField(this, "_footerRowScrollerL"); __publicField(this, "_footerRowScrollerR"); __publicField(this, "_headerRowL"); __publicField(this, "_headerRowR"); __publicField(this, "_footerRowL"); __publicField(this, "_footerRowR"); __publicField(this, "_topPanelScrollerL"); __publicField(this, "_topPanelScrollerR"); __publicField(this, "_topPanelL"); __publicField(this, "_topPanelR"); __publicField(this, "_viewportTopL"); __publicField(this, "_viewportTopR"); __publicField(this, "_viewportBottomL"); __publicField(this, "_viewportBottomR"); __publicField(this, "_canvasTopL"); __publicField(this, "_canvasTopR"); __publicField(this, "_canvasBottomL"); __publicField(this, "_canvasBottomR"); __publicField(this, "_viewportScrollContainerX"); __publicField(this, "_viewportScrollContainerY"); __publicField(this, "_headerScrollContainer"); __publicField(this, "_headerRowScrollContainer"); __publicField(this, "_footerRowScrollContainer"); // store css attributes if display:none is active in container or parent __publicField(this, "cssShow", { position: "absolute", visibility: "hidden", display: "block" }); __publicField(this, "_hiddenParents", []); __publicField(this, "oldProps", []); __publicField(this, "enforceFrozenRowHeightRecalc", !1); __publicField(this, "columnResizeDragging", !1); __publicField(this, "slickDraggableInstance", null); __publicField(this, "slickMouseWheelInstances", []); __publicField(this, "slickResizableInstances", []); __publicField(this, "sortableSideLeftInstance"); __publicField(this, "sortableSideRightInstance"); __publicField(this, "logMessageCount", 0); __publicField(this, "logMessageMaxCount", 30); __publicField(this, "_pubSubService"); if (this._container = typeof this.container == "string" ? document.querySelector(this.container) : this.container, !this._container) throw new Error(`SlickGrid requires a valid container, ${this.container} does not exist in the DOM.`); this._pubSubService = externalPubSub, this.onActiveCellChanged = new SlickEvent("onActiveCellChanged", externalPubSub), this.onActiveCellPositionChanged = new SlickEvent("onActiveCellPositionChanged", externalPubSub), this.onAddNewRow = new SlickEvent("onAddNewRow", externalPubSub), this.onAfterSetColumns = new SlickEvent("onAfterSetColumns", externalPubSub), this.onAutosizeColumns = new SlickEvent("onAutosizeColumns", externalPubSub), this.onBeforeAppendCell = new SlickEvent("onBeforeAppendCell", externalPubSub), this.onBeforeCellEditorDestroy = new SlickEvent("onBeforeCellEditorDestroy", externalPubSub), this.onBeforeColumnsResize = new SlickEvent("onBeforeColumnsResize", externalPubSub), this.onBeforeDestroy = new SlickEvent("onBeforeDestroy", externalPubSub), this.onBeforeEditCell = new SlickEvent("onBeforeEditCell", externalPubSub), this.onBeforeFooterRowCellDestroy = new SlickEvent("onBeforeFooterRowCellDestroy", externalPubSub), this.onBeforeHeaderCellDestroy = new SlickEvent("onBeforeHeaderCellDestroy", externalPubSub), this.onBeforeHeaderRowCellDestroy = new SlickEvent("onBeforeHeaderRowCellDestroy", externalPubSub), this.onBeforeRemoveCachedRow = new SlickEvent("onRowRemovedFromCache", externalPubSub), this.onBeforeSetColumns = new SlickEvent("onBeforeSetColumns", externalPubSub), this.onBeforeSort = new SlickEvent("onBeforeSort", externalPubSub), this.onBeforeUpdateColumns = new SlickEvent("onBeforeUpdateColumns", externalPubSub), this.onCellChange = new SlickEvent("onCellChange", externalPubSub), this.onCellCssStylesChanged = new SlickEvent("onCellCssStylesChanged", externalPubSub), this.onClick = new SlickEvent("onClick", externalPubSub), this.onColumnsReordered = new SlickEvent("onColumnsReordered", externalPubSub), this.onColumnsDrag = new SlickEvent("onColumnsDrag", externalPubSub), this.onColumnsResized = new SlickEvent("onColumnsResized", externalPubSub), this.onColumnsResizeDblClick = new SlickEvent("onColumnsResizeDblClick", externalPubSub), this.onCompositeEditorChange = new SlickEvent("onCompositeEditorChange", externalPubSub), this.onContextMenu = new SlickEvent("onContextMenu", externalPubSub), this.onDrag = new SlickEvent("onDrag", externalPubSub), this.onDblClick = new SlickEvent("onDblClick", externalPubSub), this.onDragInit = new SlickEvent("onDragInit", externalPubSub), this.onDragStart = new SlickEvent("onDragStart", externalPubSub), this.onDragEnd = new SlickEvent("onDragEnd", externalPubSub), this.onFooterClick = new SlickEvent("onFooterClick", externalPubSub), this.onFooterContextMenu = new SlickEvent("onFooterContextMenu", externalPubSub), this.onFooterRowCellRendered = new SlickEvent("onFooterRowCellRendered", externalPubSub), this.onHeaderCellRendered = new SlickEvent("onHeaderCellRendered", externalPubSub), this.onHeaderClick = new SlickEvent("onHeaderClick", externalPubSub), this.onHeaderContextMenu = new SlickEvent("onHeaderContextMenu", externalPubSub), this.onHeaderMouseEnter = new SlickEvent("onHeaderMouseEnter", externalPubSub), this.onHeaderMouseLeave = new SlickEvent("onHeaderMouseLeave", externalPubSub), this.onHeaderRowCellRendered = new SlickEvent("onHeaderRowCellRendered", externalPubSub), this.onHeaderRowMouseEnter = new SlickEvent("onHeaderRowMouseEnter", externalPubSub), this.onHeaderRowMouseLeave = new SlickEvent("onHeaderRowMouseLeave", externalPubSub), this.onPreHeaderClick = new SlickEvent("onPreHeaderClick", externalPubSub), this.onPreHeaderContextMenu = new SlickEvent("onPreHeaderContextMenu", externalPubSub), this.onKeyDown = new SlickEvent("onKeyDown", externalPubSub), this.onMouseEnter = new SlickEvent("onMouseEnter", externalPubSub), this.onMouseLeave = new SlickEvent("onMouseLeave", externalPubSub), this.onRendered = new SlickEvent("onRendered", externalPubSub), this.onScroll = new SlickEvent("onScroll", externalPubSub), this.onSelectedRowsChanged = new SlickEvent("onSelectedRowsChanged", externalPubSub), this.onSetOptions = new SlickEvent("onSetOptions", externalPubSub), this.onActivateChangedOptions = new SlickEvent("onActivateChangedOptions", externalPubSub), this.onSort = new SlickEvent("onSort", externalPubSub), this.onValidationError = new SlickEvent("onValidationError", externalPubSub), this.onViewportChanged = new SlickEvent("onViewportChanged", externalPubSub), this.initialize(options); } ////////////////////////////////////////////////////////////////////////////////////////////// // Grid and Dom Initialisation ////////////////////////////////////////////////////////////////////////////////////////////// /** Initializes the grid. */ init() { this.finishInitialization(); } /** * Processes the provided grid options (mixing in default settings as needed), * validates required modules (for example, ensuring Sortable.js is loaded if column reordering is enabled), * and creates all necessary DOM elements for the grid (including header containers, viewports, canvases, panels, etc.). * It also caches CSS if the container or its ancestors are hidden and calls finish. * * @param {Partial<O>} options - Partial grid options to be applied during initialization. */ initialize(options) { if (options != null && options.mixinDefaults ? (this._options || (this._options = options), Utils.applyDefaults(this._options, this._defaults)) : this._options = Utils.extend(!0, {}, this._defaults, options), this.scrollThrottle = this.actionThrottle(this.render.bind(this), this._options.scrollRenderThrottling), this.maxSupportedCssHeight = this.maxSupportedCssHeight || this.getMaxSupportedCssHeight(), this.validateAndEnforceOptions(), this._columnDefaults.width = this._options.defaultColumnWidth, this._options.suppressCssChangesOnHiddenInit || this.cacheCssForHiddenInit(), this.updateColumnProps(), this._options.enableColumnReorder && (!Sortable || !Sortable.create)) throw new Error("SlickGrid requires Sortable.js module to be loaded"); this.editController = { commitCurrentEdit: this.commitCurrentEdit.bind(this), cancelCurrentEdit: this.cancelCurrentEdit.bind(this) }, Utils.emptyElement(this._container), this._container.style.outline = String(0), this._container.classList.add(this.uid), this._container.classList.add("ui-widget"), this._container.setAttribute("role", "grid"); let containerStyles = window.getComputedStyle(this._container); /relative|absolute|fixed/.test(containerStyles.position) || (this._container.style.position = "relative"), this._focusSink = Utils.createDomElement("div", { tabIndex: 0, style: { position: "fixed", width: "0px", height: "0px", top: "0px", left: "0px", outline: "0px" } }, this._container), this._options.createTopHeaderPanel && (this._topHeaderPanelScroller = Utils.createDomElement("div", { className: "slick-topheader-panel slick-state-default", style: { overflow: "hidden", position: "relative" } }, this._container), this._topHeaderPanelScroller.appendChild(document.createElement("div")), this._topHeaderPanel = Utils.createDomElement("div", null, this._topHeaderPanelScroller), this._topHeaderPanelSpacer = Utils.createDomElement("div", { style: { display: "block", height: "1px", position: "absolute", top: "0px", left: "0px" } }, this._topHeaderPanelScroller), this._options.showTopHeaderPanel || Utils.hide(this._topHeaderPanelScroller)), this._paneHeaderL = Utils.createDomElement("div", { className: "slick-pane slick-pane-header slick-pane-left", tabIndex: 0 }, this._container), this._paneHeaderR = Utils.createDomElement("div", { className: "slick-pane slick-pane-header slick-pane-right", tabIndex: 0 }, this._container), this._paneTopL = Utils.createDomElement("div", { className: "slick-pane slick-pane-top slick-pane-left", tabIndex: 0 }, this._container), this._paneTopR = Utils.createDomElement("div", { className: "slick-pane slick-pane-top slick-pane-right", tabIndex: 0 }, this._container), this._paneBottomL = Utils.createDomElement("div", { className: "slick-pane slick-pane-bottom slick-pane-left", tabIndex: 0 }, this._container), this._paneBottomR = Utils.createDomElement("div", { className: "slick-pane slick-pane-bottom slick-pane-right", tabIndex: 0 }, this._container), this._options.createPreHeaderPanel && (this._preHeaderPanelScroller = Utils.createDomElement("div", { className: "slick-preheader-panel ui-state-default slick-state-default", style: { overflow: "hidden", position: "relative" } }, this._paneHeaderL), this._preHeaderPanelScroller.appendChild(document.createElement("div")), this._preHeaderPanel = Utils.createDomElement("div", null, this._preHeaderPanelScroller), this._preHeaderPanelSpacer = Utils.createDomElement("div", { style: { display: "block", height: "1px", position: "absolute", top: "0px", left: "0px" } }, this._preHeaderPanelScroller), this._preHeaderPanelScrollerR = Utils.createDomElement("div", { className: "slick-preheader-panel ui-state-default slick-state-default", style: { overflow: "hidden", position: "relative" } }, this._paneHeaderR), this._preHeaderPanelR = Utils.createDomElement("div", null, this._preHeaderPanelScrollerR), this._preHeaderPanelSpacerR = Utils.createDomElement("div", { style: { display: "block", height: "1px", position: "absolute", top: "0px", left: "0px" } }, this._preHeaderPanelScrollerR), this._options.showPreHeaderPanel || (Utils.hide(this._preHeaderPanelScroller), Utils.hide(this._preHeaderPanelScrollerR))), this._headerScrollerL = Utils.createDomElement("div", { className: "slick-header ui-state-default slick-state-default slick-header-left" }, this._paneHeaderL), this._headerScrollerR = Utils.createDomElement("div", { className: "slick-header ui-state-default slick-state-default slick-header-right" }, this._paneHeaderR), this._headerScroller.push(this._headerScrollerL), this._headerScroller.push(this._headerScrollerR), this._headerL = Utils.createDomElement("div", { className: "slick-header-columns slick-header-columns-left", role: "row", style: { left: "-1000px" } }, this._headerScrollerL), this._headerR = Utils.createDomElement("div", { className: "slick-header-columns slick-header-columns-right", role: "row", style: { left: "-1000px" } }, this._headerScrollerR), this._headers = [this._headerL, this._headerR], this._headerRowScrollerL = Utils.createDomElement("div", { className: "slick-headerrow ui-state-default slick-state-default" }, this._paneTopL), this._headerRowScrollerR = Utils.createDomElement("div", { className: "slick-headerrow ui-state-default slick-state-default" }, this._paneTopR), this._headerRowScroller = [this._headerRowScrollerL, this._headerRowScrollerR], this._headerRowSpacerL = Utils.createDomElement("div", { style: { display: "block", height: "1px", position: "absolute", top: "0px", left: "0px" } }, this._headerRowScrollerL), this._headerRowSpacerR = Utils.createDomElement("div", { style: { display: "block", height: "1px", position: "absolute", top: "0px", left: "0px" } }, this._headerRowScrollerR), this._headerRowL = Utils.createDomElement("div", { className: "slick-headerrow-columns slick-headerrow-columns-left" }, this._headerRowScrollerL), this._headerRowR = Utils.createDomElement("div", { className: "slick-headerrow-columns slick-headerrow-columns-right" }, this._headerRowScrollerR), this._headerRows = [this._headerRowL, this._headerRowR], this._topPanelScrollerL = Utils.createDomElement("div", { className: "slick-top-panel-scroller ui-state-default slick-state-default" }, this._paneTopL), this._topPanelScrollerR = Utils.createDomElement("div", { className: "slick-top-panel-scroller ui-state-default slick-state-default" }, this._paneTopR), this._topPanelScrollers = [this._topPanelScrollerL, this._topPanelScrollerR], this._topPanelL = Utils.createDomElement("div", { className: "slick-top-panel", style: { width: "10000px" } }, this._topPanelScrollerL), this._topPanelR = Utils.createDomElement("div", { className: "slick-top-panel", style: { width: "10000px" } }, this._topPanelScrollerR), this._topPanels = [this._topPanelL, this._topPanelR], this._options.showColumnHeader || this._headerScroller.forEach((el) => { Utils.hide(el); }), this._options.showTopPanel || this._topPanelScrollers.forEach((scroller) => { Utils.hide(scroller); }), this._options.showHeaderRow || this._headerRowScroller.forEach((scroller) => { Utils.hide(scroller); }), this._viewportTopL = Utils.createDomElement("div", { className: "slick-viewport slick-viewport-top slick-viewport-left", tabIndex: 0 }, this._paneTopL), this._viewportTopR = Utils.createDomElement("div", { className: "slick-viewport slick-viewport-top slick-viewport-right", tabIndex: 0 }, this._paneTopR), this._viewportBottomL = Utils.createDomElement("div", { className: "slick-viewport slick-viewport-bottom slick-viewport-left", tabIndex: 0 }, this._paneBottomL), this._viewportBottomR = Utils.createDomElement("div", { className: "slick-viewport slick-viewport-bottom slick-viewport-right", tabIndex: 0 }, this._paneBottomR), this._viewport = [this._viewportTopL, this._viewportTopR, this._viewportBottomL, this._viewportBottomR], this._options.viewportClass && this._viewport.forEach((view) => { view.classList.add(...Utils.classNameToList(this._options.viewportClass)); }), this._activeViewportNode = this._viewportTopL, this._canvasTopL = Utils.createDomElement("div", { className: "grid-canvas grid-canvas-top grid-canvas-left", tabIndex: 0 }, this._viewportTopL), this._canvasTopR = Utils.createDomElement("div", { className: "grid-canvas grid-canvas-top grid-canvas-right", tabIndex: 0 }, this._viewportTopR), this._canvasBottomL = Utils.createDomElement("div", { className: "grid-canvas grid-canvas-bottom grid-canvas-left", tabIndex: 0 }, this._viewportBottomL), this._canvasBottomR = Utils.createDomElement("div", { className: "grid-canvas grid-canvas-bottom grid-canvas-right", tabIndex: 0 }, this._viewportBottomR), this._canvas = [this._canvasTopL, this._canvasTopR, this._canvasBottomL, this._canvasBottomR], this.scrollbarDimensions = this.scrollbarDimensions || this.measureScrollbar(); let canvasWithScrollbarWidth = this.getCanvasWidth() + this.scrollbarDimensions.width; this._activeCanvasNode = this._canvasTopL, this._topHeaderPanelSpacer && Utils.width(this._topHeaderPanelSpacer, canvasWithScrollbarWidth), this._preHeaderPanelSpacer && Utils.width(this._preHeaderPanelSpacer, canvasWithScrollbarWidth), this._headers.forEach((el) => { Utils.width(el, this.getHeadersWidth()); }), Utils.width(this._headerRowSpacerL, canvasWithScrollbarWidth), Utils.width(this._headerRowSpacerR, canvasWithScrollbarWidth), this._options.createFooterRow && (this._footerRowScrollerR = Utils.createDomElement("div", { className: "slick-footerrow ui-state-default slick-state-default" }, this._paneTopR), this._footerRowScrollerL = Utils.createDomElement("div", { className: "slick-footerrow ui-state-default slick-state-default" }, this._paneTopL), this._footerRowScroller = [this._footerRowScrollerL, this._footerRowScrollerR], this._footerRowSpacerL = Utils.createDomElement("div", { style: { display: "block", height: "1px", position: "absolute", top: "0px", left: "0px" } }, this._footerRowScrollerL), Utils.width(this._footerRowSpacerL, canvasWithScrollbarWidth), this._footerRowSpacerR = Utils.createDomElement("div", { style: { display: "block", height: "1px", position: "absolute", top: "0px", left: "0px" } }, this._footerRowScrollerR), Utils.width(this._footerRowSpacerR, canvasWithScrollbarWidth), this._footerRowL = Utils.createDomElement("div", { className: "slick-footerrow-columns slick-footerrow-columns-left" }, this._footerRowScrollerL), this._footerRowR = Utils.createDomElement("div", { className: "slick-footerrow-columns slick-footerrow-columns-right" }, this._footerRowScrollerR), this._footerRow = [this._footerRowL, this._footerRowR], this._options.showFooterRow || this._footerRowScroller.forEach((scroller) => { Utils.hide(scroller); })), this._focusSink2 = this._focusSink.cloneNode(!0), this._container.appendChild(this._focusSink2), this._options.explicitInitialization || this.finishInitialization(); } /** * Completes grid initialisation by calculating viewport dimensions, measuring cell padding and border differences, * disabling text selection (except on editable inputs), setting frozen options and pane visibility, * updating column caches, creating column headers and footers, setting up column sorting, * creating CSS rules, binding ancestor scroll events, and binding various event handlers * (e.g. for scrolling, mouse, keyboard, drag-and-drop). * It also starts up any asynchronous post–render processing if enabled. */ finishInitialization() { this.initialized || (this.initialized = !0, this.getViewportWidth(), this.getViewportHeight(), this.measureCellPaddingAndBorder(), this.disableSelection(this._headers), this._options.enableTextSelectionOnCells || this._viewport.forEach((view) => { this._bindingEventService.bind(view, "selectstart", (event) => { event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement; }); }), 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({ element: view, onMouseWheel: this.handleMouseWheel.bind(this) })); }), this._headerScroller.forEach((el) => { this._bindingEventService.bind(el, "contextmenu", this.handleHeaderContextMenu.bind(this)), this._bindingEventService.bind(el, "click", this.handleHeaderClick.bind(this)); }), this._headerRowScroller.forEach((scroller) => { this._bindingEventService.bind(scroller, "scroll", this.handleHeaderRowScroll.bind(this)); }), this._options.createFooterRow && (this._footerRow.forEach((footer) => { this._bindingEventService.bind(footer, "contextmenu", this.handleFooterContextMenu.bind(this)), this._bindingEventService.bind(footer, "click", this.handleFooterClick.bind(this)); }), this._footerRowScroller.forEach((scroller) => { this._bindingEventService.bind(scroller, "scroll", this.handleFooterRowScroll.bind(this)); })), this._options.createTopHeaderPanel && this._bindingEventService.bind(this._topHeaderPanelScroller, "scroll", this.handleTopHeaderPanelScroll.bind(this)), this._options.createPreHeaderPanel && (this._bindingEventService.bind(this._preHeaderPanelScroller, "scroll", this.handlePreHeaderPanelScroll.bind(this)), this._bindingEventService.bind(this._preHeaderPanelScroller, "contextmenu", this.handlePreHeaderContextMenu.bind(this)), this._bindingEventService.bind(this._preHeaderPanelScrollerR, "contextmenu", this.handlePreHeaderContextMenu.bind(this)), this._bindingEventService.bind(this._preHeaderPanelScroller, "click", this.handlePreHeaderClick.bind(this)), this._bindingEventService.bind(this._preHeaderPanelScrollerR, "click", this.handlePreHeaderClick.bind(this))), this._bindingEventService.bind(this._focusSink, "keydown", this.handleKeyDown.bind(this)), this._bindingEventService.bind(this._focusSink2, "keydown", this.handleKeyDown.bind(this)), this._canvas.forEach((element) => { this._bindingEventService.bind(element, "keydown", this.handleKeyDown.bind(this)), this._bindingEventService.bind(element, "click", this.handleClick.bind(this)), this._bindingEventService.bind(element, "dblclick", this.handleDblClick.bind(this)), this._bindingEventService.bind(element, "contextmenu", this.handleContextMenu.bind(this)), this._bindingEventService.bind(element, "mouseover", this.handleCellMouseOver.bind(this)), this._bindingEventService.bind(element, "mouseout", this.handleCellMouseOut.bind(this)); }), Draggable && (this.slickDraggableInstance = Draggable({ containerElement: this._container, allowDragFrom: "div.slick-cell", // the slick cell parent must always contain `.dnd` and/or `.cell-reorder` class to be identified as draggable allowDragFromClosest: "div.slick-cell.dnd, div.slick-cell.cell-reorder", preventDragFromKeys: this._options.preventDragFromKeys, onDragInit: this.handleDragInit.bind(this), onDragStart: this.handleDragStart.bind(this), onDrag: this.handleDrag.bind(this), onDragEnd: this.handleDragEnd.bind(this) })), this._options.suppressCssChangesOnHiddenInit || this.restoreCssFromHiddenInit()); } /** * Finds all container ancestors/parents (including the grid container itself) that are hidden (i.e. have display:none) * and temporarily applies visible CSS properties (absolute positioning, hidden visibility, block display) * so that dimensions can be measured correctly. * It stores the original CSS properties in an internal array for later restoration. * * Related to issue: https://github.com/6pac/SlickGrid/issues/568 */ cacheCssForHiddenInit() { this._hiddenParents = Utils.parents(this._container, ":hidden"), this.oldProps = [], this._hiddenParents.forEach((el) => { let old = {}; Object.keys(this.cssShow).forEach((name) => { this.cssShow && (old[name] = el.style[name], el.style[name] = this.cssShow[name]); }), this.oldProps.push(old); }); } /** * Restores the original CSS properties for the container and its hidden * ancestors that were modified by cacheCssForHiddenInit. * This ensures that after initial measurements the DOM elements revert * to their original style settings. */ restoreCssFromHiddenInit() { let i = 0; this._hiddenParents && (this._hiddenParents.forEach((el) => { let old = this.oldProps[i++]; Object.keys(this.cssShow).forEach((name) => { this.cssShow && (el.style[name] = old[name]); }); }), this._hiddenParents = []); } /** * Registers an external plugin to the grid’s internal plugin list. * Once added, it immediately initialises the plugin by calling its init() * method with the grid instance. * @param {T} plugin - The plugin instance to be registered. */ registerPlugin(plugin) { this.plugins.unshift(plugin), plugin.init(this); } /** * Unregister (destroy) an external Plugin. * Searches for the specified plugin in the grid’s plugin list. * When found, it calls the plugin’s destroy() method and removes the plugin from the list, * thereby unregistering it from the grid. * @param {T} plugin - The plugin instance to be registered. */ unregisterPlugin(plugin) { var _a; for (let i = this.plugins.length; i >= 0; i--) if (this.plugins[i] === plugin) { (_a = this.plugins[i]) == null || _a.destroy(), this.plugins.splice(i, 1); break; } } /** * Destroy (dispose) of SlickGrid * * Unbinds all event handlers, cancels any active cell edits, triggers the onBeforeDestroy event, * unregisters and destroys plugins, destroys sortable and other interaction instances, * unbinds ancestor scroll events, removes CSS rules, unbinds events from all key DOM elements * (canvas, viewports, header, footer, etc.), empties the grid container, removes the grid’s uid class, * and clears all timers. Optionally, if shouldDestroyAllElements is true, * calls destroyAllElements to nullify all DOM references. * * @param {boolean} shouldDestroyAllElements - do we want to destroy (nullify) all DOM elements as well? This help in avoiding mem leaks */ destroy(shouldDestroyAllElements) { var _a, _b, _c, _d; this._bindingEventService.unbindAll(), this.slickDraggableInstance = this.destroyAllInstances(this.slickDraggableInstance), this.slickMouseWheelInstances = this.destroyAllInstances(this.slickMouseWheelInstances), this.slickResizableInstances = this.destroyAllInstances(this.slickResizableInstances), (_a = this.getEditorLock()) == null || _a.cancelCurrentEdit(), this.trigger(this.onBeforeDestroy, {}); let i = this.plugins.length; for (; i--; ) this.unregisterPlugin(this.plugins[i]); this._options.enableColumnReorder && typeof ((_b = this.sortableSideLeftInstance) == null ? void 0 : _b.destroy) == "function" && ((_c = this.sortableSideLeftInstance) == null || _c.destroy(), (_d = this.sortableSideRightInstance) == null || _d.destroy()), this.unbindAncestorScrollEvents(), this._bindingEventService.unbindByEventName(this._container, "resize"), this.removeCssRules(), this._canvas.forEach((element) => { this._bindingEventService.unbindByEventName(element, "keydown"), this._bindingEventService.unbindByEventName(element, "click"), this._bindingEventService.unbindByEventName(element, "dblclick"), this._bindingEventService.unbindByEventName(element, "contextmenu"), this._bindingEventService.unbindByEventName(element, "mouseover"), this._bindingEventService.unbindByEventName(element, "mouseout"); }), this._viewport.forEach((view) => { this._bindingEventService.unbindByEventName(view, "scroll"); }), this._headerScroller.forEach((el) => { this._bindingEventService.unbindByEventName(el, "contextmenu"), this._bindingEventService.unbindByEventName(el, "click"); }), this._headerRowScroller.forEach((scroller) => { this._bindingEventService.unbindByEventName(scroller, "scroll"); }), this._footerRow && this._footerRow.forEach((footer) => { this._bindingEventService.unbindByEventName(footer, "contextmenu"), this._bindingEventService.unbindByEventName(footer, "click"); }), this._footerRowScroller && this._footerRowScroller.forEach((scroller) => { this._bindingEventService.unbindByEventName(scroller, "scroll"); }), this._preHeaderPanelScroller && this._bindingEventService.unbindByEventName(this._preHeaderPanelScroller, "scroll"), this._topHeaderPanelScroller && this._bindingEventService.unbindByEventName(this._topHeaderPanelScroller, "scroll"), this._bindingEventService.unbindByEventName(this._focusSink, "keydown"), this._bindingEventService.unbindByEventName(this._focusSink2, "keydown"); let resizeHandles = this._container.querySelectorAll(".slick-resizable-handle"); [].forEach.call(resizeHandles, (handle) => { this._bindingEventService.unbindByEventName(handle, "dblclick"); }); let headerColumns = this._container.querySelectorAll(".slick-header-column"); [].forEach.call(headerColumns, (column) => { this._bindingEventService.unbindByEventName(column, "mouseenter"), this._bindingEventService.unbindByEventName(column, "mouseleave"), this._bindingEventService.unbindByEventName(column, "mouseenter"), this._bindingEventService.unbindByEventName(column, "mouseleave"); }), Utils.emptyElement(this._container), this._container.classList.remove(this.uid), this.clearAllTimers(), shouldDestroyAllElements && this.destroyAllElements(); } /** * Call destroy method, when exists, on all the instance(s) it found * * Given either a single instance or an array of instances (e.g. draggable, mousewheel, resizable), * pops each one and calls its destroy method if available, then resets the input to an empty array * (or null for a single instance). Returns the reset value. * * @params instances - can be a single instance or a an array of instances */ destroyAllInstances(inputInstances) { if (inputInstances) { let instances = Array.isArray(inputInstances) ? inputInstances : [inputInstances], instance; for (; Utils.isDefined(instance = instances.pop()); ) instance && typeof instance.destroy == "function" && instance.destroy(); } return inputInstances = Array.isArray(inputInstances) ? [] : null, inputInstances; } /** * Sets all internal references to DOM elements * (e.g. canvas containers, headers, viewports, focus sinks, etc.) * to null so that they can be garbage collected. */ destroyAllElements() { this._activeCanvasNode = null, this._activeViewportNode = null, this._boundAncestors = null, this._canvas = null, this._canvasTopL = null, this._canvasTopR = null, this._canvasBottomL = null, this._canvasBottomR = null, this._container = null, this._focusSink = null, this._focusSink2 = null, this._groupHeaders = null, this._groupHeadersL = null, this._groupHeadersR = null, this._headerL = null, this._headerR = null, this._headers = null, this._headerRows = null, this._headerRowL = null, this._headerRowR = null, this._headerRowSpacerL = null, this._headerRowSpacerR = null, this._headerRowScrollContainer = null, this._headerRowScroller = null, this._headerRowScrollerL = null, this._headerRowScrollerR = null, this._headerScrollContainer = null, this._headerScroller = null, this._headerScrollerL = null, this._headerScrollerR = null, this._hiddenParents = null, this._footerRow = null, this._footerRowL = null, this._footerRowR = null, this._footerRowSpacerL = null, this._footerRowSpacerR = null, this._footerRowScroller = null, this._footerRowScrollerL = null, this._footerRowScrollerR = null, this._footerRowScrollContainer = null, this._preHeaderPanel = null, this._preHeaderPanelR = null, this._preHeaderPanelScroller = null, this._preHeaderPanelScrollerR = null, this._preHeaderPanelSpacer = null, this._preHeaderPanelSpacerR = null, this._topPanels = null, this._topPanelScrollers = null, this._style = null, this._topPanelScrollerL = null, this._topPanelScrollerR = null, this._topPanelL = null, this._topPanelR = null, this._paneHeaderL = null, this._paneHeaderR = null, this._paneTopL = null, this._paneTopR = null, this._paneBottomL = null, this._paneBottomR = null, this._viewport = null, this._viewportTopL = null, this._viewportTopR = null, this._viewportBottomL = null, this._viewportBottomR = null, this._viewportScrollContainerX = null, this._viewportScrollContainerY = null; } /** Returns an object containing all of the Grid options set on the grid. See a list of Grid Options here. */ getOptions() { return this._options; } /** * Extends grid options with a given hash. If an there is an active edit, the grid will attempt to commit the changes and only continue if the attempt succeeds. * @param {Object} options - an object with configuration options. * @param {Boolean} [suppressRender] - do we want to supress the grid re-rendering? (defaults to false) * @param {Boolean} [suppressColumnSet] - do we want to supress the columns set, via "setColumns()" method? (defaults to false) * @param {Boolean} [suppressSetOverflow] - do we want to suppress the call to `setOverflow` */ setOptions(newOptions, suppressRender, suppressColumnSet, suppressSetOverflow) { this.prepareForOptionsChange(), this._options.enableAddRow !== newOptions.enableAddRow && this.invalidateRow(this.getDataLength()), newOptions.frozenColumn !== void 0 && newOptions.frozenColumn >= 0 && (this.getViewports().forEach((vp) => vp.scrollLeft = 0), this.handleScroll()); let originalOptions = Utils.extend(!0, {}, this._options); this._options = Utils.extend(this._options, newOptions), this.trigger(this.onSetOptions, { opt