UNPKG

slickgrid

Version:

A lightning fast JavaScript grid/spreadsheet

652 lines (651 loc) 219 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), 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.9.0"); /** optional grid state clientId */ __publicField(this, "cid", ""); // Events __publicField(this, "onActiveCellChanged"); __publicField(this, "onActiveCellPositionChanged"); __publicField(this, "onAddNewRow"); __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, "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, "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, showPreHeaderPanel: !1, preHeaderPanelHeight: 25, showTopPanel: !1, topPanelHeight: 25, formatterFactory: null, editorFactory: null, cellFlashingCssClass: "flashing", rowHighlightCssClass: "highlight-animate", rowHighlightDuration: 400, selectedCellCssClass: "selected", multiSelect: !0, 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, 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, scrollRenderThrottling: 50, autosizeTextAvgToMWidthRatio: 0.75, viewportSwitchToScrollModeWidthPercent: void 0, viewportMinWidthPx: void 0, viewportMaxWidthPx: void 0, suppressCssChangesOnHiddenInit: !1, ffMaxSupportedCssHeight: 6e6, maxSupportedCssHeight: 1e9, 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, "_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, "activeRow"); __publicField(this, "activeCell"); __publicField(this, "activeCellNode", null); __publicField(this, "currentEditor", null); __publicField(this, "serializedEditorValue"); __publicField(this, "editController"); __publicField(this, "rowsCache", {}); __publicField(this, "renderedRows", 0); __publicField(this, "numVisibleRows", 0); __publicField(this, "prevScrollTop", 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", null); __publicField(this, "h_render", null); __publicField(this, "h_postrender", null); __publicField(this, "h_postrenderCleanup", null); __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.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.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.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); } ////////////////////////////////////////////////////////////////////////////////////////////// // Initialization /** Initializes the grid. */ init() { this.finishInitialization(); } /** * Apply HTML code by 3 different ways depending on what is provided as input and what options are enabled. * 1. value is an HTMLElement or DocumentFragment, then first empty the target and simply append the HTML to the target element. * 2. value is string and `enableHtmlRendering` is enabled, then use `target.innerHTML = value;` * 3. value is string and `enableHtmlRendering` is disabled, then use `target.textContent = value;` * @param target - target element to apply to * @param val - input value can be either a string or an HTMLElement * @param options - * `emptyTarget`, defaults to true, will empty the target. * `skipEmptyReassignment`, defaults to true, when enabled it will not try to reapply an empty value when the target is already empty */ applyHtmlCode(target, val, options) { if (target) if (val instanceof HTMLElement || val instanceof DocumentFragment) (options == null ? void 0 : options.emptyTarget) !== !1 && Utils.emptyElement(target), target.appendChild(val); else { if ((options == null ? void 0 : options.skipEmptyReassignment) !== !1 && !Utils.isDefined(val) && !target.innerHTML) return; let sanitizedText = val; typeof sanitizedText == "number" || typeof sanitizedText == "boolean" ? target.textContent = sanitizedText : (sanitizedText = this.sanitizeHtmlString(val), this._options.enableHtmlRendering && sanitizedText ? target.innerHTML = sanitizedText : target.textContent = sanitizedText); } } 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.overflow = "hidden", 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._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(), this._activeCanvasNode = this._canvasTopL, this._preHeaderPanelSpacer && Utils.width(this._preHeaderPanelSpacer, this.getCanvasWidth() + this.scrollbarDimensions.width), this._headers.forEach((el) => { Utils.width(el, this.getHeadersWidth()); }), Utils.width(this._headerRowSpacerL, this.getCanvasWidth() + this.scrollbarDimensions.width), Utils.width(this._headerRowSpacerR, this.getCanvasWidth() + this.scrollbarDimensions.width), 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, this.getCanvasWidth() + this.scrollbarDimensions.width), this._footerRowSpacerR = Utils.createDomElement("div", { style: { display: "block", height: "1px", position: "absolute", top: "0px", left: "0px" } }, this._footerRowScrollerR), Utils.width(this._footerRowSpacerR, this.getCanvasWidth() + this.scrollbarDimensions.width), 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(); } 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.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.createPreHeaderPanel && this._bindingEventService.bind(this._preHeaderPanelScroller, "scroll", this.handlePreHeaderPanelScroll.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", 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()); } /** handles "display:none" on container or container parents, related to issue: https://github.com/6pac/SlickGrid/issues/568 */ cacheCssForHiddenInit() { this._hiddenParents = Utils.parents(this._container, ":hidden"), 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); }); } 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]); }); }); } hasFrozenColumns() { return this._options.frozenColumn > -1; } /** Register an external Plugin */ registerPlugin(plugin) { this.plugins.unshift(plugin), plugin.init(this); } /** Unregister (destroy) an external Plugin */ 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; } } /** Get a Plugin (addon) by its name */ getPluginByName(name) { var _a; for (let i = this.plugins.length - 1; i >= 0; i--) if (((_a = this.plugins[i]) == null ? void 0 : _a.pluginName) === name) return this.plugins[i]; } /** * Unregisters a current selection model and registers a new one. See the definition of SelectionModel for more information. * @param {Object} selectionModel A SelectionModel. */ setSelectionModel(model) { this.selectionModel && (this.selectionModel.onSelectedRangesChanged.unsubscribe(this.handleSelectedRangesChanged.bind(this)), this.selectionModel.destroy && this.selectionModel.destroy()), this.selectionModel = model, this.selectionModel && (this.selectionModel.init(this), this.selectionModel.onSelectedRangesChanged.subscribe(this.handleSelectedRangesChanged.bind(this))); } /** Returns the current SelectionModel. See here for more information about SelectionModels. */ getSelectionModel() { return this.selectionModel; } /** Get Grid Canvas Node DOM Element */ getCanvasNode(columnIdOrIdx, rowIndex) { return this._getContainerElement(this.getCanvases(), columnIdOrIdx, rowIndex); } /** Get the canvas DOM element */ getActiveCanvasNode(e) { return e === void 0 ? this._activeCanvasNode : (e instanceof SlickEventData && (e = e.getNativeEvent()), this._activeCanvasNode = e == null ? void 0 : e.target.closest(".grid-canvas"), this._activeCanvasNode); } /** Get the canvas DOM element */ getCanvases() { return this._canvas; } /** Get the Viewport DOM node element */ getViewportNode(columnIdOrIdx, rowIndex) { return this._getContainerElement(this.getViewports(), columnIdOrIdx, rowIndex); } /** Get all the Viewport node elements */ getViewports() { return this._viewport; } getActiveViewportNode(e) { return this.setActiveViewportNode(e), this._activeViewportNode; } /** Sets an active viewport node */ setActiveViewportNode(e) { return e instanceof SlickEventData && (e = e.getNativeEvent()), this._activeViewportNode = e == null ? void 0 : e.target.closest(".slick-viewport"), this._activeViewportNode; } _getContainerElement(targetContainers, columnIdOrIdx, rowIndex) { if (!targetContainers) return; columnIdOrIdx || (columnIdOrIdx = 0), rowIndex || (rowIndex = 0); let idx = typeof columnIdOrIdx == "number" ? columnIdOrIdx : this.getColumnIndex(columnIdOrIdx), isBottomSide = this.hasFrozenRows && rowIndex >= this.actualFrozenRow + (this._options.frozenBottom ? 0 : 1), isRightSide = this.hasFrozenColumns() && idx > this._options.frozenColumn; return targetContainers[(isBottomSide ? 2 : 0) + (isRightSide ? 1 : 0)]; } measureScrollbar() { let className = ""; this._viewport.forEach((v) => className += v.className); let outerdiv = Utils.createDomElement("div", { className, style: { position: "absolute", top: "-10000px", left: "-10000px", overflow: "auto", width: "100px", height: "100px" } }, document.body), innerdiv = Utils.createDomElement("div", { style: { width: "200px", height: "200px", overflow: "auto" } }, outerdiv), dim = { width: outerdiv.offsetWidth - outerdiv.clientWidth, height: outerdiv.offsetHeight - outerdiv.clientHeight }; return innerdiv.remove(), outerdiv.remove(), dim; } /** Get the headers width in pixel */ getHeadersWidth() { var _a, _b, _c, _d, _e, _f, _g, _h; this.headersWidth = this.headersWidthL = this.headersWidthR = 0; let includeScrollbar = !this._options.autoHeight, i = 0, ii = this.columns.length; for (i = 0; i < ii; i++) { if (!this.columns[i] || this.columns[i].hidden) continue; let width = this.columns[i].width; this._options.frozenColumn > -1 && i > this._options.frozenColumn ? this.headersWidthR += width || 0 : this.headersWidthL += width || 0; } return includeScrollbar && (this._options.frozenColumn > -1 && i > this._options.frozenColumn ? this.headersWidthR += (_b = (_a = this.scrollbarDimensions) == null ? void 0 : _a.width) != null ? _b : 0 : this.headersWidthL += (_d = (_c = this.scrollbarDimensions) == null ? void 0 : _c.width) != null ? _d : 0), this.hasFrozenColumns() ? (this.headersWidthL = this.headersWidthL + 1e3, this.headersWidthR = Math.max(this.headersWidthR, this.viewportW) + this.headersWidthL, this.headersWidthR += (_f = (_e = this.scrollbarDimensions) == null ? void 0 : _e.width) != null ? _f : 0) : (this.headersWidthL += (_h = (_g = this.scrollbarDimensions) == null ? void 0 : _g.width) != null ? _h : 0, this.headersWidthL = Math.max(this.headersWidthL, this.viewportW) + 1e3), this.headersWidth = this.headersWidthL + this.headersWidthR, Math.max(this.headersWidth, this.viewportW) + 1e3; } /** Get the grid canvas width */ getCanvasWidth() { var _a, _b; let availableWidth = this.viewportHasVScroll ? this.viewportW - ((_b = (_a = this.scrollbarDimensions) == null ? void 0 : _a.width) != null ? _b : 0) : this.viewportW, i = this.columns.length; for (this.canvasWidthL = this.canvasWidthR = 0; i--; ) !this.columns[i] || this.columns[i].hidden || (this.hasFrozenColumns() && i > this._options.frozenColumn ? this.canvasWidthR += this.columns[i].width || 0 : this.canvasWidthL += this.columns[i].width || 0); let totalRowWidth = this.canvasWidthL + this.canvasWidthR; if (this._options.fullWidthRows) { let extraWidth = Math.max(totalRowWidth, availableWidth) - totalRowWidth; extraWidth > 0 && (totalRowWidth += extraWidth, this.hasFrozenColumns() ? this.canvasWidthR += extraWidth : this.canvasWidthL += extraWidth); } return totalRowWidth; } updateCanvasWidth(forceColumnWidthsUpdate) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; let oldCanvasWidth = this.canvasWidth, oldCanvasWidthL = this.canvasWidthL, oldCanvasWidthR = this.canvasWidthR; this.canvasWidth = this.getCanvasWidth(); let widthChanged = this.canvasWidth !== oldCanvasWidth || this.canvasWidthL !== oldCanvasWidthL || this.canvasWidthR !== oldCanvasWidthR; if (widthChanged || this.hasFrozenColumns() || this.hasFrozenRows) if (Utils.width(this._canvasTopL, this.canvasWidthL), this.getHeadersWidth(), Utils.width(this._headerL, this.headersWidthL), Utils.width(this._headerR, this.headersWidthR), this.hasFrozenColumns()) { let cWidth = Utils.width(this._container) || 0; if (cWidth > 0 && this.canvasWidthL > cWidth && this._options.throwWhenFrozenNotAllViewable) throw new Error("[SlickGrid] Frozen columns cannot be wider than the actual grid container width. Make sure to have less columns freezed or make your grid container wider"); Utils.width(this._canvasTopR, this.canvasWidthR), Utils.width(this._paneHeaderL, this.canvasWidthL), Utils.setStyleSize(this._paneHeaderR, "left", this.canvasWidthL), Utils.setStyleSize(this._paneHeaderR, "width", this.viewportW - this.canvasWidthL), Utils.width(this._paneTopL, this.canvasWidthL), Utils.setStyleSize(this._paneTopR, "left", this.canvasWidthL), Utils.width(this._paneTopR, this.viewportW - this.canvasWidthL), Utils.width(this._headerRowScrollerL, this.canvasWidthL), Utils.width(this._headerRowScrollerR, this.viewportW - this.canvasWidthL), Utils.width(this._headerRowL, this.canvasWidthL), Utils.width(this._headerRowR, this.canvasWidthR), this._options.createFooterRow && (Utils.width(this._footerRowScrollerL, this.canvasWidthL), Utils.width(this._footerRowScrollerR, this.viewportW - this.canvasWidthL), Utils.width(this._footerRowL, this.canvasWidthL), Utils.width(this._footerRowR, this.canvasWidthR)), this._options.createPreHeaderPanel && Utils.width(this._preHeaderPanel, this.canvasWidth), Utils.width(this._viewportTopL, this.canvasWidthL), Utils.width(this._viewportTopR, this.viewportW - this.canvasWidthL), this.hasFrozenRows && (Utils.width(this._paneBottomL, this.canvasWidthL), Utils.setStyleSize(this._paneBottomR, "left", this.canvasWidthL), Utils.width(this._viewportBottomL, this.canvasWidthL), Utils.width(this._viewportBottomR, this.viewportW - this.canvasWidthL), Utils.width(this._canvasBottomL, this.canvasWidthL), Utils.width(this._canvasBottomR, this.canvasWidthR)); } else Utils.width(this._paneHeaderL, "100%"), Utils.width(this._paneTopL, "100%"), Utils.width(this._headerRowScrollerL, "100%"), Utils.width(this._headerRowL, this.canvasWidth), this._options.createFooterRow && (Utils.width(this._footerRowScrollerL, "100%"), Utils.width(this._footerRowL, this.canvasWidth)), this._options.createPreHeaderPanel && Utils.width(this._preHeaderPanel, this.canvasWidth), Utils.width(this._viewportTopL, "100%"), this.hasFrozenRows && (Utils.width(this._viewportBottomL, "100%"), Utils.width(this._canvasBottomL, this.canvasWidthL)); this.viewportHasHScroll = this.canvasWidth >= this.viewportW - ((_b = (_a = this.scrollbarDimensions) == null ? void 0 : _a.width) != null ? _b : 0), Utils.width(this._headerRowSpacerL, this.canvasWidth + (this.viewportHasVScroll && (_d = (_c = this.scrollbarDimensions) == null ? void 0 : _c.width) != null ? _d : 0)), Utils.width(this._headerRowSpacerR, this.canvasWidth + (this.viewportHasVScroll && (_f = (_e = this.scrollbarDimensions) == null ? void 0 : _e.width) != null ? _f : 0)), this._options.createFooterRow && (Utils.width(this._footerRowSpacerL, this.canvasWidth + (this.viewportHasVScroll && (_h = (_g = this.scrollbarDimensions) == null ? void 0 : _g.width) != null ? _h : 0)), Utils.width(this._footerRowSpacerR, this.canvasWidth + (this.viewportHasVScroll && (_j = (_i = this.scrollbarDimensions) == null ? void 0 : _i.width) != null ? _j : 0))), (widthChanged || forceColumnWidthsUpdate) && this.applyColumnWidths(); } disableSelection(target) { target.forEach((el) => { el.setAttribute("unselectable", "on"), el.style.mozUserSelect = "none", this._bindingEventService.bind(el, "selectstart", () => !1); }); } getMaxSupportedCssHeight() { let supportedHeight = 1e6, testUpTo = navigator.userAgent.toLowerCase().match(/firefox/) ? this._options.ffMaxSupportedCssHeight : this._options.maxSupportedCssHeight, div = Utils.createDomElement("div", { style: { display: "hidden" } }, document.body); for (; ; ) { let test = supportedHeight * 2; Utils.height(div, test); let height = Utils.height(div); if (test > testUpTo || height !== test) break; supportedHeight = test; } return div.remove(), supportedHeight; } /** Get grid unique identifier */ getUID() { return this.uid; } /** Get Header Column Width Difference in pixel */ getHeaderColumnWidthDiff() { return this.headerColumnWidthDiff; } /** Get scrollbar dimensions */ getScrollbarDimensions() { return this.scrollbarDimensions; } /** Get the displayed scrollbar dimensions */ getDisplayedScrollbarDimensions() { var _a, _b, _c, _d; return { width: this.viewportHasVScroll && (_b = (_a = this.scrollbarDimensions) == null ? void 0 : _a.width) != null ? _b : 0, height: this.viewportHasHScroll && (_d = (_c = this.scrollbarDimensions) == null ? void 0 : _c.height) != null ? _d : 0 }; } /** Get the absolute column minimum width */ getAbsoluteColumnMinWidth() { return this.absoluteColumnMinWidth; } getPubSubService() { return this._pubSubService; } // TODO: this is static. need to handle page mutation. bindAncestorScrollEvents() { let elem = this.hasFrozenRows && !this._options.frozenBottom ? this._canvasBottomL : this._canvasTopL; for (; (elem = elem.parentNode) !== document.body && elem; ) (el