From d636a2f683d27366a68da405c86a2f249f381c69 Mon Sep 17 00:00:00 2001 From: "lzyme.dev@gmail.com" Date: Mon, 12 Oct 2026 16:32:49 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=89=B4=E5=AE=9A=E8=AE=B0?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist/jhs-enhance.user.js | 24624 ++++++++++++++++++++++++++++++++++++- package.json | 2 +- vite.config.mjs | 4 +- 3 files changed, 24388 insertions(+), 242 deletions(-) diff --git a/dist/jhs-enhance.user.js b/dist/jhs-enhance.user.js index f43a45d..0124032 100644 --- a/dist/jhs-enhance.user.js +++ b/dist/jhs-enhance.user.js @@ -24,7 +24,6 @@ // @exclude https://*seejav*/forum/* // @exclude https://*seejav*/*actresses // @require https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js -// @require https://cdn.jsdelivr.net/npm/tabulator-tables@6.5.2/dist/js/tabulator.min.js // @require https://cdn.jsdelivr.net/npm/layui-layer@1.0.9/dist/layer.min.js // @require https://cdn.jsdelivr.net/npm/blueimp-md5@2.19.0/js/md5.min.js // @require https://cdn.jsdelivr.net/npm/toastify-js@1.12.0/src/toastify.min.js @@ -88,7 +87,6 @@ System.addImportMap({ imports: { - "tabulator-tables": "user:tabulator-tables", "jquery": "user:jquery", "localforage": "user:localforage", "toastify-js": "user:toastify-js", @@ -97,11 +95,6 @@ System.addImportMap({ "qrcodejs": "user:qrcodejs" } }); -System.set("user:tabulator-tables", (() => { - const _ = Tabulator; - ('default' in _) || (_.default = _); - return _ -})()); System.set("user:jquery", (() => { const _ = jQuery; ('default' in _) || (_.default = _); @@ -133,9 +126,9 @@ System.set("user:qrcodejs", (() => { return _ })()); -System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueimp-md5', 'viewerjs', 'qrcodejs', 'tabulator-tables'], (function (exports, module) { +System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueimp-md5', 'viewerjs', 'qrcodejs'], (function (exports, module) { 'use strict'; - var $$1, localforage$1, Toastify$1, md5$1, Viewer$1, QRCode$1, TabulatorFull; + var $$1, localforage$1, Toastify$1, md5$1, Viewer$1, QRCode$1; return { setters: [module => { $$1 = module.default; @@ -149,8 +142,6 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim Viewer$1 = module.default; }, module => { QRCode$1 = module.default; - }, module => { - TabulatorFull = module.TabulatorFull; }], execute: (async function () { @@ -162,6 +153,7 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + var _a; const scriptRel = /* @__PURE__ */ (function detectScriptRel() { const relList = typeof document !== "undefined" && document.createElement("link").relList; return relList && relList.supports && relList.supports("modulepreload") ? "modulepreload" : "preload"; @@ -198,21 +190,21 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) { return; } - const link = document.createElement("link"); - link.rel = isCss ? "stylesheet" : scriptRel; + const link2 = document.createElement("link"); + link2.rel = isCss ? "stylesheet" : scriptRel; if (!isCss) { - link.as = "script"; + link2.as = "script"; } - link.crossOrigin = ""; - link.href = dep; + link2.crossOrigin = ""; + link2.href = dep; if (cspNonce) { - link.setAttribute("nonce", cspNonce); + link2.setAttribute("nonce", cspNonce); } - document.head.appendChild(link); + document.head.appendChild(link2); if (isCss) { return new Promise((res, rej) => { - link.addEventListener("load", res); - link.addEventListener( + link2.addEventListener("load", res); + link2.addEventListener( "error", () => rej(new Error(`Unable to preload CSS for ${dep}`)) ); @@ -2277,19 +2269,20 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim seconds = String(now.getSeconds()).padStart(2, "0"); return `${[year, month, day].join(dateSplitStr)} ${[hours, minutes, seconds].join(timeSplitStr)}`; } - formatDate(date, dateSplitStr = "-", timeSplitStr = ":") { + + formatDate(date2, dateSplitStr = "-", timeSplitStr = ":") { let targetDate; - if (date instanceof Date) targetDate = date; + if (date2 instanceof Date) targetDate = date2; else { - if ("string" != typeof date) throw new Error("Invalid date input: must be Date object or date string"); - targetDate = new Date(date); + if ("string" != typeof date2) throw new Error("Invalid date input: must be Date object or date string"); + targetDate = new Date(date2); if (isNaN(targetDate.getTime())) throw new Error("Invalid date string"); } - const year = targetDate.getFullYear(), month = String(targetDate.getMonth() + 1).padStart(2, "0"), - day = String(targetDate.getDate()).padStart(2, "0"), - hours = String(targetDate.getHours()).padStart(2, "0"), - minutes = String(targetDate.getMinutes()).padStart(2, "0"), - seconds = String(targetDate.getSeconds()).padStart(2, "0"); + const year = targetDate.getFullYear(), month = String(targetDate.getMonth() + 1).padStart(2, "0"), + day = String(targetDate.getDate()).padStart(2, "0"), + hours = String(targetDate.getHours()).padStart(2, "0"), + minutes = String(targetDate.getMinutes()).padStart(2, "0"), + seconds = String(targetDate.getSeconds()).padStart(2, "0"); return `${[year, month, day].join(dateSplitStr)} ${[hours, minutes, seconds].join(timeSplitStr)}`; } getHourDifference(date1, date2) { @@ -2329,10 +2322,10 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim return new Promise(((resolve) => { const start = performance.now(), startPosition = window.pageYOffset; window.requestAnimationFrame((function scrollStep(timestamp) { - const elapsed = timestamp - start, progress = Math.min(elapsed / duration, 1), - easeInOutCubic = progress < 0.5 ? 4 * progress * progress * progress : 1 - Math.pow(-2 * progress + 2, 3) / 2; + const elapsed = timestamp - start, progress2 = Math.min(elapsed / duration, 1), + easeInOutCubic = progress2 < 0.5 ? 4 * progress2 * progress2 * progress2 : 1 - Math.pow(-2 * progress2 + 2, 3) / 2; window.scrollTo(0, startPosition * (1 - easeInOutCubic)); - progress < 1 ? window.requestAnimationFrame(scrollStep) : resolve(); + progress2 < 1 ? window.requestAnimationFrame(scrollStep) : resolve(); })); })); } @@ -2377,9 +2370,10 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim copyToClipboard(type, text) { navigator.clipboard.writeText(text).then((() => show.info(`${type}已复制到剪切板, ${text}`))).catch(((err) => console.error("复制失败: ", err))); } - htmlTo$dom(html) { + + htmlTo$dom(html2) { const parser = new DOMParser(); - return $(parser.parseFromString(html, "text/html")); + return $(parser.parseFromString(html2, "text/html")); } addCookie(cookieStr, options = {}) { const {maxAge = 604800, path = "/", domain = "", secure = false, sameSite = "Lax"} = options; @@ -2433,8 +2427,8 @@ System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueim const sortedArr = [...arr], safeDateConvert = (value) => { if (value instanceof Date) return value; if ("string" == typeof value) { - const date = new Date(value); - if (!isNaN(date.getTime())) return date; + const date2 = new Date(value); + if (!isNaN(date2.getTime())) return date2; } return value; }; @@ -2926,6 +2920,24152 @@ ${value}\r return false; } } + + class CoreFeature { + constructor(table) { + this.table = table; + } + + ////////////////////////////////////////// + /////////////// DataLoad ///////////////// + ////////////////////////////////////////// + reloadData(data, silent, columnsChanged) { + return this.table.dataLoader.load(data, void 0, void 0, void 0, silent, columnsChanged); + } + + ////////////////////////////////////////// + ///////////// Localization /////////////// + ////////////////////////////////////////// + langText() { + return this.table.modules.localize.getText(...arguments); + } + + langBind() { + return this.table.modules.localize.bind(...arguments); + } + + langLocale() { + return this.table.modules.localize.getLocale(...arguments); + } + + ////////////////////////////////////////// + ////////// Inter Table Comms ///////////// + ////////////////////////////////////////// + commsConnections() { + return this.table.modules.comms.getConnections(...arguments); + } + + commsSend() { + return this.table.modules.comms.send(...arguments); + } + + ////////////////////////////////////////// + //////////////// Layout ///////////////// + ////////////////////////////////////////// + /** @returns {("fitData" | "fitDataFill" | "fitDataTable" | "fitDataStretch" | "fitColumns")} */ + layoutMode() { + return this.table.modules.layout.getMode(); + } + + layoutRefresh(force) { + return this.table.modules.layout.layout(force); + } + + ////////////////////////////////////////// + /////////////// Event Bus //////////////// + ////////////////////////////////////////// + subscribe() { + return this.table.eventBus.subscribe(...arguments); + } + + unsubscribe() { + return this.table.eventBus.unsubscribe(...arguments); + } + + subscribed(key) { + return this.table.eventBus.subscribed(key); + } + + subscriptionChange() { + return this.table.eventBus.subscriptionChange(...arguments); + } + + dispatch() { + return this.table.eventBus.dispatch(...arguments); + } + + chain() { + return this.table.eventBus.chain(...arguments); + } + + confirm() { + return this.table.eventBus.confirm(...arguments); + } + + dispatchExternal() { + return this.table.externalEvents.dispatch(...arguments); + } + + subscribedExternal(key) { + return this.table.externalEvents.subscribed(key); + } + + subscriptionChangeExternal() { + return this.table.externalEvents.subscriptionChange(...arguments); + } + + ////////////////////////////////////////// + //////////////// Options ///////////////// + ////////////////////////////////////////// + options(key) { + return this.table.options[key]; + } + + setOption(key, value) { + if (typeof value !== "undefined") { + this.table.options[key] = value; + } + return this.table.options[key]; + } + + ////////////////////////////////////////// + /////////// Deprecation Checks /////////// + ////////////////////////////////////////// + deprecationCheck(oldOption, newOption, convert) { + return this.table.deprecationAdvisor.check(oldOption, newOption, convert); + } + + deprecationCheckMsg(oldOption, msg) { + return this.table.deprecationAdvisor.checkMsg(oldOption, msg); + } + + deprecationMsg(msg) { + return this.table.deprecationAdvisor.msg(msg); + } + + ////////////////////////////////////////// + //////////////// Modules ///////////////// + ////////////////////////////////////////// + module(key) { + return this.table.module(key); + } + } + + class Helpers { + static elVisible(el) { + return !(el.offsetWidth <= 0 && el.offsetHeight <= 0); + } + + static elOffset(el) { + var box = el.getBoundingClientRect(); + return { + top: box.top + window.pageYOffset - document.documentElement.clientTop, + left: box.left + window.pageXOffset - document.documentElement.clientLeft + }; + } + + static retrieveNestedData(separator, field, data) { + var structure = separator ? field.split(separator) : [field], length = structure.length, output; + for (let i = 0; i < length; i++) { + data = data[structure[i]]; + output = data; + if (!data) { + break; + } + } + return output; + } + + static deepClone(obj, clone, list2 = []) { + var objectProto = {}.__proto__, arrayProto = [].__proto__; + if (!clone) { + clone = Object.assign(Array.isArray(obj) ? [] : {}, obj); + } + for (var i in obj) { + let subject = obj[i], match, copy; + if (subject != null && typeof subject === "object" && (subject.__proto__ === objectProto || subject.__proto__ === arrayProto)) { + match = list2.findIndex((item) => { + return item.subject === subject; + }); + if (match > -1) { + clone[i] = list2[match].copy; + } else { + copy = Object.assign(Array.isArray(subject) ? [] : {}, subject); + list2.unshift({subject, copy}); + clone[i] = this.deepClone(subject, copy, list2); + } + } + } + return clone; + } + } + + let Popup$1 = class Popup extends CoreFeature { + constructor(table, element, parent2) { + super(table); + this.element = element; + this.container = this._lookupContainer(); + this.parent = parent2; + this.reversedX = false; + this.childPopup = null; + this.blurable = false; + this.blurCallback = null; + this.blurEventsBound = false; + this.renderedCallback = null; + this.visible = false; + this.hideable = true; + this.element.classList.add("tabulator-popup-container"); + this.blurEvent = this.hide.bind(this, false); + this.escEvent = this._escapeCheck.bind(this); + this.destroyBinding = this.tableDestroyed.bind(this); + this.destroyed = false; + } + + tableDestroyed() { + this.destroyed = true; + this.hide(true); + } + + _lookupContainer() { + var container = this.table.options.popupContainer; + if (typeof container === "string") { + container = document.querySelector(container); + if (!container) { + console.warn("Menu Error - no container element found matching selector:", this.table.options.popupContainer, "(defaulting to document body)"); + } + } else if (container === true) { + container = this.table.element; + } + if (container && !this._checkContainerIsParent(container)) { + container = false; + console.warn("Menu Error - container element does not contain this table:", this.table.options.popupContainer, "(defaulting to document body)"); + } + if (!container) { + container = document.body; + } + return container; + } + + _checkContainerIsParent(container, element = this.table.element) { + if (container === element) { + return true; + } else { + return element.parentNode ? this._checkContainerIsParent(container, element.parentNode) : false; + } + } + + renderCallback(callback) { + this.renderedCallback = callback; + } + + containerEventCoords(e) { + var touch = !(e instanceof MouseEvent); + var x = touch ? e.touches[0].pageX : e.pageX; + var y = touch ? e.touches[0].pageY : e.pageY; + if (this.container !== document.body) { + let parentOffset = Helpers.elOffset(this.container); + x -= parentOffset.left; + y -= parentOffset.top; + } + return {x, y}; + } + + elementPositionCoords(element, position = "right") { + var offset = Helpers.elOffset(element), containerOffset, x, y; + if (this.container !== document.body) { + containerOffset = Helpers.elOffset(this.container); + offset.left -= containerOffset.left; + offset.top -= containerOffset.top; + } + switch (position) { + case "right": + x = offset.left + element.offsetWidth; + y = offset.top - 1; + break; + case "bottom": + x = offset.left; + y = offset.top + element.offsetHeight; + break; + case "left": + x = offset.left; + y = offset.top - 1; + break; + case "top": + x = offset.left; + y = offset.top; + break; + case "center": + x = offset.left + element.offsetWidth / 2; + y = offset.top + element.offsetHeight / 2; + break; + } + return {x, y, offset}; + } + + show(origin, position) { + var x, y, parentEl, parentOffset, coords; + if (this.destroyed || this.table.destroyed) { + return this; + } + if (origin instanceof HTMLElement) { + parentEl = origin; + coords = this.elementPositionCoords(origin, position); + parentOffset = coords.offset; + x = coords.x; + y = coords.y; + } else if (typeof origin === "number") { + parentOffset = {top: 0, left: 0}; + x = origin; + y = position; + } else { + coords = this.containerEventCoords(origin); + x = coords.x; + y = coords.y; + this.reversedX = false; + } + this.element.style.top = y + "px"; + this.element.style.left = x + "px"; + this.container.appendChild(this.element); + if (typeof this.renderedCallback === "function") { + this.renderedCallback(); + } + this._fitToScreen(x, y, parentEl, parentOffset, position); + this.visible = true; + this.subscribe("table-destroy", this.destroyBinding); + this.element.addEventListener("mousedown", (e) => { + e.stopPropagation(); + }); + return this; + } + + _fitToScreen(x, y, parentEl, parentOffset, position) { + var scrollTop = this.container === document.body ? document.documentElement.scrollTop : this.container.scrollTop; + if (x + this.element.offsetWidth >= this.container.offsetWidth || this.reversedX) { + this.element.style.left = ""; + if (parentEl) { + this.element.style.right = this.container.offsetWidth - parentOffset.left + "px"; + } else { + this.element.style.right = this.container.offsetWidth - x + "px"; + } + this.reversedX = true; + } + let offsetHeight = Math.max(this.container.offsetHeight, scrollTop ? this.container.scrollHeight : 0); + if (y + this.element.offsetHeight > offsetHeight) { + if (parentEl) { + switch (position) { + case "bottom": + this.element.style.top = parseInt(this.element.style.top) - this.element.offsetHeight - parentEl.offsetHeight - 1 + "px"; + break; + default: + this.element.style.top = parseInt(this.element.style.top) - this.element.offsetHeight + parentEl.offsetHeight + 1 + "px"; + } + } else { + let menuHeight = this.element.offsetHeight; + if (menuHeight > offsetHeight) { + this.element.style.top = "0px"; + this.element.style.height = offsetHeight + "px"; + } else { + let newTop = y - menuHeight; + if (newTop < 0) { + newTop = offsetHeight - menuHeight; + } + this.element.style.top = newTop + "px"; + } + } + } + } + + isVisible() { + return this.visible; + } + + hideOnBlur(callback) { + this.blurable = true; + if (this.visible) { + setTimeout(() => { + if (this.visible) { + this.table.rowManager.element.addEventListener("scroll", this.blurEvent); + this.subscribe("cell-editing", this.blurEvent); + document.body.addEventListener("click", this.blurEvent); + document.body.addEventListener("contextmenu", this.blurEvent); + document.body.addEventListener("mousedown", this.blurEvent); + window.addEventListener("resize", this.blurEvent); + document.body.addEventListener("keydown", this.escEvent); + this.blurEventsBound = true; + } + }, 100); + this.blurCallback = callback; + } + return this; + } + + /** @param {KeyboardEvent} e */ + _escapeCheck(e) { + if (e.key == 27) { + this.hide(); + } + } + + blockHide() { + this.hideable = false; + } + + restoreHide() { + this.hideable = true; + } + + hide(silent = false) { + if (this.visible && this.hideable) { + if (this.blurable && this.blurEventsBound) { + document.body.removeEventListener("keydown", this.escEvent); + document.body.removeEventListener("click", this.blurEvent); + document.body.removeEventListener("contextmenu", this.blurEvent); + document.body.removeEventListener("mousedown", this.blurEvent); + window.removeEventListener("resize", this.blurEvent); + this.table.rowManager.element.removeEventListener("scroll", this.blurEvent); + this.unsubscribe("cell-editing", this.blurEvent); + this.blurEventsBound = false; + } + if (this.childPopup) { + this.childPopup.hide(); + } + if (this.parent) { + this.parent.childPopup = null; + } + if (this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + this.visible = false; + if (this.blurCallback && !silent) { + this.blurCallback(); + } + this.unsubscribe("table-destroy", this.destroyBinding); + } + return this; + } + + child(element) { + if (this.childPopup) { + this.childPopup.hide(); + } + this.childPopup = new Popup(this.table, element, this); + return this.childPopup; + } + }; + + class Module extends CoreFeature { + constructor(table, name2) { + super(table); + this._handler = null; + } + + initialize() { + } + + /////////////////////////////////// + ////// Options Registration /////// + /////////////////////////////////// + registerTableOption(key, value) { + this.table.optionsList.register(key, value); + } + + registerColumnOption(key, value) { + this.table.columnManager.optionsList.register(key, value); + } + + /////////////////////////////////// + /// Public Function Registration /// + /////////////////////////////////// + registerTableFunction(name2, func) { + if (typeof this.table[name2] === "undefined") { + this.table[name2] = (...args) => { + this.table.initGuard(name2); + return func(...args); + }; + } else { + console.warn("Unable to bind table function, name already in use", name2); + } + } + + registerComponentFunction(component, func, handler) { + return this.table.componentFunctionBinder.bind(component, func, handler); + } + + /////////////////////////////////// + ////////// Data Pipeline ////////// + /////////////////////////////////// + registerDataHandler(handler, priority) { + this.table.rowManager.registerDataPipelineHandler(handler, priority); + this._handler = handler; + } + + registerDisplayHandler(handler, priority) { + this.table.rowManager.registerDisplayPipelineHandler(handler, priority); + this._handler = handler; + } + + displayRows(adjust) { + var index = this.table.rowManager.displayRows.length - 1, lookupIndex; + if (this._handler) { + lookupIndex = this.table.rowManager.displayPipeline.findIndex((item) => { + return item.handler === this._handler; + }); + if (lookupIndex > -1) { + index = lookupIndex; + } + } + if (adjust) { + index = index + adjust; + } + if (this._handler) { + if (index > -1) { + return this.table.rowManager.getDisplayRows(index); + } else { + return this.activeRows(); + } + } + } + + activeRows() { + return this.table.rowManager.activeRows; + } + + refreshData(renderInPosition, handler) { + if (!handler) { + handler = this._handler; + } + if (handler) { + this.table.rowManager.refreshActiveData(handler, false, renderInPosition); + } + } + + /////////////////////////////////// + //////// Footer Management //////// + /////////////////////////////////// + footerAppend(element) { + return this.table.footerManager.append(element); + } + + footerPrepend(element) { + return this.table.footerManager.prepend(element); + } + + footerRemove(element) { + return this.table.footerManager.remove(element); + } + + /////////////////////////////////// + //////// Popups Management //////// + /////////////////////////////////// + popup(menuEl, menuContainer) { + return new Popup$1(this.table, menuEl, menuContainer); + } + + /////////////////////////////////// + //////// Alert Management //////// + /////////////////////////////////// + alert(content, type) { + return this.table.alertManager.alert(content, type); + } + + clearAlert() { + return this.table.alertManager.clear(); + } + } + + var defaultAccessors = { + rownum: function (value, data, type, params, column, row) { + return row.getPosition(); + } + }; + const _Accessor = class _Accessor extends Module { + constructor(table) { + super(table); + this.allowedTypes = ["", "data", "download", "clipboard", "print", "htmlOutput"]; + this.registerColumnOption("accessor"); + this.registerColumnOption("accessorParams"); + this.registerColumnOption("accessorData"); + this.registerColumnOption("accessorDataParams"); + this.registerColumnOption("accessorDownload"); + this.registerColumnOption("accessorDownloadParams"); + this.registerColumnOption("accessorClipboard"); + this.registerColumnOption("accessorClipboardParams"); + this.registerColumnOption("accessorPrint"); + this.registerColumnOption("accessorPrintParams"); + this.registerColumnOption("accessorHtmlOutput"); + this.registerColumnOption("accessorHtmlOutputParams"); + } + + initialize() { + this.subscribe("column-layout", this.initializeColumn.bind(this)); + this.subscribe("row-data-retrieve", this.transformRow.bind(this)); + } + + //initialize column accessor + initializeColumn(column) { + var match = false, config = {}; + this.allowedTypes.forEach((type) => { + var key = "accessor" + (type.charAt(0).toUpperCase() + type.slice(1)), accessor; + if (column.definition[key]) { + accessor = this.lookupAccessor(column.definition[key]); + if (accessor) { + match = true; + config[key] = { + accessor, + params: column.definition[key + "Params"] || {} + }; + } + } + }); + if (match) { + column.modules.accessor = config; + } + } + + lookupAccessor(value) { + var accessor = false; + switch (typeof value) { + case "string": + if (_Accessor.accessors[value]) { + accessor = _Accessor.accessors[value]; + } else { + console.warn("Accessor Error - No such accessor found, ignoring: ", value); + } + break; + case "function": + accessor = value; + break; + } + return accessor; + } + + //apply accessor to row + transformRow(row, type) { + var key = "accessor" + (type.charAt(0).toUpperCase() + type.slice(1)), + rowComponent = row.getComponent(); + var data = Helpers.deepClone(row.data || {}); + this.table.columnManager.traverse(function (column) { + var value, accessor, params, colComponent; + if (column.modules.accessor) { + accessor = column.modules.accessor[key] || column.modules.accessor.accessor || false; + if (accessor) { + value = column.getFieldValue(data); + if (value != "undefined") { + colComponent = column.getComponent(); + params = typeof accessor.params === "function" ? accessor.params(value, data, type, colComponent, rowComponent) : accessor.params; + column.setFieldValue(data, accessor.accessor(value, data, type, params, colComponent, rowComponent)); + } + } + } + }); + return data; + } + }; + __publicField(_Accessor, "moduleName", "accessor"); + //load defaults + __publicField(_Accessor, "accessors", defaultAccessors); + let Accessor = _Accessor; + var defaultConfig = { + method: "GET" + }; + + function generateParamsList$1(data, prefix) { + var output = []; + prefix = prefix || ""; + if (Array.isArray(data)) { + data.forEach((item, i) => { + output = output.concat(generateParamsList$1(item, prefix ? prefix + "[" + i + "]" : i)); + }); + } else if (typeof data === "object") { + for (var key in data) { + output = output.concat(generateParamsList$1(data[key], prefix ? prefix + "[" + key + "]" : key)); + } + } else { + output.push({key: prefix, value: data}); + } + return output; + } + + function serializeParams(params) { + var output = generateParamsList$1(params), encoded = []; + output.forEach(function (item) { + encoded.push(encodeURIComponent(item.key) + "=" + encodeURIComponent(item.value)); + }); + return encoded.join("&"); + } + + function urlBuilder(url, config, params) { + if (url) { + if (params && Object.keys(params).length) { + if (!config.method || config.method.toLowerCase() == "get") { + config.method = "get"; + url += (url.includes("?") ? "&" : "?") + serializeParams(params); + } + } + } + return url; + } + + function defaultLoaderPromise(url, config, params) { + var contentType; + return new Promise((resolve, reject) => { + url = this.urlGenerator.call(this.table, url, config, params); + if (config.method.toUpperCase() != "GET") { + contentType = typeof this.table.options.ajaxContentType === "object" ? this.table.options.ajaxContentType : this.contentTypeFormatters[this.table.options.ajaxContentType]; + if (contentType) { + for (var key in contentType.headers) { + if (!config.headers) { + config.headers = {}; + } + if (typeof config.headers[key] === "undefined") { + config.headers[key] = contentType.headers[key]; + } + } + config.body = contentType.body.call(this, url, config, params); + } else { + console.warn("Ajax Error - Invalid ajaxContentType value:", this.table.options.ajaxContentType); + } + } + if (url) { + if (typeof config.headers === "undefined") { + config.headers = {}; + } + if (typeof config.headers.Accept === "undefined") { + config.headers.Accept = "application/json"; + } + if (typeof config.headers["X-Requested-With"] === "undefined") { + config.headers["X-Requested-With"] = "XMLHttpRequest"; + } + if (typeof config.mode === "undefined") { + config.mode = "cors"; + } + if (config.mode == "cors") { + if (typeof config.headers["Origin"] === "undefined") { + config.headers["Origin"] = window.location.origin; + } + if (typeof config.credentials === "undefined") { + config.credentials = "same-origin"; + } + } else { + if (typeof config.credentials === "undefined") { + config.credentials = "include"; + } + } + fetch(url, config).then((response) => { + if (response.ok) { + response.json().then((data) => { + resolve(data); + }).catch((error) => { + reject(error); + console.warn("Ajax Load Error - Invalid JSON returned", error); + }); + } else { + console.error("Ajax Load Error - Connection Error: " + response.status, response.statusText); + reject(response); + } + }).catch((error) => { + console.error("Ajax Load Error - Connection Error: ", error); + reject(error); + }); + } else { + console.warn("Ajax Load Error - No URL Set"); + resolve([]); + } + }); + } + + function generateParamsList(data, prefix) { + var output = []; + prefix = prefix || ""; + if (Array.isArray(data)) { + data.forEach((item, i) => { + output = output.concat(generateParamsList(item, prefix ? prefix + "[" + i + "]" : i)); + }); + } else if (typeof data === "object") { + for (var key in data) { + output = output.concat(generateParamsList(data[key], prefix ? prefix + "[" + key + "]" : key)); + } + } else { + output.push({key: prefix, value: data}); + } + return output; + } + + var defaultContentTypeFormatters = { + "json": { + headers: { + "Content-Type": "application/json" + }, + body: function (url, config, params) { + return JSON.stringify(params); + } + }, + "form": { + headers: {}, + body: function (url, config, params) { + var output = generateParamsList(params), form = new FormData(); + output.forEach(function (item) { + form.append(item.key, item.value); + }); + return form; + } + } + }; + const _Ajax = class _Ajax extends Module { + constructor(table) { + super(table); + this.config = {}; + this.url = ""; + this.urlGenerator = false; + this.params = false; + this.loaderPromise = false; + this.registerTableOption("ajaxURL", false); + this.registerTableOption("ajaxURLGenerator", false); + this.registerTableOption("ajaxParams", {}); + this.registerTableOption("ajaxConfig", "get"); + this.registerTableOption("ajaxContentType", "form"); + this.registerTableOption("ajaxRequestFunc", false); + this.registerTableOption("ajaxRequesting", function () { + }); + this.registerTableOption("ajaxResponse", false); + this.contentTypeFormatters = _Ajax.contentTypeFormatters; + } + + //initialize setup options + initialize() { + this.loaderPromise = this.table.options.ajaxRequestFunc || _Ajax.defaultLoaderPromise; + this.urlGenerator = this.table.options.ajaxURLGenerator || _Ajax.defaultURLGenerator; + if (this.table.options.ajaxURL) { + this.setUrl(this.table.options.ajaxURL); + } + this.setDefaultConfig(this.table.options.ajaxConfig); + this.registerTableFunction("getAjaxUrl", this.getUrl.bind(this)); + this.subscribe("data-loading", this.requestDataCheck.bind(this)); + this.subscribe("data-params", this.requestParams.bind(this)); + this.subscribe("data-load", this.requestData.bind(this)); + } + + requestParams(data, config, silent, params) { + var ajaxParams = this.table.options.ajaxParams; + if (ajaxParams) { + if (typeof ajaxParams === "function") { + ajaxParams = ajaxParams.call(this.table); + } + params = Object.assign(Object.assign({}, ajaxParams), params); + } + return params; + } + + requestDataCheck(data, params, config, silent) { + return !!(!data && this.url || typeof data === "string"); + } + + requestData(url, params, config, silent, previousData) { + var ajaxConfig; + if (!previousData && this.requestDataCheck(url)) { + if (url) { + this.setUrl(url); + } + ajaxConfig = this.generateConfig(config); + return this.sendRequest(this.url, params, ajaxConfig); + } else { + return previousData; + } + } + + setDefaultConfig(config = {}) { + this.config = Object.assign({}, _Ajax.defaultConfig); + if (typeof config == "string") { + this.config.method = config; + } else { + Object.assign(this.config, config); + } + } + + //load config object + generateConfig(config = {}) { + var ajaxConfig = Object.assign({}, this.config); + if (typeof config == "string") { + ajaxConfig.method = config; + } else { + Object.assign(ajaxConfig, config); + } + return ajaxConfig; + } + + //set request url + setUrl(url) { + this.url = url; + } + + //get request url + getUrl() { + return this.url; + } + + //send ajax request + sendRequest(url, params, config) { + if (this.table.options.ajaxRequesting.call(this.table, url, params) !== false) { + return this.loaderPromise(url, config, params).then((data) => { + if (this.table.options.ajaxResponse) { + data = this.table.options.ajaxResponse.call(this.table, url, params, data); + } + return data; + }); + } else { + return Promise.reject(); + } + } + }; + __publicField(_Ajax, "moduleName", "ajax"); + //load defaults + __publicField(_Ajax, "defaultConfig", defaultConfig); + __publicField(_Ajax, "defaultURLGenerator", urlBuilder); + __publicField(_Ajax, "defaultLoaderPromise", defaultLoaderPromise); + __publicField(_Ajax, "contentTypeFormatters", defaultContentTypeFormatters); + let Ajax = _Ajax; + var defaultPasteActions = { + replace: function (data) { + return this.table.setData(data); + }, + update: function (data) { + return this.table.updateOrAddData(data); + }, + insert: function (data) { + return this.table.addData(data); + } + }; + var defaultPasteParsers = { + table: function (clipboard) { + var data = [], headerFindSuccess = true, columns = this.table.columnManager.columns, columnMap = [], + rows2 = []; + clipboard = clipboard.split("\n"); + clipboard.forEach(function (row) { + data.push(row.split(" ")); + }); + if (data.length && !(data.length === 1 && data[0].length < 2)) { + data[0].forEach(function (value) { + var column = columns.find(function (column2) { + return value && column2.definition.title && value.trim() && column2.definition.title.trim() === value.trim(); + }); + if (column) { + columnMap.push(column); + } else { + headerFindSuccess = false; + } + }); + if (!headerFindSuccess) { + headerFindSuccess = true; + columnMap = []; + data[0].forEach(function (value) { + var column = columns.find(function (column2) { + return value && column2.field && value.trim() && column2.field.trim() === value.trim(); + }); + if (column) { + columnMap.push(column); + } else { + headerFindSuccess = false; + } + }); + if (!headerFindSuccess) { + columnMap = this.table.columnManager.columnsByIndex; + } + } + if (headerFindSuccess) { + data.shift(); + } + data.forEach(function (item) { + var row = {}; + item.forEach(function (value, i) { + if (columnMap[i]) { + row[columnMap[i].field] = value; + } + }); + rows2.push(row); + }); + return rows2; + } else { + return false; + } + } + }; + var bindings$2 = { + copyToClipboard: ["ctrl + 67", "meta + 67"] + }; + var actions$2 = { + copyToClipboard: function (e) { + if (!this.table.modules.edit.currentCell) { + if (this.table.modExists("clipboard", true)) { + this.table.modules.clipboard.copy(false, true); + } + } + } + }; + var extensions$4 = { + keybindings: { + bindings: bindings$2, + actions: actions$2 + } + }; + const _Clipboard = class _Clipboard extends Module { + constructor(table) { + super(table); + this.mode = true; + this.pasteParser = function () { + }; + this.pasteAction = function () { + }; + this.customSelection = false; + this.rowRange = false; + this.blocked = true; + this.registerTableOption("clipboard", false); + this.registerTableOption("clipboardCopyStyled", true); + this.registerTableOption("clipboardCopyConfig", false); + this.registerTableOption("clipboardCopyFormatter", false); + this.registerTableOption("clipboardCopyRowRange", "active"); + this.registerTableOption("clipboardPasteParser", "table"); + this.registerTableOption("clipboardPasteAction", "insert"); + this.registerColumnOption("clipboard"); + this.registerColumnOption("titleClipboard"); + } + + initialize() { + this.mode = this.table.options.clipboard; + this.rowRange = this.table.options.clipboardCopyRowRange; + if (this.mode === true || this.mode === "copy") { + this.table.element.addEventListener("copy", (e) => { + var plain, html2, list2; + if (!this.blocked) { + e.preventDefault(); + if (this.customSelection) { + plain = this.customSelection; + if (this.table.options.clipboardCopyFormatter) { + plain = this.table.options.clipboardCopyFormatter("plain", plain); + } + } else { + list2 = this.table.modules.export.generateExportList(this.table.options.clipboardCopyConfig, this.table.options.clipboardCopyStyled, this.rowRange, "clipboard"); + html2 = this.table.modules.export.generateHTMLTable(list2); + plain = html2 ? this.generatePlainContent(list2) : ""; + if (this.table.options.clipboardCopyFormatter) { + plain = this.table.options.clipboardCopyFormatter("plain", plain); + html2 = this.table.options.clipboardCopyFormatter("html", html2); + } + } + if (window.clipboardData && window.clipboardData.setData) { + window.clipboardData.setData("Text", plain); + } else if (e.clipboardData && e.clipboardData.setData) { + e.clipboardData.setData("text/plain", plain); + if (html2) { + e.clipboardData.setData("text/html", html2); + } + } else if (e.originalEvent && e.originalEvent.clipboardData.setData) { + e.originalEvent.clipboardData.setData("text/plain", plain); + if (html2) { + e.originalEvent.clipboardData.setData("text/html", html2); + } + } + this.dispatchExternal("clipboardCopied", plain, html2); + this.reset(); + } + }); + } + if (this.mode === true || this.mode === "paste") { + this.table.element.addEventListener("paste", (e) => { + this.paste(e); + }); + } + this.setPasteParser(this.table.options.clipboardPasteParser); + this.setPasteAction(this.table.options.clipboardPasteAction); + this.registerTableFunction("copyToClipboard", this.copy.bind(this)); + } + + reset() { + this.blocked = true; + this.customSelection = false; + } + + generatePlainContent(list2) { + var output = []; + list2.forEach((row) => { + var rowData = []; + row.columns.forEach((col) => { + var value = ""; + if (col) { + if (row.type === "group") { + col.value = col.component.getKey(); + } + if (col.value === null) { + value = ""; + } else { + switch (typeof col.value) { + case "object": + value = JSON.stringify(col.value); + break; + case "undefined": + value = ""; + break; + default: + value = col.value; + } + } + } + rowData.push(value); + }); + output.push(rowData.join(" ")); + }); + return output.join("\n"); + } + + copy(range2, internal) { + var sel, textRange; + this.blocked = false; + this.customSelection = false; + if (this.mode === true || this.mode === "copy") { + this.rowRange = range2 || this.table.options.clipboardCopyRowRange; + if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") { + range2 = document.createRange(); + range2.selectNodeContents(this.table.element); + sel = window.getSelection(); + if (sel.toString() && internal) { + this.customSelection = sel.toString(); + } + sel.removeAllRanges(); + sel.addRange(range2); + } else if (typeof document.selection != "undefined" && typeof document.body.createTextRange != "undefined") { + textRange = document.body.createTextRange(); + textRange.moveToElementText(this.table.element); + textRange.select(); + } + document.execCommand("copy"); + if (sel) { + sel.removeAllRanges(); + } + } + } + + //PASTE EVENT HANDLING + setPasteAction(action) { + switch (typeof action) { + case "string": + this.pasteAction = _Clipboard.pasteActions[action]; + if (!this.pasteAction) { + console.warn("Clipboard Error - No such paste action found:", action); + } + break; + case "function": + this.pasteAction = action; + break; + } + } + + setPasteParser(parser) { + switch (typeof parser) { + case "string": + this.pasteParser = _Clipboard.pasteParsers[parser]; + if (!this.pasteParser) { + console.warn("Clipboard Error - No such paste parser found:", parser); + } + break; + case "function": + this.pasteParser = parser; + break; + } + } + + paste(e) { + var data, rowData, rows2; + if (this.checkPasteOrigin(e)) { + data = this.getPasteData(e); + rowData = this.pasteParser.call(this, data); + if (rowData) { + e.preventDefault(); + if (this.table.modExists("mutator")) { + rowData = this.mutateData(rowData); + } + rows2 = this.pasteAction.call(this, rowData); + this.dispatchExternal("clipboardPasted", data, rowData, rows2); + } else { + this.dispatchExternal("clipboardPasteError", data); + } + } + } + + mutateData(data) { + var output = []; + if (Array.isArray(data)) { + data.forEach((row) => { + output.push(this.table.modules.mutator.transformRow(row, "clipboard")); + }); + } else { + output = data; + } + return output; + } + + checkPasteOrigin(e) { + var valid = true; + var blocked = this.confirm("clipboard-paste", [e]); + if (blocked || !["DIV", "SPAN"].includes(e.target.tagName)) { + valid = false; + } + return valid; + } + + getPasteData(e) { + var data; + if (window.clipboardData && window.clipboardData.getData) { + data = window.clipboardData.getData("Text"); + } else if (e.clipboardData && e.clipboardData.getData) { + data = e.clipboardData.getData("text/plain"); + } else if (e.originalEvent && e.originalEvent.clipboardData.getData) { + data = e.originalEvent.clipboardData.getData("text/plain"); + } + return data; + } + }; + __publicField(_Clipboard, "moduleName", "clipboard"); + __publicField(_Clipboard, "moduleExtensions", extensions$4); + //load defaults + __publicField(_Clipboard, "pasteActions", defaultPasteActions); + __publicField(_Clipboard, "pasteParsers", defaultPasteParsers); + let Clipboard = _Clipboard; + + class CalcComponent { + constructor(row) { + this._row = row; + return new Proxy(this, { + get: function (target, name2, receiver) { + if (typeof target[name2] !== "undefined") { + return target[name2]; + } else { + return target._row.table.componentFunctionBinder.handle("row", target._row, name2); + } + } + }); + } + + getData(transform) { + return this._row.getData(transform); + } + + getElement() { + return this._row.getElement(); + } + + getTable() { + return this._row.table; + } + + getCells() { + var cells = []; + this._row.getCells().forEach(function (cell) { + cells.push(cell.getComponent()); + }); + return cells; + } + + getCell(column) { + var cell = this._row.getCell(column); + return cell ? cell.getComponent() : false; + } + + _getSelf() { + return this._row; + } + } + + class CellComponent { + constructor(cell) { + this._cell = cell; + return new Proxy(this, { + get: function (target, name2, receiver) { + if (typeof target[name2] !== "undefined") { + return target[name2]; + } else { + return target._cell.table.componentFunctionBinder.handle("cell", target._cell, name2); + } + } + }); + } + + getValue() { + return this._cell.getValue(); + } + + getOldValue() { + return this._cell.getOldValue(); + } + + getInitialValue() { + return this._cell.initialValue; + } + + getElement() { + return this._cell.getElement(); + } + + getRow() { + return this._cell.row.getComponent(); + } + + getData(transform) { + return this._cell.row.getData(transform); + } + + getType() { + return "cell"; + } + + getField() { + return this._cell.column.getField(); + } + + getColumn() { + return this._cell.column.getComponent(); + } + + setValue(value, mutate) { + if (typeof mutate == "undefined") { + mutate = true; + } + this._cell.setValue(value, mutate); + } + + restoreOldValue() { + this._cell.setValueActual(this._cell.getOldValue()); + } + + restoreInitialValue() { + this._cell.setValueActual(this._cell.initialValue); + } + + checkHeight() { + this._cell.checkHeight(); + } + + getTable() { + return this._cell.table; + } + + _getSelf() { + return this._cell; + } + } + + class Cell extends CoreFeature { + constructor(column, row) { + super(column.table); + this.table = column.table; + this.column = column; + this.row = row; + this.element = null; + this.value = null; + this.initialValue; + this.oldValue = null; + this.modules = {}; + this.height = null; + this.width = null; + this.minWidth = null; + this.component = null; + this.loaded = false; + this.build(); + } + + //////////////// Setup Functions ///////////////// + //generate element + build() { + this.generateElement(); + this.setWidth(); + this._configureCell(); + this.setValueActual(this.column.getFieldValue(this.row.data)); + this.initialValue = this.value; + } + + generateElement() { + this.element = document.createElement("div"); + this.element.className = "tabulator-cell"; + this.element.setAttribute("role", "gridcell"); + if (this.column.isRowHeader) { + this.element.classList.add("tabulator-row-header"); + } + } + + _configureCell() { + var element = this.element, field = this.column.getField(), vertAligns = { + top: "flex-start", + bottom: "flex-end", + middle: "center" + }, hozAligns = { + left: "flex-start", + right: "flex-end", + center: "center" + }; + element.style.textAlign = this.column.hozAlign; + if (this.column.vertAlign) { + element.style.display = "inline-flex"; + element.style.alignItems = vertAligns[this.column.vertAlign] || ""; + if (this.column.hozAlign) { + element.style.justifyContent = hozAligns[this.column.hozAlign] || ""; + } + } + if (field) { + element.setAttribute("tabulator-field", field); + } + if (this.column.definition.cssClass) { + var classNames = this.column.definition.cssClass.split(" "); + classNames.forEach((className) => { + element.classList.add(className); + }); + } + this.dispatch("cell-init", this); + if (!this.column.visible) { + this.hide(); + } + } + + //generate cell contents + _generateContents() { + var val; + val = this.chain("cell-format", this, null, () => { + return this.element.innerHTML = this.value; + }); + switch (typeof val) { + case "object": + if (val instanceof Node) { + while (this.element.firstChild) this.element.removeChild(this.element.firstChild); + this.element.appendChild(val); + } else { + this.element.innerHTML = ""; + if (val != null) { + console.warn("Format Error - Formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:", val); + } + } + break; + case "undefined": + this.element.innerHTML = ""; + break; + default: + this.element.innerHTML = val; + } + } + + cellRendered() { + this.dispatch("cell-rendered", this); + } + + //////////////////// Getters //////////////////// + getElement(containerOnly) { + if (!this.loaded) { + this.loaded = true; + if (!containerOnly) { + this.layoutElement(); + } + } + return this.element; + } + + getValue() { + return this.value; + } + + getOldValue() { + return this.oldValue; + } + + //////////////////// Actions //////////////////// + setValue(value, mutate, force) { + var changed = this.setValueProcessData(value, mutate, force); + if (changed) { + this.dispatch("cell-value-updated", this); + this.cellRendered(); + if (this.column.definition.cellEdited) { + this.column.definition.cellEdited.call(this.table, this.getComponent()); + } + this.dispatchExternal("cellEdited", this.getComponent()); + if (this.subscribedExternal("dataChanged")) { + this.dispatchExternal("dataChanged", this.table.rowManager.getData()); + } + } + } + + setValueProcessData(value, mutate, force) { + var changed = false; + if (this.value !== value || force) { + changed = true; + if (mutate) { + value = this.chain("cell-value-changing", [this, value], null, value); + } + } + this.setValueActual(value); + if (changed) { + this.dispatch("cell-value-changed", this); + } + return changed; + } + + setValueActual(value) { + this.oldValue = this.value; + this.value = value; + this.dispatch("cell-value-save-before", this); + this.column.setFieldValue(this.row.data, value); + this.dispatch("cell-value-save-after", this); + if (this.loaded) { + this.layoutElement(); + } + } + + layoutElement() { + this._generateContents(); + this.dispatch("cell-layout", this); + } + + setWidth() { + this.width = this.column.width; + this.element.style.width = this.column.widthStyled; + } + + clearWidth() { + this.width = ""; + this.element.style.width = ""; + } + + getWidth() { + return this.width || this.element.offsetWidth; + } + + setMinWidth() { + this.minWidth = this.column.minWidth; + this.element.style.minWidth = this.column.minWidthStyled; + } + + setMaxWidth() { + this.maxWidth = this.column.maxWidth; + this.element.style.maxWidth = this.column.maxWidthStyled; + } + + checkHeight() { + this.row.reinitializeHeight(); + } + + clearHeight() { + this.element.style.height = ""; + this.height = null; + this.dispatch("cell-height", this, ""); + } + + setHeight() { + this.height = this.row.height; + this.element.style.height = this.row.heightStyled; + this.dispatch("cell-height", this, this.row.heightStyled); + } + + getHeight() { + return this.height || this.element.offsetHeight; + } + + show() { + this.element.style.display = this.column.vertAlign ? "inline-flex" : ""; + } + + hide() { + this.element.style.display = "none"; + } + + delete() { + this.dispatch("cell-delete", this); + if (!this.table.rowManager.redrawBlock && this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + this.element = false; + this.column.deleteCell(this); + this.row.deleteCell(this); + this.calcs = {}; + } + + getIndex() { + return this.row.getCellIndex(this); + } + + //////////////// Object Generation ///////////////// + getComponent() { + if (!this.component) { + this.component = new CellComponent(this); + } + return this.component; + } + } + + class ColumnComponent { + constructor(column) { + this._column = column; + this.type = "ColumnComponent"; + return new Proxy(this, { + get: function (target, name2, receiver) { + if (typeof target[name2] !== "undefined") { + return target[name2]; + } else { + return target._column.table.componentFunctionBinder.handle("column", target._column, name2); + } + } + }); + } + + getElement() { + return this._column.getElement(); + } + + getDefinition() { + return this._column.getDefinition(); + } + + getField() { + return this._column.getField(); + } + + getTitleDownload() { + return this._column.getTitleDownload(); + } + + getCells() { + var cells = []; + this._column.cells.forEach(function (cell) { + cells.push(cell.getComponent()); + }); + return cells; + } + + isVisible() { + return this._column.visible; + } + + show() { + if (this._column.isGroup) { + this._column.columns.forEach(function (column) { + column.show(); + }); + } else { + this._column.show(); + } + } + + hide() { + if (this._column.isGroup) { + this._column.columns.forEach(function (column) { + column.hide(); + }); + } else { + this._column.hide(); + } + } + + toggle() { + if (this._column.visible) { + this.hide(); + } else { + this.show(); + } + } + + delete() { + return this._column.delete(); + } + + getSubColumns() { + var output = []; + if (this._column.columns.length) { + this._column.columns.forEach(function (column) { + output.push(column.getComponent()); + }); + } + return output; + } + + getParentColumn() { + return this._column.getParentComponent(); + } + + _getSelf() { + return this._column; + } + + scrollTo(position, ifVisible) { + return this._column.table.columnManager.scrollToColumn(this._column, position, ifVisible); + } + + getTable() { + return this._column.table; + } + + move(to, after) { + var toColumn = this._column.table.columnManager.findColumn(to); + if (toColumn) { + this._column.table.columnManager.moveColumn(this._column, toColumn, after); + } else { + console.warn("Move Error - No matching column found:", toColumn); + } + } + + getNextColumn() { + var nextCol = this._column.nextColumn(); + return nextCol ? nextCol.getComponent() : false; + } + + getPrevColumn() { + var prevCol = this._column.prevColumn(); + return prevCol ? prevCol.getComponent() : false; + } + + updateDefinition(updates) { + return this._column.updateDefinition(updates); + } + + getWidth() { + return this._column.getWidth(); + } + + setWidth(width) { + var result; + if (width === true) { + result = this._column.reinitializeWidth(true); + } else { + result = this._column.setWidth(width); + } + this._column.table.columnManager.rerenderColumns(true); + return result; + } + } + + var defaultColumnOptions = { + "title": void 0, + "field": void 0, + "columns": void 0, + "visible": void 0, + "hozAlign": void 0, + "vertAlign": void 0, + "width": void 0, + "minWidth": 40, + "maxWidth": void 0, + "maxInitialWidth": void 0, + "cssClass": void 0, + "variableHeight": void 0, + "headerVertical": void 0, + "headerHozAlign": void 0, + "headerWordWrap": false, + "editableTitle": void 0 + }; + const _Column = class _Column extends CoreFeature { + constructor(def, parent2, rowHeader) { + super(parent2.table); + this.definition = def; + this.parent = parent2; + this.type = "column"; + this.columns = []; + this.cells = []; + this.isGroup = false; + this.isRowHeader = rowHeader; + this.element = this.createElement(); + this.contentElement = false; + this.titleHolderElement = false; + this.titleElement = false; + this.groupElement = this.createGroupElement(); + this.hozAlign = ""; + this.vertAlign = ""; + this.field = ""; + this.fieldStructure = ""; + this.getFieldValue = ""; + this.setFieldValue = ""; + this.titleDownload = null; + this.titleFormatterRendered = false; + this.mapDefinitions(); + this.setField(this.definition.field); + this.modules = {}; + this.width = null; + this.widthStyled = ""; + this.maxWidth = null; + this.maxWidthStyled = ""; + this.maxInitialWidth = null; + this.minWidth = null; + this.minWidthStyled = ""; + this.widthFixed = false; + this.visible = true; + this.component = null; + if (this.definition.columns) { + this.isGroup = true; + this.definition.columns.forEach((def2, i) => { + var newCol = new _Column(def2, this); + this.attachColumn(newCol); + }); + this.checkColumnVisibility(); + } else { + parent2.registerColumnField(this); + } + this._initialize(); + } + + createElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-col"); + el.setAttribute("role", "columnheader"); + el.setAttribute("aria-sort", "none"); + if (this.isRowHeader) { + el.classList.add("tabulator-row-header"); + } + switch (this.table.options.columnHeaderVertAlign) { + case "middle": + el.style.justifyContent = "center"; + break; + case "bottom": + el.style.justifyContent = "flex-end"; + break; + } + return el; + } + + createGroupElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-col-group-cols"); + return el; + } + + mapDefinitions() { + var defaults = this.table.options.columnDefaults; + if (defaults) { + for (let key in defaults) { + if (typeof this.definition[key] === "undefined") { + this.definition[key] = defaults[key]; + } + } + } + this.definition = this.table.columnManager.optionsList.generate(_Column.defaultOptionList, this.definition); + } + + checkDefinition() { + Object.keys(this.definition).forEach((key) => { + if (_Column.defaultOptionList.indexOf(key) === -1) { + console.warn("Invalid column definition option in '" + (this.field || this.definition.title) + "' column:", key); + } + }); + } + + setField(field) { + this.field = field; + this.fieldStructure = field ? this.table.options.nestedFieldSeparator ? field.split(this.table.options.nestedFieldSeparator) : [field] : []; + this.getFieldValue = this.fieldStructure.length > 1 ? this._getNestedData : this._getFlatData; + this.setFieldValue = this.fieldStructure.length > 1 ? this._setNestedData : this._setFlatData; + } + + //register column position with column manager + registerColumnPosition(column) { + this.parent.registerColumnPosition(column); + } + + //register column position with column manager + registerColumnField(column) { + this.parent.registerColumnField(column); + } + + //trigger position registration + reRegisterPosition() { + if (this.isGroup) { + this.columns.forEach(function (column) { + column.reRegisterPosition(); + }); + } else { + this.registerColumnPosition(this); + } + } + + //build header element + _initialize() { + var def = this.definition; + while (this.element.firstChild) this.element.removeChild(this.element.firstChild); + if (def.headerVertical) { + this.element.classList.add("tabulator-col-vertical"); + if (def.headerVertical === "flip") { + this.element.classList.add("tabulator-col-vertical-flip"); + } + } + this.contentElement = this._buildColumnHeaderContent(); + this.element.appendChild(this.contentElement); + if (this.isGroup) { + this._buildGroupHeader(); + } else { + this._buildColumnHeader(); + } + this.dispatch("column-init", this); + } + + //build header element for header + _buildColumnHeader() { + var def = this.definition; + this.dispatch("column-layout", this); + if (typeof def.visible != "undefined") { + if (def.visible) { + this.show(true); + } else { + this.hide(true); + } + } + if (def.cssClass) { + var classNames = def.cssClass.split(" "); + classNames.forEach((className) => { + this.element.classList.add(className); + }); + } + if (def.field) { + this.element.setAttribute("tabulator-field", def.field); + } + this.setMinWidth(parseInt(def.minWidth)); + if (def.maxInitialWidth) { + this.maxInitialWidth = parseInt(def.maxInitialWidth); + } + if (def.maxWidth) { + this.setMaxWidth(parseInt(def.maxWidth)); + } + this.reinitializeWidth(); + this.hozAlign = this.definition.hozAlign; + this.vertAlign = this.definition.vertAlign; + this.titleElement.style.textAlign = this.definition.headerHozAlign; + } + + _buildColumnHeaderContent() { + var contentElement = document.createElement("div"); + contentElement.classList.add("tabulator-col-content"); + this.titleHolderElement = document.createElement("div"); + this.titleHolderElement.classList.add("tabulator-col-title-holder"); + contentElement.appendChild(this.titleHolderElement); + this.titleElement = this._buildColumnHeaderTitle(); + this.titleHolderElement.appendChild(this.titleElement); + return contentElement; + } + + //build title element of column + _buildColumnHeaderTitle() { + var def = this.definition; + var titleHolderElement = document.createElement("div"); + titleHolderElement.classList.add("tabulator-col-title"); + if (def.headerWordWrap) { + titleHolderElement.classList.add("tabulator-col-title-wrap"); + } + if (def.editableTitle) { + var titleElement = document.createElement("input"); + titleElement.classList.add("tabulator-title-editor"); + titleElement.addEventListener("click", (e) => { + e.stopPropagation(); + titleElement.focus(); + }); + titleElement.addEventListener("mousedown", (e) => { + e.stopPropagation(); + }); + titleElement.addEventListener("change", () => { + def.title = titleElement.value; + this.dispatchExternal("columnTitleChanged", this.getComponent()); + }); + titleHolderElement.appendChild(titleElement); + if (def.field) { + this.langBind("columns|" + def.field, (text) => { + titleElement.value = text || (def.title || " "); + }); + } else { + titleElement.value = def.title || " "; + } + } else { + if (def.field) { + this.langBind("columns|" + def.field, (text) => { + this._formatColumnHeaderTitle(titleHolderElement, text || (def.title || " ")); + }); + } else { + this._formatColumnHeaderTitle(titleHolderElement, def.title || " "); + } + } + return titleHolderElement; + } + + _formatColumnHeaderTitle(el, title) { + var contents = this.chain("column-format", [this, title, el], null, () => { + return title; + }); + switch (typeof contents) { + case "object": + if (contents instanceof Node) { + el.appendChild(contents); + } else { + el.innerHTML = ""; + console.warn("Format Error - Title formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:", contents); + } + break; + case "undefined": + el.innerHTML = ""; + break; + default: + el.innerHTML = contents; + } + } + + //build header element for column group + _buildGroupHeader() { + this.element.classList.add("tabulator-col-group"); + this.element.setAttribute("role", "columngroup"); + this.element.setAttribute("aria-title", this.definition.title); + if (this.definition.cssClass) { + var classNames = this.definition.cssClass.split(" "); + classNames.forEach((className) => { + this.element.classList.add(className); + }); + } + this.titleElement.style.textAlign = this.definition.headerHozAlign; + this.element.appendChild(this.groupElement); + } + + //flat field lookup + _getFlatData(data) { + return data[this.field]; + } + + //nested field lookup + _getNestedData(data) { + var dataObj = data, structure = this.fieldStructure, length = structure.length, output; + for (let i = 0; i < length; i++) { + dataObj = dataObj[structure[i]]; + output = dataObj; + if (!dataObj) { + break; + } + } + return output; + } + + //flat field set + _setFlatData(data, value) { + if (this.field) { + data[this.field] = value; + } + } + + //nested field set + _setNestedData(data, value) { + var dataObj = data, structure = this.fieldStructure, length = structure.length; + for (let i = 0; i < length; i++) { + if (i == length - 1) { + dataObj[structure[i]] = value; + } else { + if (!dataObj[structure[i]]) { + if (typeof value !== "undefined") { + dataObj[structure[i]] = {}; + } else { + break; + } + } + dataObj = dataObj[structure[i]]; + } + } + } + + //attach column to this group + attachColumn(column) { + if (this.groupElement) { + this.columns.push(column); + this.groupElement.appendChild(column.getElement()); + column.columnRendered(); + } else { + console.warn("Column Warning - Column being attached to another column instead of column group"); + } + } + + //vertically align header in column + verticalAlign(alignment, height) { + var parentHeight = this.parent.isGroup ? this.parent.getGroupElement().clientHeight : height || this.parent.getHeadersElement().clientHeight; + this.element.style.height = parentHeight + "px"; + this.dispatch("column-height", this, this.element.style.height); + if (this.isGroup) { + this.groupElement.style.minHeight = parentHeight - this.contentElement.offsetHeight + "px"; + } + this.columns.forEach(function (column) { + column.verticalAlign(alignment); + }); + } + + //clear vertical alignment + clearVerticalAlign() { + this.element.style.paddingTop = ""; + this.element.style.height = ""; + this.element.style.minHeight = ""; + this.groupElement.style.minHeight = ""; + this.columns.forEach(function (column) { + column.clearVerticalAlign(); + }); + this.dispatch("column-height", this, ""); + } + + //// Retrieve Column Information //// + //return column header element + getElement() { + return this.element; + } + + //return column group element + getGroupElement() { + return this.groupElement; + } + + //return field name + getField() { + return this.field; + } + + getTitleDownload() { + return this.titleDownload; + } + + //return the first column in a group + getFirstColumn() { + if (!this.isGroup) { + return this; + } else { + if (this.columns.length) { + return this.columns[0].getFirstColumn(); + } else { + return false; + } + } + } + + //return the last column in a group + getLastColumn() { + if (!this.isGroup) { + return this; + } else { + if (this.columns.length) { + return this.columns[this.columns.length - 1].getLastColumn(); + } else { + return false; + } + } + } + + //return all columns in a group + getColumns(traverse) { + var columns = []; + if (traverse) { + this.columns.forEach((column) => { + columns.push(column); + columns = columns.concat(column.getColumns(true)); + }); + } else { + columns = this.columns; + } + return columns; + } + + //return all columns in a group + getCells() { + return this.cells; + } + + //retrieve the top column in a group of columns + getTopColumn() { + if (this.parent.isGroup) { + return this.parent.getTopColumn(); + } else { + return this; + } + } + + //return column definition object + getDefinition(updateBranches) { + var colDefs = []; + if (this.isGroup && updateBranches) { + this.columns.forEach(function (column) { + colDefs.push(column.getDefinition(true)); + }); + this.definition.columns = colDefs; + } + return this.definition; + } + + //////////////////// Actions //////////////////// + checkColumnVisibility() { + var visible = false; + this.columns.forEach(function (column) { + if (column.visible) { + visible = true; + } + }); + if (visible) { + this.show(); + this.dispatchExternal("columnVisibilityChanged", this.getComponent(), false); + } else { + this.hide(); + } + } + + //show column + show(silent, responsiveToggle) { + if (!this.visible) { + this.visible = true; + this.element.style.display = ""; + if (this.parent.isGroup) { + this.parent.checkColumnVisibility(); + } + this.cells.forEach(function (cell) { + cell.show(); + }); + if (!this.isGroup && this.width === null) { + this.reinitializeWidth(); + } + this.table.columnManager.verticalAlignHeaders(); + this.dispatch("column-show", this, responsiveToggle); + if (!silent) { + this.dispatchExternal("columnVisibilityChanged", this.getComponent(), true); + } + if (this.parent.isGroup) { + this.parent.matchChildWidths(); + } + if (!this.silent) { + this.table.columnManager.rerenderColumns(); + } + } + } + + //hide column + hide(silent, responsiveToggle) { + if (this.visible) { + this.visible = false; + this.element.style.display = "none"; + this.table.columnManager.verticalAlignHeaders(); + if (this.parent.isGroup) { + this.parent.checkColumnVisibility(); + } + this.cells.forEach(function (cell) { + cell.hide(); + }); + this.dispatch("column-hide", this, responsiveToggle); + if (!silent) { + this.dispatchExternal("columnVisibilityChanged", this.getComponent(), false); + } + if (this.parent.isGroup) { + this.parent.matchChildWidths(); + } + if (!this.silent) { + this.table.columnManager.rerenderColumns(); + } + } + } + + matchChildWidths() { + var childWidth = 0; + if (this.contentElement && this.columns.length) { + this.columns.forEach(function (column) { + if (column.visible) { + childWidth += column.getWidth(); + } + }); + this.contentElement.style.maxWidth = childWidth - 1 + "px"; + if (this.table.initialized) { + this.element.style.width = childWidth + "px"; + } + if (this.parent.isGroup) { + this.parent.matchChildWidths(); + } + } + } + + removeChild(child) { + var index = this.columns.indexOf(child); + if (index > -1) { + this.columns.splice(index, 1); + } + if (!this.columns.length) { + this.delete(); + } + } + + setWidth(width) { + this.widthFixed = true; + this.setWidthActual(width); + } + + setWidthActual(width) { + if (isNaN(width)) { + width = Math.floor(this.table.element.clientWidth / 100 * parseInt(width)); + } + width = Math.max(this.minWidth, width); + if (this.maxWidth) { + width = Math.min(this.maxWidth, width); + } + this.width = width; + this.widthStyled = width ? width + "px" : ""; + this.element.style.width = this.widthStyled; + if (!this.isGroup) { + this.cells.forEach(function (cell) { + cell.setWidth(); + }); + } + if (this.parent.isGroup) { + this.parent.matchChildWidths(); + } + this.dispatch("column-width", this); + if (this.subscribedExternal("columnWidth")) { + this.dispatchExternal("columnWidth", this.getComponent()); + } + } + + checkCellHeights() { + var rows2 = []; + this.cells.forEach(function (cell) { + if (cell.row.heightInitialized) { + if (cell.row.getElement().offsetParent !== null) { + rows2.push(cell.row); + cell.row.clearCellHeight(); + } else { + cell.row.heightInitialized = false; + } + } + }); + rows2.forEach(function (row) { + row.calcHeight(); + }); + rows2.forEach(function (row) { + row.setCellHeight(); + }); + } + + getWidth() { + var width = 0; + if (this.isGroup) { + this.columns.forEach(function (column) { + if (column.visible) { + width += column.getWidth(); + } + }); + } else { + width = this.width; + } + return width; + } + + getLeftOffset() { + var offset = this.element.offsetLeft; + if (this.parent.isGroup) { + offset += this.parent.getLeftOffset(); + } + return offset; + } + + getHeight() { + return Math.ceil(this.element.getBoundingClientRect().height); + } + + setMinWidth(minWidth) { + if (this.maxWidth && minWidth > this.maxWidth) { + minWidth = this.maxWidth; + console.warn("the minWidth (" + minWidth + "px) for column '" + this.field + "' cannot be bigger that its maxWidth (" + this.maxWidthStyled + ")"); + } + this.minWidth = minWidth; + this.minWidthStyled = minWidth ? minWidth + "px" : ""; + this.element.style.minWidth = this.minWidthStyled; + this.cells.forEach(function (cell) { + cell.setMinWidth(); + }); + } + + setMaxWidth(maxWidth) { + if (this.minWidth && maxWidth < this.minWidth) { + maxWidth = this.minWidth; + console.warn("the maxWidth (" + maxWidth + "px) for column '" + this.field + "' cannot be smaller that its minWidth (" + this.minWidthStyled + ")"); + } + this.maxWidth = maxWidth; + this.maxWidthStyled = maxWidth ? maxWidth + "px" : ""; + this.element.style.maxWidth = this.maxWidthStyled; + this.cells.forEach(function (cell) { + cell.setMaxWidth(); + }); + } + + delete() { + return new Promise((resolve, reject) => { + if (this.isGroup) { + this.columns.forEach(function (column) { + column.delete(); + }); + } + this.dispatch("column-delete", this); + var cellCount = this.cells.length; + for (let i = 0; i < cellCount; i++) { + this.cells[0].delete(); + } + if (this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + this.element = false; + this.contentElement = false; + this.titleElement = false; + this.groupElement = false; + if (this.parent.isGroup) { + this.parent.removeChild(this); + } + this.table.columnManager.deregisterColumn(this); + this.table.columnManager.rerenderColumns(true); + this.dispatch("column-deleted", this); + resolve(); + }); + } + + columnRendered() { + if (this.titleFormatterRendered) { + this.titleFormatterRendered(); + } + this.dispatch("column-rendered", this); + } + + //////////////// Cell Management ///////////////// + //generate cell for this column + generateCell(row) { + var cell = new Cell(this, row); + this.cells.push(cell); + return cell; + } + + nextColumn() { + var index = this.table.columnManager.findColumnIndex(this); + return index > -1 ? this._nextVisibleColumn(index + 1) : false; + } + + _nextVisibleColumn(index) { + var column = this.table.columnManager.getColumnByIndex(index); + return !column || column.visible ? column : this._nextVisibleColumn(index + 1); + } + + prevColumn() { + var index = this.table.columnManager.findColumnIndex(this); + return index > -1 ? this._prevVisibleColumn(index - 1) : false; + } + + _prevVisibleColumn(index) { + var column = this.table.columnManager.getColumnByIndex(index); + return !column || column.visible ? column : this._prevVisibleColumn(index - 1); + } + + reinitializeWidth(force) { + this.widthFixed = false; + if (typeof this.definition.width !== "undefined" && !force) { + this.setWidth(this.definition.width); + } + this.dispatch("column-width-fit-before", this); + this.fitToData(force); + this.dispatch("column-width-fit-after", this); + } + + //set column width to maximum cell width for non group columns + fitToData(force) { + if (this.isGroup) { + return; + } + if (!this.widthFixed) { + this.element.style.width = ""; + this.cells.forEach((cell) => { + cell.clearWidth(); + }); + } + var maxWidth = this.element.offsetWidth; + if (!this.width || !this.widthFixed) { + this.cells.forEach((cell) => { + var width = cell.getWidth(); + if (width > maxWidth) { + maxWidth = width; + } + }); + if (maxWidth) { + var setTo = maxWidth + 1; + if (force) { + this.setWidth(setTo); + } else { + if (this.maxInitialWidth && !force) { + setTo = Math.min(setTo, this.maxInitialWidth); + } + this.setWidthActual(setTo); + } + } + } + } + + updateDefinition(updates) { + var definition; + if (!this.isGroup) { + if (!this.parent.isGroup) { + definition = Object.assign({}, this.getDefinition()); + definition = Object.assign(definition, updates); + return this.table.columnManager.addColumn(definition, false, this).then((column) => { + if (definition.field == this.field) { + this.field = false; + } + return this.delete().then(() => { + return column.getComponent(); + }); + }); + } else { + console.error("Column Update Error - The updateDefinition function is only available on ungrouped columns"); + return Promise.reject("Column Update Error - The updateDefinition function is only available on columns, not column groups"); + } + } else { + console.error("Column Update Error - The updateDefinition function is only available on ungrouped columns"); + return Promise.reject("Column Update Error - The updateDefinition function is only available on columns, not column groups"); + } + } + + deleteCell(cell) { + var index = this.cells.indexOf(cell); + if (index > -1) { + this.cells.splice(index, 1); + } + } + + //////////////// Object Generation ///////////////// + getComponent() { + if (!this.component) { + this.component = new ColumnComponent(this); + } + return this.component; + } + + getPosition() { + return this.table.columnManager.getVisibleColumnsByIndex().indexOf(this) + 1; + } + + getParentComponent() { + return this.parent instanceof _Column ? this.parent.getComponent() : false; + } + }; + __publicField(_Column, "defaultOptionList", defaultColumnOptions); + let Column = _Column; + + class RowComponent { + constructor(row) { + this._row = row; + return new Proxy(this, { + get: function (target, name2, receiver) { + if (typeof target[name2] !== "undefined") { + return target[name2]; + } else { + return target._row.table.componentFunctionBinder.handle("row", target._row, name2); + } + } + }); + } + + getData(transform) { + return this._row.getData(transform); + } + + getElement() { + return this._row.getElement(); + } + + getCells() { + var cells = []; + this._row.getCells().forEach(function (cell) { + cells.push(cell.getComponent()); + }); + return cells; + } + + getCell(column) { + var cell = this._row.getCell(column); + return cell ? cell.getComponent() : false; + } + + getIndex() { + return this._row.getData("data")[this._row.table.options.index]; + } + + getPosition() { + return this._row.getPosition(); + } + + watchPosition(callback) { + return this._row.watchPosition(callback); + } + + delete() { + return this._row.delete(); + } + + scrollTo(position, ifVisible) { + return this._row.table.rowManager.scrollToRow(this._row, position, ifVisible); + } + + move(to, after) { + this._row.moveToRow(to, after); + } + + update(data) { + return this._row.updateData(data); + } + + normalizeHeight() { + this._row.normalizeHeight(true); + } + + _getSelf() { + return this._row; + } + + reformat() { + return this._row.reinitialize(); + } + + getTable() { + return this._row.table; + } + + getNextRow() { + var row = this._row.nextRow(); + return row ? row.getComponent() : row; + } + + getPrevRow() { + var row = this._row.prevRow(); + return row ? row.getComponent() : row; + } + } + + class Row extends CoreFeature { + constructor(data, parent2, type = "row") { + super(parent2.table); + this.parent = parent2; + this.data = {}; + this.type = type; + this.element = false; + this.modules = {}; + this.cells = []; + this.height = 0; + this.heightStyled = ""; + this.manualHeight = false; + this.outerHeight = 0; + this.initialized = false; + this.heightInitialized = false; + this.position = 0; + this.positionWatchers = []; + this.component = null; + this.created = false; + this.setData(data); + } + + create() { + if (!this.created) { + this.created = true; + this.generateElement(); + } + } + + createElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-row"); + el.setAttribute("role", "row"); + this.element = el; + } + + getElement() { + this.create(); + return this.element; + } + + detachElement() { + if (this.element && this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + } + + generateElement() { + this.createElement(); + this.dispatch("row-init", this); + } + + generateCells() { + this.cells = this.table.columnManager.generateCells(this); + } + + //functions to setup on first render + initialize(force, inFragment) { + this.create(); + if (!this.initialized || force) { + this.deleteCells(); + while (this.element.firstChild) this.element.removeChild(this.element.firstChild); + this.dispatch("row-layout-before", this); + this.generateCells(); + this.initialized = true; + this.table.columnManager.renderer.renderRowCells(this, inFragment); + if (force) { + this.normalizeHeight(); + } + this.dispatch("row-layout", this); + if (this.table.options.rowFormatter) { + this.table.options.rowFormatter(this.getComponent()); + } + this.dispatch("row-layout-after", this); + } else { + this.table.columnManager.renderer.rerenderRowCells(this, inFragment); + } + } + + rendered() { + this.cells.forEach((cell) => { + cell.cellRendered(); + }); + } + + reinitializeHeight() { + this.heightInitialized = false; + if (this.element && this.element.offsetParent !== null) { + this.normalizeHeight(true); + } + } + + deinitialize() { + this.initialized = false; + } + + deinitializeHeight() { + this.heightInitialized = false; + } + + reinitialize(children) { + this.initialized = false; + this.heightInitialized = false; + if (!this.manualHeight) { + this.height = 0; + this.heightStyled = ""; + } + if (this.element && this.element.offsetParent !== null) { + this.initialize(true); + } + this.dispatch("row-relayout", this); + } + + //get heights when doing bulk row style calcs in virtual DOM + calcHeight(force) { + var maxHeight = 0, minHeight = 0; + if (this.table.options.rowHeight) { + this.height = this.table.options.rowHeight; + } else { + minHeight = this.calcMinHeight(); + maxHeight = this.calcMaxHeight(); + if (force) { + this.height = Math.max(maxHeight, minHeight); + } else { + this.height = this.manualHeight ? this.height : Math.max(maxHeight, minHeight); + } + } + this.heightStyled = this.height ? this.height + "px" : ""; + this.outerHeight = this.element.offsetHeight; + } + + calcMinHeight() { + return this.table.options.resizableRows ? this.element.clientHeight : 0; + } + + calcMaxHeight() { + var maxHeight = 0; + this.cells.forEach(function (cell) { + var height = cell.getHeight(); + if (height > maxHeight) { + maxHeight = height; + } + }); + return maxHeight; + } + + //set of cells + setCellHeight() { + this.cells.forEach(function (cell) { + cell.setHeight(); + }); + this.heightInitialized = true; + } + + clearCellHeight() { + this.cells.forEach(function (cell) { + cell.clearHeight(); + }); + } + + //normalize the height of elements in the row + normalizeHeight(force) { + if (force && !this.table.options.rowHeight) { + this.clearCellHeight(); + } + this.calcHeight(force); + this.setCellHeight(); + } + + //set height of rows + setHeight(height, force) { + if (this.height != height || force) { + this.manualHeight = true; + this.height = height; + this.heightStyled = height ? height + "px" : ""; + this.setCellHeight(); + this.outerHeight = this.element.offsetHeight; + if (this.subscribedExternal("rowHeight")) { + this.dispatchExternal("rowHeight", this.getComponent()); + } + } + } + + //return rows outer height + getHeight() { + return this.outerHeight; + } + + //return rows outer Width + getWidth() { + return this.element.offsetWidth; + } + + //////////////// Cell Management ///////////////// + deleteCell(cell) { + var index = this.cells.indexOf(cell); + if (index > -1) { + this.cells.splice(index, 1); + } + } + + //////////////// Data Management ///////////////// + setData(data) { + this.data = this.chain("row-data-init-before", [this, data], void 0, data); + this.dispatch("row-data-init-after", this); + } + + //update the rows data + updateData(updatedData) { + var visible = this.element && Helpers.elVisible(this.element), tempData = {}, newRowData; + return new Promise((resolve, reject) => { + if (typeof updatedData === "string") { + updatedData = JSON.parse(updatedData); + } + this.dispatch("row-data-save-before", this); + if (this.subscribed("row-data-changing")) { + tempData = Object.assign(tempData, this.data); + tempData = Object.assign(tempData, updatedData); + } + newRowData = this.chain("row-data-changing", [this, tempData, updatedData], null, updatedData); + const cellsToUpdate = []; + for (let attrname in updatedData) { + let columns = this.table.columnManager.getColumnsByFieldRoot(attrname); + columns.forEach((column) => { + let cell = this.getCell(column.getField()); + if (cell) { + let value = column.getFieldValue(newRowData); + if (cell.getValue() !== value) { + cellsToUpdate.push([cell, value]); + } + } + }); + } + for (let attrname in newRowData) { + this.data[attrname] = newRowData[attrname]; + } + this.dispatch("row-data-save-after", this); + cellsToUpdate.forEach(([cell, value]) => { + cell.setValueProcessData(value); + if (visible) { + cell.cellRendered(); + } + }); + if (visible) { + this.normalizeHeight(true); + if (this.table.options.rowFormatter) { + this.table.options.rowFormatter(this.getComponent()); + } + } else { + this.initialized = false; + this.height = 0; + this.heightStyled = ""; + } + this.dispatch("row-data-changed", this, visible, updatedData); + this.dispatchExternal("rowUpdated", this.getComponent()); + if (this.subscribedExternal("dataChanged")) { + this.dispatchExternal("dataChanged", this.table.rowManager.getData()); + } + resolve(); + }); + } + + getData(transform) { + if (transform) { + return this.chain("row-data-retrieve", [this, transform], null, this.data); + } + return this.data; + } + + getCell(column) { + var match = false; + column = this.table.columnManager.findColumn(column); + if (!this.initialized && this.cells.length === 0) { + this.generateCells(); + } + match = this.cells.find(function (cell) { + return cell.column === column; + }); + return match; + } + + getCellIndex(findCell) { + return this.cells.findIndex(function (cell) { + return cell === findCell; + }); + } + + findCell(subject) { + return this.cells.find((cell) => { + return cell.element === subject; + }); + } + + getCells() { + if (!this.initialized && this.cells.length === 0) { + this.generateCells(); + } + return this.cells; + } + + nextRow() { + var row = this.table.rowManager.nextDisplayRow(this, true); + return row || false; + } + + prevRow() { + var row = this.table.rowManager.prevDisplayRow(this, true); + return row || false; + } + + moveToRow(to, before) { + var toRow = this.table.rowManager.findRow(to); + if (toRow) { + this.table.rowManager.moveRowActual(this, toRow, !before); + this.table.rowManager.refreshActiveData("display", false, true); + } else { + console.warn("Move Error - No matching row found:", to); + } + } + + ///////////////////// Actions ///////////////////// + delete() { + this.dispatch("row-delete", this); + this.deleteActual(); + return Promise.resolve(); + } + + deleteActual(blockRedraw) { + this.detachModules(); + this.table.rowManager.deleteRow(this, blockRedraw); + this.deleteCells(); + this.initialized = false; + this.heightInitialized = false; + this.element = false; + this.dispatch("row-deleted", this); + } + + detachModules() { + this.dispatch("row-deleting", this); + } + + deleteCells() { + var cellCount = this.cells.length; + for (let i = 0; i < cellCount; i++) { + this.cells[0].delete(); + } + } + + wipe() { + this.detachModules(); + this.deleteCells(); + if (this.element) { + while (this.element.firstChild) this.element.removeChild(this.element.firstChild); + if (this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + } + this.element = false; + this.modules = {}; + } + + isDisplayed() { + return this.table.rowManager.getDisplayRows().includes(this); + } + + getPosition() { + return this.isDisplayed() ? this.position : false; + } + + setPosition(position) { + if (position != this.position) { + this.position = position; + this.positionWatchers.forEach((callback) => { + callback(this.position); + }); + } + } + + watchPosition(callback) { + this.positionWatchers.push(callback); + callback(this.position); + } + + getGroup() { + return this.modules.group || false; + } + + //////////////// Object Generation ///////////////// + getComponent() { + if (!this.component) { + this.component = new RowComponent(this); + } + return this.component; + } + } + + var defaultCalculations = { + "avg": function (values, data, calcParams) { + var output = 0, precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : 2; + if (values.length) { + output = values.reduce(function (sum, value) { + return Number(sum) + Number(value); + }); + output = output / values.length; + output = precision !== false ? output.toFixed(precision) : output; + } + return parseFloat(output).toString(); + }, + "max": function (values, data, calcParams) { + var output = null, + precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : false; + values.forEach(function (value) { + value = Number(value); + if (value > output || output === null) { + output = value; + } + }); + return output !== null ? precision !== false ? output.toFixed(precision) : output : ""; + }, + "min": function (values, data, calcParams) { + var output = null, + precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : false; + values.forEach(function (value) { + value = Number(value); + if (value < output || output === null) { + output = value; + } + }); + return output !== null ? precision !== false ? output.toFixed(precision) : output : ""; + }, + "sum": function (values, data, calcParams) { + var output = 0, precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : false; + if (values.length) { + values.forEach(function (value) { + value = Number(value); + output += !isNaN(value) ? Number(value) : 0; + }); + } + return precision !== false ? output.toFixed(precision) : output; + }, + "concat": function (values, data, calcParams) { + var output = 0; + if (values.length) { + output = values.reduce(function (sum, value) { + return String(sum) + String(value); + }); + } + return output; + }, + "count": function (values, data, calcParams) { + var output = 0; + if (values.length) { + values.forEach(function (value) { + if (value) { + output++; + } + }); + } + return output; + }, + "unique": function (values, data, calcParams) { + var unique = values.filter((value, index) => { + return (values || value === 0) && values.indexOf(value) === index; + }); + return unique.length; + } + }; + const _ColumnCalcs = class _ColumnCalcs extends Module { + constructor(table) { + super(table); + this.topCalcs = []; + this.botCalcs = []; + this.genColumn = false; + this.topElement = this.createElement(); + this.botElement = this.createElement(); + this.topRow = false; + this.botRow = false; + this.topInitialized = false; + this.botInitialized = false; + this.blocked = false; + this.recalcAfterBlock = false; + this.registerTableOption("columnCalcs", true); + this.registerColumnOption("topCalc"); + this.registerColumnOption("topCalcParams"); + this.registerColumnOption("topCalcFormatter"); + this.registerColumnOption("topCalcFormatterParams"); + this.registerColumnOption("bottomCalc"); + this.registerColumnOption("bottomCalcParams"); + this.registerColumnOption("bottomCalcFormatter"); + this.registerColumnOption("bottomCalcFormatterParams"); + } + + createElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-calcs-holder"); + return el; + } + + initialize() { + this.genColumn = new Column({field: "value"}, this); + this.subscribe("cell-value-changed", this.cellValueChanged.bind(this)); + this.subscribe("column-init", this.initializeColumnCheck.bind(this)); + this.subscribe("row-deleted", this.rowsUpdated.bind(this)); + this.subscribe("scroll-horizontal", this.scrollHorizontal.bind(this)); + this.subscribe("row-added", this.rowsUpdated.bind(this)); + this.subscribe("column-moved", this.recalcActiveRows.bind(this)); + this.subscribe("column-add", this.recalcActiveRows.bind(this)); + this.subscribe("data-refreshed", this.recalcActiveRowsRefresh.bind(this)); + this.subscribe("table-redraw", this.tableRedraw.bind(this)); + this.subscribe("rows-visible", this.visibleRows.bind(this)); + this.subscribe("scrollbar-vertical", this.adjustForScrollbar.bind(this)); + this.subscribe("redraw-blocked", this.blockRedraw.bind(this)); + this.subscribe("redraw-restored", this.restoreRedraw.bind(this)); + this.subscribe("table-redrawing", this.resizeHolderWidth.bind(this)); + this.subscribe("column-resized", this.resizeHolderWidth.bind(this)); + this.subscribe("column-show", this.resizeHolderWidth.bind(this)); + this.subscribe("column-hide", this.resizeHolderWidth.bind(this)); + this.registerTableFunction("getCalcResults", this.getResults.bind(this)); + this.registerTableFunction("recalc", this.userRecalc.bind(this)); + this.resizeHolderWidth(); + } + + resizeHolderWidth() { + this.topElement.style.minWidth = this.table.columnManager.headersElement.offsetWidth + "px"; + } + + tableRedraw(force) { + this.recalc(this.table.rowManager.activeRows); + if (force) { + this.redraw(); + } + } + + blockRedraw() { + this.blocked = true; + this.recalcAfterBlock = false; + } + + restoreRedraw() { + this.blocked = false; + if (this.recalcAfterBlock) { + this.recalcAfterBlock = false; + this.recalcActiveRowsRefresh(); + } + } + + /////////////////////////////////// + ///////// Table Functions ///////// + /////////////////////////////////// + userRecalc() { + this.recalc(this.table.rowManager.activeRows); + } + + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + blockCheck() { + if (this.blocked) { + this.recalcAfterBlock = true; + } + return this.blocked; + } + + visibleRows(viewable, rows2) { + if (this.topRow) { + rows2.unshift(this.topRow); + } + if (this.botRow) { + rows2.push(this.botRow); + } + return rows2; + } + + rowsUpdated(row) { + if (this.table.options.groupBy) { + this.recalcRowGroup(row); + } else { + this.recalcActiveRows(); + } + } + + recalcActiveRowsRefresh() { + if (this.table.options.groupBy && this.table.options.dataTreeStartExpanded && this.table.options.dataTree) { + this.recalcAll(); + } else { + this.recalcActiveRows(); + } + } + + recalcActiveRows() { + this.recalc(this.table.rowManager.activeRows); + } + + cellValueChanged(cell) { + if (cell.column.definition.topCalc || cell.column.definition.bottomCalc) { + if (this.table.options.groupBy) { + if (this.table.options.columnCalcs == "table" || this.table.options.columnCalcs == "both") { + this.recalcActiveRows(); + } + if (this.table.options.columnCalcs != "table") { + this.recalcRowGroup(cell.row); + } + } else { + this.recalcActiveRows(); + } + } + } + + initializeColumnCheck(column) { + if (column.definition.topCalc || column.definition.bottomCalc) { + this.initializeColumn(column); + } + } + + //initialize column calcs + initializeColumn(column) { + var def = column.definition; + var config = { + topCalcParams: def.topCalcParams || {}, + botCalcParams: def.bottomCalcParams || {} + }; + if (def.topCalc) { + switch (typeof def.topCalc) { + case "string": + if (_ColumnCalcs.calculations[def.topCalc]) { + config.topCalc = _ColumnCalcs.calculations[def.topCalc]; + } else { + console.warn("Column Calc Error - No such calculation found, ignoring: ", def.topCalc); + } + break; + case "function": + config.topCalc = def.topCalc; + break; + } + if (config.topCalc) { + column.modules.columnCalcs = config; + this.topCalcs.push(column); + if (this.table.options.columnCalcs != "group") { + this.initializeTopRow(); + } + } + } + if (def.bottomCalc) { + switch (typeof def.bottomCalc) { + case "string": + if (_ColumnCalcs.calculations[def.bottomCalc]) { + config.botCalc = _ColumnCalcs.calculations[def.bottomCalc]; + } else { + console.warn("Column Calc Error - No such calculation found, ignoring: ", def.bottomCalc); + } + break; + case "function": + config.botCalc = def.bottomCalc; + break; + } + if (config.botCalc) { + column.modules.columnCalcs = config; + this.botCalcs.push(column); + if (this.table.options.columnCalcs != "group") { + this.initializeBottomRow(); + } + } + } + } + + //dummy functions to handle being mock column manager + registerColumnField() { + } + + removeCalcs() { + var changed = false; + if (this.topInitialized) { + this.topInitialized = false; + this.topElement.parentNode.removeChild(this.topElement); + changed = true; + } + if (this.botInitialized) { + this.botInitialized = false; + this.footerRemove(this.botElement); + changed = true; + } + if (changed) { + this.table.rowManager.adjustTableSize(); + } + } + + reinitializeCalcs() { + if (this.topCalcs.length) { + this.initializeTopRow(); + } + if (this.botCalcs.length) { + this.initializeBottomRow(); + } + } + + initializeTopRow() { + var fragment = document.createDocumentFragment(); + if (!this.topInitialized) { + fragment.appendChild(document.createElement("br")); + fragment.appendChild(this.topElement); + this.table.columnManager.getContentsElement().insertBefore(fragment, this.table.columnManager.headersElement.nextSibling); + this.topInitialized = true; + } + } + + initializeBottomRow() { + if (!this.botInitialized) { + this.footerPrepend(this.botElement); + this.botInitialized = true; + } + } + + scrollHorizontal(left) { + if (this.botInitialized && this.botRow) { + this.botElement.scrollLeft = left; + } + } + + recalc(rows2) { + var data, row; + if (!this.blockCheck()) { + if (this.topInitialized || this.botInitialized) { + data = this.rowsToData(rows2); + if (this.topInitialized) { + if (this.topRow) { + this.topRow.deleteCells(); + } + row = this.generateRow("top", data); + this.topRow = row; + while (this.topElement.firstChild) this.topElement.removeChild(this.topElement.firstChild); + this.topElement.appendChild(row.getElement()); + row.initialize(true); + } + if (this.botInitialized) { + if (this.botRow) { + this.botRow.deleteCells(); + } + row = this.generateRow("bottom", data); + this.botRow = row; + while (this.botElement.firstChild) this.botElement.removeChild(this.botElement.firstChild); + this.botElement.appendChild(row.getElement()); + row.initialize(true); + } + this.table.rowManager.adjustTableSize(); + if (this.table.modExists("frozenColumns")) { + this.table.modules.frozenColumns.layout(); + } + } + } + } + + recalcRowGroup(row) { + this.recalcGroup(this.table.modules.groupRows.getRowGroup(row)); + } + + recalcAll() { + if (this.topCalcs.length || this.botCalcs.length) { + if (this.table.options.columnCalcs !== "group") { + this.recalcActiveRows(); + } + if (this.table.options.groupBy && this.table.options.columnCalcs !== "table") { + var groups = this.table.modules.groupRows.getChildGroups(); + groups.forEach((group) => { + this.recalcGroup(group); + }); + } + } + } + + recalcGroup(group) { + var data, rowData; + if (!this.blockCheck()) { + if (group) { + if (group.calcs) { + if (group.calcs.bottom) { + data = this.rowsToData(group.rows); + rowData = this.generateRowData("bottom", data); + group.calcs.bottom.updateData(rowData); + group.calcs.bottom.reinitialize(); + } + if (group.calcs.top) { + data = this.rowsToData(group.rows); + rowData = this.generateRowData("top", data); + group.calcs.top.updateData(rowData); + group.calcs.top.reinitialize(); + } + } + } + } + } + + //generate top stats row + generateTopRow(rows2) { + return this.generateRow("top", this.rowsToData(rows2)); + } + + //generate bottom stats row + generateBottomRow(rows2) { + return this.generateRow("bottom", this.rowsToData(rows2)); + } + + rowsToData(rows2) { + var data = [], + hasDataTreeColumnCalcs = this.table.options.dataTree && this.table.options.dataTreeChildColumnCalcs, + dataTree = this.table.modules.dataTree; + rows2.forEach((row) => { + var _a2; + data.push(row.getData()); + if (hasDataTreeColumnCalcs && ((_a2 = row.modules.dataTree) == null ? void 0 : _a2.open)) { + this.rowsToData(dataTree.getFilteredTreeChildren(row)).forEach((dataRow) => { + data.push(dataRow); + }); + } + }); + return data; + } + + //generate stats row + generateRow(pos, data) { + var rowData = this.generateRowData(pos, data), row; + if (this.table.modExists("mutator")) { + this.table.modules.mutator.disable(); + } + row = new Row(rowData, this, "calc"); + if (this.table.modExists("mutator")) { + this.table.modules.mutator.enable(); + } + row.getElement().classList.add("tabulator-calcs", "tabulator-calcs-" + pos); + row.component = false; + row.getComponent = () => { + if (!row.component) { + row.component = new CalcComponent(row); + } + return row.component; + }; + row.generateCells = () => { + var cells = []; + this.table.columnManager.columnsByIndex.forEach((column) => { + this.genColumn.setField(column.getField()); + this.genColumn.hozAlign = column.hozAlign; + if (column.definition[pos + "CalcFormatter"] && this.table.modExists("format")) { + this.genColumn.modules.format = { + formatter: this.table.modules.format.lookupFormatter(column.definition[pos + "CalcFormatter"]), + params: column.definition[pos + "CalcFormatterParams"] || {} + }; + } else { + this.genColumn.modules.format = { + formatter: this.table.modules.format.lookupFormatter("plaintext"), + params: {} + }; + } + this.genColumn.definition.cssClass = column.definition.cssClass; + var cell = new Cell(this.genColumn, row); + cell.getElement(); + cell.column = column; + cell.setWidth(); + column.cells.push(cell); + cells.push(cell); + if (!column.visible) { + cell.hide(); + } + }); + row.cells = cells; + }; + return row; + } + + //generate stats row + generateRowData(pos, data) { + var rowData = {}, calcs = pos == "top" ? this.topCalcs : this.botCalcs, + type = pos == "top" ? "topCalc" : "botCalc", params, paramKey; + calcs.forEach(function (column) { + var values = []; + if (column.modules.columnCalcs && column.modules.columnCalcs[type]) { + data.forEach(function (item) { + values.push(column.getFieldValue(item)); + }); + paramKey = type + "Params"; + params = typeof column.modules.columnCalcs[paramKey] === "function" ? column.modules.columnCalcs[paramKey](values, data) : column.modules.columnCalcs[paramKey]; + column.setFieldValue(rowData, column.modules.columnCalcs[type](values, data, params)); + } + }); + return rowData; + } + + hasTopCalcs() { + return !!this.topCalcs.length; + } + + hasBottomCalcs() { + return !!this.botCalcs.length; + } + + //handle table redraw + redraw() { + if (this.topRow) { + this.topRow.normalizeHeight(true); + } + if (this.botRow) { + this.botRow.normalizeHeight(true); + } + } + + //return the calculated + getResults() { + var results = {}, groups; + if (this.table.options.groupBy && this.table.modExists("groupRows")) { + groups = this.table.modules.groupRows.getGroups(true); + groups.forEach((group) => { + results[group.getKey()] = this.getGroupResults(group); + }); + } else { + results = { + top: this.topRow ? this.topRow.getData() : {}, + bottom: this.botRow ? this.botRow.getData() : {} + }; + } + return results; + } + + //get results from a group + getGroupResults(group) { + var groupObj = group._getSelf(), subGroups = group.getSubGroups(), subGroupResults = {}, results = {}; + subGroups.forEach((subgroup) => { + subGroupResults[subgroup.getKey()] = this.getGroupResults(subgroup); + }); + results = { + top: groupObj.calcs.top ? groupObj.calcs.top.getData() : {}, + bottom: groupObj.calcs.bottom ? groupObj.calcs.bottom.getData() : {}, + groups: subGroupResults + }; + return results; + } + + adjustForScrollbar(width) { + if (this.botRow) { + if (this.table.rtl) { + this.botElement.style.paddingLeft = width + "px"; + } else { + this.botElement.style.paddingRight = width + "px"; + } + } + } + }; + __publicField(_ColumnCalcs, "moduleName", "columnCalcs"); + //load defaults + __publicField(_ColumnCalcs, "calculations", defaultCalculations); + let ColumnCalcs = _ColumnCalcs; + + class DataTree extends Module { + constructor(table) { + super(table); + this.indent = 10; + this.field = ""; + this.collapseEl = null; + this.expandEl = null; + this.branchEl = null; + this.elementField = false; + this.startOpen = function () { + }; + this.registerTableOption("dataTree", false); + this.registerTableOption("dataTreeFilter", true); + this.registerTableOption("dataTreeSort", true); + this.registerTableOption("dataTreeElementColumn", false); + this.registerTableOption("dataTreeBranchElement", true); + this.registerTableOption("dataTreeChildIndent", 9); + this.registerTableOption("dataTreeChildField", "_children"); + this.registerTableOption("dataTreeCollapseElement", false); + this.registerTableOption("dataTreeExpandElement", false); + this.registerTableOption("dataTreeStartExpanded", false); + this.registerTableOption("dataTreeChildColumnCalcs", false); + this.registerTableOption("dataTreeSelectPropagate", false); + this.registerComponentFunction("row", "treeCollapse", this.collapseRow.bind(this)); + this.registerComponentFunction("row", "treeExpand", this.expandRow.bind(this)); + this.registerComponentFunction("row", "treeToggle", this.toggleRow.bind(this)); + this.registerComponentFunction("row", "getTreeParent", this.getTreeParent.bind(this)); + this.registerComponentFunction("row", "getTreeChildren", this.getRowChildren.bind(this)); + this.registerComponentFunction("row", "addTreeChild", this.addTreeChildRow.bind(this)); + this.registerComponentFunction("row", "isTreeExpanded", this.isRowExpanded.bind(this)); + } + + initialize() { + if (this.table.options.dataTree) { + var dummyEl = null, options = this.table.options; + this.field = options.dataTreeChildField; + this.indent = options.dataTreeChildIndent; + if (this.options("movableRows")) { + console.warn("The movableRows option is not available with dataTree enabled, moving of child rows could result in unpredictable behavior"); + } + if (options.dataTreeBranchElement) { + if (options.dataTreeBranchElement === true) { + this.branchEl = document.createElement("div"); + this.branchEl.classList.add("tabulator-data-tree-branch"); + } else { + if (typeof options.dataTreeBranchElement === "string") { + dummyEl = document.createElement("div"); + dummyEl.innerHTML = options.dataTreeBranchElement; + this.branchEl = dummyEl.firstChild; + } else { + this.branchEl = options.dataTreeBranchElement; + } + } + } else { + this.branchEl = document.createElement("div"); + this.branchEl.classList.add("tabulator-data-tree-branch-empty"); + } + if (options.dataTreeCollapseElement) { + if (typeof options.dataTreeCollapseElement === "string") { + dummyEl = document.createElement("div"); + dummyEl.innerHTML = options.dataTreeCollapseElement; + this.collapseEl = dummyEl.firstChild; + } else { + this.collapseEl = options.dataTreeCollapseElement; + } + } else { + this.collapseEl = document.createElement("div"); + this.collapseEl.classList.add("tabulator-data-tree-control"); + this.collapseEl.tabIndex = 0; + this.collapseEl.innerHTML = "
"; + } + if (options.dataTreeExpandElement) { + if (typeof options.dataTreeExpandElement === "string") { + dummyEl = document.createElement("div"); + dummyEl.innerHTML = options.dataTreeExpandElement; + this.expandEl = dummyEl.firstChild; + } else { + this.expandEl = options.dataTreeExpandElement; + } + } else { + this.expandEl = document.createElement("div"); + this.expandEl.classList.add("tabulator-data-tree-control"); + this.expandEl.tabIndex = 0; + this.expandEl.innerHTML = "
"; + } + switch (typeof options.dataTreeStartExpanded) { + case "boolean": + this.startOpen = function (row, index) { + return options.dataTreeStartExpanded; + }; + break; + case "function": + this.startOpen = options.dataTreeStartExpanded; + break; + default: + this.startOpen = function (row, index) { + return options.dataTreeStartExpanded[index]; + }; + break; + } + this.subscribe("row-init", this.initializeRow.bind(this)); + this.subscribe("row-layout-after", this.layoutRow.bind(this)); + this.subscribe("row-deleting", this.rowDeleting.bind(this)); + this.subscribe("row-deleted", this.rowDelete.bind(this), 0); + this.subscribe("row-data-changed", this.rowDataChanged.bind(this), 10); + this.subscribe("cell-value-updated", this.cellValueChanged.bind(this)); + this.subscribe("edit-cancelled", this.cellValueChanged.bind(this)); + this.subscribe("column-moving-rows", this.columnMoving.bind(this)); + this.subscribe("table-built", this.initializeElementField.bind(this)); + this.subscribe("table-redrawing", this.tableRedrawing.bind(this)); + this.registerDisplayHandler(this.getRows.bind(this), 30); + } + } + + tableRedrawing(force) { + var rows2; + if (force) { + rows2 = this.table.rowManager.getRows(); + rows2.forEach((row) => { + this.reinitializeRowChildren(row); + }); + } + } + + initializeElementField() { + var firstCol = this.table.columnManager.getFirstVisibleColumn(); + this.elementField = this.table.options.dataTreeElementColumn || (firstCol ? firstCol.field : false); + } + + getRowChildren(row) { + return this.getTreeChildren(row, true); + } + + columnMoving() { + var rows2 = []; + this.table.rowManager.rows.forEach((row) => { + rows2 = rows2.concat(this.getTreeChildren(row, false, true)); + }); + return rows2; + } + + rowDataChanged(row, visible, updatedData) { + if (this.redrawNeeded(updatedData)) { + this.initializeRow(row); + if (visible) { + this.layoutRow(row); + this.refreshData(true); + } + } + } + + cellValueChanged(cell) { + var field = cell.column.getField(); + if (field === this.elementField) { + this.layoutRow(cell.row); + } + } + + initializeRow(row) { + var childArray = row.getData()[this.field]; + var isArray = Array.isArray(childArray); + var children = isArray || !isArray && typeof childArray === "object" && childArray !== null; + if (!children && row.modules.dataTree && row.modules.dataTree.branchEl && row.modules.dataTree.branchEl.parentNode) { + row.modules.dataTree.branchEl.parentNode.removeChild(row.modules.dataTree.branchEl); + } + if (!children && row.modules.dataTree && row.modules.dataTree.controlEl && row.modules.dataTree.controlEl.parentNode) { + row.modules.dataTree.controlEl.parentNode.removeChild(row.modules.dataTree.controlEl); + } + row.modules.dataTree = { + index: row.modules.dataTree ? row.modules.dataTree.index : 0, + open: children ? row.modules.dataTree ? row.modules.dataTree.open : this.startOpen(row.getComponent(), 0) : false, + controlEl: row.modules.dataTree && children ? row.modules.dataTree.controlEl : false, + branchEl: row.modules.dataTree && children ? row.modules.dataTree.branchEl : false, + parent: row.modules.dataTree ? row.modules.dataTree.parent : false, + children + }; + } + + reinitializeRowChildren(row) { + var children = this.getTreeChildren(row, false, true); + children.forEach(function (child) { + child.reinitialize(true); + }); + } + + layoutRow(row) { + var cell = this.elementField ? row.getCell(this.elementField) : row.getCells()[0], + el = cell.getElement(), config = row.modules.dataTree; + if (config.branchEl) { + if (config.branchEl.parentNode) { + config.branchEl.parentNode.removeChild(config.branchEl); + } + config.branchEl = false; + } + if (config.controlEl) { + if (config.controlEl.parentNode) { + config.controlEl.parentNode.removeChild(config.controlEl); + } + config.controlEl = false; + } + this.generateControlElement(row, el); + row.getElement().classList.add("tabulator-tree-level-" + config.index); + if (config.index) { + if (this.branchEl) { + config.branchEl = this.branchEl.cloneNode(true); + el.insertBefore(config.branchEl, el.firstChild); + if (this.table.rtl) { + config.branchEl.style.marginRight = (config.branchEl.offsetWidth + config.branchEl.style.marginLeft) * (config.index - 1) + config.index * this.indent + "px"; + } else { + config.branchEl.style.marginLeft = (config.branchEl.offsetWidth + config.branchEl.style.marginRight) * (config.index - 1) + config.index * this.indent + "px"; + } + } else { + if (this.table.rtl) { + el.style.paddingRight = parseInt(window.getComputedStyle(el, null).getPropertyValue("padding-right")) + config.index * this.indent + "px"; + } else { + el.style.paddingLeft = parseInt(window.getComputedStyle(el, null).getPropertyValue("padding-left")) + config.index * this.indent + "px"; + } + } + } + } + + generateControlElement(row, el) { + var config = row.modules.dataTree, oldControl = config.controlEl; + el = el || row.getCells()[0].getElement(); + if (config.children !== false) { + if (config.open) { + config.controlEl = this.collapseEl.cloneNode(true); + config.controlEl.addEventListener("click", (e) => { + e.stopPropagation(); + this.collapseRow(row); + }); + } else { + config.controlEl = this.expandEl.cloneNode(true); + config.controlEl.addEventListener("click", (e) => { + e.stopPropagation(); + this.expandRow(row); + }); + } + config.controlEl.addEventListener("mousedown", (e) => { + e.stopPropagation(); + }); + if (oldControl && oldControl.parentNode === el) { + oldControl.parentNode.replaceChild(config.controlEl, oldControl); + } else { + el.insertBefore(config.controlEl, el.firstChild); + } + } + } + + getRows(rows2) { + var output = []; + rows2.forEach((row, i) => { + var config, children; + output.push(row); + if (row instanceof Row) { + row.create(); + config = row.modules.dataTree; + if (!config.index && config.children !== false) { + children = this.getChildren(row, false, true); + children.forEach((child) => { + child.create(); + output.push(child); + }); + } + } + }); + return output; + } + + getChildren(row, allChildren, sortOnly) { + var config = row.modules.dataTree, children = [], output = []; + if (config.children !== false && (config.open || allChildren)) { + if (!Array.isArray(config.children)) { + config.children = this.generateChildren(row); + } + if (this.table.modExists("filter") && this.table.options.dataTreeFilter) { + children = this.table.modules.filter.filter(config.children); + } else { + children = config.children; + } + if (this.table.modExists("sort") && this.table.options.dataTreeSort) { + this.table.modules.sort.sort(children, sortOnly); + } + children.forEach((child) => { + output.push(child); + var subChildren = this.getChildren(child, false, true); + subChildren.forEach((sub) => { + output.push(sub); + }); + }); + } + return output; + } + + generateChildren(row) { + var children = []; + var childArray = row.getData()[this.field]; + if (!Array.isArray(childArray)) { + childArray = [childArray]; + } + childArray.forEach((childData) => { + var childRow = new Row(childData || {}, this.table.rowManager); + childRow.create(); + childRow.modules.dataTree.index = row.modules.dataTree.index + 1; + childRow.modules.dataTree.parent = row; + if (childRow.modules.dataTree.children) { + childRow.modules.dataTree.open = this.startOpen(childRow.getComponent(), childRow.modules.dataTree.index); + } + children.push(childRow); + }); + return children; + } + + expandRow(row, silent) { + var config = row.modules.dataTree; + if (config.children !== false) { + config.open = true; + row.reinitialize(); + this.refreshData(true); + this.dispatchExternal("dataTreeRowExpanded", row.getComponent(), row.modules.dataTree.index); + } + } + + collapseRow(row) { + var config = row.modules.dataTree; + if (config.children !== false) { + config.open = false; + row.reinitialize(); + this.refreshData(true); + this.dispatchExternal("dataTreeRowCollapsed", row.getComponent(), row.modules.dataTree.index); + } + } + + toggleRow(row) { + var config = row.modules.dataTree; + if (config.children !== false) { + if (config.open) { + this.collapseRow(row); + } else { + this.expandRow(row); + } + } + } + + isRowExpanded(row) { + return row.modules.dataTree.open; + } + + getTreeParent(row) { + return row.modules.dataTree.parent ? row.modules.dataTree.parent.getComponent() : false; + } + + getTreeParentRoot(row) { + return row.modules.dataTree && row.modules.dataTree.parent ? this.getTreeParentRoot(row.modules.dataTree.parent) : row; + } + + getFilteredTreeChildren(row) { + var config = row.modules.dataTree, output = [], children; + if (config.children) { + if (!Array.isArray(config.children)) { + config.children = this.generateChildren(row); + } + if (this.table.modExists("filter") && this.table.options.dataTreeFilter) { + children = this.table.modules.filter.filter(config.children); + } else { + children = config.children; + } + children.forEach((childRow) => { + if (childRow instanceof Row) { + output.push(childRow); + } + }); + } + return output; + } + + rowDeleting(row) { + var config = row.modules.dataTree; + if (config && config.children && Array.isArray(config.children)) { + config.children.forEach((childRow) => { + if (childRow instanceof Row) { + childRow.wipe(); + } + }); + } + } + + rowDelete(row) { + var parent2 = row.modules.dataTree.parent, childIndex; + if (parent2) { + childIndex = this.findChildIndex(row, parent2); + if (childIndex !== false) { + parent2.data[this.field].splice(childIndex, 1); + } + if (!parent2.data[this.field].length) { + delete parent2.data[this.field]; + } + this.initializeRow(parent2); + this.layoutRow(parent2); + } + this.refreshData(true); + } + + addTreeChildRow(row, data, top, index) { + var childIndex = false; + if (typeof data === "string") { + data = JSON.parse(data); + } + if (!Array.isArray(row.data[this.field])) { + row.data[this.field] = []; + row.modules.dataTree.open = this.startOpen(row.getComponent(), row.modules.dataTree.index); + } + if (typeof index !== "undefined") { + childIndex = this.findChildIndex(index, row); + if (childIndex !== false) { + row.data[this.field].splice(top ? childIndex : childIndex + 1, 0, data); + } + } + if (childIndex === false) { + if (top) { + row.data[this.field].unshift(data); + } else { + row.data[this.field].push(data); + } + } + this.initializeRow(row); + this.layoutRow(row); + this.refreshData(true); + } + + findChildIndex(subject, parent2) { + var match = false; + if (typeof subject == "object") { + if (subject instanceof Row) { + match = subject.data; + } else if (subject instanceof RowComponent) { + match = subject._getSelf().data; + } else if (typeof HTMLElement !== "undefined" && subject instanceof HTMLElement) { + if (parent2.modules.dataTree) { + match = parent2.modules.dataTree.children.find((childRow) => { + return childRow instanceof Row ? childRow.element === subject : false; + }); + if (match) { + match = match.data; + } + } + } else if (subject === null) { + match = false; + } + } else if (typeof subject == "undefined") { + match = false; + } else { + match = parent2.data[this.field].find((row) => { + return row.data[this.table.options.index] == subject; + }); + } + if (match) { + if (Array.isArray(parent2.data[this.field])) { + match = parent2.data[this.field].indexOf(match); + } + if (match == -1) { + match = false; + } + } + return match; + } + + getTreeChildren(row, component, recurse) { + var config = row.modules.dataTree, output = []; + if (config && config.children) { + if (!Array.isArray(config.children)) { + config.children = this.generateChildren(row); + } + config.children.forEach((childRow) => { + if (childRow instanceof Row) { + output.push(component ? childRow.getComponent() : childRow); + if (recurse) { + this.getTreeChildren(childRow, component, recurse).forEach((child) => { + output.push(child); + }); + } + } + }); + } + return output; + } + + getChildField() { + return this.field; + } + + redrawNeeded(data) { + return (this.field ? typeof data[this.field] !== "undefined" : false) || (this.elementField ? typeof data[this.elementField] !== "undefined" : false); + } + } + + __publicField(DataTree, "moduleName", "dataTree"); + + function csv$1(list2, options = {}, setFileContents) { + var delimiter = options.delimiter ? options.delimiter : ",", fileContents = [], headers = []; + list2.forEach((row) => { + var item = []; + switch (row.type) { + case "group": + console.warn("Download Warning - CSV downloader cannot process row groups"); + break; + case "calc": + console.warn("Download Warning - CSV downloader cannot process column calculations"); + break; + case "header": + row.columns.forEach((col, i) => { + if (col && col.depth === 1) { + headers[i] = typeof col.value == "undefined" || col.value === null ? "" : '"' + String(col.value).split('"').join('""') + '"'; + } + }); + break; + case "row": + row.columns.forEach((col) => { + if (col) { + switch (typeof col.value) { + case "object": + col.value = col.value !== null ? JSON.stringify(col.value) : ""; + break; + case "undefined": + col.value = ""; + break; + } + item.push('"' + String(col.value).split('"').join('""') + '"'); + } + }); + fileContents.push(item.join(delimiter)); + break; + } + }); + if (headers.length) { + fileContents.unshift(headers.join(delimiter)); + } + fileContents = fileContents.join("\n"); + if (options.bom) { + fileContents = "\uFEFF" + fileContents; + } + setFileContents(fileContents, "text/csv"); + } + + function json$2(list2, options, setFileContents) { + var fileContents = []; + list2.forEach((row) => { + var item = {}; + switch (row.type) { + case "header": + break; + case "group": + console.warn("Download Warning - JSON downloader cannot process row groups"); + break; + case "calc": + console.warn("Download Warning - JSON downloader cannot process column calculations"); + break; + case "row": + row.columns.forEach((col) => { + if (col) { + item[col.component.getTitleDownload() || col.component.getField()] = col.value; + } + }); + fileContents.push(item); + break; + } + }); + fileContents = JSON.stringify(fileContents, null, " "); + setFileContents(fileContents, "application/json"); + } + + function pdf(list2, options = {}, setFileContents) { + var header = [], body = [], autoTableParams = {}, rowGroupStyles = options.rowGroupStyles || { + fontStyle: "bold", + fontSize: 12, + cellPadding: 6, + fillColor: 220 + }, rowCalcStyles = options.rowCalcStyles || { + fontStyle: "bold", + fontSize: 10, + cellPadding: 4, + fillColor: 232 + }, jsPDFParams = options.jsPDF || {}, title = options.title ? options.title : "", jspdfLib, doc; + if (!jsPDFParams.orientation) { + jsPDFParams.orientation = options.orientation || "landscape"; + } + if (!jsPDFParams.unit) { + jsPDFParams.unit = "pt"; + } + list2.forEach((row) => { + switch (row.type) { + case "header": + header.push(parseRow(row)); + break; + case "group": + body.push(parseRow(row, rowGroupStyles)); + break; + case "calc": + body.push(parseRow(row, rowCalcStyles)); + break; + case "row": + body.push(parseRow(row)); + break; + } + }); + + function parseRow(row, styles) { + var rowData = []; + row.columns.forEach((col) => { + var cell; + if (col) { + switch (typeof col.value) { + case "object": + col.value = col.value !== null ? JSON.stringify(col.value) : ""; + break; + case "undefined": + col.value = ""; + break; + } + cell = { + content: col.value, + colSpan: col.width, + rowSpan: col.height + }; + if (styles) { + cell.styles = styles; + } + rowData.push(cell); + } + }); + return rowData; + } + + jspdfLib = this.dependencyRegistry.lookup("jspdf", "jsPDF"); + doc = new jspdfLib(jsPDFParams); + if (options.autoTable) { + if (typeof options.autoTable === "function") { + autoTableParams = options.autoTable(doc) || {}; + } else { + autoTableParams = options.autoTable; + } + } + if (title) { + autoTableParams.didDrawPage = function (data) { + doc.text(title, 40, 30); + }; + } + autoTableParams.head = header; + autoTableParams.body = body; + doc.autoTable(autoTableParams); + if (options.documentProcessing) { + options.documentProcessing(doc); + } + setFileContents(doc.output("arraybuffer"), "application/pdf"); + } + + function xlsx$1(list2, options, setFileContents) { + var self = this, sheetName = options.sheetName || "Sheet1", + XLSXLib = this.dependencyRegistry.lookup("XLSX"), workbook = XLSXLib.utils.book_new(), + tableFeatures = new CoreFeature(this), compression = "compress" in options ? options.compress : true, + writeOptions = options.writeOptions || {bookType: "xlsx", bookSST: true, compression}, output; + writeOptions.type = "binary"; + workbook.SheetNames = []; + workbook.Sheets = {}; + + function generateSheet() { + var rows2 = [], merges = [], worksheet = {}, range2 = { + s: {c: 0, r: 0}, + e: { + c: list2[0] ? list2[0].columns.reduce((a, b) => a + (b && b.width ? b.width : 1), 0) : 0, + r: list2.length + } + }; + list2.forEach((row, i) => { + var rowData = []; + row.columns.forEach(function (col, j) { + if (col) { + rowData.push(!(col.value instanceof Date) && typeof col.value === "object" ? JSON.stringify(col.value) : col.value); + if (col.width > 1 || col.height > -1) { + if (col.height > 1 || col.width > 1) { + merges.push({s: {r: i, c: j}, e: {r: i + col.height - 1, c: j + col.width - 1}}); + } + } + } else { + rowData.push(""); + } + }); + rows2.push(rowData); + }); + XLSXLib.utils.sheet_add_aoa(worksheet, rows2); + worksheet["!ref"] = XLSXLib.utils.encode_range(range2); + if (merges.length) { + worksheet["!merges"] = merges; + } + return worksheet; + } + + if (options.sheetOnly) { + setFileContents(generateSheet()); + return; + } + if (options.sheets) { + for (var sheet in options.sheets) { + if (options.sheets[sheet] === true) { + workbook.SheetNames.push(sheet); + workbook.Sheets[sheet] = generateSheet(); + } else { + workbook.SheetNames.push(sheet); + tableFeatures.commsSend(options.sheets[sheet], "download", "intercept", { + type: "xlsx", + options: {sheetOnly: true}, + active: self.active, + intercept: function (data) { + workbook.Sheets[sheet] = data; + } + }); + } + } + } else { + workbook.SheetNames.push(sheetName); + workbook.Sheets[sheetName] = generateSheet(); + } + if (options.documentProcessing) { + workbook = options.documentProcessing(workbook); + } + + function s2ab(s) { + var buf = new ArrayBuffer(s.length); + var view = new Uint8Array(buf); + for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 255; + return buf; + } + + output = XLSXLib.write(workbook, writeOptions); + setFileContents(s2ab(output), "application/octet-stream"); + } + + function html$1(list2, options, setFileContents) { + if (this.modExists("export", true)) { + setFileContents(this.modules.export.generateHTMLTable(list2), "text/html"); + } + } + + function jsonLines(list2, options, setFileContents) { + const fileContents = []; + list2.forEach((row) => { + const item = {}; + switch (row.type) { + case "header": + break; + case "group": + console.warn("Download Warning - JSON downloader cannot process row groups"); + break; + case "calc": + console.warn("Download Warning - JSON downloader cannot process column calculations"); + break; + case "row": + row.columns.forEach((col) => { + if (col) { + item[col.component.getTitleDownload() || col.component.getField()] = col.value; + } + }); + fileContents.push(JSON.stringify(item)); + break; + } + }); + setFileContents(fileContents.join("\n"), "application/x-ndjson"); + } + + var defaultDownloaders = { + csv: csv$1, + json: json$2, + jsonLines, + pdf, + xlsx: xlsx$1, + html: html$1 + }; + const _Download = class _Download extends Module { + constructor(table) { + super(table); + this.registerTableOption("downloadEncoder", function (data, mimeType) { + return new Blob([data], {type: mimeType}); + }); + this.registerTableOption("downloadConfig", {}); + this.registerTableOption("downloadRowRange", "active"); + this.registerColumnOption("download"); + this.registerColumnOption("titleDownload"); + } + + initialize() { + this.deprecatedOptionsCheck(); + this.registerTableFunction("download", this.download.bind(this)); + this.registerTableFunction("downloadToTab", this.downloadToTab.bind(this)); + } + + deprecatedOptionsCheck() { + } + + /////////////////////////////////// + ///////// Table Functions ///////// + /////////////////////////////////// + downloadToTab(type, filename, options, active) { + this.download(type, filename, options, active, true); + } + + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + //trigger file download + download(type, filename, options, range2, interceptCallback) { + var downloadFunc = false; + + function buildLink(data, mime) { + if (interceptCallback) { + if (interceptCallback === true) { + this.triggerDownload(data, mime, type, filename, true); + } else { + interceptCallback(data); + } + } else { + this.triggerDownload(data, mime, type, filename); + } + } + + if (typeof type == "function") { + downloadFunc = type; + } else { + if (_Download.downloaders[type]) { + downloadFunc = _Download.downloaders[type]; + } else { + console.warn("Download Error - No such download type found: ", type); + } + } + if (downloadFunc) { + var list2 = this.generateExportList(range2); + downloadFunc.call(this.table, list2, options || {}, buildLink.bind(this)); + } + } + + generateExportList(range2) { + var list2 = this.table.modules.export.generateExportList(this.table.options.downloadConfig, false, range2 || this.table.options.downloadRowRange, "download"); + var groupHeader = this.table.options.groupHeaderDownload; + if (groupHeader && !Array.isArray(groupHeader)) { + groupHeader = [groupHeader]; + } + list2.forEach((row) => { + var group; + if (row.type === "group") { + group = row.columns[0]; + if (groupHeader && groupHeader[row.indent]) { + group.value = groupHeader[row.indent](group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component); + } + } + }); + return list2; + } + + triggerDownload(data, mime, type, filename, newTab) { + var element = document.createElement("a"), blob = this.table.options.downloadEncoder(data, mime); + if (blob) { + if (newTab) { + window.open(window.URL.createObjectURL(blob)); + } else { + filename = filename || "Tabulator." + (typeof type === "function" ? "txt" : type); + if (navigator.msSaveOrOpenBlob) { + navigator.msSaveOrOpenBlob(blob, filename); + } else { + element.setAttribute("href", window.URL.createObjectURL(blob)); + element.setAttribute("download", filename); + element.style.display = "none"; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); + } + } + this.dispatchExternal("downloadComplete"); + } + } + + commsReceived(table, action, data) { + switch (action) { + case "intercept": + this.download(data.type, "", data.options, data.active, data.intercept); + break; + } + } + }; + __publicField(_Download, "moduleName", "download"); + //load defaults + __publicField(_Download, "downloaders", defaultDownloaders); + let Download = _Download; + + function maskInput(el, options) { + var mask = options.mask, + maskLetter = typeof options.maskLetterChar !== "undefined" ? options.maskLetterChar : "A", + maskNumber = typeof options.maskNumberChar !== "undefined" ? options.maskNumberChar : "9", + maskWildcard = typeof options.maskWildcardChar !== "undefined" ? options.maskWildcardChar : "*"; + + function fillSymbols(index) { + var symbol = mask[index]; + if (typeof symbol !== "undefined" && symbol !== maskWildcard && symbol !== maskLetter && symbol !== maskNumber) { + el.value = el.value + "" + symbol; + fillSymbols(index + 1); + } + } + + el.addEventListener("keydown", (e) => { + var index = el.value.length, char = e.key; + if (e.key.length === 1 && !e.ctrlKey && !e.metaKey) { + if (index >= mask.length) { + e.preventDefault(); + e.stopPropagation(); + return false; + } else { + switch (mask[index]) { + case maskLetter: + if (char.toUpperCase() == char.toLowerCase()) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + break; + case maskNumber: + if (isNaN(char)) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + break; + case maskWildcard: + break; + default: + if (char !== mask[index]) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + } + } + } + return; + }); + el.addEventListener("keyup", (e) => { + if (e.key.length === 1) { + if (options.maskAutoFill) { + fillSymbols(el.value.length); + } + } + }); + if (!el.placeholder) { + el.placeholder = mask; + } + if (options.maskAutoFill) { + fillSymbols(el.value.length); + } + } + + function input(cell, onRendered, success, cancel, editorParams) { + var cellValue = cell.getValue(), input2 = document.createElement("input"); + input2.setAttribute("type", editorParams.search ? "search" : "text"); + input2.style.padding = "4px"; + input2.style.width = "100%"; + input2.style.boxSizing = "border-box"; + if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { + for (let key in editorParams.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); + } else { + input2.setAttribute(key, editorParams.elementAttributes[key]); + } + } + } + input2.value = typeof cellValue !== "undefined" ? cellValue : ""; + onRendered(function () { + if (cell.getType() === "cell") { + input2.focus({preventScroll: true}); + input2.style.height = "100%"; + if (editorParams.selectContents) { + input2.select(); + } + } + }); + + function onChange(e) { + if ((cellValue === null || typeof cellValue === "undefined") && input2.value !== "" || input2.value !== cellValue) { + if (success(input2.value)) { + cellValue = input2.value; + } + } else { + cancel(); + } + } + + input2.addEventListener("change", onChange); + input2.addEventListener("blur", onChange); + input2.addEventListener("keydown", function (e) { + switch (e.key) { + // case "Tab": + case "Enter": + onChange(); + break; + case "Escape": + cancel(); + break; + case "End": + case "Home": + e.stopPropagation(); + break; + } + }); + if (editorParams.mask) { + maskInput(input2, editorParams); + } + return input2; + } + + function textarea$1(cell, onRendered, success, cancel, editorParams) { + var cellValue = cell.getValue(), vertNav = editorParams.verticalNavigation || "hybrid", + value = String(cellValue !== null && typeof cellValue !== "undefined" ? cellValue : ""), + input2 = document.createElement("textarea"), scrollHeight = 0; + input2.style.display = "block"; + input2.style.padding = "2px"; + input2.style.height = "100%"; + input2.style.width = "100%"; + input2.style.boxSizing = "border-box"; + input2.style.whiteSpace = "pre-wrap"; + input2.style.resize = "none"; + if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { + for (let key in editorParams.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); + } else { + input2.setAttribute(key, editorParams.elementAttributes[key]); + } + } + } + input2.value = value; + onRendered(function () { + if (cell.getType() === "cell") { + input2.focus({preventScroll: true}); + input2.style.height = "100%"; + input2.scrollHeight; + input2.style.height = input2.scrollHeight + "px"; + cell.getRow().normalizeHeight(); + if (editorParams.selectContents) { + input2.select(); + } + } + }); + + function onChange(e) { + if ((cellValue === null || typeof cellValue === "undefined") && input2.value !== "" || input2.value !== cellValue) { + if (success(input2.value)) { + cellValue = input2.value; + } + setTimeout(function () { + cell.getRow().normalizeHeight(); + }, 300); + } else { + cancel(); + } + } + + input2.addEventListener("change", onChange); + input2.addEventListener("blur", onChange); + input2.addEventListener("keyup", function () { + input2.style.height = ""; + var heightNow = input2.scrollHeight; + input2.style.height = heightNow + "px"; + if (heightNow != scrollHeight) { + scrollHeight = heightNow; + cell.getRow().normalizeHeight(); + } + }); + input2.addEventListener("keydown", function (e) { + switch (e.key) { + case "Enter": + if (e.shiftKey && editorParams.shiftEnterSubmit) { + onChange(); + } + break; + case "Escape": + cancel(); + break; + case "ArrowUp": + if (vertNav == "editor" || vertNav == "hybrid" && input2.selectionStart) { + e.stopImmediatePropagation(); + e.stopPropagation(); + } + break; + case "ArrowDown": + if (vertNav == "editor" || vertNav == "hybrid" && input2.selectionStart !== input2.value.length) { + e.stopImmediatePropagation(); + e.stopPropagation(); + } + break; + case "End": + case "Home": + e.stopPropagation(); + break; + } + }); + if (editorParams.mask) { + maskInput(input2, editorParams); + } + return input2; + } + + function number$1(cell, onRendered, success, cancel, editorParams) { + var cellValue = cell.getValue(), vertNav = editorParams.verticalNavigation || "editor", + input2 = document.createElement("input"); + input2.setAttribute("type", "number"); + if (typeof editorParams.max != "undefined") { + input2.setAttribute("max", editorParams.max); + } + if (typeof editorParams.min != "undefined") { + input2.setAttribute("min", editorParams.min); + } + if (typeof editorParams.step != "undefined") { + input2.setAttribute("step", editorParams.step); + } + input2.style.padding = "4px"; + input2.style.width = "100%"; + input2.style.boxSizing = "border-box"; + if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { + for (let key in editorParams.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); + } else { + input2.setAttribute(key, editorParams.elementAttributes[key]); + } + } + } + input2.value = cellValue; + var blurFunc = function (e) { + onChange(); + }; + onRendered(function () { + if (cell.getType() === "cell") { + input2.removeEventListener("blur", blurFunc); + input2.focus({preventScroll: true}); + input2.style.height = "100%"; + input2.addEventListener("blur", blurFunc); + if (editorParams.selectContents) { + input2.select(); + } + } + }); + + function onChange() { + var value = input2.value; + if (!isNaN(value) && value !== "") { + value = Number(value); + } + if (value !== cellValue) { + if (success(value)) { + cellValue = value; + } + } else { + cancel(); + } + } + + input2.addEventListener("keydown", function (e) { + switch (e.key) { + case "Enter": + onChange(); + break; + case "Escape": + cancel(); + break; + case "ArrowUp": + case "ArrowDown": + if (vertNav == "editor") { + e.stopImmediatePropagation(); + e.stopPropagation(); + } + break; + case "End": + case "Home": + e.stopPropagation(); + break; + } + }); + if (editorParams.mask) { + maskInput(input2, editorParams); + } + return input2; + } + + function range(cell, onRendered, success, cancel, editorParams) { + var cellValue = cell.getValue(), input2 = document.createElement("input"); + input2.setAttribute("type", "range"); + if (typeof editorParams.max != "undefined") { + input2.setAttribute("max", editorParams.max); + } + if (typeof editorParams.min != "undefined") { + input2.setAttribute("min", editorParams.min); + } + if (typeof editorParams.step != "undefined") { + input2.setAttribute("step", editorParams.step); + } + input2.style.padding = "4px"; + input2.style.width = "100%"; + input2.style.boxSizing = "border-box"; + if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { + for (let key in editorParams.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); + } else { + input2.setAttribute(key, editorParams.elementAttributes[key]); + } + } + } + input2.value = cellValue; + onRendered(function () { + if (cell.getType() === "cell") { + input2.focus({preventScroll: true}); + input2.style.height = "100%"; + } + }); + + function onChange() { + var value = input2.value; + if (!isNaN(value) && value !== "") { + value = Number(value); + } + if (value != cellValue) { + if (success(value)) { + cellValue = value; + } + } else { + cancel(); + } + } + + input2.addEventListener("blur", function (e) { + onChange(); + }); + input2.addEventListener("keydown", function (e) { + switch (e.key) { + case "Enter": + onChange(); + break; + case "Escape": + cancel(); + break; + } + }); + return input2; + } + + function date$1(cell, onRendered, success, cancel, editorParams) { + var inputFormat = editorParams.format, vertNav = editorParams.verticalNavigation || "editor", + DT = inputFormat ? window.DateTime || luxon.DateTime : null; + var cellValue = cell.getValue(), input2 = document.createElement("input"); + + function convertDate(value) { + var newDatetime; + if (DT.isDateTime(value)) { + newDatetime = value; + } else if (inputFormat === "x") { + newDatetime = DT.fromMillis(value); + } else if (inputFormat === "iso") { + newDatetime = DT.fromISO(String(value)); + } else { + newDatetime = DT.fromFormat(String(value), inputFormat); + } + return newDatetime.toFormat("yyyy-MM-dd"); + } + + input2.type = "date"; + input2.style.padding = "4px"; + input2.style.width = "100%"; + input2.style.boxSizing = "border-box"; + if (editorParams.max) { + input2.setAttribute("max", inputFormat ? convertDate(editorParams.max) : editorParams.max); + } + if (editorParams.min) { + input2.setAttribute("min", inputFormat ? convertDate(editorParams.min) : editorParams.min); + } + if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { + for (let key in editorParams.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); + } else { + input2.setAttribute(key, editorParams.elementAttributes[key]); + } + } + } + cellValue = typeof cellValue !== "undefined" ? cellValue : ""; + if (inputFormat) { + if (DT) { + cellValue = convertDate(cellValue); + } else { + console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js"); + } + } + input2.value = cellValue; + onRendered(function () { + if (cell.getType() === "cell") { + input2.focus({preventScroll: true}); + input2.style.height = "100%"; + if (editorParams.selectContents) { + input2.select(); + } + } + }); + + function onChange() { + var value = input2.value, luxDate; + if ((cellValue === null || typeof cellValue === "undefined") && value !== "" || value !== cellValue) { + if (value && inputFormat) { + luxDate = DT.fromFormat(String(value), "yyyy-MM-dd"); + switch (inputFormat) { + case true: + value = luxDate; + break; + case "x": + value = luxDate.toMillis(); + break; + case "iso": + value = luxDate.toISO(); + break; + default: + value = luxDate.toFormat(inputFormat); + } + } + if (success(value)) { + cellValue = input2.value; + } + } else { + cancel(); + } + } + + input2.addEventListener("blur", function (e) { + if (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input2) { + onChange(); + } + }); + input2.addEventListener("keydown", function (e) { + switch (e.key) { + // case "Tab": + case "Enter": + onChange(); + break; + case "Escape": + cancel(); + break; + case "End": + case "Home": + e.stopPropagation(); + break; + case "ArrowUp": + case "ArrowDown": + if (vertNav == "editor") { + e.stopImmediatePropagation(); + e.stopPropagation(); + } + break; + } + }); + return input2; + } + + function time$1(cell, onRendered, success, cancel, editorParams) { + var inputFormat = editorParams.format, vertNav = editorParams.verticalNavigation || "editor", + DT = inputFormat ? window.DateTime || luxon.DateTime : null, newDatetime; + var cellValue = cell.getValue(), input2 = document.createElement("input"); + input2.type = "time"; + input2.style.padding = "4px"; + input2.style.width = "100%"; + input2.style.boxSizing = "border-box"; + if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { + for (let key in editorParams.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); + } else { + input2.setAttribute(key, editorParams.elementAttributes[key]); + } + } + } + cellValue = typeof cellValue !== "undefined" ? cellValue : ""; + if (inputFormat) { + if (DT) { + if (DT.isDateTime(cellValue)) { + newDatetime = cellValue; + } else if (inputFormat === "x") { + newDatetime = DT.fromMillis(cellValue); + } else if (inputFormat === "iso") { + newDatetime = DT.fromISO(String(cellValue)); + } else { + newDatetime = DT.fromFormat(String(cellValue), inputFormat); + } + cellValue = newDatetime.toFormat("HH:mm"); + } else { + console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js"); + } + } + input2.value = cellValue; + onRendered(function () { + if (cell.getType() == "cell") { + input2.focus({preventScroll: true}); + input2.style.height = "100%"; + if (editorParams.selectContents) { + input2.select(); + } + } + }); + + function onChange() { + var value = input2.value, luxTime; + if ((cellValue === null || typeof cellValue === "undefined") && value !== "" || value !== cellValue) { + if (value && inputFormat) { + luxTime = DT.fromFormat(String(value), "hh:mm"); + switch (inputFormat) { + case true: + value = luxTime; + break; + case "x": + value = luxTime.toMillis(); + break; + case "iso": + value = luxTime.toISO(); + break; + default: + value = luxTime.toFormat(inputFormat); + } + } + if (success(value)) { + cellValue = input2.value; + } + } else { + cancel(); + } + } + + input2.addEventListener("blur", function (e) { + if (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input2) { + onChange(); + } + }); + input2.addEventListener("keydown", function (e) { + switch (e.key) { + // case "Tab": + case "Enter": + onChange(); + break; + case "Escape": + cancel(); + break; + case "End": + case "Home": + e.stopPropagation(); + break; + case "ArrowUp": + case "ArrowDown": + if (vertNav == "editor") { + e.stopImmediatePropagation(); + e.stopPropagation(); + } + break; + } + }); + return input2; + } + + function datetime$2(cell, onRendered, success, cancel, editorParams) { + var inputFormat = editorParams.format, vertNav = editorParams.verticalNavigation || "editor", + DT = inputFormat ? this.table.dependencyRegistry.lookup(["luxon", "DateTime"], "DateTime") : null, + newDatetime; + var cellValue = cell.getValue(), input2 = document.createElement("input"); + input2.type = "datetime-local"; + input2.style.padding = "4px"; + input2.style.width = "100%"; + input2.style.boxSizing = "border-box"; + if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { + for (let key in editorParams.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); + } else { + input2.setAttribute(key, editorParams.elementAttributes[key]); + } + } + } + cellValue = typeof cellValue !== "undefined" ? cellValue : ""; + if (inputFormat) { + if (DT) { + if (DT.isDateTime(cellValue)) { + newDatetime = cellValue; + } else if (inputFormat === "x") { + newDatetime = DT.fromMillis(cellValue); + } else if (inputFormat === "iso") { + newDatetime = DT.fromISO(String(cellValue)); + } else { + newDatetime = DT.fromFormat(String(cellValue), inputFormat); + } + cellValue = newDatetime.toFormat("yyyy-MM-dd") + "T" + newDatetime.toFormat("HH:mm"); + } else { + console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js"); + } + } + input2.value = cellValue; + onRendered(function () { + if (cell.getType() === "cell") { + input2.focus({preventScroll: true}); + input2.style.height = "100%"; + if (editorParams.selectContents) { + input2.select(); + } + } + }); + + function onChange() { + var value = input2.value, luxDateTime; + if ((cellValue === null || typeof cellValue === "undefined") && value !== "" || value !== cellValue) { + if (value && inputFormat) { + luxDateTime = DT.fromISO(String(value)); + switch (inputFormat) { + case true: + value = luxDateTime; + break; + case "x": + value = luxDateTime.toMillis(); + break; + case "iso": + value = luxDateTime.toISO(); + break; + default: + value = luxDateTime.toFormat(inputFormat); + } + } + if (success(value)) { + cellValue = input2.value; + } + } else { + cancel(); + } + } + + input2.addEventListener("blur", function (e) { + if (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input2) { + onChange(); + } + }); + input2.addEventListener("keydown", function (e) { + switch (e.key) { + // case "Tab": + case "Enter": + onChange(); + break; + case "Escape": + cancel(); + break; + case "End": + case "Home": + e.stopPropagation(); + break; + case "ArrowUp": + case "ArrowDown": + if (vertNav == "editor") { + e.stopImmediatePropagation(); + e.stopPropagation(); + } + break; + } + }); + return input2; + } + + let Edit$1 = class Edit { + constructor(editor, cell, onRendered, success, cancel, editorParams) { + this.edit = editor; + this.table = editor.table; + this.cell = cell; + this.params = this._initializeParams(editorParams); + this.data = []; + this.displayItems = []; + this.currentItems = []; + this.focusedItem = null; + this.input = this._createInputElement(); + this.listEl = this._createListElement(); + this.initialValues = null; + this.isFilter = cell.getType() === "header"; + this.filterTimeout = null; + this.filtered = false; + this.typing = false; + this.values = []; + this.popup = null; + this.listIteration = 0; + this.lastAction = ""; + this.filterTerm = ""; + this.blurable = true; + this.actions = { + success, + cancel + }; + this._deprecatedOptionsCheck(); + this._initializeValue(); + onRendered(this._onRendered.bind(this)); + } + + _deprecatedOptionsCheck() { + } + + _initializeValue() { + var initialValue = this.cell.getValue(); + if (typeof initialValue === "undefined" && typeof this.params.defaultValue !== "undefined") { + initialValue = this.params.defaultValue; + } + this.initialValues = this.params.multiselect ? initialValue : [initialValue]; + if (this.isFilter) { + this.input.value = this.initialValues ? this.initialValues.join(",") : ""; + this.headerFilterInitialListGen(); + } + } + + _onRendered() { + var cellEl = this.cell.getElement(); + + function clickStop(e) { + e.stopPropagation(); + } + + if (!this.isFilter) { + this.input.style.height = "100%"; + this.input.focus({preventScroll: true}); + } + cellEl.addEventListener("click", clickStop); + setTimeout(() => { + cellEl.removeEventListener("click", clickStop); + }, 1e3); + this.input.addEventListener("mousedown", this._preventPopupBlur.bind(this)); + } + + _createListElement() { + var listEl = document.createElement("div"); + listEl.classList.add("tabulator-edit-list"); + listEl.addEventListener("mousedown", this._preventBlur.bind(this)); + listEl.addEventListener("keydown", this._inputKeyDown.bind(this)); + return listEl; + } + + _setListWidth() { + var element = this.isFilter ? this.input : this.cell.getElement(); + this.listEl.style.minWidth = element.offsetWidth + "px"; + if (this.params.maxWidth) { + if (this.params.maxWidth === true) { + this.listEl.style.maxWidth = element.offsetWidth + "px"; + } else if (typeof this.params.maxWidth === "number") { + this.listEl.style.maxWidth = this.params.maxWidth + "px"; + } else { + this.listEl.style.maxWidth = this.params.maxWidth; + } + } + } + + _createInputElement() { + var attribs = this.params.elementAttributes; + var input2 = document.createElement("input"); + input2.setAttribute("type", this.params.clearable ? "search" : "text"); + input2.style.padding = "4px"; + input2.style.width = "100%"; + input2.style.boxSizing = "border-box"; + if (!this.params.autocomplete) { + input2.style.cursor = "default"; + input2.style.caretColor = "transparent"; + } + if (attribs && typeof attribs == "object") { + for (let key in attribs) { + if (key.charAt(0) == "+") { + key = key.slice(1); + input2.setAttribute(key, input2.getAttribute(key) + attribs["+" + key]); + } else { + input2.setAttribute(key, attribs[key]); + } + } + } + if (this.params.mask) { + maskInput(input2, this.params); + } + this._bindInputEvents(input2); + return input2; + } + + _initializeParams(params) { + var valueKeys = ["values", "valuesURL", "valuesLookup"], valueCheck; + params = Object.assign({}, params); + params.verticalNavigation = params.verticalNavigation || "editor"; + params.placeholderLoading = typeof params.placeholderLoading === "undefined" ? "Searching ..." : params.placeholderLoading; + params.placeholderEmpty = typeof params.placeholderEmpty === "undefined" ? "No Results Found" : params.placeholderEmpty; + params.filterDelay = typeof params.filterDelay === "undefined" ? 300 : params.filterDelay; + params.emptyValue = Object.keys(params).includes("emptyValue") ? params.emptyValue : ""; + valueCheck = Object.keys(params).filter((key) => valueKeys.includes(key)).length; + if (!valueCheck) { + console.warn("list editor config error - either the values, valuesURL, or valuesLookup option must be set"); + } else if (valueCheck > 1) { + console.warn("list editor config error - only one of the values, valuesURL, or valuesLookup options can be set on the same editor"); + } + if (params.autocomplete) { + if (params.multiselect) { + params.multiselect = false; + console.warn("list editor config error - multiselect option is not available when autocomplete is enabled"); + } + } else { + if (params.freetext) { + params.freetext = false; + console.warn("list editor config error - freetext option is only available when autocomplete is enabled"); + } + if (params.filterFunc) { + params.filterFunc = false; + console.warn("list editor config error - filterFunc option is only available when autocomplete is enabled"); + } + if (params.filterRemote) { + params.filterRemote = false; + console.warn("list editor config error - filterRemote option is only available when autocomplete is enabled"); + } + if (params.mask) { + params.mask = false; + console.warn("list editor config error - mask option is only available when autocomplete is enabled"); + } + if (params.allowEmpty) { + params.allowEmpty = false; + console.warn("list editor config error - allowEmpty option is only available when autocomplete is enabled"); + } + if (params.listOnEmpty) { + params.listOnEmpty = false; + console.warn("list editor config error - listOnEmpty option is only available when autocomplete is enabled"); + } + } + if (params.filterRemote && !(typeof params.valuesLookup === "function" || params.valuesURL)) { + params.filterRemote = false; + console.warn("list editor config error - filterRemote option should only be used when values list is populated from a remote source"); + } + return params; + } + + ////////////////////////////////////// + ////////// Event Handling //////////// + ////////////////////////////////////// + _bindInputEvents(input2) { + input2.addEventListener("focus", this._inputFocus.bind(this)); + input2.addEventListener("click", this._inputClick.bind(this)); + input2.addEventListener("blur", this._inputBlur.bind(this)); + input2.addEventListener("keydown", this._inputKeyDown.bind(this)); + input2.addEventListener("search", this._inputSearch.bind(this)); + if (this.params.autocomplete) { + input2.addEventListener("keyup", this._inputKeyUp.bind(this)); + } + } + + _inputFocus(e) { + this.rebuildOptionsList(); + } + + _filter() { + if (this.params.filterRemote) { + clearTimeout(this.filterTimeout); + this.filterTimeout = setTimeout(() => { + this.rebuildOptionsList(); + }, this.params.filterDelay); + } else { + this._filterList(); + } + } + + _inputClick(e) { + e.stopPropagation(); + } + + _inputBlur(e) { + if (this.blurable) { + if (this.popup) { + this.popup.hide(); + } else { + this._resolveValue(true); + } + } + } + + _inputSearch() { + this._clearChoices(); + } + + _inputKeyDown(e) { + switch (e.key) { + case "ArrowUp": + this._keyUp(e); + break; + case "ArrowDown": + this._keyDown(e); + break; + case "ArrowLeft": + case "ArrowRight": + this._keySide(e); + break; + case "Enter": + this._keyEnter(); + break; + case "Escape": + this._keyEsc(); + break; + case "Home": + case "End": + this._keyHomeEnd(e); + break; + case "Tab": + this._keyTab(e); + break; + default: + this._keySelectLetter(e); + } + } + + _inputKeyUp(e) { + switch (e.key) { + case "ArrowUp": + case "ArrowLeft": + case "ArrowRight": + case "ArrowDown": + case "Enter": + case "Escape": + break; + default: + this._keyAutoCompLetter(e); + } + } + + _preventPopupBlur() { + if (this.popup) { + this.popup.blockHide(); + } + setTimeout(() => { + if (this.popup) { + this.popup.restoreHide(); + } + }, 10); + } + + _preventBlur() { + this.blurable = false; + setTimeout(() => { + this.blurable = true; + }, 10); + } + + ////////////////////////////////////// + //////// Keyboard Navigation ///////// + ////////////////////////////////////// + _keyTab(e) { + if (this.params.autocomplete && this.lastAction === "typing") { + this._resolveValue(true); + } else { + if (this.focusedItem) { + this._chooseItem(this.focusedItem, true); + } + } + } + + _keyUp(e) { + var index = this.displayItems.indexOf(this.focusedItem); + if (this.params.verticalNavigation == "editor" || this.params.verticalNavigation == "hybrid" && index) { + e.stopImmediatePropagation(); + e.stopPropagation(); + e.preventDefault(); + if (index > 0) { + this._focusItem(this.displayItems[index - 1]); + } + } + } + + _keyDown(e) { + var index = this.displayItems.indexOf(this.focusedItem); + if (this.params.verticalNavigation == "editor" || this.params.verticalNavigation == "hybrid" && index < this.displayItems.length - 1) { + e.stopImmediatePropagation(); + e.stopPropagation(); + e.preventDefault(); + if (index < this.displayItems.length - 1) { + if (index == -1) { + this._focusItem(this.displayItems[0]); + } else { + this._focusItem(this.displayItems[index + 1]); + } + } + } + } + + _keySide(e) { + if (!this.params.autocomplete) { + e.stopImmediatePropagation(); + e.stopPropagation(); + e.preventDefault(); + } + } + + _keyEnter(e) { + if (this.params.autocomplete && this.lastAction === "typing") { + this._resolveValue(true); + } else { + if (this.focusedItem) { + if (this.isFilter && !this.params.multiselect && this.focusedItem.selected) { + this._resolveValue(); + } else { + this._chooseItem(this.focusedItem); + } + } + } + } + + _keyEsc(e) { + this._cancel(); + } + + _keyHomeEnd(e) { + if (this.params.autocomplete) { + e.stopImmediatePropagation(); + } + } + + _keySelectLetter(e) { + if (!this.params.autocomplete) { + e.preventDefault(); + if (e.key.length === 1) { + this._scrollToValue(e.key.toUpperCase().charCodeAt(0)); + } + } + } + + _keyAutoCompLetter(e) { + this._filter(); + this.lastAction = "typing"; + this.typing = true; + } + + _scrollToValue(char) { + clearTimeout(this.filterTimeout); + var character = String.fromCharCode(char).toLowerCase(); + this.filterTerm += character.toLowerCase(); + var match = this.displayItems.find((item) => { + return typeof item.label !== "undefined" && item.label.toLowerCase().startsWith(this.filterTerm); + }); + if (match) { + this._focusItem(match); + } + this.filterTimeout = setTimeout(() => { + this.filterTerm = ""; + }, 800); + } + + _focusItem(item) { + this.lastAction = "focus"; + if (this.focusedItem && this.focusedItem.element) { + this.focusedItem.element.classList.remove("focused"); + } + this.focusedItem = item; + if (item && item.element) { + item.element.classList.add("focused"); + item.element.scrollIntoView({behavior: "smooth", block: "nearest", inline: "start"}); + } + } + + ////////////////////////////////////// + /////// Data List Generation ///////// + ////////////////////////////////////// + headerFilterInitialListGen() { + this._generateOptions(true); + } + + rebuildOptionsList() { + this._generateOptions().then(this._sortOptions.bind(this)).then(this._buildList.bind(this)).then(this._showList.bind(this)).catch((e) => { + if (!Number.isInteger(e)) { + console.error("List generation error", e); + } + }); + } + + _filterList() { + this._buildList(this._filterOptions()); + this._showList(); + } + + _generateOptions(silent) { + var values = []; + var iteration = ++this.listIteration; + this.filtered = false; + if (this.params.values) { + values = this.params.values; + } else if (this.params.valuesURL) { + values = this._ajaxRequest(this.params.valuesURL, this.input.value); + } else { + if (typeof this.params.valuesLookup === "function") { + values = this.params.valuesLookup(this.cell, this.input.value); + } else if (this.params.valuesLookup) { + values = this._uniqueColumnValues(this.params.valuesLookupField); + } + } + if (values instanceof Promise) { + if (!silent) { + this._addPlaceholder(this.params.placeholderLoading); + } + return values.then().then((responseValues) => { + if (this.listIteration === iteration) { + return this._parseList(responseValues); + } else { + return Promise.reject(iteration); + } + }); + } else { + return Promise.resolve(this._parseList(values)); + } + } + + _addPlaceholder(contents) { + var placeholder = document.createElement("div"); + if (typeof contents === "function") { + contents = contents(this.cell.getComponent(), this.listEl); + } + if (contents) { + this._clearList(); + if (contents instanceof HTMLElement) { + placeholder = contents; + } else { + placeholder.classList.add("tabulator-edit-list-placeholder"); + placeholder.innerHTML = contents; + } + this.listEl.appendChild(placeholder); + this._showList(); + } + } + + _ajaxRequest(url, term) { + var params = this.params.filterRemote ? {term} : {}; + url = urlBuilder(url, {}, params); + return fetch(url).then((response) => { + if (response.ok) { + return response.json().catch((error) => { + console.warn("List Ajax Load Error - Invalid JSON returned", error); + return Promise.reject(error); + }); + } else { + console.error("List Ajax Load Error - Connection Error: " + response.status, response.statusText); + return Promise.reject(response); + } + }).catch((error) => { + console.error("List Ajax Load Error - Connection Error: ", error); + return Promise.reject(error); + }); + } + + _uniqueColumnValues(field) { + var output = {}, data = this.table.getData(this.params.valuesLookup), column; + if (field) { + column = this.table.columnManager.getColumnByField(field); + } else { + column = this.cell.getColumn()._getSelf(); + } + if (column) { + data.forEach((row) => { + var val = column.getFieldValue(row); + if (!this._emptyValueCheck(val)) { + if (this.params.multiselect && Array.isArray(val)) { + val.forEach((item) => { + if (!this._emptyValueCheck(item)) { + output[item] = true; + } + }); + } else { + output[val] = true; + } + } + }); + } else { + console.warn("unable to find matching column to create select lookup list:", field); + output = []; + } + return Object.keys(output); + } + + _emptyValueCheck(value) { + return value === null || typeof value === "undefined" || value === ""; + } + + _parseList(inputValues) { + var data = []; + if (!Array.isArray(inputValues)) { + inputValues = Object.entries(inputValues).map(([key, value]) => { + return { + label: value, + value: key + }; + }); + } + inputValues.forEach((value) => { + if (typeof value !== "object") { + value = { + label: value, + value + }; + } + this._parseListItem(value, data, 0); + }); + if (!this.currentItems.length && this.params.freetext) { + this.input.value = this.initialValues; + this.typing = true; + this.lastAction = "typing"; + } + if (this.params.multiselect) { + this.initialValues = null; + } + this.data = data; + return data; + } + + _parseListItem(option, data, level) { + var item = {}; + if (option.options) { + item = this._parseListGroup(option, level + 1); + } else { + item = { + label: option.label, + value: option.value, + itemParams: option.itemParams, + elementAttributes: option.elementAttributes, + element: false, + selected: false, + visible: true, + level, + original: option + }; + if (this.params.multiselect) { + var existingIndex = this.currentItems.findIndex((existing) => existing.value === option.value); + if (existingIndex > -1) { + if (this.focusedItem === this.currentItems[existingIndex]) { + this.focusedItem = item; + } + this.currentItems[existingIndex] = item; + item.selected = true; + } else if (this.initialValues && this.initialValues.indexOf(option.value) > -1) { + this._chooseItem(item, true); + } + } else if (this.initialValues && this.initialValues.indexOf(option.value) > -1) { + this._chooseItem(item, true); + } + } + data.push(item); + } + + _parseListGroup(option, level) { + var item = { + label: option.label, + group: true, + itemParams: option.itemParams, + elementAttributes: option.elementAttributes, + element: false, + visible: true, + level, + options: [], + original: option + }; + option.options.forEach((child) => { + this._parseListItem(child, item.options, level); + }); + return item; + } + + _sortOptions(options) { + var sorter; + if (this.params.sort) { + sorter = typeof this.params.sort === "function" ? this.params.sort : this._defaultSortFunction.bind(this); + this._sortGroup(sorter, options); + } + return options; + } + + _sortGroup(sorter, options) { + options.sort((a, b) => { + return sorter(a.label, b.label, a.value, b.value, a.original, b.original); + }); + options.forEach((option) => { + if (option.group) { + this._sortGroup(sorter, option.options); + } + }); + } + + _defaultSortFunction(as, bs) { + var a, b, a1, b1, i = 0, L, rx = /(\d+)|(\D+)/g, rd = /\d/; + var emptyAlign = 0; + if (this.params.sort === "desc") { + [as, bs] = [bs, as]; + } + if (!as && as !== 0) { + emptyAlign = !bs && bs !== 0 ? 0 : -1; + } else if (!bs && bs !== 0) { + emptyAlign = 1; + } else { + if (isFinite(as) && isFinite(bs)) return as - bs; + a = String(as).toLowerCase(); + b = String(bs).toLowerCase(); + if (a === b) return 0; + if (!(rd.test(a) && rd.test(b))) return a > b ? 1 : -1; + a = a.match(rx); + b = b.match(rx); + L = a.length > b.length ? b.length : a.length; + while (i < L) { + a1 = a[i]; + b1 = b[i++]; + if (a1 !== b1) { + if (isFinite(a1) && isFinite(b1)) { + if (a1.charAt(0) === "0") a1 = "." + a1; + if (b1.charAt(0) === "0") b1 = "." + b1; + return a1 - b1; + } else return a1 > b1 ? 1 : -1; + } + } + return a.length > b.length; + } + return emptyAlign; + } + + _filterOptions() { + var filterFunc = this.params.filterFunc || this._defaultFilterFunc, term = this.input.value; + if (term) { + this.filtered = true; + this.data.forEach((item) => { + this._filterItem(filterFunc, term, item); + }); + } else { + this.filtered = false; + } + return this.data; + } + + _filterItem(func, term, item) { + var matches = false; + if (!item.group) { + item.visible = func(term, item.label, item.value, item.original); + } else { + item.options.forEach((option) => { + if (this._filterItem(func, term, option)) { + matches = true; + } + }); + item.visible = matches; + } + return item.visible; + } + + _defaultFilterFunc(term, label, value, item) { + term = String(term).toLowerCase(); + if (label !== null && typeof label !== "undefined") { + if (String(label).toLowerCase().indexOf(term) > -1 || String(value).toLowerCase().indexOf(term) > -1) { + return true; + } + } + return false; + } + + ////////////////////////////////////// + /////////// Display List ///////////// + ////////////////////////////////////// + _clearList() { + while (this.listEl.firstChild) this.listEl.removeChild(this.listEl.firstChild); + this.displayItems = []; + } + + _buildList(data) { + this._clearList(); + data.forEach((option) => { + this._buildItem(option); + }); + if (!this.displayItems.length) { + this._addPlaceholder(this.params.placeholderEmpty); + } + } + + _buildItem(item) { + var el = item.element, contents; + if (!this.filtered || item.visible) { + if (!el) { + el = document.createElement("div"); + el.tabIndex = 0; + contents = this.params.itemFormatter ? this.params.itemFormatter(item.label, item.value, item.original, el) : item.label; + if (contents instanceof HTMLElement) { + el.appendChild(contents); + } else { + el.innerHTML = contents; + } + if (item.group) { + el.classList.add("tabulator-edit-list-group"); + } else { + el.classList.add("tabulator-edit-list-item"); + } + el.classList.add("tabulator-edit-list-group-level-" + item.level); + if (item.elementAttributes && typeof item.elementAttributes == "object") { + for (let key in item.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + el.setAttribute(key, this.input.getAttribute(key) + item.elementAttributes["+" + key]); + } else { + el.setAttribute(key, item.elementAttributes[key]); + } + } + } + if (item.group) { + el.addEventListener("click", this._groupClick.bind(this, item)); + } else { + el.addEventListener("click", this._itemClick.bind(this, item)); + } + el.addEventListener("mousedown", this._preventBlur.bind(this)); + item.element = el; + } + this._styleItem(item); + this.listEl.appendChild(el); + if (item.group) { + item.options.forEach((option) => { + this._buildItem(option); + }); + } else { + this.displayItems.push(item); + } + } + } + + _showList() { + var startVis = this.popup && this.popup.isVisible(); + if (this.input.parentNode) { + if (this.params.autocomplete && this.input.value === "" && !this.params.listOnEmpty) { + if (this.popup) { + this.popup.hide(true); + } + return; + } + this._setListWidth(); + if (!this.popup) { + this.popup = this.edit.popup(this.listEl); + } + this.popup.show(this.cell.getElement(), "bottom"); + if (!startVis) { + setTimeout(() => { + this.popup.hideOnBlur(this._resolveValue.bind(this, true)); + }, 10); + } + } + } + + _styleItem(item) { + if (item && item.element) { + if (item.selected) { + item.element.classList.add("active"); + } else { + item.element.classList.remove("active"); + } + } + } + + ////////////////////////////////////// + ///////// User Interaction /////////// + ////////////////////////////////////// + _itemClick(item, e) { + e.stopPropagation(); + this._chooseItem(item); + } + + _groupClick(item, e) { + e.stopPropagation(); + } + + ////////////////////////////////////// + ////// Current Item Management /////// + ////////////////////////////////////// + _cancel() { + this.popup.hide(true); + this.actions.cancel(); + } + + _clearChoices() { + this.typing = true; + this.currentItems.forEach((item) => { + item.selected = false; + this._styleItem(item); + }); + this.currentItems = []; + this.focusedItem = null; + } + + _chooseItem(item, silent) { + var index; + this.typing = false; + if (this.params.multiselect) { + index = this.currentItems.indexOf(item); + if (index > -1) { + this.currentItems.splice(index, 1); + item.selected = false; + } else { + this.currentItems.push(item); + item.selected = true; + } + this.input.value = this.currentItems.map((item2) => item2.label).join(","); + this._styleItem(item); + } else { + if (this.isFilter && !silent && item.selected) { + this._clearChoices(); + this.input.value = ""; + this._resolveValue(); + return; + } + this.currentItems = [item]; + item.selected = true; + this.input.value = item.label; + this._styleItem(item); + if (!silent) { + this._resolveValue(); + } + } + this._focusItem(item); + } + + _resolveValue(blur) { + var output, initialValue; + if (this.popup) { + this.popup.hide(true); + } + if (this.params.multiselect) { + output = this.currentItems.map((item) => item.value); + } else { + if (blur && this.params.autocomplete && this.typing) { + if (this.params.freetext || this.params.allowEmpty && this.input.value === "") { + output = this.input.value; + } else { + this.actions.cancel(); + return; + } + } else { + if (this.currentItems[0]) { + output = this.currentItems[0].value; + } else if (this.isFilter && this.focusedItem && this.focusedItem.selected) { + output = this.focusedItem.value; + } else { + initialValue = Array.isArray(this.initialValues) ? this.initialValues[0] : this.initialValues; + if (initialValue === null || typeof initialValue === "undefined" || initialValue === "") { + output = initialValue; + } else { + output = this.params.emptyValue; + } + } + } + } + if (output === "") { + output = this.params.emptyValue; + } + this.actions.success(output); + if (this.isFilter) { + this.initialValues = output && !Array.isArray(output) ? [output] : output; + this.currentItems = []; + } + } + }; + + function list(cell, onRendered, success, cancel, editorParams) { + var list2 = new Edit$1(this, cell, onRendered, success, cancel, editorParams); + return list2.input; + } + + function star$1(cell, onRendered, success, cancel, editorParams) { + var self = this, element = cell.getElement(), value = cell.getValue(), + maxStars = element.getElementsByTagName("svg").length || 5, + size = element.getElementsByTagName("svg")[0] ? element.getElementsByTagName("svg")[0].getAttribute("width") : 14, + stars = [], starsHolder = document.createElement("div"), + star2 = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + + function starChange(val) { + stars.forEach(function (star3, i2) { + if (i2 < val) { + if (self.table.browser == "ie") { + star3.setAttribute("class", "tabulator-star-active"); + } else { + star3.classList.replace("tabulator-star-inactive", "tabulator-star-active"); + } + star3.innerHTML = ''; + } else { + if (self.table.browser == "ie") { + star3.setAttribute("class", "tabulator-star-inactive"); + } else { + star3.classList.replace("tabulator-star-active", "tabulator-star-inactive"); + } + star3.innerHTML = ''; + } + }); + } + + function buildStar(i2) { + var starHolder = document.createElement("span"); + var nextStar = star2.cloneNode(true); + stars.push(nextStar); + starHolder.addEventListener("mouseenter", function (e) { + e.stopPropagation(); + e.stopImmediatePropagation(); + starChange(i2); + }); + starHolder.addEventListener("mousemove", function (e) { + e.stopPropagation(); + e.stopImmediatePropagation(); + }); + starHolder.addEventListener("click", function (e) { + e.stopPropagation(); + e.stopImmediatePropagation(); + success(i2); + element.blur(); + }); + starHolder.appendChild(nextStar); + starsHolder.appendChild(starHolder); + } + + function changeValue(val) { + value = val; + starChange(val); + } + + element.style.whiteSpace = "nowrap"; + element.style.overflow = "hidden"; + element.style.textOverflow = "ellipsis"; + starsHolder.style.verticalAlign = "middle"; + starsHolder.style.display = "inline-block"; + starsHolder.style.padding = "4px"; + star2.setAttribute("width", size); + star2.setAttribute("height", size); + star2.setAttribute("viewBox", "0 0 512 512"); + star2.setAttribute("xml:space", "preserve"); + star2.style.padding = "0 1px"; + if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { + for (let key in editorParams.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + starsHolder.setAttribute(key, starsHolder.getAttribute(key) + editorParams.elementAttributes["+" + key]); + } else { + starsHolder.setAttribute(key, editorParams.elementAttributes[key]); + } + } + } + for (var i = 1; i <= maxStars; i++) { + buildStar(i); + } + value = Math.min(parseInt(value), maxStars); + starChange(value); + starsHolder.addEventListener("mousemove", function (e) { + starChange(0); + }); + starsHolder.addEventListener("click", function (e) { + success(0); + }); + element.addEventListener("blur", function (e) { + cancel(); + }); + element.addEventListener("keydown", function (e) { + switch (e.key) { + case "ArrowRight": + changeValue(value + 1); + break; + case "ArrowLeft": + changeValue(value - 1); + break; + case "Enter": + success(value); + break; + case "Escape": + cancel(); + break; + } + }); + return starsHolder; + } + + function progress$1(cell, onRendered, success, cancel, editorParams) { + var element = cell.getElement(), + max = typeof editorParams.max === "undefined" ? element.getElementsByTagName("div")[0] && element.getElementsByTagName("div")[0].getAttribute("max") || 100 : editorParams.max, + min = typeof editorParams.min === "undefined" ? element.getElementsByTagName("div")[0] && element.getElementsByTagName("div")[0].getAttribute("min") || 0 : editorParams.min, + percent = (max - min) / 100, value = cell.getValue() || 0, handle2 = document.createElement("div"), + bar = document.createElement("div"), mouseDrag, mouseDragWidth; + + function updateValue() { + var style = window.getComputedStyle(element, null); + var calcVal = percent * Math.round(bar.offsetWidth / ((element.clientWidth - parseInt(style.getPropertyValue("padding-left")) - parseInt(style.getPropertyValue("padding-right"))) / 100)) + min; + success(calcVal); + element.setAttribute("aria-valuenow", calcVal); + element.setAttribute("aria-label", value); + } + + handle2.style.position = "absolute"; + handle2.style.right = "0"; + handle2.style.top = "0"; + handle2.style.bottom = "0"; + handle2.style.width = "5px"; + handle2.classList.add("tabulator-progress-handle"); + bar.style.display = "inline-block"; + bar.style.position = "relative"; + bar.style.height = "100%"; + bar.style.backgroundColor = "#488CE9"; + bar.style.maxWidth = "100%"; + bar.style.minWidth = "0%"; + if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { + for (let key in editorParams.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + bar.setAttribute(key, bar.getAttribute(key) + editorParams.elementAttributes["+" + key]); + } else { + bar.setAttribute(key, editorParams.elementAttributes[key]); + } + } + } + element.style.padding = "4px 4px"; + value = Math.min(parseFloat(value), max); + value = Math.max(parseFloat(value), min); + value = Math.round((value - min) / percent); + bar.style.width = value + "%"; + element.setAttribute("aria-valuemin", min); + element.setAttribute("aria-valuemax", max); + bar.appendChild(handle2); + handle2.addEventListener("mousedown", function (e) { + mouseDrag = e.screenX; + mouseDragWidth = bar.offsetWidth; + }); + handle2.addEventListener("mouseover", function () { + handle2.style.cursor = "ew-resize"; + }); + element.addEventListener("mousemove", function (e) { + if (mouseDrag) { + bar.style.width = mouseDragWidth + e.screenX - mouseDrag + "px"; + } + }); + element.addEventListener("mouseup", function (e) { + if (mouseDrag) { + e.stopPropagation(); + e.stopImmediatePropagation(); + mouseDrag = false; + mouseDragWidth = false; + updateValue(); + } + }); + element.addEventListener("keydown", function (e) { + switch (e.key) { + case "ArrowRight": + e.preventDefault(); + bar.style.width = bar.clientWidth + element.clientWidth / 100 + "px"; + break; + case "ArrowLeft": + e.preventDefault(); + bar.style.width = bar.clientWidth - element.clientWidth / 100 + "px"; + break; + case "Tab": + case "Enter": + updateValue(); + break; + case "Escape": + cancel(); + break; + } + }); + element.addEventListener("blur", function () { + cancel(); + }); + return bar; + } + + function tickCross$1(cell, onRendered, success, cancel, editorParams) { + var value = cell.getValue(), input2 = document.createElement("input"), tristate = editorParams.tristate, + indetermValue = typeof editorParams.indeterminateValue === "undefined" ? null : editorParams.indeterminateValue, + indetermState = false, trueValueSet = Object.keys(editorParams).includes("trueValue"), + falseValueSet = Object.keys(editorParams).includes("falseValue"); + input2.setAttribute("type", "checkbox"); + input2.style.marginTop = "5px"; + input2.style.boxSizing = "border-box"; + if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { + for (let key in editorParams.elementAttributes) { + if (key.charAt(0) == "+") { + key = key.slice(1); + input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); + } else { + input2.setAttribute(key, editorParams.elementAttributes[key]); + } + } + } + input2.value = value; + if (tristate && (typeof value === "undefined" || value === indetermValue || value === "")) { + indetermState = true; + input2.indeterminate = true; + } + if (this.table.browser != "firefox" && this.table.browser != "safari") { + onRendered(function () { + if (cell.getType() === "cell") { + input2.focus({preventScroll: true}); + } + }); + } + input2.checked = trueValueSet ? value === editorParams.trueValue : value === true || value === "true" || value === "True" || value === 1; + + function setValue(blur) { + var checkedValue = input2.checked; + if (trueValueSet && checkedValue) { + checkedValue = editorParams.trueValue; + } else if (falseValueSet && !checkedValue) { + checkedValue = editorParams.falseValue; + } + if (tristate) { + if (!blur) { + if (input2.checked && !indetermState) { + input2.checked = false; + input2.indeterminate = true; + indetermState = true; + return indetermValue; + } else { + indetermState = false; + return checkedValue; + } + } else { + if (indetermState) { + return indetermValue; + } else { + return checkedValue; + } + } + } else { + return checkedValue; + } + } + + input2.addEventListener("change", function (e) { + success(setValue()); + }); + input2.addEventListener("blur", function (e) { + success(setValue(true)); + }); + input2.addEventListener("keydown", function (e) { + if (e.key == "Enter") { + success(setValue()); + } + if (e.key == "Escape") { + cancel(); + } + }); + return input2; + } + + function adaptable$1(cell, onRendered, success, cancel, params) { + var column = cell._getSelf().column, lookup2, editorFunc, editorParams; + + function defaultLookup(cell2) { + var value = cell2.getValue(), editor = "input"; + switch (typeof value) { + case "number": + editor = "number"; + break; + case "boolean": + editor = "tickCross"; + break; + case "string": + if (value.includes("\n")) { + editor = "textarea"; + } + break; + } + return editor; + } + + lookup2 = params.editorLookup ? params.editorLookup(cell) : defaultLookup(cell); + if (params.paramsLookup) { + editorParams = typeof params.paramsLookup === "function" ? params.paramsLookup(lookup2, cell) : params.paramsLookup[lookup2]; + } + editorFunc = this.table.modules.edit.lookupEditor(lookup2, column); + return editorFunc.call(this, cell, onRendered, success, cancel, editorParams || {}); + } + + var defaultEditors = { + input, + textarea: textarea$1, + number: number$1, + range, + date: date$1, + time: time$1, + datetime: datetime$2, + list, + star: star$1, + progress: progress$1, + tickCross: tickCross$1, + adaptable: adaptable$1 + }; + const _Edit = class _Edit extends Module { + constructor(table) { + super(table); + this.currentCell = false; + this.mouseClick = false; + this.recursionBlock = false; + this.invalidEdit = false; + this.editedCells = []; + this.convertEmptyValues = false; + this.editors = _Edit.editors; + this.registerTableOption("editTriggerEvent", "focus"); + this.registerTableOption("editorEmptyValue"); + this.registerTableOption("editorEmptyValueFunc", this.emptyValueCheck.bind(this)); + this.registerColumnOption("editable"); + this.registerColumnOption("editor"); + this.registerColumnOption("editorParams"); + this.registerColumnOption("editorEmptyValue"); + this.registerColumnOption("editorEmptyValueFunc"); + this.registerColumnOption("cellEditing"); + this.registerColumnOption("cellEdited"); + this.registerColumnOption("cellEditCancelled"); + this.registerTableFunction("getEditedCells", this.getEditedCells.bind(this)); + this.registerTableFunction("clearCellEdited", this.clearCellEdited.bind(this)); + this.registerTableFunction("navigatePrev", this.navigatePrev.bind(this)); + this.registerTableFunction("navigateNext", this.navigateNext.bind(this)); + this.registerTableFunction("navigateLeft", this.navigateLeft.bind(this)); + this.registerTableFunction("navigateRight", this.navigateRight.bind(this)); + this.registerTableFunction("navigateUp", this.navigateUp.bind(this)); + this.registerTableFunction("navigateDown", this.navigateDown.bind(this)); + this.registerComponentFunction("cell", "isEdited", this.cellIsEdited.bind(this)); + this.registerComponentFunction("cell", "clearEdited", this.clearEdited.bind(this)); + this.registerComponentFunction("cell", "edit", this.editCell.bind(this)); + this.registerComponentFunction("cell", "cancelEdit", this.cellCancelEdit.bind(this)); + this.registerComponentFunction("cell", "navigatePrev", this.navigatePrev.bind(this)); + this.registerComponentFunction("cell", "navigateNext", this.navigateNext.bind(this)); + this.registerComponentFunction("cell", "navigateLeft", this.navigateLeft.bind(this)); + this.registerComponentFunction("cell", "navigateRight", this.navigateRight.bind(this)); + this.registerComponentFunction("cell", "navigateUp", this.navigateUp.bind(this)); + this.registerComponentFunction("cell", "navigateDown", this.navigateDown.bind(this)); + } + + initialize() { + this.subscribe("cell-init", this.bindEditor.bind(this)); + this.subscribe("cell-delete", this.clearEdited.bind(this)); + this.subscribe("cell-value-changed", this.updateCellClass.bind(this)); + this.subscribe("column-layout", this.initializeColumnCheck.bind(this)); + this.subscribe("column-delete", this.columnDeleteCheck.bind(this)); + this.subscribe("row-deleting", this.rowDeleteCheck.bind(this)); + this.subscribe("row-layout", this.rowEditableCheck.bind(this)); + this.subscribe("data-refreshing", this.cancelEdit.bind(this)); + this.subscribe("clipboard-paste", this.pasteBlocker.bind(this)); + if (!this.confirm("edit-nav-disabled")) { + this.subscribe("keybinding-nav-prev", this.navigatePrev.bind(this, void 0)); + this.subscribe("keybinding-nav-next", this.keybindingNavigateNext.bind(this)); + this.subscribe("keybinding-nav-up", this.navigateUp.bind(this, void 0)); + this.subscribe("keybinding-nav-down", this.navigateDown.bind(this, void 0)); + } + this.subscribe("edit-check-editing", this.checkEditing.bind(this)); + this.subscribe("edit-cancel-cell", this.cancelEditEvent.bind(this)); + if (Object.keys(this.table.options).includes("editorEmptyValue")) { + this.convertEmptyValues = true; + } + } + + /////////////////////////////////// + ///////// Paste Negation ////////// + /////////////////////////////////// + pasteBlocker(e) { + if (this.currentCell) { + return true; + } + } + + /////////////////////////////////// + ////// Keybinding Functions /////// + /////////////////////////////////// + keybindingNavigateNext(e) { + var cell = this.currentCell, newRow = this.options("tabEndNewRow"); + if (cell) { + if (!this.navigateNext(cell, e)) { + if (newRow) { + cell.getElement().firstChild.blur(); + if (!this.invalidEdit) { + if (newRow === true) { + newRow = this.table.addRow({}); + } else { + if (typeof newRow == "function") { + newRow = this.table.addRow(newRow(cell.row.getComponent())); + } else { + newRow = this.table.addRow(Object.assign({}, newRow)); + } + } + newRow.then(() => { + setTimeout(() => { + cell.getComponent().navigateNext(); + }); + }); + } + } + } + } + } + + /////////////////////////////////// + ///////// Cell Functions ////////// + /////////////////////////////////// + cellIsEdited(cell) { + return !!cell.modules.edit && cell.modules.edit.edited; + } + + cellCancelEdit(cell) { + if (cell === this.currentCell) { + this.table.modules.edit.cancelEdit(); + } else { + console.warn("Cancel Editor Error - This cell is not currently being edited "); + } + } + + /////////////////////////////////// + ///////// Table Functions ///////// + /////////////////////////////////// + updateCellClass(cell) { + if (this.allowEdit(cell)) { + cell.getElement().classList.add("tabulator-editable"); + } else { + cell.getElement().classList.remove("tabulator-editable"); + } + } + + clearCellEdited(cells) { + if (!cells) { + cells = this.table.modules.edit.getEditedCells(); + } + if (!Array.isArray(cells)) { + cells = [cells]; + } + cells.forEach((cell) => { + this.table.modules.edit.clearEdited(cell._getSelf()); + }); + } + + navigatePrev(cell = this.currentCell, e) { + var nextCell, prevRow; + if (cell) { + if (e) { + e.preventDefault(); + } + nextCell = this.navigateLeft(); + if (nextCell) { + return true; + } else { + prevRow = this.table.rowManager.prevDisplayRow(cell.row, true); + if (prevRow) { + nextCell = this.findPrevEditableCell(prevRow, prevRow.cells.length); + if (nextCell) { + nextCell.getComponent().edit(); + return true; + } + } + } + } + return false; + } + + navigateNext(cell = this.currentCell, e) { + var nextCell, nextRow; + if (cell) { + if (e) { + e.preventDefault(); + } + nextCell = this.navigateRight(); + if (nextCell) { + return true; + } else { + nextRow = this.table.rowManager.nextDisplayRow(cell.row, true); + if (nextRow) { + nextCell = this.findNextEditableCell(nextRow, -1); + if (nextCell) { + nextCell.getComponent().edit(); + return true; + } + } + } + } + return false; + } + + navigateLeft(cell = this.currentCell, e) { + var index, nextCell; + if (cell) { + if (e) { + e.preventDefault(); + } + index = cell.getIndex(); + nextCell = this.findPrevEditableCell(cell.row, index); + if (nextCell) { + nextCell.getComponent().edit(); + return true; + } + } + return false; + } + + navigateRight(cell = this.currentCell, e) { + var index, nextCell; + if (cell) { + if (e) { + e.preventDefault(); + } + index = cell.getIndex(); + nextCell = this.findNextEditableCell(cell.row, index); + if (nextCell) { + nextCell.getComponent().edit(); + return true; + } + } + return false; + } + + navigateUp(cell = this.currentCell, e) { + var index, nextRow; + if (cell) { + if (e) { + e.preventDefault(); + } + index = cell.getIndex(); + nextRow = this.table.rowManager.prevDisplayRow(cell.row, true); + if (nextRow) { + nextRow.cells[index].getComponent().edit(); + return true; + } + } + return false; + } + + navigateDown(cell = this.currentCell, e) { + var index, nextRow; + if (cell) { + if (e) { + e.preventDefault(); + } + index = cell.getIndex(); + nextRow = this.table.rowManager.nextDisplayRow(cell.row, true); + if (nextRow) { + nextRow.cells[index].getComponent().edit(); + return true; + } + } + return false; + } + + findNextEditableCell(row, index) { + var nextCell = false; + if (index < row.cells.length - 1) { + for (var i = index + 1; i < row.cells.length; i++) { + let cell = row.cells[i]; + if (cell.column.modules.edit && Helpers.elVisible(cell.getElement())) { + let allowEdit = this.allowEdit(cell); + if (allowEdit) { + nextCell = cell; + break; + } + } + } + } + return nextCell; + } + + findPrevEditableCell(row, index) { + var prevCell = false; + if (index > 0) { + for (var i = index - 1; i >= 0; i--) { + let cell = row.cells[i]; + if (cell.column.modules.edit && Helpers.elVisible(cell.getElement())) { + let allowEdit = this.allowEdit(cell); + if (allowEdit) { + prevCell = cell; + break; + } + } + } + } + return prevCell; + } + + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + initializeColumnCheck(column) { + if (typeof column.definition.editor !== "undefined") { + this.initializeColumn(column); + } + } + + columnDeleteCheck(column) { + if (this.currentCell && this.currentCell.column === column) { + this.cancelEdit(); + } + } + + rowDeleteCheck(row) { + if (this.currentCell && this.currentCell.row === row) { + this.cancelEdit(); + } + } + + rowEditableCheck(row) { + row.getCells().forEach((cell) => { + if (cell.column.modules.edit && typeof cell.column.modules.edit.check === "function") { + this.updateCellClass(cell); + } + }); + } + + //initialize column editor + initializeColumn(column) { + var convertEmpty = Object.keys(column.definition).includes("editorEmptyValue"); + var config = { + editor: false, + blocked: false, + check: column.definition.editable, + params: column.definition.editorParams || {}, + convertEmptyValues: convertEmpty, + editorEmptyValue: column.definition.editorEmptyValue, + editorEmptyValueFunc: column.definition.editorEmptyValueFunc + }; + config.editor = this.lookupEditor(column.definition.editor, column); + if (config.editor) { + column.modules.edit = config; + } + } + + lookupEditor(editor, column) { + var editorFunc; + switch (typeof editor) { + case "string": + if (this.editors[editor]) { + editorFunc = this.editors[editor]; + } else { + console.warn("Editor Error - No such editor found: ", editor); + } + break; + case "function": + editorFunc = editor; + break; + case "boolean": + if (editor === true) { + if (typeof column.definition.formatter !== "function") { + if (this.editors[column.definition.formatter]) { + editorFunc = this.editors[column.definition.formatter]; + } else { + editorFunc = this.editors["input"]; + } + } else { + console.warn("Editor Error - Cannot auto lookup editor for a custom formatter: ", column.definition.formatter); + } + } + break; + } + return editorFunc; + } + + getCurrentCell() { + return this.currentCell ? this.currentCell.getComponent() : false; + } + + checkEditing() { + return !!this.currentCell; + } + + cancelEditEvent() { + if (this.currentCell) { + this.cancelEdit(); + return true; + } + return false; + } + + clearEditor(cancel) { + var cell = this.currentCell, cellEl; + this.invalidEdit = false; + if (cell) { + this.currentCell = false; + cellEl = cell.getElement(); + this.dispatch("edit-editor-clear", cell, cancel); + cellEl.classList.remove("tabulator-editing"); + while (cellEl.firstChild) cellEl.removeChild(cellEl.firstChild); + cell.row.getElement().classList.remove("tabulator-editing"); + cell.table.element.classList.remove("tabulator-editing"); + } + } + + cancelEdit() { + if (this.currentCell) { + var cell = this.currentCell; + var component = this.currentCell.getComponent(); + this.clearEditor(true); + cell.setValueActual(cell.getValue()); + cell.cellRendered(); + if (cell.column.definition.editor == "textarea" || cell.column.definition.variableHeight) { + cell.row.normalizeHeight(true); + } + if (cell.column.definition.cellEditCancelled) { + cell.column.definition.cellEditCancelled.call(this.table, component); + } + this.dispatch("edit-cancelled", cell); + this.dispatchExternal("cellEditCancelled", component); + } + } + + //return a formatted value for a cell + bindEditor(cell) { + if (cell.column.modules.edit) { + var self = this, element = cell.getElement(true); + this.updateCellClass(cell); + element.setAttribute("tabindex", 0); + element.addEventListener("mousedown", function (e) { + if (e.button === 2) { + e.preventDefault(); + } else { + self.mouseClick = true; + } + }); + if (this.options("editTriggerEvent") === "dblclick") { + element.addEventListener("dblclick", function (e) { + if (!element.classList.contains("tabulator-editing")) { + element.focus({preventScroll: true}); + self.edit(cell, e, false); + } + }); + } + if (this.options("editTriggerEvent") === "focus" || this.options("editTriggerEvent") === "click") { + element.addEventListener("click", function (e) { + if (!element.classList.contains("tabulator-editing")) { + element.focus({preventScroll: true}); + self.edit(cell, e, false); + } + }); + } + if (this.options("editTriggerEvent") === "focus") { + element.addEventListener("focus", function (e) { + if (!self.recursionBlock) { + self.edit(cell, e, false); + } + }); + } + } + } + + focusCellNoEvent(cell, block) { + this.recursionBlock = true; + if (!(block && this.table.browser === "ie")) { + cell.getElement().focus({preventScroll: true}); + } + this.recursionBlock = false; + } + + editCell(cell, forceEdit) { + this.focusCellNoEvent(cell); + this.edit(cell, false, forceEdit); + } + + focusScrollAdjust(cell) { + if (this.table.rowManager.getRenderMode() == "virtual") { + var topEdge = this.table.rowManager.element.scrollTop, + bottomEdge = this.table.rowManager.element.clientHeight + this.table.rowManager.element.scrollTop, + rowEl = cell.row.getElement(); + if (rowEl.offsetTop < topEdge) { + this.table.rowManager.element.scrollTop -= topEdge - rowEl.offsetTop; + } else { + if (rowEl.offsetTop + rowEl.offsetHeight > bottomEdge) { + this.table.rowManager.element.scrollTop += rowEl.offsetTop + rowEl.offsetHeight - bottomEdge; + } + } + var leftEdge = this.table.rowManager.element.scrollLeft, + rightEdge = this.table.rowManager.element.clientWidth + this.table.rowManager.element.scrollLeft, + cellEl = cell.getElement(); + if (this.table.modExists("frozenColumns")) { + leftEdge += parseInt(this.table.modules.frozenColumns.leftMargin || 0); + rightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin || 0); + } + if (this.table.options.renderHorizontal === "virtual") { + leftEdge -= parseInt(this.table.columnManager.renderer.vDomPadLeft); + rightEdge -= parseInt(this.table.columnManager.renderer.vDomPadLeft); + } + if (cellEl.offsetLeft < leftEdge) { + this.table.rowManager.element.scrollLeft -= leftEdge - cellEl.offsetLeft; + } else { + if (cellEl.offsetLeft + cellEl.offsetWidth > rightEdge) { + this.table.rowManager.element.scrollLeft += cellEl.offsetLeft + cellEl.offsetWidth - rightEdge; + } + } + } + } + + allowEdit(cell) { + var check = cell.column.modules.edit ? true : false; + if (cell.column.modules.edit) { + switch (typeof cell.column.modules.edit.check) { + case "function": + if (cell.row.initialized) { + check = cell.column.modules.edit.check(cell.getComponent()); + } + break; + case "string": + check = !!cell.row.data[cell.column.modules.edit.check]; + break; + case "boolean": + check = cell.column.modules.edit.check; + break; + } + } + return check; + } + + edit(cell, e, forceEdit) { + var self = this, allowEdit = true, rendered = function () { + }, element = cell.getElement(), editFinished = false, cellEditor, component, params; + if (this.currentCell) { + if (!this.invalidEdit && this.currentCell !== cell) { + this.cancelEdit(); + } + return; + } + + function success(value) { + if (self.currentCell === cell && !editFinished) { + var valid = self.chain("edit-success", [cell, value], true, true); + if (valid === true || self.table.options.validationMode === "highlight") { + editFinished = true; + self.clearEditor(); + if (!cell.modules.edit) { + cell.modules.edit = {}; + } + cell.modules.edit.edited = true; + if (self.editedCells.indexOf(cell) == -1) { + self.editedCells.push(cell); + } + value = self.transformEmptyValues(value, cell); + cell.setValue(value, true); + return valid === true; + } else { + editFinished = true; + self.invalidEdit = true; + self.focusCellNoEvent(cell, true); + rendered(); + setTimeout(() => { + editFinished = false; + }, 10); + return false; + } + } + } + + function cancel() { + if (self.currentCell === cell && !editFinished) { + self.cancelEdit(); + } + } + + function onRendered(callback) { + rendered = callback; + } + + if (!cell.column.modules.edit.blocked) { + allowEdit = this.allowEdit(cell); + if (allowEdit || forceEdit) { + if (e) { + e.stopPropagation(); + } + self.cancelEdit(); + self.currentCell = cell; + this.focusScrollAdjust(cell); + component = cell.getComponent(); + if (this.mouseClick) { + this.mouseClick = false; + if (cell.column.definition.cellClick) { + cell.column.definition.cellClick.call(this.table, e, component); + } + } + if (cell.column.definition.cellEditing) { + cell.column.definition.cellEditing.call(this.table, component); + } + this.dispatch("cell-editing", cell); + this.dispatchExternal("cellEditing", component); + params = typeof cell.column.modules.edit.params === "function" ? cell.column.modules.edit.params(component) : cell.column.modules.edit.params; + cellEditor = cell.column.modules.edit.editor.call(self, component, onRendered, success, cancel, params); + if (this.currentCell && cellEditor !== false) { + if (cellEditor instanceof Node) { + element.classList.add("tabulator-editing"); + cell.row.getElement().classList.add("tabulator-editing"); + cell.table.element.classList.add("tabulator-editing"); + while (element.firstChild) element.removeChild(element.firstChild); + element.appendChild(cellEditor); + rendered(); + var children = element.children; + for (var i = 0; i < children.length; i++) { + children[i].addEventListener("click", function (e2) { + e2.stopPropagation(); + }); + } + } else { + console.warn("Edit Error - Editor should return an instance of Node, the editor returned:", cellEditor); + this.blur(element); + return false; + } + } else { + this.blur(element); + return false; + } + return true; + } else { + this.mouseClick = false; + this.blur(element); + return false; + } + } else { + this.mouseClick = false; + this.blur(element); + return false; + } + } + + emptyValueCheck(value) { + return value === "" || value === null || typeof value === "undefined"; + } + + transformEmptyValues(value, cell) { + var mod = cell.column.modules.edit, convert = mod.convertEmptyValues || this.convertEmptyValues, + checkFunc; + if (convert) { + checkFunc = mod.editorEmptyValueFunc || this.options("editorEmptyValueFunc"); + if (checkFunc && checkFunc(value)) { + value = mod.convertEmptyValues ? mod.editorEmptyValue : this.options("editorEmptyValue"); + } + } + return value; + } + + blur(element) { + if (!this.confirm("edit-blur", [element])) { + element.blur(); + } + } + + getEditedCells() { + var output = []; + this.editedCells.forEach((cell) => { + output.push(cell.getComponent()); + }); + return output; + } + + clearEdited(cell) { + var editIndex; + if (cell.modules.edit && cell.modules.edit.edited) { + cell.modules.edit.edited = false; + this.dispatch("edit-edited-clear", cell); + } + editIndex = this.editedCells.indexOf(cell); + if (editIndex > -1) { + this.editedCells.splice(editIndex, 1); + } + } + }; + __publicField(_Edit, "moduleName", "edit"); + //load defaults + __publicField(_Edit, "editors", defaultEditors); + let Edit2 = _Edit; + + class ExportRow { + constructor(type, columns, component, indent) { + this.type = type; + this.columns = columns; + this.component = component || false; + this.indent = indent || 0; + } + } + + class ExportColumn { + constructor(value, component, width, height, depth) { + this.value = value; + this.component = component || false; + this.width = width; + this.height = height; + this.depth = depth; + } + } + + var columnLookups$1 = {}; + var rowLookups$1 = { + visible: function () { + return this.rowManager.getVisibleRows(false, true); + }, + all: function () { + return this.rowManager.rows; + }, + selected: function () { + return this.modules.selectRow.selectedRows; + }, + active: function () { + if (this.options.pagination) { + return this.rowManager.getDisplayRows(this.rowManager.displayRows.length - 2); + } else { + return this.rowManager.getDisplayRows(); + } + } + }; + const _Export = class _Export extends Module { + constructor(table) { + super(table); + this.config = {}; + this.cloneTableStyle = true; + this.colVisProp = ""; + this.colVisPropAttach = ""; + this.registerTableOption("htmlOutputConfig", false); + this.registerColumnOption("htmlOutput"); + this.registerColumnOption("titleHtmlOutput"); + } + + initialize() { + this.registerTableFunction("getHtml", this.getHtml.bind(this)); + } + + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + generateExportList(config, style, range2, colVisProp) { + var headers, body, columns, colLookup; + this.cloneTableStyle = style; + this.config = config || {}; + this.colVisProp = colVisProp; + this.colVisPropAttach = this.colVisProp.charAt(0).toUpperCase() + this.colVisProp.slice(1); + colLookup = _Export.columnLookups[range2]; + if (colLookup) { + columns = colLookup.call(this.table); + columns = columns.filter((col) => this.columnVisCheck(col)); + } + headers = this.config.columnHeaders !== false ? this.headersToExportRows(this.generateColumnGroupHeaders(columns)) : []; + if (columns) { + columns = columns.map((col) => col.getComponent()); + } + body = this.bodyToExportRows(this.rowLookup(range2), columns); + return headers.concat(body); + } + + generateTable(config, style, range2, colVisProp) { + var list2 = this.generateExportList(config, style, range2, colVisProp); + return this.generateTableElement(list2); + } + + rowLookup(range2) { + var rows2 = [], rowLookup; + if (typeof range2 == "function") { + range2.call(this.table).forEach((row) => { + row = this.table.rowManager.findRow(row); + if (row) { + rows2.push(row); + } + }); + } else { + rowLookup = _Export.rowLookups[range2] || _Export.rowLookups["active"]; + rows2 = rowLookup.call(this.table); + } + return Object.assign([], rows2); + } + + generateColumnGroupHeaders(columns) { + var output = []; + if (!columns) { + columns = this.config.columnGroups !== false ? this.table.columnManager.columns : this.table.columnManager.columnsByIndex; + } + columns.forEach((column) => { + var colData = this.processColumnGroup(column); + if (colData) { + output.push(colData); + } + }); + return output; + } + + processColumnGroup(column) { + var subGroups = column.columns, maxDepth = 0, + title = column.definition["title" + this.colVisPropAttach] || column.definition.title; + var groupData = { + title, + column, + depth: 1 + }; + if (subGroups.length) { + groupData.subGroups = []; + groupData.width = 0; + subGroups.forEach((subGroup) => { + var subGroupData = this.processColumnGroup(subGroup); + if (subGroupData) { + groupData.width += subGroupData.width; + groupData.subGroups.push(subGroupData); + if (subGroupData.depth > maxDepth) { + maxDepth = subGroupData.depth; + } + } + }); + groupData.depth += maxDepth; + if (!groupData.width) { + return false; + } + } else { + if (this.columnVisCheck(column)) { + groupData.width = 1; + } else { + return false; + } + } + return groupData; + } + + columnVisCheck(column) { + var visProp = column.definition[this.colVisProp]; + if (this.config.rowHeaders === false && column.isRowHeader) { + return false; + } + if (typeof visProp === "function") { + visProp = visProp.call(this.table, column.getComponent()); + } + if (visProp === false || visProp === true) { + return visProp; + } + return column.visible && column.field; + } + + headersToExportRows(columns) { + var headers = [], headerDepth = 0, exportRows = []; + + function parseColumnGroup(column, level) { + var depth = headerDepth - level; + if (typeof headers[level] === "undefined") { + headers[level] = []; + } + column.height = column.subGroups ? 1 : depth - column.depth + 1; + headers[level].push(column); + if (column.height > 1) { + for (let i = 1; i < column.height; i++) { + if (typeof headers[level + i] === "undefined") { + headers[level + i] = []; + } + headers[level + i].push(false); + } + } + if (column.width > 1) { + for (let i = 1; i < column.width; i++) { + headers[level].push(false); + } + } + if (column.subGroups) { + column.subGroups.forEach(function (subGroup) { + parseColumnGroup(subGroup, level + 1); + }); + } + } + + columns.forEach(function (column) { + if (column.depth > headerDepth) { + headerDepth = column.depth; + } + }); + columns.forEach(function (column) { + parseColumnGroup(column, 0); + }); + headers.forEach((header) => { + var columns2 = []; + header.forEach((col) => { + if (col) { + let title = typeof col.title === "undefined" ? "" : col.title; + columns2.push(new ExportColumn(title, col.column.getComponent(), col.width, col.height, col.depth)); + } else { + columns2.push(null); + } + }); + exportRows.push(new ExportRow("header", columns2)); + }); + return exportRows; + } + + bodyToExportRows(rows2, columns = []) { + var exportRows = []; + if (columns.length === 0) { + this.table.columnManager.columnsByIndex.forEach((column) => { + if (this.columnVisCheck(column)) { + columns.push(column.getComponent()); + } + }); + } + if (this.config.columnCalcs !== false && this.table.modExists("columnCalcs")) { + if (this.table.modules.columnCalcs.topInitialized) { + rows2.unshift(this.table.modules.columnCalcs.topRow); + } + if (this.table.modules.columnCalcs.botInitialized) { + rows2.push(this.table.modules.columnCalcs.botRow); + } + } + rows2 = rows2.filter((row) => { + switch (row.type) { + case "group": + return this.config.rowGroups !== false; + case "calc": + return this.config.columnCalcs !== false; + case "row": + return !(this.table.options.dataTree && this.config.dataTree === false && row.modules.dataTree.parent); + } + return true; + }); + rows2.forEach((row, i) => { + var rowData = row.getData(this.colVisProp); + var exportCols = []; + var indent = 0; + switch (row.type) { + case "group": + indent = row.level; + exportCols.push(new ExportColumn(row.key, row.getComponent(), columns.length, 1)); + break; + case "calc": + case "row": + columns.forEach((col) => { + exportCols.push(new ExportColumn(col._column.getFieldValue(rowData), col, 1, 1)); + }); + if (this.table.options.dataTree && this.config.dataTree !== false) { + indent = row.modules.dataTree.index; + } + break; + } + exportRows.push(new ExportRow(row.type, exportCols, row.getComponent(), indent)); + }); + return exportRows; + } + + generateTableElement(list2) { + var table = document.createElement("table"), headerEl = document.createElement("thead"), + bodyEl = document.createElement("tbody"), styles = this.lookupTableStyles(), + rowFormatter = this.table.options["rowFormatter" + this.colVisPropAttach], setup = {}; + setup.rowFormatter = rowFormatter !== null ? rowFormatter : this.table.options.rowFormatter; + if (this.table.options.dataTree && this.config.dataTree !== false && this.table.modExists("columnCalcs")) { + setup.treeElementField = this.table.modules.dataTree.elementField; + } + setup.groupHeader = this.table.options["groupHeader" + this.colVisPropAttach]; + if (setup.groupHeader && !Array.isArray(setup.groupHeader)) { + setup.groupHeader = [setup.groupHeader]; + } + table.classList.add("tabulator-print-table"); + this.mapElementStyles(this.table.columnManager.getHeadersElement(), headerEl, ["border-top", "border-left", "border-right", "border-bottom", "background-color", "color", "font-weight", "font-family", "font-size"]); + if (list2.length > 1e3) { + console.warn("It may take a long time to render an HTML table with more than 1000 rows"); + } + list2.forEach((row, i) => { + let rowEl; + switch (row.type) { + case "header": + headerEl.appendChild(this.generateHeaderElement(row, setup, styles)); + break; + case "group": + bodyEl.appendChild(this.generateGroupElement(row, setup, styles)); + break; + case "calc": + bodyEl.appendChild(this.generateCalcElement(row, setup, styles)); + break; + case "row": + rowEl = this.generateRowElement(row, setup, styles); + this.mapElementStyles(i % 2 && styles.evenRow ? styles.evenRow : styles.oddRow, rowEl, ["border-top", "border-left", "border-right", "border-bottom", "color", "font-weight", "font-family", "font-size", "background-color"]); + bodyEl.appendChild(rowEl); + break; + } + }); + if (headerEl.innerHTML) { + table.appendChild(headerEl); + } + table.appendChild(bodyEl); + this.mapElementStyles(this.table.element, table, ["border-top", "border-left", "border-right", "border-bottom"]); + return table; + } + + lookupTableStyles() { + var styles = {}; + if (this.cloneTableStyle && window.getComputedStyle) { + styles.oddRow = this.table.element.querySelector(".tabulator-row-odd:not(.tabulator-group):not(.tabulator-calcs)"); + styles.evenRow = this.table.element.querySelector(".tabulator-row-even:not(.tabulator-group):not(.tabulator-calcs)"); + styles.calcRow = this.table.element.querySelector(".tabulator-row.tabulator-calcs"); + styles.firstRow = this.table.element.querySelector(".tabulator-row:not(.tabulator-group):not(.tabulator-calcs)"); + styles.firstGroup = this.table.element.getElementsByClassName("tabulator-group")[0]; + if (styles.firstRow) { + styles.styleCells = styles.firstRow.getElementsByClassName("tabulator-cell"); + styles.styleRowHeader = styles.firstRow.getElementsByClassName("tabulator-row-header")[0]; + styles.firstCell = styles.styleCells[0]; + styles.lastCell = styles.styleCells[styles.styleCells.length - 1]; + } + } + return styles; + } + + generateHeaderElement(row, setup, styles) { + var rowEl = document.createElement("tr"); + row.columns.forEach((column) => { + if (column) { + var cellEl = document.createElement("th"); + var classNames = column.component._column.definition.cssClass ? column.component._column.definition.cssClass.split(" ") : []; + cellEl.colSpan = column.width; + cellEl.rowSpan = column.height; + cellEl.innerHTML = column.value; + if (this.cloneTableStyle) { + cellEl.style.boxSizing = "border-box"; + } + classNames.forEach(function (className) { + cellEl.classList.add(className); + }); + this.mapElementStyles(column.component.getElement(), cellEl, ["text-align", "border-left", "border-right", "background-color", "color", "font-weight", "font-family", "font-size"]); + this.mapElementStyles(column.component._column.contentElement, cellEl, ["padding-top", "padding-left", "padding-right", "padding-bottom"]); + if (column.component._column.visible) { + this.mapElementStyles(column.component.getElement(), cellEl, ["width"]); + } else { + if (column.component._column.definition.width) { + cellEl.style.width = column.component._column.definition.width + "px"; + } + } + if (column.component._column.parent && column.component._column.parent.isGroup) { + this.mapElementStyles(column.component._column.parent.groupElement, cellEl, ["border-top"]); + } else { + this.mapElementStyles(column.component.getElement(), cellEl, ["border-top"]); + } + if (column.component._column.isGroup) { + this.mapElementStyles(column.component.getElement(), cellEl, ["border-bottom"]); + } else { + this.mapElementStyles(this.table.columnManager.getElement(), cellEl, ["border-bottom"]); + } + rowEl.appendChild(cellEl); + } + }); + return rowEl; + } + + generateGroupElement(row, setup, styles) { + var rowEl = document.createElement("tr"), cellEl = document.createElement("td"), group = row.columns[0]; + rowEl.classList.add("tabulator-print-table-row"); + if (setup.groupHeader && setup.groupHeader[row.indent]) { + group.value = setup.groupHeader[row.indent](group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component); + } else { + if (setup.groupHeader !== false) { + group.value = row.component._group.generator(group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component); + } + } + cellEl.colSpan = group.width; + cellEl.innerHTML = group.value; + rowEl.classList.add("tabulator-print-table-group"); + rowEl.classList.add("tabulator-group-level-" + row.indent); + if (group.component.isVisible()) { + rowEl.classList.add("tabulator-group-visible"); + } + this.mapElementStyles(styles.firstGroup, rowEl, ["border-top", "border-left", "border-right", "border-bottom", "color", "font-weight", "font-family", "font-size", "background-color"]); + this.mapElementStyles(styles.firstGroup, cellEl, ["padding-top", "padding-left", "padding-right", "padding-bottom"]); + rowEl.appendChild(cellEl); + return rowEl; + } + + generateCalcElement(row, setup, styles) { + var rowEl = this.generateRowElement(row, setup, styles); + rowEl.classList.add("tabulator-print-table-calcs"); + this.mapElementStyles(styles.calcRow, rowEl, ["border-top", "border-left", "border-right", "border-bottom", "color", "font-weight", "font-family", "font-size", "background-color"]); + return rowEl; + } + + generateRowElement(row, setup, styles) { + var rowEl = document.createElement("tr"); + rowEl.classList.add("tabulator-print-table-row"); + row.columns.forEach((col, i) => { + if (col) { + var cellEl = document.createElement("td"), column = col.component._column, table = this.table, + index = table.columnManager.findColumnIndex(column), value = col.value, cellStyle, + styleProps; + var cellWrapper = { + modules: {}, + getValue: function () { + return value; + }, + getField: function () { + return column.definition.field; + }, + getElement: function () { + return cellEl; + }, + getType: function () { + return "cell"; + }, + getColumn: function () { + return column.getComponent(); + }, + getData: function () { + return row.component.getData(); + }, + getRow: function () { + return row.component; + }, + getTable: function () { + return table; + }, + getComponent: function () { + return cellWrapper; + }, + column + }; + var classNames = column.definition.cssClass ? column.definition.cssClass.split(" ") : []; + classNames.forEach(function (className) { + cellEl.classList.add(className); + }); + if (this.table.modExists("format") && this.config.formatCells !== false) { + value = this.table.modules.format.formatExportValue(cellWrapper, this.colVisProp); + } else { + switch (typeof value) { + case "object": + value = value !== null ? JSON.stringify(value) : ""; + break; + case "undefined": + value = ""; + break; + } + } + if (value instanceof Node) { + cellEl.appendChild(value); + } else { + cellEl.innerHTML = value; + } + styleProps = ["padding-top", "padding-left", "padding-right", "padding-bottom", "border-top", "border-left", "border-right", "border-bottom", "color", "font-weight", "font-family", "font-size", "text-align"]; + if (column.isRowHeader) { + cellStyle = styles.styleRowHeader; + styleProps.push("background-color"); + } else { + cellStyle = styles.styleCells && styles.styleCells[index] ? styles.styleCells[index] : styles.firstCell; + } + if (cellStyle) { + this.mapElementStyles(cellStyle, cellEl, styleProps); + if (column.definition.align) { + cellEl.style.textAlign = column.definition.align; + } + } + if (this.table.options.dataTree && this.config.dataTree !== false) { + if (setup.treeElementField && setup.treeElementField == column.field || !setup.treeElementField && i == 0) { + if (row.component._row.modules.dataTree.controlEl) { + cellEl.insertBefore(row.component._row.modules.dataTree.controlEl.cloneNode(true), cellEl.firstChild); + } + if (row.component._row.modules.dataTree.branchEl) { + cellEl.insertBefore(row.component._row.modules.dataTree.branchEl.cloneNode(true), cellEl.firstChild); + } + } + } + rowEl.appendChild(cellEl); + if (cellWrapper.modules.format && cellWrapper.modules.format.renderedCallback) { + cellWrapper.modules.format.renderedCallback(); + } + } + }); + if (setup.rowFormatter && row.type === "row" && this.config.formatCells !== false) { + let formatComponent = Object.assign(row.component); + formatComponent.getElement = function () { + return rowEl; + }; + setup.rowFormatter(row.component); + } + return rowEl; + } + + generateHTMLTable(list2) { + var holder = document.createElement("div"); + holder.appendChild(this.generateTableElement(list2)); + return holder.innerHTML; + } + + getHtml(visible, style, config, colVisProp) { + var list2 = this.generateExportList(config || this.table.options.htmlOutputConfig, style, visible, colVisProp || "htmlOutput"); + return this.generateHTMLTable(list2); + } + + mapElementStyles(from, to, props) { + if (this.cloneTableStyle && from && to) { + var lookup2 = { + "background-color": "backgroundColor", + "color": "fontColor", + "width": "width", + "font-weight": "fontWeight", + "font-family": "fontFamily", + "font-size": "fontSize", + "text-align": "textAlign", + "border-top": "borderTop", + "border-left": "borderLeft", + "border-right": "borderRight", + "border-bottom": "borderBottom", + "padding-top": "paddingTop", + "padding-left": "paddingLeft", + "padding-right": "paddingRight", + "padding-bottom": "paddingBottom" + }; + if (window.getComputedStyle) { + var fromStyle = window.getComputedStyle(from); + props.forEach(function (prop) { + if (!to.style[lookup2[prop]]) { + to.style[lookup2[prop]] = fromStyle.getPropertyValue(prop); + } + }); + } + } + } + }; + __publicField(_Export, "moduleName", "export"); + __publicField(_Export, "columnLookups", columnLookups$1); + __publicField(_Export, "rowLookups", rowLookups$1); + let Export = _Export; + var defaultFilters = { + //equal to + "=": function (filterVal, rowVal, rowData, filterParams) { + return rowVal == filterVal ? true : false; + }, + //less than + "<": function (filterVal, rowVal, rowData, filterParams) { + return rowVal < filterVal ? true : false; + }, + //less than or equal to + "<=": function (filterVal, rowVal, rowData, filterParams) { + return rowVal <= filterVal ? true : false; + }, + //greater than + ">": function (filterVal, rowVal, rowData, filterParams) { + return rowVal > filterVal ? true : false; + }, + //greater than or equal to + ">=": function (filterVal, rowVal, rowData, filterParams) { + return rowVal >= filterVal ? true : false; + }, + //not equal to + "!=": function (filterVal, rowVal, rowData, filterParams) { + return rowVal != filterVal ? true : false; + }, + "regex": function (filterVal, rowVal, rowData, filterParams) { + if (typeof filterVal == "string") { + filterVal = new RegExp(filterVal); + } + return filterVal.test(rowVal); + }, + //contains the string + "like": function (filterVal, rowVal, rowData, filterParams) { + if (filterVal === null || typeof filterVal === "undefined") { + return rowVal === filterVal ? true : false; + } else { + if (typeof rowVal !== "undefined" && rowVal !== null) { + return String(rowVal).toLowerCase().indexOf(filterVal.toLowerCase()) > -1; + } else { + return false; + } + } + }, + //contains the keywords + "keywords": function (filterVal, rowVal, rowData, filterParams) { + var keywords = filterVal.toLowerCase().split(typeof filterParams.separator === "undefined" ? " " : filterParams.separator), + value = String(rowVal === null || typeof rowVal === "undefined" ? "" : rowVal).toLowerCase(), + matches = []; + keywords.forEach((keyword) => { + if (value.includes(keyword)) { + matches.push(true); + } + }); + return filterParams.matchAll ? matches.length === keywords.length : !!matches.length; + }, + //starts with the string + "starts": function (filterVal, rowVal, rowData, filterParams) { + if (filterVal === null || typeof filterVal === "undefined") { + return rowVal === filterVal ? true : false; + } else { + if (typeof rowVal !== "undefined" && rowVal !== null) { + return String(rowVal).toLowerCase().startsWith(filterVal.toLowerCase()); + } else { + return false; + } + } + }, + //ends with the string + "ends": function (filterVal, rowVal, rowData, filterParams) { + if (filterVal === null || typeof filterVal === "undefined") { + return rowVal === filterVal ? true : false; + } else { + if (typeof rowVal !== "undefined" && rowVal !== null) { + return String(rowVal).toLowerCase().endsWith(filterVal.toLowerCase()); + } else { + return false; + } + } + }, + //in array + "in": function (filterVal, rowVal, rowData, filterParams) { + if (Array.isArray(filterVal)) { + return filterVal.length ? filterVal.indexOf(rowVal) > -1 : true; + } else { + console.warn("Filter Error - filter value is not an array:", filterVal); + return false; + } + }, + // Smart filter + // Supports ., !, <, >, <=, >=, = and falls back to like filter + "smart": function (filterVal, rowVal, rowData, filterParams) { + const search = filterVal.trim(); + if (search === ".") return !(rowVal === null || rowVal == ""); + if (search === "!") return rowVal === null || rowVal == ""; + if (search.indexOf("<=") === 0) + return this["<="]( + parseFloat(search.substring(2)), + rowVal, + rowData, + filterParams + ); + if (search.indexOf(">=") === 0) + return this[">="]( + parseFloat(search.substring(2)), + rowVal, + rowData, + filterParams + ); + if (search.indexOf("<") === 0) + return this["<"]( + parseFloat(search.substring(1)), + rowVal, + rowData, + filterParams + ); + if (search.indexOf(">") === 0) + return this[">"]( + parseFloat(search.substring(1)), + rowVal, + rowData, + filterParams + ); + if (search.indexOf("=") === 0) + return this["="](search.substring(1).trim(), rowVal, rowData, filterParams); + if (search.includes(" ")) { + const terms = search.split(/\s+/).filter((term) => term.length > 0); + if (terms.length > 1) { + const fuzzySearch = terms.join(" AND "); + return this["smarter"](fuzzySearch, rowVal, rowData, filterParams); + } + } + return this["like"](search, rowVal, rowData, filterParams); + }, + // Smarter filter + // Just like the smart filter but you can combine multiple filters (AND/OR) + // Examples: + // - "john AND smith" - both terms must match + // - "john OR jane" - either term must match + // - ">100 AND <500" - value must be between 100 and 500 + // - "! OR foo" - either empty or foo + "smarter": function (filterVal, rowVal, rowData, filterParams) { + const search = filterVal.trim(); + if (!search) return true; + const parts = search.split(/\s+(AND|OR)\s+/i); + if (parts.length === 1) { + return this["smart"](search, rowVal, rowData, filterParams); + } + let result = null; + let currentOperator = null; + for (let i = 0; i < parts.length; i++) { + const part = parts[i].trim(); + if (part === "AND" || part === "OR") { + currentOperator = part; + continue; + } + const partResult = this["smart"](part, rowVal, rowData, filterParams); + if (result === null) { + result = partResult; + } else if (currentOperator === "AND") { + result = result && partResult; + } else if (currentOperator === "OR") { + result = result || partResult; + } + } + return result !== null ? result : true; + } + }; + const _Filter = class _Filter extends Module { + constructor(table) { + super(table); + this.filterList = []; + this.headerFilters = {}; + this.headerFilterColumns = []; + this.prevHeaderFilterChangeCheck = ""; + this.prevHeaderFilterChangeCheck = "{}"; + this.changed = false; + this.tableInitialized = false; + this.registerTableOption("filterMode", "local"); + this.registerTableOption("initialFilter", false); + this.registerTableOption("initialHeaderFilter", false); + this.registerTableOption("headerFilterLiveFilterDelay", 300); + this.registerTableOption("placeholderHeaderFilter", false); + this.registerColumnOption("headerFilter"); + this.registerColumnOption("headerFilterPlaceholder"); + this.registerColumnOption("headerFilterParams"); + this.registerColumnOption("headerFilterEmptyCheck"); + this.registerColumnOption("headerFilterFunc"); + this.registerColumnOption("headerFilterFuncParams"); + this.registerColumnOption("headerFilterLiveFilter"); + this.registerTableFunction("searchRows", this.searchRows.bind(this)); + this.registerTableFunction("searchData", this.searchData.bind(this)); + this.registerTableFunction("setFilter", this.userSetFilter.bind(this)); + this.registerTableFunction("refreshFilter", this.userRefreshFilter.bind(this)); + this.registerTableFunction("addFilter", this.userAddFilter.bind(this)); + this.registerTableFunction("getFilters", this.getFilters.bind(this)); + this.registerTableFunction("setHeaderFilterFocus", this.userSetHeaderFilterFocus.bind(this)); + this.registerTableFunction("getHeaderFilterValue", this.userGetHeaderFilterValue.bind(this)); + this.registerTableFunction("setHeaderFilterValue", this.userSetHeaderFilterValue.bind(this)); + this.registerTableFunction("getHeaderFilters", this.getHeaderFilters.bind(this)); + this.registerTableFunction("removeFilter", this.userRemoveFilter.bind(this)); + this.registerTableFunction("clearFilter", this.userClearFilter.bind(this)); + this.registerTableFunction("clearHeaderFilter", this.userClearHeaderFilter.bind(this)); + this.registerComponentFunction("column", "headerFilterFocus", this.setHeaderFilterFocus.bind(this)); + this.registerComponentFunction("column", "reloadHeaderFilter", this.reloadHeaderFilter.bind(this)); + this.registerComponentFunction("column", "getHeaderFilterValue", this.getHeaderFilterValue.bind(this)); + this.registerComponentFunction("column", "setHeaderFilterValue", this.setHeaderFilterValue.bind(this)); + } + + initialize() { + this.subscribe("column-init", this.initializeColumnHeaderFilter.bind(this)); + this.subscribe("column-width-fit-before", this.hideHeaderFilterElements.bind(this)); + this.subscribe("column-width-fit-after", this.showHeaderFilterElements.bind(this)); + this.subscribe("table-built", this.tableBuilt.bind(this)); + this.subscribe("placeholder", this.generatePlaceholder.bind(this)); + if (this.table.options.filterMode === "remote") { + this.subscribe("data-params", this.remoteFilterParams.bind(this)); + } + this.registerDataHandler(this.filter.bind(this), 10); + } + + tableBuilt() { + if (this.table.options.initialFilter) { + this.setFilter(this.table.options.initialFilter); + } + if (this.table.options.initialHeaderFilter) { + this.table.options.initialHeaderFilter.forEach((item) => { + var column = this.table.columnManager.findColumn(item.field); + if (column) { + this.setHeaderFilterValue(column, item.value); + } else { + console.warn("Column Filter Error - No matching column found:", item.field); + return false; + } + }); + } + this.tableInitialized = true; + } + + remoteFilterParams(data, config, silent, params) { + params.filter = this.getFilters(true, true); + return params; + } + + generatePlaceholder(text) { + if (this.table.options.placeholderHeaderFilter && Object.keys(this.headerFilters).length) { + return this.table.options.placeholderHeaderFilter; + } + } + + /////////////////////////////////// + ///////// Table Functions ///////// + /////////////////////////////////// + //set standard filters + userSetFilter(field, type, value, params) { + this.setFilter(field, type, value, params); + this.refreshFilter(); + } + + //set standard filters + userRefreshFilter() { + this.refreshFilter(); + } + + //add filter to array + userAddFilter(field, type, value, params) { + this.addFilter(field, type, value, params); + this.refreshFilter(); + } + + userSetHeaderFilterFocus(field) { + var column = this.table.columnManager.findColumn(field); + if (column) { + this.setHeaderFilterFocus(column); + } else { + console.warn("Column Filter Focus Error - No matching column found:", field); + return false; + } + } + + userGetHeaderFilterValue(field) { + var column = this.table.columnManager.findColumn(field); + if (column) { + return this.getHeaderFilterValue(column); + } else { + console.warn("Column Filter Error - No matching column found:", field); + } + } + + userSetHeaderFilterValue(field, value) { + var column = this.table.columnManager.findColumn(field); + if (column) { + this.setHeaderFilterValue(column, value); + } else { + console.warn("Column Filter Error - No matching column found:", field); + return false; + } + } + + //remove filter from array + userRemoveFilter(field, type, value) { + this.removeFilter(field, type, value); + this.refreshFilter(); + } + + //clear filters + userClearFilter(all) { + this.clearFilter(all); + this.refreshFilter(); + } + + //clear header filters + userClearHeaderFilter() { + this.clearHeaderFilter(); + this.refreshFilter(); + } + + //search for specific row components + searchRows(field, type, value) { + return this.search("rows", field, type, value); + } + + //search for specific data + searchData(field, type, value) { + return this.search("data", field, type, value); + } + + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + initializeColumnHeaderFilter(column) { + var def = column.definition; + if (def.headerFilter) { + this.initializeColumn(column); + } + } + + //initialize column header filter + initializeColumn(column, value) { + var self = this, field = column.getField(); + + function success(value2) { + var filterType = column.modules.filter.tagType == "input" && column.modules.filter.attrType == "text" || column.modules.filter.tagType == "textarea" ? "partial" : "match", + type = "", filterChangeCheck = "", filterFunc; + if (typeof column.modules.filter.prevSuccess === "undefined" || column.modules.filter.prevSuccess !== value2) { + column.modules.filter.prevSuccess = value2; + if (!column.modules.filter.emptyFunc(value2)) { + column.modules.filter.value = value2; + switch (typeof column.definition.headerFilterFunc) { + case "string": + if (_Filter.filters[column.definition.headerFilterFunc]) { + type = column.definition.headerFilterFunc; + filterFunc = function (data) { + var params = column.definition.headerFilterFuncParams || {}; + var fieldVal = column.getFieldValue(data); + params = typeof params === "function" ? params(value2, fieldVal, data) : params; + return _Filter.filters[column.definition.headerFilterFunc](value2, fieldVal, data, params); + }; + } else { + console.warn("Header Filter Error - Matching filter function not found: ", column.definition.headerFilterFunc); + } + break; + case "function": + filterFunc = function (data) { + var params = column.definition.headerFilterFuncParams || {}; + var fieldVal = column.getFieldValue(data); + params = typeof params === "function" ? params(value2, fieldVal, data) : params; + return column.definition.headerFilterFunc(value2, fieldVal, data, params); + }; + type = filterFunc; + break; + } + if (!filterFunc) { + switch (filterType) { + case "partial": + filterFunc = function (data) { + var colVal = column.getFieldValue(data); + if (typeof colVal !== "undefined" && colVal !== null) { + return String(colVal).toLowerCase().indexOf(String(value2).toLowerCase()) > -1; + } else { + return false; + } + }; + type = "like"; + break; + default: + filterFunc = function (data) { + return column.getFieldValue(data) == value2; + }; + type = "="; + } + } + self.headerFilters[field] = {value: value2, func: filterFunc, type}; + } else { + delete self.headerFilters[field]; + } + column.modules.filter.value = value2; + filterChangeCheck = JSON.stringify(self.headerFilters); + if (self.prevHeaderFilterChangeCheck !== filterChangeCheck) { + self.prevHeaderFilterChangeCheck = filterChangeCheck; + self.trackChanges(); + self.refreshFilter(); + } + } + return true; + } + + column.modules.filter = { + success, + attrType: false, + tagType: false, + emptyFunc: false + }; + this.generateHeaderFilterElement(column); + } + + generateHeaderFilterElement(column, initialValue, reinitialize) { + var self = this, success = column.modules.filter.success, field = column.getField(), filterElement, + editor, editorElement, cellWrapper, typingTimer, searchTrigger, params, onRenderedCallback; + column.modules.filter.value = initialValue; + + function cancel() { + } + + function onRendered(callback) { + onRenderedCallback = callback; + } + + if (column.modules.filter.headerElement && column.modules.filter.headerElement.parentNode) { + column.contentElement.removeChild(column.modules.filter.headerElement.parentNode); + } + if (field) { + column.modules.filter.emptyFunc = column.definition.headerFilterEmptyCheck || function (value) { + return !value && value !== 0; + }; + filterElement = document.createElement("div"); + filterElement.classList.add("tabulator-header-filter"); + switch (typeof column.definition.headerFilter) { + case "string": + if (self.table.modules.edit.editors[column.definition.headerFilter]) { + editor = self.table.modules.edit.editors[column.definition.headerFilter]; + if ((column.definition.headerFilter === "tick" || column.definition.headerFilter === "tickCross") && !column.definition.headerFilterEmptyCheck) { + column.modules.filter.emptyFunc = function (value) { + return value !== true && value !== false; + }; + } + } else { + console.warn("Filter Error - Cannot build header filter, No such editor found: ", column.definition.editor); + } + break; + case "function": + editor = column.definition.headerFilter; + break; + case "boolean": + if (column.modules.edit && column.modules.edit.editor) { + editor = column.modules.edit.editor; + } else { + if (column.definition.formatter && self.table.modules.edit.editors[column.definition.formatter]) { + editor = self.table.modules.edit.editors[column.definition.formatter]; + if ((column.definition.formatter === "tick" || column.definition.formatter === "tickCross") && !column.definition.headerFilterEmptyCheck) { + column.modules.filter.emptyFunc = function (value) { + return value !== true && value !== false; + }; + } + } else { + editor = self.table.modules.edit.editors["input"]; + } + } + break; + } + if (editor) { + cellWrapper = { + getValue: function () { + return typeof initialValue !== "undefined" ? initialValue : ""; + }, + getField: function () { + return column.definition.field; + }, + getElement: function () { + return filterElement; + }, + getColumn: function () { + return column.getComponent(); + }, + getTable: () => { + return this.table; + }, + getType: () => { + return "header"; + }, + getRow: function () { + return { + normalizeHeight: function () { + } + }; + } + }; + params = column.definition.headerFilterParams || {}; + params = typeof params === "function" ? params.call(self.table, cellWrapper) : params; + editorElement = editor.call(this.table.modules.edit, cellWrapper, onRendered, success, cancel, params); + if (!editorElement) { + console.warn("Filter Error - Cannot add filter to " + field + " column, editor returned a value of false"); + return; + } + if (!(editorElement instanceof Node)) { + console.warn("Filter Error - Cannot add filter to " + field + " column, editor should return an instance of Node, the editor returned:", editorElement); + return; + } + self.langBind("headerFilters|columns|" + column.definition.field, function (value) { + editorElement.setAttribute("placeholder", typeof value !== "undefined" && value ? value : column.definition.headerFilterPlaceholder || self.langText("headerFilters|default")); + }); + editorElement.addEventListener("click", function (e) { + e.stopPropagation(); + editorElement.focus(); + }); + editorElement.addEventListener("focus", (e) => { + var left = this.table.columnManager.contentsElement.scrollLeft; + var headerPos = this.table.rowManager.element.scrollLeft; + if (left !== headerPos) { + this.table.rowManager.scrollHorizontal(left); + this.table.columnManager.scrollHorizontal(left); + } + }); + typingTimer = false; + searchTrigger = function (e) { + if (typingTimer) { + clearTimeout(typingTimer); + } + typingTimer = setTimeout(function () { + success(editorElement.value); + }, self.table.options.headerFilterLiveFilterDelay); + }; + column.modules.filter.headerElement = editorElement; + column.modules.filter.attrType = editorElement.hasAttribute("type") ? editorElement.getAttribute("type").toLowerCase() : ""; + column.modules.filter.tagType = editorElement.tagName.toLowerCase(); + if (column.definition.headerFilterLiveFilter !== false) { + if (!(column.definition.headerFilter === "autocomplete" || column.definition.headerFilter === "tickCross" || (column.definition.editor === "autocomplete" || column.definition.editor === "tickCross") && column.definition.headerFilter === true)) { + editorElement.addEventListener("keyup", searchTrigger); + editorElement.addEventListener("search", searchTrigger); + if (column.modules.filter.attrType == "number") { + editorElement.addEventListener("change", function (e) { + success(editorElement.value); + }); + } + if (column.modules.filter.attrType == "text" && this.table.browser !== "ie") { + editorElement.setAttribute("type", "search"); + } + } + if (column.modules.filter.tagType == "input" || column.modules.filter.tagType == "select" || column.modules.filter.tagType == "textarea") { + editorElement.addEventListener("mousedown", function (e) { + e.stopPropagation(); + }); + } + } + filterElement.appendChild(editorElement); + column.contentElement.appendChild(filterElement); + if (!reinitialize) { + self.headerFilterColumns.push(column); + } + if (onRenderedCallback) { + onRenderedCallback(); + } + } + } else { + console.warn("Filter Error - Cannot add header filter, column has no field set:", column.definition.title); + } + } + + //hide all header filter elements (used to ensure correct column widths in "fitData" layout mode) + hideHeaderFilterElements() { + this.headerFilterColumns.forEach(function (column) { + if (column.modules.filter && column.modules.filter.headerElement) { + column.modules.filter.headerElement.style.display = "none"; + } + }); + } + + //show all header filter elements (used to ensure correct column widths in "fitData" layout mode) + showHeaderFilterElements() { + this.headerFilterColumns.forEach(function (column) { + if (column.modules.filter && column.modules.filter.headerElement) { + column.modules.filter.headerElement.style.display = ""; + } + }); + } + + //programmatically set focus of header filter + setHeaderFilterFocus(column) { + if (column.modules.filter && column.modules.filter.headerElement) { + column.modules.filter.headerElement.focus(); + } else { + console.warn("Column Filter Focus Error - No header filter set on column:", column.getField()); + } + } + + //programmatically get value of header filter + getHeaderFilterValue(column) { + if (column.modules.filter && column.modules.filter.headerElement) { + return column.modules.filter.value; + } else { + console.warn("Column Filter Error - No header filter set on column:", column.getField()); + } + } + + //programmatically set value of header filter + setHeaderFilterValue(column, value) { + if (column) { + if (column.modules.filter && column.modules.filter.headerElement) { + this.generateHeaderFilterElement(column, value, true); + column.modules.filter.success(value); + } else { + console.warn("Column Filter Error - No header filter set on column:", column.getField()); + } + } + } + + reloadHeaderFilter(column) { + if (column) { + if (column.modules.filter && column.modules.filter.headerElement) { + this.generateHeaderFilterElement(column, column.modules.filter.value, true); + } else { + console.warn("Column Filter Error - No header filter set on column:", column.getField()); + } + } + } + + refreshFilter() { + if (this.tableInitialized) { + if (this.table.options.filterMode === "remote") { + this.reloadData(null, false, false); + } else { + this.refreshData(true); + } + } + } + + //check if the filters has changed since last use + trackChanges() { + this.changed = true; + this.dispatch("filter-changed"); + } + + //check if the filters has changed since last use + hasChanged() { + var changed = this.changed; + this.changed = false; + return changed; + } + + //set standard filters + setFilter(field, type, value, params) { + this.filterList = []; + if (!Array.isArray(field)) { + field = [{field, type, value, params}]; + } + this.addFilter(field); + } + + //add filter to array + addFilter(field, type, value, params) { + var changed = false; + if (!Array.isArray(field)) { + field = [{field, type, value, params}]; + } + field.forEach((filter) => { + filter = this.findFilter(filter); + if (filter) { + this.filterList.push(filter); + changed = true; + } + }); + if (changed) { + this.trackChanges(); + } + } + + findFilter(filter) { + var column; + if (Array.isArray(filter)) { + return this.findSubFilters(filter); + } + var filterFunc = false; + if (typeof filter.field == "function") { + filterFunc = function (data) { + return filter.field(data, filter.type || {}); + }; + } else { + if (_Filter.filters[filter.type]) { + column = this.table.columnManager.getColumnByField(filter.field); + if (column) { + filterFunc = function (data) { + return _Filter.filters[filter.type](filter.value, column.getFieldValue(data), data, filter.params || {}); + }; + } else { + filterFunc = function (data) { + return _Filter.filters[filter.type](filter.value, data[filter.field], data, filter.params || {}); + }; + } + } else { + console.warn("Filter Error - No such filter type found, ignoring: ", filter.type); + } + } + filter.func = filterFunc; + return filter.func ? filter : false; + } + + findSubFilters(filters) { + var output = []; + filters.forEach((filter) => { + filter = this.findFilter(filter); + if (filter) { + output.push(filter); + } + }); + return output.length ? output : false; + } + + //get all filters + getFilters(all, ajax) { + var output = []; + if (all) { + output = this.getHeaderFilters(); + } + if (ajax) { + output.forEach(function (item) { + if (typeof item.type == "function") { + item.type = "function"; + } + }); + } + output = output.concat(this.filtersToArray(this.filterList, ajax)); + return output; + } + + //filter to Object + filtersToArray(filterList, ajax) { + var output = []; + filterList.forEach((filter) => { + var item; + if (Array.isArray(filter)) { + output.push(this.filtersToArray(filter, ajax)); + } else { + item = {field: filter.field, type: filter.type, value: filter.value}; + if (ajax) { + if (typeof item.type == "function") { + item.type = "function"; + } + } + output.push(item); + } + }); + return output; + } + + //get all filters + getHeaderFilters() { + var output = []; + for (var key in this.headerFilters) { + output.push({field: key, type: this.headerFilters[key].type, value: this.headerFilters[key].value}); + } + return output; + } + + //remove filter from array + removeFilter(field, type, value) { + if (!Array.isArray(field)) { + field = [{field, type, value}]; + } + field.forEach((filter) => { + var index = -1; + if (typeof filter.field == "object") { + index = this.filterList.findIndex((element) => { + return filter === element; + }); + } else { + index = this.filterList.findIndex((element) => { + return filter.field === element.field && filter.type === element.type && filter.value === element.value; + }); + } + if (index > -1) { + this.filterList.splice(index, 1); + } else { + console.warn("Filter Error - No matching filter type found, ignoring: ", filter.type); + } + }); + this.trackChanges(); + } + + //clear filters + clearFilter(all) { + this.filterList = []; + if (all) { + this.clearHeaderFilter(); + } + this.trackChanges(); + } + + //clear header filters + clearHeaderFilter() { + this.headerFilters = {}; + this.prevHeaderFilterChangeCheck = "{}"; + this.headerFilterColumns.forEach((column) => { + if (typeof column.modules.filter.value !== "undefined") { + delete column.modules.filter.value; + } + column.modules.filter.prevSuccess = void 0; + this.reloadHeaderFilter(column); + }); + this.trackChanges(); + } + + //search data and return matching rows + search(searchType, field, type, value) { + var activeRows = [], filterList = []; + if (!Array.isArray(field)) { + field = [{field, type, value}]; + } + field.forEach((filter) => { + filter = this.findFilter(filter); + if (filter) { + filterList.push(filter); + } + }); + this.table.rowManager.rows.forEach((row) => { + var match = true; + filterList.forEach((filter) => { + if (!this.filterRecurse(filter, row.getData())) { + match = false; + } + }); + if (match) { + activeRows.push(searchType === "data" ? row.getData("data") : row.getComponent()); + } + }); + return activeRows; + } + + //filter row array + filter(rowList, filters) { + var activeRows = [], activeRowComponents = []; + if (this.subscribedExternal("dataFiltering")) { + this.dispatchExternal("dataFiltering", this.getFilters(true)); + } + if (this.table.options.filterMode !== "remote" && (this.filterList.length || Object.keys(this.headerFilters).length)) { + rowList.forEach((row) => { + if (this.filterRow(row)) { + activeRows.push(row); + } + }); + } else { + activeRows = rowList.slice(0); + } + if (this.subscribedExternal("dataFiltered")) { + activeRows.forEach((row) => { + activeRowComponents.push(row.getComponent()); + }); + this.dispatchExternal("dataFiltered", this.getFilters(true), activeRowComponents); + } + return activeRows; + } + + //filter individual row + filterRow(row, filters) { + var match = true, data = row.getData(); + this.filterList.forEach((filter) => { + if (!this.filterRecurse(filter, data)) { + match = false; + } + }); + for (var field in this.headerFilters) { + if (!this.headerFilters[field].func(data)) { + match = false; + } + } + return match; + } + + filterRecurse(filter, data) { + var match = false; + if (Array.isArray(filter)) { + filter.forEach((subFilter) => { + if (this.filterRecurse(subFilter, data)) { + match = true; + } + }); + } else { + match = filter.func(data); + } + return match; + } + }; + __publicField(_Filter, "moduleName", "filter"); + //load defaults + __publicField(_Filter, "filters", defaultFilters); + let Filter = _Filter; + + function plaintext(cell, formatterParams, onRendered) { + return this.emptyToSpace(this.sanitizeHTML(cell.getValue())); + } + + function html(cell, formatterParams, onRendered) { + return cell.getValue(); + } + + function textarea(cell, formatterParams, onRendered) { + cell.getElement().style.whiteSpace = "pre-wrap"; + return this.emptyToSpace(this.sanitizeHTML(cell.getValue())); + } + + function money(cell, formatterParams, onRendered) { + var floatVal = parseFloat(cell.getValue()), sign = "", number2, integer, decimal, rgx, value; + var decimalSym = formatterParams.decimal || "."; + var thousandSym = formatterParams.thousand || ","; + var negativeSign = formatterParams.negativeSign || "-"; + var symbol = formatterParams.symbol || ""; + var after = !!formatterParams.symbolAfter; + var precision = typeof formatterParams.precision !== "undefined" ? formatterParams.precision : 2; + if (Number.isNaN(floatVal)) { + return this.emptyToSpace(this.sanitizeHTML(cell.getValue())); + } + if (floatVal < 0) { + floatVal = Math.abs(floatVal); + sign = negativeSign; + } + number2 = precision !== false ? floatVal.toFixed(precision) : floatVal; + number2 = String(number2).split("."); + integer = number2[0]; + decimal = number2.length > 1 ? decimalSym + number2[1] : ""; + if (formatterParams.thousand !== false) { + rgx = /(\d+)(\d{3})/; + while (rgx.test(integer)) { + integer = integer.replace(rgx, "$1" + thousandSym + "$2"); + } + } + value = integer + decimal; + if (sign === true) { + value = "(" + value + ")"; + return after ? value + symbol : symbol + value; + } else { + return after ? sign + value + symbol : sign + symbol + value; + } + } + + function link(cell, formatterParams, onRendered) { + var value = cell.getValue(), urlPrefix = formatterParams.urlPrefix || "", + download = formatterParams.download, label = value, el = document.createElement("a"), data; + + function labelTraverse(path, data2) { + var item = path.shift(), value2 = data2[item]; + if (path.length && typeof value2 === "object") { + return labelTraverse(path, value2); + } + return value2; + } + + if (formatterParams.labelField) { + data = cell.getData(); + label = labelTraverse(formatterParams.labelField.split(this.table.options.nestedFieldSeparator), data); + } + if (formatterParams.label) { + switch (typeof formatterParams.label) { + case "string": + label = formatterParams.label; + break; + case "function": + label = formatterParams.label(cell); + break; + } + } + if (label) { + if (formatterParams.urlField) { + data = cell.getData(); + value = Helpers.retrieveNestedData(this.table.options.nestedFieldSeparator, formatterParams.urlField, data); + } + if (formatterParams.url) { + switch (typeof formatterParams.url) { + case "string": + value = formatterParams.url; + break; + case "function": + value = formatterParams.url(cell); + break; + } + } + el.setAttribute("href", urlPrefix + value); + if (formatterParams.target) { + el.setAttribute("target", formatterParams.target); + } + if (formatterParams.download) { + if (typeof download == "function") { + download = download(cell); + } else { + download = download === true ? "" : download; + } + el.setAttribute("download", download); + } + el.innerHTML = this.emptyToSpace(this.sanitizeHTML(label)); + return el; + } else { + return " "; + } + } + + function image(cell, formatterParams, onRendered) { + var el = document.createElement("img"), src = cell.getValue(); + if (formatterParams.urlPrefix) { + src = formatterParams.urlPrefix + cell.getValue(); + } + if (formatterParams.urlSuffix) { + src = src + formatterParams.urlSuffix; + } + el.setAttribute("src", src); + switch (typeof formatterParams.height) { + case "number": + el.style.height = formatterParams.height + "px"; + break; + case "string": + el.style.height = formatterParams.height; + break; + } + switch (typeof formatterParams.width) { + case "number": + el.style.width = formatterParams.width + "px"; + break; + case "string": + el.style.width = formatterParams.width; + break; + } + el.addEventListener("load", function () { + cell.getRow().normalizeHeight(); + }); + return el; + } + + function tickCross(cell, formatterParams, onRendered) { + var value = cell.getValue(), element = cell.getElement(), empty = formatterParams.allowEmpty, + truthy = formatterParams.allowTruthy, trueValueSet = Object.keys(formatterParams).includes("trueValue"), + tick = typeof formatterParams.tickElement !== "undefined" ? formatterParams.tickElement : '', + cross = typeof formatterParams.crossElement !== "undefined" ? formatterParams.crossElement : ''; + if (trueValueSet && value === formatterParams.trueValue || !trueValueSet && (truthy && value || (value === true || value === "true" || value === "True" || value === 1 || value === "1"))) { + element.setAttribute("aria-checked", true); + return tick || ""; + } else { + if (empty && (value === "null" || value === "" || value === null || typeof value === "undefined")) { + element.setAttribute("aria-checked", "mixed"); + return ""; + } else { + element.setAttribute("aria-checked", false); + return cross || ""; + } + } + } + + function datetime$1(cell, formatterParams, onRendered) { + var DT = this.table.dependencyRegistry.lookup(["luxon", "DateTime"], "DateTime"); + var inputFormat = formatterParams.inputFormat || "yyyy-MM-dd HH:mm:ss"; + var outputFormat = formatterParams.outputFormat || "dd/MM/yyyy HH:mm:ss"; + var invalid = typeof formatterParams.invalidPlaceholder !== "undefined" ? formatterParams.invalidPlaceholder : ""; + var value = cell.getValue(); + if (typeof DT != "undefined") { + var newDatetime; + if (DT.isDateTime(value)) { + newDatetime = value; + } else if (inputFormat === "x") { + newDatetime = DT.fromMillis(value); + } else if (inputFormat === "iso") { + newDatetime = DT.fromISO(String(value)); + } else { + newDatetime = DT.fromFormat(String(value), inputFormat); + } + if (newDatetime.isValid) { + if (formatterParams.timezone) { + newDatetime = newDatetime.setZone(formatterParams.timezone); + } + return newDatetime.toFormat(outputFormat); + } else { + if (invalid === true || !value) { + return value; + } else if (typeof invalid === "function") { + return invalid(value); + } else { + return invalid; + } + } + } else { + console.error("Format Error - 'datetime' formatter is dependant on luxon.js"); + } + } + + function datetimediff(cell, formatterParams, onRendered) { + var DT = this.table.dependencyRegistry.lookup(["luxon", "DateTime"], "DateTime"); + var inputFormat = formatterParams.inputFormat || "yyyy-MM-dd HH:mm:ss"; + var invalid = typeof formatterParams.invalidPlaceholder !== "undefined" ? formatterParams.invalidPlaceholder : ""; + var suffix = typeof formatterParams.suffix !== "undefined" ? formatterParams.suffix : false; + var unit = typeof formatterParams.unit !== "undefined" ? formatterParams.unit : "days"; + var humanize = typeof formatterParams.humanize !== "undefined" ? formatterParams.humanize : false; + var date2 = typeof formatterParams.date !== "undefined" ? formatterParams.date : DT.now(); + var value = cell.getValue(); + if (typeof DT != "undefined") { + var newDatetime; + if (DT.isDateTime(value)) { + newDatetime = value; + } else if (inputFormat === "x") { + newDatetime = DT.fromMillis(value); + } else if (inputFormat === "iso") { + newDatetime = DT.fromISO(String(value)); + } else { + newDatetime = DT.fromFormat(String(value), inputFormat); + } + if (newDatetime.isValid) { + if (humanize) { + return newDatetime.diff(date2, unit).toHuman() + (suffix ? " " + suffix : ""); + } else { + return parseInt(newDatetime.diff(date2, unit)[unit]) + (suffix ? " " + suffix : ""); + } + } else { + if (invalid === true) { + return value; + } else if (typeof invalid === "function") { + return invalid(value); + } else { + return invalid; + } + } + } else { + console.error("Format Error - 'datetimediff' formatter is dependant on luxon.js"); + } + } + + function lookup(cell, formatterParams, onRendered) { + var value = cell.getValue(); + if (typeof formatterParams[value] === "undefined") { + console.warn("Missing display value for " + value); + return value; + } + return formatterParams[value]; + } + + function star(cell, formatterParams, onRendered) { + var value = cell.getValue(), element = cell.getElement(), + maxStars = formatterParams && formatterParams.stars ? formatterParams.stars : 5, + stars = document.createElement("span"), + star2 = document.createElementNS("http://www.w3.org/2000/svg", "svg"), + starActive = '', + starInactive = ''; + stars.style.verticalAlign = "middle"; + star2.setAttribute("width", "14"); + star2.setAttribute("height", "14"); + star2.setAttribute("viewBox", "0 0 512 512"); + star2.setAttribute("xml:space", "preserve"); + star2.style.padding = "0 1px"; + value = value && !Number.isNaN(value) ? parseInt(value) : 0; + value = Math.max(0, Math.min(value, maxStars)); + for (var i = 1; i <= maxStars; i++) { + var nextStar = star2.cloneNode(true); + nextStar.innerHTML = i <= value ? starActive : starInactive; + stars.appendChild(nextStar); + } + element.style.whiteSpace = "nowrap"; + element.style.overflow = "hidden"; + element.style.textOverflow = "ellipsis"; + element.setAttribute("aria-label", value); + return stars; + } + + function traffic(cell, formatterParams, onRendered) { + var value = this.sanitizeHTML(cell.getValue()) || 0, el = document.createElement("span"), + max = formatterParams && formatterParams.max ? formatterParams.max : 100, + min = formatterParams && formatterParams.min ? formatterParams.min : 0, + colors = formatterParams && typeof formatterParams.color !== "undefined" ? formatterParams.color : ["red", "orange", "green"], + color2 = "#666666", percent, percentValue; + if (Number.isNaN(value) || typeof cell.getValue() === "undefined") { + return; + } + el.classList.add("tabulator-traffic-light"); + percentValue = parseFloat(value) <= max ? parseFloat(value) : max; + percentValue = parseFloat(percentValue) >= min ? parseFloat(percentValue) : min; + percent = (max - min) / 100; + percentValue = Math.round((percentValue - min) / percent); + switch (typeof colors) { + case "string": + color2 = colors; + break; + case "function": + color2 = colors(value); + break; + case "object": + if (Array.isArray(colors)) { + var unit = 100 / colors.length; + var index = Math.floor(percentValue / unit); + index = Math.min(index, colors.length - 1); + index = Math.max(index, 0); + color2 = colors[index]; + break; + } + } + el.style.backgroundColor = color2; + return el; + } + + function progress(cell, formatterParams = {}, onRendered) { + var value = this.sanitizeHTML(cell.getValue()) || 0, element = cell.getElement(), + max = formatterParams.max ? formatterParams.max : 100, + min = formatterParams.min ? formatterParams.min : 0, + legendAlign = formatterParams.legendAlign ? formatterParams.legendAlign : "center", percent, + percentValue, color2, legend, legendColor; + percentValue = parseFloat(value) <= max ? parseFloat(value) : max; + percentValue = parseFloat(percentValue) >= min ? parseFloat(percentValue) : min; + percent = (max - min) / 100; + percentValue = Math.round((percentValue - min) / percent); + switch (typeof formatterParams.color) { + case "string": + color2 = formatterParams.color; + break; + case "function": + color2 = formatterParams.color(value); + break; + case "object": + if (Array.isArray(formatterParams.color)) { + let unit = 100 / formatterParams.color.length; + let index = Math.floor(percentValue / unit); + index = Math.min(index, formatterParams.color.length - 1); + index = Math.max(index, 0); + color2 = formatterParams.color[index]; + break; + } + default: + color2 = "#2DC214"; + } + switch (typeof formatterParams.legend) { + case "string": + legend = formatterParams.legend; + break; + case "function": + legend = formatterParams.legend(value); + break; + case "boolean": + legend = value; + break; + default: + legend = false; + } + switch (typeof formatterParams.legendColor) { + case "string": + legendColor = formatterParams.legendColor; + break; + case "function": + legendColor = formatterParams.legendColor(value); + break; + case "object": + if (Array.isArray(formatterParams.legendColor)) { + let unit = 100 / formatterParams.legendColor.length; + let index = Math.floor(percentValue / unit); + index = Math.min(index, formatterParams.legendColor.length - 1); + index = Math.max(index, 0); + legendColor = formatterParams.legendColor[index]; + } + break; + default: + legendColor = "#000"; + } + element.style.minWidth = "30px"; + element.style.position = "relative"; + element.setAttribute("aria-label", percentValue); + var barEl = document.createElement("div"); + barEl.style.display = "inline-block"; + barEl.style.width = percentValue + "%"; + barEl.style.backgroundColor = color2; + barEl.style.height = "100%"; + barEl.setAttribute("data-max", max); + barEl.setAttribute("data-min", min); + var barContainer = document.createElement("div"); + barContainer.style.position = "relative"; + barContainer.style.width = "100%"; + barContainer.style.height = "100%"; + if (legend) { + var legendEl = document.createElement("div"); + legendEl.style.position = "absolute"; + legendEl.style.top = 0; + legendEl.style.left = 0; + legendEl.style.textAlign = legendAlign; + legendEl.style.width = "100%"; + legendEl.style.color = legendColor; + legendEl.innerHTML = legend; + } + onRendered(function () { + if (!(cell instanceof CellComponent)) { + var holderEl = document.createElement("div"); + holderEl.style.position = "absolute"; + holderEl.style.top = "4px"; + holderEl.style.bottom = "4px"; + holderEl.style.left = "4px"; + holderEl.style.right = "4px"; + element.appendChild(holderEl); + element = holderEl; + } + element.appendChild(barContainer); + barContainer.appendChild(barEl); + if (legend) { + barContainer.appendChild(legendEl); + } + }); + return ""; + } + + function color(cell, formatterParams, onRendered) { + cell.getElement().style.backgroundColor = this.sanitizeHTML(cell.getValue()); + return ""; + } + + function buttonTick(cell, formatterParams, onRendered) { + return ''; + } + + function buttonCross(cell, formatterParams, onRendered) { + return ''; + } + + function toggle(cell, formatterParams, onRendered) { + var value = cell.getValue(), size = formatterParams.size || 15, sizePx = size + "px", containEl, switchEl, + onValue = formatterParams.hasOwnProperty("onValue") ? formatterParams.onValue : true, + offValue = formatterParams.hasOwnProperty("offValue") ? formatterParams.offValue : false, + state = formatterParams.onTruthy ? value : value === onValue; + containEl = document.createElement("div"); + containEl.classList.add("tabulator-toggle"); + if (state) { + containEl.classList.add("tabulator-toggle-on"); + containEl.style.flexDirection = "row-reverse"; + if (formatterParams.onColor) { + containEl.style.background = formatterParams.onColor; + } + } else { + if (formatterParams.offColor) { + containEl.style.background = formatterParams.offColor; + } + } + containEl.style.width = 2.5 * size + "px"; + containEl.style.borderRadius = sizePx; + if (formatterParams.clickable) { + containEl.addEventListener("click", (e) => { + cell.setValue(state ? offValue : onValue); + }); + } + switchEl = document.createElement("div"); + switchEl.classList.add("tabulator-toggle-switch"); + switchEl.style.height = sizePx; + switchEl.style.width = sizePx; + switchEl.style.borderRadius = sizePx; + containEl.appendChild(switchEl); + return containEl; + } + + function rownum(cell, formatterParams, onRendered) { + var content = document.createElement("span"); + var row = cell.getRow(); + var table = cell.getTable(); + row.watchPosition((position) => { + if (formatterParams.relativeToPage) { + position += table.modules.page.getPageSize() * (table.modules.page.getPage() - 1); + } + content.innerText = position; + }); + return content; + } + + function handle(cell, formatterParams, onRendered) { + cell.getElement().classList.add("tabulator-row-handle"); + return "
"; + } + + function adaptable(cell, params, onRendered) { + var lookup2, formatterFunc, formatterParams; + + function defaultLookup(cell2) { + var value = cell2.getValue(), formatter = "plaintext"; + switch (typeof value) { + case "boolean": + formatter = "tickCross"; + break; + case "string": + if (value.includes("\n")) { + formatter = "textarea"; + } + break; + } + return formatter; + } + + lookup2 = params.formatterLookup ? params.formatterLookup(cell) : defaultLookup(cell); + if (params.paramsLookup) { + formatterParams = typeof params.paramsLookup === "function" ? params.paramsLookup(lookup2, cell) : params.paramsLookup[lookup2]; + } + formatterFunc = this.table.modules.format.lookupFormatter(lookup2); + return formatterFunc.call(this, cell, formatterParams || {}, onRendered); + } + + function array$2(cell, formatterParams, onRendered) { + var delimiter = formatterParams.delimiter || ",", value = cell.getValue(), table = this.table, valueMap; + if (formatterParams.valueMap) { + if (typeof formatterParams.valueMap === "string") { + valueMap = function (value2) { + return value2.map((item) => { + return Helpers.retrieveNestedData(table.options.nestedFieldSeparator, formatterParams.valueMap, item); + }); + }; + } else { + valueMap = formatterParams.valueMap; + } + } + if (Array.isArray(value)) { + if (valueMap) { + value = valueMap(value); + } + return value.join(delimiter); + } else { + return value; + } + } + + function json$1(cell, formatterParams, onRendered) { + var indent = formatterParams.indent || " ", + multiline = typeof formatterParams.multiline === "undefined" ? true : formatterParams.multiline, + replacer = formatterParams.replacer || null, value = cell.getValue(); + if (multiline) { + cell.getElement().style.whiteSpace = "pre-wrap"; + } + return JSON.stringify(value, replacer, indent); + } + + var defaultFormatters = { + plaintext, + html, + textarea, + money, + link, + image, + tickCross, + datetime: datetime$1, + datetimediff, + lookup, + star, + traffic, + progress, + color, + buttonTick, + buttonCross, + toggle, + rownum, + handle, + adaptable, + array: array$2, + json: json$1 + }; + const _Format = class _Format extends Module { + constructor(table) { + super(table); + this.registerColumnOption("formatter"); + this.registerColumnOption("formatterParams"); + this.registerColumnOption("formatterPrint"); + this.registerColumnOption("formatterPrintParams"); + this.registerColumnOption("formatterClipboard"); + this.registerColumnOption("formatterClipboardParams"); + this.registerColumnOption("formatterHtmlOutput"); + this.registerColumnOption("formatterHtmlOutputParams"); + this.registerColumnOption("titleFormatter"); + this.registerColumnOption("titleFormatterParams"); + } + + initialize() { + this.subscribe("cell-format", this.formatValue.bind(this)); + this.subscribe("cell-rendered", this.cellRendered.bind(this)); + this.subscribe("column-layout", this.initializeColumn.bind(this)); + this.subscribe("column-format", this.formatHeader.bind(this)); + } + + //initialize column formatter + initializeColumn(column) { + column.modules.format = this.lookupTypeFormatter(column, ""); + if (typeof column.definition.formatterPrint !== "undefined") { + column.modules.format.print = this.lookupTypeFormatter(column, "Print"); + } + if (typeof column.definition.formatterClipboard !== "undefined") { + column.modules.format.clipboard = this.lookupTypeFormatter(column, "Clipboard"); + } + if (typeof column.definition.formatterHtmlOutput !== "undefined") { + column.modules.format.htmlOutput = this.lookupTypeFormatter(column, "HtmlOutput"); + } + } + + lookupTypeFormatter(column, type) { + var config = {params: column.definition["formatter" + type + "Params"] || {}}, + formatter = column.definition["formatter" + type]; + config.formatter = this.lookupFormatter(formatter); + return config; + } + + lookupFormatter(formatter) { + var formatterFunc; + switch (typeof formatter) { + case "string": + if (_Format.formatters[formatter]) { + formatterFunc = _Format.formatters[formatter]; + } else { + console.warn("Formatter Error - No such formatter found: ", formatter); + formatterFunc = _Format.formatters.plaintext; + } + break; + case "function": + formatterFunc = formatter; + break; + default: + formatterFunc = _Format.formatters.plaintext; + break; + } + return formatterFunc; + } + + cellRendered(cell) { + if (cell.modules.format && cell.modules.format.renderedCallback && !cell.modules.format.rendered) { + cell.modules.format.renderedCallback(); + cell.modules.format.rendered = true; + } + } + + //return a formatted value for a column header + formatHeader(column, title, el) { + var formatter, params, onRendered, mockCell; + if (column.definition.titleFormatter) { + formatter = this.lookupFormatter(column.definition.titleFormatter); + onRendered = (callback) => { + column.titleFormatterRendered = callback; + }; + mockCell = { + getValue: function () { + return title; + }, + getElement: function () { + return el; + }, + getType: function () { + return "header"; + }, + getColumn: function () { + return column.getComponent(); + }, + getTable: () => { + return this.table; + } + }; + params = column.definition.titleFormatterParams || {}; + params = typeof params === "function" ? params() : params; + return formatter.call(this, mockCell, params, onRendered); + } else { + return title; + } + } + + //return a formatted value for a cell + formatValue(cell) { + var component = cell.getComponent(), + params = typeof cell.column.modules.format.params === "function" ? cell.column.modules.format.params(component) : cell.column.modules.format.params; + + function onRendered(callback) { + if (!cell.modules.format) { + cell.modules.format = {}; + } + cell.modules.format.renderedCallback = callback; + cell.modules.format.rendered = false; + } + + return cell.column.modules.format.formatter.call(this, component, params, onRendered); + } + + formatExportValue(cell, type) { + var formatter = cell.column.modules.format[type], params; + if (formatter) { + let onRendered = function (callback) { + if (!cell.modules.format) { + cell.modules.format = {}; + } + cell.modules.format.renderedCallback = callback; + cell.modules.format.rendered = false; + }; + params = typeof formatter.params === "function" ? formatter.params(cell.getComponent()) : formatter.params; + return formatter.formatter.call(this, cell.getComponent(), params, onRendered); + } else { + return this.formatValue(cell); + } + } + + sanitizeHTML(value) { + if (value) { + var entityMap = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "/": "/", + "`": "`", + "=": "=" + }; + return String(value).replace(/[&<>"'`=/]/g, function (s) { + return entityMap[s]; + }); + } else { + return value; + } + } + + emptyToSpace(value) { + return value === null || typeof value === "undefined" || value === "" ? " " : value; + } + }; + __publicField(_Format, "moduleName", "format"); + //load defaults + __publicField(_Format, "formatters", defaultFormatters); + let Format = _Format; + + class FrozenColumns extends Module { + constructor(table) { + super(table); + this.leftColumns = []; + this.rightColumns = []; + this.initializationMode = "left"; + this.active = false; + this.blocked = true; + this.registerColumnOption("frozen"); + } + + //reset initial state + reset() { + this.initializationMode = "left"; + this.leftColumns = []; + this.rightColumns = []; + this.active = false; + } + + initialize() { + this.subscribe("cell-layout", this.layoutCell.bind(this)); + this.subscribe("column-init", this.initializeColumn.bind(this)); + this.subscribe("column-width", this.layout.bind(this)); + this.subscribe("row-layout-after", this.layoutRow.bind(this)); + this.subscribe("table-layout", this.layout.bind(this)); + this.subscribe("columns-loading", this.reset.bind(this)); + this.subscribe("column-add", this.reinitializeColumns.bind(this)); + this.subscribe("column-deleted", this.reinitializeColumns.bind(this)); + this.subscribe("column-hide", this.reinitializeColumns.bind(this)); + this.subscribe("column-show", this.reinitializeColumns.bind(this)); + this.subscribe("columns-loaded", this.reinitializeColumns.bind(this)); + this.subscribe("table-redraw", this.layout.bind(this)); + this.subscribe("layout-refreshing", this.blockLayout.bind(this)); + this.subscribe("layout-refreshed", this.unblockLayout.bind(this)); + this.subscribe("scrollbar-vertical", this.adjustForScrollbar.bind(this)); + } + + blockLayout() { + this.blocked = true; + } + + unblockLayout() { + this.blocked = false; + } + + layoutCell(cell) { + this.layoutElement(cell.element, cell.column); + } + + reinitializeColumns() { + this.reset(); + this.table.columnManager.columnsByIndex.forEach((column) => { + this.initializeColumn(column); + }); + this.layout(); + } + + //initialize specific column + initializeColumn(column) { + var config = {margin: 0, edge: false}; + if (!column.isGroup) { + if (this.frozenCheck(column)) { + config.position = this.initializationMode; + if (this.initializationMode == "left") { + this.leftColumns.push(column); + } else { + this.rightColumns.unshift(column); + } + this.active = true; + column.modules.frozen = config; + } else { + this.initializationMode = "right"; + } + } + } + + frozenCheck(column) { + if (column.parent.isGroup && column.definition.frozen) { + console.warn("Frozen Column Error - Parent column group must be frozen, not individual columns or sub column groups"); + } + if (column.parent.isGroup) { + return this.frozenCheck(column.parent); + } else { + return column.definition.frozen; + } + } + + //layout calculation rows + layoutCalcRows() { + if (this.table.modExists("columnCalcs")) { + if (this.table.modules.columnCalcs.topInitialized && this.table.modules.columnCalcs.topRow) { + this.layoutRow(this.table.modules.columnCalcs.topRow); + } + if (this.table.modules.columnCalcs.botInitialized && this.table.modules.columnCalcs.botRow) { + this.layoutRow(this.table.modules.columnCalcs.botRow); + } + if (this.table.modExists("groupRows")) { + this.layoutGroupCalcs(this.table.modules.groupRows.getGroups()); + } + } + } + + layoutGroupCalcs(groups) { + groups.forEach((group) => { + if (group.calcs.top) { + this.layoutRow(group.calcs.top); + } + if (group.calcs.bottom) { + this.layoutRow(group.calcs.bottom); + } + if (group.groupList && group.groupList.length) { + this.layoutGroupCalcs(group.groupList); + } + }); + } + + //calculate column positions and layout headers + layoutColumnPosition(allCells) { + var leftParents = []; + var leftMargin = 0; + var rightMargin = 0; + this.leftColumns.forEach((column, i) => { + column.modules.frozen.marginValue = leftMargin; + column.modules.frozen.margin = column.modules.frozen.marginValue + "px"; + if (column.visible) { + leftMargin += column.getWidth(); + } + if (i == this.leftColumns.length - 1) { + column.modules.frozen.edge = true; + } else { + column.modules.frozen.edge = false; + } + if (column.parent.isGroup) { + var parentEl = this.getColGroupParentElement(column); + if (!leftParents.includes(parentEl)) { + this.layoutElement(parentEl, column); + leftParents.push(parentEl); + } + parentEl.classList.toggle("tabulator-frozen-left", column.modules.frozen.edge && column.modules.frozen.position === "left"); + parentEl.classList.toggle("tabulator-frozen-right", column.modules.frozen.edge && column.modules.frozen.position === "right"); + } else { + this.layoutElement(column.getElement(), column); + } + if (allCells) { + column.cells.forEach((cell) => { + this.layoutElement(cell.getElement(true), column); + }); + } + }); + this.rightColumns.forEach((column, i) => { + column.modules.frozen.marginValue = rightMargin; + column.modules.frozen.margin = column.modules.frozen.marginValue + "px"; + if (column.visible) { + rightMargin += column.getWidth(); + } + if (i == this.rightColumns.length - 1) { + column.modules.frozen.edge = true; + } else { + column.modules.frozen.edge = false; + } + if (column.parent.isGroup) { + this.layoutElement(this.getColGroupParentElement(column), column); + } else { + this.layoutElement(column.getElement(), column); + } + if (allCells) { + column.cells.forEach((cell) => { + this.layoutElement(cell.getElement(true), column); + }); + } + }); + } + + getColGroupParentElement(column) { + return column.parent.isGroup ? this.getColGroupParentElement(column.parent) : column.getElement(); + } + + //layout columns appropriately + layout() { + if (this.active && !this.blocked) { + this.layoutColumnPosition(); + this.reinitializeRows(); + this.layoutCalcRows(); + } + } + + reinitializeRows() { + var visibleRows = this.table.rowManager.getVisibleRows(true); + var otherRows = this.table.rowManager.getRows().filter((row) => !visibleRows.includes(row)); + otherRows.forEach((row) => { + row.deinitialize(); + }); + visibleRows.forEach((row) => { + if (row.type === "row") { + this.layoutRow(row); + } + }); + } + + layoutRow(row) { + if (this.table.options.layout === "fitDataFill" && this.rightColumns.length) { + this.table.rowManager.getTableElement().style.minWidth = "calc(100% - " + this.rightMargin + ")"; + } + this.leftColumns.forEach((column) => { + var cell = row.getCell(column); + if (cell) { + this.layoutElement(cell.getElement(true), column); + } + }); + this.rightColumns.forEach((column) => { + var cell = row.getCell(column); + if (cell) { + this.layoutElement(cell.getElement(true), column); + } + }); + } + + layoutElement(element, column) { + var position; + if (column.modules.frozen && element) { + element.style.position = "sticky"; + if (this.table.rtl) { + position = column.modules.frozen.position === "left" ? "right" : "left"; + } else { + position = column.modules.frozen.position; + } + element.style[position] = column.modules.frozen.margin; + element.classList.add("tabulator-frozen"); + element.classList.toggle("tabulator-frozen-left", column.modules.frozen.edge && column.modules.frozen.position === "left"); + element.classList.toggle("tabulator-frozen-right", column.modules.frozen.edge && column.modules.frozen.position === "right"); + } + } + + adjustForScrollbar(width) { + if (this.rightColumns.length) { + this.table.columnManager.getContentsElement().style.width = "calc(100% - " + width + "px)"; + } + } + + getFrozenColumns() { + return this.leftColumns.concat(this.rightColumns); + } + + _calcSpace(columns, index) { + var width = 0; + for (let i = 0; i < index; i++) { + if (columns[i].visible) { + width += columns[i].getWidth(); + } + } + return width; + } + } + + __publicField(FrozenColumns, "moduleName", "frozenColumns"); + + class FrozenRows extends Module { + constructor(table) { + super(table); + this.topElement = document.createElement("div"); + this.rows = []; + this.registerComponentFunction("row", "freeze", this.freezeRow.bind(this)); + this.registerComponentFunction("row", "unfreeze", this.unfreezeRow.bind(this)); + this.registerComponentFunction("row", "isFrozen", this.isRowFrozen.bind(this)); + this.registerTableOption("frozenRowsField", "id"); + this.registerTableOption("frozenRows", false); + } + + initialize() { + var fragment = document.createDocumentFragment(); + this.rows = []; + this.topElement.classList.add("tabulator-frozen-rows-holder"); + fragment.appendChild(this.topElement); + this.table.columnManager.getContentsElement().insertBefore(fragment, this.table.columnManager.headersElement.nextSibling); + this.subscribe("row-deleting", this.detachRow.bind(this)); + this.subscribe("rows-visible", this.visibleRows.bind(this)); + this.registerDisplayHandler(this.getRows.bind(this), 10); + if (this.table.options.frozenRows) { + this.subscribe("data-processed", this.initializeRows.bind(this)); + this.subscribe("row-added", this.initializeRow.bind(this)); + this.subscribe("table-redrawing", this.resizeHolderWidth.bind(this)); + this.subscribe("column-resized", this.resizeHolderWidth.bind(this)); + this.subscribe("column-show", this.resizeHolderWidth.bind(this)); + this.subscribe("column-hide", this.resizeHolderWidth.bind(this)); + } + this.resizeHolderWidth(); + } + + resizeHolderWidth() { + this.topElement.style.minWidth = this.table.columnManager.headersElement.offsetWidth + "px"; + } + + initializeRows() { + this.table.rowManager.getRows().forEach((row) => { + this.initializeRow(row); + }); + } + + initializeRow(row) { + var frozenRows = this.table.options.frozenRows, rowType = typeof frozenRows; + if (rowType === "number") { + if (row.getPosition() && row.getPosition() + this.rows.length <= frozenRows) { + this.freezeRow(row); + } + } else if (rowType === "function") { + if (frozenRows.call(this.table, row.getComponent())) { + this.freezeRow(row); + } + } else if (Array.isArray(frozenRows)) { + if (frozenRows.includes(row.data[this.options("frozenRowsField")])) { + this.freezeRow(row); + } + } + } + + isRowFrozen(row) { + var index = this.rows.indexOf(row); + return index > -1; + } + + isFrozen() { + return !!this.rows.length; + } + + visibleRows(viewable, rows2) { + this.rows.forEach((row) => { + rows2.push(row); + }); + return rows2; + } + + //filter frozen rows out of display data + getRows(rows2) { + var output = rows2.slice(0); + this.rows.forEach(function (row) { + var index = output.indexOf(row); + if (index > -1) { + output.splice(index, 1); + } + }); + return output; + } + + freezeRow(row) { + if (!row.modules.frozen) { + row.modules.frozen = true; + this.topElement.appendChild(row.getElement()); + row.initialize(); + row.normalizeHeight(); + this.rows.push(row); + this.refreshData(false, "display"); + this.table.rowManager.adjustTableSize(); + this.styleRows(); + } else { + console.warn("Freeze Error - Row is already frozen"); + } + } + + unfreezeRow(row) { + if (row.modules.frozen) { + row.modules.frozen = false; + this.detachRow(row); + this.table.rowManager.adjustTableSize(); + this.refreshData(false, "display"); + if (this.rows.length) { + this.styleRows(); + } + } else { + console.warn("Freeze Error - Row is already unfrozen"); + } + } + + detachRow(row) { + var index = this.rows.indexOf(row); + if (index > -1) { + var rowEl = row.getElement(); + if (rowEl.parentNode) { + rowEl.parentNode.removeChild(rowEl); + } + this.rows.splice(index, 1); + } + } + + styleRows(row) { + this.rows.forEach((row2, i) => { + this.table.rowManager.styleRow(row2, i); + }); + } + } + + __publicField(FrozenRows, "moduleName", "frozenRows"); + + class GroupComponent { + constructor(group) { + this._group = group; + this.type = "GroupComponent"; + return new Proxy(this, { + get: function (target, name2, receiver) { + if (typeof target[name2] !== "undefined") { + return target[name2]; + } else { + return target._group.groupManager.table.componentFunctionBinder.handle("group", target._group, name2); + } + } + }); + } + + getKey() { + return this._group.key; + } + + getField() { + return this._group.field; + } + + getElement() { + return this._group.element; + } + + getRows() { + return this._group.getRows(true); + } + + getSubGroups() { + return this._group.getSubGroups(true); + } + + getParentGroup() { + return this._group.parent ? this._group.parent.getComponent() : false; + } + + isVisible() { + return this._group.visible; + } + + show() { + this._group.show(); + } + + hide() { + this._group.hide(); + } + + toggle() { + this._group.toggleVisibility(); + } + + scrollTo(position, ifVisible) { + return this._group.groupManager.table.rowManager.scrollToRow(this._group, position, ifVisible); + } + + _getSelf() { + return this._group; + } + + getTable() { + return this._group.groupManager.table; + } + } + + class Group { + constructor(groupManager, parent2, level, key, field, generator, oldGroup) { + this.groupManager = groupManager; + this.parent = parent2; + this.key = key; + this.level = level; + this.field = field; + this.hasSubGroups = level < groupManager.groupIDLookups.length - 1; + this.addRow = this.hasSubGroups ? this._addRowToGroup : this._addRow; + this.type = "group"; + this.old = oldGroup; + this.rows = []; + this.groups = []; + this.groupList = []; + this.generator = generator; + this.element = false; + this.elementContents = false; + this.height = 0; + this.outerHeight = 0; + this.initialized = false; + this.calcs = {}; + this.initialized = false; + this.modules = {}; + this.arrowElement = false; + this.visible = oldGroup ? oldGroup.visible : typeof groupManager.startOpen[level] !== "undefined" ? groupManager.startOpen[level] : groupManager.startOpen[0]; + this.component = null; + this.createElements(); + this.addBindings(); + this.createValueGroups(); + } + + wipe(elementsOnly) { + if (!elementsOnly) { + if (this.groupList.length) { + this.groupList.forEach(function (group) { + group.wipe(); + }); + } else { + this.rows.forEach((row) => { + if (row.modules) { + delete row.modules.group; + } + }); + } + } + this.element = false; + this.arrowElement = false; + this.elementContents = false; + } + + createElements() { + var arrow = document.createElement("div"); + arrow.classList.add("tabulator-arrow"); + this.element = document.createElement("div"); + this.element.classList.add("tabulator-row"); + this.element.classList.add("tabulator-group"); + this.element.classList.add("tabulator-group-level-" + this.level); + this.element.setAttribute("role", "rowgroup"); + this.arrowElement = document.createElement("div"); + this.arrowElement.classList.add("tabulator-group-toggle"); + this.arrowElement.appendChild(arrow); + if (this.groupManager.table.options.movableRows !== false && this.groupManager.table.modExists("moveRow")) { + this.groupManager.table.modules.moveRow.initializeGroupHeader(this); + } + } + + createValueGroups() { + var level = this.level + 1; + if (this.groupManager.allowedValues && this.groupManager.allowedValues[level]) { + this.groupManager.allowedValues[level].forEach((value) => { + this._createGroup(value, level); + }); + } + } + + addBindings() { + var toggleElement; + if (this.groupManager.table.options.groupToggleElement) { + toggleElement = this.groupManager.table.options.groupToggleElement == "arrow" ? this.arrowElement : this.element; + toggleElement.addEventListener("click", (e) => { + if (this.groupManager.table.options.groupToggleElement === "arrow") { + e.stopPropagation(); + e.stopImmediatePropagation(); + } + setTimeout(() => { + this.toggleVisibility(); + }); + }); + } + } + + _createGroup(groupID, level) { + var groupKey = level + "_" + groupID; + var group = new Group(this.groupManager, this, level, groupID, this.groupManager.groupIDLookups[level].field, this.groupManager.headerGenerator[level] || this.groupManager.headerGenerator[0], this.old ? this.old.groups[groupKey] : false); + this.groups[groupKey] = group; + this.groupList.push(group); + } + + _addRowToGroup(row) { + var level = this.level + 1; + if (this.hasSubGroups) { + var groupID = this.groupManager.groupIDLookups[level].func(row.getData()), + groupKey = level + "_" + groupID; + if (this.groupManager.allowedValues && this.groupManager.allowedValues[level]) { + if (this.groups[groupKey]) { + this.groups[groupKey].addRow(row); + } + } else { + if (!this.groups[groupKey]) { + this._createGroup(groupID, level); + } + this.groups[groupKey].addRow(row); + } + } + } + + _addRow(row) { + this.rows.push(row); + row.modules.group = this; + } + + insertRow(row, to, after) { + var data = this.conformRowData({}); + row.updateData(data); + var toIndex = this.rows.indexOf(to); + if (toIndex > -1) { + if (after) { + this.rows.splice(toIndex + 1, 0, row); + } else { + this.rows.splice(toIndex, 0, row); + } + } else { + if (after) { + this.rows.push(row); + } else { + this.rows.unshift(row); + } + } + row.modules.group = this; + if (this.groupManager.table.modExists("columnCalcs") && this.groupManager.table.options.columnCalcs != "table") { + this.groupManager.table.modules.columnCalcs.recalcGroup(this); + } + this.groupManager.updateGroupRows(true); + } + + scrollHeader(left) { + if (this.arrowElement) { + this.arrowElement.style.marginLeft = left; + this.groupList.forEach(function (child) { + child.scrollHeader(left); + }); + } + } + + getRowIndex(row) { + } + + //update row data to match grouping constraints + conformRowData(data) { + if (this.field) { + data[this.field] = this.key; + } else { + console.warn("Data Conforming Error - Cannot conform row data to match new group as groupBy is a function"); + } + if (this.parent) { + data = this.parent.conformRowData(data); + } + return data; + } + + removeRow(row) { + var index = this.rows.indexOf(row); + var el = row.getElement(); + if (index > -1) { + this.rows.splice(index, 1); + } + if (!this.groupManager.table.options.groupValues && !this.rows.length) { + if (this.parent) { + this.parent.removeGroup(this); + } else { + this.groupManager.removeGroup(this); + } + this.groupManager.updateGroupRows(true); + } else { + if (el.parentNode) { + el.parentNode.removeChild(el); + } + if (!this.groupManager.blockRedraw) { + this.generateGroupHeaderContents(); + if (this.groupManager.table.modExists("columnCalcs") && this.groupManager.table.options.columnCalcs != "table") { + this.groupManager.table.modules.columnCalcs.recalcGroup(this); + } + } + } + } + + removeGroup(group) { + var groupKey = group.level + "_" + group.key, index; + if (this.groups[groupKey]) { + delete this.groups[groupKey]; + index = this.groupList.indexOf(group); + if (index > -1) { + this.groupList.splice(index, 1); + } + if (!this.groupList.length) { + if (this.parent) { + this.parent.removeGroup(this); + } else { + this.groupManager.removeGroup(this); + } + } + } + } + + getHeadersAndRows() { + var output = []; + output.push(this); + this._visSet(); + if (this.calcs.top) { + this.calcs.top.detachElement(); + this.calcs.top.deleteCells(); + } + if (this.calcs.bottom) { + this.calcs.bottom.detachElement(); + this.calcs.bottom.deleteCells(); + } + if (this.visible) { + if (this.groupList.length) { + this.groupList.forEach(function (group) { + output = output.concat(group.getHeadersAndRows()); + }); + } else { + if (this.groupManager.table.options.columnCalcs != "table" && this.groupManager.table.modExists("columnCalcs") && this.groupManager.table.modules.columnCalcs.hasTopCalcs()) { + this.calcs.top = this.groupManager.table.modules.columnCalcs.generateTopRow(this.rows); + output.push(this.calcs.top); + } + output = output.concat(this.rows); + if (this.groupManager.table.options.columnCalcs != "table" && this.groupManager.table.modExists("columnCalcs") && this.groupManager.table.modules.columnCalcs.hasBottomCalcs()) { + this.calcs.bottom = this.groupManager.table.modules.columnCalcs.generateBottomRow(this.rows); + output.push(this.calcs.bottom); + } + } + } else { + if (!this.groupList.length && this.groupManager.table.options.columnCalcs != "table") { + if (this.groupManager.table.modExists("columnCalcs")) { + if (this.groupManager.table.modules.columnCalcs.hasTopCalcs()) { + if (this.groupManager.table.options.groupClosedShowCalcs) { + this.calcs.top = this.groupManager.table.modules.columnCalcs.generateTopRow(this.rows); + output.push(this.calcs.top); + } + } + if (this.groupManager.table.modules.columnCalcs.hasBottomCalcs()) { + if (this.groupManager.table.options.groupClosedShowCalcs) { + this.calcs.bottom = this.groupManager.table.modules.columnCalcs.generateBottomRow(this.rows); + output.push(this.calcs.bottom); + } + } + } + } + } + return output; + } + + getData(visible, transform) { + var output = []; + this._visSet(); + if (!visible || visible && this.visible) { + this.rows.forEach((row) => { + output.push(row.getData(transform || "data")); + }); + } + return output; + } + + getRowCount() { + var count = 0; + if (this.groupList.length) { + this.groupList.forEach((group) => { + count += group.getRowCount(); + }); + } else { + count = this.rows.length; + } + return count; + } + + toggleVisibility() { + if (this.visible) { + this.hide(); + } else { + this.show(); + } + } + + hide() { + this.visible = false; + if (this.groupManager.table.rowManager.getRenderMode() == "basic" && !this.groupManager.table.options.pagination) { + this.element.classList.remove("tabulator-group-visible"); + if (this.groupList.length) { + this.groupList.forEach((group) => { + var rows2 = group.getHeadersAndRows(); + rows2.forEach((row) => { + row.detachElement(); + }); + }); + } else { + this.rows.forEach((row) => { + var rowEl = row.getElement(); + rowEl.parentNode.removeChild(rowEl); + }); + } + this.groupManager.updateGroupRows(true); + } else { + this.groupManager.updateGroupRows(true); + } + this.groupManager.table.externalEvents.dispatch("groupVisibilityChanged", this.getComponent(), false); + } + + show() { + this.visible = true; + if (this.groupManager.table.rowManager.getRenderMode() == "basic" && !this.groupManager.table.options.pagination) { + this.element.classList.add("tabulator-group-visible"); + var prev = this.generateElement(); + if (this.groupList.length) { + this.groupList.forEach((group) => { + var rows2 = group.getHeadersAndRows(); + rows2.forEach((row) => { + var rowEl = row.getElement(); + prev.parentNode.insertBefore(rowEl, prev.nextSibling); + row.initialize(); + prev = rowEl; + }); + }); + } else { + this.rows.forEach((row) => { + var rowEl = row.getElement(); + prev.parentNode.insertBefore(rowEl, prev.nextSibling); + row.initialize(); + prev = rowEl; + }); + } + this.groupManager.updateGroupRows(true); + } else { + this.groupManager.updateGroupRows(true); + } + this.groupManager.table.externalEvents.dispatch("groupVisibilityChanged", this.getComponent(), true); + } + + _visSet() { + var data = []; + if (typeof this.visible == "function") { + this.rows.forEach(function (row) { + data.push(row.getData()); + }); + this.visible = this.visible(this.key, this.getRowCount(), data, this.getComponent()); + } + } + + getRowGroup(row) { + var match = false; + if (this.groupList.length) { + this.groupList.forEach(function (group) { + var result = group.getRowGroup(row); + if (result) { + match = result; + } + }); + } else { + if (this.rows.find(function (item) { + return item === row; + })) { + match = this; + } + } + return match; + } + + getSubGroups(component) { + var output = []; + this.groupList.forEach(function (child) { + output.push(component ? child.getComponent() : child); + }); + return output; + } + + getRows(component, includeChildren) { + var output = []; + if (includeChildren && this.groupList.length) { + this.groupList.forEach((group) => { + output = output.concat(group.getRows(component, includeChildren)); + }); + } else { + this.rows.forEach(function (row) { + output.push(component ? row.getComponent() : row); + }); + } + return output; + } + + generateGroupHeaderContents() { + var data = []; + var rows2 = this.getRows(false, true); + rows2.forEach(function (row) { + data.push(row.getData()); + }); + this.elementContents = this.generator(this.key, this.getRowCount(), data, this.getComponent()); + while (this.element.firstChild) this.element.removeChild(this.element.firstChild); + if (typeof this.elementContents === "string") { + this.element.innerHTML = this.elementContents; + } else { + this.element.appendChild(this.elementContents); + } + this.element.insertBefore(this.arrowElement, this.element.firstChild); + } + + getPath(path = []) { + path.unshift(this.key); + if (this.parent) { + this.parent.getPath(path); + } + return path; + } + + ////////////// Standard Row Functions ////////////// + getElement() { + return this.elementContents ? this.element : this.generateElement(); + } + + generateElement() { + this.addBindings = false; + this._visSet(); + if (this.visible) { + this.element.classList.add("tabulator-group-visible"); + } else { + this.element.classList.remove("tabulator-group-visible"); + } + for (var i = 0; i < this.element.childNodes.length; ++i) { + this.element.childNodes[i].parentNode.removeChild(this.element.childNodes[i]); + } + this.generateGroupHeaderContents(); + return this.element; + } + + detachElement() { + if (this.element && this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + } + + //normalize the height of elements in the row + normalizeHeight() { + this.setHeight(this.element.clientHeight); + } + + initialize(force) { + if (!this.initialized || force) { + this.normalizeHeight(); + this.initialized = true; + } + } + + reinitialize() { + this.initialized = false; + this.height = 0; + if (Helpers.elVisible(this.element)) { + this.initialize(true); + } + } + + setHeight(height) { + if (this.height != height) { + this.height = height; + this.outerHeight = this.element.offsetHeight; + } + } + + //return rows outer height + getHeight() { + return this.outerHeight; + } + + getGroup() { + return this; + } + + reinitializeHeight() { + } + + calcHeight() { + this.outerHeight = this.element.offsetHeight; + } + + setCellHeight() { + } + + clearCellHeight() { + } + + deinitializeHeight() { + } + + rendered() { + } + + //////////////// Object Generation ///////////////// + getComponent() { + if (!this.component) { + this.component = new GroupComponent(this); + } + return this.component; + } + } + + class GroupRows extends Module { + constructor(table) { + super(table); + this.groupIDLookups = false; + this.startOpen = [function () { + return false; + }]; + this.headerGenerator = [function () { + return ""; + }]; + this.groupList = []; + this.allowedValues = false; + this.groups = {}; + this.displayHandler = this.getRows.bind(this); + this.blockRedraw = false; + this.registerTableOption("groupBy", false); + this.registerTableOption("groupStartOpen", true); + this.registerTableOption("groupValues", false); + this.registerTableOption("groupUpdateOnCellEdit", false); + this.registerTableOption("groupHeader", false); + this.registerTableOption("groupHeaderPrint", null); + this.registerTableOption("groupHeaderClipboard", null); + this.registerTableOption("groupHeaderHtmlOutput", null); + this.registerTableOption("groupHeaderDownload", null); + this.registerTableOption("groupToggleElement", "arrow"); + this.registerTableOption("groupClosedShowCalcs", false); + this.registerTableFunction("setGroupBy", this.setGroupBy.bind(this)); + this.registerTableFunction("setGroupValues", this.setGroupValues.bind(this)); + this.registerTableFunction("setGroupStartOpen", this.setGroupStartOpen.bind(this)); + this.registerTableFunction("setGroupHeader", this.setGroupHeader.bind(this)); + this.registerTableFunction("getGroups", this.userGetGroups.bind(this)); + this.registerTableFunction("getGroupedData", this.userGetGroupedData.bind(this)); + this.registerComponentFunction("row", "getGroup", this.rowGetGroup.bind(this)); + } + + //initialize group configuration + initialize() { + this.subscribe("table-destroy", this._blockRedrawing.bind(this)); + this.subscribe("rows-wipe", this._blockRedrawing.bind(this)); + this.subscribe("rows-wiped", this._restore_redrawing.bind(this)); + if (this.table.options.groupBy) { + if (this.table.options.groupUpdateOnCellEdit) { + this.subscribe("cell-value-updated", this.cellUpdated.bind(this)); + this.subscribe("row-data-changed", this.reassignRowToGroup.bind(this), 0); + } + this.subscribe("table-built", this.configureGroupSetup.bind(this)); + this.subscribe("row-deleting", this.rowDeleting.bind(this)); + this.subscribe("row-deleted", this.rowsUpdated.bind(this)); + this.subscribe("scroll-horizontal", this.scrollHeaders.bind(this)); + this.subscribe("rows-wipe", this.wipe.bind(this)); + this.subscribe("rows-added", this.rowsUpdated.bind(this)); + this.subscribe("row-moving", this.rowMoving.bind(this)); + this.subscribe("row-adding-index", this.rowAddingIndex.bind(this)); + this.subscribe("rows-sample", this.rowSample.bind(this)); + this.subscribe("render-virtual-fill", this.virtualRenderFill.bind(this)); + this.subscribe("table-layout", this.virtualRenderFill.bind(this)); + this.registerDisplayHandler(this.displayHandler, 20); + this.initialized = true; + } + } + + _blockRedrawing() { + this.blockRedraw = true; + } + + _restore_redrawing() { + this.blockRedraw = false; + } + + configureGroupSetup() { + if (this.table.options.groupBy) { + var groupBy = this.table.options.groupBy, startOpen = this.table.options.groupStartOpen, + groupHeader = this.table.options.groupHeader; + this.allowedValues = this.table.options.groupValues; + if (Array.isArray(groupBy) && Array.isArray(groupHeader) && groupBy.length > groupHeader.length) { + console.warn("Error creating group headers, groupHeader array is shorter than groupBy array"); + } + this.headerGenerator = [function () { + return ""; + }]; + this.startOpen = [function () { + return false; + }]; + this.langBind("groups|item", (langValue, lang) => { + this.headerGenerator[0] = (value, count, data) => { + return (typeof value === "undefined" ? "" : value) + "(" + count + " " + (count === 1 ? langValue : lang.groups.items) + ")"; + }; + }); + this.groupIDLookups = []; + if (groupBy) { + if (this.table.modExists("columnCalcs") && this.table.options.columnCalcs != "table" && this.table.options.columnCalcs != "both") { + this.table.modules.columnCalcs.removeCalcs(); + } + } else { + if (this.table.modExists("columnCalcs") && this.table.options.columnCalcs != "group") { + var cols = this.table.columnManager.getRealColumns(); + cols.forEach((col) => { + if (col.definition.topCalc) { + this.table.modules.columnCalcs.initializeTopRow(); + } + if (col.definition.bottomCalc) { + this.table.modules.columnCalcs.initializeBottomRow(); + } + }); + } + } + if (!Array.isArray(groupBy)) { + groupBy = [groupBy]; + } + groupBy.forEach((group, i) => { + var lookupFunc, column; + if (typeof group == "function") { + lookupFunc = group; + } else { + column = this.table.columnManager.getColumnByField(group); + if (column) { + lookupFunc = function (data) { + return column.getFieldValue(data); + }; + } else { + lookupFunc = function (data) { + return data[group]; + }; + } + } + this.groupIDLookups.push({ + field: typeof group === "function" ? false : group, + func: lookupFunc, + values: this.allowedValues ? this.allowedValues[i] : false + }); + }); + if (startOpen) { + if (!Array.isArray(startOpen)) { + startOpen = [startOpen]; + } + startOpen.forEach((level) => { + }); + this.startOpen = startOpen; + } + if (groupHeader) { + this.headerGenerator = Array.isArray(groupHeader) ? groupHeader : [groupHeader]; + } + } else { + this.groupList = []; + this.groups = {}; + } + } + + rowSample(rows2, prevValue) { + if (this.table.options.groupBy) { + var group = this.getGroups(false)[0]; + prevValue.push(group.getRows(false)[0]); + } + return prevValue; + } + + virtualRenderFill() { + const layout = this.layoutMode(); + if (layout === "fitDataFill" || layout === "fitDataStretch" || layout === "fitColumns") { + this.table.rowManager.tableElement.style.minWidth = this.table.columnManager.getWidth() + "px"; + } + } + + rowAddingIndex(row, index, top) { + if (this.table.options.groupBy) { + this.assignRowToGroup(row); + var groupRows = row.modules.group.rows; + if (groupRows.length > 1) { + if (!index || index && groupRows.indexOf(index) == -1) { + if (top) { + if (groupRows[0] !== row) { + index = groupRows[0]; + this.table.rowManager.moveRowInArray(row.modules.group.rows, row, index, !top); + } + } else { + if (groupRows[groupRows.length - 1] !== row) { + index = groupRows[groupRows.length - 1]; + this.table.rowManager.moveRowInArray(row.modules.group.rows, row, index, !top); + } + } + } else { + this.table.rowManager.moveRowInArray(row.modules.group.rows, row, index, !top); + } + } + return index; + } + } + + trackChanges() { + this.dispatch("group-changed"); + } + + /////////////////////////////////// + ///////// Table Functions ///////// + /////////////////////////////////// + setGroupBy(groups) { + this.table.options.groupBy = groups; + if (!this.initialized) { + this.initialize(); + } + this.configureGroupSetup(); + if (!groups && this.table.modExists("columnCalcs") && this.table.options.columnCalcs === true) { + this.table.modules.columnCalcs.reinitializeCalcs(); + } + this.refreshData(); + this.trackChanges(); + } + + setGroupValues(groupValues) { + this.table.options.groupValues = groupValues; + this.configureGroupSetup(); + this.refreshData(); + this.trackChanges(); + } + + setGroupStartOpen(values) { + this.table.options.groupStartOpen = values; + this.configureGroupSetup(); + if (this.table.options.groupBy) { + this.refreshData(); + this.trackChanges(); + } else { + console.warn("Grouping Update - cant refresh view, no groups have been set"); + } + } + + setGroupHeader(values) { + this.table.options.groupHeader = values; + this.configureGroupSetup(); + if (this.table.options.groupBy) { + this.refreshData(); + this.trackChanges(); + } else { + console.warn("Grouping Update - cant refresh view, no groups have been set"); + } + } + + userGetGroups(values) { + return this.getGroups(true); + } + + // get grouped table data in the same format as getData() + userGetGroupedData() { + return this.table.options.groupBy ? this.getGroupedData() : this.getData(); + } + + /////////////////////////////////////// + ///////// Component Functions ///////// + /////////////////////////////////////// + rowGetGroup(row) { + return row.modules.group ? row.modules.group.getComponent() : false; + } + + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + rowMoving(from, to, after) { + if (this.table.options.groupBy) { + if (!after && to instanceof Group) { + to = this.table.rowManager.prevDisplayRow(from) || to; + } + var toGroup = to instanceof Group ? to : to.modules.group; + var fromGroup = from instanceof Group ? from : from.modules.group; + if (toGroup === fromGroup) { + this.table.rowManager.moveRowInArray(toGroup.rows, from, to, after); + } else { + if (fromGroup) { + fromGroup.removeRow(from); + } + toGroup.insertRow(from, to, after); + } + } + } + + rowDeleting(row) { + if (this.table.options.groupBy && row.modules.group) { + row.modules.group.removeRow(row); + } + } + + rowsUpdated(row) { + if (this.table.options.groupBy) { + this.updateGroupRows(true); + } + } + + cellUpdated(cell) { + if (this.table.options.groupBy) { + this.reassignRowToGroup(cell.row); + } + } + + //return appropriate rows with group headers + getRows(rows2) { + if (this.table.options.groupBy && this.groupIDLookups.length) { + this.dispatchExternal("dataGrouping"); + this.generateGroups(rows2); + if (this.subscribedExternal("dataGrouped")) { + this.dispatchExternal("dataGrouped", this.getGroups(true)); + } + return this.updateGroupRows(); + } else { + return rows2.slice(0); + } + } + + getGroups(component) { + var groupComponents = []; + this.groupList.forEach(function (group) { + groupComponents.push(component ? group.getComponent() : group); + }); + return groupComponents; + } + + getChildGroups(group) { + var groupComponents = []; + if (!group) { + group = this; + } + group.groupList.forEach((child) => { + if (child.groupList.length) { + groupComponents = groupComponents.concat(this.getChildGroups(child)); + } else { + groupComponents.push(child); + } + }); + return groupComponents; + } + + wipe() { + if (this.table.options.groupBy) { + this.groupList.forEach(function (group) { + group.wipe(); + }); + this.groupList = []; + this.groups = {}; + } + } + + pullGroupListData(groupList) { + var groupListData = []; + groupList.forEach((group) => { + var groupHeader = {}; + groupHeader.level = 0; + groupHeader.rowCount = 0; + groupHeader.headerContent = ""; + var childData = []; + if (group.hasSubGroups) { + childData = this.pullGroupListData(group.groupList); + groupHeader.level = group.level; + groupHeader.rowCount = childData.length - group.groupList.length; + groupHeader.headerContent = group.generator(group.key, groupHeader.rowCount, group.rows, group); + groupListData.push(groupHeader); + groupListData = groupListData.concat(childData); + } else { + groupHeader.level = group.level; + groupHeader.headerContent = group.generator(group.key, group.rows.length, group.rows, group); + groupHeader.rowCount = group.getRows().length; + groupListData.push(groupHeader); + group.getRows().forEach((row) => { + groupListData.push(row.getData("data")); + }); + } + }); + return groupListData; + } + + getGroupedData() { + return this.pullGroupListData(this.groupList); + } + + getRowGroup(row) { + var match = false; + if (this.options("dataTree")) { + row = this.table.modules.dataTree.getTreeParentRoot(row); + } + this.groupList.forEach((group) => { + var result = group.getRowGroup(row); + if (result) { + match = result; + } + }); + return match; + } + + countGroups() { + return this.groupList.length; + } + + generateGroups(rows2) { + var oldGroups = this.groups; + this.groups = {}; + this.groupList = []; + if (this.allowedValues && this.allowedValues[0]) { + this.allowedValues[0].forEach((value) => { + this.createGroup(value, 0, oldGroups); + }); + rows2.forEach((row) => { + this.assignRowToExistingGroup(row, oldGroups); + }); + } else { + rows2.forEach((row) => { + this.assignRowToGroup(row, oldGroups); + }); + } + Object.values(oldGroups).forEach((group) => { + group.wipe(true); + }); + } + + createGroup(groupID, level, oldGroups) { + var groupKey = level + "_" + groupID, group; + oldGroups = oldGroups || []; + group = new Group(this, false, level, groupID, this.groupIDLookups[0].field, this.headerGenerator[0], oldGroups[groupKey]); + this.groups[groupKey] = group; + this.groupList.push(group); + } + + assignRowToExistingGroup(row, oldGroups) { + var groupID = this.groupIDLookups[0].func(row.getData()), groupKey = "0_" + groupID; + if (this.groups[groupKey]) { + this.groups[groupKey].addRow(row); + } + } + + assignRowToGroup(row, oldGroups) { + var groupID = this.groupIDLookups[0].func(row.getData()), newGroupNeeded = !this.groups["0_" + groupID]; + if (newGroupNeeded) { + this.createGroup(groupID, 0, oldGroups); + } + this.groups["0_" + groupID].addRow(row); + return !newGroupNeeded; + } + + reassignRowToGroup(row) { + if (row.type === "row") { + var oldRowGroup = row.modules.group, oldGroupPath = oldRowGroup.getPath(), + newGroupPath = this.getExpectedPath(row), samePath; + samePath = oldGroupPath.length == newGroupPath.length && oldGroupPath.every((element, index) => { + return element === newGroupPath[index]; + }); + if (!samePath) { + oldRowGroup.removeRow(row); + this.assignRowToGroup(row, this.groups); + this.refreshData(true); + } + } + } + + getExpectedPath(row) { + var groupPath = [], rowData = row.getData(); + this.groupIDLookups.forEach((groupId) => { + groupPath.push(groupId.func(rowData)); + }); + return groupPath; + } + + updateGroupRows(force) { + var output = []; + if (!this.blockRedraw) { + this.groupList.forEach((group) => { + output = output.concat(group.getHeadersAndRows()); + }); + if (force) { + this.refreshData(true); + } + } + return output; + } + + scrollHeaders(left) { + if (this.table.options.groupBy) { + if (this.table.options.renderHorizontal === "virtual") { + left -= this.table.columnManager.renderer.vDomPadLeft; + } + left = left + "px"; + this.groupList.forEach((group) => { + group.scrollHeader(left); + }); + } + } + + removeGroup(group) { + var groupKey = group.level + "_" + group.key, index; + if (this.groups[groupKey]) { + delete this.groups[groupKey]; + index = this.groupList.indexOf(group); + if (index > -1) { + this.groupList.splice(index, 1); + } + } + } + + checkBasicModeGroupHeaderWidth() { + var element = this.table.rowManager.tableElement, onlyGroupHeaders = true; + this.table.rowManager.getDisplayRows().forEach((row, index) => { + this.table.rowManager.styleRow(row, index); + element.appendChild(row.getElement()); + row.initialize(true); + if (row.type !== "group") { + onlyGroupHeaders = false; + } + }); + if (onlyGroupHeaders) { + element.style.minWidth = this.table.columnManager.getWidth() + "px"; + } else { + element.style.minWidth = ""; + } + } + } + + __publicField(GroupRows, "moduleName", "groupRows"); + var defaultUndoers = { + cellEdit: function (action) { + action.component.setValueProcessData(action.data.oldValue); + action.component.cellRendered(); + }, + rowAdd: function (action) { + action.component.deleteActual(); + this.table.rowManager.checkPlaceholder(); + }, + rowDelete: function (action) { + var newRow = this.table.rowManager.addRowActual(action.data.data, action.data.pos, action.data.index); + if (this.table.options.groupBy && this.table.modExists("groupRows")) { + this.table.modules.groupRows.updateGroupRows(true); + } + this._rebindRow(action.component, newRow); + this.table.rowManager.checkPlaceholder(); + }, + rowMove: function (action) { + var after = action.data.posFrom - action.data.posTo > 0; + this.table.rowManager.moveRowActual(action.component, this.table.rowManager.getRowFromPosition(action.data.posFrom), after); + this.table.rowManager.regenerateRowPositions(); + this.table.rowManager.reRenderInPosition(); + } + }; + var defaultRedoers = { + cellEdit: function (action) { + action.component.setValueProcessData(action.data.newValue); + action.component.cellRendered(); + }, + rowAdd: function (action) { + var newRow = this.table.rowManager.addRowActual(action.data.data, action.data.pos, action.data.index); + if (this.table.options.groupBy && this.table.modExists("groupRows")) { + this.table.modules.groupRows.updateGroupRows(true); + } + this._rebindRow(action.component, newRow); + this.table.rowManager.checkPlaceholder(); + }, + rowDelete: function (action) { + action.component.deleteActual(); + this.table.rowManager.checkPlaceholder(); + }, + rowMove: function (action) { + this.table.rowManager.moveRowActual(action.component, this.table.rowManager.getRowFromPosition(action.data.posTo), action.data.after); + this.table.rowManager.regenerateRowPositions(); + this.table.rowManager.reRenderInPosition(); + } + }; + var bindings$1 = { + undo: ["ctrl + 90", "meta + 90"], + redo: ["ctrl + 89", "meta + 89"] + }; + var actions$1 = { + undo: function (e) { + var cell = false; + if (this.table.options.history && this.table.modExists("history") && this.table.modExists("edit")) { + cell = this.table.modules.edit.currentCell; + if (!cell) { + e.preventDefault(); + this.table.modules.history.undo(); + } + } + }, + redo: function (e) { + var cell = false; + if (this.table.options.history && this.table.modExists("history") && this.table.modExists("edit")) { + cell = this.table.modules.edit.currentCell; + if (!cell) { + e.preventDefault(); + this.table.modules.history.redo(); + } + } + } + }; + var extensions$3 = { + keybindings: { + bindings: bindings$1, + actions: actions$1 + } + }; + const _History = class _History extends Module { + constructor(table) { + super(table); + this.history = []; + this.index = -1; + this.registerTableOption("history", false); + } + + initialize() { + if (this.table.options.history) { + this.subscribe("cell-value-updated", this.cellUpdated.bind(this)); + this.subscribe("cell-delete", this.clearComponentHistory.bind(this)); + this.subscribe("row-delete", this.rowDeleted.bind(this)); + this.subscribe("rows-wipe", this.clear.bind(this)); + this.subscribe("row-added", this.rowAdded.bind(this)); + this.subscribe("row-move", this.rowMoved.bind(this)); + } + this.registerTableFunction("undo", this.undo.bind(this)); + this.registerTableFunction("redo", this.redo.bind(this)); + this.registerTableFunction("getHistoryUndoSize", this.getHistoryUndoSize.bind(this)); + this.registerTableFunction("getHistoryRedoSize", this.getHistoryRedoSize.bind(this)); + this.registerTableFunction("clearHistory", this.clear.bind(this)); + } + + rowMoved(from, to, after) { + this.action("rowMove", from, {posFrom: from.getPosition(), posTo: to.getPosition(), to, after}); + } + + rowAdded(row, data, pos, index) { + this.action("rowAdd", row, {data, pos, index}); + } + + rowDeleted(row) { + var index, rows2; + if (this.table.options.groupBy) { + rows2 = row.getComponent().getGroup()._getSelf().rows; + index = rows2.indexOf(row); + if (index) { + index = rows2[index - 1]; + } + } else { + index = row.table.rowManager.getRowIndex(row); + if (index) { + index = row.table.rowManager.rows[index - 1]; + } + } + this.action("rowDelete", row, {data: row.getData(), pos: !index, index}); + } + + cellUpdated(cell) { + this.action("cellEdit", cell, {oldValue: cell.oldValue, newValue: cell.value}); + } + + clear() { + this.history = []; + this.index = -1; + } + + action(type, component, data) { + this.history = this.history.slice(0, this.index + 1); + this.history.push({ + type, + component, + data + }); + this.index++; + } + + getHistoryUndoSize() { + return this.index + 1; + } + + getHistoryRedoSize() { + return this.history.length - (this.index + 1); + } + + clearComponentHistory(component) { + var index = this.history.findIndex(function (item) { + return item.component === component; + }); + if (index > -1) { + this.history.splice(index, 1); + if (index <= this.index) { + this.index--; + } + this.clearComponentHistory(component); + } + } + + undo() { + if (this.index > -1) { + let action = this.history[this.index]; + _History.undoers[action.type].call(this, action); + this.index--; + this.dispatchExternal("historyUndo", action.type, action.component.getComponent(), action.data); + return true; + } else { + console.warn(this.options("history") ? "History Undo Error - No more history to undo" : "History module not enabled"); + return false; + } + } + + redo() { + if (this.history.length - 1 > this.index) { + this.index++; + let action = this.history[this.index]; + _History.redoers[action.type].call(this, action); + this.dispatchExternal("historyRedo", action.type, action.component.getComponent(), action.data); + return true; + } else { + console.warn(this.options("history") ? "History Redo Error - No more history to redo" : "History module not enabled"); + return false; + } + } + + //rebind rows to new element after deletion + _rebindRow(oldRow, newRow) { + this.history.forEach(function (action) { + if (action.component instanceof Row) { + if (action.component === oldRow) { + action.component = newRow; + } + } else if (action.component instanceof Cell) { + if (action.component.row === oldRow) { + var field = action.component.column.getField(); + if (field) { + action.component = newRow.getCell(field); + } + } + } + }); + } + }; + __publicField(_History, "moduleName", "history"); + __publicField(_History, "moduleExtensions", extensions$3); + //load defaults + __publicField(_History, "undoers", defaultUndoers); + __publicField(_History, "redoers", defaultRedoers); + let History = _History; + + class HtmlTableImport extends Module { + constructor(table) { + super(table); + this.fieldIndex = []; + this.hasIndex = false; + } + + initialize() { + this.tableElementCheck(); + } + + tableElementCheck() { + if (this.table.originalElement && this.table.originalElement.tagName === "TABLE") { + if (this.table.originalElement.childNodes.length) { + this.parseTable(); + } else { + console.warn("Unable to parse data from empty table tag, Tabulator should be initialized on a div tag unless importing data from a table element."); + } + } + } + + parseTable() { + var element = this.table.originalElement, options = this.table.options, + headers = element.getElementsByTagName("th"), rows2 = element.getElementsByTagName("tbody")[0], + data = []; + this.hasIndex = false; + this.dispatchExternal("htmlImporting"); + rows2 = rows2 ? rows2.getElementsByTagName("tr") : []; + this._extractOptions(element, options); + if (headers.length) { + this._extractHeaders(headers, rows2); + } else { + this._generateBlankHeaders(headers, rows2); + } + for (var index = 0; index < rows2.length; index++) { + var row = rows2[index], cells = row.getElementsByTagName("td"), item = {}; + if (!this.hasIndex) { + item[options.index] = index; + } + for (var i = 0; i < cells.length; i++) { + var cell = cells[i]; + if (typeof this.fieldIndex[i] !== "undefined") { + item[this.fieldIndex[i]] = cell.innerHTML; + } + } + data.push(item); + } + options.data = data; + this.dispatchExternal("htmlImported"); + } + + //extract tabulator attribute options + _extractOptions(element, options, defaultOptions2) { + var attributes = element.attributes; + var optionsArr = defaultOptions2 ? Object.keys(defaultOptions2) : Object.keys(options); + var optionsList = {}; + optionsArr.forEach((item) => { + optionsList[item.toLowerCase()] = item; + }); + for (var index in attributes) { + var attrib = attributes[index]; + var name2; + if (attrib && typeof attrib == "object" && attrib.name && attrib.name.indexOf("tabulator-") === 0) { + name2 = attrib.name.replace("tabulator-", ""); + if (typeof optionsList[name2] !== "undefined") { + options[optionsList[name2]] = this._attribValue(attrib.value); + } + } + } + } + + //get value of attribute + _attribValue(value) { + if (value === "true") { + return true; + } + if (value === "false") { + return false; + } + return value; + } + + //find column if it has already been defined + _findCol(title) { + var match = this.table.options.columns.find((column) => { + return column.title === title; + }); + return match || false; + } + + //extract column from headers + _extractHeaders(headers, rows2) { + for (var index = 0; index < headers.length; index++) { + var header = headers[index], exists2 = false, col = this._findCol(header.textContent), width; + if (col) { + exists2 = true; + } else { + col = {title: header.textContent.trim()}; + } + if (!col.field) { + col.field = header.textContent.trim().toLowerCase().replaceAll(" ", "_"); + } + width = header.getAttribute("width"); + if (width && !col.width) { + col.width = width; + } + this._extractOptions(header, col, this.table.columnManager.optionsList.registeredDefaults); + this.fieldIndex[index] = col.field; + if (col.field == this.table.options.index) { + this.hasIndex = true; + } + if (!exists2) { + this.table.options.columns.push(col); + } + } + } + + //generate blank headers + _generateBlankHeaders(headers, rows2) { + for (var index = 0; index < headers.length; index++) { + var header = headers[index], col = {title: "", field: "col" + index}; + this.fieldIndex[index] = col.field; + var width = header.getAttribute("width"); + if (width) { + col.width = width; + } + this.table.options.columns.push(col); + } + } + } + + __publicField(HtmlTableImport, "moduleName", "htmlTableImport"); + + function csv(input2) { + var data = [], row = 0, col = 0, inQuote = false; + for (let index = 0; index < input2.length; index++) { + let char = input2[index], nextChar = input2[index + 1]; + if (!data[row]) { + data[row] = []; + } + if (!data[row][col]) { + data[row][col] = ""; + } + if (char == '"' && inQuote && nextChar == '"') { + data[row][col] += char; + index++; + continue; + } + if (char == '"') { + inQuote = !inQuote; + continue; + } + if (char == "," && !inQuote) { + col++; + continue; + } + if (char == "\r" && nextChar == "\n" && !inQuote) { + col = 0; + row++; + index++; + continue; + } + if ((char == "\r" || char == "\n") && !inQuote) { + col = 0; + row++; + continue; + } + data[row][col] += char; + } + return data; + } + + function json(input2) { + try { + return JSON.parse(input2); + } catch (e) { + console.warn("JSON Import Error - File contents is invalid JSON", e); + return Promise.reject(); + } + } + + function array$1(input2) { + return input2; + } + + function xlsx(input2) { + var XLSXLib = this.dependencyRegistry.lookup("XLSX"), workbook2 = XLSXLib.read(input2), + sheet = workbook2.Sheets[workbook2.SheetNames[0]]; + return XLSXLib.utils.sheet_to_json(sheet, {header: 1}); + } + + var defaultImporters = { + csv, + json, + array: array$1, + xlsx + }; + const _Import = class _Import extends Module { + constructor(table) { + super(table); + this.registerTableOption("importFormat"); + this.registerTableOption("importReader", "text"); + this.registerTableOption("importHeaderTransform"); + this.registerTableOption("importValueTransform"); + this.registerTableOption("importDataValidator"); + this.registerTableOption("importFileValidator"); + } + + initialize() { + this.registerTableFunction("import", this.importFromFile.bind(this)); + if (this.table.options.importFormat) { + this.subscribe("data-loading", this.loadDataCheck.bind(this), 10); + this.subscribe("data-load", this.loadData.bind(this), 10); + } + } + + loadDataCheck(data) { + return this.table.options.importFormat && (typeof data === "string" || Array.isArray(data) && data.length && Array.isArray(data)); + } + + loadData(data, params, config, silent, previousData) { + return this.importData(this.lookupImporter(), data).then(this.structureData.bind(this)).catch((err) => { + console.error("Import Error:", err || "Unable to import data"); + return Promise.reject(err); + }); + } + + lookupImporter(importFormat) { + var importer; + if (!importFormat) { + importFormat = this.table.options.importFormat; + } + if (typeof importFormat === "string") { + importer = _Import.importers[importFormat]; + } else { + importer = importFormat; + } + if (!importer) { + console.error("Import Error - Importer not found:", importFormat); + } + return importer; + } + + importFromFile(importFormat, extension, importReader) { + var importer = this.lookupImporter(importFormat); + if (importer) { + return this.pickFile(extension, importReader).then(this.importData.bind(this, importer)).then(this.structureData.bind(this)).then(this.mutateData.bind(this)).then(this.validateData.bind(this)).then(this.setData.bind(this)).catch((err) => { + this.dispatch("import-error", err); + this.dispatchExternal("importError", err); + console.error("Import Error:", err || "Unable to import file"); + this.table.dataLoader.alertError(); + setTimeout(() => { + this.table.dataLoader.clearAlert(); + }, 3e3); + return Promise.reject(err); + }); + } + } + + pickFile(extensions2, importReader) { + return new Promise((resolve, reject) => { + var input2 = document.createElement("input"); + input2.type = "file"; + input2.accept = extensions2; + input2.addEventListener("change", (e) => { + var file = input2.files[0], reader = new FileReader(), valid = this.validateFile(file); + if (valid === true) { + this.dispatch("import-importing", input2.files); + this.dispatchExternal("importImporting", input2.files); + switch (importReader || this.table.options.importReader) { + case "buffer": + reader.readAsArrayBuffer(file); + break; + case "binary": + reader.readAsBinaryString(file); + break; + case "url": + reader.readAsDataURL(file); + break; + case "text": + default: + reader.readAsText(file); + } + reader.onload = (e2) => { + resolve(reader.result); + }; + reader.onerror = (e2) => { + console.warn("File Load Error - Unable to read file"); + reject(e2); + }; + } else { + reject(valid); + } + }); + this.dispatch("import-choose"); + this.dispatchExternal("importChoose"); + input2.click(); + }); + } + + importData(importer, fileContents) { + var data; + this.table.dataLoader.alertLoader(); + return new Promise((resolve, reject) => { + setTimeout(() => { + data = importer.call(this.table, fileContents); + if (data instanceof Promise) { + resolve(data); + } else { + data ? resolve(data) : reject(); + } + }, 10); + }); + } + + structureData(parsedData) { + var data = []; + if (Array.isArray(parsedData) && parsedData.length && Array.isArray(parsedData[0])) { + if (this.table.options.autoColumns) { + data = this.structureArrayToObject(parsedData); + } else { + data = this.structureArrayToColumns(parsedData); + } + return data; + } else { + return parsedData; + } + } + + mutateData(data) { + var output = []; + if (Array.isArray(data)) { + data.forEach((row) => { + output.push(this.table.modules.mutator.transformRow(row, "import")); + }); + } else { + output = data; + } + return output; + } + + transformHeader(headers) { + var output = []; + if (this.table.options.importHeaderTransform) { + headers.forEach((item) => { + output.push(this.table.options.importHeaderTransform.call(this.table, item, headers)); + }); + } else { + return headers; + } + return output; + } + + transformData(row) { + var output = []; + if (this.table.options.importValueTransform) { + row.forEach((item) => { + output.push(this.table.options.importValueTransform.call(this.table, item, row)); + }); + } else { + return row; + } + return output; + } + + structureArrayToObject(parsedData) { + var columns = this.transformHeader(parsedData.shift()); + var data = parsedData.map((values) => { + var row = {}; + values = this.transformData(values); + columns.forEach((key, i) => { + row[key] = values[i]; + }); + return row; + }); + return data; + } + + structureArrayToColumns(parsedData) { + var data = [], firstRow = this.transformHeader(parsedData[0]), columns = this.table.getColumns(); + if (columns[0] && firstRow[0]) { + if (columns[0].getDefinition().title === firstRow[0]) { + parsedData.shift(); + } + } + parsedData.forEach((rowData) => { + var row = {}; + rowData = this.transformData(rowData); + rowData.forEach((value, index) => { + var column = columns[index]; + if (column) { + row[column.getField()] = value; + } + }); + data.push(row); + }); + return data; + } + + validateFile(file) { + if (this.table.options.importFileValidator) { + return this.table.options.importFileValidator.call(this.table, file); + } + return true; + } + + validateData(data) { + var result; + if (this.table.options.importDataValidator) { + result = this.table.options.importDataValidator.call(this.table, data); + if (result === true) { + return data; + } else { + return Promise.reject(result); + } + } + return data; + } + + setData(data) { + this.dispatch("import-imported", data); + this.dispatchExternal("importImported", data); + this.table.dataLoader.clearAlert(); + return this.table.setData(data); + } + }; + __publicField(_Import, "moduleName", "import"); + //load defaults + __publicField(_Import, "importers", defaultImporters); + let Import = _Import; + + class Interaction extends Module { + constructor(table) { + super(table); + this.eventMap = { + //row events + rowClick: "row-click", + rowDblClick: "row-dblclick", + rowContext: "row-contextmenu", + rowMouseEnter: "row-mouseenter", + rowMouseLeave: "row-mouseleave", + rowMouseOver: "row-mouseover", + rowMouseOut: "row-mouseout", + rowMouseMove: "row-mousemove", + rowMouseDown: "row-mousedown", + rowMouseUp: "row-mouseup", + rowTap: "row", + rowDblTap: "row", + rowTapHold: "row", + //cell events + cellClick: "cell-click", + cellDblClick: "cell-dblclick", + cellContext: "cell-contextmenu", + cellMouseEnter: "cell-mouseenter", + cellMouseLeave: "cell-mouseleave", + cellMouseOver: "cell-mouseover", + cellMouseOut: "cell-mouseout", + cellMouseMove: "cell-mousemove", + cellMouseDown: "cell-mousedown", + cellMouseUp: "cell-mouseup", + cellTap: "cell", + cellDblTap: "cell", + cellTapHold: "cell", + //column header events + headerClick: "column-click", + headerDblClick: "column-dblclick", + headerContext: "column-contextmenu", + headerMouseEnter: "column-mouseenter", + headerMouseLeave: "column-mouseleave", + headerMouseOver: "column-mouseover", + headerMouseOut: "column-mouseout", + headerMouseMove: "column-mousemove", + headerMouseDown: "column-mousedown", + headerMouseUp: "column-mouseup", + headerTap: "column", + headerDblTap: "column", + headerTapHold: "column", + //group header + groupClick: "group-click", + groupDblClick: "group-dblclick", + groupContext: "group-contextmenu", + groupMouseEnter: "group-mouseenter", + groupMouseLeave: "group-mouseleave", + groupMouseOver: "group-mouseover", + groupMouseOut: "group-mouseout", + groupMouseMove: "group-mousemove", + groupMouseDown: "group-mousedown", + groupMouseUp: "group-mouseup", + groupTap: "group", + groupDblTap: "group", + groupTapHold: "group" + }; + this.subscribers = {}; + this.touchSubscribers = {}; + this.columnSubscribers = {}; + this.touchWatchers = { + row: { + tap: null, + tapDbl: null, + tapHold: null + }, + cell: { + tap: null, + tapDbl: null, + tapHold: null + }, + column: { + tap: null, + tapDbl: null, + tapHold: null + }, + group: { + tap: null, + tapDbl: null, + tapHold: null + } + }; + this.registerColumnOption("headerClick"); + this.registerColumnOption("headerDblClick"); + this.registerColumnOption("headerContext"); + this.registerColumnOption("headerMouseEnter"); + this.registerColumnOption("headerMouseLeave"); + this.registerColumnOption("headerMouseOver"); + this.registerColumnOption("headerMouseOut"); + this.registerColumnOption("headerMouseMove"); + this.registerColumnOption("headerMouseDown"); + this.registerColumnOption("headerMouseUp"); + this.registerColumnOption("headerTap"); + this.registerColumnOption("headerDblTap"); + this.registerColumnOption("headerTapHold"); + this.registerColumnOption("cellClick"); + this.registerColumnOption("cellDblClick"); + this.registerColumnOption("cellContext"); + this.registerColumnOption("cellMouseEnter"); + this.registerColumnOption("cellMouseLeave"); + this.registerColumnOption("cellMouseOver"); + this.registerColumnOption("cellMouseOut"); + this.registerColumnOption("cellMouseMove"); + this.registerColumnOption("cellMouseDown"); + this.registerColumnOption("cellMouseUp"); + this.registerColumnOption("cellTap"); + this.registerColumnOption("cellDblTap"); + this.registerColumnOption("cellTapHold"); + } + + initialize() { + this.initializeExternalEvents(); + this.subscribe("column-init", this.initializeColumn.bind(this)); + this.subscribe("cell-dblclick", this.cellContentsSelectionFixer.bind(this)); + this.subscribe("scroll-horizontal", this.clearTouchWatchers.bind(this)); + this.subscribe("scroll-vertical", this.clearTouchWatchers.bind(this)); + } + + clearTouchWatchers() { + var types = Object.values(this.touchWatchers); + types.forEach((type) => { + clearTimeout(type.tapDbl); + clearTimeout(type.tapHold); + for (let key in type) { + type[key] = null; + } + }); + } + + cellContentsSelectionFixer(e, cell) { + var range2; + if (this.table.modExists("edit")) { + if (this.table.modules.edit.currentCell === cell) { + return; + } + } + e.preventDefault(); + try { + if (document.selection) { + range2 = document.body.createTextRange(); + range2.moveToElementText(cell.getElement()); + range2.select(); + } else if (window.getSelection) { + range2 = document.createRange(); + range2.selectNode(cell.getElement()); + window.getSelection().removeAllRanges(); + window.getSelection().addRange(range2); + } + } catch (e2) { + } + } + + initializeExternalEvents() { + for (let key in this.eventMap) { + this.subscriptionChangeExternal(key, this.subscriptionChanged.bind(this, key)); + } + } + + subscriptionChanged(key, added) { + if (added) { + if (!this.subscribers[key]) { + if (this.eventMap[key].includes("-")) { + this.subscribers[key] = this.handle.bind(this, key); + this.subscribe(this.eventMap[key], this.subscribers[key]); + } else { + this.subscribeTouchEvents(key); + } + } + } else { + if (this.eventMap[key].includes("-")) { + if (this.subscribers[key] && !this.columnSubscribers[key] && !this.subscribedExternal(key)) { + this.unsubscribe(this.eventMap[key], this.subscribers[key]); + delete this.subscribers[key]; + } + } else { + this.unsubscribeTouchEvents(key); + } + } + } + + subscribeTouchEvents(key) { + var type = this.eventMap[key]; + if (!this.touchSubscribers[type + "-touchstart"]) { + this.touchSubscribers[type + "-touchstart"] = this.handleTouch.bind(this, type, "start"); + this.touchSubscribers[type + "-touchend"] = this.handleTouch.bind(this, type, "end"); + this.subscribe(type + "-touchstart", this.touchSubscribers[type + "-touchstart"]); + this.subscribe(type + "-touchend", this.touchSubscribers[type + "-touchend"]); + } + this.subscribers[key] = true; + } + + unsubscribeTouchEvents(key) { + var noTouch = true, type = this.eventMap[key]; + if (this.subscribers[key] && !this.subscribedExternal(key)) { + delete this.subscribers[key]; + for (let i in this.eventMap) { + if (this.eventMap[i] === type) { + if (this.subscribers[i]) { + noTouch = false; + } + } + } + if (noTouch) { + this.unsubscribe(type + "-touchstart", this.touchSubscribers[type + "-touchstart"]); + this.unsubscribe(type + "-touchend", this.touchSubscribers[type + "-touchend"]); + delete this.touchSubscribers[type + "-touchstart"]; + delete this.touchSubscribers[type + "-touchend"]; + } + } + } + + initializeColumn(column) { + var def = column.definition; + for (let key in this.eventMap) { + if (def[key]) { + this.subscriptionChanged(key, true); + if (!this.columnSubscribers[key]) { + this.columnSubscribers[key] = []; + } + this.columnSubscribers[key].push(column); + } + } + } + + handle(action, e, component) { + this.dispatchEvent(action, e, component); + } + + handleTouch(type, action, e, component) { + var watchers = this.touchWatchers[type]; + if (type === "column") { + type = "header"; + } + switch (action) { + case "start": + watchers.tap = true; + clearTimeout(watchers.tapHold); + watchers.tapHold = setTimeout(() => { + clearTimeout(watchers.tapHold); + watchers.tapHold = null; + watchers.tap = null; + clearTimeout(watchers.tapDbl); + watchers.tapDbl = null; + this.dispatchEvent(type + "TapHold", e, component); + }, 1e3); + break; + case "end": + if (watchers.tap) { + watchers.tap = null; + this.dispatchEvent(type + "Tap", e, component); + } + if (watchers.tapDbl) { + clearTimeout(watchers.tapDbl); + watchers.tapDbl = null; + this.dispatchEvent(type + "DblTap", e, component); + } else { + watchers.tapDbl = setTimeout(() => { + clearTimeout(watchers.tapDbl); + watchers.tapDbl = null; + }, 300); + } + clearTimeout(watchers.tapHold); + watchers.tapHold = null; + break; + } + } + + dispatchEvent(action, e, component) { + var componentObj = component.getComponent(), callback; + if (this.columnSubscribers[action]) { + if (component instanceof Cell) { + callback = component.column.definition[action]; + } else if (component instanceof Column) { + callback = component.definition[action]; + } + if (callback) { + callback(e, componentObj); + } + } + this.dispatchExternal(action, e, componentObj); + } + } + + __publicField(Interaction, "moduleName", "interaction"); + var defaultBindings = { + navPrev: "shift + 9", + navNext: 9, + navUp: 38, + navDown: 40, + navLeft: 37, + navRight: 39, + scrollPageUp: 33, + scrollPageDown: 34, + scrollToStart: 36, + scrollToEnd: 35 + }; + var defaultActions = { + keyBlock: function (e) { + e.stopPropagation(); + e.preventDefault(); + }, + scrollPageUp: function (e) { + var rowManager = this.table.rowManager, newPos = rowManager.scrollTop - rowManager.element.clientHeight; + e.preventDefault(); + if (rowManager.displayRowsCount) { + if (newPos >= 0) { + rowManager.element.scrollTop = newPos; + } else { + rowManager.scrollToRow(rowManager.getDisplayRows()[0]); + } + } + this.table.element.focus(); + }, + scrollPageDown: function (e) { + var rowManager = this.table.rowManager, newPos = rowManager.scrollTop + rowManager.element.clientHeight, + scrollMax = rowManager.element.scrollHeight; + e.preventDefault(); + if (rowManager.displayRowsCount) { + if (newPos <= scrollMax) { + rowManager.element.scrollTop = newPos; + } else { + rowManager.scrollToRow(rowManager.getDisplayRows()[rowManager.displayRowsCount - 1]); + } + } + this.table.element.focus(); + }, + scrollToStart: function (e) { + var rowManager = this.table.rowManager; + e.preventDefault(); + if (rowManager.displayRowsCount) { + rowManager.scrollToRow(rowManager.getDisplayRows()[0]); + } + this.table.element.focus(); + }, + scrollToEnd: function (e) { + var rowManager = this.table.rowManager; + e.preventDefault(); + if (rowManager.displayRowsCount) { + rowManager.scrollToRow(rowManager.getDisplayRows()[rowManager.displayRowsCount - 1]); + } + this.table.element.focus(); + }, + navPrev: function (e) { + this.dispatch("keybinding-nav-prev", e); + }, + navNext: function (e) { + this.dispatch("keybinding-nav-next", e); + }, + navLeft: function (e) { + this.dispatch("keybinding-nav-left", e); + }, + navRight: function (e) { + this.dispatch("keybinding-nav-right", e); + }, + navUp: function (e) { + this.dispatch("keybinding-nav-up", e); + }, + navDown: function (e) { + this.dispatch("keybinding-nav-down", e); + } + }; + const _Keybindings = class _Keybindings extends Module { + constructor(table) { + super(table); + this.watchKeys = null; + this.pressedKeys = null; + this.keyupBinding = false; + this.keydownBinding = false; + this.registerTableOption("keybindings", {}); + this.registerTableOption("tabEndNewRow", false); + } + + initialize() { + var bindings2 = this.table.options.keybindings, mergedBindings = {}; + this.watchKeys = {}; + this.pressedKeys = []; + if (bindings2 !== false) { + Object.assign(mergedBindings, _Keybindings.bindings); + Object.assign(mergedBindings, bindings2); + this.mapBindings(mergedBindings); + this.bindEvents(); + } + this.subscribe("table-destroy", this.clearBindings.bind(this)); + } + + mapBindings(bindings2) { + for (let key in bindings2) { + if (_Keybindings.actions[key]) { + if (bindings2[key]) { + if (typeof bindings2[key] !== "object") { + bindings2[key] = [bindings2[key]]; + } + bindings2[key].forEach((binding) => { + var bindingList = Array.isArray(binding) ? binding : [binding]; + bindingList.forEach((item) => { + this.mapBinding(key, item); + }); + }); + } + } else { + console.warn("Key Binding Error - no such action:", key); + } + } + } + + getKeyCode(e) { + if (e.key.length === 1) { + return e.key.toUpperCase().charCodeAt(0); + } + var specialKeys = { + "Enter": 13, + "Escape": 27, + "Tab": 9, + "Backspace": 8, + "Delete": 46, + "ArrowUp": 38, + "ArrowDown": 40, + "ArrowLeft": 37, + "ArrowRight": 39, + "Home": 36, + "End": 35, + "PageUp": 33, + "PageDown": 34, + "Insert": 45 + }; + return specialKeys[e.key] || e.keyCode || 0; + } + + mapBinding(action, symbolsList) { + var binding = { + action: _Keybindings.actions[action], + keys: [], + ctrl: false, + shift: false, + meta: false + }; + var symbols = symbolsList.toString().toLowerCase().split(" ").join("").split("+"); + symbols.forEach((symbol) => { + switch (symbol) { + case "ctrl": + binding.ctrl = true; + break; + case "shift": + binding.shift = true; + break; + case "meta": + binding.meta = true; + break; + default: + symbol = isNaN(symbol) ? symbol.toUpperCase().charCodeAt(0) : parseInt(symbol); + binding.keys.push(symbol); + if (!this.watchKeys[symbol]) { + this.watchKeys[symbol] = []; + } + this.watchKeys[symbol].push(binding); + } + }); + } + + bindEvents() { + var self = this; + this.keyupBinding = function (e) { + var code = self.getKeyCode(e); + var bindings2 = self.watchKeys[code]; + if (bindings2) { + self.pressedKeys.push(code); + bindings2.forEach(function (binding) { + self.checkBinding(e, binding); + }); + } + }; + this.keydownBinding = function (e) { + var code = self.getKeyCode(e); + var bindings2 = self.watchKeys[code]; + if (bindings2) { + var index = self.pressedKeys.indexOf(code); + if (index > -1) { + self.pressedKeys.splice(index, 1); + } + } + }; + this.table.element.addEventListener("keydown", this.keyupBinding); + this.table.element.addEventListener("keyup", this.keydownBinding); + } + + clearBindings() { + if (this.keyupBinding) { + this.table.element.removeEventListener("keydown", this.keyupBinding); + } + if (this.keydownBinding) { + this.table.element.removeEventListener("keyup", this.keydownBinding); + } + } + + checkBinding(e, binding) { + var match = true; + if (e.ctrlKey == binding.ctrl && e.shiftKey == binding.shift && e.metaKey == binding.meta) { + binding.keys.forEach((key) => { + var index = this.pressedKeys.indexOf(key); + if (index == -1) { + match = false; + } + }); + if (match) { + binding.action.call(this, e); + } + return true; + } + return false; + } + }; + __publicField(_Keybindings, "moduleName", "keybindings"); + //load defaults + __publicField(_Keybindings, "bindings", defaultBindings); + __publicField(_Keybindings, "actions", defaultActions); + let Keybindings = _Keybindings; + + class Menu extends Module { + constructor(table) { + super(table); + this.menuContainer = null; + this.nestedMenuBlock = false; + this.currentComponent = null; + this.rootPopup = null; + this.columnSubscribers = {}; + this.registerTableOption("rowContextMenu", false); + this.registerTableOption("rowClickMenu", false); + this.registerTableOption("rowDblClickMenu", false); + this.registerTableOption("groupContextMenu", false); + this.registerTableOption("groupClickMenu", false); + this.registerTableOption("groupDblClickMenu", false); + this.registerColumnOption("headerContextMenu"); + this.registerColumnOption("headerClickMenu"); + this.registerColumnOption("headerDblClickMenu"); + this.registerColumnOption("headerMenu"); + this.registerColumnOption("headerMenuIcon"); + this.registerColumnOption("contextMenu"); + this.registerColumnOption("clickMenu"); + this.registerColumnOption("dblClickMenu"); + } + + initialize() { + this.deprecatedOptionsCheck(); + this.initializeRowWatchers(); + this.initializeGroupWatchers(); + this.subscribe("column-init", this.initializeColumn.bind(this)); + } + + deprecatedOptionsCheck() { + } + + initializeRowWatchers() { + if (this.table.options.rowContextMenu) { + this.subscribe("row-contextmenu", this.loadMenuEvent.bind(this, this.table.options.rowContextMenu)); + this.table.on("rowTapHold", this.loadMenuEvent.bind(this, this.table.options.rowContextMenu)); + } + if (this.table.options.rowClickMenu) { + this.subscribe("row-click", this.loadMenuEvent.bind(this, this.table.options.rowClickMenu)); + } + if (this.table.options.rowDblClickMenu) { + this.subscribe("row-dblclick", this.loadMenuEvent.bind(this, this.table.options.rowDblClickMenu)); + } + } + + initializeGroupWatchers() { + if (this.table.options.groupContextMenu) { + this.subscribe("group-contextmenu", this.loadMenuEvent.bind(this, this.table.options.groupContextMenu)); + this.table.on("groupTapHold", this.loadMenuEvent.bind(this, this.table.options.groupContextMenu)); + } + if (this.table.options.groupClickMenu) { + this.subscribe("group-click", this.loadMenuEvent.bind(this, this.table.options.groupClickMenu)); + } + if (this.table.options.groupDblClickMenu) { + this.subscribe("group-dblclick", this.loadMenuEvent.bind(this, this.table.options.groupDblClickMenu)); + } + } + + initializeColumn(column) { + var def = column.definition; + if (def.headerContextMenu && !this.columnSubscribers.headerContextMenu) { + this.columnSubscribers.headerContextMenu = this.loadMenuTableColumnEvent.bind(this, "headerContextMenu"); + this.subscribe("column-contextmenu", this.columnSubscribers.headerContextMenu); + this.table.on("headerTapHold", this.loadMenuTableColumnEvent.bind(this, "headerContextMenu")); + } + if (def.headerClickMenu && !this.columnSubscribers.headerClickMenu) { + this.columnSubscribers.headerClickMenu = this.loadMenuTableColumnEvent.bind(this, "headerClickMenu"); + this.subscribe("column-click", this.columnSubscribers.headerClickMenu); + } + if (def.headerDblClickMenu && !this.columnSubscribers.headerDblClickMenu) { + this.columnSubscribers.headerDblClickMenu = this.loadMenuTableColumnEvent.bind(this, "headerDblClickMenu"); + this.subscribe("column-dblclick", this.columnSubscribers.headerDblClickMenu); + } + if (def.headerMenu) { + this.initializeColumnHeaderMenu(column); + } + if (def.contextMenu && !this.columnSubscribers.contextMenu) { + this.columnSubscribers.contextMenu = this.loadMenuTableCellEvent.bind(this, "contextMenu"); + this.subscribe("cell-contextmenu", this.columnSubscribers.contextMenu); + this.table.on("cellTapHold", this.loadMenuTableCellEvent.bind(this, "contextMenu")); + } + if (def.clickMenu && !this.columnSubscribers.clickMenu) { + this.columnSubscribers.clickMenu = this.loadMenuTableCellEvent.bind(this, "clickMenu"); + this.subscribe("cell-click", this.columnSubscribers.clickMenu); + } + if (def.dblClickMenu && !this.columnSubscribers.dblClickMenu) { + this.columnSubscribers.dblClickMenu = this.loadMenuTableCellEvent.bind(this, "dblClickMenu"); + this.subscribe("cell-dblclick", this.columnSubscribers.dblClickMenu); + } + } + + initializeColumnHeaderMenu(column) { + var icon = column.definition.headerMenuIcon, headerMenuEl; + headerMenuEl = document.createElement("span"); + headerMenuEl.classList.add("tabulator-header-popup-button"); + if (icon) { + if (typeof icon === "function") { + icon = icon(column.getComponent()); + } + if (icon instanceof HTMLElement) { + headerMenuEl.appendChild(icon); + } else { + headerMenuEl.innerHTML = icon; + } + } else { + headerMenuEl.innerHTML = "⋮"; + } + headerMenuEl.addEventListener("click", (e) => { + e.stopPropagation(); + e.preventDefault(); + this.loadMenuEvent(column.definition.headerMenu, e, column); + }); + column.titleElement.insertBefore(headerMenuEl, column.titleElement.firstChild); + } + + loadMenuTableCellEvent(option, e, cell) { + if (cell._cell) { + cell = cell._cell; + } + if (cell.column.definition[option]) { + this.loadMenuEvent(cell.column.definition[option], e, cell); + } + } + + loadMenuTableColumnEvent(option, e, column) { + if (column._column) { + column = column._column; + } + if (column.definition[option]) { + this.loadMenuEvent(column.definition[option], e, column); + } + } + + loadMenuEvent(menu, e, component) { + if (component._group) { + component = component._group; + } else if (component._row) { + component = component._row; + } + menu = typeof menu == "function" ? menu.call(this.table, e, component.getComponent()) : menu; + this.loadMenu(e, component, menu); + } + + loadMenu(e, component, menu, parentEl, parentPopup) { + var touch = !(e instanceof MouseEvent), menuEl = document.createElement("div"), popup; + menuEl.classList.add("tabulator-menu"); + if (!touch) { + e.preventDefault(); + } + if (!menu || !menu.length) { + return; + } + if (!parentEl) { + if (this.nestedMenuBlock) { + if (this.rootPopup) { + return; + } + } else { + this.nestedMenuBlock = setTimeout(() => { + this.nestedMenuBlock = false; + }, 100); + } + if (this.rootPopup) { + this.rootPopup.hide(); + } + this.rootPopup = popup = this.popup(menuEl); + } else { + popup = parentPopup.child(menuEl); + } + menu.forEach((item) => { + var itemEl = document.createElement("div"), label = item.label, disabled = item.disabled; + if (item.separator) { + itemEl.classList.add("tabulator-menu-separator"); + } else { + itemEl.classList.add("tabulator-menu-item"); + if (typeof label == "function") { + label = label.call(this.table, component.getComponent()); + } + if (label instanceof Node) { + itemEl.appendChild(label); + } else { + itemEl.innerHTML = label; + } + if (typeof disabled == "function") { + disabled = disabled.call(this.table, component.getComponent()); + } + if (disabled) { + itemEl.classList.add("tabulator-menu-item-disabled"); + itemEl.addEventListener("click", (e2) => { + e2.stopPropagation(); + }); + } else { + if (item.menu && item.menu.length) { + itemEl.addEventListener("click", (e2) => { + e2.stopPropagation(); + this.loadMenu(e2, component, item.menu, itemEl, popup); + }); + } else { + if (item.action) { + itemEl.addEventListener("click", (e2) => { + item.action(e2, component.getComponent()); + }); + } + } + } + if (item.menu && item.menu.length) { + itemEl.classList.add("tabulator-menu-item-submenu"); + } + } + menuEl.appendChild(itemEl); + }); + menuEl.addEventListener("click", (e2) => { + if (this.rootPopup) { + this.rootPopup.hide(); + } + }); + popup.show(parentEl || e); + if (popup === this.rootPopup) { + this.rootPopup.hideOnBlur(() => { + this.rootPopup = null; + if (this.currentComponent) { + this.dispatch("menu-closed", menu, popup); + this.dispatchExternal("menuClosed", this.currentComponent.getComponent()); + this.currentComponent = null; + } + }); + this.currentComponent = component; + this.dispatch("menu-opened", menu, popup); + this.dispatchExternal("menuOpened", component.getComponent()); + } + } + } + + __publicField(Menu, "moduleName", "menu"); + + class MoveColumns extends Module { + constructor(table) { + super(table); + this.placeholderElement = this.createPlaceholderElement(); + this.hoverElement = false; + this.checkTimeout = false; + this.checkPeriod = 250; + this.moving = false; + this.toCol = false; + this.toColAfter = false; + this.startX = 0; + this.autoScrollMargin = 40; + this.autoScrollStep = 5; + this.autoScrollTimeout = false; + this.touchMove = false; + this.moveHover = this.moveHover.bind(this); + this.endMove = this.endMove.bind(this); + this.registerTableOption("movableColumns", false); + } + + createPlaceholderElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-col"); + el.classList.add("tabulator-col-placeholder"); + return el; + } + + initialize() { + if (this.table.options.movableColumns) { + this.subscribe("column-init", this.initializeColumn.bind(this)); + this.subscribe("alert-show", this.abortMove.bind(this)); + } + } + + abortMove() { + clearTimeout(this.checkTimeout); + } + + initializeColumn(column) { + var self = this, config = {}, colEl; + if (!column.modules.frozen && !column.isGroup && !column.isRowHeader) { + colEl = column.getElement(); + config.mousemove = (function (e) { + if (column.parent === self.moving.parent) { + if ((self.touchMove ? e.touches[0].pageX : e.pageX) - Helpers.elOffset(colEl).left + self.table.columnManager.contentsElement.scrollLeft > column.getWidth() / 2) { + if (self.toCol !== column || !self.toColAfter) { + colEl.parentNode.insertBefore(self.placeholderElement, colEl.nextSibling); + self.moveColumn(column, true); + } + } else { + if (self.toCol !== column || self.toColAfter) { + colEl.parentNode.insertBefore(self.placeholderElement, colEl); + self.moveColumn(column, false); + } + } + } + }).bind(self); + colEl.addEventListener("mousedown", function (e) { + self.touchMove = false; + if (e.which === 1) { + self.checkTimeout = setTimeout(function () { + self.startMove(e, column); + }, self.checkPeriod); + } + }); + colEl.addEventListener("mouseup", function (e) { + if (e.which === 1) { + if (self.checkTimeout) { + clearTimeout(self.checkTimeout); + } + } + }); + self.bindTouchEvents(column); + } + column.modules.moveColumn = config; + } + + bindTouchEvents(column) { + var colEl = column.getElement(), startXMove = false, nextCol, prevCol, nextColWidth, prevColWidth, + nextColWidthLast, prevColWidthLast; + colEl.addEventListener("touchstart", (e) => { + this.checkTimeout = setTimeout(() => { + this.touchMove = true; + nextCol = column.nextColumn(); + nextColWidth = nextCol ? nextCol.getWidth() / 2 : 0; + prevCol = column.prevColumn(); + prevColWidth = prevCol ? prevCol.getWidth() / 2 : 0; + nextColWidthLast = 0; + prevColWidthLast = 0; + startXMove = false; + this.startMove(e, column); + }, this.checkPeriod); + }, {passive: true}); + colEl.addEventListener("touchmove", (e) => { + var diff, moveToCol; + if (this.moving) { + this.moveHover(e); + if (!startXMove) { + startXMove = e.touches[0].pageX; + } + diff = e.touches[0].pageX - startXMove; + if (diff > 0) { + if (nextCol && diff - nextColWidthLast > nextColWidth) { + moveToCol = nextCol; + if (moveToCol !== column) { + startXMove = e.touches[0].pageX; + moveToCol.getElement().parentNode.insertBefore(this.placeholderElement, moveToCol.getElement().nextSibling); + this.moveColumn(moveToCol, true); + } + } + } else { + if (prevCol && -diff - prevColWidthLast > prevColWidth) { + moveToCol = prevCol; + if (moveToCol !== column) { + startXMove = e.touches[0].pageX; + moveToCol.getElement().parentNode.insertBefore(this.placeholderElement, moveToCol.getElement()); + this.moveColumn(moveToCol, false); + } + } + } + if (moveToCol) { + nextCol = moveToCol.nextColumn(); + nextColWidthLast = nextColWidth; + nextColWidth = nextCol ? nextCol.getWidth() / 2 : 0; + prevCol = moveToCol.prevColumn(); + prevColWidthLast = prevColWidth; + prevColWidth = prevCol ? prevCol.getWidth() / 2 : 0; + } + } + }, {passive: true}); + colEl.addEventListener("touchend", (e) => { + if (this.checkTimeout) { + clearTimeout(this.checkTimeout); + } + if (this.moving) { + this.endMove(e); + } + }); + } + + startMove(e, column) { + var element = column.getElement(), headerElement = this.table.columnManager.getContentsElement(), + headersElement = this.table.columnManager.getHeadersElement(); + if (this.table.modules.selectRange && this.table.modules.selectRange.columnSelection) { + if (this.table.modules.selectRange.mousedown && this.table.modules.selectRange.selecting === "column") { + return; + } + } + this.moving = column; + this.startX = (this.touchMove ? e.touches[0].pageX : e.pageX) - Helpers.elOffset(element).left; + this.table.element.classList.add("tabulator-block-select"); + this.placeholderElement.style.width = column.getWidth() + "px"; + this.placeholderElement.style.height = column.getHeight() + "px"; + element.parentNode.insertBefore(this.placeholderElement, element); + element.parentNode.removeChild(element); + this.hoverElement = element.cloneNode(true); + this.hoverElement.classList.add("tabulator-moving"); + headerElement.appendChild(this.hoverElement); + this.hoverElement.style.left = "0"; + this.hoverElement.style.bottom = headerElement.clientHeight - headersElement.offsetHeight + "px"; + if (!this.touchMove) { + this._bindMouseMove(); + document.body.addEventListener("mousemove", this.moveHover); + document.body.addEventListener("mouseup", this.endMove); + } + this.moveHover(e); + this.dispatch("column-moving", e, this.moving); + } + + _bindMouseMove() { + this.table.columnManager.columnsByIndex.forEach(function (column) { + if (column.modules.moveColumn.mousemove) { + column.getElement().addEventListener("mousemove", column.modules.moveColumn.mousemove); + } + }); + } + + _unbindMouseMove() { + this.table.columnManager.columnsByIndex.forEach(function (column) { + if (column.modules.moveColumn.mousemove) { + column.getElement().removeEventListener("mousemove", column.modules.moveColumn.mousemove); + } + }); + } + + moveColumn(column, after) { + var movingCells = this.moving.getCells(); + this.toCol = column; + this.toColAfter = after; + if (after) { + column.getCells().forEach(function (cell, i) { + var cellEl = cell.getElement(true); + if (cellEl.parentNode && movingCells[i]) { + cellEl.parentNode.insertBefore(movingCells[i].getElement(), cellEl.nextSibling); + } + }); + } else { + column.getCells().forEach(function (cell, i) { + var cellEl = cell.getElement(true); + if (cellEl.parentNode && movingCells[i]) { + cellEl.parentNode.insertBefore(movingCells[i].getElement(), cellEl); + } + }); + } + } + + endMove(e) { + if (e.which === 1 || this.touchMove) { + this._unbindMouseMove(); + this.placeholderElement.parentNode.insertBefore(this.moving.getElement(), this.placeholderElement.nextSibling); + this.placeholderElement.parentNode.removeChild(this.placeholderElement); + this.hoverElement.parentNode.removeChild(this.hoverElement); + this.table.element.classList.remove("tabulator-block-select"); + if (this.toCol) { + this.table.columnManager.moveColumnActual(this.moving, this.toCol, this.toColAfter); + } + this.moving = false; + this.toCol = false; + this.toColAfter = false; + if (!this.touchMove) { + document.body.removeEventListener("mousemove", this.moveHover); + document.body.removeEventListener("mouseup", this.endMove); + } + } + } + + moveHover(e) { + var columnHolder = this.table.columnManager.getContentsElement(), scrollLeft = columnHolder.scrollLeft, + xPos = (this.touchMove ? e.touches[0].pageX : e.pageX) - Helpers.elOffset(columnHolder).left + scrollLeft, + scrollPos; + this.hoverElement.style.left = xPos - this.startX + "px"; + if (xPos - scrollLeft < this.autoScrollMargin) { + if (!this.autoScrollTimeout) { + this.autoScrollTimeout = setTimeout(() => { + scrollPos = Math.max(0, scrollLeft - 5); + this.table.rowManager.getElement().scrollLeft = scrollPos; + this.autoScrollTimeout = false; + }, 1); + } + } + if (scrollLeft + columnHolder.clientWidth - xPos < this.autoScrollMargin) { + if (!this.autoScrollTimeout) { + this.autoScrollTimeout = setTimeout(() => { + scrollPos = Math.min(columnHolder.clientWidth, scrollLeft + 5); + this.table.rowManager.getElement().scrollLeft = scrollPos; + this.autoScrollTimeout = false; + }, 1); + } + } + } + } + + __publicField(MoveColumns, "moduleName", "moveColumn"); + var defaultSenders = { + delete: function (fromRow, toRow, toTable) { + fromRow.delete(); + } + }; + var defaultReceivers = { + insert: function (fromRow, toRow, fromTable) { + this.table.addRow(fromRow.getData(), void 0, toRow); + return true; + }, + add: function (fromRow, toRow, fromTable) { + this.table.addRow(fromRow.getData()); + return true; + }, + update: function (fromRow, toRow, fromTable) { + if (toRow) { + toRow.update(fromRow.getData()); + return true; + } + return false; + }, + replace: function (fromRow, toRow, fromTable) { + if (toRow) { + this.table.addRow(fromRow.getData(), void 0, toRow); + toRow.delete(); + return true; + } + return false; + } + }; + const _MoveRows = class _MoveRows extends Module { + constructor(table) { + super(table); + this.placeholderElement = this.createPlaceholderElement(); + this.hoverElement = false; + this.checkTimeout = false; + this.checkPeriod = 150; + this.moving = false; + this.toRow = false; + this.toRowAfter = false; + this.hasHandle = false; + this.startY = 0; + this.startX = 0; + this.moveHover = this.moveHover.bind(this); + this.endMove = this.endMove.bind(this); + this.tableRowDropEvent = false; + this.touchMove = false; + this.connection = false; + this.connectionSelectorsTables = false; + this.connectionSelectorsElements = false; + this.connectionElements = []; + this.connections = []; + this.connectedTable = false; + this.connectedRow = false; + this.registerTableOption("movableRows", false); + this.registerTableOption("movableRowsConnectedTables", false); + this.registerTableOption("movableRowsConnectedElements", false); + this.registerTableOption("movableRowsSender", false); + this.registerTableOption("movableRowsReceiver", "insert"); + this.registerColumnOption("rowHandle"); + } + + createPlaceholderElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-row"); + el.classList.add("tabulator-row-placeholder"); + return el; + } + + initialize() { + if (this.table.options.movableRows) { + this.connectionSelectorsTables = this.table.options.movableRowsConnectedTables; + this.connectionSelectorsElements = this.table.options.movableRowsConnectedElements; + this.connection = this.connectionSelectorsTables || this.connectionSelectorsElements; + this.subscribe("cell-init", this.initializeCell.bind(this)); + this.subscribe("column-init", this.initializeColumn.bind(this)); + this.subscribe("row-init", this.initializeRow.bind(this)); + } + } + + initializeGroupHeader(group) { + var self = this, config = {}; + config.mouseup = (function (e) { + self.tableRowDrop(e, group); + }).bind(self); + config.mousemove = (function (e) { + var rowEl; + if (e.pageY - Helpers.elOffset(group.element).top + self.table.rowManager.element.scrollTop > group.getHeight() / 2) { + if (self.toRow !== group || !self.toRowAfter) { + rowEl = group.getElement(); + rowEl.parentNode.insertBefore(self.placeholderElement, rowEl.nextSibling); + self.moveRow(group, true); + } + } else { + if (self.toRow !== group || self.toRowAfter) { + rowEl = group.getElement(); + if (rowEl.previousSibling) { + rowEl.parentNode.insertBefore(self.placeholderElement, rowEl); + self.moveRow(group, false); + } + } + } + }).bind(self); + group.modules.moveRow = config; + } + + initializeRow(row) { + var self = this, config = {}, rowEl; + config.mouseup = (function (e) { + self.tableRowDrop(e, row); + }).bind(self); + config.mousemove = (function (e) { + var rowEl2 = row.getElement(); + if (e.pageY - Helpers.elOffset(rowEl2).top + self.table.rowManager.element.scrollTop > row.getHeight() / 2) { + if (self.toRow !== row || !self.toRowAfter) { + rowEl2.parentNode.insertBefore(self.placeholderElement, rowEl2.nextSibling); + self.moveRow(row, true); + } + } else { + if (self.toRow !== row || self.toRowAfter) { + rowEl2.parentNode.insertBefore(self.placeholderElement, rowEl2); + self.moveRow(row, false); + } + } + }).bind(self); + if (!this.hasHandle) { + rowEl = row.getElement(); + rowEl.addEventListener("mousedown", function (e) { + if (e.which === 1) { + self.checkTimeout = setTimeout(function () { + self.startMove(e, row); + }, self.checkPeriod); + } + }); + rowEl.addEventListener("mouseup", function (e) { + if (e.which === 1) { + if (self.checkTimeout) { + clearTimeout(self.checkTimeout); + } + } + }); + this.bindTouchEvents(row, row.getElement()); + } + row.modules.moveRow = config; + } + + initializeColumn(column) { + if (column.definition.rowHandle && this.table.options.movableRows !== false) { + this.hasHandle = true; + } + } + + initializeCell(cell) { + if (cell.column.definition.rowHandle && this.table.options.movableRows !== false) { + var self = this, cellEl = cell.getElement(true); + cellEl.addEventListener("mousedown", function (e) { + if (e.which === 1) { + self.checkTimeout = setTimeout(function () { + self.startMove(e, cell.row); + }, self.checkPeriod); + } + }); + cellEl.addEventListener("mouseup", function (e) { + if (e.which === 1) { + if (self.checkTimeout) { + clearTimeout(self.checkTimeout); + } + } + }); + this.bindTouchEvents(cell.row, cellEl); + } + } + + bindTouchEvents(row, element) { + var startYMove = false, nextRow, prevRow, nextRowHeight, prevRowHeight, nextRowHeightLast, + prevRowHeightLast; + element.addEventListener("touchstart", (e) => { + this.checkTimeout = setTimeout(() => { + this.touchMove = true; + nextRow = row.nextRow(); + nextRowHeight = nextRow ? nextRow.getHeight() / 2 : 0; + prevRow = row.prevRow(); + prevRowHeight = prevRow ? prevRow.getHeight() / 2 : 0; + nextRowHeightLast = 0; + prevRowHeightLast = 0; + startYMove = false; + this.startMove(e, row); + }, this.checkPeriod); + }, {passive: true}); + this.moving, this.toRow, this.toRowAfter; + element.addEventListener("touchmove", (e) => { + var diff, moveToRow; + if (this.moving) { + e.preventDefault(); + this.moveHover(e); + if (!startYMove) { + startYMove = e.touches[0].pageY; + } + diff = e.touches[0].pageY - startYMove; + if (diff > 0) { + if (nextRow && diff - nextRowHeightLast > nextRowHeight) { + moveToRow = nextRow; + if (moveToRow !== row) { + startYMove = e.touches[0].pageY; + moveToRow.getElement().parentNode.insertBefore(this.placeholderElement, moveToRow.getElement().nextSibling); + this.moveRow(moveToRow, true); + } + } + } else { + if (prevRow && -diff - prevRowHeightLast > prevRowHeight) { + moveToRow = prevRow; + if (moveToRow !== row) { + startYMove = e.touches[0].pageY; + moveToRow.getElement().parentNode.insertBefore(this.placeholderElement, moveToRow.getElement()); + this.moveRow(moveToRow, false); + } + } + } + if (moveToRow) { + nextRow = moveToRow.nextRow(); + nextRowHeightLast = nextRowHeight; + nextRowHeight = nextRow ? nextRow.getHeight() / 2 : 0; + prevRow = moveToRow.prevRow(); + prevRowHeightLast = prevRowHeight; + prevRowHeight = prevRow ? prevRow.getHeight() / 2 : 0; + } + } + }); + element.addEventListener("touchend", (e) => { + if (this.checkTimeout) { + clearTimeout(this.checkTimeout); + } + if (this.moving) { + this.endMove(e); + this.touchMove = false; + } + }); + } + + _bindMouseMove() { + this.table.rowManager.getDisplayRows().forEach((row) => { + if ((row.type === "row" || row.type === "group") && row.modules.moveRow && row.modules.moveRow.mousemove) { + row.getElement().addEventListener("mousemove", row.modules.moveRow.mousemove); + } + }); + } + + _unbindMouseMove() { + this.table.rowManager.getDisplayRows().forEach((row) => { + if ((row.type === "row" || row.type === "group") && row.modules.moveRow && row.modules.moveRow.mousemove) { + row.getElement().removeEventListener("mousemove", row.modules.moveRow.mousemove); + } + }); + } + + startMove(e, row) { + var element = row.getElement(); + this.setStartPosition(e, row); + this.moving = row; + this.table.element.classList.add("tabulator-block-select"); + this.placeholderElement.style.width = row.getWidth() + "px"; + this.placeholderElement.style.height = row.getHeight() + "px"; + if (!this.connection) { + element.parentNode.insertBefore(this.placeholderElement, element); + element.parentNode.removeChild(element); + } else { + this.table.element.classList.add("tabulator-movingrow-sending"); + this.connectToTables(row); + } + this.hoverElement = element.cloneNode(true); + this.hoverElement.classList.add("tabulator-moving"); + if (this.connection) { + document.body.appendChild(this.hoverElement); + this.hoverElement.style.left = "0"; + this.hoverElement.style.top = "0"; + this.hoverElement.style.width = this.table.element.clientWidth + "px"; + this.hoverElement.style.whiteSpace = "nowrap"; + this.hoverElement.style.overflow = "hidden"; + this.hoverElement.style.pointerEvents = "none"; + } else { + this.table.rowManager.getTableElement().appendChild(this.hoverElement); + this.hoverElement.style.left = "0"; + this.hoverElement.style.top = "0"; + this._bindMouseMove(); + } + document.body.addEventListener("mousemove", this.moveHover); + document.body.addEventListener("mouseup", this.endMove); + this.dispatchExternal("rowMoving", row.getComponent()); + this.moveHover(e); + } + + setStartPosition(e, row) { + var pageX = this.touchMove ? e.touches[0].pageX : e.pageX, + pageY = this.touchMove ? e.touches[0].pageY : e.pageY, element, position; + element = row.getElement(); + if (this.connection) { + position = element.getBoundingClientRect(); + this.startX = position.left - pageX + window.pageXOffset; + this.startY = position.top - pageY + window.pageYOffset; + } else { + this.startY = pageY - element.getBoundingClientRect().top; + } + } + + endMove(e) { + if (!e || e.which === 1 || this.touchMove) { + this._unbindMouseMove(); + if (!this.connection) { + this.placeholderElement.parentNode.insertBefore(this.moving.getElement(), this.placeholderElement.nextSibling); + this.placeholderElement.parentNode.removeChild(this.placeholderElement); + } + this.hoverElement.parentNode.removeChild(this.hoverElement); + this.table.element.classList.remove("tabulator-block-select"); + if (this.toRow) { + this.table.rowManager.moveRow(this.moving, this.toRow, this.toRowAfter); + } else { + this.dispatchExternal("rowMoveCancelled", this.moving.getComponent()); + } + this.moving = false; + this.toRow = false; + this.toRowAfter = false; + document.body.removeEventListener("mousemove", this.moveHover); + document.body.removeEventListener("mouseup", this.endMove); + if (this.connection) { + this.table.element.classList.remove("tabulator-movingrow-sending"); + this.disconnectFromTables(); + } + } + } + + moveRow(row, after) { + this.toRow = row; + this.toRowAfter = after; + } + + moveHover(e) { + if (this.connection) { + this.moveHoverConnections.call(this, e); + } else { + this.moveHoverTable.call(this, e); + } + } + + moveHoverTable(e) { + var rowHolder = this.table.rowManager.getElement(), scrollTop = rowHolder.scrollTop, + yPos = (this.touchMove ? e.touches[0].pageY : e.pageY) - rowHolder.getBoundingClientRect().top + scrollTop; + this.hoverElement.style.top = Math.min(yPos - this.startY, this.table.rowManager.element.scrollHeight - this.hoverElement.offsetHeight) + "px"; + } + + moveHoverConnections(e) { + this.hoverElement.style.left = this.startX + (this.touchMove ? e.touches[0].pageX : e.pageX) + "px"; + this.hoverElement.style.top = this.startY + (this.touchMove ? e.touches[0].pageY : e.pageY) + "px"; + } + + elementRowDrop(e, element, row) { + this.dispatchExternal("movableRowsElementDrop", e, element, row ? row.getComponent() : false); + } + + //establish connection with other tables + connectToTables(row) { + var connectionTables; + if (this.connectionSelectorsTables) { + connectionTables = this.commsConnections(this.connectionSelectorsTables); + this.dispatchExternal("movableRowsSendingStart", connectionTables); + this.commsSend(this.connectionSelectorsTables, "moveRow", "connect", { + row + }); + } + if (this.connectionSelectorsElements) { + this.connectionElements = []; + if (!Array.isArray(this.connectionSelectorsElements)) { + this.connectionSelectorsElements = [this.connectionSelectorsElements]; + } + this.connectionSelectorsElements.forEach((query) => { + if (typeof query === "string") { + this.connectionElements = this.connectionElements.concat(Array.prototype.slice.call(document.querySelectorAll(query))); + } else { + this.connectionElements.push(query); + } + }); + this.connectionElements.forEach((element) => { + var dropEvent = (e) => { + this.elementRowDrop(e, element, this.moving); + }; + element.addEventListener("mouseup", dropEvent); + element.tabulatorElementDropEvent = dropEvent; + element.classList.add("tabulator-movingrow-receiving"); + }); + } + } + + //disconnect from other tables + disconnectFromTables() { + var connectionTables; + if (this.connectionSelectorsTables) { + connectionTables = this.commsConnections(this.connectionSelectorsTables); + this.dispatchExternal("movableRowsSendingStop", connectionTables); + this.commsSend(this.connectionSelectorsTables, "moveRow", "disconnect"); + } + this.connectionElements.forEach((element) => { + element.classList.remove("tabulator-movingrow-receiving"); + element.removeEventListener("mouseup", element.tabulatorElementDropEvent); + delete element.tabulatorElementDropEvent; + }); + } + + //accept incomming connection + connect(table, row) { + if (!this.connectedTable) { + this.connectedTable = table; + this.connectedRow = row; + this.table.element.classList.add("tabulator-movingrow-receiving"); + this.table.rowManager.getDisplayRows().forEach((row2) => { + if (row2.type === "row" && row2.modules.moveRow && row2.modules.moveRow.mouseup) { + row2.getElement().addEventListener("mouseup", row2.modules.moveRow.mouseup); + } + }); + this.tableRowDropEvent = this.tableRowDrop.bind(this); + this.table.element.addEventListener("mouseup", this.tableRowDropEvent); + this.dispatchExternal("movableRowsReceivingStart", row, table); + return true; + } else { + console.warn("Move Row Error - Table cannot accept connection, already connected to table:", this.connectedTable); + return false; + } + } + + //close incoming connection + disconnect(table) { + if (table === this.connectedTable) { + this.connectedTable = false; + this.connectedRow = false; + this.table.element.classList.remove("tabulator-movingrow-receiving"); + this.table.rowManager.getDisplayRows().forEach((row) => { + if (row.type === "row" && row.modules.moveRow && row.modules.moveRow.mouseup) { + row.getElement().removeEventListener("mouseup", row.modules.moveRow.mouseup); + } + }); + this.table.element.removeEventListener("mouseup", this.tableRowDropEvent); + this.dispatchExternal("movableRowsReceivingStop", table); + } else { + console.warn("Move Row Error - trying to disconnect from non connected table"); + } + } + + dropComplete(table, row, success) { + var sender = false; + if (success) { + switch (typeof this.table.options.movableRowsSender) { + case "string": + sender = _MoveRows.senders[this.table.options.movableRowsSender]; + break; + case "function": + sender = this.table.options.movableRowsSender; + break; + } + if (sender) { + sender.call(this, this.moving ? this.moving.getComponent() : void 0, row ? row.getComponent() : void 0, table); + } else { + if (this.table.options.movableRowsSender) { + console.warn("Mover Row Error - no matching sender found:", this.table.options.movableRowsSender); + } + } + this.dispatchExternal("movableRowsSent", this.moving.getComponent(), row ? row.getComponent() : void 0, table); + } else { + this.dispatchExternal("movableRowsSentFailed", this.moving.getComponent(), row ? row.getComponent() : void 0, table); + } + this.endMove(); + } + + tableRowDrop(e, row) { + var receiver = false, success = false; + e.stopImmediatePropagation(); + switch (typeof this.table.options.movableRowsReceiver) { + case "string": + receiver = _MoveRows.receivers[this.table.options.movableRowsReceiver]; + break; + case "function": + receiver = this.table.options.movableRowsReceiver; + break; + } + if (receiver) { + success = receiver.call(this, this.connectedRow.getComponent(), row ? row.getComponent() : void 0, this.connectedTable); + } else { + console.warn("Mover Row Error - no matching receiver found:", this.table.options.movableRowsReceiver); + } + if (success) { + this.dispatchExternal("movableRowsReceived", this.connectedRow.getComponent(), row ? row.getComponent() : void 0, this.connectedTable); + } else { + this.dispatchExternal("movableRowsReceivedFailed", this.connectedRow.getComponent(), row ? row.getComponent() : void 0, this.connectedTable); + } + this.commsSend(this.connectedTable, "moveRow", "dropcomplete", { + row, + success + }); + } + + commsReceived(table, action, data) { + switch (action) { + case "connect": + return this.connect(table, data.row); + case "disconnect": + return this.disconnect(table); + case "dropcomplete": + return this.dropComplete(table, data.row, data.success); + } + } + }; + __publicField(_MoveRows, "moduleName", "moveRow"); + //load defaults + __publicField(_MoveRows, "senders", defaultSenders); + __publicField(_MoveRows, "receivers", defaultReceivers); + let MoveRows = _MoveRows; + var defaultMutators = {}; + const _Mutator = class _Mutator extends Module { + constructor(table) { + super(table); + this.allowedTypes = ["", "data", "edit", "clipboard", "import"]; + this.enabled = true; + this.registerColumnOption("mutator"); + this.registerColumnOption("mutatorParams"); + this.registerColumnOption("mutatorData"); + this.registerColumnOption("mutatorDataParams"); + this.registerColumnOption("mutatorEdit"); + this.registerColumnOption("mutatorEditParams"); + this.registerColumnOption("mutatorClipboard"); + this.registerColumnOption("mutatorClipboardParams"); + this.registerColumnOption("mutatorImport"); + this.registerColumnOption("mutatorImportParams"); + this.registerColumnOption("mutateLink"); + } + + initialize() { + this.subscribe("cell-value-changing", this.transformCell.bind(this)); + this.subscribe("cell-value-changed", this.mutateLink.bind(this)); + this.subscribe("column-layout", this.initializeColumn.bind(this)); + this.subscribe("row-data-init-before", this.rowDataChanged.bind(this)); + this.subscribe("row-data-changing", this.rowDataChanged.bind(this)); + } + + rowDataChanged(row, tempData, updatedData) { + return this.transformRow(tempData, "data", updatedData); + } + + //initialize column mutator + initializeColumn(column) { + var match = false, config = {}; + this.allowedTypes.forEach((type) => { + var key = "mutator" + (type.charAt(0).toUpperCase() + type.slice(1)), mutator; + if (column.definition[key]) { + mutator = this.lookupMutator(column.definition[key]); + if (mutator) { + match = true; + config[key] = { + mutator, + params: column.definition[key + "Params"] || {} + }; + } + } + }); + if (match) { + column.modules.mutate = config; + } + } + + lookupMutator(value) { + var mutator = false; + switch (typeof value) { + case "string": + if (_Mutator.mutators[value]) { + mutator = _Mutator.mutators[value]; + } else { + console.warn("Mutator Error - No such mutator found, ignoring: ", value); + } + break; + case "function": + mutator = value; + break; + } + return mutator; + } + + //apply mutator to row + transformRow(data, type, updatedData) { + var key = "mutator" + (type.charAt(0).toUpperCase() + type.slice(1)), value; + if (this.enabled) { + this.table.columnManager.traverse((column) => { + var mutator, params, component; + if (column.modules.mutate) { + mutator = column.modules.mutate[key] || column.modules.mutate.mutator || false; + if (mutator) { + value = column.getFieldValue(typeof updatedData !== "undefined" ? updatedData : data); + if (type == "data" && !updatedData || typeof value !== "undefined") { + component = column.getComponent(); + params = typeof mutator.params === "function" ? mutator.params(value, data, type, component) : mutator.params; + column.setFieldValue(data, mutator.mutator(value, data, type, params, component)); + } + } + } + }); + } + return data; + } + + //apply mutator to new cell value + transformCell(cell, value) { + if (cell.column.modules.mutate) { + var mutator = cell.column.modules.mutate.mutatorEdit || cell.column.modules.mutate.mutator || false, + tempData = {}; + if (mutator) { + tempData = Object.assign(tempData, cell.row.getData()); + cell.column.setFieldValue(tempData, value); + return mutator.mutator(value, tempData, "edit", mutator.params, cell.getComponent()); + } + } + return value; + } + + mutateLink(cell) { + var links = cell.column.definition.mutateLink; + if (links) { + if (!Array.isArray(links)) { + links = [links]; + } + links.forEach((link2) => { + var linkCell = cell.row.getCell(link2); + if (linkCell) { + linkCell.setValue(linkCell.getValue(), true, true); + } + }); + } + } + + enable() { + this.enabled = true; + } + + disable() { + this.enabled = false; + } + }; + __publicField(_Mutator, "moduleName", "mutator"); + //load defaults + __publicField(_Mutator, "mutators", defaultMutators); + let Mutator = _Mutator; + + function rows(pageSize, currentRow, currentPage, totalRows, totalPages) { + var el = document.createElement("span"), showingEl = document.createElement("span"), + valueEl = document.createElement("span"), ofEl = document.createElement("span"), + totalEl = document.createElement("span"), rowsEl = document.createElement("span"); + this.table.modules.localize.langBind("pagination|counter|showing", (value) => { + showingEl.innerHTML = value; + }); + this.table.modules.localize.langBind("pagination|counter|of", (value) => { + ofEl.innerHTML = value; + }); + this.table.modules.localize.langBind("pagination|counter|rows", (value) => { + rowsEl.innerHTML = value; + }); + if (totalRows) { + valueEl.innerHTML = " " + currentRow + "-" + Math.min(currentRow + pageSize - 1, totalRows) + " "; + totalEl.innerHTML = " " + totalRows + " "; + el.appendChild(showingEl); + el.appendChild(valueEl); + el.appendChild(ofEl); + el.appendChild(totalEl); + el.appendChild(rowsEl); + } else { + valueEl.innerHTML = " 0 "; + el.appendChild(showingEl); + el.appendChild(valueEl); + el.appendChild(rowsEl); + } + return el; + } + + function pages(pageSize, currentRow, currentPage, totalRows, totalPages) { + var el = document.createElement("span"), showingEl = document.createElement("span"), + valueEl = document.createElement("span"), ofEl = document.createElement("span"), + totalEl = document.createElement("span"), rowsEl = document.createElement("span"); + this.table.modules.localize.langBind("pagination|counter|showing", (value) => { + showingEl.innerHTML = value; + }); + valueEl.innerHTML = " " + currentPage + " "; + this.table.modules.localize.langBind("pagination|counter|of", (value) => { + ofEl.innerHTML = value; + }); + totalEl.innerHTML = " " + totalPages + " "; + this.table.modules.localize.langBind("pagination|counter|pages", (value) => { + rowsEl.innerHTML = value; + }); + el.appendChild(showingEl); + el.appendChild(valueEl); + el.appendChild(ofEl); + el.appendChild(totalEl); + el.appendChild(rowsEl); + return el; + } + + var defaultPageCounters = { + rows, + pages + }; + const _Page = class _Page extends Module { + constructor(table) { + super(table); + this.mode = "local"; + this.progressiveLoad = false; + this.element = null; + this.pageCounterElement = null; + this.pageCounter = null; + this.size = 0; + this.page = 1; + this.count = 5; + this.max = 1; + this.remoteRowCountEstimate = null; + this.initialLoad = true; + this.dataChanging = false; + this.pageSizes = []; + this.registerTableOption("pagination", false); + this.registerTableOption("paginationMode", "local"); + this.registerTableOption("paginationSize", false); + this.registerTableOption("paginationInitialPage", 1); + this.registerTableOption("paginationCounter", false); + this.registerTableOption("paginationCounterElement", false); + this.registerTableOption("paginationButtonCount", 5); + this.registerTableOption("paginationSizeSelector", false); + this.registerTableOption("paginationElement", false); + this.registerTableOption("paginationAddRow", "page"); + this.registerTableOption("paginationOutOfRange", false); + this.registerTableOption("progressiveLoad", false); + this.registerTableOption("progressiveLoadDelay", 0); + this.registerTableOption("progressiveLoadScrollMargin", 0); + this.registerTableFunction("setMaxPage", this.setMaxPage.bind(this)); + this.registerTableFunction("setPage", this.setPage.bind(this)); + this.registerTableFunction("setPageToRow", this.userSetPageToRow.bind(this)); + this.registerTableFunction("setPageSize", this.userSetPageSize.bind(this)); + this.registerTableFunction("getPageSize", this.getPageSize.bind(this)); + this.registerTableFunction("previousPage", this.previousPage.bind(this)); + this.registerTableFunction("nextPage", this.nextPage.bind(this)); + this.registerTableFunction("getPage", this.getPage.bind(this)); + this.registerTableFunction("getPageMax", this.getPageMax.bind(this)); + this.registerComponentFunction("row", "pageTo", this.setPageToRow.bind(this)); + } + + initialize() { + if (this.table.options.pagination) { + this.subscribe("row-deleted", this.rowsUpdated.bind(this)); + this.subscribe("row-added", this.rowsUpdated.bind(this)); + this.subscribe("data-processed", this.initialLoadComplete.bind(this)); + this.subscribe("table-built", this.calculatePageSizes.bind(this)); + this.subscribe("footer-redraw", this.footerRedraw.bind(this)); + if (this.table.options.paginationAddRow == "page") { + this.subscribe("row-adding-position", this.rowAddingPosition.bind(this)); + } + if (this.table.options.paginationMode === "remote") { + this.subscribe("data-params", this.remotePageParams.bind(this)); + this.subscribe("data-loaded", this._parseRemoteData.bind(this)); + } + if (this.table.options.progressiveLoad) { + console.error("Progressive Load Error - Pagination and progressive load cannot be used at the same time"); + } + this.registerDisplayHandler(this.restOnRenderBefore.bind(this), 40); + this.registerDisplayHandler(this.getRows.bind(this), 50); + this.createElements(); + this.initializePageCounter(); + this.initializePaginator(); + } else if (this.table.options.progressiveLoad) { + this.subscribe("data-params", this.remotePageParams.bind(this)); + this.subscribe("data-loaded", this._parseRemoteData.bind(this)); + this.subscribe("table-built", this.calculatePageSizes.bind(this)); + this.subscribe("data-processed", this.initialLoadComplete.bind(this)); + this.initializeProgressive(this.table.options.progressiveLoad); + if (this.table.options.progressiveLoad === "scroll") { + this.subscribe("scroll-vertical", this.scrollVertical.bind(this)); + } + } + } + + rowAddingPosition(row, top) { + var rowManager = this.table.rowManager, displayRows = rowManager.getDisplayRows(), index; + if (top) { + if (displayRows.length) { + index = displayRows[0]; + } else { + if (rowManager.activeRows.length) { + index = rowManager.activeRows[rowManager.activeRows.length - 1]; + top = false; + } + } + } else { + if (displayRows.length) { + index = displayRows[displayRows.length - 1]; + top = displayRows.length < this.size ? false : true; + } + } + return {index, top}; + } + + calculatePageSizes() { + var testElRow, testElCell; + if (this.table.options.paginationSize) { + this.size = this.table.options.paginationSize; + } else { + testElRow = document.createElement("div"); + testElRow.classList.add("tabulator-row"); + testElRow.style.visibility = "hidden"; + testElCell = document.createElement("div"); + testElCell.classList.add("tabulator-cell"); + testElCell.innerHTML = "Page Row Test"; + testElRow.appendChild(testElCell); + this.table.rowManager.getTableElement().appendChild(testElRow); + this.size = Math.floor(this.table.rowManager.getElement().clientHeight / testElRow.offsetHeight); + this.table.rowManager.getTableElement().removeChild(testElRow); + } + this.dispatchExternal("pageSizeChanged", this.size); + this.generatePageSizeSelectList(); + } + + initialLoadComplete() { + this.initialLoad = false; + } + + remotePageParams(data, config, silent, params) { + if (!this.initialLoad) { + if (this.progressiveLoad && !silent || !this.progressiveLoad && !this.dataChanging) { + this.reset(true); + } + } + params.page = this.page; + if (this.size) { + params.size = this.size; + } + return params; + } + + /////////////////////////////////// + ///////// Table Functions ///////// + /////////////////////////////////// + userSetPageToRow(row) { + if (this.table.options.pagination) { + row = this.table.rowManager.findRow(row); + if (row) { + return this.setPageToRow(row); + } + } + return Promise.reject(); + } + + userSetPageSize(size) { + if (this.table.options.pagination) { + this.setPageSize(size); + return this.setPage(1); + } else { + return false; + } + } + + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + scrollVertical(top, dir) { + var element, diff, margin; + if (!dir && !this.table.dataLoader.loading) { + element = this.table.rowManager.getElement(); + diff = element.scrollHeight - element.clientHeight - top; + margin = this.table.options.progressiveLoadScrollMargin || element.clientHeight * 2; + if (diff < margin) { + this.nextPage().catch(() => { + }); + } + } + } + + restOnRenderBefore(rows2, renderInPosition) { + if (!renderInPosition) { + if (this.mode === "local") { + this.reset(); + } + } + return rows2; + } + + rowsUpdated() { + this.refreshData(true, "all"); + } + + createElements() { + var button; + this.element = document.createElement("span"); + this.element.classList.add("tabulator-paginator"); + this.pagesElement = document.createElement("span"); + this.pagesElement.classList.add("tabulator-pages"); + button = document.createElement("button"); + button.classList.add("tabulator-page"); + button.setAttribute("type", "button"); + button.setAttribute("role", "button"); + button.setAttribute("aria-label", ""); + button.setAttribute("title", ""); + this.firstBut = button.cloneNode(true); + this.firstBut.setAttribute("data-page", "first"); + this.prevBut = button.cloneNode(true); + this.prevBut.setAttribute("data-page", "prev"); + this.nextBut = button.cloneNode(true); + this.nextBut.setAttribute("data-page", "next"); + this.lastBut = button.cloneNode(true); + this.lastBut.setAttribute("data-page", "last"); + if (this.table.options.paginationSizeSelector) { + this.pageSizeSelect = document.createElement("select"); + this.pageSizeSelect.classList.add("tabulator-page-size"); + } + } + + generatePageSizeSelectList() { + var pageSizes = []; + if (this.pageSizeSelect) { + if (Array.isArray(this.table.options.paginationSizeSelector)) { + pageSizes = this.table.options.paginationSizeSelector; + this.pageSizes = pageSizes; + if (this.pageSizes.indexOf(this.size) == -1) { + pageSizes.unshift(this.size); + } + } else { + if (this.pageSizes.indexOf(this.size) == -1) { + pageSizes = []; + for (let i = 1; i < 5; i++) { + pageSizes.push(this.size * i); + } + this.pageSizes = pageSizes; + } else { + pageSizes = this.pageSizes; + } + } + while (this.pageSizeSelect.firstChild) this.pageSizeSelect.removeChild(this.pageSizeSelect.firstChild); + pageSizes.forEach((item) => { + var itemEl = document.createElement("option"); + itemEl.value = item; + if (item === true) { + this.langBind("pagination|all", function (value) { + itemEl.innerHTML = value; + }); + } else { + itemEl.innerHTML = item; + } + this.pageSizeSelect.appendChild(itemEl); + }); + this.pageSizeSelect.value = this.size; + } + } + + initializePageCounter() { + var counter = this.table.options.paginationCounter, pageCounter = null; + if (counter) { + if (typeof counter === "function") { + pageCounter = counter; + } else { + pageCounter = _Page.pageCounters[counter]; + } + if (pageCounter) { + this.pageCounter = pageCounter; + this.pageCounterElement = document.createElement("span"); + this.pageCounterElement.classList.add("tabulator-page-counter"); + } else { + console.warn("Pagination Error - No such page counter found: ", counter); + } + } + } + + //setup pagination + initializePaginator(hidden) { + var pageSelectLabel, paginationCounterHolder; + if (!hidden) { + this.langBind("pagination|first", (value) => { + this.firstBut.innerHTML = value; + }); + this.langBind("pagination|first_title", (value) => { + this.firstBut.setAttribute("aria-label", value); + this.firstBut.setAttribute("title", value); + }); + this.langBind("pagination|prev", (value) => { + this.prevBut.innerHTML = value; + }); + this.langBind("pagination|prev_title", (value) => { + this.prevBut.setAttribute("aria-label", value); + this.prevBut.setAttribute("title", value); + }); + this.langBind("pagination|next", (value) => { + this.nextBut.innerHTML = value; + }); + this.langBind("pagination|next_title", (value) => { + this.nextBut.setAttribute("aria-label", value); + this.nextBut.setAttribute("title", value); + }); + this.langBind("pagination|last", (value) => { + this.lastBut.innerHTML = value; + }); + this.langBind("pagination|last_title", (value) => { + this.lastBut.setAttribute("aria-label", value); + this.lastBut.setAttribute("title", value); + }); + this.firstBut.addEventListener("click", () => { + this.setPage(1); + }); + this.prevBut.addEventListener("click", () => { + this.previousPage(); + }); + this.nextBut.addEventListener("click", () => { + this.nextPage(); + }); + this.lastBut.addEventListener("click", () => { + this.setPage(this.max); + }); + if (this.table.options.paginationElement) { + this.element = this.table.options.paginationElement; + } + if (this.pageSizeSelect) { + pageSelectLabel = document.createElement("label"); + this.langBind("pagination|page_size", (value) => { + this.pageSizeSelect.setAttribute("aria-label", value); + this.pageSizeSelect.setAttribute("title", value); + pageSelectLabel.innerHTML = value; + }); + this.element.appendChild(pageSelectLabel); + this.element.appendChild(this.pageSizeSelect); + this.pageSizeSelect.addEventListener("change", (e) => { + this.setPageSize(this.pageSizeSelect.value == "true" ? true : this.pageSizeSelect.value); + this.setPage(1); + }); + } + this.element.appendChild(this.firstBut); + this.element.appendChild(this.prevBut); + this.element.appendChild(this.pagesElement); + this.element.appendChild(this.nextBut); + this.element.appendChild(this.lastBut); + if (!this.table.options.paginationElement) { + if (this.table.options.paginationCounter) { + if (this.table.options.paginationCounterElement) { + if (this.table.options.paginationCounterElement instanceof HTMLElement) { + this.table.options.paginationCounterElement.appendChild(this.pageCounterElement); + } else if (typeof this.table.options.paginationCounterElement === "string") { + paginationCounterHolder = document.querySelector(this.table.options.paginationCounterElement); + if (paginationCounterHolder) { + paginationCounterHolder.appendChild(this.pageCounterElement); + } else { + console.warn("Pagination Error - Unable to find element matching paginationCounterElement selector:", this.table.options.paginationCounterElement); + } + } + } else { + this.footerAppend(this.pageCounterElement); + } + } + this.footerAppend(this.element); + } + this.page = this.table.options.paginationInitialPage; + this.count = this.table.options.paginationButtonCount; + } + this.mode = this.table.options.paginationMode; + } + + initializeProgressive(mode) { + this.initializePaginator(true); + this.mode = "progressive_" + mode; + this.progressiveLoad = true; + } + + trackChanges() { + this.dispatch("page-changed"); + } + + //calculate maximum page from number of rows + setMaxRows(rowCount) { + if (!rowCount) { + this.max = 1; + } else { + this.max = this.size === true ? 1 : Math.ceil(rowCount / this.size); + } + if (this.page > this.max) { + this.page = this.max; + } + } + + //reset to first page without triggering action + reset(force) { + if (!this.initialLoad) { + if (this.mode == "local" || force) { + this.page = 1; + this.trackChanges(); + } + } + } + + //set the maximum page + setMaxPage(max) { + max = parseInt(max); + this.max = max || 1; + if (this.page > this.max) { + this.page = this.max; + this.trigger(); + } + } + + //set current page number + setPage(page) { + switch (page) { + case "first": + return this.setPage(1); + case "prev": + return this.previousPage(); + case "next": + return this.nextPage(); + case "last": + return this.setPage(this.max); + } + page = parseInt(page); + if (page > 0 && page <= this.max || this.mode !== "local") { + this.page = page; + this.trackChanges(); + return this.trigger(); + } else { + console.warn("Pagination Error - Requested page is out of range of 1 - " + this.max + ":", page); + return Promise.reject(); + } + } + + setPageToRow(row) { + var rows2 = this.displayRows(-1); + var index = rows2.indexOf(row); + if (index > -1) { + var page = this.size === true ? 1 : Math.ceil((index + 1) / this.size); + return this.setPage(page); + } else { + console.warn("Pagination Error - Requested row is not visible"); + return Promise.reject(); + } + } + + setPageSize(size) { + if (size !== true) { + size = parseInt(size); + } + if (size > 0) { + this.size = size; + this.dispatchExternal("pageSizeChanged", size); + } + if (this.pageSizeSelect) { + this.generatePageSizeSelectList(); + } + this.trackChanges(); + } + + _setPageCounter(totalRows, size, currentRow) { + var content; + if (this.pageCounter) { + if (this.mode === "remote") { + size = this.size; + currentRow = (this.page - 1) * this.size + 1; + totalRows = this.remoteRowCountEstimate; + } + content = this.pageCounter.call(this, size, currentRow, this.page, totalRows, this.max); + switch (typeof content) { + case "object": + if (content instanceof Node) { + while (this.pageCounterElement.firstChild) this.pageCounterElement.removeChild(this.pageCounterElement.firstChild); + this.pageCounterElement.appendChild(content); + } else { + this.pageCounterElement.innerHTML = ""; + if (content != null) { + console.warn("Page Counter Error - Page Counter has returned a type of object, the only valid page counter object return is an instance of Node, the page counter returned:", content); + } + } + break; + case "undefined": + this.pageCounterElement.innerHTML = ""; + break; + default: + this.pageCounterElement.innerHTML = content; + } + } + } + + //setup the pagination buttons + _setPageButtons() { + let leftSize = Math.floor((this.count - 1) / 2); + let rightSize = Math.ceil((this.count - 1) / 2); + let min = this.max - this.page + leftSize + 1 < this.count ? this.max - this.count + 1 : Math.max(this.page - leftSize, 1); + let max = this.page <= rightSize ? Math.min(this.count, this.max) : Math.min(this.page + rightSize, this.max); + while (this.pagesElement.firstChild) this.pagesElement.removeChild(this.pagesElement.firstChild); + if (this.page == 1) { + this.firstBut.disabled = true; + this.prevBut.disabled = true; + } else { + this.firstBut.disabled = false; + this.prevBut.disabled = false; + } + if (this.page == this.max) { + this.lastBut.disabled = true; + this.nextBut.disabled = true; + } else { + this.lastBut.disabled = false; + this.nextBut.disabled = false; + } + for (let i = min; i <= max; i++) { + if (i > 0 && i <= this.max) { + this.pagesElement.appendChild(this._generatePageButton(i)); + } + } + this.footerRedraw(); + } + + _generatePageButton(page) { + var button = document.createElement("button"); + button.classList.add("tabulator-page"); + if (page == this.page) { + button.classList.add("active"); + } + button.setAttribute("type", "button"); + button.setAttribute("role", "button"); + this.langBind("pagination|page_title", (value) => { + button.setAttribute("aria-label", value + " " + page); + button.setAttribute("title", value + " " + page); + }); + button.setAttribute("data-page", page); + button.textContent = page; + button.addEventListener("click", (e) => { + this.setPage(page); + }); + return button; + } + + //previous page + previousPage() { + if (this.page > 1) { + this.page--; + this.trackChanges(); + return this.trigger(); + } else { + console.warn("Pagination Error - Previous page would be less than page 1:", 0); + return Promise.reject(); + } + } + + //next page + nextPage() { + if (this.page < this.max) { + this.page++; + this.trackChanges(); + return this.trigger(); + } else { + if (!this.progressiveLoad) { + console.warn("Pagination Error - Next page would be greater than maximum page of " + this.max + ":", this.max + 1); + } + return Promise.reject(); + } + } + + //return current page number + getPage() { + return this.page; + } + + //return max page number + getPageMax() { + return this.max; + } + + getPageSize(size) { + return this.size; + } + + getMode() { + return this.mode; + } + + //return appropriate rows for current page + getRows(data) { + var actualRowPageSize = 0, output, start, end, actualStartRow; + var actualRows = data.filter((row) => { + return row.type === "row"; + }); + if (this.mode == "local") { + output = []; + this.setMaxRows(data.length); + if (this.size === true) { + start = 0; + end = data.length; + } else { + start = this.size * (this.page - 1); + end = start + parseInt(this.size); + } + this._setPageButtons(); + for (let i = start; i < end; i++) { + let row = data[i]; + if (row) { + output.push(row); + if (row.type === "row") { + if (!actualStartRow) { + actualStartRow = row; + } + actualRowPageSize++; + } + } + } + this._setPageCounter(actualRows.length, actualRowPageSize, actualStartRow ? actualRows.indexOf(actualStartRow) + 1 : 0); + return output; + } else { + this._setPageButtons(); + this._setPageCounter(actualRows.length); + return data.slice(0); + } + } + + trigger() { + var left; + switch (this.mode) { + case "local": + left = this.table.rowManager.scrollLeft; + this.refreshData(); + this.table.rowManager.scrollHorizontal(left); + this.dispatchExternal("pageLoaded", this.getPage()); + return Promise.resolve(); + case "remote": + this.dataChanging = true; + return this.reloadData(null).finally(() => { + this.dataChanging = false; + }); + case "progressive_load": + case "progressive_scroll": + return this.reloadData(null, true); + default: + console.warn("Pagination Error - no such pagination mode:", this.mode); + return Promise.reject(); + } + } + + _parseRemoteData(data) { + var margin, paginationOutOfRange; + if (typeof data.last_page === "undefined") { + console.warn("Remote Pagination Error - Server response missing '" + (this.options("dataReceiveParams").last_page || "last_page") + "' property"); + } + if (data.data) { + this.max = parseInt(data.last_page) || 1; + this.remoteRowCountEstimate = typeof data.last_row !== "undefined" ? data.last_row : data.last_page * this.size - (this.page == data.last_page ? this.size - data.data.length : 0); + if (this.progressiveLoad) { + switch (this.mode) { + case "progressive_load": + if (this.page == 1) { + this.table.rowManager.setData(data.data, false, this.page == 1); + } else { + this.table.rowManager.addRows(data.data); + } + if (this.page < this.max) { + setTimeout(() => { + this.nextPage(); + }, this.table.options.progressiveLoadDelay); + } + break; + case "progressive_scroll": + data = this.page === 1 ? data.data : this.table.rowManager.getData().concat(data.data); + this.table.rowManager.setData(data, this.page !== 1, this.page == 1); + margin = this.table.options.progressiveLoadScrollMargin || this.table.rowManager.element.clientHeight * 2; + if (this.table.rowManager.element.scrollHeight <= this.table.rowManager.element.clientHeight + margin) { + if (this.page < this.max) { + setTimeout(() => { + this.nextPage(); + }); + } + } + break; + } + return false; + } else { + if (this.page > this.max) { + console.warn("Remote Pagination Error - Server returned last page value lower than the current page"); + paginationOutOfRange = this.options("paginationOutOfRange"); + if (paginationOutOfRange) { + return this.setPage(typeof paginationOutOfRange === "function" ? paginationOutOfRange.call(this, this.page, this.max) : paginationOutOfRange); + } + } + this.dispatchExternal("pageLoaded", this.getPage()); + } + } else { + console.warn("Remote Pagination Error - Server response missing '" + (this.options("dataReceiveParams").data || "data") + "' property"); + } + return data.data; + } + + //handle the footer element being redrawn + footerRedraw() { + var footer = this.table.footerManager.containerElement; + if (Math.ceil(footer.clientWidth) - footer.scrollWidth < 0) { + this.pagesElement.style.display = "none"; + } else { + this.pagesElement.style.display = ""; + if (Math.ceil(footer.clientWidth) - footer.scrollWidth < 0) { + this.pagesElement.style.display = "none"; + } + } + } + }; + __publicField(_Page, "moduleName", "page"); + //load defaults + __publicField(_Page, "pageCounters", defaultPageCounters); + let Page = _Page; + var defaultReaders = { + local: function (id, type) { + var data = localStorage.getItem(id + "-" + type); + return data ? JSON.parse(data) : false; + }, + cookie: function (id, type) { + var cookie = document.cookie, key = id + "-" + type, cookiePos = cookie.indexOf(key + "="), end, data; + if (cookiePos > -1) { + cookie = cookie.slice(cookiePos); + end = cookie.indexOf(";"); + if (end > -1) { + cookie = cookie.slice(0, end); + } + data = cookie.replace(key + "=", ""); + } + return data ? JSON.parse(data) : false; + } + }; + var defaultWriters = { + local: function (id, type, data) { + localStorage.setItem(id + "-" + type, JSON.stringify(data)); + }, + cookie: function (id, type, data) { + var expireDate = /* @__PURE__ */ new Date(); + expireDate.setDate(expireDate.getDate() + 1e4); + document.cookie = id + "-" + type + "=" + JSON.stringify(data) + "; expires=" + expireDate.toUTCString(); + } + }; + const _Persistence = class _Persistence extends Module { + constructor(table) { + super(table); + this.mode = ""; + this.id = ""; + this.defWatcherBlock = false; + this.config = {}; + this.readFunc = false; + this.writeFunc = false; + this.registerTableOption("persistence", false); + this.registerTableOption("persistenceID", ""); + this.registerTableOption("persistenceMode", true); + this.registerTableOption("persistenceReaderFunc", false); + this.registerTableOption("persistenceWriterFunc", false); + } + + // Test for whether localStorage is available for use. + localStorageTest() { + var testKey = "_tabulator_test"; + try { + window.localStorage.setItem(testKey, testKey); + window.localStorage.removeItem(testKey); + return true; + } catch (e) { + return false; + } + } + + //setup parameters + initialize() { + if (this.table.options.persistence) { + var mode = this.table.options.persistenceMode, id = this.table.options.persistenceID, retrievedData; + this.mode = mode !== true ? mode : this.localStorageTest() ? "local" : "cookie"; + if (this.table.options.persistenceReaderFunc) { + if (typeof this.table.options.persistenceReaderFunc === "function") { + this.readFunc = this.table.options.persistenceReaderFunc; + } else { + if (_Persistence.readers[this.table.options.persistenceReaderFunc]) { + this.readFunc = _Persistence.readers[this.table.options.persistenceReaderFunc]; + } else { + console.warn("Persistence Read Error - invalid reader set", this.table.options.persistenceReaderFunc); + } + } + } else { + if (_Persistence.readers[this.mode]) { + this.readFunc = _Persistence.readers[this.mode]; + } else { + console.warn("Persistence Read Error - invalid reader set", this.mode); + } + } + if (this.table.options.persistenceWriterFunc) { + if (typeof this.table.options.persistenceWriterFunc === "function") { + this.writeFunc = this.table.options.persistenceWriterFunc; + } else { + if (_Persistence.writers[this.table.options.persistenceWriterFunc]) { + this.writeFunc = _Persistence.writers[this.table.options.persistenceWriterFunc]; + } else { + console.warn("Persistence Write Error - invalid reader set", this.table.options.persistenceWriterFunc); + } + } + } else { + if (_Persistence.writers[this.mode]) { + this.writeFunc = _Persistence.writers[this.mode]; + } else { + console.warn("Persistence Write Error - invalid writer set", this.mode); + } + } + this.id = "tabulator-" + (id || (this.table.element.getAttribute("id") || "")); + this.config = { + sort: this.table.options.persistence === true || this.table.options.persistence.sort, + filter: this.table.options.persistence === true || this.table.options.persistence.filter, + headerFilter: this.table.options.persistence === true || this.table.options.persistence.headerFilter, + group: this.table.options.persistence === true || this.table.options.persistence.group, + page: this.table.options.persistence === true || this.table.options.persistence.page, + columns: this.table.options.persistence === true ? ["title", "width", "visible"] : this.table.options.persistence.columns + }; + if (this.config.page) { + retrievedData = this.retrieveData("page"); + if (retrievedData) { + if (typeof retrievedData.paginationSize !== "undefined" && (this.config.page === true || this.config.page.size)) { + this.table.options.paginationSize = retrievedData.paginationSize; + } + if (typeof retrievedData.paginationInitialPage !== "undefined" && (this.config.page === true || this.config.page.page)) { + this.table.options.paginationInitialPage = retrievedData.paginationInitialPage; + } + } + } + if (this.config.group) { + retrievedData = this.retrieveData("group"); + if (retrievedData) { + if (typeof retrievedData.groupBy !== "undefined" && (this.config.group === true || this.config.group.groupBy)) { + this.table.options.groupBy = retrievedData.groupBy; + } + if (typeof retrievedData.groupStartOpen !== "undefined" && (this.config.group === true || this.config.group.groupStartOpen)) { + this.table.options.groupStartOpen = retrievedData.groupStartOpen; + } + if (typeof retrievedData.groupHeader !== "undefined" && (this.config.group === true || this.config.group.groupHeader)) { + this.table.options.groupHeader = retrievedData.groupHeader; + } + } + } + if (this.config.columns) { + this.table.options.columns = this.load("columns", this.table.options.columns); + this.subscribe("column-init", this.initializeColumn.bind(this)); + this.subscribe("column-show", this.save.bind(this, "columns")); + this.subscribe("column-hide", this.save.bind(this, "columns")); + this.subscribe("column-moved", this.save.bind(this, "columns")); + } + this.subscribe("table-built", this.tableBuilt.bind(this), 0); + this.subscribe("table-redraw", this.tableRedraw.bind(this)); + this.subscribe("filter-changed", this.eventSave.bind(this, "filter")); + this.subscribe("filter-changed", this.eventSave.bind(this, "headerFilter")); + this.subscribe("sort-changed", this.eventSave.bind(this, "sort")); + this.subscribe("group-changed", this.eventSave.bind(this, "group")); + this.subscribe("page-changed", this.eventSave.bind(this, "page")); + this.subscribe("column-resized", this.eventSave.bind(this, "columns")); + this.subscribe("column-width", this.eventSave.bind(this, "columns")); + this.subscribe("layout-refreshed", this.eventSave.bind(this, "columns")); + } + this.registerTableFunction("getColumnLayout", this.getColumnLayout.bind(this)); + this.registerTableFunction("setColumnLayout", this.setColumnLayout.bind(this)); + } + + eventSave(type) { + if (this.config[type]) { + this.save(type); + } + } + + tableBuilt() { + var sorters, filters, headerFilters; + if (this.config.sort) { + sorters = this.load("sort"); + if (!sorters === false) { + this.table.options.initialSort = sorters; + } + } + if (this.config.filter) { + filters = this.load("filter"); + if (!filters === false) { + this.table.options.initialFilter = filters; + } + } + if (this.config.headerFilter) { + headerFilters = this.load("headerFilter"); + if (!headerFilters === false) { + this.table.options.initialHeaderFilter = headerFilters; + } + } + } + + tableRedraw(force) { + if (force && this.config.columns) { + this.save("columns"); + } + } + + /////////////////////////////////// + ///////// Table Functions ///////// + /////////////////////////////////// + getColumnLayout() { + return this.parseColumns(this.table.columnManager.getColumns()); + } + + setColumnLayout(layout) { + this.table.columnManager.setColumns(this.mergeDefinition(this.table.options.columns, layout, true)); + return true; + } + + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + initializeColumn(column) { + var def, keys; + if (this.config.columns) { + this.defWatcherBlock = true; + def = column.getDefinition(); + keys = this.config.columns === true ? Object.keys(def) : this.config.columns; + keys.forEach((key) => { + var props = Object.getOwnPropertyDescriptor(def, key); + var value = def[key]; + if (props) { + Object.defineProperty(def, key, { + set: (newValue) => { + value = newValue; + if (!this.defWatcherBlock) { + this.save("columns"); + } + if (props.set) { + props.set(newValue); + } + }, + get: () => { + if (props.get) { + props.get(); + } + return value; + } + }); + } + }); + this.defWatcherBlock = false; + } + } + + //load saved definitions + load(type, current) { + var data = this.retrieveData(type); + if (current) { + data = data ? this.mergeDefinition(current, data) : current; + } + return data; + } + + //retrieve data from memory + retrieveData(type) { + return this.readFunc ? this.readFunc(this.id, type) : false; + } + + //merge old and new column definitions + mergeDefinition(oldCols, newCols, mergeAllNew) { + var output = []; + newCols = newCols || []; + newCols.forEach((column, to) => { + var from = this._findColumn(oldCols, column), keys; + if (from) { + if (mergeAllNew) { + keys = Object.keys(column); + } else if (this.config.columns === true || this.config.columns == void 0) { + keys = Object.keys(from); + keys.push("width"); + } else { + keys = this.config.columns; + } + keys.forEach((key) => { + if (key !== "columns" && typeof column[key] !== "undefined") { + from[key] = column[key]; + } + }); + if (from.columns) { + from.columns = this.mergeDefinition(from.columns, column.columns); + } + output.push(from); + } + }); + oldCols.forEach((column, i) => { + var from = this._findColumn(newCols, column); + if (!from) { + if (output.length > i) { + output.splice(i, 0, column); + } else { + output.push(column); + } + } + }); + return output; + } + + //find matching columns + _findColumn(columns, subject) { + var type = subject.columns ? "group" : subject.field ? "field" : "object"; + return columns.find(function (col) { + switch (type) { + case "group": + return col.title === subject.title && col.columns.length === subject.columns.length; + case "field": + return col.field === subject.field; + case "object": + return col === subject; + } + }); + } + + //save data + save(type) { + var data = {}; + switch (type) { + case "columns": + data = this.parseColumns(this.table.columnManager.getColumns()); + break; + case "filter": + data = this.table.modules.filter.getFilters(); + break; + case "headerFilter": + data = this.table.modules.filter.getHeaderFilters(); + break; + case "sort": + data = this.validateSorters(this.table.modules.sort.getSort()); + break; + case "group": + data = this.getGroupConfig(); + break; + case "page": + data = this.getPageConfig(); + break; + } + if (this.writeFunc) { + this.writeFunc(this.id, type, data); + } + } + + //ensure sorters contain no function data + validateSorters(data) { + data.forEach(function (item) { + item.column = item.field; + delete item.field; + }); + return data; + } + + getGroupConfig() { + var data = {}; + if (this.config.group) { + if (this.config.group === true || this.config.group.groupBy) { + data.groupBy = this.table.options.groupBy; + } + if (this.config.group === true || this.config.group.groupStartOpen) { + data.groupStartOpen = this.table.options.groupStartOpen; + } + if (this.config.group === true || this.config.group.groupHeader) { + data.groupHeader = this.table.options.groupHeader; + } + } + return data; + } + + getPageConfig() { + var data = {}; + if (this.config.page) { + if (this.config.page === true || this.config.page.size) { + data.paginationSize = this.table.modules.page.getPageSize(); + } + if (this.config.page === true || this.config.page.page) { + data.paginationInitialPage = this.table.modules.page.getPage(); + } + } + return data; + } + + //parse columns for data to store + parseColumns(columns) { + var definitions = [], excludedKeys = ["headerContextMenu", "headerMenu", "contextMenu", "clickMenu"]; + columns.forEach((column) => { + var defStore = {}, colDef = column.getDefinition(), keys; + if (column.isGroup) { + defStore.title = colDef.title; + defStore.columns = this.parseColumns(column.getColumns()); + } else { + defStore.field = column.getField(); + if (this.config.columns === true || this.config.columns == void 0) { + keys = Object.keys(colDef); + keys.push("width"); + keys.push("visible"); + } else { + keys = this.config.columns; + } + keys.forEach((key) => { + switch (key) { + case "width": + defStore.width = column.getWidth(); + break; + case "visible": + defStore.visible = column.visible; + break; + default: + if (typeof colDef[key] !== "function" && excludedKeys.indexOf(key) === -1) { + defStore[key] = colDef[key]; + } + } + }); + } + definitions.push(defStore); + }); + return definitions; + } + }; + __publicField(_Persistence, "moduleName", "persistence"); + __publicField(_Persistence, "moduleInitOrder", -10); + //load defaults + __publicField(_Persistence, "readers", defaultReaders); + __publicField(_Persistence, "writers", defaultWriters); + let Persistence = _Persistence; + + class Popup2 extends Module { + constructor(table) { + super(table); + this.columnSubscribers = {}; + this.registerTableOption("rowContextPopup", false); + this.registerTableOption("rowClickPopup", false); + this.registerTableOption("rowDblClickPopup", false); + this.registerTableOption("groupContextPopup", false); + this.registerTableOption("groupClickPopup", false); + this.registerTableOption("groupDblClickPopup", false); + this.registerColumnOption("headerContextPopup"); + this.registerColumnOption("headerClickPopup"); + this.registerColumnOption("headerDblClickPopup"); + this.registerColumnOption("headerPopup"); + this.registerColumnOption("headerPopupIcon"); + this.registerColumnOption("contextPopup"); + this.registerColumnOption("clickPopup"); + this.registerColumnOption("dblClickPopup"); + this.registerComponentFunction("cell", "popup", this._componentPopupCall.bind(this)); + this.registerComponentFunction("column", "popup", this._componentPopupCall.bind(this)); + this.registerComponentFunction("row", "popup", this._componentPopupCall.bind(this)); + this.registerComponentFunction("group", "popup", this._componentPopupCall.bind(this)); + } + + initialize() { + this.initializeRowWatchers(); + this.initializeGroupWatchers(); + this.subscribe("column-init", this.initializeColumn.bind(this)); + } + + _componentPopupCall(component, contents, position) { + this.loadPopupEvent(contents, null, component, position); + } + + initializeRowWatchers() { + if (this.table.options.rowContextPopup) { + this.subscribe("row-contextmenu", this.loadPopupEvent.bind(this, this.table.options.rowContextPopup)); + this.table.on("rowTapHold", this.loadPopupEvent.bind(this, this.table.options.rowContextPopup)); + } + if (this.table.options.rowClickPopup) { + this.subscribe("row-click", this.loadPopupEvent.bind(this, this.table.options.rowClickPopup)); + } + if (this.table.options.rowDblClickPopup) { + this.subscribe("row-dblclick", this.loadPopupEvent.bind(this, this.table.options.rowDblClickPopup)); + } + } + + initializeGroupWatchers() { + if (this.table.options.groupContextPopup) { + this.subscribe("group-contextmenu", this.loadPopupEvent.bind(this, this.table.options.groupContextPopup)); + this.table.on("groupTapHold", this.loadPopupEvent.bind(this, this.table.options.groupContextPopup)); + } + if (this.table.options.groupClickPopup) { + this.subscribe("group-click", this.loadPopupEvent.bind(this, this.table.options.groupClickPopup)); + } + if (this.table.options.groupDblClickPopup) { + this.subscribe("group-dblclick", this.loadPopupEvent.bind(this, this.table.options.groupDblClickPopup)); + } + } + + initializeColumn(column) { + var def = column.definition; + if (def.headerContextPopup && !this.columnSubscribers.headerContextPopup) { + this.columnSubscribers.headerContextPopup = this.loadPopupTableColumnEvent.bind(this, "headerContextPopup"); + this.subscribe("column-contextmenu", this.columnSubscribers.headerContextPopup); + this.table.on("headerTapHold", this.loadPopupTableColumnEvent.bind(this, "headerContextPopup")); + } + if (def.headerClickPopup && !this.columnSubscribers.headerClickPopup) { + this.columnSubscribers.headerClickPopup = this.loadPopupTableColumnEvent.bind(this, "headerClickPopup"); + this.subscribe("column-click", this.columnSubscribers.headerClickPopup); + } + if (def.headerDblClickPopup && !this.columnSubscribers.headerDblClickPopup) { + this.columnSubscribers.headerDblClickPopup = this.loadPopupTableColumnEvent.bind(this, "headerDblClickPopup"); + this.subscribe("column-dblclick", this.columnSubscribers.headerDblClickPopup); + } + if (def.headerPopup) { + this.initializeColumnHeaderPopup(column); + } + if (def.contextPopup && !this.columnSubscribers.contextPopup) { + this.columnSubscribers.contextPopup = this.loadPopupTableCellEvent.bind(this, "contextPopup"); + this.subscribe("cell-contextmenu", this.columnSubscribers.contextPopup); + this.table.on("cellTapHold", this.loadPopupTableCellEvent.bind(this, "contextPopup")); + } + if (def.clickPopup && !this.columnSubscribers.clickPopup) { + this.columnSubscribers.clickPopup = this.loadPopupTableCellEvent.bind(this, "clickPopup"); + this.subscribe("cell-click", this.columnSubscribers.clickPopup); + } + if (def.dblClickPopup && !this.columnSubscribers.dblClickPopup) { + this.columnSubscribers.dblClickPopup = this.loadPopupTableCellEvent.bind(this, "dblClickPopup"); + this.subscribe("cell-click", this.columnSubscribers.dblClickPopup); + } + } + + initializeColumnHeaderPopup(column) { + var icon = column.definition.headerPopupIcon, headerPopupEl; + headerPopupEl = document.createElement("span"); + headerPopupEl.classList.add("tabulator-header-popup-button"); + if (icon) { + if (typeof icon === "function") { + icon = icon(column.getComponent()); + } + if (icon instanceof HTMLElement) { + headerPopupEl.appendChild(icon); + } else { + headerPopupEl.innerHTML = icon; + } + } else { + headerPopupEl.innerHTML = "⋮"; + } + headerPopupEl.addEventListener("click", (e) => { + e.stopPropagation(); + e.preventDefault(); + this.loadPopupEvent(column.definition.headerPopup, e, column); + }); + column.titleElement.insertBefore(headerPopupEl, column.titleElement.firstChild); + } + + loadPopupTableCellEvent(option, e, cell) { + if (cell._cell) { + cell = cell._cell; + } + if (cell.column.definition[option]) { + this.loadPopupEvent(cell.column.definition[option], e, cell); + } + } + + loadPopupTableColumnEvent(option, e, column) { + if (column._column) { + column = column._column; + } + if (column.definition[option]) { + this.loadPopupEvent(column.definition[option], e, column); + } + } + + loadPopupEvent(contents, e, component, position) { + var renderedCallback; + + function onRendered(callback) { + renderedCallback = callback; + } + + if (component._group) { + component = component._group; + } else if (component._row) { + component = component._row; + } + contents = typeof contents == "function" ? contents.call(this.table, e, component.getComponent(), onRendered) : contents; + this.loadPopup(e, component, contents, renderedCallback, position); + } + + loadPopup(e, component, contents, renderedCallback, position) { + var touch = !(e instanceof MouseEvent), contentsEl, popup; + if (contents instanceof HTMLElement) { + contentsEl = contents; + } else { + contentsEl = document.createElement("div"); + contentsEl.innerHTML = contents; + } + contentsEl.classList.add("tabulator-popup"); + contentsEl.addEventListener("click", (e2) => { + e2.stopPropagation(); + }); + if (!touch) { + e.preventDefault(); + } + popup = this.popup(contentsEl); + if (typeof renderedCallback === "function") { + popup.renderCallback(renderedCallback); + } + if (e) { + popup.show(e); + } else { + popup.show(component.getElement(), position || "center"); + } + popup.hideOnBlur(() => { + this.dispatchExternal("popupClosed", component.getComponent()); + }); + this.dispatchExternal("popupOpened", component.getComponent()); + } + } + + __publicField(Popup2, "moduleName", "popup"); + + class Print extends Module { + constructor(table) { + super(table); + this.element = false; + this.manualBlock = false; + this.beforeprintEventHandler = null; + this.afterprintEventHandler = null; + this.registerTableOption("printAsHtml", false); + this.registerTableOption("printFormatter", false); + this.registerTableOption("printHeader", false); + this.registerTableOption("printFooter", false); + this.registerTableOption("printStyled", true); + this.registerTableOption("printRowRange", "visible"); + this.registerTableOption("printConfig", {}); + this.registerColumnOption("print"); + this.registerColumnOption("titlePrint"); + } + + initialize() { + if (this.table.options.printAsHtml) { + this.beforeprintEventHandler = this.replaceTable.bind(this); + this.afterprintEventHandler = this.cleanup.bind(this); + window.addEventListener("beforeprint", this.beforeprintEventHandler); + window.addEventListener("afterprint", this.afterprintEventHandler); + this.subscribe("table-destroy", this.destroy.bind(this)); + } + this.registerTableFunction("print", this.printFullscreen.bind(this)); + } + + destroy() { + if (this.table.options.printAsHtml) { + window.removeEventListener("beforeprint", this.beforeprintEventHandler); + window.removeEventListener("afterprint", this.afterprintEventHandler); + } + } + + /////////////////////////////////// + ///////// Table Functions ///////// + /////////////////////////////////// + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + replaceTable() { + if (!this.manualBlock) { + this.element = document.createElement("div"); + this.element.classList.add("tabulator-print-table"); + this.element.appendChild(this.table.modules.export.generateTable(this.table.options.printConfig, this.table.options.printStyled, this.table.options.printRowRange, "print")); + this.table.element.style.display = "none"; + this.table.element.parentNode.insertBefore(this.element, this.table.element); + } + } + + cleanup() { + document.body.classList.remove("tabulator-print-fullscreen-hide"); + if (this.element && this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + this.table.element.style.display = ""; + } + } + + printFullscreen(visible, style, config) { + var scrollX = window.scrollX, scrollY = window.scrollY, headerEl = document.createElement("div"), + footerEl = document.createElement("div"), + tableEl = this.table.modules.export.generateTable(typeof config != "undefined" ? config : this.table.options.printConfig, typeof style != "undefined" ? style : this.table.options.printStyled, visible || this.table.options.printRowRange, "print"), + headerContent, footerContent; + this.manualBlock = true; + this.element = document.createElement("div"); + this.element.classList.add("tabulator-print-fullscreen"); + if (this.table.options.printHeader) { + headerEl.classList.add("tabulator-print-header"); + headerContent = typeof this.table.options.printHeader == "function" ? this.table.options.printHeader.call(this.table) : this.table.options.printHeader; + if (typeof headerContent == "string") { + headerEl.innerHTML = headerContent; + } else { + headerEl.appendChild(headerContent); + } + this.element.appendChild(headerEl); + } + this.element.appendChild(tableEl); + if (this.table.options.printFooter) { + footerEl.classList.add("tabulator-print-footer"); + footerContent = typeof this.table.options.printFooter == "function" ? this.table.options.printFooter.call(this.table) : this.table.options.printFooter; + if (typeof footerContent == "string") { + footerEl.innerHTML = footerContent; + } else { + footerEl.appendChild(footerContent); + } + this.element.appendChild(footerEl); + } + document.body.classList.add("tabulator-print-fullscreen-hide"); + document.body.appendChild(this.element); + if (this.table.options.printFormatter) { + this.table.options.printFormatter(this.element, tableEl); + } + window.print(); + this.cleanup(); + window.scrollTo(scrollX, scrollY); + this.manualBlock = false; + } + } + + __publicField(Print, "moduleName", "print"); + + class ReactiveData extends Module { + constructor(table) { + super(table); + this.data = false; + this.blocked = false; + this.origFuncs = {}; + this.currentVersion = 0; + this.registerTableOption("reactiveData", false); + } + + initialize() { + if (this.table.options.reactiveData) { + this.subscribe("cell-value-save-before", this.block.bind(this, "cellsave")); + this.subscribe("cell-value-save-after", this.unblock.bind(this, "cellsave")); + this.subscribe("row-data-save-before", this.block.bind(this, "rowsave")); + this.subscribe("row-data-save-after", this.unblock.bind(this, "rowsave")); + this.subscribe("row-data-init-after", this.watchRow.bind(this)); + this.subscribe("data-processing", this.watchData.bind(this)); + this.subscribe("table-destroy", this.unwatchData.bind(this)); + } + } + + watchData(data) { + var self = this, version; + this.currentVersion++; + version = this.currentVersion; + this.unwatchData(); + this.data = data; + this.origFuncs.push = data.push; + Object.defineProperty(this.data, "push", { + enumerable: false, + configurable: true, + value: function () { + var args = Array.from(arguments), result; + if (!self.blocked && version === self.currentVersion) { + self.block("data-push"); + args.forEach((arg) => { + self.table.rowManager.addRowActual(arg, false); + }); + result = Array.prototype.push.apply(data, arguments); + self.unblock("data-push"); + } + return result; + } + }); + this.origFuncs.unshift = data.unshift; + Object.defineProperty(this.data, "unshift", { + enumerable: false, + configurable: true, + value: function () { + var args = Array.from(arguments), result; + if (!self.blocked && version === self.currentVersion) { + self.block("data-unshift"); + args.forEach((arg) => { + self.table.rowManager.addRowActual(arg, true); + }); + result = Array.prototype.unshift.apply(data, arguments); + self.unblock("data-unshift"); + } + return result; + } + }); + this.origFuncs.shift = data.shift; + Object.defineProperty(this.data, "shift", { + enumerable: false, + configurable: true, + value: function () { + var row, result; + if (!self.blocked && version === self.currentVersion) { + self.block("data-shift"); + if (self.data.length) { + row = self.table.rowManager.getRowFromDataObject(self.data[0]); + if (row) { + row.deleteActual(); + } + } + result = Array.prototype.shift.call(data); + self.unblock("data-shift"); + } + return result; + } + }); + this.origFuncs.pop = data.pop; + Object.defineProperty(this.data, "pop", { + enumerable: false, + configurable: true, + value: function () { + var row, result; + if (!self.blocked && version === self.currentVersion) { + self.block("data-pop"); + if (self.data.length) { + row = self.table.rowManager.getRowFromDataObject(self.data[self.data.length - 1]); + if (row) { + row.deleteActual(); + } + } + result = Array.prototype.pop.call(data); + self.unblock("data-pop"); + } + return result; + } + }); + this.origFuncs.splice = data.splice; + Object.defineProperty(this.data, "splice", { + enumerable: false, + configurable: true, + value: function () { + var args = Array.from(arguments), start = args[0] < 0 ? data.length + args[0] : args[0], + end = args[1], newRows = args[2] ? args.slice(2) : false, startRow, result; + if (!self.blocked && version === self.currentVersion) { + self.block("data-splice"); + if (newRows) { + startRow = data[start] ? self.table.rowManager.getRowFromDataObject(data[start]) : false; + if (startRow) { + newRows.forEach((rowData) => { + self.table.rowManager.addRowActual(rowData, true, startRow, true); + }); + } else { + newRows = newRows.slice().reverse(); + newRows.forEach((rowData) => { + self.table.rowManager.addRowActual(rowData, true, false, true); + }); + } + } + if (end !== 0) { + var oldRows = data.slice(start, typeof args[1] === "undefined" ? args[1] : start + end); + oldRows.forEach((rowData, i) => { + var row = self.table.rowManager.getRowFromDataObject(rowData); + if (row) { + row.deleteActual(i !== oldRows.length - 1); + } + }); + } + if (newRows || end !== 0) { + self.table.rowManager.reRenderInPosition(); + } + result = Array.prototype.splice.apply(data, arguments); + self.unblock("data-splice"); + } + return result; + } + }); + } + + unwatchData() { + if (this.data !== false) { + for (var key in this.origFuncs) { + Object.defineProperty(this.data, key, { + enumerable: true, + configurable: true, + writable: true, + value: this.origFuncs[key] + }); + } + } + } + + watchRow(row) { + var data = row.getData(); + for (var key in data) { + this.watchKey(row, data, key); + } + if (this.table.options.dataTree) { + this.watchTreeChildren(row); + } + } + + watchTreeChildren(row) { + var self = this, childField = row.getData()[this.table.options.dataTreeChildField]; + if (childField) { + Object.defineProperty(childField, "push", { + enumerable: false, + configurable: true, + value: function () { + var result; + if (!self.blocked) { + self.block("tree-push"); + result = Array.prototype.push.apply(childField, arguments); + self.rebuildTree(row); + self.unblock("tree-push"); + } + return result; + } + }); + Object.defineProperty(childField, "unshift", { + enumerable: false, + configurable: true, + value: function () { + var result; + if (!self.blocked) { + self.block("tree-unshift"); + result = Array.prototype.unshift.apply(childField, arguments); + self.rebuildTree(row); + self.unblock("tree-unshift"); + } + return result; + } + }); + Object.defineProperty(childField, "shift", { + enumerable: false, + configurable: true, + value: function () { + var result; + if (!self.blocked) { + self.block("tree-shift"); + result = Array.prototype.shift.call(childField); + self.rebuildTree(row); + self.unblock("tree-shift"); + } + return result; + } + }); + Object.defineProperty(childField, "pop", { + enumerable: false, + configurable: true, + value: function () { + var result; + if (!self.blocked) { + self.block("tree-pop"); + result = Array.prototype.pop.call(childField); + self.rebuildTree(row); + self.unblock("tree-pop"); + } + return result; + } + }); + Object.defineProperty(childField, "splice", { + enumerable: false, + configurable: true, + value: function () { + var result; + if (!self.blocked) { + self.block("tree-splice"); + result = Array.prototype.splice.apply(childField, arguments); + self.rebuildTree(row); + self.unblock("tree-splice"); + } + return result; + } + }); + } + } + + rebuildTree(row) { + this.table.modules.dataTree.initializeRow(row); + this.table.modules.dataTree.layoutRow(row); + this.table.rowManager.refreshActiveData("tree", false, true); + } + + watchKey(row, data, key) { + var self = this, props = Object.getOwnPropertyDescriptor(data, key), value = data[key], + version = this.currentVersion; + Object.defineProperty(data, key, { + set: (newValue) => { + value = newValue; + if (!self.blocked && version === self.currentVersion) { + self.block("key"); + var update = {}; + update[key] = newValue; + row.updateData(update); + self.unblock("key"); + } + if (props.set) { + props.set(newValue); + } + }, + get: () => { + if (props.get) { + props.get(); + } + return value; + } + }); + } + + unwatchRow(row) { + var data = row.getData(); + for (var key in data) { + Object.defineProperty(data, key, { + value: data[key] + }); + } + } + + block(key) { + if (!this.blocked) { + this.blocked = key; + } + } + + unblock(key) { + if (this.blocked === key) { + this.blocked = false; + } + } + } + + __publicField(ReactiveData, "moduleName", "reactiveData"); + + class ResizeColumns extends Module { + constructor(table) { + super(table); + this.startColumn = false; + this.startX = false; + this.startWidth = false; + this.latestX = false; + this.handle = null; + this.initialNextColumn = null; + this.nextColumn = null; + this.initialized = false; + this.registerColumnOption("resizable", true); + this.registerTableOption("resizableColumnFit", false); + this.registerTableOption("resizableColumnGuide", false); + } + + initialize() { + this.subscribe("column-rendered", this.layoutColumnHeader.bind(this)); + } + + initializeEventWatchers() { + if (!this.initialized) { + this.subscribe("cell-rendered", this.layoutCellHandles.bind(this)); + this.subscribe("cell-delete", this.deInitializeComponent.bind(this)); + this.subscribe("cell-height", this.resizeHandle.bind(this)); + this.subscribe("column-moved", this.columnLayoutUpdated.bind(this)); + this.subscribe("column-hide", this.deInitializeColumn.bind(this)); + this.subscribe("column-show", this.columnLayoutUpdated.bind(this)); + this.subscribe("column-width", this.columnWidthUpdated.bind(this)); + this.subscribe("column-delete", this.deInitializeComponent.bind(this)); + this.subscribe("column-height", this.resizeHandle.bind(this)); + this.initialized = true; + } + } + + layoutCellHandles(cell) { + if (cell.row.type === "row") { + this.deInitializeComponent(cell); + this.initializeColumn("cell", cell, cell.column, cell.element); + } + } + + layoutColumnHeader(column) { + if (column.definition.resizable) { + this.initializeEventWatchers(); + this.deInitializeComponent(column); + this.initializeColumn("header", column, column, column.element); + } + } + + columnLayoutUpdated(column) { + var prev = column.prevColumn(); + this.reinitializeColumn(column); + if (prev) { + this.reinitializeColumn(prev); + } + } + + columnWidthUpdated(column) { + if (column.modules.frozen) { + if (this.table.modules.frozenColumns.leftColumns.includes(column)) { + this.table.modules.frozenColumns.leftColumns.forEach((col) => { + this.reinitializeColumn(col); + }); + } else if (this.table.modules.frozenColumns.rightColumns.includes(column)) { + this.table.modules.frozenColumns.rightColumns.forEach((col) => { + this.reinitializeColumn(col); + }); + } + } + } + + frozenColumnOffset(column) { + var offset = false; + if (column.modules.frozen) { + offset = column.modules.frozen.marginValue; + if (column.modules.frozen.position === "left") { + offset += column.getWidth() - 3; + } else { + if (offset) { + offset -= 3; + } + } + } + return offset !== false ? offset + "px" : false; + } + + reinitializeColumn(column) { + var frozenOffset = this.frozenColumnOffset(column); + column.cells.forEach((cell) => { + if (cell.modules.resize && cell.modules.resize.handleEl) { + if (frozenOffset) { + cell.modules.resize.handleEl.style[column.modules.frozen.position] = frozenOffset; + cell.modules.resize.handleEl.style["z-index"] = 11; + } + cell.element.after(cell.modules.resize.handleEl); + } + }); + if (column.modules.resize && column.modules.resize.handleEl) { + if (frozenOffset) { + column.modules.resize.handleEl.style[column.modules.frozen.position] = frozenOffset; + } + column.element.after(column.modules.resize.handleEl); + } + } + + initializeColumn(type, component, column, element) { + var self = this, variableHeight = false, mode = column.definition.resizable, config = {}, + nearestColumn = column.getLastColumn(); + if (type === "header") { + variableHeight = column.definition.formatter == "textarea" || column.definition.variableHeight; + config = {variableHeight}; + } + if ((mode === true || mode == type) && this._checkResizability(nearestColumn)) { + var handle2 = document.createElement("span"); + handle2.className = "tabulator-col-resize-handle"; + handle2.addEventListener("click", function (e) { + e.stopPropagation(); + }); + var handleDown = function (e) { + self.startColumn = column; + self.initialNextColumn = self.nextColumn = nearestColumn.nextColumn(); + self._mouseDown(e, nearestColumn, handle2); + }; + handle2.addEventListener("mousedown", handleDown); + handle2.addEventListener("touchstart", handleDown, {passive: true}); + handle2.addEventListener("dblclick", (e) => { + var oldWidth = nearestColumn.getWidth(); + e.stopPropagation(); + nearestColumn.reinitializeWidth(true); + if (oldWidth !== nearestColumn.getWidth()) { + self.dispatch("column-resized", nearestColumn); + self.dispatchExternal("columnResized", nearestColumn.getComponent()); + } + }); + if (column.modules.frozen) { + handle2.style.position = "sticky"; + handle2.style[column.modules.frozen.position] = this.frozenColumnOffset(column); + } + config.handleEl = handle2; + if (element.parentNode && column.visible) { + element.after(handle2); + } + } + component.modules.resize = config; + } + + deInitializeColumn(column) { + this.deInitializeComponent(column); + column.cells.forEach((cell) => { + this.deInitializeComponent(cell); + }); + } + + deInitializeComponent(component) { + var handleEl; + if (component.modules.resize) { + handleEl = component.modules.resize.handleEl; + if (handleEl && handleEl.parentElement) { + handleEl.parentElement.removeChild(handleEl); + } + } + } + + resizeHandle(component, height) { + if (component.modules.resize && component.modules.resize.handleEl) { + component.modules.resize.handleEl.style.height = height; + } + } + + getResizingClientX(e) { + var _a2, _b; + if (typeof e.clientX !== "undefined") return e.clientX; + const touch = this.table.options.resizableColumnGuide ? (_a2 = e.changedTouches) == null ? void 0 : _a2[0] : (_b = e.touches) == null ? void 0 : _b[0]; + return touch == null ? void 0 : touch.clientX; + } + + resize(e, column) { + var x = this.getResizingClientX(e); + if (typeof x !== "number" || !isFinite(x)) { + console.warn("ResizeColumns: could not resolve pointer X from event", e); + return; + } + var startDiff = x - this.startX, moveDiff = x - this.latestX, blockedBefore, blockedAfter; + this.latestX = x; + if (this.table.rtl) { + startDiff = -startDiff; + moveDiff = -moveDiff; + } + blockedBefore = column.width == column.minWidth || column.width == column.maxWidth; + column.setWidth(this.startWidth + startDiff); + blockedAfter = column.width == column.minWidth || column.width == column.maxWidth; + if (moveDiff < 0) { + this.nextColumn = this.initialNextColumn; + } + if (this.table.options.resizableColumnFit && this.nextColumn && !(blockedBefore && blockedAfter)) { + let colWidth = this.nextColumn.getWidth(); + if (moveDiff > 0) { + if (colWidth <= this.nextColumn.minWidth) { + this.nextColumn = this.nextColumn.nextColumn(); + } + } + if (this.nextColumn) { + this.nextColumn.setWidth(this.nextColumn.getWidth() - moveDiff); + } + } + this.table.columnManager.rerenderColumns(true); + if (!this.table.browserSlow && column.modules.resize && column.modules.resize.variableHeight) { + column.checkCellHeights(); + } + } + + calcGuidePosition(e, column, handle2) { + var mouseX = typeof e.clientX === "undefined" ? e.touches[0].clientX : e.clientX, + handleX = handle2.getBoundingClientRect().x - this.table.element.getBoundingClientRect().x, + tableX = this.table.element.getBoundingClientRect().x, + columnX = column.element.getBoundingClientRect().left - tableX, mouseDiff = mouseX - this.startX, + pos = Math.max(handleX + mouseDiff, columnX + column.minWidth); + if (column.maxWidth) { + pos = Math.min(pos, columnX + column.maxWidth); + } + return pos; + } + + _checkResizability(column) { + return column.definition.resizable; + } + + _mouseDown(e, column, handle2) { + var self = this, guideEl; + this.dispatchExternal("columnResizing", column.getComponent()); + if (self.table.options.resizableColumnGuide) { + guideEl = document.createElement("span"); + guideEl.classList.add("tabulator-col-resize-guide"); + self.table.element.appendChild(guideEl); + setTimeout(() => { + guideEl.style.left = self.calcGuidePosition(e, column, handle2) + "px"; + }); + } + self.table.element.classList.add("tabulator-block-select"); + + function mouseMove(e2) { + if (self.table.options.resizableColumnGuide) { + guideEl.style.left = self.calcGuidePosition(e2, column, handle2) + "px"; + } else { + self.resize(e2, column); + } + } + + function mouseUp(e2) { + if (self.table.options.resizableColumnGuide) { + self.resize(e2, column); + guideEl.remove(); + } + if (self.startColumn.modules.edit) { + self.startColumn.modules.edit.blocked = false; + } + if (self.table.browserSlow && column.modules.resize && column.modules.resize.variableHeight) { + column.checkCellHeights(); + } + document.body.removeEventListener("mouseup", mouseUp); + document.body.removeEventListener("mousemove", mouseMove); + handle2.removeEventListener("touchmove", mouseMove); + handle2.removeEventListener("touchend", mouseUp); + self.table.element.classList.remove("tabulator-block-select"); + if (self.startWidth !== column.getWidth()) { + self.table.columnManager.verticalAlignHeaders(); + self.dispatch("column-resized", column); + self.dispatchExternal("columnResized", column.getComponent()); + } + } + + e.stopPropagation(); + if (self.startColumn.modules.edit) { + self.startColumn.modules.edit.blocked = true; + } + self.startX = typeof e.clientX === "undefined" ? e.touches[0].clientX : e.clientX; + self.latestX = self.startX; + self.startWidth = column.getWidth(); + document.body.addEventListener("mousemove", mouseMove); + document.body.addEventListener("mouseup", mouseUp); + handle2.addEventListener("touchmove", mouseMove, {passive: true}); + handle2.addEventListener("touchend", mouseUp); + } + } + + __publicField(ResizeColumns, "moduleName", "resizeColumns"); + + class ResizeRows extends Module { + constructor(table) { + super(table); + this.startColumn = false; + this.startY = false; + this.startHeight = false; + this.handle = null; + this.prevHandle = null; + this.registerTableOption("resizableRows", false); + this.registerTableOption("resizableRowGuide", false); + } + + initialize() { + if (this.table.options.resizableRows) { + this.subscribe("row-layout-after", this.initializeRow.bind(this)); + } + } + + initializeRow(row) { + var self = this, rowEl = row.getElement(); + var handle2 = document.createElement("div"); + handle2.className = "tabulator-row-resize-handle"; + var prevHandle = document.createElement("div"); + prevHandle.className = "tabulator-row-resize-handle prev"; + handle2.addEventListener("click", function (e) { + e.stopPropagation(); + }); + var handleDown = function (e) { + self.startRow = row; + self._mouseDown(e, row, handle2); + }; + handle2.addEventListener("mousedown", handleDown); + handle2.addEventListener("touchstart", handleDown, {passive: true}); + prevHandle.addEventListener("click", function (e) { + e.stopPropagation(); + }); + var prevHandleDown = function (e) { + var prevRow = self.table.rowManager.prevDisplayRow(row); + if (prevRow) { + self.startRow = prevRow; + self._mouseDown(e, prevRow, prevHandle); + } + }; + prevHandle.addEventListener("mousedown", prevHandleDown); + prevHandle.addEventListener("touchstart", prevHandleDown, {passive: true}); + rowEl.appendChild(handle2); + rowEl.appendChild(prevHandle); + } + + resize(e, row) { + row.setHeight(this.startHeight + ((typeof e.screenY === "undefined" ? e.touches[0].screenY : e.screenY) - this.startY)); + } + + calcGuidePosition(e, row, handle2) { + var mouseY = typeof e.screenY === "undefined" ? e.touches[0].screenY : e.screenY, + handleY = handle2.getBoundingClientRect().y - this.table.element.getBoundingClientRect().y, + tableY = this.table.element.getBoundingClientRect().y, + rowY = row.element.getBoundingClientRect().top - tableY, mouseDiff = mouseY - this.startY; + return Math.max(handleY + mouseDiff, rowY); + } + + _mouseDown(e, row, handle2) { + var self = this, guideEl; + self.dispatchExternal("rowResizing", row.getComponent()); + if (self.table.options.resizableRowGuide) { + guideEl = document.createElement("span"); + guideEl.classList.add("tabulator-row-resize-guide"); + self.table.element.appendChild(guideEl); + setTimeout(() => { + guideEl.style.top = self.calcGuidePosition(e, row, handle2) + "px"; + }); + } + self.table.element.classList.add("tabulator-block-select"); + + function mouseMove(e2) { + if (self.table.options.resizableRowGuide) { + guideEl.style.top = self.calcGuidePosition(e2, row, handle2) + "px"; + } else { + self.resize(e2, row); + } + } + + function mouseUp(e2) { + if (self.table.options.resizableRowGuide) { + self.resize(e2, row); + guideEl.remove(); + } + document.body.removeEventListener("mouseup", mouseMove); + document.body.removeEventListener("mousemove", mouseMove); + handle2.removeEventListener("touchmove", mouseMove); + handle2.removeEventListener("touchend", mouseUp); + self.table.element.classList.remove("tabulator-block-select"); + self.dispatchExternal("rowResized", row.getComponent()); + } + + e.stopPropagation(); + self.startY = typeof e.screenY === "undefined" ? e.touches[0].screenY : e.screenY; + self.startHeight = row.getHeight(); + document.body.addEventListener("mousemove", mouseMove); + document.body.addEventListener("mouseup", mouseUp); + handle2.addEventListener("touchmove", mouseMove, {passive: true}); + handle2.addEventListener("touchend", mouseUp); + } + } + + __publicField(ResizeRows, "moduleName", "resizeRows"); + + class ResizeTable extends Module { + constructor(table) { + super(table); + this.binding = false; + this.visibilityObserver = false; + this.resizeObserver = false; + this.containerObserver = false; + this.tableHeight = 0; + this.tableWidth = 0; + this.containerHeight = 0; + this.containerWidth = 0; + this.autoResize = false; + this.visible = false; + this.initialized = false; + this.initialRedraw = false; + this.registerTableOption("autoResize", true); + } + + initialize() { + if (this.table.options.autoResize) { + var table = this.table, tableStyle; + this.tableHeight = table.element.clientHeight; + this.tableWidth = table.element.clientWidth; + if (table.element.parentNode) { + this.containerHeight = table.element.parentNode.clientHeight; + this.containerWidth = table.element.parentNode.clientWidth; + } + if (typeof IntersectionObserver !== "undefined" && typeof ResizeObserver !== "undefined" && table.rowManager.getRenderMode() === "virtual") { + this.initializeVisibilityObserver(); + this.autoResize = true; + this.resizeObserver = new ResizeObserver((entry) => { + if (!table.browserMobile || table.browserMobile && (!table.modules.edit || table.modules.edit && !table.modules.edit.currentCell)) { + var nodeHeight = Math.floor(entry[0].contentRect.height); + var nodeWidth = Math.floor(entry[0].contentRect.width); + if (this.tableHeight != nodeHeight || this.tableWidth != nodeWidth) { + this.tableHeight = nodeHeight; + this.tableWidth = nodeWidth; + if (table.element.parentNode) { + this.containerHeight = table.element.parentNode.clientHeight; + this.containerWidth = table.element.parentNode.clientWidth; + } + this.redrawTable(); + } + } + }); + this.resizeObserver.observe(table.element); + tableStyle = window.getComputedStyle(table.element); + if (this.table.element.parentNode && !this.table.rowManager.fixedHeight && (tableStyle.getPropertyValue("max-height") || tableStyle.getPropertyValue("min-height"))) { + this.containerObserver = new ResizeObserver((entry) => { + if (!table.browserMobile || table.browserMobile && (!table.modules.edit || table.modules.edit && !table.modules.edit.currentCell)) { + var nodeHeight = Math.floor(entry[0].contentRect.height); + var nodeWidth = Math.floor(entry[0].contentRect.width); + if (this.containerHeight != nodeHeight || this.containerWidth != nodeWidth) { + this.containerHeight = nodeHeight; + this.containerWidth = nodeWidth; + this.tableHeight = table.element.clientHeight; + this.tableWidth = table.element.clientWidth; + } + this.redrawTable(); + } + }); + this.containerObserver.observe(this.table.element.parentNode); + } + this.subscribe("table-resize", this.tableResized.bind(this)); + } else { + this.binding = function () { + if (!table.browserMobile || table.browserMobile && (!table.modules.edit || table.modules.edit && !table.modules.edit.currentCell)) { + table.columnManager.rerenderColumns(true); + table.redraw(); + } + }; + window.addEventListener("resize", this.binding); + } + this.subscribe("table-destroy", this.clearBindings.bind(this)); + } + } + + initializeVisibilityObserver() { + this.visibilityObserver = new IntersectionObserver((entries) => { + this.visible = entries[entries.length - 1].isIntersecting; + if (!this.initialized) { + this.initialized = true; + this.initialRedraw = !this.visible; + } else { + if (this.visible) { + this.redrawTable(this.initialRedraw); + this.initialRedraw = false; + } + } + }); + this.visibilityObserver.observe(this.table.element); + } + + redrawTable(force) { + if (this.initialized && this.visible) { + this.table.columnManager.rerenderColumns(true); + this.table.redraw(force); + } + } + + tableResized() { + this.table.rowManager.redraw(); + } + + clearBindings() { + if (this.binding) { + window.removeEventListener("resize", this.binding); + } + if (this.resizeObserver) { + this.resizeObserver.unobserve(this.table.element); + } + if (this.visibilityObserver) { + this.visibilityObserver.unobserve(this.table.element); + } + if (this.containerObserver) { + this.containerObserver.unobserve(this.table.element.parentNode); + } + } + } + + __publicField(ResizeTable, "moduleName", "resizeTable"); + + function responsiveCollapse(cell, formatterParams, onRendered) { + var el = document.createElement("div"), config = cell.getRow()._row.modules.responsiveLayout; + el.classList.add("tabulator-responsive-collapse-toggle"); + el.innerHTML = ` + + + + + + +`; + cell.getElement().classList.add("tabulator-row-handle"); + + function toggleList(isOpen) { + var collapseEl = config.element; + config.open = isOpen; + if (collapseEl) { + if (config.open) { + el.classList.add("open"); + collapseEl.style.display = ""; + } else { + el.classList.remove("open"); + collapseEl.style.display = "none"; + } + } + } + + el.addEventListener("click", function (e) { + e.stopImmediatePropagation(); + toggleList(!config.open); + cell.getTable().rowManager.adjustTableSize(); + }); + toggleList(config.open); + return el; + } + + var extensions$2 = { + format: { + formatters: { + responsiveCollapse + } + } + }; + + class ResponsiveLayout extends Module { + constructor(table) { + super(table); + this.columns = []; + this.hiddenColumns = []; + this.mode = ""; + this.index = 0; + this.collapseFormatter = []; + this.collapseStartOpen = true; + this.collapseHandleColumn = false; + this.registerTableOption("responsiveLayout", false); + this.registerTableOption("responsiveLayoutCollapseStartOpen", true); + this.registerTableOption("responsiveLayoutCollapseUseFormatters", true); + this.registerTableOption("responsiveLayoutCollapseFormatter", false); + this.registerColumnOption("responsive"); + } + + //generate responsive columns list + initialize() { + if (this.table.options.responsiveLayout) { + this.subscribe("column-layout", this.initializeColumn.bind(this)); + this.subscribe("column-show", this.updateColumnVisibility.bind(this)); + this.subscribe("column-hide", this.updateColumnVisibility.bind(this)); + this.subscribe("columns-loaded", this.initializeResponsivity.bind(this)); + this.subscribe("column-moved", this.initializeResponsivity.bind(this)); + this.subscribe("column-add", this.initializeResponsivity.bind(this)); + this.subscribe("column-delete", this.initializeResponsivity.bind(this)); + this.subscribe("table-redrawing", this.tableRedraw.bind(this)); + if (this.table.options.responsiveLayout === "collapse") { + this.subscribe("row-data-changed", this.generateCollapsedRowContent.bind(this)); + this.subscribe("row-init", this.initializeRow.bind(this)); + this.subscribe("row-layout", this.layoutRow.bind(this)); + } + } + } + + tableRedraw(force) { + if (["fitColumns", "fitDataStretch"].indexOf(this.layoutMode()) === -1) { + if (!force) { + this.update(); + } + } + } + + initializeResponsivity() { + var columns = []; + this.mode = this.table.options.responsiveLayout; + this.collapseFormatter = this.table.options.responsiveLayoutCollapseFormatter || this.formatCollapsedData; + this.collapseStartOpen = this.table.options.responsiveLayoutCollapseStartOpen; + this.hiddenColumns = []; + if (this.collapseFormatter) { + this.collapseFormatter = this.collapseFormatter.bind(this.table); + } + this.table.columnManager.columnsByIndex.forEach((column, i) => { + if (column.modules.responsive) { + if (column.modules.responsive.order && column.modules.responsive.visible) { + column.modules.responsive.index = i; + columns.push(column); + if (!column.visible && this.mode === "collapse") { + this.hiddenColumns.push(column); + } + } + } + }); + columns = columns.reverse(); + columns = columns.sort((a, b) => { + var diff = b.modules.responsive.order - a.modules.responsive.order; + return diff || b.modules.responsive.index - a.modules.responsive.index; + }); + this.columns = columns; + if (this.mode === "collapse") { + this.generateCollapsedContent(); + } + for (let col of this.table.columnManager.columnsByIndex) { + if (col.definition.formatter == "responsiveCollapse") { + this.collapseHandleColumn = col; + break; + } + } + if (this.collapseHandleColumn) { + if (this.hiddenColumns.length) { + this.collapseHandleColumn.show(); + } else { + this.collapseHandleColumn.hide(); + } + } + } + + //define layout information + initializeColumn(column) { + var def = column.getDefinition(); + column.modules.responsive = { + order: typeof def.responsive === "undefined" ? 1 : def.responsive, + visible: def.visible === false ? false : true + }; + } + + initializeRow(row) { + var el; + if (row.type !== "calc") { + el = document.createElement("div"); + el.classList.add("tabulator-responsive-collapse"); + row.modules.responsiveLayout = { + element: el, + open: this.collapseStartOpen + }; + if (!this.collapseStartOpen) { + el.style.display = "none"; + } + } + } + + layoutRow(row) { + var rowEl = row.getElement(); + if (row.modules.responsiveLayout) { + rowEl.appendChild(row.modules.responsiveLayout.element); + this.generateCollapsedRowContent(row); + } + } + + //update column visibility + updateColumnVisibility(column, responsiveToggle) { + if (!responsiveToggle && column.modules.responsive) { + column.modules.responsive.visible = column.visible; + this.initializeResponsivity(); + } + } + + hideColumn(column) { + var colCount = this.hiddenColumns.length; + column.hide(false, true); + if (this.mode === "collapse") { + this.hiddenColumns.unshift(column); + this.generateCollapsedContent(); + if (this.collapseHandleColumn && !colCount) { + this.collapseHandleColumn.show(); + } + } + } + + showColumn(column) { + var index; + column.show(false, true); + column.setWidth(column.getWidth()); + if (this.mode === "collapse") { + index = this.hiddenColumns.indexOf(column); + if (index > -1) { + this.hiddenColumns.splice(index, 1); + } + this.generateCollapsedContent(); + if (this.collapseHandleColumn && !this.hiddenColumns.length) { + this.collapseHandleColumn.hide(); + } + } + } + + //redraw columns to fit space + update() { + var working = true; + while (working) { + let width = this.table.modules.layout.getMode() == "fitColumns" ? this.table.columnManager.getFlexBaseWidth() : this.table.columnManager.getWidth(); + let diff = (this.table.options.headerVisible ? this.table.columnManager.element.clientWidth : this.table.element.clientWidth) - width; + if (diff < 0) { + let column = this.columns[this.index]; + if (column) { + this.hideColumn(column); + this.index++; + } else { + working = false; + } + } else { + let column = this.columns[this.index - 1]; + if (column) { + if (diff > 0) { + if (diff >= column.getWidth()) { + this.showColumn(column); + this.index--; + } else { + working = false; + } + } else { + working = false; + } + } else { + working = false; + } + } + if (!this.table.rowManager.activeRowsCount) { + this.table.rowManager.renderEmptyScroll(); + } + } + } + + generateCollapsedContent() { + var rows2 = this.table.rowManager.getDisplayRows(); + rows2.forEach((row) => { + this.generateCollapsedRowContent(row); + }); + } + + generateCollapsedRowContent(row) { + var el, contents; + if (row.modules.responsiveLayout) { + el = row.modules.responsiveLayout.element; + while (el.firstChild) el.removeChild(el.firstChild); + contents = this.collapseFormatter(this.generateCollapsedRowData(row)); + if (contents) { + el.appendChild(contents); + } + row.calcHeight(true); + } + } + + generateCollapsedRowData(row) { + var data = row.getData(), output = [], mockCellComponent; + this.hiddenColumns.forEach((column) => { + var value = column.getFieldValue(data); + if (column.definition.title && column.field) { + if (column.modules.format && this.table.options.responsiveLayoutCollapseUseFormatters) { + let onRendered = function (callback) { + callback(); + }; + mockCellComponent = { + value: false, + data: {}, + getValue: function () { + return value; + }, + getData: function () { + return data; + }, + getType: function () { + return "cell"; + }, + getElement: function () { + return document.createElement("div"); + }, + getRow: function () { + return row.getComponent(); + }, + getColumn: function () { + return column.getComponent(); + }, + getTable: () => { + return this.table; + } + }; + output.push({ + field: column.field, + title: column.definition.title, + value: column.modules.format.formatter.call(this.table.modules.format, mockCellComponent, column.modules.format.params, onRendered) + }); + } else { + output.push({ + field: column.field, + title: column.definition.title, + value + }); + } + } + }); + return output; + } + + formatCollapsedData(data) { + var list2 = document.createElement("table"); + data.forEach((item) => { + var row = document.createElement("tr"); + var titleData = document.createElement("td"); + var valueData = document.createElement("td"); + var node_content; + var titleHighlight = document.createElement("strong"); + titleData.appendChild(titleHighlight); + this.modules.localize.bind("columns|" + item.field, function (text) { + titleHighlight.innerHTML = text || item.title; + }); + if (item.value instanceof Node) { + node_content = document.createElement("div"); + node_content.appendChild(item.value); + valueData.appendChild(node_content); + } else { + valueData.innerHTML = item.value; + } + row.appendChild(titleData); + row.appendChild(valueData); + list2.appendChild(row); + }); + return Object.keys(data).length ? list2 : ""; + } + } + + __publicField(ResponsiveLayout, "moduleName", "responsiveLayout"); + __publicField(ResponsiveLayout, "moduleExtensions", extensions$2); + + function rowSelection(cell, formatterParams, onRendered) { + var checkbox = document.createElement("input"); + var blocked = false; + checkbox.type = "checkbox"; + checkbox.setAttribute("aria-label", "Select Row"); + if (this.table.modExists("selectRow", true)) { + checkbox.addEventListener("click", (e) => { + e.stopPropagation(); + }); + if (typeof cell.getRow == "function") { + var row = cell.getRow(); + if (row instanceof RowComponent) { + checkbox.addEventListener("change", (e) => { + if (this.table.options.selectableRowsRangeMode === "click") { + if (!blocked) { + row.toggleSelect(); + } else { + blocked = false; + } + } else { + row.toggleSelect(); + } + }); + if (this.table.options.selectableRowsRangeMode === "click") { + checkbox.addEventListener("click", (e) => { + blocked = true; + this.table.modules.selectRow.handleComplexRowClick(row._row, e); + }); + } + checkbox.checked = row.isSelected && row.isSelected(); + this.table.modules.selectRow.registerRowSelectCheckbox(row, checkbox); + } else { + checkbox = ""; + } + } else { + checkbox.addEventListener("change", (e) => { + if (this.table.modules.selectRow.selectedRows.length) { + this.table.deselectRow(); + } else { + this.table.selectRow(formatterParams.rowRange); + } + }); + this.table.modules.selectRow.registerHeaderSelectCheckbox(checkbox); + } + } + return checkbox; + } + + var extensions$1 = { + format: { + formatters: { + rowSelection + } + } + }; + + class SelectRow extends Module { + constructor(table) { + super(table); + this.selecting = false; + this.lastClickedRow = false; + this.selectPrev = []; + this.selectedRows = []; + this.headerCheckboxElement = null; + this.registerTableOption("selectableRows", "highlight"); + this.registerTableOption("selectableRowsRangeMode", "drag"); + this.registerTableOption("selectableRowsRollingSelection", true); + this.registerTableOption("selectableRowsPersistence", true); + this.registerTableOption("selectableRowsCheck", function (data, row) { + return true; + }); + this.registerTableFunction("selectRow", this.selectRows.bind(this)); + this.registerTableFunction("deselectRow", this.deselectRows.bind(this)); + this.registerTableFunction("toggleSelectRow", this.toggleRow.bind(this)); + this.registerTableFunction("getSelectedRows", this.getSelectedRows.bind(this)); + this.registerTableFunction("getSelectedData", this.getSelectedData.bind(this)); + this.registerComponentFunction("row", "select", this.selectRows.bind(this)); + this.registerComponentFunction("row", "deselect", this.deselectRows.bind(this)); + this.registerComponentFunction("row", "toggleSelect", this.toggleRow.bind(this)); + this.registerComponentFunction("row", "isSelected", this.isRowSelected.bind(this)); + } + + initialize() { + this.deprecatedOptionsCheck(); + if (this.table.options.selectableRows === "highlight" && this.table.options.selectableRange) { + this.table.options.selectableRows = false; + } + if (this.table.options.selectableRows !== false) { + this.subscribe("row-init", this.initializeRow.bind(this)); + this.subscribe("row-deleting", this.rowDeleted.bind(this)); + this.subscribe("rows-wipe", this.clearSelectionData.bind(this)); + this.subscribe("rows-retrieve", this.rowRetrieve.bind(this)); + if (this.table.options.selectableRows && !this.table.options.selectableRowsPersistence) { + this.subscribe("data-refreshing", this.deselectRows.bind(this)); + } + } + } + + deprecatedOptionsCheck() { + } + + rowRetrieve(type, prevValue) { + return type === "selected" ? this.selectedRows : prevValue; + } + + rowDeleted(row) { + this._deselectRow(row, true); + } + + clearSelectionData(silent) { + var prevSelected = this.selectedRows.length; + this.selecting = false; + this.lastClickedRow = false; + this.selectPrev = []; + this.selectedRows = []; + if (prevSelected && silent !== true) { + this._rowSelectionChanged(); + } + } + + initializeRow(row) { + var self = this, selectable = self.checkRowSelectability(row), element = row.getElement(); + var endSelect = function () { + setTimeout(function () { + self.selecting = false; + }, 50); + document.body.removeEventListener("mouseup", endSelect); + }; + row.modules.select = {selected: false}; + element.classList.toggle("tabulator-selectable", selectable); + element.classList.toggle("tabulator-unselectable", !selectable); + if (self.checkRowSelectability(row)) { + if (self.table.options.selectableRows && self.table.options.selectableRows != "highlight") { + if (self.table.options.selectableRowsRangeMode === "click") { + element.addEventListener("click", this.handleComplexRowClick.bind(this, row)); + } else { + element.addEventListener("click", function (e) { + if (!self.table.modExists("edit") || !self.table.modules.edit.getCurrentCell()) { + self.table._clearSelection(); + } + if (!self.selecting) { + self.toggleRow(row); + } + }); + element.addEventListener("mousedown", function (e) { + if (e.shiftKey) { + self.table._clearSelection(); + self.selecting = true; + self.selectPrev = []; + document.body.addEventListener("mouseup", endSelect); + document.body.addEventListener("keyup", endSelect); + self.toggleRow(row); + return false; + } + }); + element.addEventListener("mouseenter", function (e) { + if (self.selecting) { + self.table._clearSelection(); + self.toggleRow(row); + if (self.selectPrev[1] == row) { + self.toggleRow(self.selectPrev[0]); + } + } + }); + element.addEventListener("mouseout", function (e) { + if (self.selecting) { + self.table._clearSelection(); + self.selectPrev.unshift(row); + } + }); + } + } + } + } + + handleComplexRowClick(row, e) { + if (e.shiftKey) { + this.table._clearSelection(); + this.lastClickedRow = this.lastClickedRow || row; + var lastClickedRowIdx = this.table.rowManager.getDisplayRowIndex(this.lastClickedRow); + var rowIdx = this.table.rowManager.getDisplayRowIndex(row); + var fromRowIdx = lastClickedRowIdx <= rowIdx ? lastClickedRowIdx : rowIdx; + var toRowIdx = lastClickedRowIdx >= rowIdx ? lastClickedRowIdx : rowIdx; + var rows2 = this.table.rowManager.getDisplayRows().slice(0); + var toggledRows = rows2.splice(fromRowIdx, toRowIdx - fromRowIdx + 1); + if (e.ctrlKey || e.metaKey) { + toggledRows.forEach((toggledRow) => { + if (toggledRow !== this.lastClickedRow) { + if (this.table.options.selectableRows !== true && !this.isRowSelected(row)) { + if (this.selectedRows.length < this.table.options.selectableRows) { + this.toggleRow(toggledRow); + } + } else { + this.toggleRow(toggledRow); + } + } + }); + this.lastClickedRow = row; + } else { + this.deselectRows(void 0, true); + if (this.table.options.selectableRows !== true) { + if (toggledRows.length > this.table.options.selectableRows) { + toggledRows = toggledRows.slice(0, this.table.options.selectableRows); + } + } + this.selectRows(toggledRows); + } + this.table._clearSelection(); + } else if (e.ctrlKey || e.metaKey) { + this.toggleRow(row); + this.lastClickedRow = row; + } else { + this.deselectRows(void 0, true); + if (this.selectedRows.length === 1 && this.isRowSelected(row)) ; + else { + this.selectRows(row); + } + this.lastClickedRow = row; + } + } + + checkRowSelectability(row) { + if (row && row.type === "row") { + return this.table.options.selectableRowsCheck.call(this.table, row.getComponent()); + } + return false; + } + + //toggle row selection + toggleRow(row) { + if (this.checkRowSelectability(row)) { + if (row.modules.select && row.modules.select.selected) { + this._deselectRow(row); + } else { + this._selectRow(row); + } + } + } + + //select a number of rows + selectRows(rows2) { + var changes = [], rowMatch, change; + switch (typeof rows2) { + case "undefined": + rowMatch = this.table.rowManager.rows; + break; + case "number": + rowMatch = this.table.rowManager.findRow(rows2); + break; + case "string": + rowMatch = this.table.rowManager.findRow(rows2); + if (!rowMatch) { + rowMatch = this.table.rowManager.getRows(rows2); + } + break; + default: + rowMatch = rows2; + break; + } + if (Array.isArray(rowMatch)) { + if (rowMatch.length) { + rowMatch.forEach((row) => { + change = this._selectRow(row, true, true); + if (change) { + changes.push(change); + } + }); + this._rowSelectionChanged(false, changes); + } + } else { + if (rowMatch) { + this._selectRow(rowMatch, false, true); + } + } + } + + //select an individual row + _selectRow(rowInfo, silent, force) { + if (!isNaN(this.table.options.selectableRows) && this.table.options.selectableRows !== true && !force) { + if (this.selectedRows.length >= this.table.options.selectableRows) { + if (this.table.options.selectableRowsRollingSelection) { + this._deselectRow(this.selectedRows[0]); + } else { + return false; + } + } + } + var row = this.table.rowManager.findRow(rowInfo); + if (row) { + if (this.selectedRows.indexOf(row) == -1) { + row.getElement().classList.add("tabulator-selected"); + if (!row.modules.select) { + row.modules.select = {}; + } + row.modules.select.selected = true; + if (row.modules.select.checkboxEl) { + row.modules.select.checkboxEl.checked = true; + } + this.selectedRows.push(row); + if (this.table.options.dataTreeSelectPropagate) { + this.childRowSelection(row, true); + } + this.dispatchExternal("rowSelected", row.getComponent()); + this._rowSelectionChanged(silent, row); + return row; + } + } else { + if (!silent) { + console.warn("Selection Error - No such row found, ignoring selection:" + rowInfo); + } + } + } + + isRowSelected(row) { + return this.selectedRows.indexOf(row) !== -1; + } + + //deselect a number of rows + deselectRows(rows2, silent) { + var changes = [], rowMatch, change; + switch (typeof rows2) { + case "undefined": + rowMatch = Object.assign([], this.selectedRows); + break; + case "number": + rowMatch = this.table.rowManager.findRow(rows2); + break; + case "string": + rowMatch = this.table.rowManager.findRow(rows2); + if (!rowMatch) { + rowMatch = this.table.rowManager.getRows(rows2); + } + break; + default: + rowMatch = rows2; + break; + } + if (Array.isArray(rowMatch)) { + if (rowMatch.length) { + rowMatch.forEach((row) => { + change = this._deselectRow(row, true, true); + if (change) { + changes.push(change); + } + }); + this._rowSelectionChanged(silent, [], changes); + } + } else { + if (rowMatch) { + this._deselectRow(rowMatch, silent, true); + } + } + } + + //deselect an individual row + _deselectRow(rowInfo, silent) { + var self = this, row = self.table.rowManager.findRow(rowInfo), index, element; + if (row) { + index = self.selectedRows.findIndex(function (selectedRow) { + return selectedRow == row; + }); + if (index > -1) { + element = row.getElement(); + if (element) { + element.classList.remove("tabulator-selected"); + } + if (!row.modules.select) { + row.modules.select = {}; + } + row.modules.select.selected = false; + if (row.modules.select.checkboxEl) { + row.modules.select.checkboxEl.checked = false; + } + self.selectedRows.splice(index, 1); + if (this.table.options.dataTreeSelectPropagate) { + this.childRowSelection(row, false); + } + this.dispatchExternal("rowDeselected", row.getComponent()); + self._rowSelectionChanged(silent, void 0, row); + return row; + } + } else { + if (!silent) { + console.warn("Deselection Error - No such row found, ignoring selection:" + rowInfo); + } + } + } + + getSelectedData() { + var data = []; + this.selectedRows.forEach(function (row) { + data.push(row.getData()); + }); + return data; + } + + getSelectedRows() { + var rows2 = []; + this.selectedRows.forEach(function (row) { + rows2.push(row.getComponent()); + }); + return rows2; + } + + _rowSelectionChanged(silent, selected = [], deselected = []) { + if (this.headerCheckboxElement) { + if (this.selectedRows.length === 0) { + this.headerCheckboxElement.checked = false; + this.headerCheckboxElement.indeterminate = false; + } else if (this.table.rowManager.rows.length === this.selectedRows.length) { + this.headerCheckboxElement.checked = true; + this.headerCheckboxElement.indeterminate = false; + } else { + this.headerCheckboxElement.indeterminate = true; + this.headerCheckboxElement.checked = false; + } + } + if (!silent) { + if (!Array.isArray(selected)) { + selected = [selected]; + } + selected = selected.map((row) => row.getComponent()); + if (!Array.isArray(deselected)) { + deselected = [deselected]; + } + deselected = deselected.map((row) => row.getComponent()); + this.dispatchExternal("rowSelectionChanged", this.getSelectedData(), this.getSelectedRows(), selected, deselected); + } + } + + registerRowSelectCheckbox(row, element) { + if (!row._row.modules.select) { + row._row.modules.select = {}; + } + row._row.modules.select.checkboxEl = element; + } + + registerHeaderSelectCheckbox(element) { + this.headerCheckboxElement = element; + } + + childRowSelection(row, select) { + var children = this.table.modules.dataTree.getChildren(row, true, true); + if (select) { + for (let child of children) { + this._selectRow(child, true); + } + } else { + for (let child of children) { + this._deselectRow(child, true); + } + } + } + } + + __publicField(SelectRow, "moduleName", "selectRow"); + __publicField(SelectRow, "moduleExtensions", extensions$1); + + class RangeComponent { + constructor(range2) { + this._range = range2; + return new Proxy(this, { + get: function (target, name2, receiver) { + if (typeof target[name2] !== "undefined") { + return target[name2]; + } else { + return target._range.table.componentFunctionBinder.handle("range", target._range, name2); + } + } + }); + } + + getElement() { + return this._range.element; + } + + getData() { + return this._range.getData(); + } + + getCells() { + return this._range.getCells(true, true); + } + + getStructuredCells() { + return this._range.getStructuredCells(); + } + + getRows() { + return this._range.getRows().map((row) => row.getComponent()); + } + + getColumns() { + return this._range.getColumns().map((column) => column.getComponent()); + } + + getBounds() { + return this._range.getBounds(); + } + + getTopEdge() { + return this._range.top; + } + + getBottomEdge() { + return this._range.bottom; + } + + getLeftEdge() { + return this._range.left; + } + + getRightEdge() { + return this._range.right; + } + + setBounds(start, end) { + if (this._range.destroyedGuard("setBounds")) { + this._range.setBounds(start ? start._cell : start, end ? end._cell : end); + } + } + + setStartBound(start) { + if (this._range.destroyedGuard("setStartBound")) { + this._range.setEndBound(start ? start._cell : start); + this._range.rangeManager.layoutElement(); + } + } + + setEndBound(end) { + if (this._range.destroyedGuard("setEndBound")) { + this._range.setEndBound(end ? end._cell : end); + this._range.rangeManager.layoutElement(); + } + } + + clearValues() { + if (this._range.destroyedGuard("clearValues")) { + this._range.clearValues(); + } + } + + remove() { + if (this._range.destroyedGuard("remove")) { + this._range.destroy(true); + } + } + } + + class Range extends CoreFeature { + constructor(table, rangeManager, start, end) { + super(table); + this.rangeManager = rangeManager; + this.element = null; + this.initialized = false; + this.initializing = { + start: false, + end: false + }; + this.destroyed = false; + this.top = 0; + this.bottom = 0; + this.left = 0; + this.right = 0; + this.table = table; + this.start = {row: void 0, col: void 0}; + this.end = {row: void 0, col: void 0}; + if (this.rangeManager.rowHeader) { + this.left = 1; + this.right = 1; + this.start.col = 1; + this.end.col = 1; + } + this.initElement(); + setTimeout(() => { + this.initBounds(start, end); + }); + } + + initElement() { + this.element = document.createElement("div"); + this.element.classList.add("tabulator-range"); + } + + initBounds(start, end) { + this._updateMinMax(); + if (start) { + this.setBounds(start, end || start); + } + } + + /////////////////////////////////// + /////// Boundary Setup /////// + /////////////////////////////////// + setStart(row, col) { + if (this.start.row !== row || this.start.col !== col) { + this.start.row = row; + this.start.col = col; + this.initializing.start = true; + this._updateMinMax(); + } + } + + setEnd(row, col) { + if (this.end.row !== row || this.end.col !== col) { + this.end.row = row; + this.end.col = col; + this.initializing.end = true; + this._updateMinMax(); + } + } + + setBounds(start, end, visibleRows) { + if (start) { + this.setStartBound(start); + } + this.setEndBound(end || start); + this.rangeManager.layoutElement(visibleRows); + } + + setStartBound(element) { + var row, col; + if (element.type === "column") { + if (this.rangeManager.columnSelection) { + this.setStart(0, element.getPosition() - 1); + } + } else { + row = element.row.position - 1; + col = element.column.getPosition() - 1; + if (element.column === this.rangeManager.rowHeader) { + this.setStart(row, 1); + } else { + this.setStart(row, col); + } + } + } + + setEndBound(element) { + var rowsCount = this._getTableRows().length, row, col, isRowHeader; + if (element.type === "column") { + if (this.rangeManager.columnSelection) { + if (this.rangeManager.selecting === "column") { + this.setEnd(rowsCount - 1, element.getPosition() - 1); + } else if (this.rangeManager.selecting === "cell") { + this.setEnd(0, element.getPosition() - 1); + } + } + } else { + row = element.row.position - 1; + col = element.column.getPosition() - 1; + isRowHeader = element.column === this.rangeManager.rowHeader; + if (this.rangeManager.selecting === "row") { + this.setEnd(row, this._getTableColumns().length - 1); + } else if (this.rangeManager.selecting !== "row" && isRowHeader) { + this.setEnd(row, 0); + } else if (this.rangeManager.selecting === "column") { + this.setEnd(rowsCount - 1, col); + } else { + this.setEnd(row, col); + } + } + } + + _updateMinMax() { + this.top = Math.min(this.start.row, this.end.row); + this.bottom = Math.max(this.start.row, this.end.row); + this.left = Math.min(this.start.col, this.end.col); + this.right = Math.max(this.start.col, this.end.col); + if (this.initialized) { + this.dispatchExternal("rangeChanged", this.getComponent()); + } else { + if (this.initializing.start && this.initializing.end) { + this.initialized = true; + this.dispatchExternal("rangeAdded", this.getComponent()); + } + } + } + + _getTableColumns() { + return this.table.columnManager.getVisibleColumnsByIndex(); + } + + _getTableRows() { + return this.table.rowManager.getDisplayRows().filter((row) => row.type === "row"); + } + + /////////////////////////////////// + /////// Rendering /////// + /////////////////////////////////// + layout() { + var _vDomTop = this.table.rowManager.renderer.vDomTop, + _vDomBottom = this.table.rowManager.renderer.vDomBottom, + _vDomLeft = this.table.columnManager.renderer.leftCol, + _vDomRight = this.table.columnManager.renderer.rightCol, top, bottom, left, right, topLeftCell, + bottomRightCell, topLeftCellEl, bottomRightCellEl, topLeftRowEl, bottomRightRowEl; + if (this.table.options.renderHorizontal === "virtual" && this.rangeManager.rowHeader) { + _vDomRight += 1; + } + if (_vDomTop == null) { + _vDomTop = 0; + } + if (_vDomBottom == null) { + _vDomBottom = Infinity; + } + if (_vDomLeft == null) { + _vDomLeft = 0; + } + if (_vDomRight == null) { + _vDomRight = Infinity; + } + if (this.overlaps(_vDomLeft, _vDomTop, _vDomRight, _vDomBottom)) { + top = Math.max(this.top, _vDomTop); + bottom = Math.min(this.bottom, _vDomBottom); + left = Math.max(this.left, _vDomLeft); + right = Math.min(this.right, _vDomRight); + topLeftCell = this.rangeManager.getCell(top, left); + bottomRightCell = this.rangeManager.getCell(bottom, right); + topLeftCellEl = topLeftCell.getElement(); + bottomRightCellEl = bottomRightCell.getElement(); + topLeftRowEl = topLeftCell.row.getElement(); + bottomRightRowEl = bottomRightCell.row.getElement(); + this.element.classList.add("tabulator-range-active"); + if (this.table.rtl) { + this.element.style.right = topLeftRowEl.offsetWidth - topLeftCellEl.offsetLeft - topLeftCellEl.offsetWidth + "px"; + this.element.style.width = topLeftCellEl.offsetLeft + topLeftCellEl.offsetWidth - bottomRightCellEl.offsetLeft + "px"; + } else { + this.element.style.left = topLeftRowEl.offsetLeft + topLeftCellEl.offsetLeft + "px"; + this.element.style.width = bottomRightCellEl.offsetLeft + bottomRightCellEl.offsetWidth - topLeftCellEl.offsetLeft + "px"; + } + this.element.style.top = topLeftRowEl.offsetTop + "px"; + this.element.style.height = bottomRightRowEl.offsetTop + bottomRightRowEl.offsetHeight - topLeftRowEl.offsetTop + "px"; + } + } + + atTopLeft(cell) { + return cell.row.position - 1 === this.top && cell.column.getPosition() - 1 === this.left; + } + + atBottomRight(cell) { + return cell.row.position - 1 === this.bottom && cell.column.getPosition() - 1 === this.right; + } + + occupies(cell) { + return this.occupiesRow(cell.row) && this.occupiesColumn(cell.column); + } + + occupiesRow(row) { + return this.top <= row.position - 1 && row.position - 1 <= this.bottom; + } + + occupiesColumn(col) { + return this.left <= col.getPosition() - 1 && col.getPosition() - 1 <= this.right; + } + + overlaps(left, top, right, bottom) { + if (this.left > right || left > this.right || (this.top > bottom || top > this.bottom)) { + return false; + } + return true; + } + + getData() { + var data = [], rows2 = this.getRows(), columns = this.getColumns(); + rows2.forEach((row) => { + var rowData = row.getData(), result = {}; + columns.forEach((column) => { + result[column.field] = rowData[column.field]; + }); + data.push(result); + }); + return data; + } + + getCells(structured, component) { + var cells = [], rows2 = this.getRows(), columns = this.getColumns(); + if (structured) { + cells = rows2.map((row) => { + var arr = []; + row.getCells().forEach((cell) => { + if (columns.includes(cell.column)) { + arr.push(component ? cell.getComponent() : cell); + } + }); + return arr; + }); + } else { + rows2.forEach((row) => { + row.getCells().forEach((cell) => { + if (columns.includes(cell.column)) { + cells.push(component ? cell.getComponent() : cell); + } + }); + }); + } + return cells; + } + + getStructuredCells() { + return this.getCells(true, true); + } + + getRows() { + return this._getTableRows().slice(this.top, this.bottom + 1); + } + + getColumns() { + return this._getTableColumns().slice(this.left, this.right + 1); + } + + clearValues() { + var cells = this.getCells(); + var clearValue = this.table.options.selectableRangeClearCellsValue; + this.table.blockRedraw(); + cells.forEach((cell) => { + cell.setValue(clearValue); + }); + this.table.restoreRedraw(); + } + + getBounds(component) { + var cells = this.getCells(false, component), output = { + start: null, + end: null + }; + if (cells.length) { + output.start = cells[0]; + output.end = cells[cells.length - 1]; + } else { + console.warn("No bounds defined on range"); + } + return output; + } + + getComponent() { + if (!this.component) { + this.component = new RangeComponent(this); + } + return this.component; + } + + destroy(notify) { + this.destroyed = true; + this.element.remove(); + if (notify) { + this.rangeManager.rangeRemoved(this); + } + if (this.initialized) { + this.dispatchExternal("rangeRemoved", this.getComponent()); + } + } + + destroyedGuard(func) { + if (this.destroyed) { + console.warn("You cannot call the " + func + " function on a destroyed range"); + } + return !this.destroyed; + } + } + + var bindings = { + rangeJumpUp: ["ctrl + 38", "meta + 38"], + rangeJumpDown: ["ctrl + 40", "meta + 40"], + rangeJumpLeft: ["ctrl + 37", "meta + 37"], + rangeJumpRight: ["ctrl + 39", "meta + 39"], + rangeExpandUp: "shift + 38", + rangeExpandDown: "shift + 40", + rangeExpandLeft: "shift + 37", + rangeExpandRight: "shift + 39", + rangeExpandJumpUp: ["ctrl + shift + 38", "meta + shift + 38"], + rangeExpandJumpDown: ["ctrl + shift + 40", "meta + shift + 40"], + rangeExpandJumpLeft: ["ctrl + shift + 37", "meta + shift + 37"], + rangeExpandJumpRight: ["ctrl + shift + 39", "meta + shift + 39"] + }; + var actions = { + rangeJumpLeft: function (e) { + this.dispatch("keybinding-nav-range", e, "left", true, false); + }, + rangeJumpRight: function (e) { + this.dispatch("keybinding-nav-range", e, "right", true, false); + }, + rangeJumpUp: function (e) { + this.dispatch("keybinding-nav-range", e, "up", true, false); + }, + rangeJumpDown: function (e) { + this.dispatch("keybinding-nav-range", e, "down", true, false); + }, + rangeExpandLeft: function (e) { + this.dispatch("keybinding-nav-range", e, "left", false, true); + }, + rangeExpandRight: function (e) { + this.dispatch("keybinding-nav-range", e, "right", false, true); + }, + rangeExpandUp: function (e) { + this.dispatch("keybinding-nav-range", e, "up", false, true); + }, + rangeExpandDown: function (e) { + this.dispatch("keybinding-nav-range", e, "down", false, true); + }, + rangeExpandJumpLeft: function (e) { + this.dispatch("keybinding-nav-range", e, "left", true, true); + }, + rangeExpandJumpRight: function (e) { + this.dispatch("keybinding-nav-range", e, "right", true, true); + }, + rangeExpandJumpUp: function (e) { + this.dispatch("keybinding-nav-range", e, "up", true, true); + }, + rangeExpandJumpDown: function (e) { + this.dispatch("keybinding-nav-range", e, "down", true, true); + } + }; + var pasteActions = { + range: function (data) { + var rows2 = [], range2 = this.table.modules.selectRange.activeRange, singleCell = false, bounds, + startCell, startRow, rowWidth, dataLength; + dataLength = data.length; + if (range2) { + bounds = range2.getBounds(); + startCell = bounds.start; + if (bounds.start === bounds.end) { + singleCell = true; + } + if (startCell) { + rows2 = this.table.rowManager.activeRows.slice(); + startRow = rows2.indexOf(startCell.row); + if (singleCell) { + rowWidth = data.length; + } else { + rowWidth = rows2.indexOf(bounds.end.row) - startRow + 1; + } + if (startRow > -1) { + this.table.blockRedraw(); + rows2 = rows2.slice(startRow, startRow + rowWidth); + rows2.forEach((row, i) => { + row.updateData(data[i % dataLength]); + }); + this.table.restoreRedraw(); + } + } + } + return rows2; + } + }; + var pasteParsers = { + range: function (clipboard) { + var data = [], rows2 = [], range2 = this.table.modules.selectRange.activeRange, singleCell = false, + bounds, startCell, colWidth, columnMap, startCol; + if (range2) { + bounds = range2.getBounds(); + startCell = bounds.start; + if (bounds.start === bounds.end) { + singleCell = true; + } + if (startCell) { + clipboard = clipboard.split("\n"); + clipboard.forEach(function (row) { + data.push(row.split(" ")); + }); + if (data.length) { + columnMap = this.table.columnManager.getVisibleColumnsByIndex(); + startCol = columnMap.indexOf(startCell.column); + if (startCol > -1) { + if (singleCell) { + colWidth = data[0].length; + } else { + colWidth = columnMap.indexOf(bounds.end.column) - startCol + 1; + } + columnMap = columnMap.slice(startCol, startCol + colWidth); + data.forEach((item) => { + var row = {}; + var itemLength = item.length; + columnMap.forEach(function (col, i) { + row[col.field] = item[i % itemLength]; + }); + rows2.push(row); + }); + return rows2; + } + } + } + } + return false; + } + }; + var columnLookups = { + range: function () { + var columns = this.modules.selectRange.selectedColumns(); + if (this.columnManager.rowHeader) { + columns.unshift(this.columnManager.rowHeader); + } + return columns; + } + }; + var rowLookups = { + range: function () { + return this.modules.selectRange.selectedRows(); + } + }; + var extensions = { + keybindings: { + bindings, + actions + }, + clipboard: { + pasteActions, + pasteParsers + }, + export: { + columnLookups, + rowLookups + } + }; + + class SelectRange extends Module { + constructor(table) { + super(table); + this.selecting = "cell"; + this.mousedown = false; + this.ranges = []; + this.overlay = null; + this.rowHeader = null; + this.layoutChangeTimeout = null; + this.columnSelection = false; + this.rowSelection = false; + this.maxRanges = 0; + this.activeRange = false; + this.blockKeydown = false; + this.keyDownEvent = this._handleKeyDown.bind(this); + this.mouseUpEvent = this._handleMouseUp.bind(this); + this.registerTableOption("selectableRange", false); + this.registerTableOption("selectableRangeColumns", false); + this.registerTableOption("selectableRangeRows", false); + this.registerTableOption("selectableRangeClearCells", false); + this.registerTableOption("selectableRangeClearCellsValue", void 0); + this.registerTableOption("selectableRangeAutoFocus", true); + this.registerTableOption("selectableRangeInitializeDefault", true); + this.registerTableOption("selectableRangeBlurEditOnNavigate", void 0); + this.registerTableFunction("getRangesData", this.getRangesData.bind(this)); + this.registerTableFunction("getRanges", this.getRanges.bind(this)); + this.registerTableFunction("addRange", this.addRangeFromComponent.bind(this)); + this.registerComponentFunction("cell", "getRanges", this.cellGetRanges.bind(this)); + this.registerComponentFunction("row", "getRanges", this.rowGetRanges.bind(this)); + this.registerComponentFunction("column", "getRanges", this.colGetRanges.bind(this)); + } + + /////////////////////////////////// + /////// Initialization /////// + /////////////////////////////////// + initialize() { + if (this.options("selectableRange")) { + if (!this.options("selectableRows")) { + this.maxRanges = this.options("selectableRange"); + this.initializeTable(); + this.initializeWatchers(); + } else { + console.warn("SelectRange functionality cannot be used in conjunction with row selection"); + } + if (this.options("columns").findIndex((column) => column.frozen) > 0) { + console.warn("Having frozen column in arbitrary position with selectRange option may result in unpredictable behavior."); + } + if (this.options("columns").filter((column) => column.frozen) > 1) { + console.warn("Having multiple frozen columns with selectRange option may result in unpredictable behavior."); + } + } + this.subscribe("edit-nav-disabled", () => { + return true; + }); + } + + initializeTable() { + this.overlay = document.createElement("div"); + this.overlay.classList.add("tabulator-range-overlay"); + this.rangeContainer = document.createElement("div"); + this.rangeContainer.classList.add("tabulator-range-container"); + this.activeRangeCellElement = document.createElement("div"); + this.activeRangeCellElement.classList.add("tabulator-range-cell-active"); + this.overlay.appendChild(this.rangeContainer); + this.overlay.appendChild(this.activeRangeCellElement); + this.table.rowManager.element.addEventListener("keydown", this.keyDownEvent); + this.setDefaultRange(); + this.table.rowManager.element.appendChild(this.overlay); + this.table.columnManager.element.setAttribute("tabindex", 0); + this.table.element.classList.add("tabulator-ranges"); + } + + initializeWatchers() { + this.columnSelection = this.options("selectableRangeColumns"); + this.rowSelection = this.options("selectableRangeRows"); + this.subscribe("column-init", this.initializeColumn.bind(this)); + this.subscribe("column-mousedown", this.handleColumnMouseDown.bind(this)); + this.subscribe("column-mousemove", this.handleColumnMouseMove.bind(this)); + this.subscribe("column-resized", this.handleColumnResized.bind(this)); + this.subscribe("column-moving", this.handleColumnMoving.bind(this)); + this.subscribe("column-moved", this.handleColumnMoved.bind(this)); + this.subscribe("column-width", this.layoutChange.bind(this)); + this.subscribe("column-height", this.layoutChange.bind(this)); + this.subscribe("column-resized", this.layoutChange.bind(this)); + this.subscribe("columns-loaded", this.updateHeaderColumn.bind(this)); + this.subscribe("cell-height", this.layoutChange.bind(this)); + this.subscribe("cell-rendered", this.renderCell.bind(this)); + this.subscribe("cell-mousedown", this.handleCellMouseDown.bind(this)); + this.subscribe("cell-mousemove", this.handleCellMouseMove.bind(this)); + this.subscribe("cell-click", this.handleCellClick.bind(this)); + this.subscribe("cell-editing", this.handleEditingCell.bind(this)); + this.subscribe("page-changed", this.redraw.bind(this)); + this.subscribe("scroll-vertical", this.layoutChange.bind(this)); + this.subscribe("scroll-horizontal", this.layoutChange.bind(this)); + this.subscribe("data-destroy", this.tableDestroyed.bind(this)); + this.subscribe("data-processed", this.setDefaultRange.bind(this)); + this.subscribe("table-layout", this.layoutElement.bind(this)); + this.subscribe("table-redraw", this.redraw.bind(this)); + this.subscribe("table-destroy", this.tableDestroyed.bind(this)); + this.subscribe("edit-editor-clear", this.finishEditingCell.bind(this)); + this.subscribe("edit-blur", this.restoreFocus.bind(this)); + this.subscribe("keybinding-nav-prev", this.keyNavigate.bind(this, "prev")); + this.subscribe("keybinding-nav-next", this.keyNavigate.bind(this, "next")); + this.subscribe("keybinding-nav-left", this.keyNavigate.bind(this, "left")); + this.subscribe("keybinding-nav-right", this.keyNavigate.bind(this, "right")); + this.subscribe("keybinding-nav-up", this.keyNavigate.bind(this, "up")); + this.subscribe("keybinding-nav-down", this.keyNavigate.bind(this, "down")); + this.subscribe("keybinding-nav-range", this.keyNavigateRange.bind(this)); + } + + initializeColumn(column) { + if (this.columnSelection && column.definition.headerSort && this.options("headerSortClickElement") !== "icon") { + console.warn("Using column headerSort with selectableRangeColumns option may result in unpredictable behavior. Consider using headerSortClickElement: 'icon'."); + } + } + + updateHeaderColumn() { + var frozenCols; + if (this.rowSelection) { + this.rowHeader = this.table.columnManager.getVisibleColumnsByIndex()[0]; + if (this.rowHeader) { + this.rowHeader.definition.cssClass = this.rowHeader.definition.cssClass + " tabulator-range-row-header"; + if (this.rowHeader.definition.headerSort) { + console.warn("Using column headerSort with selectableRangeRows option may result in unpredictable behavior"); + } + if (this.rowHeader.definition.editor) { + console.warn("Using column editor with selectableRangeRows option may result in unpredictable behavior"); + } + } + } + if (this.table.modules.frozenColumns && this.table.modules.frozenColumns.active) { + frozenCols = this.table.modules.frozenColumns.getFrozenColumns(); + if (frozenCols.length > 1 || frozenCols.length === 1 && frozenCols[0] !== this.rowHeader) { + console.warn("Using frozen columns that are not the range header in combination with the selectRange option may result in unpredictable behavior"); + } + } + } + + /////////////////////////////////// + /////// Table Functions /////// + /////////////////////////////////// + getRanges() { + return this.ranges.map((range2) => range2.getComponent()); + } + + getRangesData() { + return this.ranges.map((range2) => range2.getData()); + } + + addRangeFromComponent(start, end) { + start = start ? start._cell : null; + end = end ? end._cell : null; + return this.addRange(start, end); + } + + /////////////////////////////////// + /////// Component Functions /////// + /////////////////////////////////// + cellGetRanges(cell) { + var ranges = []; + if (cell.column === this.rowHeader) { + ranges = this.ranges.filter((range2) => range2.occupiesRow(cell.row)); + } else { + ranges = this.ranges.filter((range2) => range2.occupies(cell)); + } + return ranges.map((range2) => range2.getComponent()); + } + + rowGetRanges(row) { + var ranges = this.ranges.filter((range2) => range2.occupiesRow(row)); + return ranges.map((range2) => range2.getComponent()); + } + + colGetRanges(col) { + var ranges = this.ranges.filter((range2) => range2.occupiesColumn(col)); + return ranges.map((range2) => range2.getComponent()); + } + + /////////////////////////////////// + ////////// Event Handlers ///////// + /////////////////////////////////// + _handleMouseUp(e) { + this.mousedown = false; + document.removeEventListener("mouseup", this.mouseUpEvent); + } + + _handleKeyDown(e) { + if (!this.blockKeydown && (!this.table.modules.edit || this.table.modules.edit && !this.table.modules.edit.currentCell)) { + if (e.key === "Enter") { + if (this.table.modules.edit && this.table.modules.edit.currentCell) { + return; + } + var activeCell = this.getActiveCell(); + if (!activeCell) { + return; + } + this.table.modules.edit.editCell(activeCell); + e.preventDefault(); + } + if ((e.key === "Backspace" || e.key === "Delete") && this.options("selectableRangeClearCells")) { + if (this.activeRange) { + this.activeRange.clearValues(); + } + } + } + } + + initializeFocus(cell) { + var range2; + this.restoreFocus(); + try { + if (document.selection) { + range2 = document.body.createTextRange(); + range2.moveToElementText(cell.getElement()); + range2.select(); + } else if (window.getSelection) { + range2 = document.createRange(); + range2.selectNode(cell.getElement()); + window.getSelection().removeAllRanges(); + window.getSelection().addRange(range2); + } + } catch (e) { + } + } + + restoreFocus(element) { + this.table.rowManager.element.focus(); + return true; + } + + /////////////////////////////////// + ////// Column Functionality /////// + /////////////////////////////////// + handleColumnResized(column) { + var selected; + if (this.selecting !== "column" && this.selecting !== "all") { + return; + } + selected = this.ranges.some((range2) => range2.occupiesColumn(column)); + if (!selected) { + return; + } + this.ranges.forEach((range2) => { + var selectedColumns = range2.getColumns(true); + selectedColumns.forEach((selectedColumn) => { + if (selectedColumn !== column) { + selectedColumn.setWidth(column.width); + } + }); + }); + } + + handleColumnMoving(_event, column) { + this.resetRanges().setBounds(column); + this.overlay.style.visibility = "hidden"; + } + + handleColumnMoved(from, _to, _after) { + this.activeRange.setBounds(from); + this.layoutElement(); + } + + handleColumnMouseDown(event, column) { + if (event.button === 2 && (this.selecting === "column" || this.selecting === "all") && this.activeRange.occupiesColumn(column)) { + return; + } + if (this.table.options.movableColumns && this.selecting === "column" && this.activeRange.occupiesColumn(column)) { + return; + } + this.mousedown = true; + document.addEventListener("mouseup", this.mouseUpEvent); + this.newSelection(event, column); + } + + handleColumnMouseMove(e, column) { + if (column === this.rowHeader || !this.mousedown || this.selecting === "all") { + return; + } + this.activeRange.setBounds(false, column, true); + } + + /////////////////////////////////// + //////// Cell Functionality /////// + /////////////////////////////////// + renderCell(cell) { + var el = cell.getElement(), rangeIdx = this.ranges.findIndex((range2) => range2.occupies(cell)); + el.classList.toggle("tabulator-range-selected", rangeIdx !== -1); + el.classList.toggle("tabulator-range-only-cell-selected", this.ranges.length === 1 && this.ranges[0].atTopLeft(cell) && this.ranges[0].atBottomRight(cell)); + el.dataset.range = rangeIdx; + } + + handleCellMouseDown(event, cell) { + if (event.button === 2 && (this.activeRange.occupies(cell) || (this.selecting === "row" || this.selecting === "all") && this.activeRange.occupiesRow(cell.row))) { + return; + } + this.mousedown = true; + document.addEventListener("mouseup", this.mouseUpEvent); + this.newSelection(event, cell); + } + + handleCellMouseMove(e, cell) { + if (!this.mousedown || this.selecting === "all") { + return; + } + this.activeRange.setBounds(false, cell, true); + } + + handleCellClick(e, cell) { + this.initializeFocus(cell); + } + + handleEditingCell(cell) { + if (this.activeRange) { + this.activeRange.setBounds(cell); + } + } + + finishEditingCell() { + this.blockKeydown = true; + this.table.rowManager.element.focus(); + setTimeout(() => { + this.blockKeydown = false; + }, 10); + } + + /////////////////////////////////// + /////// Navigation /////// + /////////////////////////////////// + keyNavigate(dir, e) { + if (this.options("selectableRangeBlurEditOnNavigate")) { + const isEditing = this.chain("edit-check-editing"); + if (isEditing) { + if (dir === "next" || dir === "prev") { + this.dispatch("edit-cancel-cell"); + } else { + return false; + } + } + } + if (dir === "prev") { + dir = "left"; + } else if (dir === "next") { + dir = "right"; + } + if (this.navigate(false, false, dir)) { + e.preventDefault(); + } + } + + keyNavigateRange(e, dir, jump, expand) { + if (this.navigate(jump, expand, dir)) { + e.preventDefault(); + } + } + + navigate(jump, expand, dir) { + var moved = false, range2, rangeEdge, prevRect, nextRow, nextCol, row, column, rowRect, rowManagerRect, + columnRect, columnManagerRect; + if (this.table.modules.edit && this.table.modules.edit.currentCell) { + return false; + } + if (this.ranges.length > 1) { + this.ranges = this.ranges.filter((range3) => { + if (range3 === this.activeRange) { + range3.setEnd(range3.start.row, range3.start.col); + return true; + } + range3.destroy(); + return false; + }); + } + range2 = this.activeRange; + prevRect = { + top: range2.top, + bottom: range2.bottom, + left: range2.left, + right: range2.right + }; + rangeEdge = expand ? range2.end : range2.start; + nextRow = rangeEdge.row; + nextCol = rangeEdge.col; + if (jump) { + switch (dir) { + case "left": + nextCol = this.findJumpCellLeft(range2.start.row, rangeEdge.col); + break; + case "right": + nextCol = this.findJumpCellRight(range2.start.row, rangeEdge.col); + break; + case "up": + nextRow = this.findJumpCellUp(rangeEdge.row, range2.start.col); + break; + case "down": + nextRow = this.findJumpCellDown(rangeEdge.row, range2.start.col); + break; + } + } else { + if (expand) { + if (this.selecting === "row" && (dir === "left" || dir === "right") || this.selecting === "column" && (dir === "up" || dir === "down")) { + return; + } + } + switch (dir) { + case "left": + nextCol = Math.max(nextCol - 1, 0); + break; + case "right": + nextCol = Math.min(nextCol + 1, this.getTableColumns().length - 1); + break; + case "up": + nextRow = Math.max(nextRow - 1, 0); + break; + case "down": + nextRow = Math.min(nextRow + 1, this.getTableRows().length - 1); + break; + } + } + if (this.rowHeader && nextCol === 0) { + nextCol = 1; + } + if (!expand) { + range2.setStart(nextRow, nextCol); + } + range2.setEnd(nextRow, nextCol); + if (!expand) { + this.selecting = "cell"; + } + moved = prevRect.top !== range2.top || prevRect.bottom !== range2.bottom || prevRect.left !== range2.left || prevRect.right !== range2.right; + if (moved) { + row = this.getRowByRangePos(range2.end.row); + column = this.getColumnByRangePos(range2.end.col); + rowRect = row.getElement().getBoundingClientRect(); + columnRect = column.getElement().getBoundingClientRect(); + rowManagerRect = this.table.rowManager.getElement().getBoundingClientRect(); + columnManagerRect = this.table.columnManager.getElement().getBoundingClientRect(); + if (!(rowRect.top >= rowManagerRect.top && rowRect.bottom <= rowManagerRect.bottom)) { + if (row.getElement().parentNode && column.getElement().parentNode) { + this.autoScroll(range2, row.getElement(), column.getElement()); + } else { + row.getComponent().scrollTo(void 0, false); + } + } + if (!(columnRect.left >= columnManagerRect.left + this.getRowHeaderWidth() && columnRect.right <= columnManagerRect.right)) { + if (row.getElement().parentNode && column.getElement().parentNode) { + this.autoScroll(range2, row.getElement(), column.getElement()); + } else { + column.getComponent().scrollTo(void 0, false); + } + } + this.layoutElement(); + } + return true; + } + + rangeRemoved(removed) { + this.ranges = this.ranges.filter((range2) => range2 !== removed); + if (this.activeRange === removed) { + if (this.ranges.length) { + this.activeRange = this.ranges[this.ranges.length - 1]; + } else { + this.addRange(); + } + } + this.layoutElement(true); + } + + findJumpRow(column, rows2, reverse, emptyStart, emptySide) { + if (reverse) { + rows2 = rows2.reverse(); + } + return this.findJumpItem(emptyStart, emptySide, rows2, function (row) { + return row.getData()[column.getField()]; + }); + } + + findJumpCol(row, columns, reverse, emptyStart, emptySide) { + if (reverse) { + columns = columns.reverse(); + } + return this.findJumpItem(emptyStart, emptySide, columns, function (column) { + return row.getData()[column.getField()]; + }); + } + + findJumpItem(emptyStart, emptySide, items, valueResolver) { + var nextItem; + for (let currentItem of items) { + let currentValue = valueResolver(currentItem); + if (emptyStart) { + nextItem = currentItem; + if (currentValue) { + break; + } + } else { + if (emptySide) { + nextItem = currentItem; + if (currentValue) { + break; + } + } else { + if (currentValue) { + nextItem = currentItem; + } else { + break; + } + } + } + } + return nextItem; + } + + findJumpCellLeft(rowPos, colPos) { + var row = this.getRowByRangePos(rowPos), columns = this.getTableColumns(), + isStartingCellEmpty = this.isEmpty(row.getData()[columns[colPos].getField()]), + isLeftOfStartingCellEmpty = columns[colPos - 1] ? this.isEmpty(row.getData()[columns[colPos - 1].getField()]) : false, + targetCols = this.rowHeader ? columns.slice(1, colPos) : columns.slice(0, colPos), + jumpCol = this.findJumpCol(row, targetCols, true, isStartingCellEmpty, isLeftOfStartingCellEmpty); + if (jumpCol) { + return jumpCol.getPosition() - 1; + } + return colPos; + } + + findJumpCellRight(rowPos, colPos) { + var row = this.getRowByRangePos(rowPos), columns = this.getTableColumns(), + isStartingCellEmpty = this.isEmpty(row.getData()[columns[colPos].getField()]), + isRightOfStartingCellEmpty = columns[colPos + 1] ? this.isEmpty(row.getData()[columns[colPos + 1].getField()]) : false, + jumpCol = this.findJumpCol(row, columns.slice(colPos + 1, columns.length), false, isStartingCellEmpty, isRightOfStartingCellEmpty); + if (jumpCol) { + return jumpCol.getPosition() - 1; + } + return colPos; + } + + findJumpCellUp(rowPos, colPos) { + var column = this.getColumnByRangePos(colPos), rows2 = this.getTableRows(), + isStartingCellEmpty = this.isEmpty(rows2[rowPos].getData()[column.getField()]), + isTopOfStartingCellEmpty = rows2[rowPos - 1] ? this.isEmpty(rows2[rowPos - 1].getData()[column.getField()]) : false, + jumpRow = this.findJumpRow(column, rows2.slice(0, rowPos), true, isStartingCellEmpty, isTopOfStartingCellEmpty); + if (jumpRow) { + return jumpRow.position - 1; + } + return rowPos; + } + + findJumpCellDown(rowPos, colPos) { + var column = this.getColumnByRangePos(colPos), rows2 = this.getTableRows(), + isStartingCellEmpty = this.isEmpty(rows2[rowPos].getData()[column.getField()]), + isBottomOfStartingCellEmpty = rows2[rowPos + 1] ? this.isEmpty(rows2[rowPos + 1].getData()[column.getField()]) : false, + jumpRow = this.findJumpRow(column, rows2.slice(rowPos + 1, rows2.length), false, isStartingCellEmpty, isBottomOfStartingCellEmpty); + if (jumpRow) { + return jumpRow.position - 1; + } + return rowPos; + } + + /////////////////////////////////// + /////// Selection /////// + /////////////////////////////////// + newSelection(event, element) { + var range2; + if (element.type === "column") { + if (!this.columnSelection) { + return; + } + if (element === this.rowHeader) { + range2 = this.resetRanges(); + this.selecting = "all"; + var topLeftCell, bottomRightCell = this.getCell(-1, -1); + if (this.rowHeader) { + topLeftCell = this.getCell(0, 1); + } else { + topLeftCell = this.getCell(0, 0); + } + range2.setBounds(topLeftCell, bottomRightCell); + return; + } else { + this.selecting = "column"; + } + } else if (element.column === this.rowHeader) { + this.selecting = "row"; + } else { + this.selecting = "cell"; + } + if (event.shiftKey) { + this.activeRange.setBounds(false, element, true); + } else if (event.ctrlKey) { + this.addRange().setBounds(element, void 0, true); + } else { + this.resetRanges().setBounds(element, void 0, true); + } + } + + autoScroll(range2, row, column) { + var tableHolder = this.table.rowManager.element, rect, view, withinHorizontalView, withinVerticalView; + if (typeof row === "undefined") { + row = this.getRowByRangePos(range2.end.row).getElement(); + } + if (typeof column === "undefined") { + column = this.getColumnByRangePos(range2.end.col).getElement(); + } + rect = { + left: column.offsetLeft, + right: column.offsetLeft + column.offsetWidth, + top: row.offsetTop, + bottom: row.offsetTop + row.offsetHeight + }; + view = { + left: tableHolder.scrollLeft + this.getRowHeaderWidth(), + right: Math.ceil(tableHolder.scrollLeft + tableHolder.clientWidth), + top: tableHolder.scrollTop, + bottom: tableHolder.scrollTop + tableHolder.offsetHeight - this.table.rowManager.scrollbarWidth + }; + withinHorizontalView = view.left < rect.left && rect.left < view.right && view.left < rect.right && rect.right < view.right; + withinVerticalView = view.top < rect.top && rect.top < view.bottom && view.top < rect.bottom && rect.bottom < view.bottom; + if (!withinHorizontalView) { + if (rect.left < view.left) { + tableHolder.scrollLeft = rect.left - this.getRowHeaderWidth(); + } else if (rect.right > view.right) { + tableHolder.scrollLeft = Math.min(rect.right - tableHolder.clientWidth, rect.left - this.getRowHeaderWidth()); + } + } + if (!withinVerticalView) { + if (rect.top < view.top) { + tableHolder.scrollTop = rect.top; + } else if (rect.bottom > view.bottom) { + tableHolder.scrollTop = rect.bottom - tableHolder.clientHeight; + } + } + } + + /////////////////////////////////// + /////// Layout /////// + /////////////////////////////////// + layoutChange() { + this.overlay.style.visibility = "hidden"; + clearTimeout(this.layoutChangeTimeout); + this.layoutChangeTimeout = setTimeout(this.layoutRanges.bind(this), 200); + } + + redraw(force) { + if (force) { + this.selecting = "cell"; + this.setDefaultRange(); + this.layoutElement(); + } + } + + layoutElement(visibleRows) { + var rows2; + if (visibleRows) { + rows2 = this.table.rowManager.getVisibleRows(true); + } else { + rows2 = this.table.rowManager.getRows(); + } + rows2.forEach((row) => { + if (row.type === "row") { + this.layoutRow(row); + row.cells.forEach((cell) => this.renderCell(cell)); + } + }); + this.getTableColumns().forEach((column) => { + this.layoutColumn(column); + }); + this.layoutRanges(); + } + + layoutRow(row) { + var el = row.getElement(), selected = false, + occupied = this.ranges.some((range2) => range2.occupiesRow(row)); + if (this.selecting === "row") { + selected = occupied; + } else if (this.selecting === "all") { + selected = true; + } + el.classList.toggle("tabulator-range-selected", selected); + el.classList.toggle("tabulator-range-highlight", occupied); + } + + layoutColumn(column) { + var el = column.getElement(), selected = false, + occupied = this.ranges.some((range2) => range2.occupiesColumn(column)); + if (this.selecting === "column") { + selected = occupied; + } else if (this.selecting === "all") { + selected = true; + } + el.classList.toggle("tabulator-range-selected", selected); + el.classList.toggle("tabulator-range-highlight", occupied); + } + + layoutRanges() { + var activeCell, activeCellEl, activeRowEl; + if (!this.table.initialized) { + return; + } + activeCell = this.getActiveCell(); + if (!activeCell) { + return; + } + activeCellEl = activeCell.getElement(); + activeRowEl = activeCell.row.getElement(); + if (this.table.rtl) { + this.activeRangeCellElement.style.right = activeRowEl.offsetWidth - activeCellEl.offsetLeft - activeCellEl.offsetWidth + "px"; + } else { + this.activeRangeCellElement.style.left = activeRowEl.offsetLeft + activeCellEl.offsetLeft + "px"; + } + this.activeRangeCellElement.style.top = activeRowEl.offsetTop + "px"; + this.activeRangeCellElement.style.width = activeCellEl.offsetWidth + "px"; + this.activeRangeCellElement.style.height = activeRowEl.offsetHeight + "px"; + this.ranges.forEach((range2) => range2.layout()); + this.overlay.style.visibility = "visible"; + } + + /////////////////////////////////// + /////// Helper Functions /////// + /////////////////////////////////// + getCell(rowIdx, colIdx) { + var row; + if (colIdx < 0) { + colIdx = this.getTableColumns().length + colIdx; + if (colIdx < 0) { + return null; + } + } + if (rowIdx < 0) { + rowIdx = this.getTableRows().length + rowIdx; + } + row = this.table.rowManager.getRowFromPosition(rowIdx + 1); + return row ? row.getCells(false, true).filter((cell) => cell.column.visible)[colIdx] : null; + } + + getActiveCell() { + if (!this.activeRange) return; + return this.getCell(this.activeRange.start.row, this.activeRange.start.col); + } + + getRowByRangePos(pos) { + return this.getTableRows()[pos]; + } + + getColumnByRangePos(pos) { + return this.getTableColumns()[pos]; + } + + getTableRows() { + return this.table.rowManager.getDisplayRows().filter((row) => row.type === "row"); + } + + getTableColumns() { + return this.table.columnManager.getVisibleColumnsByIndex(); + } + + addRange(start, end) { + var range2; + if (this.maxRanges !== true && this.ranges.length >= this.maxRanges) { + this.ranges.shift().destroy(); + } + range2 = new Range(this.table, this, start, end); + this.activeRange = range2; + this.ranges.push(range2); + this.rangeContainer.appendChild(range2.element); + return range2; + } + + createDefaultRange() { + var range2, cell, visibleCells; + range2 = this.addRange(); + if (this.table.rowManager.activeRows.length) { + visibleCells = this.table.rowManager.activeRows[0].cells.filter((cell2) => cell2.column.visible); + cell = visibleCells[this.rowHeader ? 1 : 0]; + if (cell) { + range2.setBounds(cell); + if (this.options("selectableRangeAutoFocus")) { + this.initializeFocus(cell); + } + } + } + return range2; + } + + clearRanges() { + this.ranges.forEach((range2) => range2.destroy()); + this.ranges = []; + } + + setDefaultRange() { + this.clearRanges(); + if (this.options("selectableRangeInitializeDefault")) { + this.createDefaultRange(); + } + } + + resetRanges() { + this.clearRanges(); + return this.createDefaultRange(); + } + + tableDestroyed() { + document.removeEventListener("mouseup", this.mouseUpEvent); + this.table.rowManager.element.removeEventListener("keydown", this.keyDownEvent); + } + + selectedRows(component) { + return component ? this.activeRange.getRows().map((row) => row.getComponent()) : this.activeRange.getRows(); + } + + selectedColumns(component) { + return component ? this.activeRange.getColumns().map((col) => col.getComponent()) : this.activeRange.getColumns(); + } + + getRowHeaderWidth() { + if (!this.rowHeader) { + return 0; + } + return this.rowHeader.getElement().offsetWidth; + } + + isEmpty(value) { + return value === null || value === void 0 || value === ""; + } + } + + __publicField(SelectRange, "moduleName", "selectRange"); + __publicField(SelectRange, "moduleInitOrder", 1); + __publicField(SelectRange, "moduleExtensions", extensions); + + function number(a, b, aRow, bRow, column, dir, params) { + var alignEmptyValues = params.alignEmptyValues; + var decimal = params.decimalSeparator; + var thousand = params.thousandSeparator; + var emptyAlign = 0; + a = String(a); + b = String(b); + if (thousand) { + a = a.split(thousand).join(""); + b = b.split(thousand).join(""); + } + if (decimal) { + a = a.split(decimal).join("."); + b = b.split(decimal).join("."); + } + a = parseFloat(a); + b = parseFloat(b); + if (isNaN(a)) { + emptyAlign = isNaN(b) ? 0 : -1; + } else if (isNaN(b)) { + emptyAlign = 1; + } else { + return a - b; + } + if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { + emptyAlign *= -1; + } + return emptyAlign; + } + + function string(a, b, aRow, bRow, column, dir, params) { + var alignEmptyValues = params.alignEmptyValues; + var emptyAlign = 0; + var locale; + if (!a) { + emptyAlign = !b ? 0 : -1; + } else if (!b) { + emptyAlign = 1; + } else { + switch (typeof params.locale) { + case "boolean": + if (params.locale) { + locale = this.langLocale(); + } + break; + case "string": + locale = params.locale; + break; + } + return String(a).toLowerCase().localeCompare(String(b).toLowerCase(), locale); + } + if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { + emptyAlign *= -1; + } + return emptyAlign; + } + + function datetime(a, b, aRow, bRow, column, dir, params) { + var DT = this.table.dependencyRegistry.lookup(["luxon", "DateTime"], "DateTime"); + var format = params.format || "dd/MM/yyyy HH:mm:ss", alignEmptyValues = params.alignEmptyValues, + emptyAlign = 0; + if (typeof DT != "undefined") { + if (!DT.isDateTime(a)) { + if (format === "iso") { + a = DT.fromISO(String(a)); + } else if (format === "x") { + a = DT.fromMillis(a); + } else { + a = DT.fromFormat(String(a), format); + } + } + if (!DT.isDateTime(b)) { + if (format === "iso") { + b = DT.fromISO(String(b)); + } else if (format === "x") { + b = DT.fromMillis(b); + } else { + b = DT.fromFormat(String(b), format); + } + } + if (!a.isValid) { + emptyAlign = !b.isValid ? 0 : -1; + } else if (!b.isValid) { + emptyAlign = 1; + } else { + return a - b; + } + if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { + emptyAlign *= -1; + } + return emptyAlign; + } else { + console.error("Sort Error - 'datetime' sorter is dependant on luxon.js"); + } + } + + function date(a, b, aRow, bRow, column, dir, params) { + if (!params.format) { + params.format = "dd/MM/yyyy"; + } + return datetime.call(this, a, b, aRow, bRow, column, dir, params); + } + + function time(a, b, aRow, bRow, column, dir, params) { + if (!params.format) { + params.format = "HH:mm"; + } + return datetime.call(this, a, b, aRow, bRow, column, dir, params); + } + + function boolean(a, b, aRow, bRow, column, dir, params) { + var el1 = a === true || a === "true" || a === "True" || a === 1 ? 1 : 0; + var el2 = b === true || b === "true" || b === "True" || b === 1 ? 1 : 0; + return el1 - el2; + } + + function array(a, b, aRow, bRow, column, dir, params) { + var type = params.type || "length", alignEmptyValues = params.alignEmptyValues, emptyAlign = 0, + table = this.table, valueMap; + if (params.valueMap) { + if (typeof params.valueMap === "string") { + valueMap = function (value) { + return value.map((item) => { + return Helpers.retrieveNestedData(table.options.nestedFieldSeparator, params.valueMap, item); + }); + }; + } else { + valueMap = params.valueMap; + } + } + + function calc(value) { + var result; + if (valueMap) { + value = valueMap(value); + } + switch (type) { + case "length": + result = value.length; + break; + case "sum": + result = value.reduce(function (c, d) { + return c + d; + }); + break; + case "max": + result = Math.max.apply(null, value); + break; + case "min": + result = Math.min.apply(null, value); + break; + case "avg": + result = value.reduce(function (c, d) { + return c + d; + }) / value.length; + break; + case "string": + result = value.join(""); + break; + } + return result; + } + + if (!Array.isArray(a)) { + emptyAlign = !Array.isArray(b) ? 0 : -1; + } else if (!Array.isArray(b)) { + emptyAlign = 1; + } else { + if (type === "string") { + return String(calc(a)).toLowerCase().localeCompare(String(calc(b)).toLowerCase()); + } else { + return calc(b) - calc(a); + } + } + if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { + emptyAlign *= -1; + } + return emptyAlign; + } + + function exists(a, b, aRow, bRow, column, dir, params) { + var el1 = typeof a == "undefined" ? 0 : 1; + var el2 = typeof b == "undefined" ? 0 : 1; + return el1 - el2; + } + + function alphanum(as, bs, aRow, bRow, column, dir, params) { + var a, b, a1, b1, i = 0, L, rx = /(\d+)|(\D+)/g, rd = /\d/; + var alignEmptyValues = params.alignEmptyValues; + var emptyAlign = 0; + if (!as && as !== 0) { + emptyAlign = !bs && bs !== 0 ? 0 : -1; + } else if (!bs && bs !== 0) { + emptyAlign = 1; + } else { + if (isFinite(as) && isFinite(bs)) return as - bs; + a = String(as).toLowerCase(); + b = String(bs).toLowerCase(); + if (a === b) return 0; + if (!(rd.test(a) && rd.test(b))) return a > b ? 1 : -1; + a = a.match(rx); + b = b.match(rx); + L = a.length > b.length ? b.length : a.length; + while (i < L) { + a1 = a[i]; + b1 = b[i++]; + if (a1 !== b1) { + if (isFinite(a1) && isFinite(b1)) { + if (a1.charAt(0) === "0") a1 = "." + a1; + if (b1.charAt(0) === "0") b1 = "." + b1; + return a1 - b1; + } else return a1 > b1 ? 1 : -1; + } + } + return a.length > b.length; + } + if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { + emptyAlign *= -1; + } + return emptyAlign; + } + + var defaultSorters = { + number, + string, + date, + time, + datetime, + boolean, + array, + exists, + alphanum + }; + const _Sort = class _Sort extends Module { + constructor(table) { + super(table); + this.sortList = []; + this.changed = false; + this.registerTableOption("sortMode", "local"); + this.registerTableOption("initialSort", false); + this.registerTableOption("columnHeaderSortMulti", true); + this.registerTableOption("sortOrderReverse", false); + this.registerTableOption("headerSortElement", "
"); + this.registerTableOption("headerSortClickElement", "header"); + this.registerColumnOption("sorter"); + this.registerColumnOption("sorterParams"); + this.registerColumnOption("headerSort", true); + this.registerColumnOption("headerSortStartingDir"); + this.registerColumnOption("headerSortTristate"); + } + + initialize() { + this.subscribe("column-layout", this.initializeColumn.bind(this)); + this.subscribe("table-built", this.tableBuilt.bind(this)); + this.registerDataHandler(this.sort.bind(this), 20); + this.registerTableFunction("setSort", this.userSetSort.bind(this)); + this.registerTableFunction("getSorters", this.getSort.bind(this)); + this.registerTableFunction("clearSort", this.clearSort.bind(this)); + if (this.table.options.sortMode === "remote") { + this.subscribe("data-params", this.remoteSortParams.bind(this)); + } + } + + tableBuilt() { + if (this.table.options.initialSort) { + this.setSort(this.table.options.initialSort); + } + } + + remoteSortParams(data, config, silent, params) { + var sorters = this.getSort(); + sorters.forEach((item) => { + delete item.column; + }); + params.sort = sorters; + return params; + } + + /////////////////////////////////// + ///////// Table Functions ///////// + /////////////////////////////////// + userSetSort(sortList, dir) { + this.setSort(sortList, dir); + this.refreshSort(); + } + + clearSort() { + this.clear(); + this.refreshSort(); + } + + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + //initialize column header for sorting + initializeColumn(column) { + var sorter = false, colEl, arrowEl; + switch (typeof column.definition.sorter) { + case "string": + if (_Sort.sorters[column.definition.sorter]) { + sorter = _Sort.sorters[column.definition.sorter]; + } else { + console.warn("Sort Error - No such sorter found: ", column.definition.sorter); + } + break; + case "function": + sorter = column.definition.sorter; + break; + } + column.modules.sort = { + sorter, + dir: "none", + params: column.definition.sorterParams || {}, + startingDir: column.definition.headerSortStartingDir || "asc", + tristate: column.definition.headerSortTristate + }; + if (column.definition.headerSort !== false) { + colEl = column.getElement(); + colEl.classList.add("tabulator-sortable"); + arrowEl = document.createElement("div"); + arrowEl.classList.add("tabulator-col-sorter"); + switch (this.table.options.headerSortClickElement) { + case "icon": + arrowEl.classList.add("tabulator-col-sorter-element"); + break; + case "header": + colEl.classList.add("tabulator-col-sorter-element"); + break; + default: + colEl.classList.add("tabulator-col-sorter-element"); + break; + } + switch (this.table.options.headerSortElement) { + case "function": + break; + case "object": + arrowEl.appendChild(this.table.options.headerSortElement); + break; + default: + arrowEl.innerHTML = this.table.options.headerSortElement; + } + column.titleHolderElement.appendChild(arrowEl); + column.modules.sort.element = arrowEl; + this.setColumnHeaderSortIcon(column, "none"); + if (this.table.options.headerSortClickElement === "icon") { + arrowEl.addEventListener("mousedown", (e) => { + e.stopPropagation(); + }); + } + (this.table.options.headerSortClickElement === "icon" ? arrowEl : colEl).addEventListener("click", (e) => { + var dir = "", sorters = [], match = false; + if (column.modules.sort) { + if (column.modules.sort.tristate) { + if (column.modules.sort.dir == "none") { + dir = column.modules.sort.startingDir; + } else { + if (column.modules.sort.dir == column.modules.sort.startingDir) { + dir = column.modules.sort.dir == "asc" ? "desc" : "asc"; + } else { + dir = "none"; + } + } + } else { + switch (column.modules.sort.dir) { + case "asc": + dir = "desc"; + break; + case "desc": + dir = "asc"; + break; + default: + dir = column.modules.sort.startingDir; + } + } + if (this.table.options.columnHeaderSortMulti && (e.shiftKey || e.ctrlKey)) { + sorters = this.getSort(); + match = sorters.findIndex((sorter2) => { + return sorter2.field === column.getField(); + }); + if (match > -1) { + sorters[match].dir = dir; + match = sorters.splice(match, 1)[0]; + if (dir != "none") { + sorters.push(match); + } + } else { + if (dir != "none") { + sorters.push({column, dir}); + } + } + this.setSort(sorters); + } else { + if (dir == "none") { + this.clear(); + } else { + this.setSort(column, dir); + } + } + this.refreshSort(); + } + }); + } + } + + refreshSort() { + if (this.table.options.sortMode === "remote") { + this.reloadData(null, false, false); + } else { + this.refreshData(true); + } + } + + //check if the sorters have changed since last use + hasChanged() { + var changed = this.changed; + this.changed = false; + return changed; + } + + //return current sorters + getSort() { + var self = this, sorters = []; + self.sortList.forEach(function (item) { + if (item.column) { + sorters.push({ + column: item.column.getComponent(), + field: item.column.getField(), + dir: item.dir + }); + } + }); + return sorters; + } + + //change sort list and trigger sort + setSort(sortList, dir) { + var self = this, newSortList = []; + if (!Array.isArray(sortList)) { + sortList = [{column: sortList, dir}]; + } + sortList.forEach(function (item) { + var column; + column = self.table.columnManager.findColumn(item.column); + if (column) { + item.column = column; + newSortList.push(item); + self.changed = true; + } else { + console.warn("Sort Warning - Sort field does not exist and is being ignored: ", item.column); + } + }); + self.sortList = newSortList; + this.dispatch("sort-changed"); + } + + //clear sorters + clear() { + this.setSort([]); + } + + //find appropriate sorter for column + findSorter(column) { + var row = this.table.rowManager.activeRows[0], sorter = "string", field, value; + if (row) { + row = row.getData(); + field = column.getField(); + if (field) { + value = column.getFieldValue(row); + switch (typeof value) { + case "undefined": + sorter = "string"; + break; + case "boolean": + sorter = "boolean"; + break; + default: + if (!isNaN(Number(value)) && value !== "") { + sorter = "number"; + } else { + if (value.match(/((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+$/i)) { + sorter = "alphanum"; + } + } + break; + } + } + } + return _Sort.sorters[sorter]; + } + + //work through sort list sorting data + sort(data, sortOnly) { + var self = this, + sortList = this.table.options.sortOrderReverse ? self.sortList.slice().reverse() : self.sortList, + sortListActual = [], rowComponents = []; + if (this.subscribedExternal("dataSorting")) { + this.dispatchExternal("dataSorting", self.getSort()); + } + if (!sortOnly) { + self.clearColumnHeaders(); + } + if (this.table.options.sortMode !== "remote") { + sortList.forEach(function (item, i) { + var sortObj; + if (item.column) { + sortObj = item.column.modules.sort; + if (sortObj) { + if (!sortObj.sorter) { + sortObj.sorter = self.findSorter(item.column); + } + item.params = typeof sortObj.params === "function" ? sortObj.params(item.column.getComponent(), item.dir) : sortObj.params; + sortListActual.push(item); + } + if (!sortOnly) { + self.setColumnHeader(item.column, item.dir); + } + } + }); + if (sortListActual.length) { + self._sortItems(data, sortListActual); + } + } else if (!sortOnly) { + sortList.forEach(function (item, i) { + self.setColumnHeader(item.column, item.dir); + }); + } + if (this.subscribedExternal("dataSorted")) { + data.forEach((row) => { + rowComponents.push(row.getComponent()); + }); + this.dispatchExternal("dataSorted", self.getSort(), rowComponents); + } + return data; + } + + //clear sort arrows on columns + clearColumnHeaders() { + this.table.columnManager.getRealColumns().forEach((column) => { + if (column.modules.sort) { + column.modules.sort.dir = "none"; + column.getElement().setAttribute("aria-sort", "none"); + this.setColumnHeaderSortIcon(column, "none"); + } + }); + } + + //set the column header sort direction + setColumnHeader(column, dir) { + column.modules.sort.dir = dir; + column.getElement().setAttribute("aria-sort", dir === "asc" ? "ascending" : "descending"); + this.setColumnHeaderSortIcon(column, dir); + } + + setColumnHeaderSortIcon(column, dir) { + var sortEl = column.modules.sort.element, arrowEl; + if (column.definition.headerSort && typeof this.table.options.headerSortElement === "function") { + while (sortEl.firstChild) sortEl.removeChild(sortEl.firstChild); + arrowEl = this.table.options.headerSortElement.call(this.table, column.getComponent(), dir); + if (typeof arrowEl === "object") { + sortEl.appendChild(arrowEl); + } else { + sortEl.innerHTML = arrowEl; + } + } + } + + //sort each item in sort list + _sortItems(data, sortList) { + var sorterCount = sortList.length - 1; + data.sort((a, b) => { + var result; + for (var i = sorterCount; i >= 0; i--) { + let sortItem = sortList[i]; + result = this._sortRow(a, b, sortItem.column, sortItem.dir, sortItem.params); + if (result !== 0) { + break; + } + } + return result; + }); + } + + //process individual rows for a sort function on active data + _sortRow(a, b, column, dir, params) { + var el1Comp, el2Comp; + var el1 = dir == "asc" ? a : b; + var el2 = dir == "asc" ? b : a; + a = column.getFieldValue(el1.getData()); + b = column.getFieldValue(el2.getData()); + a = typeof a !== "undefined" ? a : ""; + b = typeof b !== "undefined" ? b : ""; + el1Comp = el1.getComponent(); + el2Comp = el2.getComponent(); + return column.modules.sort.sorter.call(this, a, b, el1Comp, el2Comp, column.getComponent(), dir, params); + } + }; + __publicField(_Sort, "moduleName", "sort"); + //load defaults + __publicField(_Sort, "sorters", defaultSorters); + let Sort = _Sort; + + class GridCalculator { + constructor(columns, rows2) { + this.columnCount = columns; + this.rowCount = rows2; + this.columnString = []; + this.columns = []; + this.rows = []; + } + + genColumns(data) { + var colCount = Math.max(this.columnCount, Math.max(...data.map((item) => item.length))); + this.columnString = []; + this.columns = []; + for (let i = 1; i <= colCount; i++) { + this.incrementChar(this.columnString.length - 1); + this.columns.push(this.columnString.join("")); + } + return this.columns; + } + + genRows(data) { + var rowCount = Math.max(this.rowCount, data.length); + this.rows = []; + for (let i = 1; i <= rowCount; i++) { + this.rows.push(i); + } + return this.rows; + } + + incrementChar(i) { + let char = this.columnString[i]; + if (char) { + if (char !== "Z") { + this.columnString[i] = String.fromCharCode(this.columnString[i].charCodeAt(0) + 1); + } else { + this.columnString[i] = "A"; + if (i) { + this.incrementChar(i - 1); + } else { + this.columnString.push("A"); + } + } + } else { + this.columnString.push("A"); + } + } + + setRowCount(count) { + this.rowCount = count; + } + + setColumnCount(count) { + this.columnCount = count; + } + } + + class SheetComponent { + constructor(sheet) { + this._sheet = sheet; + return new Proxy(this, { + get: function (target, name2, receiver) { + if (typeof target[name2] !== "undefined") { + return target[name2]; + } else { + return target._sheet.table.componentFunctionBinder.handle("sheet", target._sheet, name2); + } + } + }); + } + + getTitle() { + return this._sheet.title; + } + + getKey() { + return this._sheet.key; + } + + getDefinition() { + return this._sheet.getDefinition(); + } + + getData() { + return this._sheet.getData(); + } + + setData(data) { + return this._sheet.setData(data); + } + + clear() { + return this._sheet.clear(); + } + + remove() { + return this._sheet.remove(); + } + + active() { + return this._sheet.active(); + } + + setTitle(title) { + return this._sheet.setTitle(title); + } + + setRows(rows2) { + return this._sheet.setRows(rows2); + } + + setColumns(columns) { + return this._sheet.setColumns(columns); + } + } + + class Sheet extends CoreFeature { + constructor(spreadsheetManager, definition) { + super(spreadsheetManager.table); + this.spreadsheetManager = spreadsheetManager; + this.definition = definition; + this.title = this.definition.title || ""; + this.key = this.definition.key || this.definition.title; + this.rowCount = this.definition.rows; + this.columnCount = this.definition.columns; + this.data = this.definition.data || []; + this.element = null; + this.isActive = false; + this.grid = new GridCalculator(this.columnCount, this.rowCount); + this.defaultColumnDefinition = {width: 100, headerHozAlign: "center", headerSort: false}; + this.columnDefinition = Object.assign(this.defaultColumnDefinition, this.options("spreadsheetColumnDefinition")); + this.columnDefs = []; + this.rowDefs = []; + this.columnFields = []; + this.columns = []; + this.rows = []; + this.scrollTop = null; + this.scrollLeft = null; + this.initialize(); + this.dispatchExternal("sheetAdded", this.getComponent()); + } + + /////////////////////////////////// + ///////// Initialization ////////// + /////////////////////////////////// + initialize() { + this.initializeElement(); + this.initializeColumns(); + this.initializeRows(); + } + + reinitialize() { + this.initializeColumns(); + this.initializeRows(); + } + + initializeElement() { + this.element = document.createElement("div"); + this.element.classList.add("tabulator-spreadsheet-tab"); + this.element.innerText = this.title; + this.element.addEventListener("click", () => { + this.spreadsheetManager.loadSheet(this); + }); + } + + initializeColumns() { + this.grid.setColumnCount(this.columnCount); + this.columnFields = this.grid.genColumns(this.data); + this.columnDefs = []; + this.columnFields.forEach((ref) => { + var def = Object.assign({}, this.columnDefinition); + def.field = ref; + def.title = ref; + this.columnDefs.push(def); + }); + } + + initializeRows() { + var refs; + this.grid.setRowCount(this.rowCount); + refs = this.grid.genRows(this.data); + this.rowDefs = []; + refs.forEach((ref, i) => { + var def = {"_id": ref}; + var data = this.data[i]; + if (data) { + data.forEach((val, j) => { + var field = this.columnFields[j]; + if (field) { + def[field] = val; + } + }); + } + this.rowDefs.push(def); + }); + } + + unload() { + this.isActive = false; + this.scrollTop = this.table.rowManager.scrollTop; + this.scrollLeft = this.table.rowManager.scrollLeft; + this.data = this.getData(true); + this.element.classList.remove("tabulator-spreadsheet-tab-active"); + } + + load() { + var wasInactive = !this.isActive; + this.isActive = true; + this.table.blockRedraw(); + this.table.setData([]); + this.table.setColumns(this.columnDefs); + this.table.setData(this.rowDefs); + this.table.restoreRedraw(); + if (wasInactive && this.scrollTop !== null) { + this.table.rowManager.element.scrollLeft = this.scrollLeft; + this.table.rowManager.element.scrollTop = this.scrollTop; + } + this.element.classList.add("tabulator-spreadsheet-tab-active"); + this.dispatchExternal("sheetLoaded", this.getComponent()); + } + + /////////////////////////////////// + //////// Helper Functions ///////// + /////////////////////////////////// + getComponent() { + return new SheetComponent(this); + } + + getDefinition() { + return { + title: this.title, + key: this.key, + rows: this.rowCount, + columns: this.columnCount, + data: this.getData() + }; + } + + getData(full) { + var output = [], rowWidths, outputWidth, outputHeight; + this.rowDefs.forEach((rowData) => { + var row = []; + this.columnFields.forEach((field) => { + row.push(rowData[field]); + }); + output.push(row); + }); + if (!full && !this.options("spreadsheetOutputFull")) { + rowWidths = output.map((row) => row.findLastIndex((val) => typeof val !== "undefined") + 1); + outputWidth = Math.max(...rowWidths); + outputHeight = rowWidths.findLastIndex((width) => width > 0) + 1; + output = output.slice(0, outputHeight); + output = output.map((row) => row.slice(0, outputWidth)); + } + return output; + } + + setData(data) { + this.data = data; + this.reinitialize(); + this.dispatchExternal("sheetUpdated", this.getComponent()); + if (this.isActive) { + this.load(); + } + } + + clear() { + this.setData([]); + } + + setTitle(title) { + this.title = title; + this.element.innerText = title; + this.dispatchExternal("sheetUpdated", this.getComponent()); + } + + setRows(rows2) { + this.rowCount = rows2; + this.initializeRows(); + this.dispatchExternal("sheetUpdated", this.getComponent()); + if (this.isActive) { + this.load(); + } + } + + setColumns(columns) { + this.columnCount = columns; + this.reinitialize(); + this.dispatchExternal("sheetUpdated", this.getComponent()); + if (this.isActive) { + this.load(); + } + } + + remove() { + this.spreadsheetManager.removeSheet(this); + } + + destroy() { + if (this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + this.dispatchExternal("sheetRemoved", this.getComponent()); + } + + active() { + this.spreadsheetManager.loadSheet(this); + } + } + + class Spreadsheet extends Module { + constructor(table) { + super(table); + this.sheets = []; + this.element = null; + this.registerTableOption("spreadsheet", false); + this.registerTableOption("spreadsheetRows", 50); + this.registerTableOption("spreadsheetColumns", 50); + this.registerTableOption("spreadsheetColumnDefinition", {}); + this.registerTableOption("spreadsheetOutputFull", false); + this.registerTableOption("spreadsheetData", false); + this.registerTableOption("spreadsheetSheets", false); + this.registerTableOption("spreadsheetSheetTabs", false); + this.registerTableOption("spreadsheetSheetTabsElement", false); + this.registerTableFunction("setSheets", this.setSheets.bind(this)); + this.registerTableFunction("addSheet", this.addSheet.bind(this)); + this.registerTableFunction("getSheets", this.getSheets.bind(this)); + this.registerTableFunction("getSheetDefinitions", this.getSheetDefinitions.bind(this)); + this.registerTableFunction("setSheetData", this.setSheetData.bind(this)); + this.registerTableFunction("getSheet", this.getSheet.bind(this)); + this.registerTableFunction("getSheetData", this.getSheetData.bind(this)); + this.registerTableFunction("clearSheet", this.clearSheet.bind(this)); + this.registerTableFunction("removeSheet", this.removeSheetFunc.bind(this)); + this.registerTableFunction("activeSheet", this.activeSheetFunc.bind(this)); + } + + /////////////////////////////////// + ////// Module Initialization ////// + /////////////////////////////////// + initialize() { + if (this.options("spreadsheet")) { + this.subscribe("table-initialized", this.tableInitialized.bind(this)); + this.subscribe("data-loaded", this.loadRemoteData.bind(this)); + this.table.options.index = "_id"; + if (this.options("spreadsheetData") && this.options("spreadsheetSheets")) { + console.warn("You cannot use spreadsheetData and spreadsheetSheets at the same time, ignoring spreadsheetData"); + this.table.options.spreadsheetData = false; + } + this.compatibilityCheck(); + if (this.options("spreadsheetSheetTabs")) { + this.initializeTabset(); + } + } + } + + compatibilityCheck() { + if (this.options("data")) { + console.warn("Do not use the data option when working with spreadsheets, use either spreadsheetData or spreadsheetSheets to pass data into the table"); + } + if (this.options("pagination")) { + console.warn("The spreadsheet module is not compatible with the pagination module"); + } + if (this.options("groupBy")) { + console.warn("The spreadsheet module is not compatible with the row grouping module"); + } + if (this.options("responsiveCollapse")) { + console.warn("The spreadsheet module is not compatible with the responsive collapse module"); + } + } + + initializeTabset() { + this.element = document.createElement("div"); + this.element.classList.add("tabulator-spreadsheet-tabs"); + var altContainer = this.options("spreadsheetSheetTabsElement"); + if (altContainer && !(altContainer instanceof HTMLElement)) { + altContainer = document.querySelector(altContainer); + if (!altContainer) { + console.warn("Unable to find element matching spreadsheetSheetTabsElement selector:", this.options("spreadsheetSheetTabsElement")); + } + } + if (altContainer) { + altContainer.appendChild(this.element); + } else { + this.footerAppend(this.element); + } + } + + tableInitialized() { + if (this.sheets.length) { + this.loadSheet(this.sheets[0]); + } else { + if (this.options("spreadsheetSheets")) { + this.loadSheets(this.options("spreadsheetSheets")); + } else if (this.options("spreadsheetData")) { + this.loadData(this.options("spreadsheetData")); + } + } + } + + /////////////////////////////////// + /////////// Ajax Parsing ////////// + /////////////////////////////////// + loadRemoteData(data, data1, data2) { + console.log("data", data, data1, data2); + if (Array.isArray(data)) { + this.table.dataLoader.clearAlert(); + this.dispatchExternal("dataLoaded", data); + if (!data.length || Array.isArray(data[0])) { + this.loadData(data); + } else { + this.loadSheets(data); + } + } else { + console.error("Spreadsheet Loading Error - Unable to process remote data due to invalid data type \nExpecting: array \nReceived: ", typeof data, "\nData: ", data); + } + return false; + } + + /////////////////////////////////// + ///////// Sheet Management //////// + /////////////////////////////////// + loadData(data) { + var def = { + data + }; + this.loadSheet(this.newSheet(def)); + } + + destroySheets() { + this.sheets.forEach((sheet) => { + sheet.destroy(); + }); + this.sheets = []; + this.activeSheet = null; + } + + loadSheets(sheets) { + if (!Array.isArray(sheets)) { + sheets = []; + } + this.destroySheets(); + sheets.forEach((def) => { + this.newSheet(def); + }); + this.loadSheet(this.sheets[0]); + } + + loadSheet(sheet) { + if (this.activeSheet !== sheet) { + if (this.activeSheet) { + this.activeSheet.unload(); + } + this.activeSheet = sheet; + sheet.load(); + } + } + + newSheet(definition = {}) { + var sheet; + if (!definition.rows) { + definition.rows = this.options("spreadsheetRows"); + } + if (!definition.columns) { + definition.columns = this.options("spreadsheetColumns"); + } + sheet = new Sheet(this, definition); + this.sheets.push(sheet); + if (this.element) { + this.element.appendChild(sheet.element); + } + return sheet; + } + + removeSheet(sheet) { + var index = this.sheets.indexOf(sheet), prevSheet; + if (this.sheets.length > 1) { + if (index > -1) { + this.sheets.splice(index, 1); + sheet.destroy(); + if (this.activeSheet === sheet) { + prevSheet = this.sheets[index - 1] || this.sheets[0]; + if (prevSheet) { + this.loadSheet(prevSheet); + } else { + this.activeSheet = null; + } + } + } + } else { + console.warn("Unable to remove sheet, at least one sheet must be active"); + } + } + + lookupSheet(key) { + if (!key) { + return this.activeSheet; + } else if (key instanceof Sheet) { + return key; + } else if (key instanceof SheetComponent) { + return key._sheet; + } else { + return this.sheets.find((sheet) => sheet.key === key) || false; + } + } + + /////////////////////////////////// + //////// Public Functions ///////// + /////////////////////////////////// + setSheets(sheets) { + this.loadSheets(sheets); + return this.getSheets(); + } + + addSheet(sheet) { + return this.newSheet(sheet).getComponent(); + } + + getSheetDefinitions() { + return this.sheets.map((sheet) => sheet.getDefinition()); + } + + getSheets() { + return this.sheets.map((sheet) => sheet.getComponent()); + } + + getSheet(key) { + var sheet = this.lookupSheet(key); + return sheet ? sheet.getComponent() : false; + } + + setSheetData(key, data) { + if (key && !data) { + data = key; + key = false; + } + var sheet = this.lookupSheet(key); + return sheet ? sheet.setData(data) : false; + } + + getSheetData(key) { + var sheet = this.lookupSheet(key); + return sheet ? sheet.getData() : false; + } + + clearSheet(key) { + var sheet = this.lookupSheet(key); + return sheet ? sheet.clear() : false; + } + + removeSheetFunc(key) { + var sheet = this.lookupSheet(key); + if (sheet) { + this.removeSheet(sheet); + } + } + + activeSheetFunc(key) { + var sheet = this.lookupSheet(key); + return sheet ? this.loadSheet(sheet) : false; + } + } + + __publicField(Spreadsheet, "moduleName", "spreadsheet"); + + class Tooltip extends Module { + constructor(table) { + super(table); + this.tooltipSubscriber = null, this.headerSubscriber = null, this.timeout = null; + this.popupInstance = null; + this.registerTableOption("tooltipDelay", 300); + this.registerColumnOption("tooltip"); + this.registerColumnOption("headerTooltip"); + } + + initialize() { + this.deprecatedOptionsCheck(); + this.subscribe("column-init", this.initializeColumn.bind(this)); + } + + deprecatedOptionsCheck() { + } + + initializeColumn(column) { + if (column.definition.headerTooltip && !this.headerSubscriber) { + this.headerSubscriber = true; + this.subscribe("column-mousemove", this.mousemoveCheck.bind(this, "headerTooltip")); + this.subscribe("column-mouseout", this.mouseoutCheck.bind(this, "headerTooltip")); + } + if (column.definition.tooltip && !this.tooltipSubscriber) { + this.tooltipSubscriber = true; + this.subscribe("cell-mousemove", this.mousemoveCheck.bind(this, "tooltip")); + this.subscribe("cell-mouseout", this.mouseoutCheck.bind(this, "tooltip")); + } + } + + mousemoveCheck(action, e, component) { + var tooltip = action === "tooltip" ? component.column.definition.tooltip : component.definition.headerTooltip; + if (tooltip) { + this.clearPopup(); + this.timeout = setTimeout(this.loadTooltip.bind(this, e, component, tooltip), this.table.options.tooltipDelay); + } + } + + mouseoutCheck(action, e, component) { + if (!this.popupInstance) { + this.clearPopup(); + } + } + + clearPopup(action, e, component) { + clearTimeout(this.timeout); + this.timeout = null; + if (this.popupInstance) { + this.popupInstance.hide(); + } + } + + loadTooltip(e, component, tooltip) { + var contentsEl, renderedCallback, coords; + + function onRendered(callback) { + renderedCallback = callback; + } + + if (typeof tooltip === "function") { + tooltip = tooltip(e, component.getComponent(), onRendered); + } + if (tooltip instanceof HTMLElement) { + contentsEl = tooltip; + } else { + contentsEl = document.createElement("div"); + if (tooltip === true) { + if (component instanceof Cell) { + tooltip = component.value; + } else { + if (component.definition.field) { + this.langBind("columns|" + component.definition.field, (value) => { + contentsEl.innerHTML = tooltip = value || component.definition.title; + }); + } else { + tooltip = component.definition.title; + } + } + } + contentsEl.innerHTML = tooltip; + } + if (tooltip || tooltip === 0 || tooltip === false) { + contentsEl.classList.add("tabulator-tooltip"); + contentsEl.addEventListener("mousemove", (e2) => e2.preventDefault()); + this.popupInstance = this.popup(contentsEl); + if (typeof renderedCallback === "function") { + this.popupInstance.renderCallback(renderedCallback); + } + coords = this.popupInstance.containerEventCoords(e); + this.popupInstance.show(coords.x + 15, coords.y + 15).hideOnBlur(() => { + this.dispatchExternal("TooltipClosed", component.getComponent()); + this.popupInstance = null; + }); + this.dispatchExternal("TooltipOpened", component.getComponent()); + } + } + } + + __publicField(Tooltip, "moduleName", "tooltip"); + var defaultValidators = { + //is integer + integer: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + value = Number(value); + return !isNaN(value) && isFinite(value) && Math.floor(value) === value; + }, + //is float + float: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + value = Number(value); + return !isNaN(value) && isFinite(value) && value % 1 !== 0; + }, + //must be a number + numeric: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + return !isNaN(value); + }, + //must be a string + string: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + return isNaN(value); + }, + //must be alphanumeric + alphanumeric: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + var reg = new RegExp(/^[a-z0-9]+$/i); + return reg.test(value); + }, + //maximum value + max: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + return parseFloat(value) <= parameters; + }, + //minimum value + min: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + return parseFloat(value) >= parameters; + }, + //starts with value + starts: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + return String(value).toLowerCase().startsWith(String(parameters).toLowerCase()); + }, + //ends with value + ends: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + return String(value).toLowerCase().endsWith(String(parameters).toLowerCase()); + }, + //minimum string length + minLength: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + return String(value).length >= parameters; + }, + //maximum string length + maxLength: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + return String(value).length <= parameters; + }, + //in provided value list + in: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + if (typeof parameters == "string") { + parameters = parameters.split("|"); + } + return parameters.indexOf(value) > -1; + }, + //must match provided regex + regex: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + var reg = new RegExp(parameters); + return reg.test(value); + }, + //value must be unique in this column + unique: function (cell, value, parameters) { + if (value === "" || value === null || typeof value === "undefined") { + return true; + } + var unique = true; + var cellData = cell.getData(); + var column = cell.getColumn()._getSelf(); + this.table.rowManager.rows.forEach(function (row) { + var data = row.getData(); + if (data !== cellData) { + if (value == column.getFieldValue(data)) { + unique = false; + } + } + }); + return unique; + }, + //must have a value + required: function (cell, value, parameters) { + return value !== "" && value !== null && typeof value !== "undefined"; + } + }; + const _Validate = class _Validate extends Module { + constructor(table) { + super(table); + this.invalidCells = []; + this.registerTableOption("validationMode", "blocking"); + this.registerColumnOption("validator"); + this.registerTableFunction("getInvalidCells", this.getInvalidCells.bind(this)); + this.registerTableFunction("clearCellValidation", this.userClearCellValidation.bind(this)); + this.registerTableFunction("validate", this.userValidate.bind(this)); + this.registerComponentFunction("cell", "isValid", this.cellIsValid.bind(this)); + this.registerComponentFunction("cell", "clearValidation", this.clearValidation.bind(this)); + this.registerComponentFunction("cell", "validate", this.cellValidate.bind(this)); + this.registerComponentFunction("column", "validate", this.columnValidate.bind(this)); + this.registerComponentFunction("row", "validate", this.rowValidate.bind(this)); + } + + initialize() { + this.subscribe("cell-delete", this.clearValidation.bind(this)); + this.subscribe("column-layout", this.initializeColumnCheck.bind(this)); + this.subscribe("edit-success", this.editValidate.bind(this)); + this.subscribe("edit-editor-clear", this.editorClear.bind(this)); + this.subscribe("edit-edited-clear", this.editedClear.bind(this)); + } + + /////////////////////////////////// + ///////// Event Handling ////////// + /////////////////////////////////// + editValidate(cell, value, previousValue) { + var valid = this.table.options.validationMode !== "manual" ? this.validate(cell.column.modules.validate, cell, value) : true; + if (valid !== true) { + setTimeout(() => { + cell.getElement().classList.add("tabulator-validation-fail"); + this.dispatchExternal("validationFailed", cell.getComponent(), value, valid); + }); + } + return valid; + } + + editorClear(cell, cancelled) { + if (cancelled) { + if (cell.column.modules.validate) { + this.cellValidate(cell); + } + } + cell.getElement().classList.remove("tabulator-validation-fail"); + } + + editedClear(cell) { + if (cell.modules.validate) { + cell.modules.validate.invalid = false; + } + } + + /////////////////////////////////// + ////////// Cell Functions ///////// + /////////////////////////////////// + cellIsValid(cell) { + return cell.modules.validate ? cell.modules.validate.invalid || true : true; + } + + cellValidate(cell) { + return this.validate(cell.column.modules.validate, cell, cell.getValue()); + } + + /////////////////////////////////// + ///////// Column Functions //////// + /////////////////////////////////// + columnValidate(column) { + var invalid = []; + column.cells.forEach((cell) => { + if (this.cellValidate(cell) !== true) { + invalid.push(cell.getComponent()); + } + }); + return invalid.length ? invalid : true; + } + + /////////////////////////////////// + ////////// Row Functions ////////// + /////////////////////////////////// + rowValidate(row) { + var invalid = []; + row.cells.forEach((cell) => { + if (this.cellValidate(cell) !== true) { + invalid.push(cell.getComponent()); + } + }); + return invalid.length ? invalid : true; + } + + /////////////////////////////////// + ///////// Table Functions ///////// + /////////////////////////////////// + userClearCellValidation(cells) { + if (!cells) { + cells = this.getInvalidCells(); + } + if (!Array.isArray(cells)) { + cells = [cells]; + } + cells.forEach((cell) => { + this.clearValidation(cell._getSelf()); + }); + } + + userValidate(cells) { + var output = []; + this.table.rowManager.rows.forEach((row) => { + row = row.getComponent(); + var valid = row.validate(); + if (valid !== true) { + output = output.concat(valid); + } + }); + return output.length ? output : true; + } + + /////////////////////////////////// + ///////// Internal Logic ////////// + /////////////////////////////////// + initializeColumnCheck(column) { + if (typeof column.definition.validator !== "undefined") { + this.initializeColumn(column); + } + } + + //validate + initializeColumn(column) { + var self = this, config = [], validator; + if (column.definition.validator) { + if (Array.isArray(column.definition.validator)) { + column.definition.validator.forEach((item) => { + validator = self._extractValidator(item); + if (validator) { + config.push(validator); + } + }); + } else { + validator = this._extractValidator(column.definition.validator); + if (validator) { + config.push(validator); + } + } + column.modules.validate = config.length ? config : false; + } + } + + _extractValidator(value) { + var type, params, pos; + switch (typeof value) { + case "string": + pos = value.indexOf(":"); + if (pos > -1) { + type = value.substring(0, pos); + params = value.substring(pos + 1); + } else { + type = value; + } + return this._buildValidator(type, params); + case "function": + return this._buildValidator(value); + case "object": + return this._buildValidator(value.type, value.parameters); + } + } + + _buildValidator(type, params) { + var func = typeof type == "function" ? type : _Validate.validators[type]; + if (!func) { + console.warn("Validator Setup Error - No matching validator found:", type); + return false; + } else { + return { + type: typeof type == "function" ? "function" : type, + func, + params + }; + } + } + + validate(validators, cell, value) { + var self = this, failedValidators = [], invalidIndex = this.invalidCells.indexOf(cell); + if (validators) { + validators.forEach((item) => { + if (!item.func.call(self, cell.getComponent(), value, item.params)) { + failedValidators.push({ + type: item.type, + parameters: item.params + }); + } + }); + } + if (!cell.modules.validate) { + cell.modules.validate = {}; + } + if (!failedValidators.length) { + cell.modules.validate.invalid = false; + cell.getElement().classList.remove("tabulator-validation-fail"); + if (invalidIndex > -1) { + this.invalidCells.splice(invalidIndex, 1); + } + } else { + cell.modules.validate.invalid = failedValidators; + if (this.table.options.validationMode !== "manual") { + cell.getElement().classList.add("tabulator-validation-fail"); + } + if (invalidIndex == -1) { + this.invalidCells.push(cell); + } + } + return failedValidators.length ? failedValidators : true; + } + + getInvalidCells() { + var output = []; + this.invalidCells.forEach((cell) => { + output.push(cell.getComponent()); + }); + return output; + } + + clearValidation(cell) { + var invalidIndex; + if (cell.modules.validate && cell.modules.validate.invalid) { + cell.getElement().classList.remove("tabulator-validation-fail"); + cell.modules.validate.invalid = false; + invalidIndex = this.invalidCells.indexOf(cell); + if (invalidIndex > -1) { + this.invalidCells.splice(invalidIndex, 1); + } + } + } + }; + __publicField(_Validate, "moduleName", "validate"); + //load defaults + __publicField(_Validate, "validators", defaultValidators); + let Validate = _Validate; + var allModules = /* @__PURE__ */ Object.freeze({ + __proto__: null, + AccessorModule: Accessor, + AjaxModule: Ajax, + ClipboardModule: Clipboard, + ColumnCalcsModule: ColumnCalcs, + DataTreeModule: DataTree, + DownloadModule: Download, + EditModule: Edit2, + ExportModule: Export, + FilterModule: Filter, + FormatModule: Format, + FrozenColumnsModule: FrozenColumns, + FrozenRowsModule: FrozenRows, + GroupRowsModule: GroupRows, + HistoryModule: History, + HtmlTableImportModule: HtmlTableImport, + ImportModule: Import, + InteractionModule: Interaction, + KeybindingsModule: Keybindings, + MenuModule: Menu, + MoveColumnsModule: MoveColumns, + MoveRowsModule: MoveRows, + MutatorModule: Mutator, + PageModule: Page, + PersistenceModule: Persistence, + PopupModule: Popup2, + PrintModule: Print, + ReactiveDataModule: ReactiveData, + ResizeColumnsModule: ResizeColumns, + ResizeRowsModule: ResizeRows, + ResizeTableModule: ResizeTable, + ResponsiveLayoutModule: ResponsiveLayout, + SelectRangeModule: SelectRange, + SelectRowModule: SelectRow, + SortModule: Sort, + SpreadsheetModule: Spreadsheet, + TooltipModule: Tooltip, + ValidateModule: Validate + }); + var defaultOptions = { + debugEventsExternal: false, + //flag to console log events + debugEventsInternal: false, + //flag to console log events + debugInvalidOptions: true, + //allow toggling of invalid option warnings + debugInvalidComponentFuncs: true, + //allow toggling of invalid component warnings + debugInitialization: true, + //allow toggling of pre initialization function call warnings + debugDeprecation: true, + //allow toggling of deprecation warnings + height: false, + //height of tabulator + minHeight: false, + //minimum height of tabulator + maxHeight: false, + //maximum height of tabulator + columnHeaderVertAlign: "top", + //vertical alignment of column headers + popupContainer: false, + columns: [], + //store for colum header info + columnDefaults: {}, + //store column default props + rowHeader: false, + data: false, + //default starting data + autoColumns: false, + //build columns from data row structure + autoColumnsDefinitions: false, + nestedFieldSeparator: ".", + //separator for nested data + footerElement: false, + //hold footer element + index: "id", + //filed for row index + textDirection: "auto", + addRowPos: "bottom", + //position to insert blank rows, top|bottom + headerVisible: true, + //hide header + renderVertical: "virtual", + renderHorizontal: "basic", + renderVerticalBuffer: 0, + // set virtual DOM buffer size + scrollToRowPosition: "top", + scrollToRowIfVisible: true, + scrollToColumnPosition: "left", + scrollToColumnIfVisible: true, + rowFormatter: false, + rowFormatterPrint: null, + rowFormatterClipboard: null, + rowFormatterHtmlOutput: null, + rowHeight: null, + placeholder: false, + dataLoader: true, + dataLoaderLoading: false, + dataLoaderError: false, + dataLoaderErrorTimeout: 3e3, + dataSendParams: {}, + dataReceiveParams: {}, + dependencies: {} + }; + + class OptionsList { + constructor(table, msgType, defaults = {}) { + this.table = table; + this.msgType = msgType; + this.registeredDefaults = Object.assign({}, defaults); + } + + register(option, value) { + this.registeredDefaults[option] = value; + } + + generate(defaultOptions2, userOptions = {}) { + var output = Object.assign({}, this.registeredDefaults), + warn = this.table.options.debugInvalidOptions || userOptions.debugInvalidOptions === true; + Object.assign(output, defaultOptions2); + for (let key in userOptions) { + if (!output.hasOwnProperty(key)) { + if (warn) { + console.warn("Invalid " + this.msgType + " option:", key); + } + output[key] = userOptions.key; + } + } + for (let key in output) { + if (key in userOptions) { + output[key] = userOptions[key]; + } else { + if (Array.isArray(output[key])) { + output[key] = Object.assign([], output[key]); + } else if (typeof output[key] === "object" && output[key] !== null) { + output[key] = Object.assign({}, output[key]); + } else if (typeof output[key] === "undefined") { + delete output[key]; + } + } + } + return output; + } + } + + class Renderer extends CoreFeature { + constructor(table) { + super(table); + this.elementVertical = table.rowManager.element; + this.elementHorizontal = table.columnManager.element; + this.tableElement = table.rowManager.tableElement; + this.verticalFillMode = "fit"; + } + + /////////////////////////////////// + /////// Internal Bindings ///////// + /////////////////////////////////// + initialize() { + } + + clearRows() { + } + + clearColumns() { + } + + reinitializeColumnWidths(columns) { + } + + renderRows() { + } + + renderColumns() { + } + + rerenderRows(callback) { + if (callback) { + callback(); + } + } + + rerenderColumns(update, blockRedraw) { + } + + renderRowCells(row) { + } + + rerenderRowCells(row, force) { + } + + scrollColumns(left, dir) { + } + + scrollRows(top, dir) { + } + + resize() { + } + + scrollToRow(row) { + } + + scrollToRowNearestTop(row) { + } + + visibleRows(includingBuffer) { + return []; + } + + /////////////////////////////////// + //////// Helper Functions ///////// + /////////////////////////////////// + rows() { + return this.table.rowManager.getDisplayRows(); + } + + styleRow(row, index) { + var rowEl = row.getElement(); + if (index % 2) { + rowEl.classList.add("tabulator-row-even"); + rowEl.classList.remove("tabulator-row-odd"); + } else { + rowEl.classList.add("tabulator-row-odd"); + rowEl.classList.remove("tabulator-row-even"); + } + } + + /////////////////////////////////// + /////// External Triggers ///////// + /////// (DO NOT OVERRIDE) ///////// + /////////////////////////////////// + clear() { + this.clearRows(); + this.clearColumns(); + } + + render() { + this.renderRows(); + this.renderColumns(); + } + + rerender(callback) { + this.rerenderRows(); + this.rerenderColumns(); + } + + scrollToRowPosition(row, position, ifVisible) { + var rowIndex = this.rows().indexOf(row), rowEl = row.getElement(), offset = 0; + return new Promise((resolve, reject) => { + if (rowIndex > -1) { + if (typeof ifVisible === "undefined") { + ifVisible = this.table.options.scrollToRowIfVisible; + } + if (!ifVisible) { + if (Helpers.elVisible(rowEl)) { + offset = Helpers.elOffset(rowEl).top - Helpers.elOffset(this.elementVertical).top; + if (offset > 0 && offset < this.elementVertical.clientHeight - rowEl.offsetHeight) { + resolve(); + return false; + } + } + } + if (typeof position === "undefined") { + position = this.table.options.scrollToRowPosition; + } + if (position === "nearest") { + position = this.scrollToRowNearestTop(row) ? "top" : "bottom"; + } + this.scrollToRow(row); + switch (position) { + case "middle": + case "center": + if (this.elementVertical.scrollHeight - this.elementVertical.scrollTop == this.elementVertical.clientHeight) { + this.elementVertical.scrollTop = this.elementVertical.scrollTop + (rowEl.offsetTop - this.elementVertical.scrollTop) - (this.elementVertical.scrollHeight - rowEl.offsetTop) / 2; + } else { + this.elementVertical.scrollTop = this.elementVertical.scrollTop - this.elementVertical.clientHeight / 2; + } + break; + case "bottom": + if (this.elementVertical.scrollHeight - this.elementVertical.scrollTop == this.elementVertical.clientHeight) { + this.elementVertical.scrollTop = this.elementVertical.scrollTop - (this.elementVertical.scrollHeight - rowEl.offsetTop) + rowEl.offsetHeight; + } else { + this.elementVertical.scrollTop = this.elementVertical.scrollTop - this.elementVertical.clientHeight + rowEl.offsetHeight; + } + break; + case "top": + this.elementVertical.scrollTop = rowEl.offsetTop; + break; + } + resolve(); + } else { + console.warn("Scroll Error - Row not visible"); + reject("Scroll Error - Row not visible"); + } + }); + } + } + + class BasicHorizontal extends Renderer { + constructor(table) { + super(table); + } + + renderRowCells(row, inFragment) { + const rowFrag = document.createDocumentFragment(); + row.cells.forEach((cell) => { + rowFrag.appendChild(cell.getElement()); + }); + row.element.appendChild(rowFrag); + if (!inFragment) { + row.cells.forEach((cell) => { + cell.cellRendered(); + }); + } + } + + reinitializeColumnWidths(columns) { + columns.forEach(function (column) { + column.reinitializeWidth(); + }); + } + } + + class VirtualDomHorizontal extends Renderer { + constructor(table) { + super(table); + this.leftCol = 0; + this.rightCol = 0; + this.scrollLeft = 0; + this.vDomScrollPosLeft = 0; + this.vDomScrollPosRight = 0; + this.vDomPadLeft = 0; + this.vDomPadRight = 0; + this.fitDataColAvg = 0; + this.windowBuffer = 200; + this.visibleRows = null; + this.initialized = false; + this.isFitData = false; + this.columns = []; + } + + initialize() { + this.compatibilityCheck(); + this.layoutCheck(); + this.vertScrollListen(); + } + + compatibilityCheck() { + if (this.options("layout") == "fitDataTable") { + console.warn("Horizontal Virtual DOM is not compatible with fitDataTable layout mode"); + } + if (this.options("responsiveLayout")) { + console.warn("Horizontal Virtual DOM is not compatible with responsive columns"); + } + if (this.options("rtl")) { + console.warn("Horizontal Virtual DOM is not currently compatible with RTL text direction"); + } + } + + layoutCheck() { + this.isFitData = this.options("layout").startsWith("fitData"); + } + + vertScrollListen() { + this.subscribe("scroll-vertical", this.clearVisRowCache.bind(this)); + this.subscribe("data-refreshed", this.clearVisRowCache.bind(this)); + } + + clearVisRowCache() { + this.visibleRows = null; + } + + ////////////////////////////////////// + ///////// Public Functions /////////// + ////////////////////////////////////// + renderColumns(row, force) { + this.dataChange(); + } + + scrollColumns(left, dir) { + if (this.scrollLeft != left) { + this.scrollLeft = left; + this.scroll(left - (this.vDomScrollPosLeft + this.windowBuffer)); + } + } + + calcWindowBuffer() { + var buffer = this.elementVertical.clientWidth; + this.table.columnManager.columnsByIndex.forEach((column) => { + if (column.visible) { + var width = column.getWidth(); + if (width > buffer) { + buffer = width; + } + } + }); + this.windowBuffer = buffer * 2; + } + + rerenderColumns(update, blockRedraw) { + var old = { + cols: this.columns, + leftCol: this.leftCol, + rightCol: this.rightCol + }, colPos = 0; + if (update && !this.initialized) { + return; + } + this.clear(); + this.calcWindowBuffer(); + this.scrollLeft = this.elementVertical.scrollLeft; + this.vDomScrollPosLeft = this.scrollLeft - this.windowBuffer; + this.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.windowBuffer; + this.table.columnManager.columnsByIndex.forEach((column) => { + var config = {}, width; + if (column.visible) { + if (!column.modules.frozen) { + width = column.getWidth(); + config.leftPos = colPos; + config.rightPos = colPos + width; + config.width = width; + if (this.isFitData) { + config.fitDataCheck = column.modules.vdomHoz ? column.modules.vdomHoz.fitDataCheck : true; + } + if (colPos + width > this.vDomScrollPosLeft && colPos < this.vDomScrollPosRight) { + if (this.leftCol == -1) { + this.leftCol = this.columns.length; + this.vDomPadLeft = colPos; + } + this.rightCol = this.columns.length; + } else { + if (this.leftCol !== -1) { + this.vDomPadRight += width; + } + } + this.columns.push(column); + column.modules.vdomHoz = config; + colPos += width; + } + } + }); + this.tableElement.style.paddingLeft = this.vDomPadLeft + "px"; + this.tableElement.style.paddingRight = this.vDomPadRight + "px"; + this.initialized = true; + if (!blockRedraw) { + if (!update || this.reinitChanged(old)) { + this.reinitializeRows(); + } + } + this.elementVertical.scrollLeft = this.scrollLeft; + } + + renderRowCells(row) { + if (this.initialized) { + this.initializeRow(row); + } else { + const rowFrag = document.createDocumentFragment(); + row.cells.forEach((cell) => { + rowFrag.appendChild(cell.getElement()); + }); + row.element.appendChild(rowFrag); + row.cells.forEach((cell) => { + cell.cellRendered(); + }); + } + } + + rerenderRowCells(row, force) { + this.reinitializeRow(row, force); + } + + reinitializeColumnWidths(columns) { + for (let i = this.leftCol; i <= this.rightCol; i++) { + let col = this.columns[i]; + if (col) { + col.reinitializeWidth(); + } + } + } + + ////////////////////////////////////// + //////// Internal Rendering ////////// + ////////////////////////////////////// + deinitialize() { + this.initialized = false; + } + + clear() { + this.columns = []; + this.leftCol = -1; + this.rightCol = 0; + this.vDomScrollPosLeft = 0; + this.vDomScrollPosRight = 0; + this.vDomPadLeft = 0; + this.vDomPadRight = 0; + } + + dataChange() { + var change = false, row, rowEl; + if (this.isFitData) { + this.table.columnManager.columnsByIndex.forEach((column) => { + if (!column.definition.width && column.visible) { + change = true; + } + }); + if (change && this.table.rowManager.getDisplayRows().length) { + this.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.windowBuffer; + row = this.chain("rows-sample", [1], [], () => { + return this.table.rowManager.getDisplayRows(); + })[0]; + if (row) { + rowEl = row.getElement(); + row.generateCells(); + this.tableElement.appendChild(rowEl); + for (let colEnd = 0; colEnd < row.cells.length; colEnd++) { + let cell = row.cells[colEnd]; + rowEl.appendChild(cell.getElement()); + cell.column.reinitializeWidth(); + } + rowEl.parentNode.removeChild(rowEl); + this.rerenderColumns(false, true); + } + } + } else { + if (this.options("layout") === "fitColumns") { + this.layoutRefresh(); + this.rerenderColumns(false, true); + } + } + } + + reinitChanged(old) { + var match = true; + if (old.cols.length !== this.columns.length || old.leftCol !== this.leftCol || old.rightCol !== this.rightCol) { + return true; + } + old.cols.forEach((col, i) => { + if (col !== this.columns[i]) { + match = false; + } + }); + return !match; + } + + reinitializeRows() { + var visibleRows = this.getVisibleRows(), + otherRows = this.table.rowManager.getRows().filter((row) => !visibleRows.includes(row)); + visibleRows.forEach((row) => { + this.reinitializeRow(row, true); + }); + otherRows.forEach((row) => { + row.deinitialize(); + }); + } + + getVisibleRows() { + if (!this.visibleRows) { + this.visibleRows = this.table.rowManager.getVisibleRows(); + } + return this.visibleRows; + } + + scroll(diff) { + this.vDomScrollPosLeft += diff; + this.vDomScrollPosRight += diff; + if (Math.abs(diff) > this.windowBuffer / 2) { + this.rerenderColumns(); + } else { + if (diff > 0) { + this.addColRight(); + this.removeColLeft(); + } else { + this.addColLeft(); + this.removeColRight(); + } + } + } + + colPositionAdjust(start, end, diff) { + for (let i = start; i < end; i++) { + let column = this.columns[i]; + column.modules.vdomHoz.leftPos += diff; + column.modules.vdomHoz.rightPos += diff; + } + } + + addColRight() { + var changes = false, working = true; + while (working) { + let column = this.columns[this.rightCol + 1]; + if (column) { + if (column.modules.vdomHoz.leftPos <= this.vDomScrollPosRight) { + changes = true; + this.getVisibleRows().forEach((row) => { + if (row.type !== "group") { + var cell = row.getCell(column); + row.getElement().insertBefore(cell.getElement(), row.getCell(this.columns[this.rightCol]).getElement().nextSibling); + cell.cellRendered(); + } + }); + this.fitDataColActualWidthCheck(column); + this.rightCol++; + this.getVisibleRows().forEach((row) => { + if (row.type !== "group") { + row.modules.vdomHoz.rightCol = this.rightCol; + } + }); + if (this.rightCol >= this.columns.length - 1) { + this.vDomPadRight = 0; + } else { + this.vDomPadRight -= column.getWidth(); + } + } else { + working = false; + } + } else { + working = false; + } + } + if (changes) { + this.tableElement.style.paddingRight = this.vDomPadRight + "px"; + } + } + + addColLeft() { + var changes = false, working = true; + while (working) { + let column = this.columns[this.leftCol - 1]; + if (column) { + if (column.modules.vdomHoz.rightPos >= this.vDomScrollPosLeft) { + changes = true; + this.getVisibleRows().forEach((row) => { + if (row.type !== "group") { + var cell = row.getCell(column); + row.getElement().insertBefore(cell.getElement(), row.getCell(this.columns[this.leftCol]).getElement()); + cell.cellRendered(); + } + }); + this.leftCol--; + this.getVisibleRows().forEach((row) => { + if (row.type !== "group") { + row.modules.vdomHoz.leftCol = this.leftCol; + } + }); + if (this.leftCol <= 0) { + this.vDomPadLeft = 0; + } else { + this.vDomPadLeft -= column.getWidth(); + } + let diff = this.fitDataColActualWidthCheck(column); + if (diff) { + this.scrollLeft = this.elementVertical.scrollLeft = this.elementVertical.scrollLeft + diff; + this.vDomPadRight -= diff; + } + } else { + working = false; + } + } else { + working = false; + } + } + if (changes) { + this.tableElement.style.paddingLeft = this.vDomPadLeft + "px"; + } + } + + removeColRight() { + var changes = false, working = true; + while (working) { + let column = this.columns[this.rightCol]; + if (column) { + if (column.modules.vdomHoz.leftPos > this.vDomScrollPosRight) { + changes = true; + this.getVisibleRows().forEach((row) => { + if (row.type !== "group") { + var cell = row.getCell(column); + try { + row.getElement().removeChild(cell.getElement()); + } catch (ex) { + console.warn("Could not removeColRight", ex.message); + } + } + }); + this.vDomPadRight += column.getWidth(); + this.rightCol--; + this.getVisibleRows().forEach((row) => { + if (row.type !== "group") { + row.modules.vdomHoz.rightCol = this.rightCol; + } + }); + } else { + working = false; + } + } else { + working = false; + } + } + if (changes) { + this.tableElement.style.paddingRight = this.vDomPadRight + "px"; + } + } + + removeColLeft() { + var changes = false, working = true; + while (working) { + let column = this.columns[this.leftCol]; + if (column) { + if (column.modules.vdomHoz.rightPos < this.vDomScrollPosLeft) { + changes = true; + this.getVisibleRows().forEach((row) => { + if (row.type !== "group") { + var cell = row.getCell(column); + try { + row.getElement().removeChild(cell.getElement()); + } catch (ex) { + console.warn("Could not removeColLeft", ex.message); + } + } + }); + this.vDomPadLeft += column.getWidth(); + this.leftCol++; + this.getVisibleRows().forEach((row) => { + if (row.type !== "group") { + row.modules.vdomHoz.leftCol = this.leftCol; + } + }); + } else { + working = false; + } + } else { + working = false; + } + } + if (changes) { + this.tableElement.style.paddingLeft = this.vDomPadLeft + "px"; + } + } + + fitDataColActualWidthCheck(column) { + var newWidth, widthDiff; + if (column.modules.vdomHoz.fitDataCheck) { + column.reinitializeWidth(); + newWidth = column.getWidth(); + widthDiff = newWidth - column.modules.vdomHoz.width; + if (widthDiff) { + column.modules.vdomHoz.rightPos += widthDiff; + column.modules.vdomHoz.width = newWidth; + this.colPositionAdjust(this.columns.indexOf(column) + 1, this.columns.length, widthDiff); + } + column.modules.vdomHoz.fitDataCheck = false; + } + return widthDiff; + } + + initializeRow(row) { + if (row.type !== "group") { + row.modules.vdomHoz = { + leftCol: this.leftCol, + rightCol: this.rightCol + }; + if (this.table.modules.frozenColumns) { + this.table.modules.frozenColumns.leftColumns.forEach((column) => { + this.appendCell(row, column); + }); + } + for (let i = this.leftCol; i <= this.rightCol; i++) { + this.appendCell(row, this.columns[i]); + } + if (this.table.modules.frozenColumns) { + this.table.modules.frozenColumns.rightColumns.forEach((column) => { + this.appendCell(row, column); + }); + } + } + } + + appendCell(row, column) { + if (column && column.visible) { + let cell = row.getCell(column); + row.getElement().appendChild(cell.getElement()); + cell.cellRendered(); + } + } + + reinitializeRow(row, force) { + if (row.type !== "group") { + if (force || !row.modules.vdomHoz || row.modules.vdomHoz.leftCol !== this.leftCol || row.modules.vdomHoz.rightCol !== this.rightCol) { + var rowEl = row.getElement(); + while (rowEl.firstChild) rowEl.removeChild(rowEl.firstChild); + this.initializeRow(row); + } + } + } + } + + class ColumnManager extends CoreFeature { + constructor(table) { + super(table); + this.blockHozScrollEvent = false; + this.headersElement = null; + this.contentsElement = null; + this.rowHeader = null; + this.element = null; + this.columns = []; + this.columnsByIndex = []; + this.columnsByField = {}; + this.scrollLeft = 0; + this.optionsList = new OptionsList(this.table, "column definition", defaultColumnOptions); + this.redrawBlock = false; + this.redrawBlockUpdate = null; + this.renderer = null; + } + + ////////////// Setup Functions ///////////////// + initialize() { + this.initializeRenderer(); + this.headersElement = this.createHeadersElement(); + this.contentsElement = this.createHeaderContentsElement(); + this.element = this.createHeaderElement(); + this.contentsElement.insertBefore(this.headersElement, this.contentsElement.firstChild); + this.element.insertBefore(this.contentsElement, this.element.firstChild); + this.initializeScrollWheelWatcher(); + this.subscribe("scroll-horizontal", this.scrollHorizontal.bind(this)); + this.subscribe("scrollbar-vertical", this.padVerticalScrollbar.bind(this)); + } + + padVerticalScrollbar(width) { + if (this.table.rtl) { + this.headersElement.style.marginLeft = width + "px"; + } else { + this.headersElement.style.marginRight = width + "px"; + } + } + + initializeRenderer() { + var renderClass; + var renderers = { + "virtual": VirtualDomHorizontal, + "basic": BasicHorizontal + }; + if (typeof this.table.options.renderHorizontal === "string") { + renderClass = renderers[this.table.options.renderHorizontal]; + } else { + renderClass = this.table.options.renderHorizontal; + } + if (renderClass) { + this.renderer = new renderClass(this.table, this.element, this.tableElement); + this.renderer.initialize(); + } else { + console.error("Unable to find matching renderer:", this.table.options.renderHorizontal); + } + } + + createHeadersElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-headers"); + el.setAttribute("role", "row"); + return el; + } + + createHeaderContentsElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-header-contents"); + return el; + } + + createHeaderElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-header"); + el.setAttribute("role", "rowgroup"); + if (!this.table.options.headerVisible) { + el.classList.add("tabulator-header-hidden"); + } + return el; + } + + //return containing element + getElement() { + return this.element; + } + + //return containing contents element + getContentsElement() { + return this.contentsElement; + } + + //return header containing element + getHeadersElement() { + return this.headersElement; + } + + //scroll horizontally to match table body + scrollHorizontal(left) { + this.contentsElement.scrollLeft = left; + this.scrollLeft = left; + this.renderer.scrollColumns(left); + } + + initializeScrollWheelWatcher() { + this.contentsElement.addEventListener("wheel", (e) => { + var left; + if (e.deltaX) { + left = this.contentsElement.scrollLeft + e.deltaX; + this.table.rowManager.scrollHorizontal(left); + this.table.columnManager.scrollHorizontal(left); + } + }); + } + + ///////////// Column Setup Functions ///////////// + generateColumnsFromRowData(data) { + var cols = [], collProgress = {}, + rowSample = this.table.options.autoColumns === "full" ? data : [data[0]], + definitions = this.table.options.autoColumnsDefinitions; + if (data && data.length) { + rowSample.forEach((row) => { + Object.keys(row).forEach((key, index) => { + let value = row[key], col; + if (!collProgress[key]) { + col = { + field: key, + title: key, + sorter: this.calculateSorterFromValue(value) + }; + cols.splice(index, 0, col); + collProgress[key] = typeof value === "undefined" ? col : true; + } else if (collProgress[key] !== true) { + if (typeof value !== "undefined") { + collProgress[key].sorter = this.calculateSorterFromValue(value); + collProgress[key] = true; + } + } + }); + }); + if (definitions) { + switch (typeof definitions) { + case "function": + this.table.options.columns = definitions.call(this.table, cols); + break; + case "object": + if (Array.isArray(definitions)) { + cols.forEach((col) => { + var match = definitions.find((def) => { + return def.field === col.field; + }); + if (match) { + Object.assign(col, match); + } + }); + } else { + cols.forEach((col) => { + if (definitions[col.field]) { + Object.assign(col, definitions[col.field]); + } + }); + } + this.table.options.columns = cols; + break; + } + } else { + this.table.options.columns = cols; + } + this.setColumns(this.table.options.columns); + } + } + + calculateSorterFromValue(value) { + var sorter; + switch (typeof value) { + case "undefined": + sorter = "string"; + break; + case "boolean": + sorter = "boolean"; + break; + case "number": + sorter = "number"; + break; + case "object": + if (Array.isArray(value)) { + sorter = "array"; + } else { + sorter = "string"; + } + break; + default: + if (!isNaN(Number(value)) && value !== "") { + sorter = "number"; + } else { + if (value.match(/((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+$/i)) { + sorter = "alphanum"; + } else { + sorter = "string"; + } + } + break; + } + return sorter; + } + + setColumns(cols, row) { + while (this.headersElement.firstChild) this.headersElement.removeChild(this.headersElement.firstChild); + this.columns = []; + this.columnsByIndex = []; + this.columnsByField = {}; + this.dispatch("columns-loading"); + this.dispatchExternal("columnsLoading"); + if (this.table.options.rowHeader) { + this.rowHeader = new Column(this.table.options.rowHeader === true ? {} : this.table.options.rowHeader, this, true); + this.columns.push(this.rowHeader); + this.headersElement.appendChild(this.rowHeader.getElement()); + this.rowHeader.columnRendered(); + } + cols.forEach((def, i) => { + this._addColumn(def); + }); + this._reIndexColumns(); + this.dispatch("columns-loaded"); + if (this.subscribedExternal("columnsLoaded")) { + this.dispatchExternal("columnsLoaded", this.getComponents()); + } + this.rerenderColumns(false, true); + this.redraw(true); + } + + _addColumn(definition, before, nextToColumn) { + var column = new Column(definition, this), colEl = column.getElement(), + index = nextToColumn ? this.findColumnIndex(nextToColumn) : nextToColumn; + if (before && this.rowHeader && (!nextToColumn || nextToColumn === this.rowHeader)) { + before = false; + nextToColumn = this.rowHeader; + index = 0; + } + if (nextToColumn && index > -1) { + var topColumn = nextToColumn.getTopColumn(); + var parentIndex = this.columns.indexOf(topColumn); + var nextEl = topColumn.getElement(); + if (before) { + this.columns.splice(parentIndex, 0, column); + nextEl.parentNode.insertBefore(colEl, nextEl); + } else { + this.columns.splice(parentIndex + 1, 0, column); + nextEl.parentNode.insertBefore(colEl, nextEl.nextSibling); + } + } else { + if (before) { + this.columns.unshift(column); + this.headersElement.insertBefore(column.getElement(), this.headersElement.firstChild); + } else { + this.columns.push(column); + this.headersElement.appendChild(column.getElement()); + } + } + column.columnRendered(); + return column; + } + + registerColumnField(col) { + if (col.definition.field) { + this.columnsByField[col.definition.field] = col; + } + } + + registerColumnPosition(col) { + this.columnsByIndex.push(col); + } + + _reIndexColumns() { + this.columnsByIndex = []; + this.columns.forEach(function (column) { + column.reRegisterPosition(); + }); + } + + //ensure column headers take up the correct amount of space in column groups + verticalAlignHeaders() { + var minHeight = 0; + if (!this.redrawBlock) { + this.headersElement.style.height = ""; + this.columns.forEach((column) => { + column.clearVerticalAlign(); + }); + this.columns.forEach((column) => { + var height = column.getHeight(); + if (height > minHeight) { + minHeight = height; + } + }); + this.headersElement.style.height = minHeight + "px"; + this.columns.forEach((column) => { + column.verticalAlign(this.table.options.columnHeaderVertAlign, minHeight); + }); + this.table.rowManager.adjustTableSize(); + } + } + + //////////////// Column Details ///////////////// + findColumn(subject) { + var columns; + if (typeof subject == "object") { + if (subject instanceof Column) { + return subject; + } else if (subject instanceof ColumnComponent) { + return subject._getSelf() || false; + } else if (typeof HTMLElement !== "undefined" && subject instanceof HTMLElement) { + columns = []; + this.columns.forEach((column) => { + columns.push(column); + columns = columns.concat(column.getColumns(true)); + }); + let match = columns.find((column) => { + return column.element === subject; + }); + return match || false; + } + } else { + return this.columnsByField[subject] || false; + } + return false; + } + + getColumnByField(field) { + return this.columnsByField[field]; + } + + getColumnsByFieldRoot(root) { + var matches = []; + Object.keys(this.columnsByField).forEach((field) => { + var fieldRoot = this.table.options.nestedFieldSeparator ? field.split(this.table.options.nestedFieldSeparator)[0] : field; + if (fieldRoot === root) { + matches.push(this.columnsByField[field]); + } + }); + return matches; + } + + getColumnByIndex(index) { + return this.columnsByIndex[index]; + } + + getFirstVisibleColumn() { + var index = this.columnsByIndex.findIndex((col) => { + return col.visible; + }); + return index > -1 ? this.columnsByIndex[index] : false; + } + + getVisibleColumnsByIndex() { + return this.columnsByIndex.filter((col) => col.visible); + } + + getColumns() { + return this.columns; + } + + findColumnIndex(column) { + return this.columnsByIndex.findIndex((col) => { + return column === col; + }); + } + + //return all columns that are not groups + getRealColumns() { + return this.columnsByIndex; + } + + //traverse across columns and call action + traverse(callback) { + this.columnsByIndex.forEach((column, i) => { + callback(column, i); + }); + } + + //get definitions of actual columns + getDefinitions(active) { + var output = []; + this.columnsByIndex.forEach((column) => { + if (!active || active && column.visible) { + output.push(column.getDefinition()); + } + }); + return output; + } + + //get full nested definition tree + getDefinitionTree() { + var output = []; + this.columns.forEach((column) => { + output.push(column.getDefinition(true)); + }); + return output; + } + + getComponents(structured) { + var output = [], columns = structured ? this.columns : this.columnsByIndex; + columns.forEach((column) => { + output.push(column.getComponent()); + }); + return output; + } + + getWidth() { + var width = 0; + this.columnsByIndex.forEach((column) => { + if (column.visible) { + width += column.getWidth(); + } + }); + return width; + } + + moveColumn(from, to, after) { + to.element.parentNode.insertBefore(from.element, to.element); + if (after) { + to.element.parentNode.insertBefore(to.element, from.element); + } + this.moveColumnActual(from, to, after); + this.verticalAlignHeaders(); + this.table.rowManager.reinitialize(); + } + + moveColumnActual(from, to, after) { + if (from.parent.isGroup) { + this._moveColumnInArray(from.parent.columns, from, to, after); + } else { + this._moveColumnInArray(this.columns, from, to, after); + } + this._moveColumnInArray(this.columnsByIndex, from, to, after, true); + this.rerenderColumns(true); + this.dispatch("column-moved", from, to, after); + if (this.subscribedExternal("columnMoved")) { + this.dispatchExternal("columnMoved", from.getComponent(), this.table.columnManager.getComponents()); + } + } + + _moveColumnInArray(columns, from, to, after, updateRows) { + var fromIndex = columns.indexOf(from), toIndex, rows2 = []; + if (fromIndex > -1) { + columns.splice(fromIndex, 1); + toIndex = columns.indexOf(to); + if (toIndex > -1) { + if (after) { + toIndex = toIndex + 1; + } + } else { + toIndex = fromIndex; + } + columns.splice(toIndex, 0, from); + if (updateRows) { + rows2 = this.chain("column-moving-rows", [from, to, after], null, []) || []; + rows2 = rows2.concat(this.table.rowManager.rows); + rows2.forEach(function (row) { + if (row.cells.length) { + var cell = row.cells.splice(fromIndex, 1)[0]; + row.cells.splice(toIndex, 0, cell); + } + }); + } + } + } + + scrollToColumn(column, position, ifVisible) { + var left = 0, offset = column.getLeftOffset(), adjust = 0, colEl = column.getElement(); + return new Promise((resolve, reject) => { + if (typeof position === "undefined") { + position = this.table.options.scrollToColumnPosition; + } + if (typeof ifVisible === "undefined") { + ifVisible = this.table.options.scrollToColumnIfVisible; + } + if (column.visible) { + switch (position) { + case "middle": + case "center": + adjust = -this.element.clientWidth / 2; + break; + case "right": + adjust = colEl.clientWidth - this.headersElement.clientWidth; + break; + } + if (!ifVisible) { + if (offset > 0 && offset + colEl.offsetWidth < this.element.clientWidth) { + return false; + } + } + left = offset + adjust; + left = Math.max(Math.min(left, this.table.rowManager.element.scrollWidth - this.table.rowManager.element.clientWidth), 0); + this.table.rowManager.scrollHorizontal(left); + this.scrollHorizontal(left); + resolve(); + } else { + console.warn("Scroll Error - Column not visible"); + reject("Scroll Error - Column not visible"); + } + }); + } + + //////////////// Cell Management ///////////////// + generateCells(row) { + var cells = []; + this.columnsByIndex.forEach((column) => { + cells.push(column.generateCell(row)); + }); + return cells; + } + + //////////////// Column Management ///////////////// + getFlexBaseWidth() { + var totalWidth = this.table.element.clientWidth, fixedWidth = 0; + if (this.table.rowManager.element.scrollHeight > this.table.rowManager.element.clientHeight) { + totalWidth -= this.table.rowManager.element.offsetWidth - this.table.rowManager.element.clientWidth; + } + this.columnsByIndex.forEach(function (column) { + var width, minWidth, colWidth; + if (column.visible) { + width = column.definition.width || 0; + minWidth = parseInt(column.minWidth); + if (typeof width == "string") { + if (width.indexOf("%") > -1) { + colWidth = totalWidth / 100 * parseInt(width); + } else { + colWidth = parseInt(width); + } + } else { + colWidth = width; + } + fixedWidth += colWidth > minWidth ? colWidth : minWidth; + } + }); + return fixedWidth; + } + + addColumn(definition, before, nextToColumn) { + return new Promise((resolve, reject) => { + var column = this._addColumn(definition, before, nextToColumn); + this._reIndexColumns(); + this.dispatch("column-add", definition, before, nextToColumn); + if (this.layoutMode() != "fitColumns") { + column.reinitializeWidth(); + } + this.redraw(true); + this.table.rowManager.reinitialize(); + this.rerenderColumns(); + resolve(column); + }); + } + + //remove column from system + deregisterColumn(column) { + var field = column.getField(), index; + if (field) { + delete this.columnsByField[field]; + } + index = this.columnsByIndex.indexOf(column); + if (index > -1) { + this.columnsByIndex.splice(index, 1); + } + index = this.columns.indexOf(column); + if (index > -1) { + this.columns.splice(index, 1); + } + this.verticalAlignHeaders(); + this.redraw(); + } + + rerenderColumns(update, silent) { + if (!this.redrawBlock) { + this.renderer.rerenderColumns(update, silent); + } else { + if (update === false || update === true && this.redrawBlockUpdate === null) { + this.redrawBlockUpdate = update; + } + } + } + + blockRedraw() { + this.redrawBlock = true; + this.redrawBlockUpdate = null; + } + + restoreRedraw() { + this.redrawBlock = false; + this.verticalAlignHeaders(); + this.renderer.rerenderColumns(this.redrawBlockUpdate); + } + + //redraw columns + redraw(force) { + if (Helpers.elVisible(this.element)) { + this.verticalAlignHeaders(); + } + if (force) { + this.table.rowManager.resetScroll(); + this.table.rowManager.reinitialize(); + } + if (!this.confirm("table-redrawing", force)) { + this.layoutRefresh(force); + } + this.dispatch("table-redraw", force); + this.table.footerManager.redraw(); + } + } + + class BasicVertical extends Renderer { + constructor(table) { + super(table); + this.verticalFillMode = "fill"; + this.scrollTop = 0; + this.scrollLeft = 0; + this.scrollTop = 0; + this.scrollLeft = 0; + } + + clearRows() { + var element = this.tableElement; + while (element.firstChild) element.removeChild(element.firstChild); + element.scrollTop = 0; + element.scrollLeft = 0; + element.style.minWidth = ""; + element.style.minHeight = ""; + element.style.display = ""; + element.style.visibility = ""; + } + + renderRows() { + var element = this.tableElement, onlyGroupHeaders = true, tableFrag = document.createDocumentFragment(), + rows2 = this.rows(); + rows2.forEach((row, index) => { + this.styleRow(row, index); + row.initialize(false, true); + if (row.type !== "group") { + onlyGroupHeaders = false; + } + tableFrag.appendChild(row.getElement()); + }); + element.appendChild(tableFrag); + rows2.forEach((row) => { + row.rendered(); + if (!row.heightInitialized) { + row.calcHeight(true); + } + }); + rows2.forEach((row) => { + if (!row.heightInitialized) { + row.setCellHeight(); + } + }); + if (onlyGroupHeaders) { + element.style.minWidth = this.table.columnManager.getWidth() + "px"; + } else { + element.style.minWidth = ""; + } + } + + rerenderRows(callback) { + this.clearRows(); + if (callback) { + callback(); + } + this.renderRows(); + if (!this.rows().length) { + this.table.rowManager.tableEmpty(); + } + } + + scrollToRowNearestTop(row) { + var rowTop = Helpers.elOffset(row.getElement()).top; + return !(Math.abs(this.elementVertical.scrollTop - rowTop) > Math.abs(this.elementVertical.scrollTop + this.elementVertical.clientHeight - rowTop)); + } + + scrollToRow(row) { + var rowEl = row.getElement(); + this.elementVertical.scrollTop = Helpers.elOffset(rowEl).top - Helpers.elOffset(this.elementVertical).top + this.elementVertical.scrollTop; + } + + visibleRows(includingBuffer) { + return this.rows(); + } + } + + class VirtualDomVertical extends Renderer { + constructor(table) { + super(table); + this.verticalFillMode = "fill"; + this.scrollTop = 0; + this.scrollLeft = 0; + this.vDomRowHeight = 20; + this.vDomTop = 0; + this.vDomBottom = 0; + this.vDomScrollPosTop = 0; + this.vDomScrollPosBottom = 0; + this.vDomTopPad = 0; + this.vDomBottomPad = 0; + this.vDomMaxRenderChain = 90; + this.vDomWindowBuffer = 0; + this.vDomWindowMinTotalRows = 20; + this.vDomWindowMinMarginRows = 5; + this.vDomTopNewRows = []; + this.vDomBottomNewRows = []; + } + + ////////////////////////////////////// + ///////// Public Functions /////////// + ////////////////////////////////////// + clearRows() { + var element = this.tableElement; + while (element.firstChild) element.removeChild(element.firstChild); + element.style.paddingTop = ""; + element.style.paddingBottom = ""; + element.style.minHeight = ""; + element.style.display = ""; + element.style.visibility = ""; + this.elementVertical.scrollTop = 0; + this.elementVertical.scrollLeft = 0; + this.scrollTop = 0; + this.scrollLeft = 0; + this.vDomTop = 0; + this.vDomBottom = 0; + this.vDomTopPad = 0; + this.vDomBottomPad = 0; + this.vDomScrollPosTop = 0; + this.vDomScrollPosBottom = 0; + } + + renderRows() { + this._virtualRenderFill(); + } + + rerenderRows(callback) { + var scrollTop = this.elementVertical.scrollTop; + var topRow = false; + var topOffset = false; + var left = this.table.rowManager.scrollLeft; + var rows2 = this.rows(); + for (var i = this.vDomTop; i <= this.vDomBottom; i++) { + if (rows2[i]) { + var diff = scrollTop - rows2[i].getElement().offsetTop; + if (topOffset === false || Math.abs(diff) < topOffset) { + topOffset = diff; + topRow = i; + } else { + break; + } + } + } + rows2.forEach((row) => { + row.deinitializeHeight(); + }); + if (callback) { + callback(); + } + if (this.rows().length) { + this._virtualRenderFill(topRow === false ? this.rows.length - 1 : topRow, true, topOffset || 0); + } else { + this.clear(); + this.table.rowManager.tableEmpty(); + } + this.scrollColumns(left); + } + + scrollColumns(left) { + this.table.rowManager.scrollHorizontal(left); + } + + scrollRows(top, dir) { + var topDiff = top - this.vDomScrollPosTop; + var bottomDiff = top - this.vDomScrollPosBottom; + var margin = this.vDomWindowBuffer * 2; + var rows2 = this.rows(); + this.scrollTop = top; + if (-topDiff > margin || bottomDiff > margin) { + var left = this.table.rowManager.scrollLeft; + this._virtualRenderFill(Math.floor(this.elementVertical.scrollTop / this.elementVertical.scrollHeight * rows2.length)); + this.scrollColumns(left); + } else { + if (dir) { + if (topDiff < 0) { + this._addTopRow(rows2, -topDiff); + } + if (bottomDiff < 0) { + if (this.vDomScrollHeight - this.scrollTop > this.vDomWindowBuffer) { + this._removeBottomRow(rows2, -bottomDiff); + } else { + this.vDomScrollPosBottom = this.scrollTop; + } + } + } else { + if (bottomDiff >= 0) { + this._addBottomRow(rows2, bottomDiff); + } + if (topDiff >= 0) { + if (this.scrollTop > this.vDomWindowBuffer) { + this._removeTopRow(rows2, topDiff); + } else { + this.vDomScrollPosTop = this.scrollTop; + } + } + } + } + } + + resize() { + this.vDomWindowBuffer = this.table.options.renderVerticalBuffer || this.elementVertical.clientHeight; + } + + scrollToRowNearestTop(row) { + var rowIndex = this.rows().indexOf(row); + return !(Math.abs(this.vDomTop - rowIndex) > Math.abs(this.vDomBottom - rowIndex)); + } + + scrollToRow(row) { + var index = this.rows().indexOf(row); + if (index > -1) { + this._virtualRenderFill(index, true); + } + } + + visibleRows(includingBuffer) { + var topEdge = this.elementVertical.scrollTop, bottomEdge = this.elementVertical.clientHeight + topEdge, + topFound = false, topRow = 0, bottomRow = 0, rows2 = this.rows(); + if (includingBuffer) { + topRow = this.vDomTop; + bottomRow = this.vDomBottom; + } else { + for (var i = this.vDomTop; i <= this.vDomBottom; i++) { + if (rows2[i]) { + if (!topFound) { + if (topEdge - rows2[i].getElement().offsetTop >= 0) { + topRow = i; + } else { + topFound = true; + if (bottomEdge - rows2[i].getElement().offsetTop >= 0) { + bottomRow = i; + } else { + break; + } + } + } else { + if (bottomEdge - rows2[i].getElement().offsetTop >= 0) { + bottomRow = i; + } else { + break; + } + } + } + } + } + return rows2.slice(topRow, bottomRow + 1); + } + + ////////////////////////////////////// + //////// Internal Rendering ////////// + ////////////////////////////////////// + //full virtual render + _virtualRenderFill(position, forceMove, offset) { + var element = this.tableElement, holder = this.elementVertical, topPad = 0, rowsHeight = 0, + rowHeight = 0, heightOccupied = 0, topPadHeight = 0, i = 0, rows2 = this.rows(), + rowsCount = rows2.length, index = 0, row, rowFragment, renderedRows = [], totalRowsRendered = 0, + rowsToRender = 0, fixedHeight = this.table.rowManager.fixedHeight, + containerHeight = this.elementVertical.clientHeight, avgRowHeight = this.table.options.rowHeight, + resized = true; + position = position || 0; + offset = offset || 0; + if (!position) { + this.clear(); + } else { + while (element.firstChild) element.removeChild(element.firstChild); + heightOccupied = (rowsCount - position + 1) * this.vDomRowHeight; + if (heightOccupied < containerHeight) { + position -= Math.ceil((containerHeight - heightOccupied) / this.vDomRowHeight); + if (position < 0) { + position = 0; + } + } + topPad = Math.min(Math.max(Math.floor(this.vDomWindowBuffer / this.vDomRowHeight), this.vDomWindowMinMarginRows), position); + position -= topPad; + } + if (rowsCount && Helpers.elVisible(this.elementVertical)) { + this.vDomTop = position; + this.vDomBottom = position - 1; + if (fixedHeight || this.table.options.maxHeight) { + if (avgRowHeight) { + rowsToRender = containerHeight / avgRowHeight + this.vDomWindowBuffer / avgRowHeight; + } + rowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil(rowsToRender)); + } else { + rowsToRender = rowsCount; + } + while ((rowsToRender == rowsCount || rowsHeight <= containerHeight + this.vDomWindowBuffer || totalRowsRendered < this.vDomWindowMinTotalRows) && this.vDomBottom < rowsCount - 1) { + renderedRows = []; + rowFragment = document.createDocumentFragment(); + i = 0; + while (i < rowsToRender && this.vDomBottom < rowsCount - 1) { + index = this.vDomBottom + 1, row = rows2[index]; + this.styleRow(row, index); + row.initialize(false, true); + if (!row.heightInitialized && !this.table.options.rowHeight) { + row.clearCellHeight(); + } + rowFragment.appendChild(row.getElement()); + renderedRows.push(row); + this.vDomBottom++; + i++; + } + if (!renderedRows.length) { + break; + } + element.appendChild(rowFragment); + renderedRows.forEach((row2) => { + row2.rendered(); + }); + const rowsNeedingHeightInit = []; + renderedRows.forEach((row2) => { + if (!row2.heightInitialized || !row2.getHeight()) { + row2.calcHeight(true); + rowsNeedingHeightInit.push(row2); + } + }); + rowsNeedingHeightInit.forEach((row2) => { + row2.setCellHeight(); + }); + renderedRows.forEach((row2) => { + rowHeight = row2.getHeight() || this.vDomRowHeight; + if (totalRowsRendered < topPad) { + topPadHeight += rowHeight; + } else { + rowsHeight += rowHeight; + } + if (rowHeight > this.vDomWindowBuffer) { + this.vDomWindowBuffer = rowHeight * 2; + } + totalRowsRendered++; + }); + resized = this.table.rowManager.adjustTableSize(); + containerHeight = this.elementVertical.clientHeight; + if (resized && (fixedHeight || this.table.options.maxHeight)) { + avgRowHeight = rowsHeight / totalRowsRendered; + rowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil(containerHeight / avgRowHeight + this.vDomWindowBuffer / avgRowHeight)); + } + } + if (!position) { + this.vDomTopPad = 0; + this.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / totalRowsRendered); + this.vDomBottomPad = this.vDomRowHeight * (rowsCount - this.vDomBottom - 1); + this.vDomScrollHeight = topPadHeight + rowsHeight + this.vDomBottomPad - containerHeight; + } else { + this.vDomTopPad = !forceMove ? this.scrollTop - topPadHeight : this.vDomRowHeight * this.vDomTop + offset; + this.vDomBottomPad = this.vDomBottom == rowsCount - 1 ? 0 : Math.max(this.vDomScrollHeight - this.vDomTopPad - rowsHeight - topPadHeight, 0); + } + element.style.paddingTop = this.vDomTopPad + "px"; + element.style.paddingBottom = this.vDomBottomPad + "px"; + if (forceMove) { + this.scrollTop = this.vDomTopPad + topPadHeight + offset - (this.elementVertical.scrollWidth > this.elementVertical.clientWidth ? this.elementVertical.offsetHeight - containerHeight : 0); + } + this.scrollTop = Math.min(this.scrollTop, this.elementVertical.scrollHeight - containerHeight); + if (this.elementVertical.scrollWidth > this.elementVertical.clientWidth && forceMove) { + this.scrollTop += this.elementVertical.offsetHeight - containerHeight; + } + this.vDomScrollPosTop = this.scrollTop; + this.vDomScrollPosBottom = this.scrollTop; + holder.scrollTop = this.scrollTop; + this.dispatch("render-virtual-fill"); + } + } + + _addTopRow(rows2, fillableSpace) { + var table = this.tableElement, addedRows = [], paddingAdjust = 0, index = this.vDomTop - 1, i = 0, + working = true; + while (working) { + if (this.vDomTop) { + let row = rows2[index], rowHeight, initialized; + if (row && i < this.vDomMaxRenderChain) { + rowHeight = row.getHeight() || this.vDomRowHeight; + initialized = row.initialized; + if (fillableSpace >= rowHeight) { + this.styleRow(row, index); + table.insertBefore(row.getElement(), table.firstChild); + if (!row.initialized || !row.heightInitialized) { + addedRows.push(row); + } + row.initialize(); + if (!initialized) { + rowHeight = row.getElement().offsetHeight; + if (rowHeight > this.vDomWindowBuffer) { + this.vDomWindowBuffer = rowHeight * 2; + } + } + fillableSpace -= rowHeight; + paddingAdjust += rowHeight; + this.vDomTop--; + index--; + i++; + } else { + working = false; + } + } else { + working = false; + } + } else { + working = false; + } + } + for (let row of addedRows) { + row.clearCellHeight(); + } + this._quickNormalizeRowHeight(addedRows); + if (paddingAdjust) { + this.vDomTopPad -= paddingAdjust; + if (this.vDomTopPad < 0) { + this.vDomTopPad = index * this.vDomRowHeight; + } + if (index < 1) { + this.vDomTopPad = 0; + } + table.style.paddingTop = this.vDomTopPad + "px"; + this.vDomScrollPosTop -= paddingAdjust; + } + } + + _removeTopRow(rows2, fillableSpace) { + var removableRows = [], paddingAdjust = 0, i = 0, working = true; + while (working) { + let row = rows2[this.vDomTop], rowHeight; + if (row && i < this.vDomMaxRenderChain) { + rowHeight = row.getHeight() || this.vDomRowHeight; + if (fillableSpace >= rowHeight) { + this.vDomTop++; + fillableSpace -= rowHeight; + paddingAdjust += rowHeight; + removableRows.push(row); + i++; + } else { + working = false; + } + } else { + working = false; + } + } + for (let row of removableRows) { + let rowEl = row.getElement(); + if (rowEl.parentNode) { + rowEl.parentNode.removeChild(rowEl); + } + } + if (paddingAdjust) { + this.vDomTopPad += paddingAdjust; + this.tableElement.style.paddingTop = this.vDomTopPad + "px"; + this.vDomScrollPosTop += this.vDomTop ? paddingAdjust : paddingAdjust + this.vDomWindowBuffer; + } + } + + _addBottomRow(rows2, fillableSpace) { + var table = this.tableElement, addedRows = [], paddingAdjust = 0, index = this.vDomBottom + 1, i = 0, + working = true; + while (working) { + let row = rows2[index], rowHeight, initialized; + if (row && i < this.vDomMaxRenderChain) { + rowHeight = row.getHeight() || this.vDomRowHeight; + initialized = row.initialized; + if (fillableSpace >= rowHeight) { + this.styleRow(row, index); + table.appendChild(row.getElement()); + if (!row.initialized || !row.heightInitialized) { + addedRows.push(row); + } + row.initialize(); + if (!initialized) { + rowHeight = row.getElement().offsetHeight; + if (rowHeight > this.vDomWindowBuffer) { + this.vDomWindowBuffer = rowHeight * 2; + } + } + fillableSpace -= rowHeight; + paddingAdjust += rowHeight; + this.vDomBottom++; + index++; + i++; + } else { + working = false; + } + } else { + working = false; + } + } + for (let row of addedRows) { + row.clearCellHeight(); + } + this._quickNormalizeRowHeight(addedRows); + if (paddingAdjust) { + this.vDomBottomPad -= paddingAdjust; + if (this.vDomBottomPad < 0 || index == rows2.length - 1) { + this.vDomBottomPad = 0; + } + table.style.paddingBottom = this.vDomBottomPad + "px"; + this.vDomScrollPosBottom += paddingAdjust; + } + } + + _removeBottomRow(rows2, fillableSpace) { + var removableRows = [], paddingAdjust = 0, i = 0, working = true; + while (working) { + let row = rows2[this.vDomBottom], rowHeight; + if (row && i < this.vDomMaxRenderChain) { + rowHeight = row.getHeight() || this.vDomRowHeight; + if (fillableSpace >= rowHeight) { + this.vDomBottom--; + fillableSpace -= rowHeight; + paddingAdjust += rowHeight; + removableRows.push(row); + i++; + } else { + working = false; + } + } else { + working = false; + } + } + for (let row of removableRows) { + let rowEl = row.getElement(); + if (rowEl.parentNode) { + rowEl.parentNode.removeChild(rowEl); + } + } + if (paddingAdjust) { + this.vDomBottomPad += paddingAdjust; + if (this.vDomBottomPad < 0) { + this.vDomBottomPad = 0; + } + this.tableElement.style.paddingBottom = this.vDomBottomPad + "px"; + this.vDomScrollPosBottom -= paddingAdjust; + } + } + + _quickNormalizeRowHeight(rows2) { + for (let row of rows2) { + row.calcHeight(); + } + for (let row of rows2) { + row.setCellHeight(); + } + } + } + + class RowManager extends CoreFeature { + constructor(table) { + super(table); + this.element = this.createHolderElement(); + this.tableElement = this.createTableElement(); + this.heightFixer = this.createTableElement(); + this.placeholder = null; + this.placeholderContents = null; + this.firstRender = false; + this.renderMode = "virtual"; + this.fixedHeight = false; + this.rows = []; + this.activeRowsPipeline = []; + this.activeRows = []; + this.activeRowsCount = 0; + this.displayRows = []; + this.displayRowsCount = 0; + this.scrollTop = 0; + this.scrollLeft = 0; + this.redrawBlock = false; + this.redrawBlockRestoreConfig = false; + this.redrawBlockRenderInPosition = false; + this.dataPipeline = []; + this.displayPipeline = []; + this.scrollbarWidth = 0; + this.renderer = null; + } + + //////////////// Setup Functions ///////////////// + createHolderElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-tableholder"); + el.setAttribute("tabindex", 0); + return el; + } + + createTableElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-table"); + el.setAttribute("role", "rowgroup"); + el.setAttribute("id", "tabulator-table-body"); + return el; + } + + initializePlaceholder() { + var placeholder = this.table.options.placeholder; + if (typeof placeholder === "function") { + placeholder = placeholder.call(this.table); + } + placeholder = this.chain("placeholder", [placeholder], placeholder, placeholder) || placeholder; + if (placeholder) { + let el = document.createElement("div"); + el.classList.add("tabulator-placeholder"); + if (typeof placeholder == "string") { + let contents = document.createElement("div"); + contents.classList.add("tabulator-placeholder-contents"); + contents.innerHTML = placeholder; + el.appendChild(contents); + this.placeholderContents = contents; + } else if (typeof HTMLElement !== "undefined" && placeholder instanceof HTMLElement) { + el.appendChild(placeholder); + this.placeholderContents = placeholder; + } else { + console.warn("Invalid placeholder provided, must be string or HTML Element", placeholder); + this.el = null; + } + this.placeholder = el; + } + } + + //return containing element + getElement() { + return this.element; + } + + //return table element + getTableElement() { + return this.tableElement; + } + + initialize() { + this.initializePlaceholder(); + this.initializeRenderer(); + this.element.appendChild(this.tableElement); + this.firstRender = true; + this.element.addEventListener("scroll", () => { + var left = this.element.scrollLeft, leftDir = this.scrollLeft > left, top = this.element.scrollTop, + topDir = this.scrollTop > top; + if (this.scrollLeft != left) { + this.scrollLeft = left; + this.dispatch("scroll-horizontal", left, leftDir); + this.dispatchExternal("scrollHorizontal", left, leftDir); + this._positionPlaceholder(); + } + if (this.scrollTop != top) { + this.scrollTop = top; + this.renderer.scrollRows(top, topDir); + this.dispatch("scroll-vertical", top, topDir); + this.dispatchExternal("scrollVertical", top, topDir); + } + }); + } + + ////////////////// Row Manipulation ////////////////// + findRow(subject) { + if (typeof subject == "object") { + if (subject instanceof Row) { + return subject; + } else if (subject instanceof RowComponent) { + return subject._getSelf() || false; + } else if (typeof HTMLElement !== "undefined" && subject instanceof HTMLElement) { + let match = this.rows.find((row) => { + return row.getElement() === subject; + }); + return match || false; + } else if (subject === null) { + return false; + } + } else if (typeof subject == "undefined") { + return false; + } else { + let match = this.rows.find((row) => { + return row.data[this.table.options.index] == subject; + }); + return match || false; + } + return false; + } + + getRowFromDataObject(data) { + var match = this.rows.find((row) => { + return row.data === data; + }); + return match || false; + } + + getRowFromPosition(position) { + return this.getDisplayRows().find((row) => { + return row.type === "row" && row.getPosition() === position && row.isDisplayed(); + }); + } + + scrollToRow(row, position, ifVisible) { + return this.renderer.scrollToRowPosition(row, position, ifVisible); + } + + ////////////////// Data Handling ////////////////// + setData(data, renderInPosition, columnsChanged) { + return new Promise((resolve, reject) => { + if (renderInPosition && this.getDisplayRows().length) { + if (this.table.options.pagination) { + this._setDataActual(data, true); + } else { + this.reRenderInPosition(() => { + this._setDataActual(data); + }); + } + } else { + if (this.table.options.autoColumns && columnsChanged && this.table.initialized) { + this.table.columnManager.generateColumnsFromRowData(data); + } + this.resetScroll(); + this._setDataActual(data); + } + resolve(); + }); + } + + _setDataActual(data, renderInPosition) { + this.dispatchExternal("dataProcessing", data); + this._wipeElements(); + if (Array.isArray(data)) { + this.dispatch("data-processing", data); + data.forEach((def, i) => { + if (def && typeof def === "object") { + var row = new Row(def, this); + this.rows.push(row); + } else { + console.warn("Data Loading Warning - Invalid row data detected and ignored, expecting object but received:", def); + } + }); + this.refreshActiveData(false, false, renderInPosition); + this.dispatch("data-processed", data); + this.dispatchExternal("dataProcessed", data); + } else { + console.error("Data Loading Error - Unable to process data due to invalid data type \nExpecting: array \nReceived: ", typeof data, "\nData: ", data); + } + } + + _wipeElements() { + this.dispatch("rows-wipe"); + this.destroy(); + this.adjustTableSize(); + this.dispatch("rows-wiped"); + } + + destroy() { + this.rows.forEach((row) => { + row.wipe(); + }); + this.rows = []; + this.activeRows = []; + this.activeRowsPipeline = []; + this.activeRowsCount = 0; + this.displayRows = []; + this.displayRowsCount = 0; + } + + deleteRow(row, blockRedraw) { + var allIndex = this.rows.indexOf(row), activeIndex = this.activeRows.indexOf(row); + if (activeIndex > -1) { + this.activeRows.splice(activeIndex, 1); + } + if (allIndex > -1) { + this.rows.splice(allIndex, 1); + } + this.setActiveRows(this.activeRows); + this.displayRowIterator((rows2) => { + var displayIndex = rows2.indexOf(row); + if (displayIndex > -1) { + rows2.splice(displayIndex, 1); + } + }); + if (!blockRedraw) { + this.reRenderInPosition(); + } + this.regenerateRowPositions(); + this.dispatchExternal("rowDeleted", row.getComponent()); + if (!this.displayRowsCount) { + this.tableEmpty(); + } + if (this.subscribedExternal("dataChanged")) { + this.dispatchExternal("dataChanged", this.getData()); + } + } + + addRow(data, pos, index, blockRedraw) { + var row = this.addRowActual(data, pos, index, blockRedraw); + return row; + } + + //add multiple rows + addRows(data, pos, index, refreshDisplayOnly) { + var rows2 = []; + return new Promise((resolve, reject) => { + pos = this.findAddRowPos(pos); + if (!Array.isArray(data)) { + data = [data]; + } + if (typeof index == "undefined" && pos || typeof index !== "undefined" && !pos) { + data.reverse(); + } + data.forEach((item, i) => { + var row = this.addRow(item, pos, index, true); + rows2.push(row); + this.dispatch("row-added", row, item, pos, index); + }); + this.refreshActiveData(refreshDisplayOnly ? "displayPipeline" : false, false, true); + this.regenerateRowPositions(); + if (this.displayRowsCount) { + this._clearPlaceholder(); + } + resolve(rows2); + }); + } + + findAddRowPos(pos) { + if (typeof pos === "undefined") { + pos = this.table.options.addRowPos; + } + if (pos === "pos") { + pos = true; + } + if (pos === "bottom") { + pos = false; + } + return pos; + } + + addRowActual(data, pos, index, blockRedraw) { + var row = data instanceof Row ? data : new Row(data || {}, this), top = this.findAddRowPos(pos), + allIndex = -1, activeIndex, chainResult; + if (!index) { + chainResult = this.chain("row-adding-position", [row, top], null, {index, top}); + index = chainResult.index; + top = chainResult.top; + } + if (typeof index !== "undefined") { + index = this.findRow(index); + } + index = this.chain("row-adding-index", [row, index, top], null, index); + if (index) { + allIndex = this.rows.indexOf(index); + } + if (index && allIndex > -1) { + activeIndex = this.activeRows.indexOf(index); + this.displayRowIterator(function (rows2) { + var displayIndex = rows2.indexOf(index); + if (displayIndex > -1) { + rows2.splice(top ? displayIndex : displayIndex + 1, 0, row); + } + }); + if (activeIndex > -1) { + this.activeRows.splice(top ? activeIndex : activeIndex + 1, 0, row); + } + this.rows.splice(top ? allIndex : allIndex + 1, 0, row); + } else { + if (top) { + this.displayRowIterator(function (rows2) { + rows2.unshift(row); + }); + this.activeRows.unshift(row); + this.rows.unshift(row); + } else { + this.displayRowIterator(function (rows2) { + rows2.push(row); + }); + this.activeRows.push(row); + this.rows.push(row); + } + } + this.setActiveRows(this.activeRows); + this.dispatchExternal("rowAdded", row.getComponent()); + if (this.subscribedExternal("dataChanged")) { + this.dispatchExternal("dataChanged", this.table.rowManager.getData()); + } + if (!blockRedraw) { + this.reRenderInPosition(); + } + return row; + } + + moveRow(from, to, after) { + this.dispatch("row-move", from, to, after); + this.moveRowActual(from, to, after); + this.regenerateRowPositions(); + this.dispatch("row-moved", from, to, after); + this.dispatchExternal("rowMoved", from.getComponent()); + } + + moveRowActual(from, to, after) { + this.moveRowInArray(this.rows, from, to, after); + this.moveRowInArray(this.activeRows, from, to, after); + this.displayRowIterator((rows2) => { + this.moveRowInArray(rows2, from, to, after); + }); + this.dispatch("row-moving", from, to, after); + } + + moveRowInArray(rows2, from, to, after) { + var fromIndex, toIndex, start, end; + if (from !== to) { + fromIndex = rows2.indexOf(from); + if (fromIndex > -1) { + rows2.splice(fromIndex, 1); + toIndex = rows2.indexOf(to); + if (toIndex > -1) { + if (after) { + rows2.splice(toIndex + 1, 0, from); + } else { + rows2.splice(toIndex, 0, from); + } + } else { + rows2.splice(fromIndex, 0, from); + } + } + if (rows2 === this.getDisplayRows()) { + start = fromIndex < toIndex ? fromIndex : toIndex; + end = toIndex > fromIndex ? toIndex : fromIndex + 1; + for (let i = start; i <= end; i++) { + if (rows2[i]) { + this.styleRow(rows2[i], i); + } + } + } + } + } + + clearData() { + this.setData([]); + } + + getRowIndex(row) { + return this.findRowIndex(row, this.rows); + } + + getDisplayRowIndex(row) { + var index = this.getDisplayRows().indexOf(row); + return index > -1 ? index : false; + } + + nextDisplayRow(row, rowOnly) { + var index = this.getDisplayRowIndex(row), nextRow = false; + if (index !== false && index < this.displayRowsCount - 1) { + nextRow = this.getDisplayRows()[index + 1]; + } + if (nextRow && (!(nextRow instanceof Row) || nextRow.type != "row")) { + return this.nextDisplayRow(nextRow, rowOnly); + } + return nextRow; + } + + prevDisplayRow(row, rowOnly) { + var index = this.getDisplayRowIndex(row), prevRow = false; + if (index) { + prevRow = this.getDisplayRows()[index - 1]; + } + if (rowOnly && prevRow && (!(prevRow instanceof Row) || prevRow.type != "row")) { + return this.prevDisplayRow(prevRow, rowOnly); + } + return prevRow; + } + + findRowIndex(row, list2) { + var rowIndex; + row = this.findRow(row); + if (row) { + rowIndex = list2.indexOf(row); + if (rowIndex > -1) { + return rowIndex; + } + } + return false; + } + + getData(active, transform) { + var output = [], rows2 = this.getRows(active); + rows2.forEach(function (row) { + if (row.type == "row") { + output.push(row.getData(transform || "data")); + } + }); + return output; + } + + getComponents(active) { + var output = [], rows2 = this.getRows(active); + rows2.forEach(function (row) { + output.push(row.getComponent()); + }); + return output; + } + + getDataCount(active) { + var rows2 = this.getRows(active); + return rows2.length; + } + + scrollHorizontal(left) { + this.scrollLeft = left; + this.element.scrollLeft = left; + this.dispatch("scroll-horizontal", left); + } + + registerDataPipelineHandler(handler, priority) { + if (typeof priority !== "undefined") { + this.dataPipeline.push({handler, priority}); + this.dataPipeline.sort((a, b) => { + return a.priority - b.priority; + }); + } else { + console.error("Data pipeline handlers must have a priority in order to be registered"); + } + } + + registerDisplayPipelineHandler(handler, priority) { + if (typeof priority !== "undefined") { + this.displayPipeline.push({handler, priority}); + this.displayPipeline.sort((a, b) => { + return a.priority - b.priority; + }); + } else { + console.error("Display pipeline handlers must have a priority in order to be registered"); + } + } + + //set active data set + refreshActiveData(handler, skipStage, renderInPosition) { + var table = this.table, stage = "", index = 0, + cascadeOrder = ["all", "dataPipeline", "display", "displayPipeline", "end"]; + if (!this.table.destroyed) { + if (typeof handler === "function") { + index = this.dataPipeline.findIndex((item) => { + return item.handler === handler; + }); + if (index > -1) { + stage = "dataPipeline"; + if (skipStage) { + if (index == this.dataPipeline.length - 1) { + stage = "display"; + } else { + index++; + } + } + } else { + index = this.displayPipeline.findIndex((item) => { + return item.handler === handler; + }); + if (index > -1) { + stage = "displayPipeline"; + if (skipStage) { + if (index == this.displayPipeline.length - 1) { + stage = "end"; + } else { + index++; + } + } + } else { + console.error("Unable to refresh data, invalid handler provided", handler); + return; + } + } + } else { + stage = handler || "all"; + index = 0; + } + if (this.redrawBlock) { + if (!this.redrawBlockRestoreConfig || this.redrawBlockRestoreConfig && (this.redrawBlockRestoreConfig.stage === stage && index < this.redrawBlockRestoreConfig.index || cascadeOrder.indexOf(stage) < cascadeOrder.indexOf(this.redrawBlockRestoreConfig.stage))) { + this.redrawBlockRestoreConfig = { + handler, + skipStage, + renderInPosition, + stage, + index + }; + } + return; + } else { + if (Helpers.elVisible(this.element)) { + if (renderInPosition) { + this.reRenderInPosition(this.refreshPipelines.bind(this, handler, stage, index, renderInPosition)); + } else { + this.refreshPipelines(handler, stage, index, renderInPosition); + if (!handler) { + this.table.columnManager.renderer.renderColumns(); + } + this.renderTable(); + if (table.options.layoutColumnsOnNewData) { + this.table.columnManager.redraw(true); + } + } + } else { + this.refreshPipelines(handler, stage, index, renderInPosition); + } + this.dispatch("data-refreshed"); + } + } + } + + refreshPipelines(handler, stage, index, renderInPosition) { + this.dispatch("data-refreshing"); + if (!handler || !this.activeRowsPipeline[0]) { + this.activeRowsPipeline[0] = this.rows.slice(0); + } + switch (stage) { + case "all": + //handle case where all data needs refreshing + case "dataPipeline": + for (let i = index; i < this.dataPipeline.length; i++) { + let result = this.dataPipeline[i].handler(this.activeRowsPipeline[i].slice(0)); + this.activeRowsPipeline[i + 1] = result || this.activeRowsPipeline[i].slice(0); + } + this.setActiveRows(this.activeRowsPipeline[this.dataPipeline.length]); + case "display": + index = 0; + this.resetDisplayRows(); + case "displayPipeline": + for (let i = index; i < this.displayPipeline.length; i++) { + let result = this.displayPipeline[i].handler((i ? this.getDisplayRows(i - 1) : this.activeRows).slice(0), renderInPosition); + this.setDisplayRows(result || this.getDisplayRows(i - 1).slice(0), i); + } + case "end": + this.regenerateRowPositions(); + } + if (this.getDisplayRows().length) { + this._clearPlaceholder(); + } + } + + //regenerate row positions + regenerateRowPositions() { + var rows2 = this.getDisplayRows(); + var index = 1; + rows2.forEach((row) => { + if (row.type === "row") { + row.setPosition(index); + index++; + } + }); + } + + setActiveRows(activeRows) { + this.activeRows = this.activeRows = Object.assign([], activeRows); + this.activeRowsCount = this.activeRows.length; + } + + //reset display rows array + resetDisplayRows() { + this.displayRows = []; + this.displayRows.push(this.activeRows.slice(0)); + this.displayRowsCount = this.displayRows[0].length; + } + + //set display row pipeline data + setDisplayRows(displayRows, index) { + this.displayRows[index] = displayRows; + if (index == this.displayRows.length - 1) { + this.displayRowsCount = this.displayRows[this.displayRows.length - 1].length; + } + } + + getDisplayRows(index) { + if (typeof index == "undefined") { + return this.displayRows.length ? this.displayRows[this.displayRows.length - 1] : []; + } else { + return this.displayRows[index] || []; + } + } + + getVisibleRows(chain, viewable) { + var rows2 = Object.assign([], this.renderer.visibleRows(!viewable)); + if (chain) { + rows2 = this.chain("rows-visible", [viewable], rows2, rows2); + } + return rows2; + } + + //repeat action across display rows + displayRowIterator(callback) { + this.activeRowsPipeline.forEach(callback); + this.displayRows.forEach(callback); + this.displayRowsCount = this.displayRows[this.displayRows.length - 1].length; + } + + //return only actual rows (not group headers etc) + getRows(type) { + var rows2 = []; + switch (type) { + case "active": + rows2 = this.activeRows; + break; + case "display": + rows2 = this.table.rowManager.getDisplayRows(); + break; + case "visible": + rows2 = this.getVisibleRows(false, true); + break; + default: + rows2 = this.chain("rows-retrieve", type, null, this.rows) || this.rows; + } + return rows2; + } + + ///////////////// Table Rendering ///////////////// + //trigger rerender of table in current position + reRenderInPosition(callback) { + if (this.redrawBlock) { + if (callback) { + callback(); + } else { + this.redrawBlockRenderInPosition = true; + } + } else { + this.dispatchExternal("renderStarted"); + this.renderer.rerenderRows(callback); + if (!this.fixedHeight) { + this.adjustTableSize(); + } + this.scrollBarCheck(); + this.dispatchExternal("renderComplete"); + } + } + + scrollBarCheck() { + var scrollbarWidth = 0; + if (this.element.scrollHeight > this.element.clientHeight) { + scrollbarWidth = this.element.offsetWidth - this.element.clientWidth; + } + if (scrollbarWidth !== this.scrollbarWidth) { + this.scrollbarWidth = scrollbarWidth; + this.dispatch("scrollbar-vertical", scrollbarWidth); + } + } + + initializeRenderer() { + var renderClass; + var renderers = { + "virtual": VirtualDomVertical, + "basic": BasicVertical + }; + if (typeof this.table.options.renderVertical === "string") { + renderClass = renderers[this.table.options.renderVertical]; + } else { + renderClass = this.table.options.renderVertical; + } + if (renderClass) { + this.renderMode = this.table.options.renderVertical; + this.renderer = new renderClass(this.table, this.element, this.tableElement); + this.renderer.initialize(); + if ((this.table.element.clientHeight || this.table.options.height) && !(this.table.options.minHeight && this.table.options.maxHeight)) { + this.fixedHeight = true; + } else { + this.fixedHeight = false; + } + } else { + console.error("Unable to find matching renderer:", this.table.options.renderVertical); + } + } + + getRenderMode() { + return this.renderMode; + } + + renderTable() { + this.dispatchExternal("renderStarted"); + this.element.scrollTop = 0; + this._clearTable(); + if (this.displayRowsCount) { + this.renderer.renderRows(); + if (this.firstRender) { + this.firstRender = false; + if (!this.fixedHeight) { + this.adjustTableSize(); + } + this.layoutRefresh(true); + } + } else { + this.renderEmptyScroll(); + } + if (!this.fixedHeight) { + this.adjustTableSize(); + } + this.dispatch("table-layout"); + if (!this.displayRowsCount) { + this._showPlaceholder(); + } + this.scrollBarCheck(); + this.dispatchExternal("renderComplete"); + } + + //show scrollbars on empty table div + renderEmptyScroll() { + if (this.placeholder) { + this.tableElement.style.display = "none"; + } else { + this.tableElement.style.minWidth = this.table.columnManager.getWidth() + "px"; + } + } + + _clearTable() { + this._clearPlaceholder(); + this.scrollTop = 0; + this.scrollLeft = 0; + this.renderer.clearRows(); + } + + tableEmpty() { + this.renderEmptyScroll(); + this._showPlaceholder(); + } + + checkPlaceholder() { + if (this.displayRowsCount) { + this._clearPlaceholder(); + } else { + this.tableEmpty(); + } + } + + _showPlaceholder() { + if (this.placeholder) { + if (this.placeholder && this.placeholder.parentNode) { + this.placeholder.parentNode.removeChild(this.placeholder); + } + this.initializePlaceholder(); + this.placeholder.setAttribute("tabulator-render-mode", this.renderMode); + this.getElement().appendChild(this.placeholder); + this._positionPlaceholder(); + this.adjustTableSize(); + } + } + + _clearPlaceholder() { + if (this.placeholder && this.placeholder.parentNode) { + this.placeholder.parentNode.removeChild(this.placeholder); + } + this.tableElement.style.minWidth = ""; + this.tableElement.style.display = ""; + } + + _positionPlaceholder() { + if (this.placeholder && this.placeholder.parentNode) { + this.placeholder.style.width = this.table.columnManager.getWidth() + "px"; + this.placeholderContents.style.width = this.table.rowManager.element.clientWidth + "px"; + this.placeholderContents.style.marginLeft = this.scrollLeft + "px"; + } + } + + styleRow(row, index) { + var rowEl = row.getElement(); + if (index % 2) { + rowEl.classList.add("tabulator-row-even"); + rowEl.classList.remove("tabulator-row-odd"); + } else { + rowEl.classList.add("tabulator-row-odd"); + rowEl.classList.remove("tabulator-row-even"); + } + } + + //normalize height of active rows + normalizeHeight(force) { + this.activeRows.forEach(function (row) { + row.normalizeHeight(force); + }); + } + + //adjust the height of the table holder to fit in the Tabulator element + adjustTableSize() { + let initialHeight = this.element.clientHeight, minHeight; + let resized = false; + if (this.renderer.verticalFillMode === "fill") { + let otherHeight = Math.floor(this.table.columnManager.getElement().getBoundingClientRect().height + (this.table.footerManager && this.table.footerManager.active && !this.table.footerManager.external ? this.table.footerManager.getElement().getBoundingClientRect().height : 0)); + if (this.fixedHeight) { + minHeight = isNaN(this.table.options.minHeight) ? this.table.options.minHeight : this.table.options.minHeight + "px"; + const height = "calc(100% - " + otherHeight + "px)"; + this.element.style.minHeight = minHeight || "calc(100% - " + otherHeight + "px)"; + this.element.style.height = height; + this.element.style.maxHeight = height; + } else { + this.element.style.height = ""; + this.element.style.height = this.table.element.clientHeight - otherHeight + "px"; + this.element.scrollTop = this.scrollTop; + } + this.renderer.resize(); + if (!this.fixedHeight && initialHeight != this.element.clientHeight) { + resized = true; + if (!this.redrawing) { + this.redrawing = true; + if (this.subscribed("table-resize")) { + this.dispatch("table-resize"); + } else { + this.redraw(); + } + this.redrawing = false; + } + } + this.scrollBarCheck(); + } + this._positionPlaceholder(); + return resized; + } + + //reinitialize all rows + reinitialize() { + this.rows.forEach(function (row) { + row.reinitialize(true); + }); + } + + //prevent table from being redrawn + blockRedraw() { + this.redrawBlock = true; + this.redrawBlockRestoreConfig = false; + } + + //restore table redrawing + restoreRedraw() { + this.redrawBlock = false; + if (this.redrawBlockRestoreConfig) { + this.refreshActiveData(this.redrawBlockRestoreConfig.handler, this.redrawBlockRestoreConfig.skipStage, this.redrawBlockRestoreConfig.renderInPosition); + this.redrawBlockRestoreConfig = false; + } else { + if (this.redrawBlockRenderInPosition) { + this.reRenderInPosition(); + } + } + this.redrawBlockRenderInPosition = false; + } + + //redraw table + redraw(force) { + this.adjustTableSize(); + this.table.tableWidth = this.table.element.clientWidth; + if (!force) { + this.reRenderInPosition(); + this.scrollHorizontal(this.scrollLeft); + } else { + this.renderTable(); + } + } + + resetScroll() { + this.element.scrollLeft = 0; + this.element.scrollTop = 0; + if (this.table.browser === "ie") { + var event = document.createEvent("Event"); + event.initEvent("scroll", false, true); + this.element.dispatchEvent(event); + } else { + this.element.dispatchEvent(new Event("scroll")); + } + } + } + + class FooterManager extends CoreFeature { + constructor(table) { + super(table); + this.active = false; + this.element = this.createElement(); + this.containerElement = this.createContainerElement(); + this.external = false; + } + + initialize() { + this.initializeElement(); + } + + createElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-footer"); + return el; + } + + createContainerElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-footer-contents"); + this.element.appendChild(el); + return el; + } + + initializeElement() { + if (this.table.options.footerElement) { + switch (typeof this.table.options.footerElement) { + case "string": + if (this.table.options.footerElement[0] === "<") { + this.containerElement.innerHTML = this.table.options.footerElement; + } else { + this.external = true; + this.containerElement = document.querySelector(this.table.options.footerElement); + } + break; + default: + this.element = this.table.options.footerElement; + break; + } + } + } + + getElement() { + return this.element; + } + + append(element) { + this.activate(); + this.containerElement.appendChild(element); + this.table.rowManager.adjustTableSize(); + } + + prepend(element) { + this.activate(); + this.element.insertBefore(element, this.element.firstChild); + this.table.rowManager.adjustTableSize(); + } + + remove(element) { + element.parentNode.removeChild(element); + this.deactivate(); + } + + deactivate(force) { + if (!this.element.firstChild || force) { + if (!this.external) { + this.element.parentNode.removeChild(this.element); + } + this.active = false; + } + } + + activate() { + if (!this.active) { + this.active = true; + if (!this.external) { + this.table.element.appendChild(this.getElement()); + this.table.element.style.display = ""; + } + } + } + + redraw() { + this.dispatch("footer-redraw"); + } + } + + class InteractionManager extends CoreFeature { + constructor(table) { + super(table); + this.el = null; + this.abortClasses = ["tabulator-headers", "tabulator-table"]; + this.previousTargets = {}; + this.listeners = [ + "click", + "dblclick", + "contextmenu", + "mouseenter", + "mouseleave", + "mouseover", + "mouseout", + "mousemove", + "mouseup", + "mousedown", + "touchstart", + "touchend" + ]; + this.componentMap = { + "tabulator-cell": "cell", + "tabulator-row": "row", + "tabulator-group": "group", + "tabulator-col": "column" + }; + this.pseudoTrackers = { + "row": { + subscriber: null, + target: null + }, + "cell": { + subscriber: null, + target: null + }, + "group": { + subscriber: null, + target: null + }, + "column": { + subscriber: null, + target: null + } + }; + this.pseudoTracking = false; + } + + initialize() { + this.el = this.table.element; + this.buildListenerMap(); + this.bindSubscriptionWatchers(); + } + + buildListenerMap() { + var listenerMap = {}; + this.listeners.forEach((listener) => { + listenerMap[listener] = { + handler: null, + components: [] + }; + }); + this.listeners = listenerMap; + } + + bindPseudoEvents() { + Object.keys(this.pseudoTrackers).forEach((key) => { + this.pseudoTrackers[key].subscriber = this.pseudoMouseEnter.bind(this, key); + this.subscribe(key + "-mouseover", this.pseudoTrackers[key].subscriber); + }); + this.pseudoTracking = true; + } + + pseudoMouseEnter(key, e, target) { + if (this.pseudoTrackers[key].target !== target) { + if (this.pseudoTrackers[key].target) { + this.dispatch(key + "-mouseleave", e, this.pseudoTrackers[key].target); + } + this.pseudoMouseLeave(key, e); + this.pseudoTrackers[key].target = target; + this.dispatch(key + "-mouseenter", e, target); + } + } + + pseudoMouseLeave(key, e) { + var leaveList = Object.keys(this.pseudoTrackers), linkedKeys = { + "row": ["cell"], + "cell": ["row"] + }; + leaveList = leaveList.filter((item) => { + var links = linkedKeys[key]; + return item !== key && (!links || links && !links.includes(item)); + }); + leaveList.forEach((key2) => { + var target = this.pseudoTrackers[key2].target; + if (this.pseudoTrackers[key2].target) { + this.dispatch(key2 + "-mouseleave", e, target); + this.pseudoTrackers[key2].target = null; + } + }); + } + + bindSubscriptionWatchers() { + var listeners = Object.keys(this.listeners), components = Object.values(this.componentMap); + for (let comp of components) { + for (let listener of listeners) { + let key = comp + "-" + listener; + this.subscriptionChange(key, this.subscriptionChanged.bind(this, comp, listener)); + } + } + this.subscribe("table-destroy", this.clearWatchers.bind(this)); + } + + subscriptionChanged(component, key, added) { + var listener = this.listeners[key].components, index = listener.indexOf(component), changed = false; + if (added) { + if (index === -1) { + listener.push(component); + changed = true; + } + } else { + if (!this.subscribed(component + "-" + key)) { + if (index > -1) { + listener.splice(index, 1); + changed = true; + } + } + } + if ((key === "mouseenter" || key === "mouseleave") && !this.pseudoTracking) { + this.bindPseudoEvents(); + } + if (changed) { + this.updateEventListeners(); + } + } + + updateEventListeners() { + for (let key in this.listeners) { + let listener = this.listeners[key]; + if (listener.components.length) { + if (!listener.handler) { + listener.handler = this.track.bind(this, key); + this.el.addEventListener(key, listener.handler); + } + } else { + if (listener.handler) { + this.el.removeEventListener(key, listener.handler); + listener.handler = null; + } + } + } + } + + track(type, e) { + var path = e.composedPath && e.composedPath() || e.path; + var targets = this.findTargets(path); + targets = this.bindComponents(type, targets); + this.triggerEvents(type, e, targets); + if (this.pseudoTracking && (type == "mouseover" || type == "mouseleave") && !Object.keys(targets).length) { + this.pseudoMouseLeave("none", e); + } + } + + findTargets(path) { + var targets = {}; + let componentMap = Object.keys(this.componentMap); + for (let el of path) { + let classList = el.classList ? [...el.classList] : []; + let abort = classList.filter((item) => { + return this.abortClasses.includes(item); + }); + if (abort.length) { + break; + } + let elTargets = classList.filter((item) => { + return componentMap.includes(item); + }); + for (let target of elTargets) { + if (!targets[this.componentMap[target]]) { + targets[this.componentMap[target]] = el; + } + } + } + if (targets.group && targets.group === targets.row) { + delete targets.row; + } + return targets; + } + + bindComponents(type, targets) { + var keys = Object.keys(targets).reverse(), listener = this.listeners[type], matches = {}, output = {}, + targetMatches = {}; + for (let key of keys) { + let component, target = targets[key], previousTarget = this.previousTargets[key]; + if (previousTarget && previousTarget.target === target) { + component = previousTarget.component; + } else { + switch (key) { + case "row": + case "group": + if (listener.components.includes("row") || listener.components.includes("cell") || listener.components.includes("group")) { + let rows2 = this.table.rowManager.getVisibleRows(true); + component = rows2.find((row) => { + return row.getElement() === target; + }); + if (targets["row"] && targets["row"].parentNode && targets["row"].parentNode.closest(".tabulator-row")) { + targets[key] = false; + } + } + break; + case "column": + if (listener.components.includes("column")) { + component = this.table.columnManager.findColumn(target); + } + break; + case "cell": + if (listener.components.includes("cell")) { + if (matches["row"] instanceof Row) { + component = matches["row"].findCell(target); + } else { + if (targets["row"]) { + console.warn("Event Target Lookup Error - The row this cell is attached to cannot be found, has the table been reinitialized without being destroyed first?"); + } + } + } + break; + } + } + if (component) { + matches[key] = component; + targetMatches[key] = { + target, + component + }; + } + } + this.previousTargets = targetMatches; + Object.keys(targets).forEach((key) => { + let value = matches[key]; + output[key] = value; + }); + return output; + } + + triggerEvents(type, e, targets) { + var listener = this.listeners[type]; + for (let key in targets) { + if (targets[key] && listener.components.includes(key)) { + this.dispatch(key + "-" + type, e, targets[key]); + } + } + } + + clearWatchers() { + for (let key in this.listeners) { + let listener = this.listeners[key]; + if (listener.handler) { + this.el.removeEventListener(key, listener.handler); + listener.handler = null; + } + } + } + } + + class ComponentFunctionBinder { + constructor(table) { + this.table = table; + this.bindings = {}; + } + + bind(type, funcName, handler) { + if (!this.bindings[type]) { + this.bindings[type] = {}; + } + if (this.bindings[type][funcName]) { + console.warn("Unable to bind component handler, a matching function name is already bound", type, funcName, handler); + } else { + this.bindings[type][funcName] = handler; + } + } + + handle(type, component, name2) { + if (this.bindings[type] && this.bindings[type][name2] && typeof this.bindings[type][name2].bind === "function") { + return this.bindings[type][name2].bind(null, component); + } else { + if (name2 !== "then" && typeof name2 === "string" && !name2.startsWith("_")) { + if (this.table.options.debugInvalidComponentFuncs) { + console.error("The " + type + " component does not have a " + name2 + " function, have you checked that you have the correct Tabulator module installed?"); + } + } + } + } + } + + class DataLoader extends CoreFeature { + constructor(table) { + super(table); + this.requestOrder = 0; + this.loading = false; + } + + initialize() { + } + + load(data, params, config, replace, silent, columnsChanged) { + var requestNo = ++this.requestOrder; + if (this.table.destroyed) { + return Promise.resolve(); + } + this.dispatchExternal("dataLoading", data); + if (data && (data.indexOf("{") == 0 || data.indexOf("[") == 0)) { + data = JSON.parse(data); + } + if (this.confirm("data-loading", [data, params, config, silent])) { + this.loading = true; + if (!silent) { + this.alertLoader(); + } + params = this.chain("data-params", [data, config, silent], params || {}, params || {}); + params = this.mapParams(params, this.table.options.dataSendParams); + var result = this.chain("data-load", [data, params, config, silent], false, Promise.resolve([])); + return result.then((response) => { + if (!this.table.destroyed) { + if (!Array.isArray(response) && typeof response == "object") { + response = this.mapParams(response, this.objectInvert(this.table.options.dataReceiveParams)); + } + var rowData = this.chain("data-loaded", [response], null, response); + if (requestNo == this.requestOrder) { + this.clearAlert(); + if (rowData !== false) { + this.dispatchExternal("dataLoaded", rowData); + this.table.rowManager.setData(rowData, replace, typeof columnsChanged === "undefined" ? !replace : columnsChanged); + } + } else { + console.warn("Data Load Response Blocked - An active data load request was blocked by an attempt to change table data while the request was being made"); + } + } else { + console.warn("Data Load Response Blocked - Table has been destroyed"); + } + }).catch((error) => { + console.error("Data Load Error: ", error); + this.dispatchExternal("dataLoadError", error); + if (!silent) { + this.alertError(); + } + setTimeout(() => { + this.clearAlert(); + }, this.table.options.dataLoaderErrorTimeout); + }).finally(() => { + this.loading = false; + }); + } else { + this.dispatchExternal("dataLoaded", data); + if (!data) { + data = []; + } + this.table.rowManager.setData(data, replace, typeof columnsChanged === "undefined" ? !replace : columnsChanged); + return Promise.resolve(); + } + } + + mapParams(params, map) { + var output = {}; + for (let key in params) { + output[map.hasOwnProperty(key) ? map[key] : key] = params[key]; + } + return output; + } + + objectInvert(obj) { + var output = {}; + for (let key in obj) { + output[obj[key]] = key; + } + return output; + } + + blockActiveLoad() { + this.requestOrder++; + } + + alertLoader() { + var shouldLoad = typeof this.table.options.dataLoader === "function" ? this.table.options.dataLoader() : this.table.options.dataLoader; + if (shouldLoad) { + this.table.alertManager.alert(this.table.options.dataLoaderLoading || this.langText("data|loading")); + } + } + + alertError() { + this.table.alertManager.alert(this.table.options.dataLoaderError || this.langText("data|error"), "error"); + } + + clearAlert() { + this.table.alertManager.clear(); + } + } + + class ExternalEventBus { + constructor(table, optionsList, debug) { + this.table = table; + this.events = {}; + this.optionsList = optionsList || {}; + this.subscriptionNotifiers = {}; + this.dispatch = debug ? this._debugDispatch.bind(this) : this._dispatch.bind(this); + this.debug = debug; + } + + subscriptionChange(key, callback) { + if (!this.subscriptionNotifiers[key]) { + this.subscriptionNotifiers[key] = []; + } + this.subscriptionNotifiers[key].push(callback); + if (this.subscribed(key)) { + this._notifySubscriptionChange(key, true); + } + } + + subscribe(key, callback) { + if (!this.events[key]) { + this.events[key] = []; + } + this.events[key].push(callback); + this._notifySubscriptionChange(key, true); + } + + unsubscribe(key, callback) { + var index; + if (this.events[key]) { + if (callback) { + index = this.events[key].findIndex((item) => { + return item === callback; + }); + if (index > -1) { + this.events[key].splice(index, 1); + } else { + console.warn("Cannot remove event, no matching event found:", key, callback); + return; + } + } else { + delete this.events[key]; + } + } else { + console.warn("Cannot remove event, no events set on:", key); + return; + } + this._notifySubscriptionChange(key, false); + } + + subscribed(key) { + return this.events[key] && this.events[key].length; + } + + _notifySubscriptionChange(key, subscribed) { + var notifiers = this.subscriptionNotifiers[key]; + if (notifiers) { + notifiers.forEach((callback) => { + callback(subscribed); + }); + } + } + + _dispatch() { + var args = Array.from(arguments), key = args.shift(), result; + if (this.events[key]) { + this.events[key].forEach((callback, i) => { + let callResult = callback.apply(this.table, args); + if (!i) { + result = callResult; + } + }); + } + return result; + } + + _debugDispatch() { + var args = Array.from(arguments), key = args[0]; + args[0] = "ExternalEvent:" + args[0]; + if (this.debug === true || this.debug.includes(key)) { + console.log(...args); + } + return this._dispatch(...arguments); + } + } + + class InternalEventBus { + constructor(debug) { + this.events = {}; + this.subscriptionNotifiers = {}; + this.dispatch = debug ? this._debugDispatch.bind(this) : this._dispatch.bind(this); + this.chain = debug ? this._debugChain.bind(this) : this._chain.bind(this); + this.confirm = debug ? this._debugConfirm.bind(this) : this._confirm.bind(this); + this.debug = debug; + } + + subscriptionChange(key, callback) { + if (!this.subscriptionNotifiers[key]) { + this.subscriptionNotifiers[key] = []; + } + this.subscriptionNotifiers[key].push(callback); + if (this.subscribed(key)) { + this._notifySubscriptionChange(key, true); + } + } + + subscribe(key, callback, priority = 1e4) { + if (!this.events[key]) { + this.events[key] = []; + } + this.events[key].push({callback, priority}); + this.events[key].sort((a, b) => { + return a.priority - b.priority; + }); + this._notifySubscriptionChange(key, true); + } + + unsubscribe(key, callback) { + var index; + if (this.events[key]) { + if (callback) { + index = this.events[key].findIndex((item) => { + return item.callback === callback; + }); + if (index > -1) { + this.events[key].splice(index, 1); + } else { + console.warn("Cannot remove event, no matching event found:", key, callback); + return; + } + } + } else { + console.warn("Cannot remove event, no events set on:", key); + return; + } + this._notifySubscriptionChange(key, false); + } + + subscribed(key) { + return this.events[key] && this.events[key].length; + } + + _chain(key, args, initialValue, fallback) { + var value = initialValue; + if (!Array.isArray(args)) { + args = [args]; + } + if (this.subscribed(key)) { + this.events[key].forEach((subscriber, i) => { + value = subscriber.callback.apply(this, args.concat([value])); + }); + return value; + } else { + return typeof fallback === "function" ? fallback() : fallback; + } + } + + _confirm(key, args) { + var confirmed = false; + if (!Array.isArray(args)) { + args = [args]; + } + if (this.subscribed(key)) { + this.events[key].forEach((subscriber, i) => { + if (subscriber.callback.apply(this, args)) { + confirmed = true; + } + }); + } + return confirmed; + } + + _notifySubscriptionChange(key, subscribed) { + var notifiers = this.subscriptionNotifiers[key]; + if (notifiers) { + notifiers.forEach((callback) => { + callback(subscribed); + }); + } + } + + _dispatch() { + var args = Array.from(arguments), key = args.shift(); + if (this.events[key]) { + this.events[key].forEach((subscriber) => { + subscriber.callback.apply(this, args); + }); + } + } + + _debugDispatch() { + var args = Array.from(arguments), key = args[0]; + args[0] = "InternalEvent:" + key; + if (this.debug === true || this.debug.includes(key)) { + console.log(...args); + } + return this._dispatch(...arguments); + } + + _debugChain() { + var args = Array.from(arguments), key = args[0]; + args[0] = "InternalEvent:" + key; + if (this.debug === true || this.debug.includes(key)) { + console.log(...args); + } + return this._chain(...arguments); + } + + _debugConfirm() { + var args = Array.from(arguments), key = args[0]; + args[0] = "InternalEvent:" + key; + if (this.debug === true || this.debug.includes(key)) { + console.log(...args); + } + return this._confirm(...arguments); + } + } + + class DeprecationAdvisor extends CoreFeature { + constructor(table) { + super(table); + } + + _warnUser() { + if (this.options("debugDeprecation")) { + console.warn(...arguments); + } + } + + check(oldOption, newOption, convert) { + var msg = ""; + if (typeof this.options(oldOption) !== "undefined") { + msg = "Deprecated Setup Option - Use of the %c" + oldOption + "%c option is now deprecated"; + if (newOption) { + msg = msg + ", Please use the %c" + newOption + "%c option instead"; + this._warnUser(msg, "font-weight: bold;", "font-weight: normal;", "font-weight: bold;", "font-weight: normal;"); + if (convert) { + this.table.options[newOption] = this.table.options[oldOption]; + } + } else { + this._warnUser(msg, "font-weight: bold;", "font-weight: normal;"); + } + return false; + } else { + return true; + } + } + + checkMsg(oldOption, msg) { + if (typeof this.options(oldOption) !== "undefined") { + this._warnUser("%cDeprecated Setup Option - Use of the %c" + oldOption + " %c option is now deprecated, " + msg, "font-weight: normal;", "font-weight: bold;", "font-weight: normal;"); + return false; + } else { + return true; + } + } + + msg(msg) { + this._warnUser(msg); + } + } + + class DependencyRegistry extends CoreFeature { + constructor(table) { + super(table); + this.deps = {}; + this.props = {}; + } + + initialize() { + this.deps = Object.assign({}, this.options("dependencies")); + } + + lookup(key, prop, silent) { + if (Array.isArray(key)) { + for (const item of key) { + var match = this.lookup(item, prop, true); + if (match) { + break; + } + } + if (match) { + return match; + } else { + this.error(key); + } + } else { + if (prop) { + return this.lookupProp(key, prop, silent); + } else { + return this.lookupKey(key, silent); + } + } + } + + lookupProp(key, prop, silent) { + var dependency; + if (this.props[key] && this.props[key][prop]) { + return this.props[key][prop]; + } else { + dependency = this.lookupKey(key, silent); + if (dependency) { + if (!this.props[key]) { + this.props[key] = {}; + } + this.props[key][prop] = dependency[prop] || dependency; + return this.props[key][prop]; + } + } + } + + lookupKey(key, silent) { + var dependency; + if (this.deps[key]) { + dependency = this.deps[key]; + } else if (window[key]) { + this.deps[key] = window[key]; + dependency = this.deps[key]; + } else { + if (!silent) { + this.error(key); + } + } + return dependency; + } + + error(key) { + console.error("Unable to find dependency", key, "Please check documentation and ensure you have imported the required library into your project"); + } + } + + function fitData(columns, forced) { + if (forced) { + this.table.columnManager.renderer.reinitializeColumnWidths(columns); + } + if (this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { + this.table.modules.responsiveLayout.update(); + } + } + + function fitDataGeneral(columns, forced) { + columns.forEach(function (column) { + column.reinitializeWidth(); + }); + if (this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { + this.table.modules.responsiveLayout.update(); + } + } + + function fitDataStretch(columns, forced) { + var colsWidth = 0, tableWidth = this.table.rowManager.element.clientWidth, gap = 0, lastCol = false; + columns.forEach((column, i) => { + if (!column.widthFixed) { + column.reinitializeWidth(); + } + if (this.table.options.responsiveLayout ? column.modules.responsive.visible : column.visible) { + lastCol = column; + } + if (column.visible) { + colsWidth += column.getWidth(); + } + }); + if (lastCol) { + gap = tableWidth - colsWidth + lastCol.getWidth(); + if (this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { + lastCol.setWidth(0); + this.table.modules.responsiveLayout.update(); + } + if (gap > 0) { + lastCol.setWidth(gap); + } else { + lastCol.reinitializeWidth(); + } + } else { + if (this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { + this.table.modules.responsiveLayout.update(); + } + } + } + + function fitColumns(columns, forced) { + var totalWidth = this.table.rowManager.element.getBoundingClientRect().width; + var fixedWidth = 0; + var flexWidth = 0; + var flexGrowUnits = 0; + var flexColWidth = 0; + var flexColumns = []; + var fixedShrinkColumns = []; + var flexShrinkUnits = 0; + var overflowWidth = 0; + var gapFill = 0; + + function calcWidth(width) { + var colWidth; + if (typeof width == "string") { + if (width.indexOf("%") > -1) { + colWidth = totalWidth / 100 * parseInt(width); + } else { + colWidth = parseInt(width); + } + } else { + colWidth = width; + } + return colWidth; + } + + function scaleColumns(columns2, freeSpace, colWidth, shrinkCols) { + var oversizeCols = [], oversizeSpace = 0, remainingSpace = 0, nextColWidth = 0, + remainingFlexGrowUnits = flexGrowUnits, gap = 0, changeUnits = 0, undersizeCols = []; + + function calcGrow(col) { + return colWidth * (col.column.definition.widthGrow || 1); + } + + function calcShrink(col) { + return calcWidth(col.width) - colWidth * (col.column.definition.widthShrink || 0); + } + + columns2.forEach(function (col, i) { + var width = shrinkCols ? calcShrink(col) : calcGrow(col); + if (col.column.minWidth >= width) { + oversizeCols.push(col); + } else { + if (col.column.maxWidth && col.column.maxWidth < width) { + col.width = col.column.maxWidth; + freeSpace -= col.column.maxWidth; + remainingFlexGrowUnits -= shrinkCols ? col.column.definition.widthShrink || 1 : col.column.definition.widthGrow || 1; + if (remainingFlexGrowUnits) { + colWidth = Math.floor(freeSpace / remainingFlexGrowUnits); + } + } else { + undersizeCols.push(col); + changeUnits += shrinkCols ? col.column.definition.widthShrink || 1 : col.column.definition.widthGrow || 1; + } + } + }); + if (oversizeCols.length) { + oversizeCols.forEach(function (col) { + oversizeSpace += shrinkCols ? col.width - col.column.minWidth : col.column.minWidth; + col.width = col.column.minWidth; + }); + remainingSpace = freeSpace - oversizeSpace; + nextColWidth = changeUnits ? Math.floor(remainingSpace / changeUnits) : remainingSpace; + gap = scaleColumns(undersizeCols, remainingSpace, nextColWidth, shrinkCols); + } else { + gap = changeUnits ? freeSpace - Math.floor(freeSpace / changeUnits) * changeUnits : freeSpace; + undersizeCols.forEach(function (column) { + column.width = shrinkCols ? calcShrink(column) : calcGrow(column); + }); + } + return gap; + } + + if (this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { + this.table.modules.responsiveLayout.update(); + } + if (this.table.rowManager.element.scrollHeight > this.table.rowManager.element.clientHeight) { + totalWidth -= this.table.rowManager.element.offsetWidth - this.table.rowManager.element.clientWidth; + } + columns.forEach(function (column) { + var width, minWidth, colWidth; + if (column.visible) { + width = column.definition.width; + minWidth = parseInt(column.minWidth); + if (width) { + colWidth = calcWidth(width); + fixedWidth += colWidth > minWidth ? colWidth : minWidth; + if (column.definition.widthShrink) { + fixedShrinkColumns.push({ + column, + width: colWidth > minWidth ? colWidth : minWidth + }); + flexShrinkUnits += column.definition.widthShrink; + } + } else { + flexColumns.push({ + column, + width: 0 + }); + flexGrowUnits += column.definition.widthGrow || 1; + } + } + }); + flexWidth = totalWidth - fixedWidth; + flexColWidth = Math.floor(flexWidth / flexGrowUnits); + gapFill = scaleColumns(flexColumns, flexWidth, flexColWidth, false); + if (flexColumns.length && gapFill > 0) { + flexColumns[flexColumns.length - 1].width += gapFill; + } + flexColumns.forEach(function (col) { + flexWidth -= col.width; + }); + overflowWidth = Math.abs(gapFill) + flexWidth; + if (overflowWidth > 0 && flexShrinkUnits) { + gapFill = scaleColumns(fixedShrinkColumns, overflowWidth, Math.floor(overflowWidth / flexShrinkUnits), true); + } + if (gapFill && fixedShrinkColumns.length) { + fixedShrinkColumns[fixedShrinkColumns.length - 1].width -= gapFill; + } + flexColumns.forEach(function (col) { + col.column.setWidth(col.width); + }); + fixedShrinkColumns.forEach(function (col) { + col.column.setWidth(col.width); + }); + } + + var defaultModes = { + fitData, + fitDataFill: fitDataGeneral, + fitDataTable: fitDataGeneral, + fitDataStretch, + fitColumns + }; + const _Layout = class _Layout extends Module { + constructor(table) { + super(table, "layout"); + this.mode = null; + this.registerTableOption("layout", "fitData"); + this.registerTableOption("layoutColumnsOnNewData", false); + this.registerColumnOption("widthGrow"); + this.registerColumnOption("widthShrink"); + } + + //initialize layout system + initialize() { + var layout = this.table.options.layout; + if (_Layout.modes[layout]) { + this.mode = layout; + } else { + console.warn("Layout Error - invalid mode set, defaulting to 'fitData' : " + layout); + this.mode = "fitData"; + } + this.table.element.setAttribute("tabulator-layout", this.mode); + this.subscribe("column-init", this.initializeColumn.bind(this)); + } + + initializeColumn(column) { + if (column.definition.widthGrow) { + column.definition.widthGrow = Number(column.definition.widthGrow); + } + if (column.definition.widthShrink) { + column.definition.widthShrink = Number(column.definition.widthShrink); + } + } + + getMode() { + return this.mode; + } + + //trigger table layout + layout(dataChanged) { + var variableHeight = this.table.columnManager.columnsByIndex.find((column) => column.definition.variableHeight || column.definition.formatter === "textarea"); + this.dispatch("layout-refreshing"); + _Layout.modes[this.mode].call(this, this.table.columnManager.columnsByIndex, dataChanged); + if (variableHeight) { + this.table.rowManager.normalizeHeight(true); + } + this.dispatch("layout-refreshed"); + } + }; + __publicField(_Layout, "moduleName", "layout"); + //load defaults + __publicField(_Layout, "modes", defaultModes); + let Layout = _Layout; + var defaultLangs = { + "default": { + //hold default locale text + "groups": { + "item": "item", + "items": "items" + }, + "columns": {}, + "data": { + "loading": "Loading", + "error": "Error" + }, + "pagination": { + "page_size": "Page Size", + "page_title": "Show Page", + "first": "First", + "first_title": "First Page", + "last": "Last", + "last_title": "Last Page", + "prev": "Prev", + "prev_title": "Prev Page", + "next": "Next", + "next_title": "Next Page", + "all": "All", + "counter": { + "showing": "Showing", + "of": "of", + "rows": "rows", + "pages": "pages" + } + }, + "headerFilters": { + "default": "filter column...", + "columns": {} + } + } + }; + const _Localize = class _Localize extends Module { + constructor(table) { + super(table); + this.locale = "default"; + this.lang = false; + this.bindings = {}; + this.langList = {}; + this.registerTableOption("locale", false); + this.registerTableOption("langs", {}); + } + + initialize() { + this.langList = Helpers.deepClone(_Localize.langs); + if (this.table.options.columnDefaults.headerFilterPlaceholder !== false) { + this.setHeaderFilterPlaceholder(this.table.options.columnDefaults.headerFilterPlaceholder); + } + for (let locale in this.table.options.langs) { + this.installLang(locale, this.table.options.langs[locale]); + } + this.setLocale(this.table.options.locale); + this.registerTableFunction("setLocale", this.setLocale.bind(this)); + this.registerTableFunction("getLocale", this.getLocale.bind(this)); + this.registerTableFunction("getLang", this.getLang.bind(this)); + } + + //set header placeholder + setHeaderFilterPlaceholder(placeholder) { + this.langList.default.headerFilters.default = placeholder; + } + + //setup a lang description object + installLang(locale, lang) { + if (this.langList[locale]) { + this._setLangProp(this.langList[locale], lang); + } else { + this.langList[locale] = lang; + } + } + + _setLangProp(lang, values) { + for (let key in values) { + if (lang[key] && typeof lang[key] == "object") { + this._setLangProp(lang[key], values[key]); + } else { + lang[key] = values[key]; + } + } + } + + //set current locale + setLocale(desiredLocale) { + desiredLocale = desiredLocale || "default"; + + function traverseLang(trans, path) { + for (var prop in trans) { + if (typeof trans[prop] == "object") { + if (!path[prop]) { + path[prop] = {}; + } + traverseLang(trans[prop], path[prop]); + } else { + path[prop] = trans[prop]; + } + } + } + + if (desiredLocale === true && navigator.language) { + desiredLocale = navigator.language.toLowerCase(); + } + if (desiredLocale) { + if (!this.langList[desiredLocale]) { + let prefix = desiredLocale.split("-")[0]; + if (this.langList[prefix]) { + console.warn("Localization Error - Exact matching locale not found, using closest match: ", desiredLocale, prefix); + desiredLocale = prefix; + } else { + console.warn("Localization Error - Matching locale not found, using default: ", desiredLocale); + desiredLocale = "default"; + } + } + } + this.locale = desiredLocale; + this.lang = Helpers.deepClone(this.langList.default || {}); + if (desiredLocale != "default") { + traverseLang(this.langList[desiredLocale], this.lang); + } + this.dispatchExternal("localized", this.locale, this.lang); + this._executeBindings(); + } + + //get current locale + getLocale(locale) { + return this.locale; + } + + //get lang object for given local or current if none provided + getLang(locale) { + return locale ? this.langList[locale] : this.lang; + } + + //get text for current locale + getText(path, value) { + var fillPath = value ? path + "|" + value : path, pathArray = fillPath.split("|"), + text = this._getLangElement(pathArray, this.locale); + return text || ""; + } + + //traverse langs object and find localized copy + _getLangElement(path, locale) { + var root = this.lang; + path.forEach(function (level) { + var rootPath; + if (root) { + rootPath = root[level]; + if (typeof rootPath != "undefined") { + root = rootPath; + } else { + root = false; + } + } + }); + return root; + } + + //set update binding + bind(path, callback) { + if (!this.bindings[path]) { + this.bindings[path] = []; + } + this.bindings[path].push(callback); + callback(this.getText(path), this.lang); + } + + //iterate through bindings and trigger updates + _executeBindings() { + for (let path in this.bindings) { + this.bindings[path].forEach((binding) => { + binding(this.getText(path), this.lang); + }); + } + } + }; + __publicField(_Localize, "moduleName", "localize"); + //load defaults + __publicField(_Localize, "langs", defaultLangs); + let Localize = _Localize; + + class Comms extends Module { + constructor(table) { + super(table); + } + + initialize() { + this.registerTableFunction("tableComms", this.receive.bind(this)); + } + + getConnections(selectors) { + var connections = [], connection; + connection = this.table.constructor.registry.lookupTable(selectors); + connection.forEach((con) => { + if (this.table !== con) { + connections.push(con); + } + }); + return connections; + } + + send(selectors, module, action, data) { + var connections = this.getConnections(selectors); + connections.forEach((connection) => { + connection.tableComms(this.table.element, module, action, data); + }); + if (!connections.length && selectors) { + console.warn("Table Connection Error - No tables matching selector found", selectors); + } + } + + receive(table, module, action, data) { + if (this.table.modExists(module)) { + return this.table.modules[module].commsReceived(table, action, data); + } else { + console.warn("Inter-table Comms Error - no such module:", module); + } + } + } + + __publicField(Comms, "moduleName", "comms"); + var coreModules = /* @__PURE__ */ Object.freeze({ + __proto__: null, + CommsModule: Comms, + LayoutModule: Layout, + LocalizeModule: Localize + }); + const _TableRegistry = class _TableRegistry { + static findTable(query) { + var results = _TableRegistry.registry.lookupTable(query, true); + return Array.isArray(results) && !results.length ? false : results; + } + }; + __publicField(_TableRegistry, "registry", { + tables: [], + register(table) { + _TableRegistry.registry.tables.push(table); + }, + deregister(table) { + var index = _TableRegistry.registry.tables.indexOf(table); + if (index > -1) { + _TableRegistry.registry.tables.splice(index, 1); + } + }, + lookupTable(query, silent) { + var results = [], matches, match; + if (typeof query === "string") { + matches = document.querySelectorAll(query); + if (matches.length) { + for (var i = 0; i < matches.length; i++) { + match = _TableRegistry.registry.matchElement(matches[i]); + if (match) { + results.push(match); + } + } + } + } else if (typeof HTMLElement !== "undefined" && query instanceof HTMLElement || query instanceof _TableRegistry) { + match = _TableRegistry.registry.matchElement(query); + if (match) { + results.push(match); + } + } else if (Array.isArray(query)) { + query.forEach(function (item) { + results = results.concat(_TableRegistry.registry.lookupTable(item)); + }); + } else { + if (!silent) { + console.warn("Table Connection Error - Invalid Selector", query); + } + } + return results; + }, + matchElement(element) { + return _TableRegistry.registry.tables.find(function (table) { + return element instanceof _TableRegistry ? table === element : table.element === element; + }); + } + }); + let TableRegistry = _TableRegistry; + const _ModuleBinder = class _ModuleBinder extends TableRegistry { + constructor() { + super(); + } + + static initializeModuleBinder(defaultModules) { + if (!_ModuleBinder.modulesRegistered) { + _ModuleBinder.modulesRegistered = true; + _ModuleBinder._registerModules(coreModules, true); + if (defaultModules) { + _ModuleBinder._registerModules(defaultModules); + } + } + } + + static _extendModule(name2, property, values) { + if (_ModuleBinder.moduleBindings[name2]) { + var source = _ModuleBinder.moduleBindings[name2][property]; + if (source) { + if (typeof values == "object") { + for (let key in values) { + source[key] = values[key]; + } + } else { + console.warn("Module Error - Invalid value type, it must be an object"); + } + } else { + console.warn("Module Error - property does not exist:", property); + } + } else { + console.warn("Module Error - module does not exist:", name2); + } + } + + static _registerModules(modules, core) { + var mods = Object.values(modules); + if (core) { + mods.forEach((mod) => { + mod.prototype.moduleCore = true; + }); + } + _ModuleBinder._registerModule(mods); + } + + static _registerModule(modules) { + if (!Array.isArray(modules)) { + modules = [modules]; + } + modules.forEach((mod) => { + _ModuleBinder._registerModuleBinding(mod); + _ModuleBinder._registerModuleExtensions(mod); + }); + } + + static _registerModuleBinding(mod) { + if (mod.moduleName) { + _ModuleBinder.moduleBindings[mod.moduleName] = mod; + } else { + console.error("Unable to bind module, no moduleName defined", mod.moduleName); + } + } + + static _registerModuleExtensions(mod) { + var extensions2 = mod.moduleExtensions; + if (mod.moduleExtensions) { + for (let modKey in extensions2) { + let ext = extensions2[modKey]; + if (_ModuleBinder.moduleBindings[modKey]) { + for (let propKey in ext) { + _ModuleBinder._extendModule(modKey, propKey, ext[propKey]); + } + } else { + if (!_ModuleBinder.moduleExtensions[modKey]) { + _ModuleBinder.moduleExtensions[modKey] = {}; + } + for (let propKey in ext) { + if (!_ModuleBinder.moduleExtensions[modKey][propKey]) { + _ModuleBinder.moduleExtensions[modKey][propKey] = {}; + } + Object.assign(_ModuleBinder.moduleExtensions[modKey][propKey], ext[propKey]); + } + } + } + } + _ModuleBinder._extendModuleFromQueue(mod); + } + + static _extendModuleFromQueue(mod) { + var extensions2 = _ModuleBinder.moduleExtensions[mod.moduleName]; + if (extensions2) { + for (let propKey in extensions2) { + _ModuleBinder._extendModule(mod.moduleName, propKey, extensions2[propKey]); + } + } + } + + //ensure that module are bound to instantiated function + _bindModules() { + var orderedStartMods = [], orderedEndMods = [], unOrderedMods = []; + this.modules = {}; + for (var name2 in _ModuleBinder.moduleBindings) { + let mod = _ModuleBinder.moduleBindings[name2]; + let module = new mod(this); + this.modules[name2] = module; + if (mod.prototype.moduleCore) { + this.modulesCore.push(module); + } else { + if (mod.moduleInitOrder) { + if (mod.moduleInitOrder < 0) { + orderedStartMods.push(module); + } else { + orderedEndMods.push(module); + } + } else { + unOrderedMods.push(module); + } + } + } + orderedStartMods.sort((a, b) => a.moduleInitOrder > b.moduleInitOrder ? 1 : -1); + orderedEndMods.sort((a, b) => a.moduleInitOrder > b.moduleInitOrder ? 1 : -1); + this.modulesRegular = orderedStartMods.concat(unOrderedMods.concat(orderedEndMods)); + } + }; + __publicField(_ModuleBinder, "moduleBindings", {}); + __publicField(_ModuleBinder, "moduleExtensions", {}); + __publicField(_ModuleBinder, "modulesRegistered", false); + __publicField(_ModuleBinder, "defaultModules", false); + let ModuleBinder = _ModuleBinder; + + class Alert extends CoreFeature { + constructor(table) { + super(table); + this.element = this._createAlertElement(); + this.msgElement = this._createMsgElement(); + this.type = null; + this.element.appendChild(this.msgElement); + } + + _createAlertElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-alert"); + return el; + } + + _createMsgElement() { + var el = document.createElement("div"); + el.classList.add("tabulator-alert-msg"); + el.setAttribute("role", "alert"); + return el; + } + + _typeClass() { + return "tabulator-alert-state-" + this.type; + } + + alert(content, type = "msg") { + if (content) { + this.clear(); + this.dispatch("alert-show", type); + this.type = type; + while (this.msgElement.firstChild) this.msgElement.removeChild(this.msgElement.firstChild); + this.msgElement.classList.add(this._typeClass()); + if (typeof content === "function") { + content = content(); + } + if (content instanceof HTMLElement) { + this.msgElement.appendChild(content); + } else { + this.msgElement.innerHTML = content; + } + this.table.element.appendChild(this.element); + } + } + + clear() { + this.dispatch("alert-hide", this.type); + if (this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + this.msgElement.classList.remove(this._typeClass()); + } + } + + let Tabulator$1 = (_a = class extends ModuleBinder { + static extendModule() { + _a.initializeModuleBinder(); + _a._extendModule(...arguments); + } + + static registerModule() { + _a.initializeModuleBinder(); + _a._registerModule(...arguments); + } + + constructor(element, options, modules) { + super(); + _a.initializeModuleBinder(modules); + this.options = {}; + this.columnManager = null; + this.rowManager = null; + this.footerManager = null; + this.alertManager = null; + this.vdomHoz = null; + this.externalEvents = null; + this.eventBus = null; + this.interactionMonitor = false; + this.browser = ""; + this.browserSlow = false; + this.browserMobile = false; + this.rtl = false; + this.originalElement = null; + this.componentFunctionBinder = new ComponentFunctionBinder(this); + this.dataLoader = false; + this.modules = {}; + this.modulesCore = []; + this.modulesRegular = []; + this.deprecationAdvisor = new DeprecationAdvisor(this); + this.optionsList = new OptionsList(this, "table constructor"); + this.dependencyRegistry = new DependencyRegistry(this); + this.initialized = false; + this.destroyed = false; + if (this.initializeElement(element)) { + this.initializeCoreSystems(options); + setTimeout(() => { + this._create(); + }); + } + this.constructor.registry.register(this); + } + + initializeElement(element) { + if (typeof HTMLElement !== "undefined" && element instanceof HTMLElement) { + this.element = element; + return true; + } else if (typeof element === "string") { + this.element = document.querySelector(element); + if (this.element) { + return true; + } else { + console.error("Tabulator Creation Error - no element found matching selector: ", element); + return false; + } + } else { + console.error("Tabulator Creation Error - Invalid element provided:", element); + return false; + } + } + + initializeCoreSystems(options) { + this.columnManager = new ColumnManager(this); + this.rowManager = new RowManager(this); + this.footerManager = new FooterManager(this); + this.dataLoader = new DataLoader(this); + this.alertManager = new Alert(this); + this._bindModules(); + this.options = this.optionsList.generate(_a.defaultOptions, options); + this._clearObjectPointers(); + this._mapDeprecatedFunctionality(); + this.externalEvents = new ExternalEventBus(this, this.options, this.options.debugEventsExternal); + this.eventBus = new InternalEventBus(this.options.debugEventsInternal); + this.interactionMonitor = new InteractionManager(this); + this.dataLoader.initialize(); + this.footerManager.initialize(); + this.dependencyRegistry.initialize(); + } + + //convert deprecated functionality to new functions + _mapDeprecatedFunctionality() { + } + + _clearSelection() { + this.element.classList.add("tabulator-block-select"); + if (window.getSelection) { + if (window.getSelection().empty) { + window.getSelection().empty(); + } else if (window.getSelection().removeAllRanges) { + window.getSelection().removeAllRanges(); + } + } else if (document.selection) { + document.selection.empty(); + } + this.element.classList.remove("tabulator-block-select"); + } + + //create table + _create() { + this.externalEvents.dispatch("tableBuilding"); + this.eventBus.dispatch("table-building"); + this._rtlCheck(); + this._buildElement(); + this._initializeTable(); + this.initialized = true; + this._loadInitialData().finally(() => { + this.eventBus.dispatch("table-initialized"); + this.externalEvents.dispatch("tableBuilt"); + }); + } + + _rtlCheck() { + var style = window.getComputedStyle(this.element); + switch (this.options.textDirection) { + case "auto": + if (style.direction !== "rtl") { + break; + } + case "rtl": + this.element.classList.add("tabulator-rtl"); + this.rtl = true; + break; + case "ltr": + this.element.classList.add("tabulator-ltr"); + default: + this.rtl = false; + } + } + + //clear pointers to objects in default config object + _clearObjectPointers() { + this.options.columns = this.options.columns.slice(0); + if (Array.isArray(this.options.data) && !this.options.reactiveData) { + this.options.data = this.options.data.slice(0); + } + } + + //build tabulator element + _buildElement() { + var element = this.element, options = this.options, newElement; + if (element.tagName === "TABLE") { + this.originalElement = this.element; + newElement = document.createElement("div"); + var attributes = element.attributes; + for (var i in attributes) { + if (typeof attributes[i] == "object") { + newElement.setAttribute(attributes[i].name, attributes[i].value); + } + } + element.parentNode.replaceChild(newElement, element); + this.element = element = newElement; + } + element.classList.add("tabulator"); + element.setAttribute("role", "grid"); + element.setAttribute("aria-owns", "tabulator-table-body"); + while (element.firstChild) element.removeChild(element.firstChild); + if (options.height) { + options.height = isNaN(options.height) ? options.height : options.height + "px"; + element.style.height = options.height; + } + if (options.minHeight !== false) { + options.minHeight = isNaN(options.minHeight) ? options.minHeight : options.minHeight + "px"; + element.style.minHeight = options.minHeight; + } + if (options.maxHeight !== false) { + options.maxHeight = isNaN(options.maxHeight) ? options.maxHeight : options.maxHeight + "px"; + element.style.maxHeight = options.maxHeight; + } + } + + //initialize core systems and modules + _initializeTable() { + var element = this.element, options = this.options; + this.interactionMonitor.initialize(); + this.columnManager.initialize(); + this.rowManager.initialize(); + this._detectBrowser(); + this.modulesCore.forEach((mod) => { + mod.initialize(); + }); + element.appendChild(this.columnManager.getElement()); + element.appendChild(this.rowManager.getElement()); + if (options.footerElement) { + this.footerManager.activate(); + } + if (options.autoColumns && options.data) { + this.columnManager.generateColumnsFromRowData(this.options.data); + } + this.modulesRegular.forEach((mod) => { + mod.initialize(); + }); + this.columnManager.setColumns(options.columns); + this.eventBus.dispatch("table-built"); + } + + _loadInitialData() { + return this.dataLoader.load(this.options.data).finally(() => { + this.columnManager.verticalAlignHeaders(); + }); + } + + //deconstructor + destroy() { + var element = this.element; + this.destroyed = true; + this.constructor.registry.deregister(this); + this.eventBus.dispatch("table-destroy"); + this.rowManager.destroy(); + while (element.firstChild) element.removeChild(element.firstChild); + element.classList.remove("tabulator"); + element.removeAttribute("tabulator-layout"); + this.externalEvents.dispatch("tableDestroyed"); + } + + _detectBrowser() { + var ua = navigator.userAgent || navigator.vendor || window.opera; + if (ua.indexOf("Trident") > -1) { + this.browser = "ie"; + this.browserSlow = true; + } else if (ua.indexOf("Edge") > -1) { + this.browser = "edge"; + this.browserSlow = true; + } else if (ua.indexOf("Firefox") > -1) { + this.browser = "firefox"; + this.browserSlow = false; + } else if (ua.indexOf("Mac OS") > -1) { + this.browser = "safari"; + this.browserSlow = false; + } else { + this.browser = "other"; + this.browserSlow = false; + } + this.browserMobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(ua) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(ua.slice(0, 4)); + } + + initGuard(func, msg) { + var stack, line; + if (this.options.debugInitialization && !this.initialized) { + if (!func) { + stack = new Error().stack.split("\n"); + line = stack[0] == "Error" ? stack[2] : stack[1]; + if (line[0] == " ") { + func = line.trim().split(" ")[1].split(".")[1]; + } else { + func = line.trim().split("@")[0]; + } + } + console.warn("Table Not Initialized - Calling the " + func + " function before the table is initialized may result in inconsistent behavior, Please wait for the `tableBuilt` event before calling this function." + (msg ? " " + msg : "")); + } + return this.initialized; + } + + ////////////////// Data Handling ////////////////// + //block table redrawing + blockRedraw() { + this.initGuard(); + this.eventBus.dispatch("redraw-blocking"); + this.rowManager.blockRedraw(); + this.columnManager.blockRedraw(); + this.eventBus.dispatch("redraw-blocked"); + } + + //restore table redrawing + restoreRedraw() { + this.initGuard(); + this.eventBus.dispatch("redraw-restoring"); + this.rowManager.restoreRedraw(); + this.columnManager.restoreRedraw(); + this.eventBus.dispatch("redraw-restored"); + } + + //load data + setData(data, params, config) { + this.initGuard(false, "To set initial data please use the 'data' property in the table constructor."); + return this.dataLoader.load(data, params, config, false); + } + + //clear data + clearData() { + this.initGuard(); + this.dataLoader.blockActiveLoad(); + this.rowManager.clearData(); + } + + //get table data array + getData(active) { + return this.rowManager.getData(active); + } + + //get table data array count + getDataCount(active) { + return this.rowManager.getDataCount(active); + } + + //replace data, keeping table in position with same sort + replaceData(data, params, config) { + this.initGuard(); + return this.dataLoader.load(data, params, config, true, true); + } + + //update table data + updateData(data) { + var responses = 0; + this.initGuard(); + return new Promise((resolve, reject) => { + this.dataLoader.blockActiveLoad(); + if (typeof data === "string") { + data = JSON.parse(data); + } + if (data && data.length > 0) { + data.forEach((item) => { + var row = this.rowManager.findRow(item[this.options.index]); + if (row) { + responses++; + row.updateData(item).then(() => { + responses--; + if (!responses) { + resolve(); + } + }).catch((e) => { + reject("Update Error - Unable to update row", item, e); + }); + } else { + reject("Update Error - Unable to find row", item); + } + }); + } else { + console.warn("Update Error - No data provided"); + reject("Update Error - No data provided"); + } + }); + } + + addData(data, pos, index) { + this.initGuard(); + return new Promise((resolve, reject) => { + this.dataLoader.blockActiveLoad(); + if (typeof data === "string") { + data = JSON.parse(data); + } + if (data) { + this.rowManager.addRows(data, pos, index).then((rows2) => { + var output = []; + rows2.forEach(function (row) { + output.push(row.getComponent()); + }); + resolve(output); + }); + } else { + console.warn("Update Error - No data provided"); + reject("Update Error - No data provided"); + } + }); + } + + //update table data + updateOrAddData(data) { + var rows2 = [], responses = 0; + this.initGuard(); + return new Promise((resolve, reject) => { + this.dataLoader.blockActiveLoad(); + if (typeof data === "string") { + data = JSON.parse(data); + } + if (data && data.length > 0) { + data.forEach((item) => { + var row = this.rowManager.findRow(item[this.options.index]); + responses++; + if (row) { + row.updateData(item).then(() => { + responses--; + rows2.push(row.getComponent()); + if (!responses) { + resolve(rows2); + } + }); + } else { + this.rowManager.addRows(item).then((newRows) => { + responses--; + rows2.push(newRows[0].getComponent()); + if (!responses) { + resolve(rows2); + } + }); + } + }); + } else { + console.warn("Update Error - No data provided"); + reject("Update Error - No data provided"); + } + }); + } + + //get row object + getRow(index) { + var row = this.rowManager.findRow(index); + if (row) { + return row.getComponent(); + } else { + console.warn("Find Error - No matching row found:", index); + return false; + } + } + + //get row object + getRowFromPosition(position) { + var row = this.rowManager.getRowFromPosition(position); + if (row) { + return row.getComponent(); + } else { + console.warn("Find Error - No matching row found:", position); + return false; + } + } + + //delete row from table + deleteRow(index) { + var foundRows = []; + this.initGuard(); + if (!Array.isArray(index)) { + index = [index]; + } + for (let item of index) { + let row = this.rowManager.findRow(item, true); + if (row) { + foundRows.push(row); + } else { + console.error("Delete Error - No matching row found:", item); + return Promise.reject("Delete Error - No matching row found"); + } + } + foundRows.sort((a, b) => { + return this.rowManager.rows.indexOf(a) > this.rowManager.rows.indexOf(b) ? 1 : -1; + }); + foundRows.forEach((row) => { + row.delete(); + }); + this.rowManager.reRenderInPosition(); + return Promise.resolve(); + } + + //add row to table + addRow(data, pos, index) { + this.initGuard(); + if (typeof data === "string") { + data = JSON.parse(data); + } + return this.rowManager.addRows(data, pos, index, true).then((rows2) => { + return rows2[0].getComponent(); + }); + } + + //update a row if it exists otherwise create it + updateOrAddRow(index, data) { + var row = this.rowManager.findRow(index); + this.initGuard(); + if (typeof data === "string") { + data = JSON.parse(data); + } + if (row) { + return row.updateData(data).then(() => { + return row.getComponent(); + }); + } else { + return this.rowManager.addRows(data).then((rows2) => { + return rows2[0].getComponent(); + }); + } + } + + //update row data + updateRow(index, data) { + var row = this.rowManager.findRow(index); + this.initGuard(); + if (typeof data === "string") { + data = JSON.parse(data); + } + if (row) { + return row.updateData(data).then(() => { + return Promise.resolve(row.getComponent()); + }); + } else { + console.warn("Update Error - No matching row found:", index); + return Promise.reject("Update Error - No matching row found"); + } + } + + //scroll to row in DOM + scrollToRow(index, position, ifVisible) { + var row = this.rowManager.findRow(index); + if (row) { + return this.rowManager.scrollToRow(row, position, ifVisible); + } else { + console.warn("Scroll Error - No matching row found:", index); + return Promise.reject("Scroll Error - No matching row found"); + } + } + + moveRow(from, to, after) { + var fromRow = this.rowManager.findRow(from); + this.initGuard(); + if (fromRow) { + fromRow.moveToRow(to, after); + } else { + console.warn("Move Error - No matching row found:", from); + } + } + + getRows(active) { + return this.rowManager.getComponents(active); + } + + //get position of row in table + getRowPosition(index) { + var row = this.rowManager.findRow(index); + if (row) { + return row.getPosition(); + } else { + console.warn("Position Error - No matching row found:", index); + return false; + } + } + + /////////////// Column Functions /////////////// + setColumns(definition) { + this.initGuard(false, "To set initial columns please use the 'columns' property in the table constructor"); + this.columnManager.setColumns(definition); + } + + getColumns(structured) { + return this.columnManager.getComponents(structured); + } + + getColumn(field) { + var column = this.columnManager.findColumn(field); + if (column) { + return column.getComponent(); + } else { + console.warn("Find Error - No matching column found:", field); + return false; + } + } + + getColumnDefinitions() { + return this.columnManager.getDefinitionTree(); + } + + showColumn(field) { + var column = this.columnManager.findColumn(field); + this.initGuard(); + if (column) { + column.show(); + } else { + console.warn("Column Show Error - No matching column found:", field); + return false; + } + } + + hideColumn(field) { + var column = this.columnManager.findColumn(field); + this.initGuard(); + if (column) { + column.hide(); + } else { + console.warn("Column Hide Error - No matching column found:", field); + return false; + } + } + + toggleColumn(field) { + var column = this.columnManager.findColumn(field); + this.initGuard(); + if (column) { + if (column.visible) { + column.hide(); + } else { + column.show(); + } + } else { + console.warn("Column Visibility Toggle Error - No matching column found:", field); + return false; + } + } + + addColumn(definition, before, field) { + var column = this.columnManager.findColumn(field); + this.initGuard(); + return this.columnManager.addColumn(definition, before, column).then((column2) => { + return column2.getComponent(); + }); + } + + deleteColumn(field) { + var column = this.columnManager.findColumn(field); + this.initGuard(); + if (column) { + return column.delete(); + } else { + console.warn("Column Delete Error - No matching column found:", field); + return Promise.reject(); + } + } + + updateColumnDefinition(field, definition) { + var column = this.columnManager.findColumn(field); + this.initGuard(); + if (column) { + return column.updateDefinition(definition); + } else { + console.warn("Column Update Error - No matching column found:", field); + return Promise.reject(); + } + } + + moveColumn(from, to, after) { + var fromColumn = this.columnManager.findColumn(from), toColumn = this.columnManager.findColumn(to); + this.initGuard(); + if (fromColumn) { + if (toColumn) { + this.columnManager.moveColumn(fromColumn, toColumn, after); + } else { + console.warn("Move Error - No matching column found:", toColumn); + } + } else { + console.warn("Move Error - No matching column found:", from); + } + } + + //scroll to column in DOM + scrollToColumn(field, position, ifVisible) { + return new Promise((resolve, reject) => { + var column = this.columnManager.findColumn(field); + if (column) { + return this.columnManager.scrollToColumn(column, position, ifVisible); + } else { + console.warn("Scroll Error - No matching column found:", field); + return Promise.reject("Scroll Error - No matching column found"); + } + }); + } + + //////////// General Public Functions //////////// + //redraw list without updating data + redraw(force) { + this.initGuard(); + this.columnManager.redraw(force); + this.rowManager.redraw(force); + } + + setHeight(height) { + this.options.height = isNaN(height) ? height : height + "px"; + this.element.style.height = this.options.height; + this.rowManager.initializeRenderer(); + this.rowManager.redraw(true); + } + + setMaxHeight(maxHeight) { + this.options.maxHeight = isNaN(maxHeight) ? maxHeight : maxHeight + "px"; + this.element.style.maxHeight = this.options.maxHeight; + this.rowManager.initializeRenderer(); + this.rowManager.redraw(true); + } + + setMinHeight(minHeight) { + this.options.minHeight = isNaN(minHeight) ? minHeight : minHeight + "px"; + this.element.style.minHeight = this.options.minHeight; + this.rowManager.initializeRenderer(); + this.rowManager.redraw(true); + } + + //////////////////// Event Bus /////////////////// + on(key, callback) { + this.externalEvents.subscribe(key, callback); + } + + off(key, callback) { + this.externalEvents.unsubscribe(key, callback); + } + + dispatchEvent() { + var args = Array.from(arguments); + args.shift(); + this.externalEvents.dispatch(...arguments); + } + + //////////////////// Alerts /////////////////// + alert(contents, type) { + this.initGuard(); + this.alertManager.alert(contents, type); + } + + clearAlert() { + this.initGuard(); + this.alertManager.clear(); + } + + ////////////// Extension Management ////////////// + modExists(plugin, required) { + if (this.modules[plugin]) { + return true; + } else { + if (required) { + console.error("Tabulator Module Not Installed: " + plugin); + } + return false; + } + } + + module(key) { + var mod = this.modules[key]; + if (!mod) { + console.error("Tabulator module not installed: " + key); + } + return mod; + } + }, //default setup options + __publicField(_a, "defaultOptions", defaultOptions), _a); + + class TabulatorFull extends Tabulator$1 { + static extendModule() { + Tabulator$1.initializeModuleBinder(allModules); + Tabulator$1._extendModule(...arguments); + } + + static registerModule() { + Tabulator$1.initializeModuleBinder(allModules); + Tabulator$1._registerModule(...arguments); + } + + constructor(element, options, modules) { + super(element, options, allModules); + } + } const DMM_GRAPHQL_URL = "https://api.video.dmm.co.jp/graphql"; const dmmGraphQLKeyword = (code) => { const match = String(code || "").trim().toUpperCase().match(/^([A-Z0-9]{2,10})-(\d{1,6})$/); @@ -2952,12 +27092,12 @@ ${value}\r return; } try { - const json = JSON.parse(response.responseText || "{}"); - if (Array.isArray(json.errors) && json.errors.length) { - reject(new Error(json.errors[0].message || "DMM GraphQL error")); + const json2 = JSON.parse(response.responseText || "{}"); + if (Array.isArray(json2.errors) && json2.errors.length) { + reject(new Error(json2.errors[0].message || "DMM GraphQL error")); return; } - resolve(json.data || {}); + resolve(json2.data || {}); } catch (e) { reject(new Error(`DMM GraphQL JSON parse error: ${e.message}`)); } @@ -3353,15 +27493,15 @@ ${value}\r if (isJavDb$1 && pageNum > maxPage || currentHref$1.includes("month")) { const beyond60Plugin = this.getBean("Beyond60Plugin"); if (beyond60Plugin) { - const {html: html2, nextUrl, hasMore} = await beyond60Plugin.handleBeyond60(this.nextUrl); - if (html2) { + const {html: html22, nextUrl, hasMore} = await beyond60Plugin.handleBeyond60(this.nextUrl); + if (html22) { const pageTop2 = this.container.scrollHeight; this.pageItems.push({ page: this.currentPage + 1, top: pageTop2, url: this.nextUrl }); - $(".movie-list").append(html2); + $(".movie-list").append(html22); } this.hasMore = hasMore; this.nextUrl = nextUrl; @@ -3372,9 +27512,9 @@ ${value}\r return; } } - const html = await gmHttp.get(this.nextUrl); + const html2 = await gmHttp.get(this.nextUrl); clog.log("请求下一页内容:", this.nextUrl); - const $dom = utils.htmlTo$dom(html); + const $dom = utils.htmlTo$dom(html2); isJavBus$1 && $dom.find(".avatar-box").length > 0 && $dom.find(".avatar-box").parent().remove(); let itemList = $dom.find(this.getSelector().requestDomItemSelector); const currentBoxCarInfoList = this.getBoxCarInfoList(), @@ -5556,12 +29696,12 @@ ${value}\r $list.html('
暂无标记删除的作品
'); return; } - let html = ""; + let html2 = ""; for (let i = 0; i < markedList.length; i++) { const item = markedList[i]; const truncatedTitle = item.title && item.title.length > 30 ? item.title.substring(0, 30) + "..." : item.title; const detailUrl = item.url ? item.url.startsWith("http") ? item.url : window.location.origin + item.url : "#"; - html += `
+ html2 += `
${item.carNum}
@@ -5571,23 +29711,23 @@ ${value}\r ✕
`; } - html += `
`; - $list.html(html); + html2 += `
`; + $list.html(html2); $("#markDeleteSelectAll").prop("checked", true); } addLabelTag(containerId, keyword) { const $tagBox = $(`${containerId} .tag-box`); - let $label, color = "#333"; + let $label, color2 = "#333"; if (/^[a-z]{2,}-/i.test(keyword) && isJavDb$1) { - color = "#3477ad"; + color2 = "#3477ad"; $label = $(` - + ${keyword} × `); } else $label = $(` -
+
${keyword} ×
@@ -5613,10 +29753,10 @@ ${value}\r } importData() { try { - const input = document.createElement("input"); - input.type = "file"; - input.accept = ".json"; - input.onchange = (e) => { + const input2 = document.createElement("input"); + input2.type = "file"; + input2.accept = ".json"; + input2.onchange = (e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); @@ -5643,9 +29783,9 @@ ${value}\r }; reader.readAsText(file); }; - document.body.appendChild(input); - input.click(); - setTimeout((() => document.body.removeChild(input)), 1e3); + document.body.appendChild(input2); + input2.click(); + setTimeout((() => document.body.removeChild(input2)), 1e3); } catch (err) { console.error(err); show.error("导入数据时出错: " + err.message); @@ -6046,7 +30186,7 @@ ${value}\r try { clog.log("正在检屏黑名单演员:", name2, url); $("#checkBlacklistMsg").text(`正在检屏黑名单演员: ${name2} ${url}`); - const html = await gmHttp.get(url), $dom = utils.htmlTo$dom(html); + const html2 = await gmHttp.get(url), $dom = utils.htmlTo$dom(html2); this.storageQueue.addTask((async () => { let {lastPublishTime} = await blacklistPlugin.parseAndSaveFilterInfo($dom, name2, starId); await storageManager.updateBlacklistItem({ @@ -6084,7 +30224,7 @@ ${value}\r clog.log(`正在抓取页面: ${currentUrl}`); $("#checkNewVideoMsg").text(`正在解析已收藏的演员: ${currentUrl}`); try { - const html = await gmHttp.get(currentUrl), $dom = utils.htmlTo$dom(html); + const html2 = await gmHttp.get(currentUrl), $dom = utils.htmlTo$dom(html2); $dom.find("#actors .actor-box a").each(((i, element) => { const $a = $(element), title = $a.attr("title"), href = $a.attr("href"); if (title && href) { @@ -6155,7 +30295,7 @@ ${value}\r try { clog.log("正在检测最新作品, 演员:", name2, url); $("#checkNewVideoMsg").text(`正在检测最新作品, 演员: ${name2}`); - const html = await gmHttp.get(url), $dom = utils.htmlTo$dom(html); + const html2 = await gmHttp.get(url), $dom = utils.htmlTo$dom(html2); this.storageQueue.addTask((async () => { await this.parsePage($dom, starId, name2, filterKeywordList, filterActorActressCarNumList); })); @@ -6220,7 +30360,7 @@ ${value}\r try { clog.log("正在检测最新作品, 演员:", name2, url); $checkNewVideoMsg.text(`正在检测最新作品, 演员: ${name2}`); - const html = await gmHttp.get(url), $dom = utils.htmlTo$dom(html); + const html2 = await gmHttp.get(url), $dom = utils.htmlTo$dom(html2); await this.parsePage($dom, starId, name2, filterKeywordList, filterActorActressCarNumList); clog.log('检测最新作品---结束'); $checkNewVideoMsg.text("检测完毕"); @@ -6320,7 +30460,7 @@ ${value}\r checkFavoriteActress_IntervalTime = settingObj.checkFavoriteActress_IntervalTime, lastCheckNewVideoTimeStr = localStorage.getItem(taskPlugin.lastCheckNewVideoTimeKey) || "无", checkNewVideo_intervalTime = settingObj.checkNewVideo_intervalTime; - let html = ` + let html2 = `
@@ -6348,7 +30488,7 @@ ${value}\r layer.open({ type: 1, title: '新作品检测 ❓', - content: html, + content: html2, scrollbar: false, area: utils.getResponsiveArea(["80%", "90%"]), anim: -1, @@ -7173,28 +31313,28 @@ ${value}\r headerSort: false, formatter: (cell, formatterParams, onRendered) => { const statusValue = cell.getData().status; - let color = "", text = ""; + let color2 = "", text = ""; switch (statusValue) { case "filter": - color = "#de3333"; + color2 = "#de3333"; text = "🚫 屏蔽"; break; case "favorite": - color = "#25b1dc"; + color2 = "#25b1dc"; text = "⭐ 收藏"; break; case "hasDown": - color = "#7bc73b"; + color2 = "#7bc73b"; text = "📥️ 已下载"; break; case "hasWatch": - color = "#d7a80c"; + color2 = "#d7a80c"; text = "🔍 已观看"; break; default: text = statusValue; } - return `${text}`; + return `${text}`; } }, { title: "备注", @@ -7261,7 +31401,7 @@ ${value}\r } } }); - this.tableObj.on("rowSelectionChanged", ((data, rows, selected, deselected) => { + this.tableObj.on("rowSelectionChanged", ((data, rows2, selected, deselected) => { const $allSelectBox = $("#allSelectBox"), $filterBox = $("#filterBox"); if (data && data.length > 0) { $filterBox.hide(); @@ -7790,9 +31930,9 @@ ${value}\r return [this.buildDefaultKeyword(details)].filter(Boolean); } static buildSubtitleBaseName(details = {}) { - var _a; - if ((_a = window.JavPackMatch115Console) == null ? void 0 : _a.buildRename) { - return window.JavPackMatch115Console.buildRename(details, [{n: `${details.code || "subtitle"}.mp4`}]); + var _a2; + if ((_a2 = window.JavPackMatch115Console) == null ? void 0 : _a2.buildRename) { + return window.JavPackMatch115Console.buildRename(details, [{n: `${details.code || "subtitle"}.mp4`}]); } return this.sanitizeName([details.code, details.title].filter(Boolean).join(" ")) || this.buildDefaultKeyword(details); } @@ -7812,8 +31952,8 @@ ${value}\r return window.Req115 || null; } static getTargetCid() { - var _a, _b; - return ((_a = document.querySelector(".x-match-cont .zymatch-item [data-cid]")) == null ? void 0 : _a.dataset.cid) || ((_b = document.querySelector(".x-match-cont .zymatch-item")) == null ? void 0 : _b.dataset.cid) || ""; + var _a2, _b; + return ((_a2 = document.querySelector(".x-match-cont .zymatch-item [data-cid]")) == null ? void 0 : _a2.dataset.cid) || ((_b = document.querySelector(".x-match-cont .zymatch-item")) == null ? void 0 : _b.dataset.cid) || ""; } static async find115Cid(code) { if (!code) return ""; @@ -7935,10 +32075,10 @@ ${value}\r } static openSearchModal({details = {}, getTargetCid} = {}) { - var _a; + var _a2; const defaultKw = this.buildDefaultKeyword(details); this.currentDetails = details; - (_a = document.getElementById(this.MODAL_ID)) == null ? void 0 : _a.remove(); + (_a2 = document.getElementById(this.MODAL_ID)) == null ? void 0 : _a2.remove(); const overlay = document.createElement("div"); overlay.id = this.MODAL_ID; overlay.className = "pdb-sub-overlay"; @@ -7947,7 +32087,7 @@ ${value}\r const contentWrap = overlay.querySelector(".pdb-sub-content"); const previewBox = overlay.querySelector(".pdb-sub-textarea"); const statusNode = overlay.querySelector("#preview-status"); - const input = overlay.querySelector("#sub-search-input"); + const input2 = overlay.querySelector("#sub-search-input"); const dirWrap = overlay.querySelector("#sub-115-wrap"); const dirSelect = overlay.querySelector("#sub-115-select"); const refresh115DirUI = () => { @@ -8013,9 +32153,9 @@ ${value}\r contentWrap.innerHTML = '
搜索失败,请稍后重试
'; } }; - overlay.querySelector("#sub-search-btn").addEventListener("click", () => performSearch(input.value.trim())); - input.addEventListener("keypress", (e) => { - if (e.key === "Enter") performSearch(input.value.trim()); + overlay.querySelector("#sub-search-btn").addEventListener("click", () => performSearch(input2.value.trim())); + input2.addEventListener("keypress", (e) => { + if (e.key === "Enter") performSearch(input2.value.trim()); }); performSearch(defaultKw); } @@ -8071,34 +32211,36 @@ ${value}\r })); return languageGroups.flat(); } - static parseSubtitleCatSearch(html) { - const doc = new DOMParser().parseFromString(html, "text/html"); + + static parseSubtitleCatSearch(html2) { + const doc = new DOMParser().parseFromString(html2, "text/html"); return [...doc.querySelectorAll("table.sub-table tbody tr")].flatMap((row) => { - var _a; - const link = row.querySelector('a[href*="subs/"]'); - const name2 = (_a = link == null ? void 0 : link.textContent) == null ? void 0 : _a.trim(); - if (!link || !name2) return []; + var _a2; + const link2 = row.querySelector('a[href*="subs/"]'); + const name2 = (_a2 = link2 == null ? void 0 : link2.textContent) == null ? void 0 : _a2.trim(); + if (!link2 || !name2) return []; return [{ name: name2, - detailUrl: new URL(link.getAttribute("href"), this.SUBTITLECAT_ORIGIN).href + detailUrl: new URL(link2.getAttribute("href"), this.SUBTITLECAT_ORIGIN).href }]; }); } - static parseSubtitleCatLanguages(html, entry) { - const doc = new DOMParser().parseFromString(html, "text/html"); + + static parseSubtitleCatLanguages(html2, entry) { + const doc = new DOMParser().parseFromString(html2, "text/html"); return [...doc.querySelectorAll(".sub-single")].flatMap((node) => { - var _a; - const languageCode = ((_a = node.querySelector("img.flag")) == null ? void 0 : _a.getAttribute("alt")) || ""; + var _a2; + const languageCode = ((_a2 = node.querySelector("img.flag")) == null ? void 0 : _a2.getAttribute("alt")) || ""; const language = this.SUBTITLECAT_CHINESE_LANGUAGES.get(languageCode); - const link = node.querySelector("a.green-link[href$='.srt']"); - if (!language || !link) return []; + const link2 = node.querySelector("a.green-link[href$='.srt']"); + if (!language || !link2) return []; return [{ name: entry.name, languageCode, languages: [language], ext: "srt", provider: "SubtitleCat", - url: new URL(link.getAttribute("href"), this.SUBTITLECAT_ORIGIN).href + url: new URL(link2.getAttribute("href"), this.SUBTITLECAT_ORIGIN).href }]; }); } @@ -8161,8 +32303,8 @@ ${value}\r }); } static renderRow(item, index, highlightRegex) { - var _a; - const lang = ((_a = item.languages) == null ? void 0 : _a[0]) || "未知"; + var _a2; + const lang = ((_a2 = item.languages) == null ? void 0 : _a2[0]) || "未知"; const name2 = item.name || item.extra_name || "未知字幕"; const provider = item.provider || "迅雷"; const providerClass = provider === "SubtitleCat" ? "pdb-sub-provider--subtitlecat" : "pdb-sub-provider--xunlei"; @@ -8270,11 +32412,11 @@ ${value}\r } static downloadBuffer(buffer, filename) { const blob = new Blob([buffer], {type: "application/octet-stream"}); - const link = document.createElement("a"); - link.href = URL.createObjectURL(blob); - link.download = filename; - link.click(); - URL.revokeObjectURL(link.href); + const link2 = document.createElement("a"); + link2.href = URL.createObjectURL(blob); + link2.download = filename; + link2.click(); + URL.revokeObjectURL(link2.href); } static uploadSubtitle(args) { return args.req115.queueMutation("上传字幕", () => this.uploadSubtitleNow(args)); @@ -8567,14 +32709,14 @@ ${value}\r return this.filesSearchAll(search_value, {...params, fc: 1}); } static async handleDir(routes) { - var _a; + var _a2; if (routes.length === 1 && /^\d{5,}$/.test(routes[0])) return routes[0]; let cid; const routesStr = routes.join("/"); const cachedCid = localStorage.getItem(routesStr); if (cachedCid) { const res = await this.files(cachedCid); - if ((_a = res == null ? void 0 : res.path) == null ? void 0 : _a.length) { + if ((_a2 = res == null ? void 0 : res.path) == null ? void 0 : _a2.length) { const path = res.path.slice(1).map((p) => p.name); if (path.join("/") === routesStr) cid = cachedCid; } @@ -8643,13 +32785,13 @@ ${value}\r if (needRemove.length) return this.rbDelete(needRemove, cid); } static async handleTags(files, tags) { - var _a; + var _a2; const {data} = await this.labelList(); - if (!((_a = data == null ? void 0 : data.list) == null ? void 0 : _a.length)) return; - const {list} = data; + if (!((_a2 = data == null ? void 0 : data.list) == null ? void 0 : _a2.length)) return; + const {list: list2} = data; const labels = []; tags.forEach((tag) => { - const item = list.find((item2) => item2.name === tag); + const item = list2.find((item2) => item2.name === tag); if (item) labels.push(item.id); }); if (labels.length) return this.filesBatchLabel(files.map((it) => it.fid).toString(), labels.toString()); @@ -8998,8 +33140,8 @@ ${value}\r const y = parseInt(dateStr.substring(0, 4), 10); const m = parseInt(dateStr.substring(4, 6), 10) - 1; const d2 = parseInt(dateStr.substring(6, 8), 10); - const date = new Date(y, m, d2); - return isNaN(date.getTime()) ? 0 : date.getTime(); + const date2 = new Date(y, m, d2); + return isNaN(date2.getTime()) ? 0 : date2.getTime(); } const d = new Date(dateStr); return isNaN(d.getTime()) ? 0 : d.getTime(); @@ -9191,19 +33333,19 @@ ${value}\r } handleBus() { isJavBus$1 && window.isDetailPage && utils.loopDetector((() => $("#magnet-table td a").length > 0), (() => { - const rows = $("#magnet-table tr"), QUALITY_KEYWORDS = ["4k", "-c", "-u", "-uc"]; + const rows2 = $("#magnet-table tr"), QUALITY_KEYWORDS = ["4k", "-c", "-u", "-uc"]; let hasHighQuality = false; - rows.each(((_, row) => { - const $row = $(row), $firstTd = $row.find("td:first-child"), - $firstLink = $firstTd.find("a:first-child"), $secondLink = $firstTd.find("a:nth-child(2)"), - linkText = $firstLink.text().toLowerCase(); + rows2.each(((_, row) => { + const $row = $(row), $firstTd = $row.find("td:first-child"), + $firstLink = $firstTd.find("a:first-child"), $secondLink = $firstTd.find("a:nth-child(2)"), + linkText = $firstLink.text().toLowerCase(); linkText.includes("4k") && $firstLink.css("color", "#f40"); if (QUALITY_KEYWORDS.some(((keyword) => linkText.includes(keyword))) || $secondLink.length && $secondLink.text().includes("字幕")) { hasHighQuality = true; $row.addClass("high-quality"); } })); - hasHighQuality ? rows.each(((_, row) => { + hasHighQuality ? rows2.each(((_, row) => { const $row = $(row); $row.hasClass("high-quality") || $row.hide(); })) : $("#enable-magnets-filter").addClass("do-hide"); @@ -9434,8 +33576,8 @@ ${value}\r async searchInfo(name2) { "三上悠亞" === name2 && (name2 = "三上悠亜"); let url = this.apiUrl + name2; - const html = await gmHttp.get(url), parser = new DOMParser(), - $dom = $(parser.parseFromString(html, "text/html")); + const html2 = await gmHttp.get(url), parser = new DOMParser(), + $dom = $(parser.parseFromString(html2, "text/html")); let birthday = $dom.find('a[title="誕生日"]').parent().parent().find("td").text().trim(), age = $dom.find("th:contains('現年齢')").parent().find("td").text().trim() ? parseInt($dom.find("th:contains('現年齢')").parent().find("td").text().trim()) + "岁" : "", height = $dom.find('tr:has(a[title="身長"]) td').text().trim().split(" ")[0] + "cm", @@ -9552,14 +33694,14 @@ ${value}\r } for (; !document.hasFocus();) await new Promise(((r) => setTimeout(r, 500))); const res = await javDbApi.getMovieDetail(movieId); - let score = res.score, watchedCount = res.watchedCount, html = ` + let score = res.score, watchedCount = res.watchedCount, html2 = ` ${this.getStarRating(score)}   ${score}分,由${watchedCount}人評價 `; - this.appendScoreHtml(movieId, html); - cacheData[movieId] = html; + this.appendScoreHtml(movieId, html2); + cacheData[movieId] = html2; localStorage.setItem("jhs_score_info", JSON.stringify(cacheData)); await new Promise(((r) => setTimeout(r, 500))); } catch (err) { @@ -10353,14 +34495,14 @@ ${err.stack}` : ""); const BASE_URL = [77, 81, 81, 85, 86, 31, 10, 10, 68, 85, 76, 8, 65, 72, 72, 87, 86, 70, 11, 20, 22, 20, 17, 22, 22, 11, 93, 92, 95].map((v) => String.fromCharCode(v ^ 37)).join(""); const COVER_API_TOKEN = [18, 28, 19, 19, 65, 65, 70, 28, 64, 29, 23, 21, 17, 29, 67, 70, 18, 64, 21, 22, 64, 16, 65, 29, 22, 19, 16, 28, 16, 17, 64, 29].map((v) => String.fromCharCode(v ^ 37)).join(""); const getCover = async (code) => { - var _a; + var _a2; const query = String(code || "").trim(); if (!query) return null; try { const r = await gmHttp.get(`${COVER_API_URL}/${encodeURIComponent(query)}`, null, { "Authorization": `Bearer ${COVER_API_TOKEN}` }, {timeout: 15e3}); - if ((_a = r == null ? void 0 : r.cover) == null ? void 0 : _a.large) { + if ((_a2 = r == null ? void 0 : r.cover) == null ? void 0 : _a2.large) { return r.cover.large; } return null; @@ -11003,8 +35145,8 @@ ${err.stack}` : ""); $.ajax({ url: nextPageLink, method: "GET", - success: (html) => { - const parser = new DOMParser(), next$dom = $(parser.parseFromString(html, "text/html")); + success: (html2) => { + const parser = new DOMParser(), next$dom = $(parser.parseFromString(html2, "text/html")); this.parseMovieList(next$dom); }, error: function (err) { @@ -11028,11 +35170,11 @@ ${err.stack}` : ""); } function fallbackCopy(text, $btn) { - const textarea = document.createElement("textarea"); - textarea.value = text; - textarea.style.position = "fixed"; - document.body.appendChild(textarea); - textarea.select(); + const textarea2 = document.createElement("textarea"); + textarea2.value = text; + textarea2.style.position = "fixed"; + document.body.appendChild(textarea2); + textarea2.select(); try { document.execCommand("copy"); showCopiedFeedback($btn); @@ -11040,7 +35182,7 @@ ${err.stack}` : ""); console.error("复制失败:", err); alert("复制失败,请手动复制链接"); } - document.body.removeChild(textarea); + document.body.removeChild(textarea2); } function parseSize(sizeStr) { @@ -11107,9 +35249,9 @@ ${err.stack}` : ""); })); } - function parseHTML(html) { + function parseHTML(html2) { const parser = new DOMParser(); - return parser.parseFromString(html, "text/html"); + return parser.parseFromString(html2, "text/html"); } class MagnetHubPlugin extends BasePlugin { constructor() { @@ -11698,8 +35840,8 @@ ${err.stack}` : ""); } async checkWhatslink(magnet) { - var _a; - (_a = document.querySelector(".whatslink-overlay")) == null ? void 0 : _a.remove(); + var _a2; + (_a2 = document.querySelector(".whatslink-overlay")) == null ? void 0 : _a2.remove(); const overlay = document.createElement("div"); overlay.className = "whatslink-overlay"; overlay.innerHTML = ''; @@ -11726,8 +35868,8 @@ ${err.stack}` : ""); } showWhatslinkModal(payload, magnet) { - var _a; - (_a = document.querySelector(".whatslink-overlay")) == null ? void 0 : _a.remove(); + var _a2; + (_a2 = document.querySelector(".whatslink-overlay")) == null ? void 0 : _a2.remove(); const shots = Array.isArray(payload == null ? void 0 : payload.screenshots) ? payload.screenshots.map((item) => item == null ? void 0 : item.screenshot).filter(Boolean) : []; let index = 0; const resourceName = (payload == null ? void 0 : payload.name) || "未知资源"; @@ -11871,8 +36013,8 @@ ${err.stack}` : ""); render(); } - parseU9A9(html, keyword) { - const $dom = utils.htmlTo$dom(html), results = []; + parseU9A9(html2, keyword) { + const $dom = utils.htmlTo$dom(html2), results = []; const kwNorm = String(keyword).toUpperCase().replace(/[^A-Z0-9]/g, ""); $dom.find(".torrent-list tbody tr").each(((i, el) => { const $el = $(el); @@ -11886,14 +36028,14 @@ ${err.stack}` : ""); } const magnet = $el.find("td:nth-child(3) a[href^='magnet:']").attr("href"); const size = $el.find("td:nth-child(4)").text().trim(); - const date = $el.find("td:nth-child(5)").text().trim(); - magnet && results.push({title, magnet, size, date}); + const date2 = $el.find("td:nth-child(5)").text().trim(); + magnet && results.push({title, magnet, size, date: date2}); })); return results; } async parseU3C3(_html, keyword) { - var _a; + var _a2; const base = "https://www.u3c3.com"; const referer = base + "/"; const home = await gmFetch(base + "/", { @@ -11902,7 +36044,7 @@ ${err.stack}` : ""); if (!home.loadstuts) return []; const homeDoc = parseHTML(home.responseText); const searchScript = [...homeDoc.scripts].map((script) => script.textContent || "").find((text) => text.includes("function search21")) || ""; - const token = ((_a = searchScript.match(/^\s*var\s+nmefafej\s*=\s*["']([^"']+)["'];?/m)) == null ? void 0 : _a[1]) || ""; + const token = ((_a2 = searchScript.match(/^\s*var\s+nmefafej\s*=\s*["']([^"']+)["'];?/m)) == null ? void 0 : _a2[1]) || ""; if (!token) return []; const searchUrl = `${base}/?search2=${encodeURIComponent(token)}&search=${encodeURIComponent(keyword)}`; const r = await gmFetch(searchUrl, { @@ -11912,10 +36054,10 @@ ${err.stack}` : ""); const doc = parseHTML(r.responseText); const normalizedKeyword = String(keyword || "").toUpperCase().replace(/[-_\s]/g, ""); const data = [...doc.querySelectorAll("table.torrent-list tbody tr.default, table.torrent-list tbody tr.success")].map((row) => { - var _a2, _b, _c, _d, _e, _f; + var _a3, _b, _c, _d, _e, _f; const titleA = row.querySelector('td:nth-child(2) a[href*="/view?id="]'); const magnetA = row.querySelector('td:nth-child(3) a[href^="magnet:"]'); - const title = ((_a2 = titleA == null ? void 0 : titleA.getAttribute("title")) == null ? void 0 : _a2.trim()) || ((_b = titleA == null ? void 0 : titleA.textContent) == null ? void 0 : _b.trim()) || ""; + const title = ((_a3 = titleA == null ? void 0 : titleA.getAttribute("title")) == null ? void 0 : _a3.trim()) || ((_b = titleA == null ? void 0 : titleA.textContent) == null ? void 0 : _b.trim()) || ""; if (!title || !(magnetA == null ? void 0 : magnetA.href)) return null; if (normalizedKeyword && !title.toUpperCase().replace(/[-_\s]/g, "").includes(normalizedKeyword)) return null; const href = titleA.getAttribute("href") || ""; @@ -11930,22 +36072,22 @@ ${err.stack}` : ""); return data; } - parseSukebei(html, keyword) { - const $dom = utils.htmlTo$dom(html), results = []; + parseSukebei(html2, keyword) { + const $dom = utils.htmlTo$dom(html2), results = []; $dom.find("tr.default, tr.success").each(((i, el) => { const $el = $(el); const title = $el.find("td:nth-child(2) a").first().attr("title") || $el.find("td:nth-child(2) a").first().text().trim(); if (!title) return; const magnet = $el.find("td:nth-child(3) a:last-child").attr("href"); const size = $el.find("td:nth-child(4)").text().trim(); - const date = $el.find("td:nth-child(5)").text().trim(); - magnet && results.push({title, magnet, size, date}); + const date2 = $el.find("td:nth-child(5)").text().trim(); + magnet && results.push({title, magnet, size, date: date2}); })); return results; } - async parseOmag(html, keyword) { - const doc = parseHTML(html); + async parseOmag(html2, keyword) { + const doc = parseHTML(html2); const base = "https://xn--mag-zna.net"; const entries = [...doc.querySelectorAll("tr")].map((row) => { const titleA = row.querySelector('td.result-title a[href^="/!"]'); @@ -12001,21 +36143,21 @@ ${err.stack}` : ""); "x-sign": sign }, onload: (response) => { - var _a; + var _a2; try { - const json = JSON.parse(response.responseText); - const items = Array.isArray(json == null ? void 0 : json.data) ? json.data : Array.isArray((_a = json == null ? void 0 : json.data) == null ? void 0 : _a.data) ? json.data.data : []; + const json2 = JSON.parse(response.responseText); + const items = Array.isArray(json2 == null ? void 0 : json2.data) ? json2.data : Array.isArray((_a2 = json2 == null ? void 0 : json2.data) == null ? void 0 : _a2.data) ? json2.data.data : []; const results = items.map((item) => { const title = String((item == null ? void 0 : item.name) || "").replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim(); const hash = String((item == null ? void 0 : item.hash) || "").replace(/^magnet:\?xt=urn:btih:/i, "").replace(/[^a-z0-9]/gi, ""); if (!/^[a-f0-9]{32,40}$/i.test(hash)) return null; const size = formatBytes(item == null ? void 0 : item.size); - const date = (item == null ? void 0 : item.created_at) || (item == null ? void 0 : item.created_time) || (item == null ? void 0 : item.create_time) || ""; + const date2 = (item == null ? void 0 : item.created_at) || (item == null ? void 0 : item.created_time) || (item == null ? void 0 : item.create_time) || ""; return { title: title || `magnet:?xt=urn:btih:${hash}`, magnet: `magnet:?xt=urn:btih:${hash}`, size, - date + date: date2 }; }).filter(Boolean); results.length > 0 && sessionStorage.setItem(cacheKey, JSON.stringify(results)); @@ -12032,12 +36174,12 @@ ${err.stack}` : ""); }); } - parseSokitty(html, keyword) { - const doc = parseHTML(html); + parseSokitty(html2, keyword) { + const doc = parseHTML(html2); const kwNorm = String(keyword).toUpperCase().replace(/[-_\s]/g, ""); const results = []; doc.querySelectorAll(".panel.search-panel").forEach((panel) => { - var _a, _b, _c, _d; + var _a2, _b, _c, _d; const titleA = panel.querySelector("h3.panel-title > a.list-title"); if (!titleA) return; const href = titleA.getAttribute("href") || ""; @@ -12048,9 +36190,9 @@ ${err.stack}` : ""); if (!title.toUpperCase().replace(/[-_\s]/g, "").includes(kwNorm)) return; const maglink = `magnet:?xt=urn:btih:${hash}`; const infoItems = [...panel.querySelectorAll(".panel-footer .info-item")]; - const size = ((_b = (_a = infoItems[0]) == null ? void 0 : _a.textContent) == null ? void 0 : _b.trim()) || ""; - const date = ((_d = (_c = infoItems[2]) == null ? void 0 : _c.textContent) == null ? void 0 : _d.trim()) || ""; - results.push({title, magnet: maglink, size, date}); + const size = ((_b = (_a2 = infoItems[0]) == null ? void 0 : _a2.textContent) == null ? void 0 : _b.trim()) || ""; + const date2 = ((_d = (_c = infoItems[2]) == null ? void 0 : _c.textContent) == null ? void 0 : _d.trim()) || ""; + results.push({title, magnet: maglink, size, date: date2}); }); return results; } @@ -12180,8 +36322,8 @@ ${err.stack}` : ""); return !!normalizedCode && normalizedText.includes(normalizedCode); }, isDetailMatched(doc, url, code) { - var _a, _b; - const title = ((_a = doc == null ? void 0 : doc.querySelector("title")) == null ? void 0 : _a.textContent) || ""; + var _a2, _b; + const title = ((_a2 = doc == null ? void 0 : doc.querySelector("title")) == null ? void 0 : _a2.textContent) || ""; const headings = [...(doc == null ? void 0 : doc.querySelectorAll("h1,h2,h3,.entry-title,.movie-title,.post-title")) || []].map((el) => el.textContent || "").join(" "); const bodyText = (((_b = doc == null ? void 0 : doc.body) == null ? void 0 : _b.textContent) || "").slice(0, 5e3); return this.isCodeMatched([url, title, headings, bodyText].join(" "), code); @@ -12203,20 +36345,20 @@ ${err.stack}` : ""); return urls.find((url) => /-1080p\./i.test(url)) || urls.find((url) => /-demosaic\./i.test(url)) || urls.find((url) => /_1\.(?:jpe?g|png|webp)$/i.test(url)) || ""; }, async javfree(code) { - var _a; + var _a2; code = this.lookupCode(code); const cacheKey = this.cacheKey(code); const cached = sessionStorage.getItem(cacheKey); if (cached) return cached; try { - const html = await gmHttp.get(`https://javfree.me/search/${code}`); - const doc = new DOMParser().parseFromString(html, "text/html"); - const link = (_a = [...doc.querySelectorAll(".entry-title>a")].find((a) => this.isCodeMatched([a.href, a.textContent].join(" "), code))) == null ? void 0 : _a.href; - if (!link) return null; - const dHtml = await gmHttp.get(link); + const html2 = await gmHttp.get(`https://javfree.me/search/${code}`); + const doc = new DOMParser().parseFromString(html2, "text/html"); + const link2 = (_a2 = [...doc.querySelectorAll(".entry-title>a")].find((a) => this.isCodeMatched([a.href, a.textContent].join(" "), code))) == null ? void 0 : _a2.href; + if (!link2) return null; + const dHtml = await gmHttp.get(link2); const dDoc = new DOMParser().parseFromString(dHtml, "text/html"); - if (!this.isDetailMatched(dDoc, link, code)) return null; - const url = this.selectJavfreePreviewUrl(dDoc, link, code); + if (!this.isDetailMatched(dDoc, link2, code)) return null; + const url = this.selectJavfreePreviewUrl(dDoc, link2, code); if (url) { sessionStorage.setItem(cacheKey, url); return url; @@ -12235,8 +36377,8 @@ ${err.stack}` : ""); const searchDoc = new DOMParser().parseFromString(searchHtml, "text/html"); const candidateLinks = searchDoc.querySelectorAll('a[href*="/"]'); const detailUrls = []; - for (const link of candidateLinks) { - const href = link.getAttribute("href"); + for (const link2 of candidateLinks) { + const href = link2.getAttribute("href"); if (!href) continue; if (href.startsWith("http") && !href.includes("javstore.net")) continue; const urlObj = new URL(href, searchUrl); @@ -12266,9 +36408,9 @@ ${err.stack}` : ""); const detailHtml = await gmHttp.get(detailUrl); const detailDoc = new DOMParser().parseFromString(detailHtml, "text/html"); if (!this.isDetailMatched(detailDoc, detailUrl, code)) return null; - for (const link of detailDoc.querySelectorAll("a")) { - if (link.textContent.includes("CLICK HERE")) { - const imgUrl = link.href || link.getAttribute("href") || ""; + for (const link2 of detailDoc.querySelectorAll("a")) { + if (link2.textContent.includes("CLICK HERE")) { + const imgUrl = link2.href || link2.getAttribute("href") || ""; if (imgUrl) return this.normalizePreviewUrl(imgUrl, detailUrl); } } @@ -12285,7 +36427,7 @@ ${err.stack}` : ""); } }, async projectjav(code) { - var _a; + var _a2; code = this.lookupCode(code); try { const request = (url) => gmHttp.get(url, {}, { @@ -12298,7 +36440,7 @@ ${err.stack}` : ""); const searchDoc = new DOMParser().parseFromString(searchHtml, "text/html"); let detailUrl = ""; const allMovieLinks = [...searchDoc.querySelectorAll('a[href*="/movie/"]')]; - const firstLink = ((_a = allMovieLinks[0]) == null ? void 0 : _a.getAttribute("href")) || ""; + const firstLink = ((_a2 = allMovieLinks[0]) == null ? void 0 : _a2.getAttribute("href")) || ""; if (firstLink) { detailUrl = firstLink.startsWith("http") ? firstLink : `https://projectjav.com${firstLink}`; } @@ -12306,8 +36448,8 @@ ${err.stack}` : ""); const detailHtml = await request(detailUrl); const detailDoc = new DOMParser().parseFromString(detailHtml, "text/html"); const screenshotLink = [...detailDoc.querySelectorAll('.col-md-12.thumbnail a[data-featherlight="image"], .thumbnail a[data-featherlight="image"]')].find((a) => { - var _a2; - return this.isCodeMatched([a.outerHTML, (_a2 = a.closest(".thumbnail")) == null ? void 0 : _a2.outerHTML, detailUrl].join(" "), code); + var _a3; + return this.isCodeMatched([a.outerHTML, (_a3 = a.closest(".thumbnail")) == null ? void 0 : _a3.outerHTML, detailUrl].join(" "), code); }); if (screenshotLink) { const thumbImg = screenshotLink.querySelector("img"); @@ -12526,8 +36668,8 @@ ${err.stack}` : ""); }); } showErrorFallback(carNum2, error) { - var _a, _b; - console.error("获取缩略图失败:", ((_b = (_a = error == null ? void 0 : error.message) == null ? void 0 : _a.substring) == null ? void 0 : _b.call(_a, 0, 100)) || error); + var _a2, _b; + console.error("获取缩略图失败:", ((_b = (_a2 = error == null ? void 0 : error.message) == null ? void 0 : _a2.substring) == null ? void 0 : _b.call(_a2, 0, 100)) || error); let differentCss = isJavBus$1 ? "margin-top:30px" : "margin-top:50px"; $(".screen-container").html( `
获取缩略图失败

点击重试 或 前往确认` @@ -12665,8 +36807,8 @@ ${err.stack}` : ""); await gmHttp.postFileFormData("https://webapi.115.com/offine/downpath", { file_id: fileId }); - const list = await getDownPathList(); - const created = list ? list.find((d) => d.file_id === fileId || String(d.file_id) === String(fileId)) : null; + const list2 = await getDownPathList(); + const created = list2 ? list2.find((d) => d.file_id === fileId || String(d.file_id) === String(fileId)) : null; return created ? created.id : null; } @@ -12749,7 +36891,7 @@ ${err.stack}` : ""); }); return; } - const sign = singInfo.sign, time = singInfo.time, userId = this.getUserId(); + const sign = singInfo.sign, time2 = singInfo.time, userId = this.getUserId(); let wp_path_id = savePath || ""; if (!wp_path_id) { const fullPath = await this.getSavePathId(); @@ -12775,24 +36917,24 @@ ${err.stack}` : ""); } } } - const result = await (async (magnet, wp_path_id2 = "", uid, sign2, time2) => { + const result = await (async (magnet, wp_path_id2 = "", uid, sign2, time3) => { const data = { url: encodeURIComponent(magnet), wp_path_id: wp_path_id2, uid, sign: sign2, - time: time2 + time: time3 }; return await gmHttp.postForm("https://115.com/web/lixian/?ct=lixian&ac=add_task_url", data); - })(magnetLink, wp_path_id, userId, sign, time); + })(magnetLink, wp_path_id, userId, sign, time2); console.log("离线下载返回值:", result); - let infoHash = result.info_hash, fileId = await this.getFileId(userId, sign, time, infoHash), + let infoHash = result.info_hash, fileId = await this.getFileId(userId, sign, time2, infoHash), openUrl = "https://115.com/?tab=offline&mode=wangpan"; fileId && (openUrl = `https://115.com/?cid=${fileId}&offset=0&mode=wangpan`); let title = "添加成功, 是否前往查看?"; false === result.state && (title = result.error_msg + " 是否前往查看?"); utils.q(null, title, (async () => { - let fileId2 = await this.getFileId(userId, sign, time, infoHash); + let fileId2 = await this.getFileId(userId, sign, time2, infoHash); fileId2 && (openUrl = `https://115.com/?cid=${fileId2}&offset=0&mode=wangpan`); window.open(openUrl); })); @@ -12821,16 +36963,17 @@ ${err.stack}` : ""); throw new Error("获取115用户Id失败"); } } - async getFileId(userId, sign, time, infoHash) { - const taskList = await (async (uid, sign2, time2) => { + + async getFileId(userId, sign, time2, infoHash) { + const taskList = await (async (uid, sign2, time3) => { const data = { page: 1, uid, sign: sign2, - time: time2 + time: time3 }; return (await gmHttp.postForm("https://115.com/web/lixian/?ct=lixian&ac=task_lists", data)).tasks; - })(userId, sign, time); + })(userId, sign, time2); console.log("云离线列表:", taskList); let fileId = null; for (let i = 0; i < taskList.length; i++) { @@ -13017,7 +37160,7 @@ ${err.stack}` : ""); const loginInfo = (await (async (loginType) => { let url = `https://qrcodeapi.115.com/api/1.0/${loginType}/1.0/token/`; return await gmHttp.get(url); - })(login115Type)).data, qrcode = loginInfo.qrcode, sign = loginInfo.sign, time = loginInfo.time, + })(login115Type)).data, qrcode = loginInfo.qrcode, sign = loginInfo.sign, time2 = loginInfo.time, uid = loginInfo.uid; console.log("生成二维码:", loginInfo); const $qrcodeBox = $("#qrcode-box"); @@ -13032,10 +37175,10 @@ ${err.stack}` : ""); loginTimeout && clearTimeout(loginTimeout); const checkLoginRecursive = async () => { try { - const loginResult = await (async (uid2, time2, sign2) => { - let url = `https://qrcodeapi.115.com/get/status/?uid=${uid2}&time=${time2}&sign=${sign2}`; + const loginResult = await (async (uid2, time3, sign2) => { + let url = `https://qrcodeapi.115.com/get/status/?uid=${uid2}&time=${time3}&sign=${sign2}`; return await gmHttp.get(url); - })(uid, time, sign); + })(uid, time2, sign); console.log("已扫码, 正在获取结果:", loginResult); let data = loginResult.data, msg = data.msg, status = data.status; if (msg) { @@ -13512,15 +37655,15 @@ ${err.stack}` : ""); for (; size >= 1024 && unit < units.length - 1;) size /= 1024, unit++; return size.toFixed(2) + " " + units[unit]; }; - let html = '
'; - html += `
作品 ${carNum2} 匹配到 ${matchList.length} 个文件夹(可删除 ${safeMatchList.length} 个):
`; + let html2 = '
'; + html2 += `
作品 ${carNum2} 匹配到 ${matchList.length} 个文件夹(可删除 ${safeMatchList.length} 个):
`; if (unsafeCount > 0) { - html += `
⚠ 已自动排除 ${unsafeCount} 个目录名不含番号的项目,防止误删
`; + html2 += `
⚠ 已自动排除 ${unsafeCount} 个目录名不含番号的项目,防止误删
`; } - html += '
'; + html2 += '
'; for (let i = 0; i < safeMatchList.length; i++) { const m = safeMatchList[i]; - html += `
+ html2 += `
`; } - html += "
"; + html2 += "
"; const layerIndex = layer.open({ type: 1, title: "删除115作品文件夹", - content: html, + content: html2, area: ["520px", "auto"], btn: ["确定删除", "取消"], shadeClose: false, yes: async (index) => { - var _a, _b; + var _a2, _b; const $layer = $(`#layui-layer${index}`); const checked = $layer.find(".jhs-delete-folder-cb:checked"); if (0 === checked.length) { @@ -13588,7 +37731,7 @@ ${err.stack}` : ""); JavPackSubtitle.cached115Matches = JavPackSubtitle.cached115Matches.filter((m) => remainingCids.has(m.cid)); JavPackSubtitle.current115Cids = JavPackSubtitle.current115Cids.filter((cid) => remainingCids.has(cid)); try { - (_b = (_a = this.getBean("WangPan115TaskPlugin")).deleteOfflineTasksByKeyword) == null ? void 0 : _b.call(_a, carNum2); + (_b = (_a2 = this.getBean("WangPan115TaskPlugin")).deleteOfflineTasksByKeyword) == null ? void 0 : _b.call(_a2, carNum2); } catch (e) { console.warn("删除离线任务暂不可用:", e.message); } @@ -14409,7 +38552,7 @@ ${err.stack}` : ""); async loadOtherSite(carNum2, sourceCarNum) { if ("yes" !== await storageManager.getSetting("enableLoadOtherSite", "yes")) return; carNum2 || (carNum2 = this.getPageInfo().carNum); - const enabledSites = this.getEnabledSites(), html = ` + const enabledSites = this.getEnabledSites(), html2 = `
${this.siteConfigs.map(((config) => { @@ -14426,8 +38569,8 @@ ${err.stack}` : "");
`; - $(".movie-panel-info").append(html); - $(".container .info").append(html); + $(".movie-panel-info").append(html2); + $(".container .info").append(html2); $("#javTrailersBtn").on("click", (async (event) => { event.preventDefault(); let settingObj = await storageManager.getSetting(); @@ -14465,7 +38608,7 @@ ${err.stack}` : ""); } const baseUrl = await config.getBaseUrl(), searchUrl = config.searchPath(baseUrl, carNum2); $btn.attr("href", searchUrl); - const html = await gmHttp.get(searchUrl, null, config.headers, true), $dom = utils.htmlTo$dom(html), + const html2 = await gmHttp.get(searchUrl, null, config.headers, true), $dom = utils.htmlTo$dom(html2), resultUrlList = []; $dom.find(config.itemSelector).each(((index, element) => { const $box2 = $(element); @@ -15408,13 +39551,13 @@ ${err.stack}` : ""); return gmHttp.get(url); })), htmlResults = await Promise.all(fetchPromises); let dataList = []; - for (const html of htmlResults) { - let $dom = $(html); + for (const html2 of htmlResults) { + let $dom = $(html2); $dom.find(".box-item").each(((index, element) => { const $item = $(element), imgSrc = $item.find("img").attr("data-src"); let carNum2 = $item.find("img").attr("title"); - const detailLink = $item.find(".detail a"), link = detailLink.attr("href"), - href = baseUrl + (link.startsWith("/") ? link : "/" + link), + const detailLink = $item.find(".detail a"), link2 = detailLink.attr("href"), + href = baseUrl + (link2.startsWith("/") ? link2 : "/" + link2), title = detailLink.text().trim().replace(carNum2 + " - ", ""); carNum2 = carNum2.replace("FC2-PPV", "FC2"); dataList.push({ @@ -15620,8 +39763,8 @@ ${err.stack}` : ""); })); } async get123AvVideoInfo(href) { - const html = await gmHttp.get(href), match = html.match(/v-scope="Movie\({id:\s*(\d+),/), - id = match ? match[1] : null, $dom = utils.htmlTo$dom(html); + const html2 = await gmHttp.get(href), match = html2.match(/v-scope="Movie\({id:\s*(\d+),/), + id = match ? match[1] : null, $dom = utils.htmlTo$dom(html2); return { id, publishDate: $dom.find('span:contains("リリース日:")').next("span").text(), @@ -15631,7 +39774,8 @@ ${err.stack}` : ""); } async getActressInfo(fc2Num) { let url = `https://fc2ppvdb.com/articles/${fc2Num.replace("FC2-", "")}`; - const html = await gmHttp.get(url), $dom = $(html), actressNodeList = $dom.find("div").filter((function () { + const html2 = await gmHttp.get(url), $dom = $(html2), + actressNodeList = $dom.find("div").filter((function () { return 0 === $(this).text().trim().indexOf("女優:"); })); if (0 === actressNodeList.length || actressNodeList.length > 1) { @@ -15665,10 +39809,10 @@ ${err.stack}` : ""); async getImgList(fc2Num) { let tempCarNum = fc2Num.replace("FC2-", ""), url = `https://adult.contents.fc2.com/article/${fc2Num.replace("FC2-", "")}/`; - const html = await gmHttp.get(url, null, { + const html2 = await gmHttp.get(url, null, { referer: url }); - let imgList = $(html).find(".items_article_SampleImagesArea img").map((function () { + let imgList = $(html2).find(".items_article_SampleImagesArea img").map((function () { return $(this).attr("src"); })).get(), imagesHtml = ""; Array.isArray(imgList) && imgList.length > 0 ? imagesHtml = imgList.map(((img, index) => ` @@ -16407,7 +40551,7 @@ ${err.stack}` : ""); } async openBlacklistDialog() { const taskPlugin = this.getBean("TaskPlugin"), settingObj = await storageManager.getSetting(); - let html = ` + let html2 = `
@@ -16443,7 +40587,7 @@ ${err.stack}` : ""); layer.open({ type: 1, title: "演员黑名单", - content: html, + content: html2, scrollbar: false, area: utils.getResponsiveArea(["80%", "90%"]), anim: -1, @@ -16771,8 +40915,8 @@ ${err.stack}` : ""); if (nextPageLink) { show.info("请不要关闭窗口, 正在解析下一页:" + nextPageLink); await new Promise(((resolve) => setTimeout(resolve, 500))); - const html = await gmHttp.get(nextPageLink), parser = new DOMParser(), - next$dom = $(parser.parseFromString(html, "text/html")); + const html2 = await gmHttp.get(nextPageLink), parser = new DOMParser(), + next$dom = $(parser.parseFromString(html2, "text/html")); await this.filterAllVideo(actorName, next$dom); } else { show.ok("执行结束!"); @@ -16789,15 +40933,15 @@ ${err.stack}` : ""); const pageNum = utils.getUrlParam(nextPageLink, "page") || 0, beyond60Plugin = this.getBean("Beyond60Plugin"); if (isJavDb$1 && beyond60Plugin && pageNum > 60) { - let {html, nextUrl, hasMore} = await beyond60Plugin.handleBeyond60(nextPageLink), mergeHtml = ` -
${html}
+ let {html: html2, nextUrl, hasMore} = await beyond60Plugin.handleBeyond60(nextPageLink), mergeHtml = ` +
${html2}
${nextUrl ? `` : ""} `; next$dom = utils.htmlTo$dom(mergeHtml); } else { clog.log("正在请求下一页内容:", nextPageLink); - const html = await gmHttp.get(nextPageLink); - next$dom = utils.htmlTo$dom(html); + const html2 = await gmHttp.get(nextPageLink); + next$dom = utils.htmlTo$dom(html2); } await this.filterActorVideo(actorName, starId, next$dom); } else { @@ -17107,8 +41251,12 @@ ${err.stack}` : ""); if (isJavBus$1 && $box2.find(".avatar-box").length > 0) return; const boxInfo = this.getBoxCarInfo($box2); if (!boxInfo) return; - const {carNum: carNum2, title} = boxInfo, {filter, favorite, hasDown, hasWatch} = carNumSets, - isFavorite = favorite.has(carNum2), isHasDown = hasDown.has(carNum2), + const {carNum: carNum2, title} = boxInfo, { + filter, + favorite, + hasDown, + hasWatch + } = carNumSets, isFavorite = favorite.has(carNum2), isHasDown = hasDown.has(carNum2), isHasWatch = hasWatch.has(carNum2), isFiltered = filter.has(carNum2), isFilterActorMale = actorCarNumToNameMap.has(carNum2), isFilterActorFemale = actressCarNumToNameMap.has(carNum2), @@ -17298,7 +41446,7 @@ ${err.stack}` : ""); if (await storageManager.getSetting("enableSaveActressCarInfo", NO$1) === YES$1) { clog.debug("鉴定补录演员信息-已启用, 开始解析详情页"); clog.debug("开始解析演员详情页", url); - const html = await gmHttp.get(url), $dom = utils.htmlTo$dom(html); + const html2 = await gmHttp.get(url), $dom = utils.htmlTo$dom(html2); isJavDb$1 ? actorName = $dom.find(".female").prev().map(((i, el) => $(el).text())).get().join(" ") : isJavBus$1 && (actorName = $dom.find('span[onmouseover*="star_"] a').map(((i, el) => $(el).text())).get().join(" ")); clog.debug("解析到名称:", actorName); } @@ -17609,7 +41757,7 @@ ${err.stack}` : ""); minWidth: "150px", textAlign: "center", zIndex: 999999999 - }, defaultConfig = { + }, defaultConfig2 = { text: msg, duration: 1e3, close: false, @@ -17633,8 +41781,8 @@ ${err.stack}` : ""); oldestFirst: false, ...finalOptions }; - -1 === defaultConfig.duration && (defaultConfig.close = true); - const toast = Toastify(defaultConfig); + -1 === defaultConfig2.duration && (defaultConfig2.close = true); + const toast = Toastify(defaultConfig2); toast.showToast(); toast.closeShow = () => { toast.toastElement.remove(); diff --git a/package.json b/package.json index 2d4527d..b1485c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jhs-enhance", - "version": "3.3.16", + "version": "3.3.17", "description": "Jav-鉴黄师 油猴脚本 - 工程化版本", "type": "module", "scripts": { diff --git a/vite.config.mjs b/vite.config.mjs index d649359..04a1514 100644 --- a/vite.config.mjs +++ b/vite.config.mjs @@ -8,7 +8,7 @@ export default defineConfig({ userscript: { name: 'JHS-enhance', namespace: 'JHS-enhance', - version: '3.3.16', + version: '3.3.17', author: 'xiebro,fireinrain', description: 'Jav-鉴黄师 增强脚本。列表页:作品状态标签、一键筛选、新作品检测、演员黑名单过滤;详情页:磁力链接高亮、DMM 多画质预览视频、标题翻译、整合字幕搜索(迅雷+SubTitleCat)并支持 115 直传、多源预览图(javfree/projectjav/javstore)含来源切换;数据:115 网盘目录匹配与多目录选择、云盘备份/恢复、跨 Tab 同步;其他:自动翻页、分类折叠、Top250、以图识图、热门榜单、评论查看、相关清单。支持 JavDB / JavBus / JavSee / SeeJav / FC2 / JavTrailers', license: 'MIT', @@ -38,7 +38,6 @@ export default defineConfig({ ], require: [ 'https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js', - 'https://cdn.jsdelivr.net/npm/tabulator-tables@6.5.2/dist/js/tabulator.min.js', 'https://cdn.jsdelivr.net/npm/layui-layer@1.0.9/dist/layer.min.js', 'https://cdn.jsdelivr.net/npm/blueimp-md5@2.19.0/js/md5.min.js', 'https://cdn.jsdelivr.net/npm/toastify-js@1.12.0/src/toastify.min.js', @@ -96,7 +95,6 @@ export default defineConfig({ 'localforage': 'localforage', 'toastify-js': 'Toastify', 'blueimp-md5': 'md5', - 'tabulator-tables': 'Tabulator', 'viewerjs': 'Viewer', 'qrcodejs': 'QRCode', },