Semantic Tabs with jQuery

This plugin creates tabbed panels from semantic markup. What does this mean?

Many (most?) javascript tab solutions tend to take the following approach: In the markup, create a list of elements to use as the tabs themselves, then create a list of elements to use as the tab panels, like so:

<ul>
  <li>Tab1</li>
  <li>Tab2</li>
  <li>Tab3</li>
</ul>
<div>
  Panel 1
</div>
<div>
  Panel 2
</div>
<div>
  Panel 3
</div>

This works OK for most users, but with javascript disabled, or using a limited platform (like a cell phone) or to a search engine spider, the headers are disconnected from the content they label.

This script allows you to structure your markup like so:

<div id="mytabset">
  <div class="panel">
    <h3>Tab1</h3>
     Panel stuff 1
  </div>
  <div class="panel">
    <h3>Tab2</h3>
     Panel stuff 2
  </div>
  <div class="panel">
    <h3>Tab3</h3>
     Panel stuff 3
  </div>
</div>

So that to a spider or device with limited rendering capability, the markup is semantically correct.

To turn the above markup into a tab set, just apply the following:

$("#mytabset").semantictabs({
  panel:'panel',                //-- Selector of individual panel body
  head:'h3',                    //-- Selector of element containing panel head
  active:':first'               //-- Selector of panel to activate by default
});

This will 'tabify' the 'mytabset' div, turning the text contained in the H3 elements into the tabs. Styling these is a an exercise for the reader, but generally the following works pretty well:

/*semantic tabs*/
ul.semtabs {
  margin:0 auto;
  clear:both;
  border-bottom: 4px solid #4c77b3;
  height:25px;
  list-style:none !important;
}
ul.semtabs li {
  float:left;
  height:30px;
  display:block;
  margin:0 !important;
  background-image:none;
}
ul.semtabs li a {
/*  height:15px;*/
  line-height:15px;
  display:block;
  padding: 5px 5em;
  text-decoration:none;
  font-weight:bold;
  background-color:#e6eeee;
}
ul.semtabs li.active a {
  background-color: #4c77b3;
  color: #fff;
}
/*end semantic tabs*/

You can also activate a tab programmatically, like so:

$("#appcontainer").semantictabs({activate:2});

Where 2 is the index of the tab you which to activate (starting from zero, of course).

See it in action at http://viewer.mars.asu.edu.

Download from the jQuery Plugins page.

Code now managed through GitHub. Download from there!

Comments

Hello,

Sorry but my english is very poor...

With your example :

<div id="mytabset" class="panelcontainer">
...
$("#mytabset").semantictabs({
  container:'panelcontainer',
...

this does not work :

container.find("." + args.container + " ." + args.panel)...

(.panelcontainer is not a descendant element)

this work :

container.parent().find("." + args.container + " ." + args.panel)...

Thank you for your plugin

Christian's picture

Yes, you're absolutely correct. My demo code is incorrect as the plugin is written at this time, but I've updated the plugin so that it's referring to the container.parent() instead of container, as this is a cleaner way of doing it, without requiring an additional container around the set of divs. I hadn't realized that all the production code I'm using has an extra container!

I've updated the code on the jQuery plugins site.

Thanks!

-chris

$("#mytabset").semantictabs({
container:'panelcontainer', //-- Selector of element containing all panels
panel:'panel', //-- Selector of individual panel body
head:'h3', //-- Selector of element containing panel head
active:':first', //-- Selector of panel to activate by default
});

should be

$("#mytabset").semantictabs({
container:'panelcontainer', //-- Selector of element containing all panels
panel:'panel', //-- Selector of individual panel body
head:'h3', //-- Selector of element containing panel head
active:':first' //-- Selector of panel to activate by default
});

took out the comma

Have not gotten this to work and believe I've followed your example precisely.

Christian's picture

Dave, thanks for the heads up. I always forget that IE will error out if it encounters a trailing comma like that. Also, I've revised the code somewhat to get rid of the redundancy in the 'panelscontainer' option. Code posted here and (shortly) on jquery.com should be correct.

Hey,

I've been using this plugin and thing it's great!!!

I ran into a slight bug, because I add additional tag's into the li's that get created.

So I changed this area:

        // Tab click behavior
        container.find("ul.tabs li").click(function(){
            container.find(args.panel).hide();
            container.find("ul.tabs li").removeClass("active");
            container.find(args.panel + "[title='"+jQuery(this).text()+"']").show();
            jQuery(this).addClass("active");
        });

This is the line:

            container.find(args.panel + "[title='"+jQuery(this).text()+"']").show();

To:

            container.find(args.panel + "[title='"+jQuery(this).find("a").first().text()+"']").show();

This makes sure that the link name is used, and no other information.

Hi Chris. I would like to hide the head element (e.g. h3) that is repeated in the panel content, how can I do it?
Thanks a lot

Hi, this looks exactly what I am after but unfortunately I cannot get this to work. I have downloaded your plugin and have copy and pasted your css and markup. Can you confirm where you place the js code to turn the divs into tabs? Can you also confirm where you place the code if you wanted to do this programatically? Sorry for the numpty questions!

Christian's picture

Span, I've added a demo.html file to the project on GitHub which illustrates how to use the plugin.

Christian's picture

Andrea, you can simply hide it with CSS:

.panel h3 {
  display:none;
}

Thank you - I had the javascript in the wrong place. I was calling it from the head and not after the div. Many thanks!

Christian's picture

Span - techinically it shouldn't matter. $(document).ready(); waits until the DOM is completely loaded and should work the same regardless of where you put it.