Endless scrolling based on a simple HTML pager

We had a little brainstorm today at work at how endless scrolling could be best implemented utilizing progressive enhancement. Here’s my idea and a proof of concept. And a good example of progressive enhancement in pure form, if I may say so.

The concept

When I think of endless scrolling, I see it as just another form of paging. Any content asynchronously loaded when scrolling down is in fact the same you would have seen when an ordinary pager was implemented, clicking on a link “next”. In practice, you don’t see the page change, the content is just loaded below the content already there.

So what you need is this:

  1. A way of detecting whether the user is near the end of the page
  2. Then determine what the link to the next page is
  3. Load the content of that url
  4. Select only the items from that content and inject those items below the items already there
  5. Make sure the next time the user reaches the end of the page, the next page according to that content is loaded, unless there are no more pages left

1. Detecting the end of the page

This is done by comparing the difference of the document’s height to the window’s height, subtracting the window’s scrollTop (how far you scrolled down) and seeing if that crosses some hard coded threshold.

if($(document).height() - $(window).height() <= $(window).scrollTop() + threshold) {
    // load the next page
}

2. Determine what the link to the next page is

This is simple. You know where the pager links are (typically in some ul), and the HTML spec provides a rel attribute which can be used to define a relationship between the current page and the page linked to. In this case, next is the right value to use.

So, the next link typically is the one within the pager, having a rel attribute set to next:

<a href="..." rel="next">Next page</a>

In the script, we’ll need to check whether a next link is actually available. If not, the endless scrolling doesn’t prove to be that endless after all.

var a = $('a[rel=next]', 'div.pager ul').first();
if(a.length) {
    // get the content from the link's href attribute
}

3. Loading the content

This is probably the easiest step, however, we need to be aware that the user might still be scrolling while the content is loaded. So, we flag a variable to make sure no second attempt at loading the next page is done while we’re still loading the next page:

var loading = false;
if($(document).height() - $(window).height() <= $(window).scrollTop() + threshold) {
    if(!loading) {
        loading = true
        $.get(page, function(data) {
             // inject the data here
             loading = false;
        });
    }
}

4. Select and inject the loaded items

Within the callback used to display the content, we can load the data into jQuery by passing that data to the jQuery constructor. Let’s just assume the request will never fail, and we don’t need to handle errors here, for the sake of the example. Using jQuery, we can use a selector to select the elements from the loaded content, and append them to the container

$.get(page, function(data) {
    var dom = $(data);
    var items =dom.find('.items');
    container.append(items);
    loading = false;
});

5. Prepare for the next time the user reaches the end

In my opinion, it’s easiest to change the current DOM in such a way that your subsequent pages load exactly the same way as the first one. This makes the plugin stateless, which is always easy to debug, and typically better pluggable.

Since we base the loading of our ‘next’ URL on the pager, we simply replace the pager with the one loaded in the asynchronous request.

$('.pager', container).replaceWith(dom.find('.pager'));

This way, the next time the user reaches the end of the page, the new pager is used to find the next page. Easy as pie.

Tuning the bits and pieces

Adding some code to make the selectors variable and hiding the pager whenever the plugin is activated, leaves you with a very usable version of an endless scrolling plugin, without you having ever to talk to a backend developer about it. How’s that?

The proof

I whipped up the implementation of endless scrolling based on a HTML pager, putting it all together. The page is generated using some simple PHP code to show some random items over a few pages. View the HTML source if you don’t know PHP; I provided a link to the PHP source as well, just to make sure the concept is clear. If you’re not planning on reading the PHP, I’ll tell you in advance that there are 10 5 pages in the example of 6 12 items per page, ending the scrolling at 66 items.

One gaping hole

Of course, this is just a proof of concept and there is at least one hole to plug. This version doesn’t handle people entering the site at a page higher than the initial one. This means that, in fact, you should inject the content that is not yet loading above the initial content, by determining the prev link from the pager.

I’ll leave this to your imagination 😉

Happy scrolling 🙂

This entry was posted in Development and tagged , , . Bookmark the permalink. Trackbacks are closed, but you can post a comment.

5 Comments

  1. Wizzkizz
    Posted February 8, 2011 at 23:04 | Permalink

    In Internet Explorer it works just fine, but in my Firefox (3.6.13) it won’t scroll. It might be because of the NoScript plugin, however I allowed all scripts on your demo page. The demo in IE works nice and I think about implementing this feature in a webshop I maintain soon, based on your solution I think 🙂

  2. drm
    Posted February 9, 2011 at 00:01 | Permalink

    I changed the number of items per page to 12. The first page probably fitted on your screen initially, a quirk mentioned here.

  3. Posted October 6, 2012 at 10:49 | Permalink

    Is there any way of doing this on a blogger blog site?

  4. Mustafa
    Posted April 8, 2013 at 11:14 | Permalink

    Many thanks for this script. Is there an opportunity to show a load gif during loading?

  5. Posted July 15, 2015 at 07:59 | Permalink

    Well I just read it and i think i saw it on LinkedIn when I go trough the list of people I might want to add to my contacts. So did you get your royalties? 😉

    @Mustafa: Of course it is possible. Maybe wait a second or so before starting to show/load the image. If the load is fast, showing the image could make the user loose the attention of reading on. At least I would.

Post a Comment

Your email is never published nor shared.

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Subscribe without commenting