UNPKG

tabulator-tables

Version:

Interactive table generation JavaScript library

2,582 lines (1,467 loc) 520 kB
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /* Tabulator v4.3.0 (c) Oliver Folkerd */ ;(function (global, factory) { if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' && typeof module !== 'undefined') { module.exports = factory(); } else if (typeof define === 'function' && define.amd) { define(factory); } else { global.Tabulator = factory(); } })(this, function () { 'use strict'; // https://tc39.github.io/ecma262/#sec-array.prototype.findIndex if (!Array.prototype.findIndex) { Object.defineProperty(Array.prototype, 'findIndex', { value: function value(predicate) { // 1. Let O be ? ToObject(this value). if (this == null) { throw new TypeError('"this" is null or not defined'); } var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception. if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. var thisArg = arguments[1]; // 5. Let k be 0. var k = 0; // 6. Repeat, while k < len while (k < len) { // a. Let Pk be ! ToString(k). // b. Let kValue be ? Get(O, Pk). // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). // d. If testResult is true, return k. var kValue = o[k]; if (predicate.call(thisArg, kValue, k, o)) { return k; } // e. Increase k by 1. k++; } // 7. Return -1. return -1; } }); } // https://tc39.github.io/ecma262/#sec-array.prototype.find if (!Array.prototype.find) { Object.defineProperty(Array.prototype, 'find', { value: function value(predicate) { // 1. Let O be ? ToObject(this value). if (this == null) { throw new TypeError('"this" is null or not defined'); } var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception. if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. var thisArg = arguments[1]; // 5. Let k be 0. var k = 0; // 6. Repeat, while k < len while (k < len) { // a. Let Pk be ! ToString(k). // b. Let kValue be ? Get(O, Pk). // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). // d. If testResult is true, return kValue. var kValue = o[k]; if (predicate.call(thisArg, kValue, k, o)) { return kValue; } // e. Increase k by 1. k++; } // 7. Return undefined. return undefined; } }); } var ColumnManager = function ColumnManager(table) { this.table = table; //hold parent table this.blockHozScrollEvent = false; this.headersElement = this.createHeadersElement(); this.element = this.createHeaderElement(); //containing element this.rowManager = null; //hold row manager object this.columns = []; // column definition object this.columnsByIndex = []; //columns by index this.columnsByField = {}; //columns by field this.scrollLeft = 0; this.element.insertBefore(this.headersElement, this.element.firstChild); }; ////////////// Setup Functions ///////////////// ColumnManager.prototype.createHeadersElement = function () { var el = document.createElement("div"); el.classList.add("tabulator-headers"); return el; }; ColumnManager.prototype.createHeaderElement = function () { var el = document.createElement("div"); el.classList.add("tabulator-header"); if (!this.table.options.headerVisible) { el.classList.add("tabulator-header-hidden"); } return el; }; ColumnManager.prototype.initialize = function () { var self = this; //scroll body along with header // self.element.addEventListener("scroll", function(e){ // if(!self.blockHozScrollEvent){ // self.table.rowManager.scrollHorizontal(self.element.scrollLeft); // } // }); }; //link to row manager ColumnManager.prototype.setRowManager = function (manager) { this.rowManager = manager; }; //return containing element ColumnManager.prototype.getElement = function () { return this.element; }; //return header containing element ColumnManager.prototype.getHeadersElement = function () { return this.headersElement; }; // ColumnManager.prototype.tempScrollBlock = function(){ // clearTimeout(this.blockHozScrollEvent); // this.blockHozScrollEvent = setTimeout(() => {this.blockHozScrollEvent = false;}, 50); // } //scroll horizontally to match table body ColumnManager.prototype.scrollHorizontal = function (left) { var hozAdjust = 0, scrollWidth = this.element.scrollWidth - this.table.element.clientWidth; // this.tempScrollBlock(); this.element.scrollLeft = left; //adjust for vertical scrollbar moving table when present if (left > scrollWidth) { hozAdjust = left - scrollWidth; this.element.style.marginLeft = -hozAdjust + "px"; } else { this.element.style.marginLeft = 0; } //keep frozen columns fixed in position //this._calcFrozenColumnsPos(hozAdjust + 3); this.scrollLeft = left; if (this.table.modExists("frozenColumns")) { this.table.modules.frozenColumns.scrollHorizontal(); } }; ///////////// Column Setup Functions ///////////// ColumnManager.prototype.generateColumnsFromRowData = function (data) { var cols = [], row, sorter; if (data && data.length) { row = data[0]; for (var key in row) { var col = { field: key, title: key }; var value = row[key]; switch (typeof value === 'undefined' ? 'undefined' : _typeof(value)) { case "undefined": sorter = "string"; break; case "boolean": sorter = "boolean"; break; case "object": if (Array.isArray(value)) { sorter = "array"; } else { sorter = "string"; } break; default: if (!isNaN(value) && value !== "") { sorter = "number"; } else { if (value.match(/((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+$/i)) { sorter = "alphanum"; } else { sorter = "string"; } } break; } col.sorter = sorter; cols.push(col); } this.table.options.columns = cols; this.setColumns(this.table.options.columns); } }; ColumnManager.prototype.setColumns = function (cols, row) { var self = this; while (self.headersElement.firstChild) { self.headersElement.removeChild(self.headersElement.firstChild); }self.columns = []; self.columnsByIndex = []; self.columnsByField = {}; //reset frozen columns if (self.table.modExists("frozenColumns")) { self.table.modules.frozenColumns.reset(); } cols.forEach(function (def, i) { self._addColumn(def); }); self._reIndexColumns(); if (self.table.options.responsiveLayout && self.table.modExists("responsiveLayout", true)) { self.table.modules.responsiveLayout.initialize(); } self.redraw(true); }; ColumnManager.prototype._addColumn = function (definition, before, nextToColumn) { var column = new Column(definition, this), colEl = column.getElement(), index = nextToColumn ? this.findColumnIndex(nextToColumn) : nextToColumn; if (nextToColumn && index > -1) { var parentIndex = this.columns.indexOf(nextToColumn.getTopColumn()); var nextEl = nextToColumn.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()); } } return column; }; ColumnManager.prototype.registerColumnField = function (col) { if (col.definition.field) { this.columnsByField[col.definition.field] = col; } }; ColumnManager.prototype.registerColumnPosition = function (col) { this.columnsByIndex.push(col); }; ColumnManager.prototype._reIndexColumns = function () { this.columnsByIndex = []; this.columns.forEach(function (column) { column.reRegisterPosition(); }); }; //ensure column headers take up the correct amount of space in column groups ColumnManager.prototype._verticalAlignHeaders = function () { var self = this, minHeight = 0; self.columns.forEach(function (column) { var height; column.clearVerticalAlign(); height = column.getHeight(); if (height > minHeight) { minHeight = height; } }); self.columns.forEach(function (column) { column.verticalAlign(self.table.options.columnVertAlign, minHeight); }); self.rowManager.adjustTableSize(); }; //////////////// Column Details ///////////////// ColumnManager.prototype.findColumn = function (subject) { var self = this; if ((typeof subject === 'undefined' ? 'undefined' : _typeof(subject)) == "object") { if (subject instanceof Column) { //subject is column element return subject; } else if (subject instanceof ColumnComponent) { //subject is public column component return subject._getSelf() || false; } else if (typeof HTMLElement !== "undefined" && subject instanceof HTMLElement) { //subject is a HTML element of the column header var match = self.columns.find(function (column) { return column.element === subject; }); return match || false; } } else { //subject should be treated as the field name of the column return this.columnsByField[subject] || false; } //catch all for any other type of input return false; }; ColumnManager.prototype.getColumnByField = function (field) { return this.columnsByField[field]; }; ColumnManager.prototype.getColumnByIndex = function (index) { return this.columnsByIndex[index]; }; ColumnManager.prototype.getFirstVisibileColumn = function (index) { var index = this.columnsByIndex.findIndex(function (col) { return col.visible; }); return index > -1 ? this.columnsByIndex[index] : false; }; ColumnManager.prototype.getColumns = function () { return this.columns; }; ColumnManager.prototype.findColumnIndex = function (column) { return this.columnsByIndex.findIndex(function (col) { return column === col; }); }; //return all columns that are not groups ColumnManager.prototype.getRealColumns = function () { return this.columnsByIndex; }; //travers across columns and call action ColumnManager.prototype.traverse = function (callback) { var self = this; self.columnsByIndex.forEach(function (column, i) { callback(column, i); }); }; //get defintions of actual columns ColumnManager.prototype.getDefinitions = function (active) { var self = this, output = []; self.columnsByIndex.forEach(function (column) { if (!active || active && column.visible) { output.push(column.getDefinition()); } }); return output; }; //get full nested definition tree ColumnManager.prototype.getDefinitionTree = function () { var self = this, output = []; self.columns.forEach(function (column) { output.push(column.getDefinition(true)); }); return output; }; ColumnManager.prototype.getComponents = function (structured) { var self = this, output = [], columns = structured ? self.columns : self.columnsByIndex; columns.forEach(function (column) { output.push(column.getComponent()); }); return output; }; ColumnManager.prototype.getWidth = function () { var width = 0; this.columnsByIndex.forEach(function (column) { if (column.visible) { width += column.getWidth(); } }); return width; }; ColumnManager.prototype.moveColumn = function (from, to, after) { this._moveColumnInArray(this.columns, from, to, after); this._moveColumnInArray(this.columnsByIndex, from, to, after, true); if (this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { this.table.modules.responsiveLayout.initialize(); } if (this.table.options.columnMoved) { this.table.options.columnMoved.call(this.table, from.getComponent(), this.table.columnManager.getComponents()); } if (this.table.options.persistentLayout && this.table.modExists("persistence", true)) { this.table.modules.persistence.save("columns"); } }; ColumnManager.prototype._moveColumnInArray = function (columns, from, to, after, updateRows) { var fromIndex = columns.indexOf(from), toIndex; 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) { this.table.rowManager.rows.forEach(function (row) { if (row.cells.length) { var cell = row.cells.splice(fromIndex, 1)[0]; row.cells.splice(toIndex, 0, cell); } }); } } }; ColumnManager.prototype.scrollToColumn = function (column, position, ifVisible) { var _this = this; var left = 0, offset = 0, adjust = 0, colEl = column.getElement(); return new Promise(function (resolve, reject) { if (typeof position === "undefined") { position = _this.table.options.scrollToColumnPosition; } if (typeof ifVisible === "undefined") { ifVisible = _this.table.options.scrollToColumnIfVisible; } if (column.visible) { //align to correct position switch (position) { case "middle": case "center": adjust = -_this.element.clientWidth / 2; break; case "right": adjust = colEl.clientWidth - _this.headersElement.clientWidth; break; } //check column visibility if (!ifVisible) { offset = colEl.offsetLeft; if (offset > 0 && offset + colEl.offsetWidth < _this.element.clientWidth) { return false; } } //calculate scroll position left = colEl.offsetLeft + _this.element.scrollLeft + 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 ///////////////// ColumnManager.prototype.generateCells = function (row) { var self = this; var cells = []; self.columnsByIndex.forEach(function (column) { cells.push(column.generateCell(row)); }); return cells; }; //////////////// Column Management ///////////////// ColumnManager.prototype.getFlexBaseWidth = function () { var self = this, totalWidth = self.table.element.clientWidth, //table element width fixedWidth = 0; //adjust for vertical scrollbar if present if (self.rowManager.element.scrollHeight > self.rowManager.element.clientHeight) { totalWidth -= self.rowManager.element.offsetWidth - self.rowManager.element.clientWidth; } this.columnsByIndex.forEach(function (column) { var width, minWidth, colWidth; if (column.visible) { width = column.definition.width || 0; minWidth = typeof column.minWidth == "undefined" ? self.table.options.columnMinWidth : 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; }; ColumnManager.prototype.addColumn = function (definition, before, nextToColumn) { var column = this._addColumn(definition, before, nextToColumn); this._reIndexColumns(); if (this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { this.table.modules.responsiveLayout.initialize(); } if (this.table.modExists("columnCalcs")) { this.table.modules.columnCalcs.recalc(this.table.rowManager.activeRows); } this.redraw(); if (this.table.modules.layout.getMode() != "fitColumns") { column.reinitializeWidth(); } this._verticalAlignHeaders(); this.table.rowManager.reinitialize(); }; //remove column from system ColumnManager.prototype.deregisterColumn = function (column) { var field = column.getField(), index; //remove from field list if (field) { delete this.columnsByField[field]; } //remove from index list index = this.columnsByIndex.indexOf(column); if (index > -1) { this.columnsByIndex.splice(index, 1); } //remove from column list index = this.columns.indexOf(column); if (index > -1) { this.columns.splice(index, 1); } if (this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { this.table.modules.responsiveLayout.initialize(); } this.redraw(); }; //redraw columns ColumnManager.prototype.redraw = function (force) { if (force) { if (Tabulator.prototype.helpers.elVisible(this.element)) { this._verticalAlignHeaders(); } this.table.rowManager.resetScroll(); this.table.rowManager.reinitialize(); } if (this.table.modules.layout.getMode() == "fitColumns") { this.table.modules.layout.layout(); } else { if (force) { this.table.modules.layout.layout(); } else { if (this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { this.table.modules.responsiveLayout.update(); } } } if (this.table.modExists("frozenColumns")) { this.table.modules.frozenColumns.layout(); } if (this.table.modExists("columnCalcs")) { this.table.modules.columnCalcs.recalc(this.table.rowManager.activeRows); } if (force) { if (this.table.options.persistentLayout && this.table.modExists("persistence", true)) { this.table.modules.persistence.save("columns"); } if (this.table.modExists("columnCalcs")) { this.table.modules.columnCalcs.redraw(); } } this.table.footerManager.redraw(); }; //public column object var ColumnComponent = function ColumnComponent(column) { this._column = column; this.type = "ColumnComponent"; }; ColumnComponent.prototype.getElement = function () { return this._column.getElement(); }; ColumnComponent.prototype.getDefinition = function () { return this._column.getDefinition(); }; ColumnComponent.prototype.getField = function () { return this._column.getField(); }; ColumnComponent.prototype.getCells = function () { var cells = []; this._column.cells.forEach(function (cell) { cells.push(cell.getComponent()); }); return cells; }; ColumnComponent.prototype.getVisibility = function () { return this._column.visible; }; ColumnComponent.prototype.show = function () { if (this._column.isGroup) { this._column.columns.forEach(function (column) { column.show(); }); } else { this._column.show(); } }; ColumnComponent.prototype.hide = function () { if (this._column.isGroup) { this._column.columns.forEach(function (column) { column.hide(); }); } else { this._column.hide(); } }; ColumnComponent.prototype.toggle = function () { if (this._column.visible) { this.hide(); } else { this.show(); } }; ColumnComponent.prototype.delete = function () { this._column.delete(); }; ColumnComponent.prototype.getSubColumns = function () { var output = []; if (this._column.columns.length) { this._column.columns.forEach(function (column) { output.push(column.getComponent()); }); } return output; }; ColumnComponent.prototype.getParentColumn = function () { return this._column.parent instanceof Column ? this._column.parent.getComponent() : false; }; ColumnComponent.prototype._getSelf = function () { return this._column; }; ColumnComponent.prototype.scrollTo = function () { return this._column.table.columnManager.scrollToColumn(this._column); }; ColumnComponent.prototype.getTable = function () { return this._column.table; }; ColumnComponent.prototype.headerFilterFocus = function () { if (this._column.table.modExists("filter", true)) { this._column.table.modules.filter.setHeaderFilterFocus(this._column); } }; ColumnComponent.prototype.reloadHeaderFilter = function () { if (this._column.table.modExists("filter", true)) { this._column.table.modules.filter.reloadHeaderFilter(this._column); } }; ColumnComponent.prototype.setHeaderFilterValue = function (value) { if (this._column.table.modExists("filter", true)) { this._column.table.modules.filter.setHeaderFilterValue(this._column, value); } }; ColumnComponent.prototype.getNextColumn = function () { var nextCol = this._column.nextColumn(); return nextCol ? nextCol.getComponent() : false; }; ColumnComponent.prototype.getPrevColumn = function () { var prevCol = this._column.prevColumn(); return prevCol ? prevCol.getComponent() : false; }; var Column = function Column(def, parent) { var self = this; this.table = parent.table; this.definition = def; //column definition this.parent = parent; //hold parent object this.type = "column"; //type of element this.columns = []; //child columns this.cells = []; //cells bound to this column this.element = this.createElement(); //column header element this.contentElement = false; this.groupElement = this.createGroupElement(); //column group holder element this.isGroup = false; this.tooltip = false; //hold column tooltip this.hozAlign = ""; //horizontal text alignment //multi dimentional filed handling this.field = ""; this.fieldStructure = ""; this.getFieldValue = ""; this.setFieldValue = ""; this.setField(this.definition.field); this.checkDefinition(); this.modules = {}; //hold module variables; this.cellEvents = { cellClick: false, cellDblClick: false, cellContext: false, cellTap: false, cellDblTap: false, cellTapHold: false, cellMouseEnter: false, cellMouseLeave: false, cellMouseOver: false, cellMouseOut: false, cellMouseMove: false }; this.width = null; //column width this.widthStyled = ""; //column width prestyled to improve render efficiency this.minWidth = null; //column minimum width this.minWidthStyled = ""; //column minimum prestyled to improve render efficiency this.widthFixed = false; //user has specified a width for this column this.visible = true; //default visible state this._mapDepricatedFunctionality(); //initialize column if (def.columns) { this.isGroup = true; def.columns.forEach(function (def, i) { var newCol = new Column(def, self); self.attachColumn(newCol); }); self.checkColumnVisibility(); } else { parent.registerColumnField(this); } if (def.rowHandle && this.table.options.movableRows !== false && this.table.modExists("moveRow")) { this.table.modules.moveRow.setHandle(true); } this._buildHeader(); }; Column.prototype.createElement = function () { var el = document.createElement("div"); el.classList.add("tabulator-col"); el.setAttribute("role", "columnheader"); el.setAttribute("aria-sort", "none"); return el; }; Column.prototype.createGroupElement = function () { var el = document.createElement("div"); el.classList.add("tabulator-col-group-cols"); return el; }; Column.prototype.checkDefinition = function () { var _this2 = this; Object.keys(this.definition).forEach(function (key) { if (_this2.defaultOptionList.indexOf(key) === -1) { console.warn("Invalid column definition option in '" + (_this2.field || _this2.definition.title) + "' column:", key); } }); }; Column.prototype.setField = function (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._setNesteData : this._setFlatData; }; //register column position with column manager Column.prototype.registerColumnPosition = function (column) { this.parent.registerColumnPosition(column); }; //register column position with column manager Column.prototype.registerColumnField = function (column) { this.parent.registerColumnField(column); }; //trigger position registration Column.prototype.reRegisterPosition = function () { if (this.isGroup) { this.columns.forEach(function (column) { column.reRegisterPosition(); }); } else { this.registerColumnPosition(this); } }; Column.prototype._mapDepricatedFunctionality = function () { if (typeof this.definition.hideInHtml !== "undefined") { this.definition.htmlOutput = !this.definition.hideInHtml; console.warn("hideInHtml column definition property is depricated, you should now use htmlOutput"); } }; Column.prototype.setTooltip = function () { var self = this, def = self.definition; //set header tooltips var tooltip = def.headerTooltip || def.tooltip === false ? def.headerTooltip : self.table.options.tooltipsHeader; if (tooltip) { if (tooltip === true) { if (def.field) { self.table.modules.localize.bind("columns|" + def.field, function (value) { self.element.setAttribute("title", value || def.title); }); } else { self.element.setAttribute("title", def.title); } } else { if (typeof tooltip == "function") { tooltip = tooltip(self.getComponent()); if (tooltip === false) { tooltip = ""; } } self.element.setAttribute("title", tooltip); } } else { self.element.setAttribute("title", ""); } }; //build header element Column.prototype._buildHeader = function () { var self = this, def = self.definition; while (self.element.firstChild) { self.element.removeChild(self.element.firstChild); }if (def.headerVertical) { self.element.classList.add("tabulator-col-vertical"); if (def.headerVertical === "flip") { self.element.classList.add("tabulator-col-vertical-flip"); } } self.contentElement = self._bindEvents(); self.contentElement = self._buildColumnHeaderContent(); self.element.appendChild(self.contentElement); if (self.isGroup) { self._buildGroupHeader(); } else { self._buildColumnHeader(); } self.setTooltip(); //set resizable handles if (self.table.options.resizableColumns && self.table.modExists("resizeColumns")) { self.table.modules.resizeColumns.initializeColumn("header", self, self.element); } //set resizable handles if (def.headerFilter && self.table.modExists("filter") && self.table.modExists("edit")) { if (typeof def.headerFilterPlaceholder !== "undefined" && def.field) { self.table.modules.localize.setHeaderFilterColumnPlaceholder(def.field, def.headerFilterPlaceholder); } self.table.modules.filter.initializeColumn(self); } //set resizable handles if (self.table.modExists("frozenColumns")) { self.table.modules.frozenColumns.initializeColumn(self); } //set movable column if (self.table.options.movableColumns && !self.isGroup && self.table.modExists("moveColumn")) { self.table.modules.moveColumn.initializeColumn(self); } //set calcs column if ((def.topCalc || def.bottomCalc) && self.table.modExists("columnCalcs")) { self.table.modules.columnCalcs.initializeColumn(self); } //update header tooltip on mouse enter self.element.addEventListener("mouseenter", function (e) { self.setTooltip(); }); }; Column.prototype._bindEvents = function () { var self = this, def = self.definition, dblTap, tapHold, tap; //setup header click event bindings if (typeof def.headerClick == "function") { self.element.addEventListener("click", function (e) { def.headerClick(e, self.getComponent()); }); } if (typeof def.headerDblClick == "function") { self.element.addEventListener("dblclick", function (e) { def.headerDblClick(e, self.getComponent()); }); } if (typeof def.headerContext == "function") { self.element.addEventListener("contextmenu", function (e) { def.headerContext(e, self.getComponent()); }); } //setup header tap event bindings if (typeof def.headerTap == "function") { tap = false; self.element.addEventListener("touchstart", function (e) { tap = true; }, { passive: true }); self.element.addEventListener("touchend", function (e) { if (tap) { def.headerTap(e, self.getComponent()); } tap = false; }); } if (typeof def.headerDblTap == "function") { dblTap = null; self.element.addEventListener("touchend", function (e) { if (dblTap) { clearTimeout(dblTap); dblTap = null; def.headerDblTap(e, self.getComponent()); } else { dblTap = setTimeout(function () { clearTimeout(dblTap); dblTap = null; }, 300); } }); } if (typeof def.headerTapHold == "function") { tapHold = null; self.element.addEventListener("touchstart", function (e) { clearTimeout(tapHold); tapHold = setTimeout(function () { clearTimeout(tapHold); tapHold = null; tap = false; def.headerTapHold(e, self.getComponent()); }, 1000); }, { passive: true }); self.element.addEventListener("touchend", function (e) { clearTimeout(tapHold); tapHold = null; }); } //store column cell click event bindings if (typeof def.cellClick == "function") { self.cellEvents.cellClick = def.cellClick; } if (typeof def.cellDblClick == "function") { self.cellEvents.cellDblClick = def.cellDblClick; } if (typeof def.cellContext == "function") { self.cellEvents.cellContext = def.cellContext; } //store column mouse event bindings if (typeof def.cellMouseEnter == "function") { self.cellEvents.cellMouseEnter = def.cellMouseEnter; } if (typeof def.cellMouseLeave == "function") { self.cellEvents.cellMouseLeave = def.cellMouseLeave; } if (typeof def.cellMouseOver == "function") { self.cellEvents.cellMouseOver = def.cellMouseOver; } if (typeof def.cellMouseOut == "function") { self.cellEvents.cellMouseOut = def.cellMouseOut; } if (typeof def.cellMouseMove == "function") { self.cellEvents.cellMouseMove = def.cellMouseMove; } //setup column cell tap event bindings if (typeof def.cellTap == "function") { self.cellEvents.cellTap = def.cellTap; } if (typeof def.cellDblTap == "function") { self.cellEvents.cellDblTap = def.cellDblTap; } if (typeof def.cellTapHold == "function") { self.cellEvents.cellTapHold = def.cellTapHold; } //setup column cell edit callbacks if (typeof def.cellEdited == "function") { self.cellEvents.cellEdited = def.cellEdited; } if (typeof def.cellEditing == "function") { self.cellEvents.cellEditing = def.cellEditing; } if (typeof def.cellEditCancelled == "function") { self.cellEvents.cellEditCancelled = def.cellEditCancelled; } }; //build header element for header Column.prototype._buildColumnHeader = function () { var self = this, def = self.definition, table = self.table, sortable; //set column sorter if (table.modExists("sort")) { table.modules.sort.initializeColumn(self, self.contentElement); } //set column formatter if (table.modExists("format")) { table.modules.format.initializeColumn(self); } //set column editor if (typeof def.editor != "undefined" && table.modExists("edit")) { table.modules.edit.initializeColumn(self); } //set colum validator if (typeof def.validator != "undefined" && table.modExists("validate")) { table.modules.validate.initializeColumn(self); } //set column mutator if (table.modExists("mutator")) { table.modules.mutator.initializeColumn(self); } //set column accessor if (table.modExists("accessor")) { table.modules.accessor.initializeColumn(self); } //set respoviveLayout if (_typeof(table.options.responsiveLayout) && table.modExists("responsiveLayout")) { table.modules.responsiveLayout.initializeColumn(self); } //set column visibility if (typeof def.visible != "undefined") { if (def.visible) { self.show(true); } else { self.hide(true); } } //asign additional css classes to column header if (def.cssClass) { var classeNames = def.cssClass.split(" "); classeNames.forEach(function (className) { self.element.classList.add(className); }); } if (def.field) { this.element.setAttribute("tabulator-field", def.field); } //set min width if present self.setMinWidth(typeof def.minWidth == "undefined" ? self.table.options.columnMinWidth : parseInt(def.minWidth)); self.reinitializeWidth(); //set tooltip if present self.tooltip = self.definition.tooltip || self.definition.tooltip === false ? self.definition.tooltip : self.table.options.tooltips; //set orizontal text alignment self.hozAlign = typeof self.definition.align == "undefined" ? "" : self.definition.align; }; Column.prototype._buildColumnHeaderContent = function () { var self = this, def = self.definition, table = self.table; var contentElement = document.createElement("div"); contentElement.classList.add("tabulator-col-content"); contentElement.appendChild(self._buildColumnHeaderTitle()); return contentElement; }; //build title element of column Column.prototype._buildColumnHeaderTitle = function () { var self = this, def = self.definition, table = self.table, title; var titleHolderElement = document.createElement("div"); titleHolderElement.classList.add("tabulator-col-title"); if (def.editableTitle) { var titleElement = document.createElement("input"); titleElement.classList.add("tabulator-title-editor"); titleElement.addEventListener("click", function (e) { e.stopPropagation(); titleElement.focus(); }); titleElement.addEventListener("change", function () { def.title = titleElement.value; table.options.columnTitleChanged.call(self.table, self.getComponent()); }); titleHolderElement.appendChild(titleElement); if (def.field) { table.modules.localize.bind("columns|" + def.field, function (text) { titleElement.value = text || def.title || "&nbsp"; }); } else { titleElement.value = def.title || "&nbsp"; } } else { if (def.field) { table.modules.localize.bind("columns|" + def.field, function (text) { self._formatColumnHeaderTitle(titleHolderElement, text || def.title || "&nbsp"); }); } else { self._formatColumnHeaderTitle(titleHolderElement, def.title || "&nbsp"); } } return titleHolderElement; }; Column.prototype._formatColumnHeaderTitle = function (el, title) { var formatter, contents, params, mockCell; if (this.definition.titleFormatter && this.table.modExists("format")) { formatter = this.table.modules.format.getFormatter(this.definition.titleFormatter); mockCell = { getValue: function getValue() { return title; }, getElement: function getElement() { return el; } }; params = this.definition.titleFormatterParams || {}; params = typeof params === "function" ? params() : params; contents = formatter.call(this.table.modules.format, mockCell, params); switch (typeof contents === 'undefined' ? 'undefined' : _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": case "null": el.innerHTML = ""; break; default: el.innerHTML = contents; } } else { el.innerHTML = title; } }; //build header element for column group Column.prototype._buildGroupHeader = function () { this.element.classList.add("tabulator-col-group"); this.element.setAttribute("role", "columngroup"); this.element.setAttribute("aria-title", this.definition.title); this.element.appendChild(this.groupElement); }; //flat field lookup Column.prototype._getFlatData = function (data) { return data[this.field]; }; //nested field lookup Column.prototype._getNestedData = function (data) { var dataObj = data, structure = this.fieldStructure, length = structure.length, output; for (var i = 0; i < length; i++) { dataObj = dataObj[structure[i]]; output = dataObj; if (!dataObj) { break; } } return output; }; //flat field set Column.prototype._setFlatData = function (data, value) { if (this.field) { data[this.field] = value; } }; //nested field set Column.prototype._setNesteData = function (data, value) { var dataObj = data, structure = this.fieldStructure, length = structure.length; for (var i = 0; i < length; i++) { if (i == length - 1) { dataObj[structure[i]] = value; } else { if (!dataObj[structure[i]]) { dataObj[structure[i]] = {}; } dataObj = dataObj[structure[i]]; } } }; //attach column to this group Column.prototype.attachColumn = function (column) { var self = this; if (self.groupElement) { self.columns.push(column); self.groupElement.appendChild(column.getElement()); } else { console.warn("Column Warning - Column being attached to another column instead of column group"); } }; //vertically align header in column Column.prototype.verticalAlign = function (alignment, height) { //calculate height of column header and group holder element var parentHeight = this.parent.isGroup ? this.parent.getGroupElement().clientHeight : height || this.parent.getHeadersElement().clientHeight; // var parentHeight = this.parent.isGroup ? this.parent.getGroupElement().clientHeight : this.parent.getHeadersElement().clientHeight; this.element.style.height = parentHeight + "px"; if (this.isGroup) { this.groupElement.style.minHeight = parentHeight - this.contentElement.offsetHeight + "px"; } //vertically align cell contents if (!this.isGroup && alignment !== "top") { if (alignment === "bottom") { this.element.style.paddingTop = this.element.clientHeight - this.contentElement.offsetHeight + "px"; } else { this.element.style.paddingTop = (this.element.clientHeight - this.contentElement.offsetHeight) / 2 + "px"; } } this.columns.forEach(function (column) { column.verticalAlign(alignment); }); }; //clear vertical alignmenet Column.prototype.clearVerticalAlign = function () { this.element.style.paddingTop = ""; this.element.style.height = ""; this.element.style.minHeight = ""; this.groupElement.style.minHeight = ""; this.columns.forEach(function (column) { column.clearVerticalAlign(); }); }; //// Retreive Column Information //// //return column header element Column.prototype.getElement = function () { return this.element; }; //return colunm group element Column.prototype.getGroupElement = function () { return this.groupElement; }; //return field name Column.prototype.getField = function () { return this.field; }; //return the first column in a group Column.prototype.getFirstColumn = function () { 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 Column.prototype.getLastColumn = function () { 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 Column.prototype.getColumns = function () { return this.columns; }; //return all columns in a group Column.prototype.getCells = function () { return this.cells; }; //retreive the top column in a group of columns Column.prototype.getTopColumn = function () { if (this.parent.isGroup) { return this.parent.getTopColumn(); } else { return this; } }; //return column definition object Column.prototype.getDefinition = function (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 //////////////////// Column.prototype.checkColumnVisibility = function () { var visible = false; this.columns.forEach(function (column) { if (column.visible) { visible = true; } }); if (visible) { this.show(); this.parent.table.options.columnVisibilityChanged.call(this.table, this.getComponent(), false); } else { this.hide(); } }; //show column Column.prototype.show = function (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(); if (this.table.options.persistentLayout && this.table.modExists("responsiveLayout", true)) { this.table.modules.persistence.save("columns"); } if (!responsiveToggle && this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { this.table.modules.responsiveLayout.updateColumnVisibility(this, this.visible); } if (!silent) { this.table.options.columnVisibilityChanged.call(this.table, this.getComponent(), true); } if (this.parent.isGroup) { this.parent.matchChildWidths(); } } }; //hide column Column.prototype.hide = function (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(); }); if (this.table.options.persistentLayout && this.table.modExists("persistence", true)) { this.table.modules.persistence.save("columns"); } if (!responsiveToggle && this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)) { this.table.modules.responsiveLayout.updateColumnVisibility(this, this.visible); } if (!silent) { this.table.options.columnVisibilityChanged.call(this.table, this.getComponent(), false); } if (this.parent.isGroup) { this.parent.matchChildWidths(); } } }; Column.prototype.matchChildWidths = function () { 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"; } }; Column.prototype.setWidth = function (width) { this.widthFixed = true; this.setWidthActual(width); }; Column.prototype.setWidthActual = function (width) { if (isNaN(width)) { width = Math.floor(this.table.element.clientWidth / 100 * parseInt(width)); } width = Math.max(this.minWidth, 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(); } //set resizable handles if (this.table.modExists("frozenColumns")) { this.table.modules.frozenColumns.layout(); } }; Column.prototype.checkCellHeights = function () { var rows = []; this.cells.forEach(function (cell) { if (cell.row.heightInitialized) { if (cell.row.getElement().offsetParent !== null) { rows.push(cell.row); cell.row.clearCellHeight(); } else { cell.row.heightInitialized = false; } } }); rows.forEach(function (row) { row.calcHeight(); }); rows.forEach(function (row) { row.setCellHeight(); }); }; Column.prototype.getWidth = function () { // return this.element.offsetWidth; return this.width; }; Column.prototype.getHeight = function () { return this.element.offsetHeight; }; Column.prototype.setMinWidth = function (minWidth) { this.minWidth = minWidth; this.minWidthStyled = minWidth ? minWidth + "px" : ""; this.element.style.minWidth = this.minWidthStyled; this.cells.forEach(function (cell) { cell.setMinWidth(); }); }; Column.prototype.delete = function () { if (this.isGroup) { this.columns.forEach(function (column) { column.delete(); }); } var cellCount = this.cells.length; for (var i = 0; i < cellCount; i++) { this.cells[0].delete(); } this.element.parentNode.removeChild(this.element); this.table.columnManager.deregisterColumn(this); }; //////////////// Cell Management ///////////////// //generate cell for this column Column.prototype.generateCell = function (row) { var self = this; var cell = new Cell(self, row); this.cells.push(cell); return cell; }; Column.prototype.nextColumn = function () { var index = this.table.columnManager.findColumnIndex(this); return index > -1 ? this.table.columnManager.getColumnByIndex(index + 1) : false; }; Column.prototype.prevColumn = function () { var index = this.table.columnManager.findColumnIndex(this); return index > -1 ? this.table.columnManager.getColumnByIndex(index - 1) : false; }; Column.prototype.reinitializeWidth = function (force) { this.widthFixed = false; //set width if present if (typeof this.definition.width !== "undefined" && !force) { this.setWidth(this.definition.width); } //hide header filters to prevent them altering column width if (this.table.modExists("filter")) { this.table.modules.filter.hideHeaderFilterElements(); } this.fitToData(); //show header filters again after layout is complete if (this.table.modExists("filter")) { this.table.modules.filter.showHeaderFilterElements(); } }; //set column width to maximum cell width Column.prototype.fitToData = function () { var self = this; if (!this.widthFixed) { this.element.style.width = ""; self.cells.forEach(function (cell) { cell.clearWidth(); }); } var maxWidth = this.element.offsetWidth; if (!self.width || !this.widthFixed) { self.cells.forEach(function (cell) { var width = cell.getWidth(); if (width > maxWidth) { maxWidth = width; } }); if (maxWidth) { self.setWidthActual(maxWidth + 1); } } }; Column.prototype.deleteCell = function (cell) { var index = this.cells.indexOf(cell); if (index > -1) { this.cells.splice(index, 1); } }; Column.prototype.defaultOptionList = ["title", "field", "columns", "visible", "align", "width", "minWidth", "widthGrow", "widthShrink", "resizable", "frozen", "responsive", "tooltip", "cssClass", "rowHandle", "hideInHtml", "print", "htmlOutput", "sorter", "sorterParams", "formatter", "formatterParams", "variableHeight", "editable", "editor", "editorParams", "validator", "mutator", "mutatorParams", "mutatorData", "mutatorDataParams", "mutatorEdit", "mutatorEditParams", "mutatorClipboard", "mutatorClipboardParams", "accessor", "accessorParams", "accessorData", "accessorDataParams", "accessorDownload", "accessorDownloadParams", "accessorClipboard", "accessorClipboardParams", "download", "downloadTitle", "topCalc", "topCalcParams", "topCalcFormatter", "topCalcFormatterParams", "bottomCalc", "bottomCalcParams", "bottomCalcFormatter", "bottomCalcFormatterParams", "cellClick", "cellDblClick", "cellContext", "cellTap", "cellDblTap", "cellTapHold", "cellMouseEnter", "cellMouseLeave", "cellMouseOver", "cellMouseOut", "cellMouseMove", "cellEditing", "cellEdited", "cellEditCancelled", "headerSort", "headerSortStartingDir", "headerSortTristate", "headerClick", "headerDblClick", "headerContext", "headerTap", "headerDblTap", "headerTapHold", "headerTooltip", "headerVertical", "editableTitle", "titleFormatter", "titleFormatterPa