UNPKG

jquery.tabulator

Version:

Interactive table generation plugin for jQuery UI

520 lines (386 loc) 12.8 kB
var ColumnManager = function(table){ this.table = table; //hold parent table this.headersElement = $("<div class='tabulator-headers'></div>"); this.element = $("<div class='tabulator-header'></div>"); //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.prepend(this.headersElement); }; ////////////// Setup Functions ///////////////// //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; }; //scroll horizontally to match table body ColumnManager.prototype.scrollHorizontal = function(left){ var hozAdjust = 0, scrollWidth = this.element[0].scrollWidth - this.table.element.innerWidth(); this.element.scrollLeft(left); //adjust for vertical scrollbar moving table when present if(left > scrollWidth){ hozAdjust = left - scrollWidth this.element.css("margin-left", -(hozAdjust)); }else{ this.element.css("margin-left", 0); } //keep frozen columns fixed in position //this._calcFrozenColumnsPos(hozAdjust + 3); this.scrollLeft = left; if(this.table.extExists("frozenColumns")){ this.table.extensions.frozenColumns.layout(); } }; ///////////// Column Setup Functions ///////////// ColumnManager.prototype.setColumns = function(cols, row){ var self = this; self.headersElement.empty(); self.columns = []; self.columnsByIndex = []; self.columnsByField = []; //reset frozen columns if(self.table.extExists("frozenColumns")){ self.table.extensions.frozenColumns.reset(); } cols.forEach(function(def, i){ self._addColumn(def); }); self._reIndexColumns(); if(self.table.options.responsiveLayout && self.table.extExists("responsiveLayout", true)){ self.table.extensions.responsiveLayout.initialize(); } self.redraw(true); }; ColumnManager.prototype._addColumn = function(definition, before, nextToColumn){ var column = new Column(definition, this); var index = nextToColumn ? this.findColumnIndex(nextToColumn) : nextToColumn; if(nextToColumn && index > -1){ let parentIndex = this.columns.indexOf(nextToColumn.getTopColumn()); if(before){ this.columns.splice(parentIndex, 0, column); nextToColumn.getElement().before(column.getElement()); }else{ this.columns.splice(parentIndex + 1, 0, column); nextToColumn.getElement().after(column.getElement()); } }else{ if(before){ this.columns.unshift(column); this.headersElement.prepend(column.getElement()); }else{ this.columns.push(column); this.headersElement.append(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; self.columns.forEach(function(column){ column.clearVerticalAlign(); }); self.columns.forEach(function(column){ column.verticalAlign(self.table.options.columnVertAlign); }); self.rowManager.adjustTableSize(); }; //////////////// Column Details ///////////////// ColumnManager.prototype.findColumn = function(subject){ var self = this; if(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(subject instanceof jQuery){ //subject is a jquery element of the column header let 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.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.extExists("responsiveLayout", true)){ this.table.extensions.responsiveLayout.initialize(); } if(this.table.options.columnMoved){ this.table.options.columnMoved(from.getComponent(), this.table.columnManager.getComponents()); } if(this.table.options.persistentLayout && this.table.extExists("persistence", true)){ this.table.extensions.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 left = 0, offset = 0, adjust = 0; 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[0].clientWidth / 2; break; case "right": adjust = column.element.innerWidth() - this.headersElement.innerWidth(); break; } //check column visibility if(!ifVisible){ offset = column.element.position().left; if(offset > 0 && offset + column.element.outerWidth() < this.element[0].clientWidth){ return false; } } //calculate scroll position left = column.element.position().left + this.element.scrollLeft() + adjust; left = Math.max(Math.min(left, this.table.rowManager.element[0].scrollWidth - this.table.rowManager.element[0].clientWidth),0); this.table.rowManager.scrollHorizontal(left); this.scrollHorizontal(left); return true }else{ console.warn("Scroll Error - Column not visible"); return false; } }; //////////////// 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.innerWidth(), //table element width fixedWidth = 0; //adjust for vertical scrollbar if present if(self.rowManager.element[0].scrollHeight > self.rowManager.element.innerHeight()){ totalWidth -= self.rowManager.element[0].offsetWidth - self.rowManager.element[0].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.extExists("responsiveLayout", true)){ this.table.extensions.responsiveLayout.initialize(); } if(this.table.extExists("columnCalcs")){ this.table.extensions.columnCalcs.recalc(this.table.rowManager.activeRows); } this.redraw(); if(this.table.extensions.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.extExists("responsiveLayout", true)){ this.table.extensions.responsiveLayout.initialize(); } this.redraw(); }; //redraw columns ColumnManager.prototype.redraw = function(force){ if(force){ if(this.element.is(":visible")){ this._verticalAlignHeaders(); } this.table.rowManager.resetScroll(); this.table.rowManager.reinitialize(); } if(this.table.extensions.layout.getMode() == "fitColumns"){ this.table.extensions.layout.layout(); }else{ if(force){ this.table.extensions.layout.layout(); }else{ if(this.table.options.responsiveLayout && this.table.extExists("responsiveLayout", true)){ this.table.extensions.responsiveLayout.update(); } } } if(this.table.extExists("frozenColumns")){ this.table.extensions.frozenColumns.layout(); } if(this.table.extExists("columnCalcs")){ this.table.extensions.columnCalcs.recalc(this.table.rowManager.activeRows); } if(force){ if(this.table.options.persistentLayout && this.table.extExists("persistence", true)){ this.table.extensions.persistence.save("columns"); } if(this.table.extExists("columnCalcs")){ this.table.extensions.columnCalcs.redraw(); } } this.table.footerManager.redraw(); };