DataTables / DataTables/Scroller
Multiple Ajax Requests ServerSide - Part 2 (Possible Partial Solution)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 83
- Forks
- 66
- PR merge metrics
- No merged PRs in 30d
Description
Hello again,
Sorry to take your time again, but i came up with a possible partial solution to the problem, and i would like to share with you, so you may consider it and tell me if i'm doing something wrong.
I came up with a level system, based on a certain amount of rows enough to avoid making so many AJAX requests, and overlapping just a small part to ensure the infinite scroll position.
I still have two problems to solve:
1 - When a new request is made and rows are updated, the position of the table is higher/lower than it should be, by 1 or 2 lines. I think this problem is happening because Scroller is forcing start row to be an odd one.
2 - Cache the small part left so no overlapping exists at all.
First, in Settings (this.s), after "loaderVisible: false", i define a start level = 1;
Then i update the _fnScroll function as it follows (changes are marked with (AM):
/**
- Scrolling function - fired whenever the scrolling position is changed.
- This method needs to use the stored values to see if the table should be
- redrawn as we are moving towards the end of the information that is
- currently drawn or not. If needed, then it will redraw the table based on
- the new position.
- @returns {void}
- @private
*/
"_fnScroll": function ()
{
var
that = this,
heights = this.s.heights,
iScrollTop = this.dom.scroller.scrollTop,
iTopRow;
if ( this.s.skip ) {
return;
}
if ( this.s.ingnoreScroll ) {
return;
}
/* If the table has been sorted or filtered, then we use the redraw that
* DataTables as done, rather than performing our own
*/
if ( this.s.dt.bFiltered || this.s.dt.bSorted ) {
this.s.lastScrollTop = 0;
return;
}
/* Update the table's information display for what is now in the viewport */
this._fnInfo();
/* We don't want to state save on every scroll event - that's heavy
* handed, so use a timeout to update the state saving only when the
* scrolling has finished
*/
clearTimeout( this.s.stateTO );
this.s.stateTO = setTimeout( function () {
that.s.dt.oApi._fnSaveState( that.s.dt );
}, 250 );
/* Check if the scroll point is outside the trigger boundary which would required
* a DataTables redraw
*/
if ( iScrollTop < this.s.redrawTop || iScrollTop > this.s.redrawBottom ) {
var preRows = Math.ceil( ((this.s.displayBuffer-1)/2) * this.s.viewportRows );
if ( Math.abs( iScrollTop - this.s.lastScrollTop ) > heights.viewport || this.s.ani ) {
iTopRow = parseInt(this._domain( 'physicalToVirtual', iScrollTop ) / heights.row, 10) - preRows;
this.s.topRowFloat = (this._domain( 'physicalToVirtual', iScrollTop ) / heights.row);
}
else {
iTopRow = this.fnPixelsToRow( iScrollTop - preRows);
this.s.topRowFloat = this.fnPixelsToRow( iScrollTop, false );
}
/* At the start of the table */
if ( iTopRow <= 0 ) {
iTopRow = 0;
}
/* At the end of the table */
else if ( iTopRow + this.s.dt._iDisplayLength > this.s.dt.fnRecordsDisplay() ) {
iTopRow = this.s.dt.fnRecordsDisplay() - this.s.dt._iDisplayLength;
if ( iTopRow < 0 ) {
iTopRow = 0;
}
}
// For the row-striping classes (odd/even) we want only to start
// on evens otherwise the stripes will change between draws and
// look rubbish
else if ( iTopRow % 2 !== 0 ) {
iTopRow++;
}
// (AM) Set level boundary line based on the maximum number of rows
// necessary to ensure the minimum of Ajax requests
// and also the infinite scrolling behavior at the same time.
var levelBoundary = this.s.dt._iDisplayLength - preRows;
// (AM) Level changes when boundary line is crossed
var level = iTopRow > levelBoundary ? Math.ceil( iTopRow / levelBoundary ) : 1;
// (AM) Only request new data when level changes
if (level !== this.s.level) {
// (AM) Local displayStart definition
var displayStart = null;
// (AM) Scroll Up/Down Start Position
if (level > this.s.level) {
displayStart = iTopRow;
} else {
displayStart = (iTopRow - (this.s.dt._iDisplayLength - preRows));
if (displayStart < 0) {
displayStart = 0;
}
}
// (AM) Update Level
this.s.level = level;
/* Cache the new table position for quick lookups */
this.s.tableTop = $(this.s.dt.nTable).offset().top;
this.s.tableBottom = $(this.s.dt.nTable).height() + this.s.tableTop;
var draw = function () {
if ( that.s.scrollDrawReq === null ) {
that.s.scrollDrawReq = iScrollTop;
}
// (AM) Assign displayStart
that.s.dt._iDisplayStart = displayStart;
if ( that.s.dt.oApi._fnCalculateEnd ) { // Removed in 1.10
that.s.dt.oApi._fnCalculateEnd( that.s.dt );
}
that.s.dt.oApi._fnDraw( that.s.dt );
};
/* Do the DataTables redraw based on the calculated start point - note that when
* using server-side processing we introduce a small delay to not DoS the server...
*/
if ( this.s.dt.oFeatures.bServerSide ) {
clearTimeout( this.s.drawTO );
this.s.drawTO = setTimeout( draw, this.s.serverWait );
}
else {
draw();
}
if ( this.dom.loader && ! this.s.loaderVisible ) {
this.dom.loader.css( 'display', 'block' );
this.s.loaderVisible = true;
}
}
}
this.s.lastScrollTop = iScrollTop;
this.s.stateSaveThrottle();
}
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the Scroller settings and the _fnScroll function shown in the issue, including the level and displayStart calculations. Reproduce server-side scrolling and investigate the reported one- or two-row position shift and overlapping requests; done means the scrolling position remains stable while unnecessary AJAX requests are avoided.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- frontend, performance
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100