LivePipe has been deprecated and is no longer maintained.
The author now works primarily on Thorax

Control.Tabs

Unobtrusive CSS tabs for Prototype.

Introduction & Examples

Control.Tabs attaches creates a tabbed interface from an unordered list of links/anchors that point to any elements on your page that have an id attribute. Since it attaches these behaviors to HTML that already has semantic meaning, it will degrade gracefully for browsers that do not support JavaScript, and is search engine friendly. It attaches in one line of code for simple use cases, but is highly customizable and can be used in a variety of edge cases.

This is the simplest example of a set of tabs.

Note that the styling for the tabs is done with CSS, not the Control.Tabs script.

This example demonstrates scripting a Control.Tabs instance. Try clicking the links below, or changing the select box.

I am the second tab.

I am the third tab.

I am the fourth tab.

« »

Control.Tabs is fully programmable, so in the example above the links are programmed to change which tab is active, and an event handler is registered to change the select box (and visa versa). The tabs can also be trigged via hovering, and need not even look like tabs. The example below use images instead of divs, and the "hover" option. See the API section for more details.

HTML


	<!-- example 1 -->
	<ul id="tabs_example_one" class="subsection_tabs">
		<li class="tab"><a href="#one">One</a></li>
		<li class="tab"><a href="#two">Two</a></li>
	</ul>
	<div id="one"><p>This is the simplest example of a set of tabs.</p></div>
	<div id="two"><p>Note that the styling for the tabs is done with CSS, not the Control.Tabs script.</p></div>

	<!-- example 2 -->
	<ul id="tabs_example_two" class="subsection_tabs">
		<li class="tab"><a href="#a">One</a></li>
		<li class="tab"><a href="#b">Two</a></li>
		<li class="tab"><a href="#c">Three</a></li>
		<li class="tab"><a href="#d">Four</a></li>
	</ul>
	<div id="a"><p>This example demonstrates scripting a Control.Tabs instance. Try clicking the links below, or changing the select box.</p></div>
	<div id="b"><p>I am the second tab.</p></div>
	<div id="c"><p>I am the third tab.</p></div>
	<div id="d"><p>I am the fourth tab.</p></div>
	<a href="" id="tabs_example_two_first" style="margin-right:10px;">&laquo;</a>
	<a href="" id="tabs_example_two_previous" style="margin-right:10px;">&larr;</a>
	<select id="tabs_example_two_select" style="margin-right:10px;">
		<option value="a">One</option>
		<option value="b">Two</option>
		<option value="c">Three</option>
		<option value="d">Four</option>
	</select>
	<a href="" id="tabs_example_two_next" style="margin-right:10px;">&rarr;</a>
	<a href="" id="tabs_example_two_last">&raquo;</a>

	<!-- example 3 -->
	<ul class="tabbed_images" id="tabs_example_three">
		<li><a href="#image_1"><img src="/stylesheets/sample_images/tabs_example_1_small.jpg"/></a></li>
		<li><a href="#image_2"><img src="/stylesheets/sample_images/tabs_example_2_small.jpg"/></a></li>
		<li><a href="#image_3"><img src="/stylesheets/sample_images/tabs_example_3_small.jpg"/></a></li>
		<li><a href="#image_4"><img src="/stylesheets/sample_images/tabs_example_4_small.jpg"/></a></li>
	</ul>
	<img src="/stylesheets/sample_images/tabs_example_1_big.jpg" id="image_1"/>
	<img src="/stylesheets/sample_images/tabs_example_2_big.jpg" id="image_2"/>
	<img src="/stylesheets/sample_images/tabs_example_3_big.jpg" id="image_3"/>
	<img src="/stylesheets/sample_images/tabs_example_4_big.jpg" id="image_4"/>

JavaScript


	//example 1
	new Control.Tabs('tabs_example_one');
	
	//example 2
	var tabs_example_two = new Control.Tabs('tabs_example_two',{
		afterChange: function(new_container){
			$A($('tabs_example_two_select').options).each(function(option,i){
				if(option.value == new_container.id){
					$('tabs_example_two_select').options.selectedIndex = i;
					throw $break;
				}
			});
		}
	});
	$('tabs_example_two_select').observe('change',function(){
		tabs_example_two.setActiveTab($('tabs_example_two_select').value);
	});
	$('tabs_example_two_first').observe('click',function(event){
		this.first();
		Event.stop(event);
	}.bindAsEventListener(tabs_example_two));
	$('tabs_example_two_previous').observe('click',function(event){
		this.previous();
		Event.stop(event);
	}.bindAsEventListener(tabs_example_two));
	$('tabs_example_two_next').observe('click',function(event){
		this.next();
		Event.stop(event);
	}.bindAsEventListener(tabs_example_two));
	$('tabs_example_two_last').observe('click',function(event){
		this.last();
		Event.stop(event);
	}.bindAsEventListener(tabs_example_two));
	
	//example 3
	new Control.Tabs('tabs_example_three',{
		hover: true
	});

Note that this example doesn't have an style information. If you want the CSS used on this page, view source to find the stylesheet, and then look for ".subsection_tabs"

Creating Control.Tabs Instances by Class Name

In the above example above the tab list has an id attribute. The constructor for control tabs can take any element object, or id string, so if you assigned each list a class of "tabs", you could do the following instead.


		$$('.tabs').each(function(tab_group){
			new Control.Tabs(tab_group);
		});
	

Linking to Tabs from Other Pages

If you need to have a tab pre selected, just link to it as you would any other page with an element id in it. For instance, open this url in a new window: http://livepipe.net/control/tabs#api. The API tab on this page will now be selected. If you need to have multiple tabs pre selected (i.e, if you have multiple tab sets on a page), separate their names with commas, try "#two,four" for instance. This overrides the defaultTab option.

Linking to Other Pages within a Tab Set

If a link in a list of tabs does not begin with with "#" it will not be included in the tab list. This means you can mix and match on page tab links and external links as you please.

Linking to a Tab on the Same Page Outside the Tab List

By default, links pointing to a tab container outside of the list of tabs, will set the active tab. You can turn this off by specifying the option "autoLinkExternal" as false. For example the following link points to the API section of this page (HTML <a href="#api">API</a>) : API

Flash of Unstyled Content Problem (FOUC)

A common problem in larger pages is that the Control.Tabs script, Prototype.js, or other assets may take some time to load. While they are loading, The active tab will not be set. On this page for example, #tutorial starts as the active tab. If this page takes a long time to load, all three tabs will be shown. If we manually write in style="display:none;" onto the other two tabs, browsers without JavaScript will never see them. A not entirely endorsed (but perfectly functional) solution is to use document.write() to create style information that hides the other tabs. This must be on the page and not in a library or external file. This way non JavaScript browsers still see all the content, and the rest of us see the tabs as intended.


		document.write('<style>#api, #resources { display:none; }</style>');
	

More Usage Examples


		//with no options
		var tabs = new Control.Tabs($('my_list_of_tabs'));

		//with all available options. these are the defaults
		var tabs = new Control.Tabs($('my_list_of_tabs'),{
			defaultTab: 'last',
			linkSelector: 'li span a',
			activeClassName: 'active_tab',
			beforeChange: function(old_container){}
		});

		//to programatically set the active tab
		tabs.setActiveTab($('link_object'));
		//or by the link id
		tabs.setActiveTab('one');
		//or by the order that the tabs were declared
		tabs.setActiveTab(2);

		//or programatically set to these special cases
		tabs.first(); //sets the first tab to active
		tabs.last(); //sets the last tab to active
		tabs.next(); //sets the next tab to active (unless last tab is already active)
		tabs.previous(); //sets the previous tab to active (unless first tab is already active)

		//this property has a reference to the container that is being displayed
		var active_container = tabs.activeContainer;
		active_container.update('some new HTML');

		//this property has a reference to the active link
		var active_link = tabs.activeLink;

		Control.Tabs.instances.length; //should be 1
		Control.Tabs.findByTabId('one').setActiveTab('two');

		//using Object.Event
		Control.Tabs.observe('beforeChange',function(control_tabs_instance,old_container,new_container){
		    //this is called whenever any Control.Tabs instance changes
		});
		tabs.observe('beforeChange',function(old_container,new_container){
		    //this is called whenever our "tabs" instance changes
		});
	

Class

ReturnNameDescription
object || falsefindByTabId(string element_id)Find an instance by any container id that it contains.
arrayinstancesAll created Control.Tabs instances.

Instance

ReturnNameDescription
Control.Tabsinitialize(Element container [,Hash options])Create a new instance by passing in a string id or Element object.
nulladdTab(Element link)Add a link Element object to the list of tabs.
nullfirst()Calls setActiveTab() on the first tab.
nulllast()Calls setActiveTab() on the last tab.
nullnext()Calls setActiveTab() on the next tab.
nullprevious()Calls setActiveTab() on the previous tab.
nullsetActiveTab(mixed link)Set the active tab by a link id string, a link Element object, or the index of tab.
ElementactiveContainerContains the currently active container element.
ElementactiveLinkContains the currently active link element.

Options

TypeNameDefaultDescription
stringactiveClassName'active'The class name added to the active link.
boolautoLinkExternaltrueWether to have links that point to containers in the tab list, but are outside of it, control the tabs instance.
stringdefaultTab'first'Which tabs starts as active. Can be 'first', 'last' or any link id string.
boolhoverfalseShould the tabs change when the mouse hovers over a link instead of clicking.
string || functionlinkSelector'li a'CSS selector that matches a link inside the list of tabs.
boolsetClassOnContainerfalseWether to set the activeClassName to the link, or it's parent element.
RegExptargetRegExp/#(.+)$/The RegExp object that will be used to match link hrefs inside the list.

Events

NameDescription
afterChange(Element new_container)
beforeChange(Element old_container, Element new_container)Throwing $break will prevent the new tab from becoming active.