Shares

This tutorial is born right from the Vinkk code base.  I was in the same boat as you a few weeks ago, and when I didn’t find out something elegant, I decided to roll up my own solution. Well, in true Mr. Geek fashion, I am sharing with you the “Laravel 4 Pagination with Infinite Scroll using jQuery” tutorial.

Laravel 4 Pagination with Infinite Scroll using jQuery from Ali Gajani on Vimeo.

 

This tutorial is targeted at users who have a working Laravel app, including data, pagination and a Bootstrap layout. If you don’t, you can still read on but it’s way more fun if you can simulate what I am trying to show here. Let’s get started.

Pagination Object

I am not here to teach you the basics of Laravel 4, or things like pagination. So, I’ll dive straight into the code. Here’s how we paginate entities. Each time we scroll down, we receive a chunk of 20 entities – articles in my example.

 $articles = Article::orderBy('vinkk_score', 'DESC')->where('published_at','>=',$day_old)->paginate(20); 

Currently, your Laravel 4 pagination works through a navigation bar, and navigating to a new page by mouse clicks is not a hallmark of a great user experience. Users will just run away. Time is money. Infinite scrolling is way better. Let’s make it work.

To View

When you return a paginated object, you shall pass it to the view of your choice as shown below. I assume you’ve been doing this already. Up to this point, you don’t have to change anything. Dynamic functionality with jQuery comes next.

 return View::make('feed.feed')->with(['articles' => $articles]); 

The Markup

This is how the markup looks like. Add the class .ajax_scroll to your .row div which contains the entities. These entities, I must reiterate, can be articles, pictures, blog posts. Don’t forget to apply the id “container” to this div.

 <div id="container" data-masonry-options='{ "itemSelector": ".item" }' class="row js-masonry ajax_scroll"> 

Inside this, you shall have another div with the class .item and the required column size. For example:

 <div class="col-md-3 item"> <!-- ITEM START --> 

Once you have the styling applied to whatever you are paginating, add this below:

<div class="col-md-12">
    <div class="row text-center">
        <a id="inifiniteLoader">
            <img src="http://chimplyimage.appspot.com/images/samples/classic-spinner/turningBarIndicator.gif">
            <noscript>
                You don't have Javascript enabled? You kiddin' me bro.
            </noscript>
        </a>
    </div>

</div>

It would be wise to boot up Masonry at the end, like this. I hope you know how to pull in the Masonry script.

{{ HTML::script('assets/js/masonry.pkgd.min.js') }}
<script>
    $('#container').masonry({
        itemSelector: '.item',
        columnWidth: 100,
        gutter: 10
    });
</script>

The Infinite Scroll

Best things for last. Once you have setup your pagination objects and the relevant markup, it’s time to make the magic happen with the Infinite Scroll script coded up entirely in jQuery. You must put this main.js file after loading your jQuery, preferably at the bottom.

The MIT License (MIT)

Copyright (c) 2014 Ali Gajani (http://www.aligajani.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

$(window).load(function () {

//Infinite Scroll Ajax
$(document).ready(function ($) {

//to get the max page, I suggest to output the result via an API call
var api = "http://localhost:8000" + "/api/v1/collection";

$.getJSON(api, function (json) {
var max_page = json.collection['last_page'];
var count = 2;
var total = max_page;

//when user reaches bottom of the page, make an ajax request
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
if (count > total) {
return false;
} else {
loadFeed(count);
}
count++;
}
});

});

//the ajax request comes here with the page number
function loadFeed(pageNumber) {

//display the ajax loader while things load
$('a#inifiniteLoader').show('fast');

//get the current url
var curURL = window.location.href;

//the actual ajax request happens here
$.ajax({

//these query strings must look familiar by now
url: curURL + "?page=%",

//perform a GET request with the data
type: 'GET',
data: {page: pageNumber},

//when there is an output
success: function (html) {
$('a#inifiniteLoader').hide('1000');

//you need to manipulate the DOM by filtering via class
var items = $(html).find(".ajax_scroll").html();

//don't render if there are no items
render(items);

}
});
return false;
}

//once items are loaded, now render them in HTML
function render(item_html) {

var el = jQuery(item_html);

//this makes the masonry animation happen
$('.ajax_scroll').append(el).masonry('appended', el, true);

}

});
});

About Ali Gajani

Hi. I am Ali Gajani. I started Mr. Geek in early 2012 as a result of my growing enthusiasm and passion for technology. I love sharing my knowledge and helping out the community by creating useful, engaging and compelling content. If you want to write for Mr. Geek, just PM me on my Facebook profile.