tabulator-tables
Version:
Interactive table generation JavaScript library
2,582 lines (1,467 loc) • 520 kB
JavaScript
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 || " ";
});
} else {
titleElement.value = def.title || " ";
}
} else {
if (def.field) {
table.modules.localize.bind("columns|" + def.field, function (text) {
self._formatColumnHeaderTitle(titleHolderElement, text || def.title || " ");
});
} else {
self._formatColumnHeaderTitle(titleHolderElement, def.title || " ");
}
}
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