tabulator-tables
Version:
Interactive table generation JavaScript library
449 lines (334 loc) • 10.3 kB
JavaScript
var VDomHoz = function(table){
this.table = table;
this.element = this.table.rowManager.tableElement;
this.holderEl = this.table.rowManager.element;
this.leftCol = 0;
this.rightCol = 0;
this.scrollLeft = 0;
this.vDomScrollPosLeft = 0;
this.vDomScrollPosRight = 0;
this.vDomPadLeft = 0;
this.vDomPadRight = 0;
this.fitDataColAvg = 0;
this.window = 200; //pixel margin to make column visible before it is shown on screen
this.initialized = false;
this.columns = [];
if(this.compatabilityCheck()){
this.initialize();
}
};
VDomHoz.prototype.compatabilityCheck = function(){
var options = this.table.options,
frozen = false,
ok = true;
if(options.layout == "fitDataTable"){
console.warn("Horizontal Vitrual DOM is not compatible with fitDataTable layout mode");
ok = false;
}
if(options.responsiveLayout){
console.warn("Horizontal Vitrual DOM is not compatible with responsive columns");
ok = false;
}
if(this.table.rtl){
console.warn("Horizontal Vitrual DOM is not currently compatible with RTL text direction");
ok = false;
}
// if(options.rowFormatter){
// console.warn("Horizontal Vitrual DOM is not compatible with row formatters");
// ok = false;
// }
if(options.columns){
frozen = options.columns.find((col) => {
return col.frozen;
});
if(frozen){
console.warn("Horizontal Vitrual DOM is not compatible with frozen columns");
ok = false;
}
}
if(!ok){
options.virtualDomHoz = false;
}
return ok;
};
VDomHoz.prototype.initialize = function(){
this.holderEl.addEventListener("scroll", () => {
var left = this.holderEl.scrollLeft;
if(this.scrollLeft != left){
this.scrollLeft = left;
this.scroll(left - (this.vDomScrollPosLeft + this.window));
}
});
};
VDomHoz.prototype.deinitialize = function(){
this.initialized = false;
};
VDomHoz.prototype.clear = function(){
this.columns = [];
this.leftCol = -1;
this.rightCol = 0;
this.vDomScrollPosLeft = 0;
this.vDomScrollPosRight = 0;
this.vDomPadLeft = 0;
this.vDomPadRight = 0;
};
VDomHoz.prototype.dataChange = function(){
var change = false,
collsWidth = 0,
colEnd = 0,
group, row, rowEl;
if(this.table.options.layout === "fitData"){
this.table.columnManager.columnsByIndex.forEach((column) => {
if(!column.definition.width && column.visible){
change = true;
}
});
if(change){
if(change && this.table.rowManager.getDisplayRows().length){
// this.table.vdomHoz.deinitialize();
this.vDomScrollPosRight = this.scrollLeft + this.holderEl.clientWidth + this.window;
if(this.table.options.groupBy){
group = this.table.modules.groupRows.getGroups(false)[0];
row = group.getRows(false)[0];
}else{
row = this.table.rowManager.getDisplayRows()[0];
}
if(row){
rowEl = row.getElement();
row.generateCells();
this.element.appendChild(rowEl);
for(var colEnd = 0; colEnd < row.cells.length; colEnd++){
let cell = row.cells[colEnd];
rowEl.appendChild(cell.getElement());
cell.column.reinitializeWidth();
collsWidth += cell.column.getWidth();
if(collsWidth > this.vDomScrollPosRight){
break;
}
}
rowEl.parentNode.removeChild(rowEl);
this.fitDataColAvg = Math.floor(collsWidth / (colEnd + 1));
for(colEnd; colEnd < this.table.columnManager.columnsByIndex.length; colEnd++){
this.table.columnManager.columnsByIndex[colEnd].setWidth(this.fitDataColAvg);
}
this.reinitialize(false, true);
}
}
}
}else{
if(this.table.options.layout === "fitColumns"){
this.table.modules.layout.layout();
this.table.vdomHoz.reinitialize(false, true);
}
}
};
VDomHoz.prototype.fitDataLayoutOverride = function(){
for(let i = this.leftCol; i <= this.rightCol; i++){
this.columns[i].reinitializeWidth();
}
};
VDomHoz.prototype.reinitialize = function(update, blockRedraw){
var old = {
cols:this.columns,
leftCol:this.leftCol,
rightCol:this.rightCol,
};
if(update && !this.initialized){
return;
}
this.clear();
this.scrollLeft = this.holderEl.scrollLeft;
this.vDomScrollPosLeft = this.scrollLeft - this.window;
this.vDomScrollPosRight = this.scrollLeft + this.holderEl.clientWidth + this.window;
var colPos = 0;
this.table.columnManager.columnsByIndex.forEach((column) => {
var config = {};
if(column.visible){
var width = column.getWidth();
config.leftPos = colPos;
config.rightPos = colPos + width;
if((colPos + width > this.vDomScrollPosLeft) && (colPos < this.vDomScrollPosRight)){
//column is visible
if(this.leftCol == -1){
this.leftCol = this.columns.length;
this.vDomPadLeft = colPos;
}
this.rightCol = this.columns.length;
}else{
// column is hidden
if(this.leftCol !== -1){
this.vDomPadRight += width;
}
}
this.columns.push(column);
column.modules.vdomHoz = config;
colPos += width;
}
});
this.element.style.paddingLeft = this.vDomPadLeft + "px";
this.element.style.paddingRight = this.vDomPadRight + "px";
this.initialized = true;
if(!blockRedraw){
if(!update || this.reinitChanged(old)){
this.renitializeRows();
}
}
this.holderEl.scrollLeft = this.scrollLeft;
};
VDomHoz.prototype.reinitChanged = function(old){
var match = true;
if(old.cols.length !== this.columns.length || old.leftCol !== this.leftCol || old.rightCol !== this.rightCol){
return true;
}
old.cols.forEach((col, i) => {
if(col !== this.columns[i]){
match = false;
}
});
return !match;
};
VDomHoz.prototype.renitializeRows = function(){
var rows = this.table.rowManager.getVisibleRows();
rows.forEach((row) => {
this.reinitializeRow(row, true);
});
};
VDomHoz.prototype.scroll = function(diff){
this.vDomScrollPosLeft += diff;
this.vDomScrollPosRight += diff;
if(diff > (this.holderEl.clientWidth * .8)){
this.reinitialize();
}else{
if(diff > 0){
//scroll right
this.addColRight();
this.removeColLeft();
}else{
//scroll left
this.addColLeft();
this.removeColRight();
}
}
};
VDomHoz.prototype.colPositionAdjust = function (start, end, diff){
for(let i = start; i < end; i++){
let column = this.columns[i];
column.modules.vdomHoz.leftPos -= diff;
column.modules.vdomHoz.rightPos -= diff;
}
};
VDomHoz.prototype.addColRight = function(){
var column = this.columns[this.rightCol + 1],
rows, oldWidth, widthDiff;
if(column && column.modules.vdomHoz.leftPos <= this.vDomScrollPosRight){
rows = this.table.rowManager.getVisibleRows();
rows.forEach((row) => {
if(row.type !== "group"){
var cell = row.getCell(column);
row.getElement().appendChild(cell.getElement());
cell.cellRendered();
}
});
if(this.fitDataColAvg){
oldWidth = column.getWidth();
if(oldWidth === this.fitDataColAvg){
column.reinitializeWidth();
widthDiff = oldWidth - column.getWidth();
if(widthDiff){
column.modules.vdomHoz.rightPos -= widthDiff;
this.colPositionAdjust(this.rightCol + 1, this.columns.length, widthDiff);
}
}
}
this.rightCol++;
if(this.rightCol >= (this.columns.length - 1)){
this.vDomPadRight = 0;
}else{
this.vDomPadRight -= column.getWidth();
}
this.element.style.paddingRight = this.vDomPadRight + "px";
this.addColRight();
}
};
VDomHoz.prototype.addColLeft = function(){
var column = this.columns[this.leftCol - 1],
rows;
if(column && column.modules.vdomHoz.rightPos >= this.vDomScrollPosLeft){
var rows = this.table.rowManager.getVisibleRows();
rows.forEach((row) => {
if(row.type !== "group"){
var cell = row.getCell(column);
row.getElement().prepend(cell.getElement());
cell.cellRendered();
}
});
if(!this.leftCol){
this.vDomPadLeft = 0;
}else{
this.vDomPadLeft -= column.getWidth();
}
this.element.style.paddingLeft = this.vDomPadLeft + "px";
this.leftCol--;
this.addColLeft();
}
};
VDomHoz.prototype.removeColRight = function(column){
var column = this.columns[this.rightCol],
rows;
if(column && column.modules.vdomHoz.leftPos > this.vDomScrollPosRight){
rows = this.table.rowManager.getVisibleRows();
column.modules.vdomHoz.visible = false;
rows.forEach((row) => {
if(row.type !== "group"){
var cell = row.getCell(column);
row.getElement().removeChild(cell.getElement());
}
});
this.vDomPadRight += column.getWidth();
this.element.style.paddingRight = this.vDomPadRight + "px";
this.rightCol --;
this.removeColRight();
}
};
VDomHoz.prototype.removeColLeft = function(){
var column = this.columns[this.leftCol],
rows;
if(column && column.modules.vdomHoz.rightPos < this.vDomScrollPosLeft){
rows = this.table.rowManager.getVisibleRows();
rows.forEach((row) => {
if(row.type !== "group"){
var cell = row.getCell(column);
row.getElement().removeChild(cell.getElement());
}
});
this.vDomPadLeft += column.getWidth();
this.element.style.paddingLeft = this.vDomPadLeft + "px";
this.leftCol ++;
this.removeColLeft();
}
};
VDomHoz.prototype.initializeRow = function(row){
if(row.type !== "group"){
row.modules.vdomHoz = {
leftCol:this.leftCol,
rightCol:this.rightCol,
};
for(let i = this.leftCol; i <= this.rightCol; i++){
let column = this.columns[i];
if(column && column.visible){
let cell = row.getCell(column);
row.getElement().appendChild(cell.getElement());
cell.cellRendered();
}
}
}
};
VDomHoz.prototype.reinitializeRow = function(row, force){
if(row.type !== "group"){
if(force || !row.modules.vdomHoz || row.modules.vdomHoz.leftCol !== this.leftCol || row.modules.vdomHoz.rightCol !== this.rightCol){
var rowEl = row.getElement();
while(rowEl.firstChild) rowEl.removeChild(rowEl.firstChild);
this.initializeRow(row);
}
}
};