PATCH: Small Scroller performance enhancement

PATCH: Small Scroller performance enhancement

jlabancajlabanca Posts: 6Questions: 0Answers: 0
edited November 2012 in Plug-ins
Scroller#_fnDrawCallback() forces browsers layout twice, but only needs to do it once with a very simple change. It saves about 30ms for me in IE, which is a lot if you're filtering rows as the user types.

[code]
"_fnDrawCallback": function ()
{
var
that = this,
// NOTE: scrollTop forces browser layout
iScrollTop = this.dom.scroller.scrollTop,
iScrollBottom = iScrollTop + this.s.viewportHeight,
// CHANGE: Calculate iTableHeight here while the layout is still valid
iTableHeight = $(this.s.dt.nTable).height();

/* Set the height of the scrolling forcer to be suitable for the number of rows
* in this draw
*/
this.dom.force.style.height = (this.s.rowHeight * this.s.dt.fnRecordsDisplay())+"px";

/* Calculate the position that the top of the table should be at */
var iTableTop = (this.s.rowHeight*this.s.dt._iDisplayStart);
if ( this.s.dt._iDisplayStart === 0 )
{
iTableTop = 0;
}
else if ( this.s.dt._iDisplayStart === this.s.dt.fnRecordsDisplay() - this.s.dt._iDisplayLength )
{
iTableTop = this.s.rowHeight * this.s.dt._iDisplayStart;
}

this.dom.table.style.top = iTableTop+"px";

/* Cache some information for the scroller */
this.s.tableTop = iTableTop;
// CHANGE: Use the precalculated iTableHeight
// this.s.tableBottom = $(this.s.dt.nTable).height() + this.s.tableTop;
this.s.tableBottom = iTableHeight + this.s.tableTop;

this.s.redrawTop = iScrollTop - ( (iScrollTop - this.s.tableTop) * this.s.boundaryScale );
this.s.redrawBottom = iScrollTop + ( (this.s.tableBottom - iScrollBottom) * this.s.boundaryScale );

if ( this.s.trace )
{
console.log(
"Table redraw. Table top: "+iTableTop+"px "+
"Table bottom: "+this.s.tableBottom+" "+
"Scroll boundary top: "+this.s.redrawTop+" "+
"Scroll boundary bottom: "+this.s.redrawBottom+" "+
"Rows drawn: "+this.s.dt._iDisplayLength);
}

/* Because of the order of the DT callbacks, the info update will
* take precidence over the one we want here. So a 'thread' break is
* needed
*/
setTimeout( function () {
that._fnInfo.call( that );
}, 0 );

/* Restore the scrolling position that was saved by DataTable's state saving
* Note that this is done on the second draw when data is Ajax sourced, and the
* first draw when DOM soured
*/
if ( this.s.dt.oFeatures.bStateSave && this.s.dt.oLoadedState !== null &&
typeof this.s.dt.oLoadedState.iScroller != 'undefined' )
{
if ( (this.s.dt.sAjaxSource !== null && this.s.dt.iDraw == 2) ||
(this.s.dt.sAjaxSource === null && this.s.dt.iDraw == 1) )
{
setTimeout( function () {
$(that.dom.scroller).scrollTop( that.s.dt.oLoadedState.iScroller );
that.s.redrawTop = that.s.dt.oLoadedState.iScroller - (that.s.viewportHeight/2);
}, 0 );
}
}
},
[/code]

Replies

  • jlabancajlabanca Posts: 6Questions: 0Answers: 0
    It might be hard to see, but all I'm suggesting is that you move the line:
    [code]
    $(this.s.dt.nTable).height()
    [/code]

    To the top of the function, before setting this.dom.table.style.top, which invalidates layout.
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Sounds like an excellent plan. It's now in the Scroller 1.1.1.dev nightly :-)

    https://github.com/DataTables/Scroller/commit/d12b61cc9bf74d2764d4215c22ddcf2f8f88798b

    Thanks for this!

    Allan
  • jlabancajlabanca Posts: 6Questions: 0Answers: 0
    Thanks for the quick turnaround. Looking forward to the next release
This discussion has been closed.