Last updated October 29, 2012. Created by hansrossel on March 8, 2012.
Edited by revagomes, Morten Najbjerg, rli, mkalbere. Log in to edit this page.

Convert any pager (views, search, ...) to an autoloading endless scroll autopager with just a few lines of code.

Step 1:

Download the file jquery.infinitescroll.min.js from https://github.com/paulirish/infinite-scroll and put it in /sites/all/themes/YOURTHEME/js/jquery.infinitescroll.min.js.

If you are using responsive design with flexible images (and thus no widht/height in the html), it is recommended to also add the imagesloaded plugin to be sure your images have a width and height before they get added. Add the file jquery.imagesloaded.min.js from https://github.com/desandro/imagesloaded. If you don't install this plugin you need to remove the $container.imagesLoaded( function(){ wrapper from the examples below.

Step 2:

Add the js file to the info file of your theme

Step 3:

Make a custom javascript file /sites/all/themes/YOURTHEME/js/YOURTHEME.js with contents (Drupal 6).

Drupal 6 code

/**
* Implementation of autopager @see https://github.com/paulirish/infinite-scroll
* All views that have the "autopager" class will have an autopager
*/
Drupal.behaviors.viewsInfiniteScroll = function(context) {
  $(function(){
    var $container = $('div.autopager div.view-content');
    $container.imagesLoaded( function(){
      $container.infinitescroll({
        navSelector  : 'div.autopager .pager',    // selector for the paged navigation
        nextSelector : 'div.autopager .pager-next a',  // selector for the NEXT link (to page 2)
        itemSelector : 'div.autopager .views-row',     // selector for all items you'll retrieve
        loading: {
          finishedMsg: 'No more pages to load.',
          img: Drupal.settings.basePath + 'sites/all/themes/YOURTHEME/images/loading.gif'
        }
      })
    })
  });
}

Drupal 7 code

(function ($) {
  Drupal.behaviors.viewsInfiniteScroll = {
    attach: function (context, settings) {
      $(function(){
        var $container = $('div.autopager div.view-content');
        $container.imagesLoaded( function(){
          $container.infinitescroll({
            navSelector  : 'div.autopager .pager',    // selector for the paged navigation
            nextSelector : 'div.autopager .pager-next a',  // selector for the NEXT link (to page 2)
            itemSelector : 'div.autopager .views-row',     // selector for all items you'll retrieve
            loading: {
              finishedMsg: 'No more pages to load.',
              img: Drupal.settings.basePath + 'sites/all/themes/YOURTHEME/images/loading.gif'
            }
        })
    })
  });
  }
};
})(jQuery);

The above example converts the pager of every view that has the class "autopager" (which you can set in the views interface) to an auto load more pager.

You can easily adapt the css classes to target the pager of a list of search results or any other pager. Just make sure the classes are specific enough so you target only one pager in case there are blocks that use views or others.

The default loading image can be found at http://www.infinite-scroll.com/loading.gif, but you can use any loading image.

More settings

In the "All options" section of http://www.infinite-scroll.com/ you can find more information how to change loading text and other options.

Adapt the javascript code if you don't want an automatic loading but a load more button: http://www.infinite-scroll.com/trigger.html

Example code

$('#body').infinitescroll({
      navSelector  : "a#next:last",
                     // selector for the paged navigation (it will be hidden)
      nextSelector : "a#next:last",
                     // selector for the NEXT link (to page 2)
      itemSelector : "#body p"
                     // selector for all items you'll retrieve
    });
    // kill scroll binding
    $(window).unbind('.infscr');
    // hook up the manual click guy.
    $('a#next').click(function(){
      $(document).trigger('retrieve.infscr');
      return false;
    });
    // remove the paginator when we're done.
    $(document).ajaxError(function(e,xhr,opt){
      if (xhr.status == 404) $('a#next').remove();
    });

STEP 4: Add CSS of infinite scroll loader

#infscr-loading {
  position: fixed;
  text-align: center;
  bottom: 300px;
  left: 42%;
  z-index: 100;
  background: white;
  background: hsla( 0, 0%, 100%, 0.9 );
  padding: 20px;
  color: #222;
  font-size: 15px;
  font-weight: bold;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  border-radius: 10px;
}

STEP 5: Make sure jquery version is newer than 1.7.1.

Use one of the methods described in http://drupal.org/node/1058168 for installing a newer version of jquery in Drupal.

Update - 02-02-2012 for D7

Great info, but as said in http://drupal.org/node/1472304#comment-5819046
You need to hack the js lib downloaded (https://github.com/paulirish/infinite-scroll) to support drupal syntax by replacing :
the \/ to & in all occurence matching
"match(/^(.*?page=)2(\/.*|$)/" => "match(/^(.*?page=)2(&.*|$)/"

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

I'm running into a bit of a snag:

If I set a value for items per page in the views pager, I get the loading animation, however it returns with "No More Pages to load" even if there are.

If I set a value of 0 for the items per page, I don't get any animation at all.

Something I missed?

i'm trying to make the infinity scroll script works with a more link button but without success may anyone help me please..this is my script:
(function ($) {

Drupal.behaviors.viewsInfiniteScroll = {
attach: function (context, settings) {
$(function(){

var container = $(".view-content");

container.infinitescroll({
navSelector : "ul.pager",
// selector for the paged navigation (it will be hidden)
nextSelector : "a#next",
// selector for the NEXT link (to page 2)
itemSelector : ".views-row .node-page",
// selector for all items you'll retrieve

});

// kill scroll binding
$(window).unbind('.infscr');

// hook up the manual click guy.
$('a#next').click(function(){
//alert("eeee");
$(document).trigger('retrieve.infscr');
return false;
});

// remove the paginator when we're done.
$(document).ajaxError(function(e,xhr,opt){
if (xhr.status == 404) $('a#next').remove();
});

});
}
};

})(jQuery);

I found a solution here: http://drupal.org/node/1808018

Uses jMasonry with InfiniteScroll. Works like a charm.

Hi All,

What should i change in the Drupal 7 code given below to make it work with search result page.
I have html structure is given like this . I don't know where should i change to work with search result page..

(function ($) {
  Drupal.behaviors.viewsInfiniteScroll = {
    attach: function (context, settings) {
      $(function(){
        var $container = $('div.autopager div.view-content');
        $container.imagesLoaded( function(){
          $container.infinitescroll({
            navSelector  : 'div.autopager .pager',    // selector for the paged navigation
            nextSelector : 'div.autopager .pager-next a',  // selector for the NEXT link (to page 2)
            itemSelector : 'div.autopager .views-row',     // selector for all items you'll retrieve
            loading: {
              finishedMsg: 'No more pages to load.',
              img: Drupal.settings.basePath + 'sites/all/themes/YOURTHEME/images/loading.gif'
            }
        })
    })
  });
  }
};
})(jQuery);

-Mohit

I couldn't get this to work on a simple pager, built calling the pager theme.

By the way, the official demo of infinite scroll's jquery plugin doesn't work either.

Hi Johann Wagner,
I have make it work..
Here is code for my infinitescroll.js

(function($){
Drupal.behaviors.viewsInfiniteScroll = {
    attach: function (context, settings) {
      $(function(){
    if (this.processed) return;
    this.processed=true;
    if ($('.search-results').length==0) return;
        var $container = $('.search-results');
        $container.imagesLoaded( function(){
          $container.infinitescroll({
            navSelector  : 'ul.pager',    // selector for the paged navigation
            nextSelector : '.pager-next a',  // selector for the NEXT link (to page 2)
            itemSelector : '.search-results',     // selector for all items you'll retrieve
            animate      : true,
            msgText  : Drupal.t("Loading new results..."),
            img: '/sites/default/themes/egrievance/images/ajax-loader.gif',
            donetext:Drupal.t('No more results to load.'),
        },function(arrayOfNewElems,state){
        //YOUR CALLBACK STUFF .. To re-attach behaviour if needed
          })
    })
  });
  }
};
})(jQuery);

Remember here i wanted to do it on search result so i added .search-results in $container.

You can download all the files from here https://gist.github.com/mohit-rocks/5660610

With the help of these files and procedure shown above i achieved the infinite scroll.

-Mohit

Hi, I can concurr this works as Mohit said. At first I used the body class of the search page (.page-search) but in his example it is more specific to the container of the retrieved results on the search page; the container selector is the immediate wrapper of the search results (. search-results)

Works like a charm! Thanks!

For some reason, the information on site is outdated. If you want to load more content on click:
https://github.com/paulirish/infinite-scroll/issues/204#issuecomment-747...

So I read, and reread, and then pulled my hair out over this entry. When I finally got down and dirty with the infinite-scroll code, I realized that it was assuming that the first page had an index of 1 (which in Drupal it doesn't,) and didn't seem to be calculating the last page very well. So here is my implementation that works for Drupal default pager (not Views):

Drupal.behaviors.mysiteInfiniteScroll = {
    attach: function (context, settings) {
      $('div.item-list .pager:not(.mysite-scroll-processed)', context).each(function(){
if($('#zone-content-wrapper div.item-list .pager:not(.mysite-scroll-processed) .pager-next').length == 0) return;
               // Determine the Last Page
var $max_page = $('div.item-list li.pager-last > a').attr('href').substring($('div.item-list li.pager-last > a').attr('href').lastIndexOf("page=")+5);
               // Determine the Current Page
var $curr_page = $('div.item-list li.pager-next > a').attr('href').substring($('div.item-list li.pager-next > a').attr('href').lastIndexOf("page=")+5) - 1;
                $('#zone-content-wrapper #block-system-main div.block-inner > div.content').infinitescroll({
navSelector  : 'div.item-list ul.pager',    // selector for the paged navigation
                        nextSelector : 'div.item-list li.pager-next > a',  // selector for the NEXT link (to page 2)
                        itemSelector : '#block-system-main .node',     // selector for all items you'll retrieve
                        loading: {
                                finishedMsg: 'No more pages to load.',
                                img: Drupal.settings.basePath + 'sites/all/themes/mysite/Images/temp_loader.gif'
                        },
bufferPx     : 650, // my own default pixel buffer
donetext     : Drupal.t('No more results to load.'),
maxPage      : $max_page, // calculated above
state: {
currPage : $curr_page // calculated above
},
                   },function(arrayOfNewElems){
        Drupal.attachBehaviors($(this));
});
$(this).addClass('mysite-scroll-processed');
  });
  }
};

This could probably use some cleaning up, and would greatly take suggestions. Also, I'm using jQuery 1.8 (using jQuery Update module). Hope this help any of you struggling to make this work outside of Views.

Hi,

I tried to integrate it with SOLR search results which has similar HTML structure to default search, but unfortunately this code doesn't give accurate results as it always appends the same data.

For e.g.: If at the time of page load our next page is "page=2" and last page is 5, in this case it simply appends 2 times the results of "page=2" to current results.

I have rewrite the complete code using jquery autopager "jQuery.autopager".

To integrate it with search, just download the jquery autopager and use below code:

(function($){
  var search_infinite_scroll_was_initialised = false;
  Drupal.behaviors.search_infinite_scroll = {
    attach:function() {
      // Make sure that autopager plugin is loaded
      if($.autopager) {
        if(!search_infinite_scroll_was_initialised) {
          search_infinite_scroll_was_initialised = true;
          if($('div.item-list ul.pager')) {
              var content_selector = '.search-results';
              var items_selector   = '.search-results';
              var pager_selector   = 'div.item-list ul.pager';
              var next_selector    = 'div.item-list li.pager-next > a';
              var img_path         = Drupal.settings.basePath + 'themes/bartik/images/ajax-loader.gif';
              var img              = '<div id="search_infinite_scroll-ajax-loader"><img src="' + img_path + '" alt="loading..."/></div>';
              $(pager_selector).hide();
              var handle = $.autopager({
                appendTo: content_selector,
                content: items_selector,
                link: next_selector,
                page: 0,
                start: function() {
                  $('.search-results').after(img);
                },
                load: function() {
                  $('div#search_infinite_scroll-ajax-loader').remove();
                  Drupal.attachBehaviors(this);
                }
              });
              // Trigger autoload if content height is less than doc height already
              var prev_content_height = $(content_selector).height();
              do {
                var last = $(items_selector).filter(':last');
                if(last.offset().top + last.height() < $(document).scrollTop() + $(window).height()) {
                  last = $(items_selector).filter(':last');
                  handle.autopager('load');
                }
                else {
                  break;
                }
              }
              while ($(content_selector).height() > prev_content_height);
          }
        }
      }
      else {
        alert(Drupal.t('Autopager jquery plugin in not loaded.'));
      }
    }
  }
})(jQuery);

This seems to sort of be working for me, but only seems to autopage once (i.e. I get double the results, but that's it... no more autopaging when I hit the bottom of the page...)

Any ideas?

Are you getting any JS or some other errors??
If so please can you explain.

For custom coded page I have created own version for replacing drupal pager with "read more" AJAX functionality: (works without infinite-scroll plugin)

(function ($) {
  Drupal.behaviors.readMoreAjax = {
    attach: function (context, settings) {
      $('.read-more-ajax', context).click(function () {
        var nextPage = $('.pager .pager-next a').attr('href');
        var lastPage = $('.pager .pager-last a').attr('href');
        $.get(nextPage, function (data) {
          $(data).find('.produktlist').insertBefore($('.item-list'));
          $('.item-list .pager').remove();
          if (nextPage == lastPage) {
            $('.read-more-ajax').remove();
          }
          else {
            $(data).find('.item-list .pager').appendTo($('.item-list'));
            Drupal.attachBehaviors($('.item-list'));
          }
        });
      });
      $('.item-list .pager').hide();
    }
  };
})(jQuery);

Where:

  • '.read-more-ajax' - button to load more
  • '.produktlist' - nodes/divs that should be loaded

Hi,
I have tried the minimal set of options to make the infinite scroll working in Drupal 7. It looks working fine, I have only to pages at the moment, but the last page keeps being loaded. I saw that the pager (which is hidden) is not updated and so it always has the "next" page link.
Any hint?

Thanks,
Vince

Many thanks to @babruix. Below is amended code for search results page:

(function ($) {
  Drupal.behaviors.loadMoreAjax = {
    attach: function (context, settings) {
      $('.load-more-ajax', context).click(function () {
        var nextPage = $('.pager .pager-next a').attr('href');
        var lastPage = $('.pager .pager-last a').attr('href');
        $.get(nextPage, function (data) {
          $(data).find('.search-results.node-results').insertBefore($('.item-list'));
          $('.item-list .pager').remove();
          if (nextPage == lastPage) {
            $('.load-more-ajax').remove();
          }
          else {
            $(data).find('.item-list .pager').appendTo($('.item-list'));
            Drupal.attachBehaviors($('.item-list'));
          }
        });
      });
      $('.item-list .pager').hide();
    }
  };
})(jQuery);

Remember to add the button (class="load-more-ajax") in the search results.tpl.php.