Google

Client Login.



Justin Long // ExpressionEngine Expert

Implementing Infinite-Scroll in Your ExpressionEngine Site

Written by: Justin Long | On: July 24, 2012

I recently needed to implement an infinite scroll functionality on a client site I did some searching and found a couple of solutions in various places including the ExpressionEngine forums and The Good Lab's Site but none worked exactly how I wanted or needed. The solution that I came up with uses 2 templates, a snippet, and a bit of jQuery goodness. In all actuality you can get this set up with a single template and some jQuery but I prefer this way and in my test resulted in less overhead on my server when additional content is loaded.
 

The Snippet


I am going to start with the snippet portion of this tutorial as it will save us time later down the road, especially if we need to make any changes to the code. I have named my snippet "snip_ajax_scroll". I am going to assume some very basic content in this example but any content that you have in your channel entries loop will work just fine.

{!-- snip_ajax_scroll --}</p>
<
div id="articles">
    
{exp:channel:entries channel="my_channel" disable="categories|category_fields|member_data" limit="5"}
    
<div class="entry">
        <
h2>
            <
a href="{comment_url_title_auto_path=">{title}</a></h2>
        <
p>
            
{summary}</p>
        <
img class="summary_img" src="{summary_img}" />
        <
div class="posted_by">
            
{author} on {entry_date format="%M/%D/%Y"| <a data-disqus-identifier="{site_name}_{entry_id}" href="{url_title_path='/comments'}#disqus_thread">Leave a comment</a></div>
    </
div>
    
{paginate}
    
<div class="navigation">
        
{if next_page}<class="next js_hide_next" href="{auto_path}">Next Page</a>{/if}</div>
    
{/paginate} {/exp:channel:entries}</div>
<
p

So that is the basic setup to display your entries, there is nothing to crazy going on. Now that we have the snippet created lets get started on creating the tempalte that will actually house the infinite scrolling.

The Template


</p>
<
title></title>
<
script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script><p>
    
{snip_ajax_scroll} <script type="text/javascript">
    
    
</script></p>
<
p

Since we created the snippet that contains the channel entries loop that is all we need to get started. There are few Infinite-Scroll scripts available on the web the one in particular that I am using is a fork Paul Irish's version and can be downloaded on GitHub. The forked version has a crucial change that allows us to use it with ExpressionEngine without having to modify it at all. I have downloaded it and moved it to my js folder on my server /assets/js/ so lets update the template and add the basic functionality.

</p>
<
title></title>
<
script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script><p>
    
{snip_ajax_scroll} <script src="/assets/js/jquery.infinitescroll.js"></script><script type="text/javascript">
    $(
document).ready(function(){
     
$('#articles').infinitescroll({
          navSelector 
".navigation",
          
nextSelector "a.next",
          
itemSelector ".entry",
          
contentSelector"#articles",
          
extractLinktrue// This is crucial if you want it work properly. Setting this to false or excluding it will not allow the script to work with EE
      
})
    
});
    
</script> 

In the newly added code we need to match the values of our container div, each item's div, the navigation, and the next link values. We also needed to add the "extractLink: true," parameter to get it work with EE. Now if we save the template and navigate to the template you just created you should be able to scroll down and have new entries added.

Great so that working

You could vary well stop there and call it a day. Depending on the page where you pagination links are you can cause some serious overhead on your server by having users reload a resource intensive page multiple times just to pull out your paginated entries. That is why I personally create a second template in my embeds template group.

The New Template

The code for this template is very simple since we have are actual channel entries loop in a snippet already. I am calling mine "ajax_scroll".

{!-- Located at embeds/ajax_scroll --} {!-- The snippet embeds the channel entries loop required for our pagination pages --} {snip_ajax_scroll} 

Now that we have that setup we need to make a slight adjustment to our snippet that we created earlier so that when the paginated entries are fetched that they are using our lightweight template instead of the main template.


snip_ajax_scroll:

!-- snip_ajax_scroll --}</p>
<
div id="articles">
    
{exp:channel:entries channel="my_channel" disable="categories|category_fields|member_data" limit="5" paginate_base="embeds/ajax_scroll"}
    
<div class="entry">
        <
h2>
            <
a href="{comment_url_title_auto_path=">{title}</a></h2>
        <
p>
            
{summary}</p>
        <
img class="summary_img" src="{summary_img}" />
        <
div class="posted_by">
            
{author} on {entry_date format="%M/%D/%Y"| <a data-disqus-identifier="{site_name}_{entry_id}" href="{url_title_path='/comments'}#disqus_thread">Leave a comment</a></div>
    </
div>
    
{paginate}
    
<div class="navigation">
        
{if next_page}<class="next js_hide_next" href="{auto_path}">Next Page</a>{/if}</div>
    
{/paginate} {/exp:channel:entries}</div>
<
p

Basically the same code as before just with the addition of (paginate_base="embeds/ajax_scroll") being added to the opening channel entries tag.

The Wrap Up

You should now have a functioning Infinite Scroll content area on your site. If you have any questions or comments about the code or content of this tutorial please post them below.

Loading Social Buttons


Since I have posted this I have had a few people reach out to me and ask about updating things like social buttons, Disqus comment counts, and lightbox scripts. These will usually not work right out of the box because the javascript fires right after the page has loaded and the AJAX content is loaded after that. The infinite-scroll script does have a compatibility mode that will allow you to call your javascript on the new content. I am including the necessary javascript to get the three most common elements I see (Facebook, Twitter and Disqus).

Facebook

<script type="text/javascript">
    $(
document).ready(function(){
     
$('#articles').infinitescroll({
          navSelector 
".navigation",
          
nextSelector "a.next",
          
itemSelector ".entry",
          
contentSelector"#articles",
          
extractLinktrue// This is crucial if you want it work properly. Setting this to false or excluding it will not allow the script to work with EE
      
})
      $(
document).ajaxComplete(function(){
            try{
                FB
.XFBML.parse(); 
            
}catch(ex){}
        }
);
    
});
    
</script> 

Twitter

<script type="text/javascript">
    $(
document).ready(function(){
     
$('#articles').infinitescroll({
          navSelector 
".navigation",
          
nextSelector "a.next",
          
itemSelector ".entry",
          
contentSelector"#articles",
          
extractLinktrue// This is crucial if you want it work properly. Setting this to false or excluding it will not allow the script to work with EE
      
})
      $(
document).ajaxComplete(function(){
            try{
                twttr
.widgets.load(); 
            
}catch(ex){}
        }
);
    
});
    
</script> 

Disqus Comment Count

Currently Disqus 2012 does not support Disqus Reset function so you have to actually use the normal comment count javascript with the slight modification that you can not use the normal variable of Disqus shortname. You will need to actually hardcode the name into the source.

<script type="text/javascript">
    $(
document).ready(function(){
     
$('#articles').infinitescroll({
          navSelector 
".navigation",
          
nextSelector "a.next",
          
itemSelector ".entry",
          
contentSelector"#articles",
          
extractLinktrue// This is crucial if you want it work properly. Setting this to false or excluding it will not allow the script to work with EE
      
})
      $(
document).ajaxComplete(function(){
            try{
                 
var document.createElement('script'); s.async true;
                    
s.type 'text/javascript';
                    
s.src 'http://your_forum_shortname.disqus.com/count.js';
                    (
document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
                
}()); 
            
}catch(ex){}
        }
);
    
});
    
</script> 

Trigger Infinite-Scroll

I have had a few people send me messages asking if there was a way to allow the infinite-scroll functionality but only when a user clicks a button or link to load more content. It is certainly possible to do we can start from our previous template:

<html>
    <
head>
        <
title>My Infinite Scroll Demo</title>
        <
script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

    
</head>
    <
body>
    
    
{snip_ajax_scroll}
    
    
    
<script src="/assets/js/jquery.infinitescroll.js"></script>
    
<script type="text/javascript">
    $(
document).ready(function(){
     
$('#articles').infinitescroll({
          navSelector 
".navigation",
          
nextSelector "a.next",
          
itemSelector ".entry",
          
contentSelector"#articles",
          
extractLinktrue// This is crucial if you want it work properly. Setting this to false or excluding it will not allow the script to work with EE
      
})
    
});
    
</script>
    
</body>
    </
html
From there we will need to first unbind the normal behavior of the script by adding
$(window).unbind('.infscr'); 
directly after the closing }); of the script. From there we will need to bind the infinite-scroll functionality to a click function like this
$('a#next').click(function(){
        
$(document).trigger('retrieve.infscr');
        return 
false;
     
}); 
This causes the infinite-scroll script to fire when a user clicks on a link with an ID of "next". That is it so your final template code would look something like this
<html>
    <
head>
        <
title>My Infinite Scroll Demo</title>
        <
script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

    
</head>
    <
body>
    
    
{snip_ajax_scroll}
    
    
    
<script src="/assets/js/jquery.infinitescroll.js"></script>
    
<script type="text/javascript">
    $(
document).ready(function(){
     
$('#articles').infinitescroll({
          navSelector 
".navigation",
          
nextSelector "a.next",
          
itemSelector ".entry",
          
contentSelector"#articles",
          
extractLinktrue// This is crucial if you want it work properly. Setting this to false or excluding it will not allow the script to work with EE
      
})
    
});
    
// Unbind normal behavior
    
$(window).unbind('.infscr');
    
    
// Bind normal behavior to the click function and prevent the browser from redirecting to the URL.
    
$('a#next').click(function(){
        
$(document).trigger('retrieve.infscr');
        return 
false;
     
});
    
    
</script>
    
</body>
    </
html
That should do it.

Next entry >>> <<< Previous entry

Comments

<<< Go back to entry list