UNPKG

@limetech/lime-elements

Version:
2,146 lines (1,687 loc) • 830 kB
import { r as registerInstance, c as createEvent, h, H as Host, a as getElement } from './index-DBTJNfo7.js'; import { h as hasPath, c as castPath, a as toKey, d as baseGet, e as arrayMap, b as baseIteratee } from './_baseIteratee-1mEitKxK.js'; import { a as assignValue } from './_assignValue-DkGAX8ec.js'; import { b as isArrayLike, a as isIndex } from './isArrayLike-bWHU4ebg.js'; import { i as isObject } from './isObject-BJQylLSL.js'; import { f as isPrototype, m as arrayLikeKeys, n as stubArray, l as arrayPush, p as getSymbols, q as baseGetAllKeys } from './_baseIsEqual-DEKrwcEh.js'; import { g as getPrototype } from './_getPrototype-C17KNemI.js'; import { n as negate } from './negate-ooVD-6_a.js'; import { _ as _mapLayout } from './layout-C4zsCPOF.js'; import { i as isEqual } from './isEqual-m-UUey98.js'; import { t as translate } from './translations-DVRaJQvC.js'; import './isArray-B8VKuhvH.js'; import './isSymbol-ClAke5ga.js'; import './isObjectLike-oiMYqRQ0.js'; import './identity-CK4jS9_E.js'; import './_baseAssignValue-C8Uwn8zr.js'; import './_defineProperty-yVdnnt__.js'; import './_getNative-aN4R8EiP.js'; import './eq-D7VMHFyO.js'; /** * This function is like * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) * except that it includes inherited enumerable properties. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function nativeKeysIn(object) { var result = []; if (object != null) { for (var key in Object(object)) { result.push(key); } } return result; } /** Used for built-in method references. */ var objectProto$1 = Object.prototype; /** Used to check objects for own properties. */ var hasOwnProperty$1 = objectProto$1.hasOwnProperty; /** * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeysIn(object) { if (!isObject(object)) { return nativeKeysIn(object); } var isProto = isPrototype(object), result = []; for (var key in object) { if (!(key == 'constructor' && (isProto || !hasOwnProperty$1.call(object, key)))) { result.push(key); } } return result; } /** * Creates an array of the own and inherited enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ * @since 3.0.0 * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keysIn(new Foo); * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ function keysIn(object) { return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); } /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeGetSymbols = Object.getOwnPropertySymbols; /** * Creates an array of the own and inherited enumerable symbols of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of symbols. */ var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { var result = []; while (object) { arrayPush(result, getSymbols(object)); object = getPrototype(object); } return result; }; /** * Creates an array of own and inherited enumerable property names and * symbols of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names and symbols. */ function getAllKeysIn(object) { return baseGetAllKeys(object, keysIn, getSymbolsIn); } /** Used for built-in method references. */ var objectProto = Object.prototype; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** * The base implementation of `_.has` without support for deep paths. * * @private * @param {Object} [object] The object to query. * @param {Array|string} key The key to check. * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHas(object, key) { return object != null && hasOwnProperty.call(object, key); } /** * Checks if `path` is a direct property of `object`. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path to check. * @returns {boolean} Returns `true` if `path` exists, else `false`. * @example * * var object = { 'a': { 'b': 2 } }; * var other = _.create({ 'a': _.create({ 'b': 2 }) }); * * _.has(object, 'a'); * // => true * * _.has(object, 'a.b'); * // => true * * _.has(object, ['a', 'b']); * // => true * * _.has(other, 'a'); * // => false */ function has(object, path) { return object != null && hasPath(object, path, baseHas); } /** * The base implementation of `_.set`. * * @private * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. * @param {*} value The value to set. * @param {Function} [customizer] The function to customize path creation. * @returns {Object} Returns `object`. */ function baseSet(object, path, value, customizer) { if (!isObject(object)) { return object; } path = castPath(path, object); var index = -1, length = path.length, lastIndex = length - 1, nested = object; while (nested != null && ++index < length) { var key = toKey(path[index]), newValue = value; if (key === '__proto__' || key === 'constructor' || key === 'prototype') { return object; } if (index != lastIndex) { var objValue = nested[key]; newValue = undefined; if (newValue === undefined) { newValue = isObject(objValue) ? objValue : (isIndex(path[index + 1]) ? [] : {}); } } assignValue(nested, key, newValue); nested = nested[key]; } return object; } /** * The base implementation of `_.pickBy` without support for iteratee shorthands. * * @private * @param {Object} object The source object. * @param {string[]} paths The property paths to pick. * @param {Function} predicate The function invoked per property. * @returns {Object} Returns the new object. */ function basePickBy(object, paths, predicate) { var index = -1, length = paths.length, result = {}; while (++index < length) { var path = paths[index], value = baseGet(object, path); if (predicate(value, path)) { baseSet(result, castPath(path, object), value); } } return result; } /** * Creates an object composed of the `object` properties `predicate` returns * truthy for. The predicate is invoked with two arguments: (value, key). * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The source object. * @param {Function} [predicate=_.identity] The function invoked per property. * @returns {Object} Returns the new object. * @example * * var object = { 'a': 1, 'b': '2', 'c': 3 }; * * _.pickBy(object, _.isNumber); * // => { 'a': 1, 'c': 3 } */ function pickBy(object, predicate) { if (object == null) { return {}; } var props = arrayMap(getAllKeysIn(object), function(prop) { return [prop]; }); predicate = baseIteratee(predicate); return basePickBy(object, props, function(value, path) { return predicate(value, path[0]); }); } /* Tabulator v6.3.1 (c) Oliver Folkerd 2025 */ class CoreFeature{ constructor(table){ this.table = table; } ////////////////////////////////////////// /////////////// DataLoad ///////////////// ////////////////////////////////////////// reloadData(data, silent, columnsChanged){ return this.table.dataLoader.load(data, undefined, undefined, undefined, 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 ///////////////// ////////////////////////////////////////// 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, list = []){ 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 = list.findIndex((item) => { return item.subject === subject; }); if(match > -1){ clone[i] = list[match].copy; }else { copy = Object.assign(Array.isArray(subject) ? [] : {}, subject); list.unshift({subject, copy}); clone[i] = this.deepClone(subject, copy, list); } } } return clone; } } let Popup$1 = class Popup extends CoreFeature{ constructor(table, element, parent){ super(table); this.element = element; this.container = this._lookupContainer(); this.parent = parent; 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; //move menu to start on right edge if it is too close to the edge of the screen 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; } //move menu to start on bottom edge if it is too close to the edge of the screen 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 { this.element.style.height = offsetHeight + "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; } _escapeCheck(e){ if(e.keyCode == 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, name){ super(table); this._handler = null; } initialize(){ // setup module when table is initialized, to be overridden in module } /////////////////////////////////// ////// 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(name, func){ if(typeof this.table[name] === "undefined"){ this.table[name] = (...args) => { this.table.initGuard(name); return func(...args); }; }else { console.warn("Unable to bind table function, name already in use", name); } } 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(); } }; class Accessor extends Module{ static moduleName = "accessor"; //load defaults static accessors = defaultAccessors; constructor(table){ super(table); this.allowedTypes = ["", "data", "download", "clipboard", "print", "htmlOutput"]; //list of accessor types 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:accessor, params: column.definition[key + "Params"] || {}, }; } } }); if(match){ column.modules.accessor = config; } } lookupAccessor(value){ var accessor = false; //set column accessor 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(); //clone data object with deep copy to isolate internal data from returned result 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; } } 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) => { //set url url = this.urlGenerator.call(this.table, url, config, params); //set body content if not GET request 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){ //configure headers 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'; } } //send request 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; }, }, }; class Ajax extends Module{ static moduleName = "ajax"; //load defaults static defaultConfig = defaultConfig; static defaultURLGenerator = urlBuilder; static defaultLoaderPromise = defaultLoaderPromise; static contentTypeFormatters = defaultContentTypeFormatters; constructor(table){ super(table); this.config = {}; //hold config object for ajax request this.url = ""; //request URL this.urlGenerator = false; this.params = false; //request parameters this.loaderPromise = false; this.registerTableOption("ajaxURL", false); //url for ajax loading this.registerTableOption("ajaxURLGenerator", false); this.registerTableOption("ajaxParams", {}); //params for ajax loading this.registerTableOption("ajaxConfig", "get"); //ajax request type this.registerTableOption("ajaxContentType", "form"); //ajax request type this.registerTableOption("ajaxRequestFunc", false); //promise function 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(); } } } 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 = [], rows = []; //get data from clipboard into array of columns and rows. clipboard = clipboard.split("\n"); clipboard.forEach(function(row){ data.push(row.split("\t")); }); if(data.length && !(data.length === 1 && data[0].length < 2)){ //check if headers are present by title data[0].forEach(function(value){ var column = columns.find(function(column){ return value && column.definition.title && value.trim() && column.definition.title.trim() === value.trim(); }); if(column){ columnMap.push(column); }else { headerFindSuccess = false; } }); //check if column headers are present by field if(!headerFindSuccess){ headerFindSuccess = true; columnMap = []; data[0].forEach(function(value){ var column = columns.find(function(column){ return value && column.field && value.trim() && column.field.trim() === value.trim(); }); if(column){ columnMap.push(column); }else { headerFindSuccess = false; } }); if(!headerFindSuccess){ columnMap = this.table.columnManager.columnsByIndex; } } //remove header row if found if(headerFindSuccess){ data.shift(); } data.forEach(function(item){ var row = {}; item.forEach(function(value, i){ if(columnMap[i]){ row[columnMap[i].field] = value; } }); rows.push(row); }); return rows; }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 }, }; class Clipboard extends Module{ static moduleName = "clipboard"; static moduleExtensions = extensions$4; //load defaults static pasteActions = defaultPasteActions; static pasteParsers = defaultPasteParsers; constructor(table){ super(table); this.mode = true; this.pasteParser = function(){}; this.pasteAction = function(){}; this.customSelection = false; this.rowRange = false; this.blocked = true; //block copy actions not originating from this command this.registerTableOption("clipboard", false); //enable clipboard this.registerTableOption("clipboardCopyStyled", true); //formatted table data this.registerTableOption("clipboardCopyConfig", false); //clipboard config this.registerTableOption("clipboardCopyFormatter", false); //DEPRECATED - REMOVE in 5.0 this.registerTableOption("clipboardCopyRowRange", "active"); //restrict clipboard to visible rows only this.registerTableOption("clipboardPasteParser", "table"); //convert pasted clipboard data to rows this.registerTableOption("clipboardPasteAction", "insert"); //how to insert pasted data into the table 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, html, list; if(!this.blocked){ e.preventDefault(); if(this.customSelection){ plain = this.customSelection; if(this.table.options.clipboardCopyFormatter){ plain = this.table.options.clipboardCopyFormatter("plain", plain); } }else { list = this.table.modules.export.generateExportList(this.table.options.clipboardCopyConfig, this.table.options.clipboardCopyStyled, this.rowRange, "clipboard"); html = this.table.modules.export.generateHTMLTable(list); plain = html ? this.generatePlainContent(list) : ""; if(this.table.options.clipboardCopyFormatter){ plain = this.table.options.clipboardCopyFormatter("plain", plain); html = this.table.options.clipboardCopyFormatter("html", html); } } 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(html){ e.clipboardData.setData('text/html', html); } } else if (e.originalEvent && e.originalEvent.clipboardData.setData) { e.originalEvent.clipboardData.setData('text/plain', plain); if(html){ e.originalEvent.clipboardData.setData('text/html', html); } } this.dispatchExternal("clipboardCopied", plain, html); 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 (list) { var output = []; list.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("\t")); }); return output.join("\n"); } copy (range, internal) { var sel, textRange; this.blocked = false; this.customSelection = false; if (this.mode === true || this.mode === "copy") { this.rowRange = range || this.table.options.clipboardCopyRowRange; if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") { range = document.createRange(); range.selectNodeContents(this.table.element); sel = window.getSelection(); if (sel.toString() && internal) { this.customSelection = sel.toString(); } sel.removeAllRanges(); sel.addRange(range); } 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, rows; 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); } rows = this.pasteAction.call(this, rowData); this.dispatchExternal("clipboardPasted", data, rowData, rows); }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; } } class CalcComponent{ constructor (row){ this._row = row; return new Proxy(this, { get: function(target, name, receiver) { if (typeof target[name] !== "undefined") { return target[name]; }else { return target._row.table.componentFunctionBinder.handle("row", target._row, name); } } }); } 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; } } //public cell object class CellComponent { constructor (cell){ this._cell = cell; return new Proxy(this, { get: function(target, name, receiver) { if (typeof target[name] !== "undefined") { return target[name]; }else { return target._cell.table.componentFunctionBinder.handle("cell", target._cell, name); } } }); } 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.oldValue = null; this.modules = {}; this.height = null; this.width = null; this.minWidth = null; this.component = null; this.loaded = false; //track if the cell has been added to the DOM yet 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", }; //set text alignment 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); } //add class to cell if needed if(this.column.definition.cssClass){ var classNames = this.column.definition.cssClass.split(" "); classNames.forEach((className) => { element.classList.add(className); }); } this.dispatch("cell-init", this); //hide cell if not visible 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){ //clear previous cell contents 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(){ // var height = this.element.css("height"); 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.tabl