Unobtrusive Ajax Navigation – Version 1

June 1, 2009 11:12 by scibuff

This is the first post in my new series about creating unobtrusive AJAX navigation for a website using Javascript frameworks. I still remember the first time I saw AJAX in action on the Gmail registration page a while back. It gave users the option to check if a given username was taken, and it did the check asynchronously, i.e. the HTML page did not have to be reloaded.

AJAX navigation is not only cool, it is also fast and saves bandwidth. It can be seen around the web (Gmail or Facebook for example) but many pages are missing a fall-back for users without Javascript, or on mobile devices. Javascript should be used ONLY to enhance the usability of web sites and NEVER to create functionality that does not already exist. In this tutorial (the first of many) I’m going to demonstrate how easy it is to set up unobtrusive Ajax navigation using jQuery.

Check out the demo of this tutorial or download all the files.

First, create a simple web page.

<body id="version-1">
	<div id="wrapper">
		<div id="header">
			<h2>Unobtrusive Ajax Navigation - Version 1</h2>
			<ul class="inline-list navigation-main" >
				<li><a href="index.php" class="ajax-link">Home</a></li>
				<li><a href="about.php" class="ajax-link">About</a></li>
			</ul>
			<div class="clear-both"></div>
		</div>
		<div id="content">
		</div>
		<div id="footer">
			<p>Footer</p>
		</div>
	</div>
</body>

I took the liberty of adding some CSS styles to make the page look nice. The important part is adding ajax-link to the links’ class name. In just a moment, it will be used it to add AJAX functionality to the navigation. As the first step include the jQuery libraries. I prefer to link to the Google code libraries as it not only saves the trouble of downloading/uploading jQuery for every project but the library is likely to already be in your browser’s cache (from other sites).

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

Next, add the project’s javascript file, I named it ajax-version-1.0.js and placed it into a js directory.

<script type="text/javascript" src="js/ajax-version-1.0.js"></script>

That’s it for the HTML code. Now let’s have a look at the Javascript that actually does all the work for the AJAX navigation.

$(document).ready(function () {
	$('a.ajax-link').click( function( event ) {
		set_ajax_link( $(this), event );
	});
});
function set_ajax_link( el, event ){
	event.preventDefault();
	var url = el.attr("href");
	load_page_content( url );
}
function load_page_content( url ){
	$("#content").load( url, { 'ajax': 'true' }, function(){
		$('#content a.ajax-link').click( function( event ) {
			set_ajax_link( $(this), event );
		});
	});
}

As a rule of thumb, I wrap my code within the document ready block, to ensure that DOM is fully loaded before trying to access its elements.

$(document).ready(function () {});

The next part searches for all a tag elements which has been assigned a className of ajax-link.

$('a.ajax-link').click( function( event ) {
	set_ajax_link( $(this), event );
});

All such elements are then passed into my set_ajax_link function.¬† Also pass in the click event instance (we’ll see in a second why).

function set_ajax_link( el, event ){
	event.preventDefault();
	var url = el.attr("href");
	load_page_content( url );
}

The first command in the set_ajax_link function stops the default behavior when the user clicks on a link because the desired functionality is to load the content asynchronously instead of navigating to that page. Next, grab the link’s URL using the attr function, and as the last step¬† load the content from that URL using the load_page_content function.

function load_page_content( url ){
	$("#content").load( url, { 'ajax': 'true' }, function(){
		$('#content a.ajax-link').click( function( event ) {
			set_ajax_link( $(this), event );
		});
	});
}

All that the load_page_content function has to accomplish is to load the content from the URL. This is achieved via jQuery’s load function. Once the content is loaded it will be placed into the div element with id “content”. Using the second argument of the load function the script will send a query parameter named ajax with value set to true along with the asynchronous request. The third argument points to a function that is executed once a response is received from the server. The script will give the AJAX navigation functionality to all links with className of ajax-link in the received response.

Using the HTML code created in the very first step and some new functionality create the homepage (name it index.php).

<?php
 
	// if the page is requested by AJAX
	if ( isset($_REQUEST['ajax']) && $_REQUEST['ajax'] == "true" ){
		print_content();
	}
	else {
		print_header();
		print_content();
		print_footer();
	}
 
function print_header(){
?>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
	<head profile="http://gmpg.org/xfn/11">
		<title>Unobtrusive Ajax Navigation - Version 1</title>
 
		<link rel="stylesheet" href="style.css" type="text/css" media="screen" />
 
		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
		<script type="text/javascript" src="js/ajax-version-1.0.js"></script>
 
	</head>
	<body id="version-1-0">
		<div id="wrapper" class="border-module">
			<div id="header" class="border-module">
				<h2>Unobtrusive Ajax Navigation - Version 1.0</h2>
				<ul class="inline-list navigation-main" >
					<li><a href="index.php" class="ajax-link">Home</a></li>
					<li><a href="about.php" class="ajax-link">About</a></li>
				</ul>
				<div class="clear-both"></div>
			</div>
			<div id="content" class="border-module">
<?php
}
 
function print_footer(){
?>
			</div>
			<div id="footer" class="border-module">
				<p>Footer</p>
			</div>
		</div>
	</body>
</html>
<?php
}
 
function print_content(){
?>
	<h2>Homepage</h2>
	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<?php
}
 
?>

Now HTML content of our index.php is identical to the static HTML page created originally. The difference is that the HTML code is split into three parts by three PHP functions, print_header(), print_footer() and print_content(). There are a few reasons for this separation. Some will be discussed/addressed in future tutorials. One of the reasons becomes clear when we examine the top of the index.php script page.

// if the page is requested by AJAX
if ( isset($_REQUEST['ajax']) &amp;&amp; $_REQUEST['ajax'] == "true" ){
	print_content();
}
else {
	print_header();
	print_content();
	print_footer();
}

Now we can see the reason behind added the ajax query parameter in our load_page_content Javascript function. The script will use it to determine whether the user arrived at the page directly (when the if statement evaluates to false) or the request came from the AJAX request. If the user arrives directly to our index.php page, the script will output the entire HTML code (using the print_header(), print_footer() and print_content() functions), however, the AJAX request will return the content ONLY (you can’t see that content by visiting index.php?ajax=true directly).

As the final step, I created another page and name it about.php. Then I simply copied everything from out index.php over to about.php and change the content of the print_content() function.

function print_content(){
?>
	<h2>About</h2>
	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<?php
}
?>

The first version on a simple website using unobtrusive Ajax navigation is now finished. It has only to pages (Home and About) but can easily be extended to as many pages as necessary. The main advantage is that if user’s browser does not have Javascript support (or Javascript is disabled), the user will be able to navigate our sites in the conventional manner by simply clicking on the navigation links. Furthermore, the AJAX functionality can be developed independently of other aspects of the sites, i.e. we can have different people working simultaneously on the front-end and back-end.

Nevertheless, this version is quite far from an optimal solution and has many drawbacks:

  • it does not allow users to bookmark the page they are currently viewing
  • there is no support for the browsers Back and Forward buttons
  • it restricts placing the content from asynchronous calls only to the div element with id “content”
  • the PHP code has as many duplicates are there are pages – print_header() and print_footer() are identical across all pages and should be in a single file
  • the Javascript code does not prevent possible conflicts with other scripts which could use functions with same names
  • the are no error checks or error messages
  • no indication of content being loaded
  • etc…

I will address all these issues in future tutorials on this subject. Meanwhile, check out the demo of this tutorial or download all the files.

Be Sociable, Share!

Comments

8

Unobtrusive Ajax Navigation – Version 2

[…] Last week I started a new series about creating unobtrusive Ajax navigation. The first version represented a good start and laid a solid foundation. Nevertheless, it was far from an ideal solution mainly for the lack of some basic functionality and poor organization of both the front- and back-end code. […]

Ta Duc

this is not good base on my experience, what is the point of having this beside saving bandwidth. I think you should provide some anchor in the url to make back, forward functional. also to make user easier to copy the url.

scibuff

thx for your comment … you are indeed correct … that is exactly what the second part of the mini-series does

Marcello Barnaba

Hello,

we developed upon these ideas and beyond (history support, UI disabling, in the future file uploads as well) and created an AJAX Nav framework. Check it out on github: http://github.com/Panmind/jquery-ajax-nav

Roven

Is this supposed to work in Internet Explorer ?
I was playing around with this code, from 1-3, and then adding some stuff like tabbed navigation & jQuery animations for the transitions.
Then i tested it in IE8 and it didn’t work at all. I’m using XAMPP locally though, don’t know if it has anything to do with that.
Great read btw !

scibuff

Roven, I tested it in IE6 and IE7 (8 wasn’t around then yet) so I can’t imagine it wouldn’t work in IE8. Try to have a look at the demo page here http://www.scibuff.com/dev/ajax/ajax-version-1.0/ (so there’s no additional javascript)

Roven

Thanks for the quick reply

I’ve just tested it both online & local.
Appearently it does work online, but the local version fails to load the content.

The same thing happened when I tried the above Ajax Nav framework and they’ve added a messagebox to warn it only works online.

The downside is it also seems to break my other scripts when testing in IE, so I guess I’ll have to make a conditional statement to disable this js in IE for now…

Leave your comment:
XHTML:You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> . * required