diff --git a/src/js/core/rendering/renderers/VirtualDomVertical.js b/src/js/core/rendering/renderers/VirtualDomVertical.js index c4b775b2f..cead649a3 100644 --- a/src/js/core/rendering/renderers/VirtualDomVertical.js +++ b/src/js/core/rendering/renderers/VirtualDomVertical.js @@ -287,9 +287,10 @@ export default class VirtualDomVertical extends Renderer{ rowFragment = document.createDocumentFragment(); i = 0; + index = this.vDomBottom; - while ((i < rowsToRender) && this.vDomBottom < rowsCount -1) { - index = this.vDomBottom + 1, + while ((i < rowsToRender) && this.vDomBottom < rowsCount -1) { + index++; row = rows[index]; this.styleRow(row, index); @@ -310,9 +311,9 @@ export default class VirtualDomVertical extends Renderer{ } element.appendChild(rowFragment); - + // NOTE: The next 3 loops are separate on purpose - // This is to batch up the dom writes and reads which drastically improves performance + // This is to batch up the dom writes and reads which drastically improves performance renderedRows.forEach((row) => { row.rendered(); @@ -330,7 +331,7 @@ export default class VirtualDomVertical extends Renderer{ renderedRows.forEach((row) => { rowHeight = row.getHeight(); - + if(totalRowsRendered < topPad){ topPadHeight += rowHeight; }else { @@ -389,66 +390,71 @@ export default class VirtualDomVertical extends Renderer{ _addTopRow(rows, fillableSpace){ var table = this.tableElement, - addedRows = [], paddingAdjust = 0, index = this.vDomTop -1, - i = 0, - working = true; - - while(working){ - if(this.vDomTop){ - let row = rows[index], - rowHeight, initialized; - - if(row && i < this.vDomMaxRenderChain){ - rowHeight = row.getHeight() || this.vDomRowHeight; - initialized = row.initialized; - - if(fillableSpace >= rowHeight){ - - this.styleRow(row, index); - table.insertBefore(row.getElement(), table.firstChild); - - if(!row.initialized || !row.heightInitialized){ - addedRows.push(row); - } + i = 0 + , working = true; + + let numRowsToAdd = Math.ceil(fillableSpace / this.vDomRowHeight); + while(working && numRowsToAdd && this.vDomTop && fillableSpace > 0 && i < this.vDomMaxRenderChain){ + const docFrag = document.createDocumentFragment(); + const addedRows = []; + const newInitRows = []; + while( i < numRowsToAdd){ + let row = rows[index], rowHeight; + if(!row){ + working = false; + break; + } - row.initialize(); + rowHeight = row.getHeight() || this.vDomRowHeight; + if(fillableSpace < rowHeight){ + working = false; + break; + } - if(!initialized){ - rowHeight = row.getElement().offsetHeight; + this.styleRow(row, index); + if(!row.initialized){ + newInitRows.push(row); + }else{ + addedRows.push(row); + } - if(rowHeight > this.vDomWindowBuffer){ - this.vDomWindowBuffer = rowHeight * 2; - } - } + row.initialize(false, true); + docFrag.insertBefore(row.getElement(), docFrag.firstChild); - fillableSpace -= rowHeight; - paddingAdjust += rowHeight; + this.vDomTop--; + index--; + i++; + } + table.insertBefore(docFrag, table.firstChild); - this.vDomTop--; - index--; - i++; + for (let row of newInitRows){ + row.clearCellHeight(); + } - }else{ - working = false; - } + this._quickNormalizeRowHeight(newInitRows); - }else{ - working = false; + for (let row of newInitRows){ + const rowHeight = row.getElement().offsetHeight; + if(rowHeight > this.vDomWindowBuffer){ + this.vDomWindowBuffer = rowHeight * 2; } + } - }else{ - working = false; + let totalRowHeight = 0; + for (let row of addedRows){ + const rowHeight = row.getHeight() || row.getElement().offsetHeight; + totalRowHeight += rowHeight; + + fillableSpace -= rowHeight; + paddingAdjust += rowHeight; } - } - for (let row of addedRows){ - row.clearCellHeight(); + const avgRowHeight = Math.max(totalRowHeight / addedRows.length, 0); + numRowsToAdd = avgRowHeight > 0 ? Math.ceil(fillableSpace / avgRowHeight) : 0; } - this._quickNormalizeRowHeight(addedRows); - if(paddingAdjust){ this.vDomTopPad -= paddingAdjust; @@ -511,59 +517,71 @@ export default class VirtualDomVertical extends Renderer{ _addBottomRow(rows, fillableSpace){ var table = this.tableElement, - addedRows = [], paddingAdjust = 0, index = this.vDomBottom + 1, i = 0, working = true; - while(working){ - let row = rows[index], - rowHeight, initialized; + let numRowsToAdd = Math.ceil(fillableSpace / this.vDomRowHeight); + while(working && numRowsToAdd && this.vDomTop && fillableSpace > 0 && i < this.vDomMaxRenderChain){ + const docFrag = document.createDocumentFragment(); + const addedRows = []; + const newInitRows = []; + while( i < numRowsToAdd){ + let row = rows[index], rowHeight; + if(!row){ + working = false; + break; + } - if(row && i < this.vDomMaxRenderChain){ rowHeight = row.getHeight() || this.vDomRowHeight; - initialized = row.initialized; + if(fillableSpace < rowHeight){ + working = false; + break; + } - if(fillableSpace >= rowHeight){ + this.styleRow(row, index); + if(!row.initialized){ + newInitRows.push(row); + }else{ + addedRows.push(row); + } - this.styleRow(row, index); - table.appendChild(row.getElement()); + row.initialize(false, true); + docFrag.append(row.getElement()); - if(!row.initialized || !row.heightInitialized){ - addedRows.push(row); - } + this.vDomTop++; + index++; + i++; + } + table.append(docFrag); - row.initialize(); + for (let row of newInitRows){ + row.clearCellHeight(); + } - if(!initialized){ - rowHeight = row.getElement().offsetHeight; + this._quickNormalizeRowHeight(newInitRows); - if(rowHeight > this.vDomWindowBuffer){ - this.vDomWindowBuffer = rowHeight * 2; - } - } + for (let row of newInitRows){ + const rowHeight = row.getElement().offsetHeight; + if(rowHeight > this.vDomWindowBuffer){ + this.vDomWindowBuffer = rowHeight * 2; + } + } - fillableSpace -= rowHeight; - paddingAdjust += rowHeight; + let totalRowHeight = 0; + for (let row of addedRows){ + const rowHeight = row.getHeight() || row.getElement().offsetHeight; + totalRowHeight += rowHeight; - this.vDomBottom++; - index++; - i++; - }else{ - working = false; - } - }else{ - working = false; + fillableSpace -= rowHeight; + paddingAdjust += rowHeight; } - } - for (let row of addedRows){ - row.clearCellHeight(); + const avgRowHeight = Math.max(totalRowHeight / addedRows.length, 0); + numRowsToAdd = avgRowHeight > 0 ? Math.ceil(fillableSpace / avgRowHeight) : 0; } - this._quickNormalizeRowHeight(addedRows); - if(paddingAdjust){ this.vDomBottomPad -= paddingAdjust;