Coding a jQuery AJAX site that degrades gracefully
Posted on 03. Mar, 2010 by Guillermo in Development
Over the course of this tutorial I’ll show how to create a simple way (Ajax powered) to refresh the content of the pages while degrading gracefully when there’s no javascript. Added bonus: its “crawler friendly”.

The idea
The site we are building for this tutorial will have a normal navigation, consisting of plain old links to the different pages. If javascript is enabled it will replace the default action of these links (for example going to a new page) with a new behavior: load the content using Ajax and refreshing the page without going to a new URL.
We’ll use the jQuery load function. This function will fetch the new page. It has a very useful feature (essential in our case) that lets you load a page fragment and not the whole page as right now we’re only interested in the main content div.
The HTML
<ul id="menu"> <li><a href="index.html">Home</a></li> <li><a href="link2.html">Link 2</a></li> <li><a href="contact.html">Contact</a></li> </ul>
Here we have the main navigation. It doesn’t have anything special, we only need the id of the navigation element containing the links we want to add this special behavior
<div id="ajax-wrap"> <div id="text"> </div> </div>

Another important part is to create a div that wraps the content; this will be the div whose content will change when we move from page to page. Note we have two elements, the wrapper div and the actual element that has the content in it (in this case the div with the “text” id).
Also note that all the content pages are complete html pages by themselves. We load them with ajax and only use the content portion. If someone actually goes to the URL the link is pointing to, they should see a full page and not just the content portion. (This is key for the site to work without javascript, like a regular site).
Javascript
I’ve created a small javascript object that handles everything, here’s the code:
var AjaxContent = function(){
var container_div = '';
var content_div = '';
return {
getContent : function(url){
$(container_div).animate({opacity:0}, //Turn the opacity to 0
function(){ // the callback, loads the content with ajax
$(container_div).load(url+" "+content_div, //only loads the selected portion
function(){
$(container_div).animate({opacity:1}); //and finally bring back the opacity back to 1
}
);
});
},
ajaxify_links: function(elements){
$(elements).click(function(){
AjaxContent.getContent(this.href);
return false; //prevents the link from beign followed
});
},
init: function(params){ //sets the initial parameters
container_div = params.containerDiv;
content_div = params.contentDiv;
return this; //returns the object in order to make it chainable
}
}
}();
We include this script on the pages (along with jQuery) and we’re ready to rock and roll. I’ll explain it little by little.
When the page loads, we have to identify the links and assign them some new events. Here’s the part where we initialize and set up the special nav.
$(function(){
AjaxContent.init({containerDiv:"#ajax-wrap",contentDiv:"#text"}).ajaxify_links("#menu a");
});
This call initializes the AjaxContent object with the ids of the wrapper div and the content div (note the jquery [selector] notation). The second chained call tells which links we want to add this special behavior, in this case the links inside the element with the “menu” id (“#menu a”). This is it! It should work by now although let’s explain what’s going on inside.
ajaxify_links: function(elements){
$(elements).click(function(){
AjaxContent.getContent(this.href);
return false;
});
}
This is the method we called before. It selects all the elements passed using our jQuery selector string, in this case it takes all the links. For each one of them, it assigns a function to the click event. This function calls the getContent method and prevents the link from being followed by the browser (with the “return false” sentence).
getContent : function(url){
$(container_div).animate({opacity:0}, //first, turn the opacity to 0
function(){ //on the callback, load the content with ajax
$(container_div).load(url+" "+content_div,
function(){
$(container_div).animate({opacity:1}); //and finally bring back the opacity back to 1
}
);
});
}
This method fades out the container div. It then calls the load method and only retrieves the part that we want, in this case we’ve told the script to get the div with the “text” id (jQuery actually loads the whole HTML and then parses it, returning only the part we’ve asked for). When the content is loaded, it fades in the content again.
Conclusion
As you could see, thanks to the power of jQuery, this is really easy to do. We now have a fancy way to retrieve the content and keep the site looking like a normal non-ajax site to the ones who don’t use javascript. The site also remains both SEO friendly and fully accessible to the crawlers because the links are normal <a> elements with the href property.
Thanks to the guys on Solucija for the free template I’ve used for this example.
Happy coding!
Source files:
and Demo
Related posts:
Spanish





602.288.5333
+54 261 4340244

Jeremy
Mar 29th, 2010
Hi,
This AJAX tool works great, and I love that it’s SEO friendly. Do you have any plans to make the back button work?
Thanks!
Jeremy
Guillermo
Mar 30th, 2010
Thanks Jeremy!
It’s true, back button doesn’t work with this approach. This could be solved appending a hashtag on the url every time that the content changes and then using that hashtag to reload the content again when the user clicks back or forward.
Right now adding that feature is not on the plans, the article was only to show how to load AJAX content in a crawler friendy way, but we’ll let you know if we make any changes
Brent
Jun 23rd, 2010
cool, I was seeing some other tutorials but none of them degraded gracefully. It’d be awesome if you could work in the back button fix using URL hash at some point, if you ever do please email me – brent@mimoymima.com
thanks!
b r e n t
Peter
Aug 1st, 2010
I am implementing your code to my web, everything work perfect besides Back button. The page url change on back button but content does not update. I was trying to plug in BBQ or history.js but nothing works. Could you help me with this.