简体   繁体   中英

infinity scroll: Load all data from database and scroll to show more

I am using infinity scroll in my project. First it will fetch few records from MySQL database and show on page. Once page scroll down it make ajax query to server and load more data.

Is it possible to fetch all data at once from mysql database in json format and then perform load more on client side. So, basically I want no ajax request to database.

Here is the code which is working fine if I make ajax request on page scroll.

flag = true;
$(window).scroll(function() {
    if($(window).scrollTop() + $(window).height() == $(document).height()){
        first = $('#first').val();
        limit = $('#limit').val();
        no_data = true;
        if(flag && no_data){
            flag = false;
            $('#loader').show();
            $.ajax({
                url : 'ajax_html.php',
                method: 'post',
                data: {
                   start : first,
                   limit : limit
                },
                success: function( data ) {
                    flag = true;
                    $('#loader').hide();
                    if(data !=''){

                        first = parseInt($('#first').val());
                        limit = parseInt($('#limit').val());
                        $('#first').val( first+limit );
                        $('#timeline-conatiner').append( '<li class="year">'+year+'</li>');

                        $('#timeline-conatiner').append( data );
                        year--;
                    }else{
                        alert('No more data to show');
                        no_data = false;
                    }
                },
                error: function( data ){
                    flag = true;
                    $('#loader').hide();
                    no_data = false;
                    alert('Something went wrong, Please contact admin');
                }
            });
        }


    }
}); 

This is untested and just an example of the method, Sorry I don't have time for a full example but this should give you the idea.

 //data cache
 var cache = ['one','two', 'three' .....];
 //current location in cache
 var current = 0; 
 //ajax request object
 var request;

 if($(window).scrollTop() + $(window).height() == $(document).height()){
      var cache_total = cache.length;
      //add next item to page & increase the current pointer
      $('#timeline-conatiner').append( cache[current] );
      ++current;

      if( current - cache.length < 50 ){
           //if we only have 50 items not shown in cache pull next results with ajax and add to cache

           if( !request ){
                //also youll want to keep track if you have a pending request that hasn't returned yet, to prevent race conditions.
                request = $.ajax( .... ).success( function( data ){
                     $.extend( cache, data ); //or push each if you like
                }).always( function(){
                     request = false; //should be false on finish but just because.
                });
            } //end if request

       //make sure to properly offset the data using the total in the cache to prevent pulling duplicates. eg SELECT ... LIMIT {cache.length}, 50
      } // end if cached
 } //end scroll

See the issue with what you have above is the user needs to wait for the ajax call to finish, which essentially turns it into a synchronous request ( like reloading the page ). You want to keep it asynchronous as ajax is intended to be. So instead of displaying the results of the ajax, you buffer them and keep some data you are not showing. Then on scroll show some buffered data and after that fill the cache back up.

Obviously this makes it much more complex to code, but the advantage is you don't need to pull a massive amount of data at one time and the user wont get the delay from halting on the ajax request. You'll have to balance the time the request takes with the amount of data in the cache so you always have some data in there. This depends on how much space data takes to render and how long the ajax query takes.

If all data has been retrieved and added to DOM, then following script may be helpful. First add hidden class to extra elements. Run this script after DOM is created.

$(".elements").each(function(index, el) { // `elements` is the common class for all elements on which this functionality is to be done
    if (index >= maxLimitToShow) { // maxLimitToShow - number of elements to show in the beginning
        $(el).addClass("hidden"); // for extra elements
    }
});

Add css for class hidden

.hidden {
    display: none;
}

And check when scroll has reached the bottom of page to show more items.

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() == $(document).height()) {  // checks if scroll reached at bottom
       var elements = $(".elements.hidden"); // fetch all hidden elements
       elements.each(function (index, el) {
         if (index < singleRowLimit) { // singleRowLimit  - number of elements to show in one scroll
             $(el).removeClass('hidden');
         }
     });
   }
});

EDIT - without using CSS - hide/show

If all data has been retrieved and added to DOM, then following script may be helpful. First add hidden class to extra elements. Run this script after DOM is created.

$(".elements").each(function(index, el) { // `elements` is the common class for all elements on which this functionality is to be done
    if (index >= maxLimitToShow) { // maxLimitToShow - number of elements to show in the beginning
        $(el).addClass("hidden").hide(); // for extra elements
    }
});

And check when scroll has reached the bottom of page to show more items.

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() == $(document).height()) {  // checks if scroll reached at bottom
       var elements = $(".elements.hidden"); // fetch all hidden elements
       elements.each(function (index, el) {
         if (index < singleRowLimit) { // singleRowLimit  - number of elements to show in one scroll
             $(el).removeClass('hidden').show();
         }
     });
   }
});

I would say you don't need infinity scroller (or whatever) at all to do what u want... but since u have it all nicely working and I suspect u might decide u want that 'lazy load' type functionality back at some point u could do the lazy thing...

Simply try playing around with the first and limit param values in your example...

Say... first = 0 and limit = some really big number...

I think u can set some values and force a single ajax call on page load very easily.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM