netnik.com

Ajax and Graceful Degradation

By Bob Hay

Ajax stands for Asynchronous Javascript. What this means is that part of a web page can be changed without reloading the whole page. Although, that may not seem like a big deal, it is one of the foundation technologies for "Web 2.0."

Above the content on this page are five tabs which trigger the loading of content into the <div id="loadarea"> div. In this part, the aptly named Part 1, I will explain how jQuery powers the Ajax on this page, and then in part 2, I will examine how the page can be modified to work for users who, for whatever reason, may have javascript turned off. The term for this process is graceful degradation, which is a somewhat unpleasant turn of phrase, but it beats "This web page doesn't work." The three remaining tabs contain the final code for this page.

First, let's take a look at our nice, simple HTML code:

<!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">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="Author" content="Bob Hay" />
<title>Graceful JQuery Tabs and Ajax</title>

<link rel="stylesheet" type="text/css" href="style.css" />
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="graceful.js"></script> 

</head>
<body>

<div id="page">
<ul id="tabs">
<li id="part1" class="active">Part 1</li>
<li id="part2">Part 2</li>
<li id="html">html</li>
<li id="css">css</li>
<li id="js">javascript</li>
</ul>

<div id="loadarea"></div>
<div id="forcescroll"></div>
</div>
</body>
</html>

Yep, that's all there is to it. Note in the <head> of our document that our stylesheet, style.css, and the current version of jQuery, and our javascript, graceful.js, are loaded. (You can downlaod the latest stable version of jQuery and find anything you want to know about jQuery at jquery.com.)

JQuery can manipulate and apply actions to CSS selectors. On this page, it detects clicks on the tabs and loads the appropriate content. The tabs themselves are list items in an unordered list:

<ul id="tabs">
<li id="part1" class="active">Part 1</li>
<li id="part2">Part 2</li>
<li id="html">html</li>
<li id="css">css</li>
<li id="js">javascript</li>
</ul>

The <li>s are styled by CSS to float acroos the page with this:

ul#tabs {
list-style: none;       /* removes default <ul> behavior, i.e bullets */
float: left;
margin: 0;
padding: 0;
}

ul#tabs li {
display: inline;        /* changes <li>s from block to inline elements */
float: left;
margin: 0 0 0 12px;     /* left margin of 12px spaces the tabs apart */
padding: 4px;
width: 120px;
background-color: #abc;
color: #000;
font-size: 1.2em;
text-align: center;
font-weight: bold;
}

ul#tabs li.active {      /* visual cue for the active tab */
background-color: #567;
color: #fff;
}

ul#tabs li:hover {      /* visual cue for tab mouse-over */
color: #fff;
}

When the user clicks on a tab, the jQuery kicks in. Here is the code, from the file "graceful.js", which calls on the jQuery library.

 $(document).ready(function() {      // do stuff when DOM is ready
 
	$("#loadarea").load("part1.html");
 
	$("li#part1").click(function(){
	$("#loadarea").load("part1.html");
	$("ul#tabs li").removeClass("active");
	$("li#part1").addClass("active");
	})
	
	$("li#part2").click(function(){
	$("#loadarea").load("part2.html");
	$("ul#tabs li").removeClass("active");
	$("li#part2").addClass("active");
	})
	
	$("li#html").click(function(){
	$("#loadarea").load("html.html");
	$("ul#tabs li").removeClass("active");
	$("li#html").addClass("active");
	})
	
	$("li#css").click(function(){
	$("#loadarea").load("style.css");
	$("#ul#tabs li").removeClass("active");
	$("li#css").addClass("active");
	})
	
	$("li#js").click(function(){
	$("#loadarea").load("graceful.js");
	$("ul#tabs li").removeClass("active");
	$("li#js").addClass("active");
	})
});

What we have here are five functions, one for each of the tabs.

The whole thing starts off with the standard document ready function that is used to start virtually all blocks of jQuery code. It's purpose is to wait for the DOM to load before executing any code. The second line of code is then executed. It loads the document "part1.html" into the div with the id of "loadarea".

$("#loadarea").load("part1.html");

The syntax of the jQuery code is quite simple. To break it down word for word:

  • The $ signifies that it is jQuery code which will call upon the jQuery library.
  • Next comes the CSS selector which specifies what the target is. In this case, it is any element with the id of "loadarea". (As in CSS, the # signifies an id, which is by definition unique. We could use "div#loadarea", but it is not really necessary.)
  • Then, following the dot, comes the jQuery ajax command "load". (One thing that tends to confuse me when I look at code is telling the difference between words that are part of the language and words that are essentially arbitrary, e.g. variable names, div and class names, etc. that are made up by the programmer. So to be clear in this example, "load" is a jQuery command. The rest of the words reference things I have named, in this case the div "loadarea" and the document "part1.html".)
  • Lastly comes the name of the external document that is to be loaded in to the target element.

Note that the five functions that follow are not executed. This is because they are functions and they will not be executed until an event (in these five cases a "click") triggers them.

As you can see, each of the five functions are quite similar. Let's look at the second one line by line.

$("li#part2").click(function(){ 
When the <li> with the id of "part2" is clicked, execute the function.
$("#loadarea").load("part2.html"); 
You'll recognize this one as similar to the one already discussed. It loads "part2.html" into the loadarea div. The last two lines change the CSS attributes of the <li>s so the user gets a visual cue as to which tab is active. First it removes the class "active" from any and all <li>s within the <ul> with the id of "tabs" with the jQuery command "removeClass". Then it adds class="active" to the <li> that has an id of "part2" with the jQuery command "addClass.
$("ul#tabs li").removeClass("active");
$("li#part2").addClass("active");
}) 

I think this is an awesome display of jQuery's power. You'll notice that it turns the <li>s themselves into clickable objects without using any <a> anchor tags. This may be its most impressive feature, but it is also it's downfall.

As i mentioned earlier, jQuery will not work for anyone who has javascript disabled in their browser. One could decide to ignore those users as not worth worrying about, but there is one further consideration, i.e. search engines. Think about what search engine spiders do... They follow links. As it stands right now, a spider would find our page empty of content, since even "part1.html" is loaded by jQuery.

We need to rememdy this. To see how, click the "Part 2" tab.