Ajax Pagination & Back Button

Ok so hands up if your a fan of Ajax, you can’t see it but I certainly have my hands up as do many of the other developers out there, so what is this post about? Well if you have ever built an Ajax application or website you would know that Ajax breaks the browsers natural navigation, things like the ‘back button’, ‘forward button’, history, favouriting a page or browsing to it via the URL input all become useless because there is no physical URL for those elements to use or save.

Now yes there are some solutions out there for providing Ajaxified links that keep your back buttons working, they are complex and usually written in a specific framework, so if you want to use them well your going to be adding a lot more code then you thought to your web site. Plus this is how Gmail and Facebook do it, you won’t find there code or get any help from them on the topic so I decided to build it myself so everyone could get the benefits of Ajax URL navigation. Below is an example of a simple yet elegant Ajax Pagination system I’ve written to relieve the navigation hicups Ajax causes.

Demo

View Demo :: MooTools
View Demo :: jQuery

How it works

Very simply the pagination class is loading each successive request via ajax into the dom and slides it into view, it also replaces the pagination controls each time with the new correct numbering of the new pagination controls including highlighting, prev, next buttons etc… Replacing the pagination controls each time is by far the smartest way of doing things, as the Pagination class has nothing to do with manipulating the controls, saving complexity in a grand way because in an ajaxed pagination application the JavaScript should never be responsible for rebuilding the pagination controls, that should be handled by your server side code!

URL hash Now here is the kicker, after you have used the pagination controls, hit the Back Button, and there you go, BAM, you’ve gone back to your previously selected pagination results without causing a reload of your page. This is accomplished by updating the hash (#) value of the URL, we have full access to the hash section of a URL via JavaScript, we have no access to the URL though, it is a security measure built into JavaScript which denies us the power to edit it. So the answer to creating new linkable URL’s is the hash value. We can update and check it as we need to.

{code type=php}
/* get hash value */
var tmp = window.location.hash;

/* set hash value */
window.location.hash = tmp;
{/code}

The Pagination class simply sets the hash value everytime you click the pagination controls, allowing the browser a history of what you have been doing in the application, then the Pagination class checks every half second or so to see whether you the user have done something in the browser that changes the hash value from the last one it has set in the URL. If the Pagination class determines the hash values are not the same it will use the new hash from the URL, which is essentially an Ajaxed URL, that will load the correct page.

Browsing by URL The next cool thing is browsing by URL, on the demo page at the bottom there is a link that says, ‘Go To page 4’ that link has no javascript attached to it, the link simply updates the URL which the pagination class will check and then browse to. You can also navigate straight to an ajaxed URL without going to page 1 of the paginator first, in essence you’re browsing by hard URL which will allow linking to it and favouriting of the link.

Why is that important in an Ajax application you ask, well lets say that you have an image gallery with 100 pictures in it, each page displays 10 pics and a user really likes the images on page 7. In 99% of Ajaxified pagination applications it would be impossible for that user to favourite page 7, or send a link to a friend, or link to it from his own web-page because your pagination will either in the worst case, force a user to click seven times to get to page seven, or require you to load page 1 of the results every time before they can click on page number 7 and have it load. Neither way allows you to save the URL in your browser, or link to it from another page, essentially making your very valuable image library somewhat un-navigatable.

We should always give users a valid URL to save and navigate to later!

Usage

{code type=php}
/* Load the paginator with default options */
new Paginator(‘http://local.dev.com.au/pagination/ajax.php’);

/* Load paginator, but change time between hash/url check to one second */
new Paginator(‘http://local.dev.com.au/pagination/ajax.php’, {
‘timer’ : 1000
});
{/code}

Options

{code type=php}
/* Default Options */
{
xString = {}
qString : ‘?p=’,
items:10,
pagination: ‘pagination_pager’,
container: ‘pagination_container’,
duration: 800,
timer: 500
}
{/code}

Here is a quick idea of what each option is doing.

  • xParams – Allows extra params to be sent through the Ajax query
    • qString – The query section of your URL. By default it is ‘?p=3’ . ie. Page number 3
    • items – Items per page, defaults to 10
    • pagination – The Id of the element that your pagination controls will be inserted into to
    • container – The Id of the element that your pagination results will be inserted into to
    • duration – Duration of the sliding animation, 800 = 8 tenths of a second
    • timer – Time between checking for a new URL hash. Faster will make the application more responsive to changed hashes. I find 500 is a good number. ie. Half a second

    Pagination on the server side

    You will need a PHP function to calculate your pagination, the one provided in “functions.php” is a simple 5 number step sliding pagination, very similar to Facebook’s and extremely useable and friendly. It is included in zip file download. I mention it because you can change it to any pagination function you would like, you don’t have to keep mine. You have all the necessary variables you need for a healthy pagination method including, max item count, page number, current page, items per page and the base path, so you can get totally creative with you pagination outputs.

    Download

    Easy Ajax Pagination:: MooTools
    Easy Ajax Pagination:: jQuery

    Installing

    Step 1. Change the URL in pagination.php or pagination_jquery.php

    {code type=php}
    new Paginator(‘http://local.dev.com.au/pagination/ajax.php’);
    {/code}

    Step 2. Upload it

    Upload it to your server or testing environment. Then your done, now you just use ajax.php to get your result desired set, make it look how ever you’d like with whatever data you want and style up the application to suit your need.

    I will be posting more on this code soon as I’m going to submit it as an jQuery & MooTools plugin, so there will also be GitHub versions to check out and contribute to.

    Extending the parameter list

    A few people asked for ways to extend the parameters you send through the Ajax request, here is how I implemented it.

    {code type=php}
    var pagination = new Paginator(‘http://local.dev.com.au/pagination/ajax.php’);

    // User event requiring extra data in Ajax request

    pagination.options.xParams = { ‘someData’ : ‘someValue’ }
    {/code}

    All new requests are now sending this parameter along with the pagination details. Any further changes to xParams just keeps merging the objects together to form your request.

    Note: Edit your ‘pagination.php’ file to capture and use the extra params.

    Enjoy!

17 Comments

  1. devseo says:

    Interesting post.thanks for posting. I’ll likely be coming back to your blog. Keep up great writing.

  2. Bruno says:

    Hi Simon,

    this is a nice one. Thanks!
    Created a little snippet to use it on modx-revolution together with its getPage-snippet.

    http://modxcms.com/forums/index.php/topic,57687.msg330977.html#msg330977

  3. Simon says:

    Nice one Bruno, hope you guys get it working 🙂

  4. Marc says:

    Great tutorial. Got it to work no problems.

    Question: how would I go about parsing more parameters following the #.

    For example, let’s say I’m running a real estate website and somebody has selected to view listings with 2 bedrooms. How would I parse this from the URL:

    http://www.aplusdesign.com.au/misc/pagination/pagination_jquery.php#p=6&beds=2

    How would I get the system to recognize that I need to update the results and display listings with only 2 bedrooms?

    I greatly appreciate any help.

  5. Marc says:

    I guess if you, or anybody else for that matter, is feeling generous, how would I go about placing a call to a database? (PHP & MySQL)

  6. Simon says:

    That is actually very easy to do, and built into the class already. I just messed it up at some point.

    I will post up a newer version of the code shortly with a quick tutorial to show how you would pass extra params through the pagination.

  7. Simon says:

    Alrighty, the new code is up, so just re-download the zips, there is a parameter in the options object now called ‘xParams’, this object gets merged with the params sent through to your pagination.php file, allowing for extra parameters to be specified.

    A quick example is provided under the heading ‘Extending the parameter list’

  8. Marc says:

    Hey man, thanks so much for the update!

    I downloaded the new .zip file, but the pagination does not seem to grab any additional URL parameters.

    Is there anything else I need to edit/add to get this to work?

    Example URL: http://localhost/pagination/pagination_jquery.php#p=6&beds=2

    (AJAX/JSON is not my strong suit… but I’m trying to learn)

  9. Simon says:

    Heya, there won’t be any extra params sent through by default. If you check out the example under ‘Extending the parameter list’ you will see how you create a pagination object, then are able to later on provide some extra data that the request will send.

    The reason it is implemented like that is two fold, you can specify extra data in your initialisation call, for example “var pagination = new Paginator(‘http://local.dev.com.au/pagination/ajax.php’, {xParams: { data : value }});”

    Now, pagination.options.xParams is equal to { data : value }, the data:value pair will be sent with the request.

    You can then later over-ride xParams if the user does something that requires some extra data to be sent for your pagination script.

    Example.

    pagination.options.xParams = { data : value, data2 : value2 }

    the new value pairs are merged into the request.

  10. Marc says:

    Thanks Simon.

    Here is my current code in pagination_jquery.php:

    $(document).ready(function() {
    var pagination = new Paginator(‘http://localhost/pagination/ajax.php’, {
    xParams : {
    ‘beds’ : 2
    }
    })
    });

    However, when I click to go to another page, those values are lost from the URL. Doesn’t seem that the paginator is holding those values for further use.

    Those values (beds = 2), are going to be changing as per a users input. So, beds will not always equal 2, but will be variable to the users input. With taht said, setting a hard-coded ‘2’ in the xParams setup just won’t work for what I am going to use it for.

    Thinking I am getting ahead of myself here and should just go back to basics and learn to walk before I run. I am very interested in using your script at some point though, and thank you very much for your help so far.

  11. Simon says:

    Your set-up call is correct, now every time there is a pagination ajax request you are sending the value of beds to ajax.php. Use firebug to inspect the parameters being sent.

    When a user changes the value of beds, just change xParams.

    ie.

    // a user event that changes beds value, then
    pagination.options.xParams = {
    ‘beds’ : newValue
    }

    Now each pagination request has the new beds value.

    It definitely works, it may just require some more understanding of how ajax sends and retrieves data.

  12. Marc says:

    Hey Simon,

    I did some messing around and got it to work, however, I’m not sure if it’s working how you intended the script to work.

    I need it to work with newValue being dynamic since this is a large site and I don’t know what people are going to be searching for.

    pagination.options.xParams = {
    ‘beds’ : newValue <– needs to be a dynamic value; there will be lot's of other options, too, ie. baths, property types, etc.
    }

    Anyways, since I was having trouble parsing the variable(s) from the URL after the hash, I figured a way to do so with a separate function, and then I passed those variables through the paginator (PHP) function where they are now showing up in the pagination display in the browser.

    In fear of making a mess of this, I may call on your services in the near future to help me build a solid system, as I can see the benefits of using a system like this for SEO and user accessibility. You would be compensated for your time, of course.

    Ultimately, this system needs to make a query against a database full of listings, and needs to return listings that match the user's specific query (1 bedroom, 2 bathroom, home for sale, for example). Hence the reason for it needing to be dynamic.

    Here is what I did to accomplish where I'm at:

    var pagination = new Paginator('http://localhost/pagination/ajax.php&#039;, {
    xParams : {
    'beds' : getUrlVars()['beds'],
    'baths' : getUrlVars()['baths']
    }
    });

    Then I passed the value(s) through the paginator function:

    $pagination = paginator($basePath . $qString, $loadPage, $maxItems, $items, true, false, $beds);

    in the ajax.php file, where I then concatenated $beds to the pagination setup.

    Where the getUrlVars() function strips each separate value from the URL after the hash. I do apologize if your system already did this, but I just couldn't get it to work on my end. My PHP skills FAR outweigh my AJAX/jQuery skills.

  13. magnushung says:

    This is what you can do. From the ajax.php file at this line:
    $basePath = ‘http://’ . $_SERVER[‘SERVER_NAME’] . $_SERVER[‘PHP_SELF’];

    Change to:
    $basePath = ‘http://’ . $_SERVER[‘SERVER_NAME’] . $_SERVER[‘PHP_SELF’] . “?beds=”. urlencode($_REQUEST[‘beds’] . “&baths=” .urlencode($_REQUEST[‘baths’];

  14. magnushung says:

    Next, your pagination_jquery.php file from the line:
    new Paginator(‘http://localhost/pagination/ajax.php’)

    Change it to:
    var pagination = new Paginator(‘http://localhost/pagination/ajax.php’, {
    xParams : { ‘beds’ : , ‘baths’ : }
    });
    This code should work with the pagination to pass the variables to the next page and so on.

  15. magnushung says:

    Also you have to do one more thing in the pagination-jq.js at the line:
    qString : ‘?p=’,

    Change it to:

    qString : ‘&p=’,

    So that should work. The pagination paging should change the pages.

  16. Nikun says:

    This is very interesting post for all php developer
    Thankx

  17. synchrist says:

    Thanks for this posting and sharing this Simon, it’s very useful 😀

Post a Comment