Control.Tabs

Unobtrusive CSS tabs for Prototype.js

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.

View source on the examples above to learn more about their inner workings. Each code block beings with a comment such as <!-- begin example 2 code -->

Sample HTML

<ul id="tab_group_one">
    <li><a href="#one">One</a></li>
    <li><a href="#two">Two</a></li>
</ul>
<div id="one"><p>I am the content for tab one.</p></div>
<div id="two"><p>I am the content for tab two.</p></div>
<script>
    new Control.Tabs('tab_group_one');
</script>

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.

document.getElementsByClassName('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/projects/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.

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

How to Read the API Table

A "Class Method or Property" is often referred to in other languages as a static method or property. The "instances" property would be referenced as "Control.Tabs.instances". An "Instance Method or Property" refers to something that is available to each instance of the class. For example, the "setActiveTab" would be referenced like so: "var my_tabs = new Control.Tabs(); my_tabs.setActiveTab();". Anything in the method and property lists that ends with "()" is a method, and anything that doesn't is a property. All events are specifiable in the options hash, or via "observe()" if Object.Event has been included on the page before Control.Tabs was. In a method signature, each argument is separated by a comma, if the words are lower case it refers to the data type and gives a hint to what it is used for, if there is an upper case word it refers to the class of object that must be used. Arguments with [square brackets] around them are optional.

Class Methods and Properties

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

Instance Methods and Properties

ReturnNameDescription
objectinitialize(mixed element_id[,options Hash])Create a new instance by passing in a string id or Element object.
voidaddTab(link Element)Add a link Element object to the list of tabs.
voidsetActiveTab(mixed element_id)Set the active tab by a link id string, or a link Element object.
voidnext()Calls setActiveTab() on the next tab.
voidprevious()Calls setActiveTab() on the previous tab.
voidfirst()Calls setActiveTab() on the first tab.
voidlast()Calls setActiveTab() on the last tab.
ElementactiveContainerContains the currently active container element.
ElementactiveLinkContains the currently active link element.

Options

TypeNameDefaultDescription
functionbeforeChangeempty functionCalled before a tab changes.
functionafterChangeempty functionCalled before a tab changes.
booleanhoverfalseShould 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.
booleansetClassOnContainerfalseWether to set the activeClassName to the link, or it's parent element.
stringactiveClassName'active'The class name added to the active link
stringdefaultTab'first'Which tabs starts as active. Can be 'first', 'last' or any link id string.
booleanautoLinkExternaltrueWether to have links that point to containers in the tab list, but are outside of it, control the tabs instance.
RegExptargetRegExp/#(.+)$/The RegExp object that will be used to match link hrefs inside the list.

Events

All events can be passed in as an option, or if Object.Event has been included, they can be observed by calling Control.Tabs.observe() to observe all instances, or by calling observe() on any particular instance to just observe that one.

NameDescription
beforeChange(old_container Element)Element is the old container Element object.
afterChange(new_container Element)Element is the new container Element object.

Advanced Usage Examples

//with no options
var tabs = new Control.Tabs($('my_list_of_tabs'));
//with all available options. these are the defaults
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 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){
    //this is called whenever any Control.Tabs instance changes
});
tabs.observe('beforeChange',function(old_container){
    //this is called whenever our "tabs" instance changes
});

RSS Changelog

Is available at http://livepipe.net/projects/control_tabs/changelog.rss

Downloads & SVN

The new 2.0 version is available via the button in the upper right. It introduces a backwards compatibility break with 1.0 by removing the responders functionality. This functionality is superseded by using the Object.Event library.

The Control Suite subversion repository is available at: svn://livepipe.net/control_suite/

The last 1.0 series release is available at http://livepipe.net/downloads/control.tabs.1.6.0.js

Online Forum

Do you have questions, bug reports or suggestions? Visit the Control.Tabs online forum.

Other Resources

Have you written a post or article about Control.Tabs? Please contact me!

  • Ajax Usability: Tab History