Unobtrusive Draggable Tabbed Navigation

3

Posted on : 09/15/2008 | By : Jimmy Vu | In : Solution

There are many examples on creating tabbed navigation with (or without) help of JavaScript frameworks like Prototype, MooTools or JQuery. However, I find that it’s much easier to create draggable tabbed navigation using Chain.js and its great extension: Interaction.js.

Riziq, creator of Chain.js & Interaction.js, already showed an example on how to utilize the libs to build tab interface in a few JS code lines. However, for its own purpose, the example is not SEO-friendly — disabling JavaScript in your browser will result in empty content and search engines will see nothing on your page consequently. Now say, you want to create a tabbed navigation for your blog to show/hide “Latest Posts”, “Latest Comments” etc. and you want the links can be seen no matter if JavaScript is enabled or not in reader’s browser — something looks like this:

Tabbed navigation for my blog

Blog's tabbed navigation

Step 1: HTML & CSS

Just create a template in HTML and full links to latest posts, comments and most popular articles:

<div id="wrapper">
	<ul id="tabs">
		<li class="tab"><a href="#" class="title">Tab</a></li>
	</ul>
 
	<div class="content" id="latest_posts">
		<h2>Latest Posts</h2>
		<p></p>
	</div>
 
	<div class="content" id="latest_comments">
		<h2>Latest Comments</h2>
		<p></p>
	</div>
 
	<div class="content" id="most_pop">
		<h2>Most Popular</h2>
		<p></p>
	<div>
</div>

And here is the style sheet to get tabbed look:

#wrapper * {
    margin: 0;
    padding: 0;
}
 
#wrapper {
    background: #000;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 0.8em;
    padding-bottom: 1px;
    padding: 15px;
    width: 400px;
}
 
#wrapper ul {
    float: left;
    list-style: none;
}
 
#wrapper li {
    display: block;
    float: left;
    margin: 0 6px 0 0;
}
 
#wrapper li a{
	display: block;
    float: left;
    padding: 9px 15px;
    text-decoration: none;
}
 
#wrapper div {
    background: #fff;
    clear: left;
    height: 200px;
}
 
#wrapper .content{
	padding: 10px 15px;
}
 
#wrapper .content p{
    line-height: 1.6em;
    padding-top: 0.5em;
}
 
#wrapper .content a{
	color: #666;
}
 
.tab a {
    background: url("off_tab.png") top left repeat-x;
    color: #f2f2f2;
}
 
.tab.selected a{
    background: url("active_tab.png") top left repeat-x;
    color: #000;
}

At this point, the page looks fairly good and search engines (Yahoo, Google…) will be surely happy with it.

Step 2 – Creating Tabs and Link Them to Contents

It’s very simple to create tabs with Chain.js. The following scripts will do the job (for those who are not familiar with Chain.js, please read my articles here and here).

1
2
3
4
5
6
7
8
$('#tabs')
	.items([
		{id: 'latest_posts', title:'Latest Posts'},
		{id: 'latest_comments', title:'Latest Comments'},
		{id: 'most_pop', title:'Most Popular'}
	])
	.selectable({required:true}) /* force the first tab selected */
	.chain();

Now, we need to link tabs with related contents in div tags specified by id field. On tab clicked, all other contents should be hidden but linked one; this function is to accomplish that.

1
2
3
4
5
6
function showContent(id){
	$('.content').each(function(i, el){
		$(el).hide(); // hide all tabs
	});
	$('#' + id).show(); // show selected tab
}

By customizing default chain() method, we can inject onclick event to each tab.

8
9
10
11
12
13
.chain(function(){
	var self = this;
	this.click(function(){
		showContent(self.item().id);
	});
}

All codes are as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$(document).ready(function(){
	$('#tabs')
		.items([
			{id: 'latest_posts', title:'Latest Posts'},
			{id: 'latest_comments', title:'Latest Comments'},
			{id: 'most_pop', title:'Most Popular'}
		])
		.selectable({required:true}) /* force the first tab selected */
		.chain(function(){
			var self = this;
			this.click(	function(){
				showContent(self.item().id);
			});
		});
 
	showContent('latest_posts');
});
 
function showContent(id){
	$('.content').each(function(i, el){
		$(el).hide(); // hide all tabs
	});
	$('#' + id).show(); // show selected tab
}

Step 3 – Enable Drag-n-Drop

Of course, in practice, there is almost no need to make tabs draggable for a blog’s tabbed navigation. But if required, it can be fulfilled by just adding 2 more functions, draggable() and  sortable(), before the chain() method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$('#tabs')
	.items([
		{id: 'latest_posts', title:'Latest Posts'},
		{id: 'latest_comments', title:'Latest Comments'},
		{id: 'most_pop', title:'Most Popular'}
	])
	.selectable({required:true}) /* force the first tab selected */
	.draggable({axis:'x'})  /* enable drag-n-drop */
	.sortable({align:'horizontal'})
	.chain(function(){
		var self = this;
		this.click(	function(){
			showContent(self.item().id);
		});
	});

So now we have a tabbed navigation with advanced functionality implemented in a few code lines which are completely separated from HTML. And like other examples here, you can see demo and download source codes from links below:

Recommended Reading

JavaScript: The Good PartsJavaScript: The Good Parts

Most programming languages contain good and bad parts, but JavaScript has more than its share of the bad, having been developed and released in a h... Read More >

CSS: The Missing ManualCSS: The Missing Manual

Cascading Style Sheets can turn humdrum websites into highly-functional, professional-looking destinations, but many designers merely treat CSS as ... Read More >

Eloquent JavaScript: A Modern Introduction to ProgrammingEloquent JavaScript: A Modern Introduction to Programming

"A concise and balanced mix of principles and pragmatics. I loved the tutorial-style game-like program development. This book rekindled my earliest... Read More >

Share this :

  • Stumble upon
  • twitter

Comments (3)

[...] z javascriptly.com Minimalizovat, maximalizovat a [...]

I touch a bit on the strengths and weaknesses of Chain.js in a blog post of mine:

http://samuelmueller.com/post/2008/10/20/Client-side-templates-using-ASPNET-JQuery-Chain-and-TaffyDB.aspx

Hi Jimmy,

nice post, but I think it could be done using jQuery alone, hehe :)
May be I could add items(‘extract’) feature in the next (may be 0.3) release, so you can extract items from html.

Cheers!