I wanted to use tabs as a navigational tool and load page content based on those tabs without a page load but in a way that would gracefully degrade. The technique is shared here in hopes that it helps others out who are considering the same thing.
This code is taken from a site I wrote for work.
Here’s the nav bar in basic XHTML. The class=”activeLink” is used for the current page and is styled identically to the a:hover pseudo class.
<ul id="nav">
<li><a href="index.html" class="activeLink">Overview</a></li>
<li><a href="technology.html">Technology</a></li>
<li><a href="advantages.html">Advantages</a></li>
<li><a href="learning.html">Objectives</a></li>
<li><a href="video.html">Video</a></li>
</ul>
The content we want to change is in a div with the id of content. Each of the five pages above contains the same container div with this id.
The javascript is easy and clean, thanks to the magic of jQuery which is powerful and lighter than competing frameworks. After including jQuery (this example uses 1.2.3, but it does not rely on any recent functionality). The following javascript is all that’s needed for the effect:
// when the page has finished loading...
$(document).ready(function() {
// links for the nav tabs.
// clicking on an anchor hides the content, loads new content, and fades the new in.
// this function also changes the class of the tabs and prevents the browser from loading the href
$('#nav a').click(function(event) {
$('#content').hide().load($(this).attr("href") + ' #content').fadeIn(1000);
// remove active link class for all links then change the class of the link
$('#nav a').removeClass("activeLink");
$(this).addClass("activeLink");
// used in place of 'return false;' as suggested by http://docs.jquery.com/Events_%28Guide%29
event.preventDefault();
});
});
The comments should help, but let’s break it down:
// when the page has finished loading...
$(document).ready(function() {
This is jQuery’s ready function that executes after page load and avoids the tricky window.onload issue that needs works around.
$('#nav a').click(function(event) {
Take the anchor links from within the #nav and add a click event to them. This applies the function to each of the links (5 in this case) and prevents cluttering the source code with onclick attributes. We pass event (a click in this case) as a parameter to be used later.
$('#content').hide().load($(this).attr("href") + ' #content').fadeIn(1000);
This line chains useful events together. It selects the content div, which contains unique data for each page. Then that div is hidden to prepare it for the new content. The handy AJAX method .load fetches content from another page. To determine which page we want to load, we’re going to use the $(this) variable, which refers to the current object (an anchor tag in this case), and by accessing the attr function, retrieve the href attribute. This means that click on Video link will return video.html. The second part of the attribute in the .load function (the + ’ #content’ part) allows you to select a sub-section of the page to extract. In this case, we’re wanting to retrieve all the HTML from the element with the id of content from another page. Finally, we call the fadeIn function to display the div again, with an adjustable speed (1000 milliseconds in this case).
// remove active link class for all links then change the class of the link
$('#nav a').removeClass("activeLink");
$(this).addClass("activeLink");
The removeClass and addClass functions are also straightforward. First we remove the activeLink class (the one that emulates the a:hover pseudo class) from all anchor elements in the nav bar (though only one will have it). Then we add that class to the current anchor tag, defined by the $(this) variable.
// used in place of 'return false;' as suggested by http://docs.jquery.com/Events_%28Guide%29
event.preventDefault();
Finally, we ignore the default value of the event (passed in the .click function) to prevent a click on the link from going to the target of the link. This allows the page to work in browsers without javascript and keeps our code clean and tidy.
The pages in this example are static, but it could easily be generated from any page. As long as the page link in the href attribute of the link returns a page with an identifiable div, it will work. There are some nice features of this approach:
- Since the individual pages are kept, they can be linked to individually and all can act as a base page for AJAX reloads.
- The page fading effect is a nice visual touch for reloading the content.
- Our markup remains clean and tidy (save for the class=”activeLink” which I’d prefer to emulate in jQuery by adding a pseudo class to the links rather than a separate class).
- By using jQuery, the rest of its functions can be leveraged in other parts of the site.
Hope it’s helpful to someone. I’d appreciate any comments or suggestions!