tabulator-tables
Version:
Interactive table generation JavaScript library
1,560 lines (1,225 loc) • 38.9 kB
JavaScript
//public column object
var ColumnComponent = function (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(){
console.warn("getVisibility function is deprecated, you should now use the isVisible function");
return this._column.visible;
};
ColumnComponent.prototype.isVisible = 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(){
return 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.getHeaderFilterValue = function(){
if(this._column.table.modExists("filter", true)){
return this._column.table.modules.filter.getHeaderFilterValue(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.move = function(to, after){
var toColumn = this._column.table.columnManager.findColumn(to);
if(toColumn){
this._column.table.columnManager.moveColumn(this._column, toColumn, after)
}else{
console.warn("Move Error - No matching column found:", toColumn);
}
};
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;
};
ColumnComponent.prototype.updateDefinition = function(updates){
return this._column.updateDefinition(updates);
};
ColumnComponent.prototype.getWidth = function(){
return this._column.getWidth();
};
ColumnComponent.prototype.setWidth = function(width){
var result;
if(width === true){
result = this._column.reinitializeWidth(true);
}else{
result = this._column.setWidth(width);
}
if(this._column.table.options.virtualDomHoz){
this._column.table.vdomHoz.reinitialize(true);
}
return result;
};
ColumnComponent.prototype.validate = function(){
return this._column.validate();
};
var Column = function(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.titleHolderElement = false;
this.titleElement = false;
this.groupElement = this.createGroupElement(); //column group holder element
this.isGroup = false;
this.tooltip = false; //hold column tooltip
this.hozAlign = ""; //horizontal text alignment
this.vertAlign = ""; //vert text alignment
//multi dimensional filed handling
this.field ="";
this.fieldStructure = "";
this.getFieldValue = "";
this.setFieldValue = "";
this.titleFormatterRendered = false;
this.setField(this.definition.field);
if(this.table.options.invalidOptionWarnings){
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.maxWidth = null; //column maximum width
this.maxWidthStyled = ""; //column maximum 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.component = null;
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();
this.bindModuleColumns();
};
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(){
Object.keys(this.definition).forEach((key) => {
if(this.defaultOptionList.indexOf(key) === -1){
console.warn("Invalid column definition option in '" + (this.field || this.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._setNestedData : 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 deprecated, you should now use htmlOutput")
}
if(typeof this.definition.align !== "undefined"){
this.definition.hozAlign = this.definition.align;
console.warn("align column definition property is deprecated, you should now use hozAlign");
}
if(typeof this.definition.downloadTitle !== "undefined"){
this.definition.titleDownload = this.definition.downloadTitle;
console.warn("downloadTitle definition property is deprecated, you should now use titleDownload");
}
};
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);
}
//handle persistence
if(self.table.modExists("persistence") && self.table.modules.persistence.config.columns){
self.table.modules.persistence.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 def = this.definition,
table = this.table,
sortable;
//set column sorter
if(table.modExists("sort")){
table.modules.sort.initializeColumn(this, this.titleHolderElement);
}
//set column header context menu
if((def.headerContextMenu || def.headerClickMenu || def.headerMenu) && table.modExists("menu")){
table.modules.menu.initializeColumnHeader(this);
}
//set column formatter
if(table.modExists("format")){
table.modules.format.initializeColumn(this);
}
//set column editor
if(typeof def.editor != "undefined" && table.modExists("edit")){
table.modules.edit.initializeColumn(this);
}
//set colum validator
if(typeof def.validator != "undefined" && table.modExists("validate")){
table.modules.validate.initializeColumn(this);
}
//set column mutator
if(table.modExists("mutator")){
table.modules.mutator.initializeColumn(this);
}
//set column accessor
if(table.modExists("accessor")){
table.modules.accessor.initializeColumn(this);
}
//set respoviveLayout
if(typeof table.options.responsiveLayout && table.modExists("responsiveLayout")){
table.modules.responsiveLayout.initializeColumn(this);
}
//set column visibility
if(typeof def.visible != "undefined"){
if(def.visible){
this.show(true);
}else{
this.hide(true);
}
}
//asign additional css classes to column header
if(def.cssClass){
var classeNames = def.cssClass.split(" ");
classeNames.forEach((className) => {
this.element.classList.add(className);
});
}
if(def.field){
this.element.setAttribute("tabulator-field", def.field);
}
//set min width if present
this.setMinWidth(typeof def.minWidth == "undefined" ? this.table.options.columnMinWidth : parseInt(def.minWidth));
if(def.maxWidth || this.table.options.columnMaxWidth){
if(def.maxWidth !== false){
this.setMaxWidth(typeof def.maxWidth == "undefined" ? this.table.options.columnMaxWidth : parseInt(def.maxWidth));
}
}
this.reinitializeWidth();
//set tooltip if present
this.tooltip = this.definition.tooltip || this.definition.tooltip === false ? this.definition.tooltip : this.table.options.tooltips;
//set orizontal text alignment
this.hozAlign = typeof(this.definition.hozAlign) == "undefined" ? this.table.options.cellHozAlign : this.definition.hozAlign;
this.vertAlign = typeof(this.definition.vertAlign) == "undefined" ? this.table.options.cellVertAlign : this.definition.vertAlign;
this.titleElement.style.textAlign = this.definition.headerHozAlign || this.table.options.headerHozAlign;
};
Column.prototype._buildColumnHeaderContent = function(){
var def = this.definition,
table = this.table;
var contentElement = document.createElement("div");
contentElement.classList.add("tabulator-col-content");
this.titleHolderElement = document.createElement("div");
this.titleHolderElement.classList.add("tabulator-col-title-holder");
contentElement.appendChild(this.titleHolderElement);
this.titleElement = this._buildColumnHeaderTitle();
this.titleHolderElement.appendChild(this.titleElement);
return contentElement;
};
//build title element of column
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, onRendered;
if(this.definition.titleFormatter && this.table.modExists("format")){
formatter = this.table.modules.format.getFormatter(this.definition.titleFormatter);
onRendered = (callback) => {
this.titleFormatterRendered = callback;
};
mockCell = {
getValue:function(){
return title;
},
getElement:function(){
return el;
}
};
params = this.definition.titleFormatterParams || {};
params = typeof params === "function" ? params() : params;
contents = formatter.call(this.table.modules.format, mockCell, params, onRendered);
switch(typeof contents){
case "object":
if(contents instanceof Node){
el.appendChild(contents);
}else{
el.innerHTML = "";
console.warn("Format Error - Title formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:", contents);
}
break;
case "undefined":
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);
//asign additional css classes to column header
if(this.definition.cssClass){
var classeNames = this.definition.cssClass.split(" ");
classeNames.forEach((className) => {
this.element.classList.add(className);
});
}
//set column header context menu
if ((this.definition.headerContextMenu || this.definition.headerMenu) && this.table.modExists("menu")) {
this.table.modules.menu.initializeColumnHeader(this);
}
this.titleElement.style.textAlign = this.definition.headerHozAlign || this.table.options.headerHozAlign;
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(let 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._setNestedData = function(data, value){
var dataObj = data,
structure = this.fieldStructure,
length = structure.length;
for(let i = 0; i < length; i++){
if(i == length -1){
dataObj[structure[i]] = value;
}else{
if(!dataObj[structure[i]]){
if(typeof value !== "undefined"){
dataObj[structure[i]] = {};
}else{
break;
}
}
dataObj = dataObj[structure[i]];
}
}
};
//attach column to this group
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();
});
};
Column.prototype.bindModuleColumns = function (){
//check if rownum formatter is being used on a column
if(this.definition.formatter == "rownum"){
this.table.rowManager.rowNumColumn = this;
}
};
//// 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.persistence && this.table.modExists("persistence", true) && this.table.modules.persistence.config.columns){
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();
}
if(!this.silent && this.table.options.virtualDomHoz){
this.table.vdomHoz.reinitialize();
}
}
};
//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.persistence && this.table.modExists("persistence", true) && this.table.modules.persistence.config.columns){
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();
}
if(!this.silent && this.table.options.virtualDomHoz){
this.table.vdomHoz.reinitialize();
}
}
};
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";
if(this.parent.isGroup){
this.parent.matchChildWidths();
}
}
};
Column.prototype.removeChild = function(child){
var index = this.columns.indexOf(child);
if(index > -1){
this.columns.splice(index, 1);
}
if(!this.columns.length){
this.delete();
}
};
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);
if(this.maxWidth){
width = Math.min(this.maxWidth, width);
}
this.width = width;
this.widthStyled = width ? width + "px" : "";
this.element.style.width = this.widthStyled;
if(!this.isGroup){
this.cells.forEach(function(cell){
cell.setWidth();
});
}
if(this.parent.isGroup){
this.parent.matchChildWidths();
}
//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(){
var width = 0;
if(this.isGroup){
this.columns.forEach(function(column){
if(column.visible){
width += column.getWidth();
}
});
}else{
width = this.width;
}
return 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.setMaxWidth = function(maxWidth){
this.maxWidth = maxWidth;
this.maxWidthStyled = maxWidth ? maxWidth + "px" : "";
this.element.style.maxWidth = this.maxWidthStyled;
this.cells.forEach(function(cell){
cell.setMaxWidth();
});
};
Column.prototype.delete = function(){
return new Promise((resolve, reject) => {
var index;
if(this.isGroup){
this.columns.forEach(function(column){
column.delete();
});
}
//cancel edit if column is currently being edited
if(this.table.modExists("edit")){
if(this.table.modules.edit.currentCell.column === this){
this.table.modules.edit.cancelEdit();
}
}
var cellCount = this.cells.length;
for(let i = 0; i < cellCount; i++){
this.cells[0].delete();
}
if(this.element.parentNode){
this.element.parentNode.removeChild(this.element);
}
this.element = false;
this.contentElement = false;
this.titleElement = false;
this.groupElement = false;
if(this.parent.isGroup){
this.parent.removeChild(this);
}
this.table.columnManager.deregisterColumn(this);
if(this.table.options.virtualDomHoz){
this.table.vdomHoz.reinitialize(true);
}
resolve();
});
};
Column.prototype.columnRendered = function(){
if(this.titleFormatterRendered){
this.titleFormatterRendered();
}
};
Column.prototype.validate = function(){
var invalid = [];
this.cells.forEach(function(cell){
if(!cell.validate()){
invalid.push(cell.getComponent());
}
});
return invalid.length ? invalid : true;
};
//////////////// 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._nextVisibleColumn(index + 1) : false;
};
Column.prototype._nextVisibleColumn = function(index){
var column = this.table.columnManager.getColumnByIndex(index);
return !column || column.visible ? column : this._nextVisibleColumn(index + 1);
};
Column.prototype.prevColumn = function(){
var index = this.table.columnManager.findColumnIndex(this);
return index > -1 ? this._prevVisibleColumn(index - 1) : false;
};
Column.prototype._prevVisibleColumn = function(index){
var column = this.table.columnManager.getColumnByIndex(index);
return !column || column.visible ? column : this._prevVisibleColumn(index - 1);
};
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.updateDefinition = function(updates){
return new Promise((resolve, reject) => {
var definition;
if(!this.isGroup){
if(!this.parent.isGroup){
definition = Object.assign({}, this.getDefinition());
definition = Object.assign(definition, updates);
this.table.columnManager.addColumn(definition, false, this)
.then((column) => {
if(definition.field == this.field){
this.field = false; //cleair field name to prevent deletion of duplicate column from arrays
}
this.delete()
.then(() => {
resolve(column.getComponent());
}).catch((err) => {
reject(err);
});
}).catch((err) => {
reject(err);
});
}else{
console.warn("Column Update Error - The updateDefinition function is only available on ungrouped columns");
reject("Column Update Error - The updateDefinition function is only available on columns, not column groups");
}
}else{
console.warn("Column Update Error - The updateDefinition function is only available on ungrouped columns");
reject("Column Update Error - The updateDefinition function is only available on columns, not column groups");
}
});
};
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",
"hozAlign",
"vertAlign",
"width",
"minWidth",
"maxWidth",
"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",
"accessorPrint",
"accessorPrintParams",
"accessorHtmlOutput",
"accessorHtmlOutputParams",
"clipboard",
"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",
"headerHozAlign",
"editableTitle",
"titleFormatter",
"titleFormatterParams",
"headerFilter",
"headerFilterPlaceholder",
"headerFilterParams",
"headerFilterEmptyCheck",
"headerFilterFunc",
"headerFilterFuncParams",
"headerFilterLiveFilter",
"print",
"headerContextMenu",
"headerMenu",
"contextMenu",
// "headerClickMenu",
"clickMenu",
"formatterPrint",
"formatterPrintParams",
"formatterClipboard",
"formatterClipboardParams",
"formatterHtmlOutput",
"formatterHtmlOutputParams",
"titlePrint",
"titleClipboard",
"titleHtmlOutput",
"titleDownload",
];
//////////////// Event Bindings /////////////////
//////////////// Object Generation /////////////////
Column.prototype.getComponent = function(){
if(!this.component){
this.component = new ColumnComponent(this);
}
return this.component;
};