ericwaldheim
10-28-2006, 09:12 PM
My app needs to quickly unload many rows from a grid and replace them with many other rows.
I've added a couple of optimizations to the previously posted lazy row rendering.
Basically I'm just trying to avoid the slow DOM calls.
For removing all rows from a grid (1000 rows x 3 columns), time went from 2.5 sec to 0.1 sec.
For inserting into an empty grid (1500 rows x 3 columns), time went from 3.0 sec to 0.5 sec.
(this is the time required to 'lazy render' the first two pages of rows.)
With all three optimizations time went from 18 sec to 1.3 sec (remove 1000 rows, add 1500 rows).
I've only tested this on Firefox.
Thanks,
Eric
YAHOO.ext.grid.FastGridView = function(){
YAHOO.ext.grid.FastGridView.superclass.constructor.call(this);
this.rendered = [];
};
YAHOO.extendX(YAHOO.ext.grid.FastGridView, YAHOO.ext.grid.GridView);
YAHOO.ext.grid.FastGridView.prototype.init = function(grid){
YAHOO.ext.grid.FastGridView.superclass.init.call(this, grid);
this.grid.maxRowsToMeasure = 1; // hack
this.grid.addListener('bodyscroll', this.lazyRender, this, true);
}
YAHOO.ext.grid.FastGridView.prototype.insertRows
= function(dataModel, firstRow, lastRow)
{
this.updateBodyHeight();
this.adjustForScroll(true);
var renderers = this.getColumnRenderers();
var dindexes = this.getDataIndexes();
var colCount = this.grid.colModel.getColumnCount();
var beforeRow = null;
var bt = this.getBodyTable();
if(firstRow < bt.childNodes.length){
beforeRow = bt.childNodes[firstRow];
}
if (firstRow == 0 && lastRow == dataModel.getRowCount() - 1)
{
var s = "";
var stripeRows = this.grid.stripeRows;
var stripe = false;
for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
var alt = stripe && stripeRows ? ' ygrid-row-alt' : '';
s += "<span class='ygrid-row"+ alt +"' style='top:"
+ (rowIndex * this.rowHeight) + "px' rowIndex:'"+rowIndex
+"'></span>";
this.rendered[rowIndex] = false;
stripe = !stripe;
}
bt.innerHTML = bt.innerHTML + s;
}
else
{
for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
var row = document.createElement('span');
row.className = 'ygrid-row';
row.style.top = (rowIndex * this.rowHeight) + 'px';
this.rendered[rowIndex] = false;
if(beforeRow){
bt.insertBefore(row, beforeRow);
}else{
bt.appendChild(row);
}
}
this.updateRowIndexes(firstRow);
}
this.adjustForScroll();
this.lazyRender();
};
YAHOO.ext.grid.FastGridView.prototype.lazyRender = function()
{
var y = this.wrap.scrollTop;
var rowHeight = this.getRowHeight();
var rowIndex = (y == 0 ? 0 : Math.floor(y / rowHeight));
var grid = this.grid;
var dataModel = grid.getDataModel();
var rowCount = dataModel.getRowCount();
if (rowIndex >= rowCount ){ return; }
var numDisplayedRows = Math.ceil(this.wrap.clientHeight / rowHeight);
var lastRowIndex = Math.min(rowCount - 1, rowIndex + numDisplayedRows * 2);
var colCount = grid.colModel.getColumnCount();
var renderers = this.getColumnRenderers();
var dindexes = this.getDataIndexes();
while (rowIndex <= lastRowIndex)
{
if (!this.rendered[rowIndex])
{
var row = grid.getRow(rowIndex);
this.renderRow(dataModel, row, rowIndex, colCount, renderers, dindexes);
this.rendered[rowIndex] = true;
}
++rowIndex;
}
}
YAHOO.ext.grid.FastGridView.prototype.deleteRows
= function(dataModel, firstRow, lastRow)
{
this.updateBodyHeight();
// first make sure they are deselected
var bt = this.getBodyTable();
if (!this.grid.dataModel.getRowCount())
{
this.grid.selModel.clearSelections();
bt.innerHTML = "";
}
else
{
this.grid.selModel.deselectRange(firstRow, lastRow);
var rows = []; // get references because the rowIndex will change
for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
rows.push(bt.childNodes[rowIndex]);
}
for(var i = 0; i < rows.length; i++){
bt.removeChild(rows[i]);
rows[i] = null;
}
rows = null;
this.updateRowIndexes(firstRow);
this.adjustForScroll();
}
};
I've added a couple of optimizations to the previously posted lazy row rendering.
Basically I'm just trying to avoid the slow DOM calls.
For removing all rows from a grid (1000 rows x 3 columns), time went from 2.5 sec to 0.1 sec.
For inserting into an empty grid (1500 rows x 3 columns), time went from 3.0 sec to 0.5 sec.
(this is the time required to 'lazy render' the first two pages of rows.)
With all three optimizations time went from 18 sec to 1.3 sec (remove 1000 rows, add 1500 rows).
I've only tested this on Firefox.
Thanks,
Eric
YAHOO.ext.grid.FastGridView = function(){
YAHOO.ext.grid.FastGridView.superclass.constructor.call(this);
this.rendered = [];
};
YAHOO.extendX(YAHOO.ext.grid.FastGridView, YAHOO.ext.grid.GridView);
YAHOO.ext.grid.FastGridView.prototype.init = function(grid){
YAHOO.ext.grid.FastGridView.superclass.init.call(this, grid);
this.grid.maxRowsToMeasure = 1; // hack
this.grid.addListener('bodyscroll', this.lazyRender, this, true);
}
YAHOO.ext.grid.FastGridView.prototype.insertRows
= function(dataModel, firstRow, lastRow)
{
this.updateBodyHeight();
this.adjustForScroll(true);
var renderers = this.getColumnRenderers();
var dindexes = this.getDataIndexes();
var colCount = this.grid.colModel.getColumnCount();
var beforeRow = null;
var bt = this.getBodyTable();
if(firstRow < bt.childNodes.length){
beforeRow = bt.childNodes[firstRow];
}
if (firstRow == 0 && lastRow == dataModel.getRowCount() - 1)
{
var s = "";
var stripeRows = this.grid.stripeRows;
var stripe = false;
for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
var alt = stripe && stripeRows ? ' ygrid-row-alt' : '';
s += "<span class='ygrid-row"+ alt +"' style='top:"
+ (rowIndex * this.rowHeight) + "px' rowIndex:'"+rowIndex
+"'></span>";
this.rendered[rowIndex] = false;
stripe = !stripe;
}
bt.innerHTML = bt.innerHTML + s;
}
else
{
for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
var row = document.createElement('span');
row.className = 'ygrid-row';
row.style.top = (rowIndex * this.rowHeight) + 'px';
this.rendered[rowIndex] = false;
if(beforeRow){
bt.insertBefore(row, beforeRow);
}else{
bt.appendChild(row);
}
}
this.updateRowIndexes(firstRow);
}
this.adjustForScroll();
this.lazyRender();
};
YAHOO.ext.grid.FastGridView.prototype.lazyRender = function()
{
var y = this.wrap.scrollTop;
var rowHeight = this.getRowHeight();
var rowIndex = (y == 0 ? 0 : Math.floor(y / rowHeight));
var grid = this.grid;
var dataModel = grid.getDataModel();
var rowCount = dataModel.getRowCount();
if (rowIndex >= rowCount ){ return; }
var numDisplayedRows = Math.ceil(this.wrap.clientHeight / rowHeight);
var lastRowIndex = Math.min(rowCount - 1, rowIndex + numDisplayedRows * 2);
var colCount = grid.colModel.getColumnCount();
var renderers = this.getColumnRenderers();
var dindexes = this.getDataIndexes();
while (rowIndex <= lastRowIndex)
{
if (!this.rendered[rowIndex])
{
var row = grid.getRow(rowIndex);
this.renderRow(dataModel, row, rowIndex, colCount, renderers, dindexes);
this.rendered[rowIndex] = true;
}
++rowIndex;
}
}
YAHOO.ext.grid.FastGridView.prototype.deleteRows
= function(dataModel, firstRow, lastRow)
{
this.updateBodyHeight();
// first make sure they are deselected
var bt = this.getBodyTable();
if (!this.grid.dataModel.getRowCount())
{
this.grid.selModel.clearSelections();
bt.innerHTML = "";
}
else
{
this.grid.selModel.deselectRange(firstRow, lastRow);
var rows = []; // get references because the rowIndex will change
for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
rows.push(bt.childNodes[rowIndex]);
}
for(var i = 0; i < rows.length; i++){
bt.removeChild(rows[i]);
rows[i] = null;
}
rows = null;
this.updateRowIndexes(firstRow);
this.adjustForScroll();
}
};