tabulator-tables
Version:
Interactive table generation JavaScript library
302 lines (237 loc) • 7.76 kB
JavaScript
import Module from '../../core/Module.js';
export default class FrozenColumns extends Module{
static moduleName = "frozenColumns";
constructor(table){
super(table);
this.leftColumns = [];
this.rightColumns = [];
this.initializationMode = "left";
this.active = false;
this.blocked = true;
this.registerColumnOption("frozen");
}
//reset initial state
reset(){
this.initializationMode = "left";
this.leftColumns = [];
this.rightColumns = [];
this.active = false;
}
initialize(){
this.subscribe("cell-layout", this.layoutCell.bind(this));
this.subscribe("column-init", this.initializeColumn.bind(this));
this.subscribe("column-width", this.layout.bind(this));
this.subscribe("row-layout-after", this.layoutRow.bind(this));
this.subscribe("table-layout", this.layout.bind(this));
this.subscribe("columns-loading", this.reset.bind(this));
this.subscribe("column-add", this.reinitializeColumns.bind(this));
this.subscribe("column-deleted", this.reinitializeColumns.bind(this));
this.subscribe("column-hide", this.reinitializeColumns.bind(this));
this.subscribe("column-show", this.reinitializeColumns.bind(this));
this.subscribe("columns-loaded", this.reinitializeColumns.bind(this));
this.subscribe("table-redraw", this.layout.bind(this));
this.subscribe("layout-refreshing", this.blockLayout.bind(this));
this.subscribe("layout-refreshed", this.unblockLayout.bind(this));
this.subscribe("scrollbar-vertical", this.adjustForScrollbar.bind(this));
}
blockLayout(){
this.blocked = true;
}
unblockLayout(){
this.blocked = false;
}
layoutCell(cell){
this.layoutElement(cell.element, cell.column);
}
reinitializeColumns(){
this.reset();
this.table.columnManager.columnsByIndex.forEach((column) => {
this.initializeColumn(column);
});
this.layout();
}
//initialize specific column
initializeColumn(column){
var config = {margin:0, edge:false};
if(!column.isGroup){
if(this.frozenCheck(column)){
config.position = this.initializationMode;
if(this.initializationMode == "left"){
this.leftColumns.push(column);
}else{
this.rightColumns.unshift(column);
}
this.active = true;
column.modules.frozen = config;
}else{
this.initializationMode = "right";
}
}
}
frozenCheck(column){
if(column.parent.isGroup && column.definition.frozen){
console.warn("Frozen Column Error - Parent column group must be frozen, not individual columns or sub column groups");
}
if(column.parent.isGroup){
return this.frozenCheck(column.parent);
}else{
return column.definition.frozen;
}
}
//layout calculation rows
layoutCalcRows(){
if(this.table.modExists("columnCalcs")){
if(this.table.modules.columnCalcs.topInitialized && this.table.modules.columnCalcs.topRow){
this.layoutRow(this.table.modules.columnCalcs.topRow);
}
if(this.table.modules.columnCalcs.botInitialized && this.table.modules.columnCalcs.botRow){
this.layoutRow(this.table.modules.columnCalcs.botRow);
}
if(this.table.modExists("groupRows")){
this.layoutGroupCalcs(this.table.modules.groupRows.getGroups());
}
}
}
layoutGroupCalcs(groups){
groups.forEach((group) => {
if(group.calcs.top){
this.layoutRow(group.calcs.top);
}
if(group.calcs.bottom){
this.layoutRow(group.calcs.bottom);
}
if(group.groupList && group.groupList.length){
this.layoutGroupCalcs(group.groupList);
}
});
}
//calculate column positions and layout headers
layoutColumnPosition(allCells){
var leftParents = [];
var leftMargin = 0;
var rightMargin = 0;
this.leftColumns.forEach((column, i) => {
column.modules.frozen.marginValue = leftMargin;
column.modules.frozen.margin = column.modules.frozen.marginValue + "px";
if(column.visible){
leftMargin += column.getWidth();
}
if(i == this.leftColumns.length - 1){
column.modules.frozen.edge = true;
}else{
column.modules.frozen.edge = false;
}
if(column.parent.isGroup){
var parentEl = this.getColGroupParentElement(column);
if(!leftParents.includes(parentEl)){
this.layoutElement(parentEl, column);
leftParents.push(parentEl);
}
parentEl.classList.toggle("tabulator-frozen-left", column.modules.frozen.edge && column.modules.frozen.position === "left");
parentEl.classList.toggle("tabulator-frozen-right", column.modules.frozen.edge && column.modules.frozen.position === "right");
}else{
this.layoutElement(column.getElement(), column);
}
if(allCells){
column.cells.forEach((cell) => {
this.layoutElement(cell.getElement(true), column);
});
}
});
this.rightColumns.forEach((column, i) => {
column.modules.frozen.marginValue = rightMargin;
column.modules.frozen.margin = column.modules.frozen.marginValue + "px";
if(column.visible){
rightMargin += column.getWidth();
}
if(i == this.rightColumns.length - 1){
column.modules.frozen.edge = true;
}else{
column.modules.frozen.edge = false;
}
if(column.parent.isGroup){
this.layoutElement(this.getColGroupParentElement(column), column);
}else{
this.layoutElement(column.getElement(), column);
}
if(allCells){
column.cells.forEach((cell) => {
this.layoutElement(cell.getElement(true), column);
});
}
});
}
getColGroupParentElement(column){
return column.parent.isGroup ? this.getColGroupParentElement(column.parent) : column.getElement();
}
//layout columns appropriately
layout(){
if(this.active && !this.blocked){
//calculate left columns
this.layoutColumnPosition();
this.reinitializeRows();
this.layoutCalcRows();
}
}
reinitializeRows(){
var visibleRows = this.table.rowManager.getVisibleRows(true);
var otherRows = this.table.rowManager.getRows().filter(row => !visibleRows.includes(row));
otherRows.forEach((row) =>{
row.deinitialize();
});
visibleRows.forEach((row) =>{
if(row.type === "row"){
this.layoutRow(row);
}
});
}
layoutRow(row){
if(this.table.options.layout === "fitDataFill" && this.rightColumns.length){
this.table.rowManager.getTableElement().style.minWidth = "calc(100% - " + this.rightMargin + ")";
}
this.leftColumns.forEach((column) => {
var cell = row.getCell(column);
if(cell){
this.layoutElement(cell.getElement(true), column);
}
});
this.rightColumns.forEach((column) => {
var cell = row.getCell(column);
if(cell){
this.layoutElement(cell.getElement(true), column);
}
});
}
layoutElement(element, column){
var position;
if(column.modules.frozen && element){
element.style.position = "sticky";
if(this.table.rtl){
position = column.modules.frozen.position === "left" ? "right" : "left";
}else{
position = column.modules.frozen.position;
}
element.style[position] = column.modules.frozen.margin;
element.classList.add("tabulator-frozen");
element.classList.toggle("tabulator-frozen-left", column.modules.frozen.edge && column.modules.frozen.position === "left");
element.classList.toggle("tabulator-frozen-right", column.modules.frozen.edge && column.modules.frozen.position === "right");
}
}
adjustForScrollbar(width){
if(this.rightColumns.length){
this.table.columnManager.getContentsElement().style.width = "calc(100% - " + width + "px)";
}
}
getFrozenColumns(){
return this.leftColumns.concat(this.rightColumns);
}
_calcSpace(columns, index){
var width = 0;
for (let i = 0; i < index; i++){
if(columns[i].visible){
width += columns[i].getWidth();
}
}
return width;
}
}