Ajax and Graceful Degradation - Part 2
By Bob Hay
As it turns out, it is fairly easy to make our awesome jQuery-powered Ajax machine degrade gracefully so that it can be read by anyone including search engines. In fact, since our HTML code is so simple and since our CSS styling and our javascript are safely stowed away separate from the HTML, these pages could be read using Mosaic from circa 1995!
Here's what were going to do:
- Add some links to our tab <li<>>s by using <a href=""> tags.
- Add a few lines to our style.css file to style those links.
- Wrap each of our content files in our HTML template, so that each can stand alone. We just need to add one div to the template, so the jQuery Ajax can pull tne content from them.
- And finally, we will tweak our jQuery script a little to account for the <a> links.
Here is the tabs <ul> with links added:
<ul id="tabs"> <li id="part1"><a href="index.html">Part 1</a></li> <li id="part2" class="active"><a href="part2.html">Part 2</a></li> <li id="html"><a href="html.html">html</a></li> <li id="css"><a href="css.html">css</a></li> <li id="js"><a href="javascript.html">javascript</a></li> </ul>
Next we add some style to the <a> tags by adding a few lines to styles.css. Essentially we want the tabs to look the same as they did before, so we just need to specify the text color.
ul#tabs li a {
color: #000;
}
ul#tabs li.active a {
color: #fff;
}
You may observe that the links in the tabs will now be underlined, since I didn't specify "text-decoration: none;". What I'm thinking is that I would prefer the links to be underlined in cases where javascript is disabled, and not underlined when javascript is turned on. So I'm going to remove the underlining with jQuery.
But first I want to mention a small change necessary in our HTML. Here is our modified template:
<!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"><a href="index.html">Part 1</a></li> <li id="part2" class="active"><a href="part2.html">Part 2</a></li> <li id="html"><a href="html.html">html</a></li> <li id="css"><a href="css.html">css</a></li> <li id="js"><a href="javascript.html">javascript</a></li> </ul> <div id="loadarea"> <div id="content"> <!-- CONTENT GOES HERE --> </div> </div> <div id="forcescroll"></div> </div> </body> </html>
The only change, besides adding links inside the tab <li>s, is the addition of a div with id="content" inside the loadarea div. That will allow jQuery to pull the content from each of our wrapped content pages. That way we can use our stand-alone HTML content pages as our Ajax sources as well. (When I build the pages for displaying code, e.g. CSS, I will wrap that content with a <pre> </pre> tag to avoid having to add a lot of <br /> tags.) As you build pages, also change which <li> is given the class "active". That way our non-javascript friends will still get a visual cue from CSS for which tab is on top.
So let's take a look at our modified javascript.
$(document).ready(function() { // do stuff when DOM is ready
$("ul#tabs li a").css("text-decoration","none");
$("li#part1, li#part1 a").click(function(){
$("#loadarea").load("index.html #content");
$("ul#tabs li").removeClass("active");
$("li#part1").addClass("active");
return false;
})
$("li#part2, li#part2 a").click(function(){
$("#loadarea").load("part2.html #content");
$("ul#tabs li").removeClass("active");
$("li#part1").addClass("active");
return false;
})
$("li#html, li#html a").click(function(){
$("#loadarea").load("html.html #content");
$("ul#tabs li").removeClass("active");
$("li#html").addClass("active");
return false;
})
$("li#css, li#css a").click(function(){
$("#loadarea").load("style.html #content");
$("#tabs ul li").removeClass("active");
$("li#css").addClass("active");
return false;
})
$("li#js, li#js a").click(function(){
$("#loadarea").load("js.html #content");
$("ul#tabs li").removeClass("active");
$("li#js").addClass("active");
return false;
})
});
What has changed?
- We no longer need to load part1 into the loadarea, because the content is already on the page, so I removed the $("#loadarea").load("part1.html"); line. Now the content is availble to search spiders.
- The only action that is performed when the document is ready is to set the text-decoration of our tab links to "none" which I mentioned earlier. This is done with the jQuery command "css".
- I also changed the first two lines of each of the five click functions slightly.
- In the first line, I added an additional css selector so the <a> tag would perform the same function as the <li> tag. A companion to this is the final line that I added to each section, "return false;". This prevents the link from performing its default action of clicking through to its href. If javascript is disabled, the link will function normally.
- In the second line I added "#content" to the URL to be loaded. This results in just the <div id="content"> being loaded as ajax content, instead of the whole page being loaded, which would be a major train-wreck.
Okay, that wraps it up. You can get the HTML, CSS, and javascript by clicking the tabs above. (Don't forget to get the jQuery from jquery.com.)