UNPKG

tabulator-tables

Version:

Interactive table generation JavaScript library

449 lines (334 loc) 10.3 kB
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); } } };