Introduction
I’m sure most of you are aware of the infinite scroll feature we’re writing about. If not, check out: Svpply, Pinterest, or Lookbook.nu. The concept is not too hard to understand. When the page first loads, it loads an initial amount of items, and after the user has scrolled to the bottom of the content, more content is loaded and the user has the ability to keep scrolling. Assuming there is an endless amount of content, the user could scroll forever, hence infinite.
This technique uses nearly every part of a common technology stack in a typical ExpressionEngine build: HTML + CSS, Javascript, and a few EE template tags. I’ll go through each of these areas incrementally and at the end of the tutorial you can see a working version and download the sample code.
In our example, we are going to be creating a basic News Feed, with the page initially loading 3 articles, and when the user scroll to the bottom of the page, we load more articles one at a time.
HTML
The HTML in our example is pretty straight forward. All we need is a container that holds our individual news articles, and a few additional data parameters, which help communicate with the javascript. To begin, we’ll setup our basic html structure. Then, add a container to hold these articles. Inside the article container we’ll create an individual article to be shown. Note, we’ve included some CSS to clean things up a bit.
In the above example you’ll notice the div, #articles-container, has two data attributes: data-start-at and data-increment-by. These two pieces of data are the first inklings to the infinite scroll functionality. The data-start-at value corresponds to the number of items we are going initially have on the page. Data-increment-by is the value for the number of articles we want to load once we reach the bottom of the page. After loading this into the browser, here is what we should have:
Next, we’ll go over our EE setup and add the Channel tags necessary for our page load content.
EE Setup
Within the EE Control Panel we have created a Field Group, News, which will hold our news stories. We have two additional fields for our example:
- news_image : image field
- news_content : text area field
We have also created a Channel, News, which uses our News Field Group. After creating a handful of test entries, we will go back into our markup and add EE tags to list our articles. (You’ll probably want to create 7 - 10 entries to really test this out.)
The channel:entries tag should be nothing out of the ordinary, but notice we are setting the limit to 3. This limit parameter should have the same value as the data-start-at attribute we created on the #articles-container div.
After loading the page with the EE tags implemented we should get an output resembling this:
Next, we’ll hook up some javascript and ajax to get the infinite scroll working.
Javascript
The javascript for this technique is definitely the most complicated part. For this example I am using jQuery along with a jQuery plugin, Endlessscroll, which fires a callback function when we have reached the bottom of the page.
After including jQuery and Endlessscroll, we’ll want to create a class to control the infinite scroll feature. In our example, we have called this Scroll_class. The first method we’re going to add to Scroll_class is init, which will handle setting up some global JS variables.
In the first part of the init method we get a reference to the container holding all the articles. Next, we get the two data attributes we specified and set another property, self.current_index, which will hold the number of articles we have loaded onto the page at any given point during the scrolling.
Please use a modern version of jQuery, as an old version may not support the .data() method.
In this init method, we set self.current_index to the self.start_at value because it will initially correspond to the number of articles we load onto the page. Next, we setup two fuse properties. These will be used to alert us when we need to stop loading content, either because of an error or if we have no more content to load. Finally, we initialize our endlessScroll event. The endless-scroll plugin has a variety of options, but here are the ones we are using:
- bottomPixels: How many pixels from the bottom of the page we want the event to fire at.
- fireDelay: How many milliseconds to wait before we let another event fire off.
- fireOnce: Only fire once until the execution of the current event is completed.
- callback: The function to run after the event has fired.
For the callback parameter we create an anonymous function, which in-turn calls another Scroll_class method, get_new_content.
The get_new_content method needs to do 2 main things: One, it needs to load our new content. Two, it needs to increment our self.current_index property, which tells us what specific piece of content to load. Here is the code for this method:
First, you’ll see we have a conditional checking to see if we are at the end of the content or if we have encountered an error. Assuming both of these are set to false, we proceed. The next piece is setting up an AJAX call to request our new content. Our AJAX options are:
- type - we want to send the data to EE via POST vars.
- url - this is the template our ajax call will get content from
- data - the data that will be passed via POST.
- success - the function to call after the content has been returned
Notice that the data object has two properties: offset and limit which we set to our two class properties self.current_index and self.increment_by.
Our success function has the parameter data, which holds the HTML to the content being returned. The first thing happening in the method is trimming the data variable.
Sometimes, because of the EE template parser, content can have white spaces preceding and trailing the markup.
Next, check to see if the data returned was the string “error” or “end”, which would signify each respective issue when loading content. If one of those strings is detected, the class property is set and we return false, causing no content to be added to the screen. Assuming the content that was returned is not one of our fuse flags, we will then append the HTML returned to the container. Finally, after the new content has been added to the screen we increment the self.current_index property.
Now that we see how the javascript is written to handle the loading of new content, lets take a look at the server-side ajax template, which returns us our content.
AJAX
The last major part of the infinite scroll technique is returning new content from the AJAX request. In our example, we have created another template, ajax_scroll.html, which contains HTML and EE tags to return our content. As we saw in the previous section, we’re passing two POST variables with our ajax request: offset and limit, and in order to access these we have enabled PHP within this specific template, with it being parsed on input.
You can probably use another plugin or extension, such as Mo’ Variables, to handle this without turning on PHP, but for the sake of simplicity we will rely on PHP for this example.
Within this template we have 3 major pieces:
- Getting the post variables
- An EE chanel entries tag
- The markup
Within the PHP tags at the top of the page, we first get the EE super object, which gives us access to the post variables. After getting those two variables we do a quick check to make sure they were actually included. If not we return “error”, which if you remember, we are checking for in our javascript. The next parts are the EE entries tag and the HTML markup. These two should be fairly straight forward. The markup is the exact same that is used on our main listing template, and the channel:entries tag uses our post variables to know which content to display. Also, notice the no_result conditional which will return “end” if there is no content to display i.e.: we have reached the end of our content listing.
After getting this last piece in place, we are done with the implementation. Fire up your page to see how things look, hopefully your content loads and scrolls correctly.
Result
That’s it! Pretty simple, right?
With any solution there are always a few drawbacks. The first one we think of is the fact that each time we reach out for an AJAX request, we have to use the template parser class, which is somewhat slow. It could possibly be handled better by just returning the exact data you need and handling the “templating” in the javascript. We’ve actually used this JSON plugin in the past to accomplish this (however I’m not 100% sure if it still avoids using the template parser), or you could write some raw SQL queries if you are feeling up to it.
The second drawback would be the duplicate code in the ajax_scroll.html template. We typically try to keep our code as DRY as possible and having two identical code blocks, which both need to be maintained, is somewhat cumbersome. You could probably come up with a pretty quick snippet to handle this, but thats something for the developer to decide for themselves.
We hope this tutorial was helpful and shed some light onto a useful EE technique. You can see the demo here, and full code is available here. Feel free to download and take a look for yourself.
Awesome plugin, but the demo isn’t working in IE8… kind of a bummer since I’m not a js wizard yet. Thank you once again, Explorer.
Hey guys,
I’ve been trying to use Endless Scroll combined with Masonry, been trying to use your code example above with no luck.
Have you ever used it in combination with masonry?
P
Great tutorial, perfect for what I need to do - however, I’m having the same issue as James. Sometimes it loads duplicate blocks of content. I can’t see a pattern to it, but it’s as if it forgets the offset.
Ignore post, I was missing the “being parsed on input.” portion. Feel utterly braindead for the one. Fantastic tutorial btw :)
Hello, I seem to keep getting an endless loop, it wont catch the end of the entries at all, any ideas how to get around that?
Wonderful tutorial, I’ve been looking for a way to implement this on my site for over a year and up until now haven’t been able to find instructions that I had the programming knowledge to follow or understand.
I seem to have got the basic functionality working on my site now, but I randomly get duplicate entries as I scroll down, sometimes whole blocks of two or three entries are duplicated.
The output page is here: http://www.jamesmattison.co.uk/index.php/blog
Is there anything you can imagine I’ve done incorrectly that might be causing this?
Thanks Philip!
Excellent tutorial guys. I’ve been looking for a good EE infinite scroll example for a while.
This is definitely needed for EE and there are no tutorials out there like this. Thanks for taking the time to write this.
It works no problem with basic EE search, but I’ve been having issues with implementing it with Solspace Super Search instead of using the channel entries tag because of its dynamic nature and reading from uris. If I figure it out, I’ll post my solution on how to get it working.
Thanks again.