Implementing Infinite Scroll Pagination with MODX

Published on , in Back-end with no comments .

What is Infinite Scroll?

Infinite scroll is a pagination style that is designed to enhance the user experience by providing a more efficient and responsive way to browse long lists of content. The idea is simple: as the user scrolls the page we automatically load and inject more content into the page, avoiding the need for the user to wait on an entirely new page loading.

This means users may be more likely to continue browsing since the content is loaded automatically for them, which could lead to more engagement on the site. However users can also get lost. Standard pagination gives the user a sense of control and they have a rough idea of where they are in this mountain of content. With infinite scrolling everything is on the first page in one massive list. Infinite scrolling also results in an un-reachable footer since more content is automatically loaded.

Perhaps the best solution is a hybrid: infinite pages. This concept is basically the same as infinite scrolling but rather than automatically load new content as the user hits, or approaches, the bottom of the page we provide them with a button to load more content. This fixes the problems with infinite scrolling. The footer is now reachable, the user is back in control and has that sense of position within the results, and new content still loads significantly quicker than standard pagination.

The specific implementation you choose is up to you and doesn’t affect how you’d handle it within MODX. So now we know what Infinite Scrolling and Infinite Pages are, let’s see how to implement them within MODX. Both methods require two things: an AJAX call to request the new content, and a wrapper snippet for getResources.

Using getResources

Here’s the getResources wrapper snippet in its entirety:


<?php
$method = $modx->getOption('method', $scriptProperties, 'initial');
$limit  = $modx->getOption('limit', $scriptProperties, 6);
$parent = $modx->getOption('parent', $scriptProperties);
$tpl    = $modx->getOption('tpl', $scriptProperties);

$load   = (int) $_GET['page'];
$offset = 0;

if($method == "initial") {
    if($load != 0) {
        $limit = $limit * $load;
    }
} elseif($method == "pagination") {
    $offset = $limit * ($load - 1);
}

$page = $modx->runSnippet('getResources', array(
    'parents'        => $parent,
    'limit'          => $limit,
    'offset'         => $offset,
    'includeTVs'     => '1',
    'tvPrefix'       => '',
    'includeContent' => '1',
    'tpl'            => $tpl
));

if($method == "initial") {
    return $page;
} elseif($method == "pagination") {
    if(empty($page)) {
        $noResults = $modx->parseChunk('no-results',array('text' => 'No more posts!'));

        return json_encode(array(
            'success' => false,
            'page'    => $noResults
        ));
    } else {
        return json_encode(array(
            'success' => true,
            'page'    => $page
        ));
    }
}

As you can see it’s very simple with only three main parts. We do some calculations to determine the page to load, run getResources and send the appropriate response.

Let’s go into a bit more detail. Our snippet has two methods — “initial” and “pagination.” The reason is that the initial list will be part of the page to start with and not injected after an AJAX call so we have to treat it a little bit differently. After we run getResources we simply return the result. With the “pagination” method though we check that we have content or not. If we do, then we json_encode our response which includes the HTML from the getResources call. If we don’t have any more content then we parse the no results chunk and return that, also encoded. Our no results chunk is just some simple HTML. You can set a placeholder if you like, or just hard code the message as part of the chunk.


<div class="no-results">
    <p>[[+text]]</p>
</div>

We need to have two different calls to our wrapper snippet. Our first would be placed on our main page. If we were using it on a blog, for example, then this call would be placed on your main blog page. This is our “initial” call to get the first batch of content.


[[!infinite-pagination?
    &parent=`[[*id]]`
    &tpl=`blog-post-item`
]]

For our second call we will need a separate page. Create one in the MODX manager and call it something like “Pagination Processor.” This page should not use a template and contain only our snippet call. It’s to this page that we will send our AJAX call.


[[!infinite-pagination?
    &method=`pagination`
    &parent=`2`
    &tpl=`blog-post-item`
]]

The AJAX Call

Here's an example using jQuery and a load more button.


$('.load-more').click(function(e) {
    e.preventDefault();

    var $this = $(this);

    var load   = $this.data('current-page') + 1;
    var parent = $this.data('parent');

    $.ajax({
        type: "GET",
        url: "/blog/pagination-processor.html",
        data: {page: load, parent: parent},
        success: function (response) {
            response = $.parseJSON(response);

            if(response.success) {
                $(".post-list").append(response.page);

                // Update the page attribute
                $this.data('current-page', load);
            } else {
                $this.after(response.page);
                $this.remove();
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            // Do something if there was an error
        }
    });
});

There’s nothing complicated here either. I’m using HTML data attributes to store the current page and the parent page ID. We send these values to our pagination processor which then uses them to retrieve the next batch of results. Since the response is JSON it needs to be parsed. If the request was successful then we append the results to our existing content and update the current page data attribute. At this point you could also update the URL to reflect the current page by using the history API if you wanted to. If the request was not successful (no more results) then we insert that response into our page and remove the load more button.

Need a functioning demo? Then look no further than the blog on this site. Have you already implemented infinite scrolling on a MODX site? How did you achieve it? Let me know in the comments below.

Leave a Comment