Ajax Workshop 2: Building Tabbed Content
Filed Under (Lessons, Tutorials, Workshops) by admin on 18-02-2006
This workshop we will be building a tabbed content browser that’s Ajax powered. When ever a user clicks a tab the Ajax will communicate with the server and send back the appropriate data for that tab. We will start this workshop off with the XHTML and CSS for the tabbed content browser. We will need 3 main IDs (one for the container, one for the content area and one for the loading status) and 1 class (for the tabs).
#container { width:500px; } .tabs { width:50px; margin-right:10px; padding:4px; text-align:center; float:left; cursor:pointer; border:1px solid #ccc; border-bottom:0; } #content { height:250px; clear:both; border:1px solid #ccc; } #load { position:absolute; left:0; top:0; width:100px; height:20px; background-color:red; color:white; display:none; }
The first ID #container will hold the tabs as well as the content area, we only give this a width which everything inside can inherit. The following class .tabs is going to style our tabs, most of the styling we have is mostly for looks an important property is the float:left. The float:left makes the tabs so they are on the same horizontally aligned, this can also be done with using display:inline but with a little more tweaking. We also gave it a property of cursor:pointer so when the user mousses over the tab that it has the look and feel of a button. Finally we have the ID #content. We set a height for the content area which can be changed depending on how much content you want and we set the clear property to clear:both. This is because about this div we have all of tabs floated left this makes the content div break to a new line directly beneath. The loading style is used for when the Ajax is communicating with the server we set the display to display:none so it only shows while the page is loading. We also gave all the tabs IDs this will be covered further down the workshop.
Here is the XHTML needed for the styles above:
<div id="load">Loading...</div> <div id="container"> <div class="tabs" id="tab1">Tab 1</div> <div class="tabs" id="tab2">Tab 2</div> <div class="tabs" id="tab3">Tab 3</div> <div class="tabs" id="tab4">Tab 4</div> <div id="content"></div> </div>
This is pretty self explanatory; we are creating the container div with all of the tab divs and the content div. We are also applying the correct ID or class to the appropriate div. We should have something that looks like the following:

Now that the XHTML and CSS is out of the way time for the JavaScript/Ajax. We will be using the Prototype.js Framework again in this tutorial which can be downloaded http://prototype.conio.net/.
function init () { var tabs = document.getElementsByClassName('tabs'); for (var i = 0; i < tabs.length; i++) { $(tabs[i].id).onclick = function () { getTabData(this.id); } } } function getTabData(id) { var url = 'process.php'; var rand = Math.random(9999); var pars = 'id=' + id + '&rand=' + rand; var myAjax = new Ajax.Request( url, {method: 'get', parameters: pars, onLoading: showLoad, onComplete: showResponse} ); } function showLoad () { $('load').style.display = 'block'; } function showResponse (originalRequest) { var newData = originalRequest.responseText; $('load').style.display = 'none'; $('content').innerHTML = newData; }
The first function init() (which we will be attached to the body onload) we are setting up the onclick events for the tabs. First we are getting all of the tabs as objects by using Prototype’s getElemenetsByClassName function. This returns an array of all elements with the class name provided as a parameter. Next we need to loop through that array and and add an onclick function. We are setting up the tabs so that when they are clicked we trigger getTabData and pass it the tab ID so that the server side can figure out which data to pass back to the content area. The getTabData function is similar to the sendData function of our first workshop. We are setting the URL which is what will determine what data to pass back, we also created a new variable called rand. This variable ensures that the content is never cached on the server side. Next we create our pars variable to tell the Ajax object what parameters we are passing to the server side. Finally we create the Ajax object, set the method to get, pass in the parameters and set our event functions for the object. We cover this in greater detail in the first workshop. The next function showLoad which is called by myAjax while the object is communicating with the server simply changes the CSS style of the load div to block to notify the user that the content is loading. Finally the show response function has a parameter of originalRequest, this is the data that is passed back from the server. In this function we set the style of the load div back to display:none and then populate the content div with the correct data we received from the server. Here is the complete XHTML and CSS:
<!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=iso-8859-1" /> <title>Ajax Workshop 2: Building Tabbed Content</title> <script type="text/javascript" src="prototype.js"></script> <script type="text/javascript"> function init () { var tabs = document.getElementsByClassName('tabs'); for (var i = 0; i < tabs.length; i++) { $(tabs[i].id).onclick = function () { getTabData(this.id); } } } function getTabData(id) { var url = 'process.php'; var rand = Math.random(9999); var pars = 'id=' + id + '&rand=' + rand; var myAjax = new Ajax.Request( url, {method: 'get', parameters: pars, onLoading: showLoad, onComplete: showResponse} ); } function showLoad () { $('load').style.display = 'block'; } function showResponse (originalRequest) { var newData = originalRequest.responseText; $('load').style.display = 'none'; $('content').innerHTML = newData; } </script> <style type="text/css"> body { font-family:Arial, Helvetica, sans-serif; font-size:12px; } #container { width:500px; } .tabs { width:50px; margin-right:10px; padding:4px; text-align:center; float:left; cursor:pointer; border:1px solid #ccc; border-bottom:0; } #content { height:250px; clear:both; border:1px solid #ccc; } #load { position:absolute; left:0; top:0; width:100px; height:20px; background-color:red; color:white; display:none; } </style> </head> <body onload="init()"> <div id="load">Loading...</div> <div id="container"> <div class="tabs" id="tab1">Tab 1</div> <div class="tabs" id="tab2">Tab 2</div> <div class="tabs" id="tab3">Tab 3</div> <div class="tabs" id="tab4">Tab 4</div> <div id="content"></div> </div> </body> </html>
Finally here is the PHP which is self explanatory for Process.php.
<?php function stringForJavascript($in_string) { $str = ereg_replace("[\r\n]", " \\n\\\n", $in_string); $str = ereg_replace('"', '\\"', $str); Return $str; } switch($_GET['id']) { case 'tab1': $content = 'This is content for tab 1.'; break; case 'tab2': $content = 'This is content for tab 2.'; break; case 'tab3': $content = 'This is content for tab 3.'; break; case 'tab4': $content = 'This is content for tab 4.'; break; default: $content = 'There was an error.'; break; } print stringForJavascript($content); usleep(400000); ?>
Alternatively you could check the database for content instead of using a case statement and having the content hard coded.
Here is what it looks like when complete
If you guys have any questions or comments there is a thread in the discussion boards.










I love your tutorials! Great stuff. Please keep them coming.
Digg Effect!!!!! (a.k.a you never got good traffic to this site?)
Remove the key for the timestamp guys.
I getting the same wordpress error just now 3:46pm EST on Sat. 18th.
Nice tutorial though - thanks
This would be loads easier to do with hidden divs, then you could just toggle visibility between none and block.
What Echilon said. Seems stupid to have to load the content for Tab2 on both the first click and the N+1th click.
Nice but it fails under IE6.x
Funny that loading the content via AJAX takes just as long if not longer than a page refresh.
Loving the article, thanks ever so much. Great site, keep up the good work!
Cool code :-). But what if the contents from the tab overflows the tab window? That is, I don’t see any scroll bars appearing, the text just overlaps the tab frame.
That’s pretty nice, but you neglected to implement a fix for breaking the back button (i.e.: hidden iFrames and URL fragment)
This is interesting.. come on guys… This tutorial seems like a good start !.. don’t expect it to do too much.
Keep it up author.
Great job!
@jglynn - This is because I put a sleep of 0.4 seconds in the PHP file to show the load div, if not it is basically instant.
@Kevin C - You can set the overflow for the content div to scroll.
Awesome script.
Could someone tell me how to put a linebreak into the $content part, without having ” \n\ ” in the actual output?
If you use this for your main navigation then this is one of the inappropriate use of AJAX, because it will break the back button and that is really bad.
Hidden divs would be better solution for this, even if loading tab2 seems redundant while tab1 is selected. Speed is the sole point for putting extra behavior on the browser side.
What if I click to tab2 then decide to go back to tab1. You’ll keep me wait twice by showing an obnoxious “Loading” banner!
If the link target is fixed regardless of current context (i.e. selected tab), and the probability of the user clicking it is reasonably high … just keep them hidden and display them upon request.
If probability of click is low, and the result is dependent on the current context use AJAX. Livesearch on large archive makes sense with AJAX. While toggling search options might not be good choice.
Guys, I think you’re missing the point of this tutorial. It’s a starting point that you’d obviously have to customize to your site/liking just as you have with any other that you’ve used from the net.
As far as the back button compatibility, all you have to do really is add a hash, or anchor if that’s the term you prefer, to the URL that’s sent. So when you clicked tab 2 the URL would be something like: http://www.ajaxlessons.com/demo/workshop2.html#tab2 and so on.
@jglynn - the amount of time saved/taken is not the key to Ajax, unless it’s taking an unusually long time to complete the process. The key is that you’re not refreshing so the user experience stays intact. For the user it seems more like a customized experience for themon a one to one basis. (The content I want, when I want it, kind of thing)
@Andrew - Keep it up, these are good starts for peeps. I’ll put something together soon.
Laters
Thanks for this tutorial, I can already think of some fun things to do with it.
Ugh….I’m so tired of hearing people say, “….breaks the back button….” One of the major reasons behind implementing an Ajax-ified web app is to give the user the same experience they get from a thick-client app. First, developers need to address what the purposes of using the back button in the app are, and then implement solutions to provide the same functionality. Every time I hear someone say, “Ajax breaks the back button,” I think “Really? Not the way I develop.” I can’t think of any desktop applications that I use on a regular basis that uses a back button. If your app has to use the back button and you can’t program it differently, then maybe Ajax isn’t right for your app.
Great site. Would it be possible to get a printable version of the lessons? I love to read these online but would also like to print it our since i travel alot.
Yes, expect PDF versions of all of the workshops coming soon.
Interesting, the title of this page grabbed my attention straight away. Simple because we are current building an application exactly like that. It’s not using AJAX but I wouldn’t mind converting it if I could figure out someway to make validation, error message and field highlighting easier.
Nice website! Useful tutorial ! keep them coming!
I’ve accomplished something similar already but the problem i’m facing now is that i want to implement further AJAX techniques (e.g. form validation) into the page (DIV) that is being refreshed…
this would require another approach since the innerHTML method doesn’t parse anything more than basic HTML.
Any suggestions on this?
thnx
Hic, man!
It’s greate tutorial.
Thanks for sharing…
Please write more articles using AJAX for PHP & XML
I’m having trouble figuring out how to load other pages in the content div… I want to load some PHP forms that are already coded and work… Is there a way for it not to simply load text? Or, text formatted with HTML?
http://www.ajaxlessons.com/demo/dynamicTabs.html
for a simple tab navigation, i think that´s better/simple than ajax.
Does anybody know of a way to have a tab load by default, so that when the page is first visited a tab shows.
function init () {
//////// just call a function right away ////////
getTabData(’tab1′);
var tabs = document.getElementsByClassName(’tabs’);
for (var i = 0; i
I am having trouble forcing this to load content into 2 defferent divs. For example, you have the main div that content is loaded into when you click the tab but what javascript would you need to add so that the content of 2 different div’s is updated?
Hi, nice site, nice tutes. I jsut started with ajax, and I´m trying to use this on my site, but when I put the div´s inside another and give a property of text-align center to the body, in Firefox the content dosen´t align center, and in seconde when I put the script to load the content of 1, the preloader stays open until I click on another button.
Could someone tell me how to put a linebreak into the $content part, without having ” \n\ ” in the actual output?
It works fine if I remove the function called StringForJavascript, whats the point of all the eregs?
IM trying to write $content = Click but the “link” doesnt seem to work.
Any ideas how I can make it?
Thanks for the script by the way =)
hi,
This example helps me lot for my preparation,
when i used some text box in the screens and enter the values in it. when i move one tab to next tab and came to the previous tab where i have entered the some value in the text box its not present there how to capture the values and retrieve to be present in the box as i entered before. please help me out ASAP.
Thanks & Regards
Vijayan.gk
Great tutorial!
I have a doubt: I’m triying to write and image inside $content, in process.php, but it doesn’t appear in the page result. Anybody know a solution?
Of course I have check the path was correct, and it is.
Thanks!
Don’t take care about the question asked before. I have solved my problem. The path was wrong. Sorry!
where can I add evalScripts: true in this script?
Ive tried
var myAjax = new Ajax.Request( URL, {method: ‘get’, parameters: pars, onLoading: showLoad, onComplete: showResponse, evalScripts: true} );
and also var myAjax = new Ajax.Update > evalscripts: true
but nothing works.. any ideas?
Thank you for providing such a great tutorial…
I need to ask…if i want to load a different HTML file for each tab…so how should i change for the getTabData function??
Hello!
Better:
function init(){
var tabs =document.getElementsByClassName(’tab’);
tabs.each(
function(tab,iterator){
tab.onclick = function(){
getTabData(this.id);
}
}
);
How do I place 2 #content on each page?
Lets say..
Tab 1 & 2 will load the content in #content while Tab 3 & 4 will load the content in #content2 ?
Good stuff
how can load default tab when page is open first and how can change background tabs when user clicks on a tab?
It will be good for my gaming site
Nice tut. !
Keep up the good work!
This is great place for web developer. Thanks for providing such articles and project samples.
Great tutorial, I’ll keep an eye on this website!
Thank you!
Great. Thanks for sharing the great tips
Great tutorial. This is what I’ve been looking for.
Great tutorial! Exactly what IM after, nice and slick with no extra useless code. Its a great base to work on.
Keep up the good work (any try not to get disheartened at the noobs making silly comments… expecting it to do everything)
Hi! Nice site! In this workshop how do you think it is the best way to include a web form?
Thanks!
thnx
Very good.Thanks
Hey, I love it.
Thank you.
I love it kindly show how one can do the text and images at the same time tried doing the text and connecting to the db but i was not able to get my data in the right way may be am doing something wrong……………………….may be
hii, this is a great tutorials,
thanks
i’ll try this for my site
thank you
Great tutorial. This is what I’ve been looking for
Good Work!
nice tutorial! Thanks for posting!
However I am stuck trying to put a form into each tab and post the content to the very same tab (ideally I would like to use it like an iframe) - is this possible? If yes, could someone be so kind a provide a code - hint to help me out?
Cheers