简体   繁体   中英

jQuery Load More Data When Scroll Position at Bottom

I have jQuery Scroll Auto Load More. The function is to load more data from database using PHP.

The function is running OK, when I try to scroll then the next data will load. Until I facing problem, when I put the scroll to bottom then I refresh the page, the function is load but it always show double data.

Here is my JS function so far:

$(document).ready(function()
{
     $('#content').scrollPagination(
     {
         nop : 10,
         id : 10,
         offset : 0,
         error : 'You have reached the end of the post.',   
         delay : 500,
         scroll : true
     });
});

(function($)
{
     $.fn.scrollPagination = function(options)
     {
          var settings =
          {
               nop     : 10, // The number of posts per scroll to be loaded
               offset  : 0, // Initial offset, begins at 0 in this case
               error   : 'No More Posts!',
               delay   : 500,
               scroll  : true
          }

          if(options)
          {
               $.extend(settings, options);
          }

          return this.each(function()
          {
               $this = $(this);
               $settings = settings;
               var offset = $settings.offset;
               var busy = false;
               if($settings.scroll == true) $initmessage = '';
               else $initmessage = 'Click for more';
               $this.append('<div class="content"></div><div class="loading-bar">'+$initmessage+'</div>');

               $('.animation_images').show();

               function getData()
               {
                    $.post('load_post_user.php', {
                    action        : 'scrollpagination',
                    number        : $settings.nop,
                    offset        : offset,
                    uid           : '<?php echo $q_uid; ?>',
                    }, function(data) {
                    $this.find('.loading-bar').html($initmessage);
                    $('.animation_images').hide();

                    if(data == "") {
                    $this.find('.loading-bar').html($settings.error);
                    }
                    else {
                    offset = offset+$settings.nop;
                    $this.find('.content').append(data);
                    busy = false;
                    }
                 });
                }

                getData();

                if($settings.scroll == true) {
                     $(window).scroll(function() {
                     if($(window).scrollTop() + $(window).height() > $this.height() && !busy) {
                         busy = true;
                         $('.animation_images').hide();
                         $this.find('.loading-bar').html('<img src="../assets/img/processing.gif"/>');

                         setTimeout(function() {
                             getData();
                         }, $settings.delay);
                        }
                       });
                      }

                 $this.find('.loading-bar').click(function() {
                      if(busy == false) {
                          busy = true;
                          getData();
                      }
                 });
               });
              }
             })(jQuery);

As discussed in chat this is a problem with asynchronous calls and I answer here for the sake of completeness.

The scripts contains an initial getData() - call that initially fires for every element that scrollPagination was called on when the script is loaded.

getData sets off an asynchronous "AJAX" - call to the backend with the given parameters, initially set to nop = 10 and offset = 0 .

Right after this call, a scroll-handler to the window is bound. It may be different from browser to browser, but this usually fires too when the page is fully loaded.

If the scrollposition is set to the bottom of the page, the if-clause in this handler is true while the initial AJAX-request is still being handled, and that is the problem here.

The offset is being set to the new correct value after this request returns successfully. As the request did not return anything at the point the scroll-handler is fired the first time, it is still set to 0, resulting in the exact same request with a parameter of &offset=0 sent with it and of course, returning the same results as the first request.

This happens because the busy bool isn't being set for the first call, so my recommended approach would be to set busy=true; not before calling getData() , but right at the start of this function.

function getData()
{
    busy = true;
    $.post('load_post_user.php', {
        ....
    }
}

This will prevent a second request being sent in general when scrolling if another request is already being executed.

If you still want the second part of the content being loaded when initially having the scrollposition at the bottom of the page, you would need to introduce something like a initial - flag;

At the beginning of your initialization:

return this.each(function()
{
    $this = $(this);
    $settings = settings;
    var offset = $settings.offset;
    var busy = false;
    var initial = true;    //set to true only this one time when initialising
    ....

and edit the check in your scroll-handler:

if($settings.scroll == true) {
    $(window).scroll(function() {

    //only execute if either busy is false or initial is true
    if($(window).scrollTop() + $(window).height() > $this.height() && (!busy || initial) {

        if(initial && offset === 0){
            // set correct offset for the second call
            offset += $settings.nop;
        }
        initial = false; //set initial to false and not set it back to true anywhere else
    ....

This way the second scroll call will be executed nontheless but with the correct offset.

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