DataTables / DataTables/Scroller

Multiple Ajax Requests ServerSide - Part 2 (Possible Partial Solution)

Open
#46 1 comment 0 reactions 0 assignees View on GitHub

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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.