Tabs

Page history last edited by stevefaulkner 2 mos ago

 

type: widget

release: 1.5

priority: -

status: complete

documentation: http://docs.jquery.com/UI/Tabs

demo: http://jqueryui.com/demos/tabs

 


 

1 - Description:

 

A tab strip is used to chunk sections of content into multiple panes that can be shown one at a time, much like the sections in a notebook. Depending on the size of the window and length of tab labels, you can create a tab view that contains between two and six to eight tabs. This rule of thumb is followed because tab strips should never wrap to multiple rows or insert horizontal scrollers for the tabs because of the poor visual connection between the tab and the pane below (yes, these have been seen in the past, but is not a good thing). If there are too many items to fit in a tab strip, consider re-grouping the tab content into fewer tabs or moving to a different navigation widget like a vertical left navigation bar or tree which can accomodate a larger number of items.

 

There is a current tab widget in the UI library that needs to be extended to allow for vertical tabs (left or right orientation):

http://docs.jquery.com/UI/Tabs

http://jqueryui.com/demos/tabs

 

Detailed tab behavior descriptions can be found for Apple OS X and Microsoft Windows.

 


 

2 - Visual Design:

 

 


 

 

3 - Functional Specifications/Requirements:

 

Options/Methods/Callbacks

  • options:
    • selected (integer, default: 0)
      • Zero-based index of the tab to be selected on initialization. To set all tabs to unselected set this option to -1 (null is deprecated).
    • deselectable (boolean, default: false)
      • When set to true, clicking a selected tab will unselect it.
    • event (string, default: "click")
      • Name of the event that is used for selecting a tab. To select on hover, use "mouseover".
    • disabled (array, default: [])
      • Array of zero-based tab indices that will be disabled on initialization. Disabled tabs cannot be selected by the selection event.
    • cookie (object, default: null (no cookie used))
      • Save the currently selected tab in a cookie. This value is then being used to determine the initially selected tab if the selected option is not defined. Requires the jQuery cookie plugin.
      • The options in this object are passed through to the jQuery.cookie method.
      • Additional option: name (string, default: UUID generated from jQuery.data method) (the cookie's name)
    • spinner (string, default: "Loading…")
      • While remote content is loading, this HTML content will be displayed in the tab title area. To disable the feature, set to an empty string.
    • cache (boolean, default: false)
      • By default, tabs that load remote content will re-request the content each time the tab is re-selected. Set this option to true to have the remote content requested only the first time and cached for subsequent selections.
    • ajaxOptions (object, default: {})
      • The options in this object are passed through to the jQuery.ajax method on remote content loads.
    • idPrefix (string, default: "ui-tabs-")
      • For generation of ids for newly added tab panels.
    • fx (object or array of 2 objects, default: (no effects used))
      • The options in this object/these objects are passed through to the jQuery.animate method.
      • If objects are given in array, the first object defines the hide, the second one the show animation being used.
    • tabTemplate (string, default: "<li><a href="#{href}"><span>#{label}</span></a></li>")
      • Template to create a new a tab label form. The placeholders #{href} and #{label} are

        are replaced with their values passed to the add method.

    • panelTemplate (string, default: "<div></div>")
      • Template to create a new tab content panel from.
  • methods:
    • select
    • load
    • add
    • remove
    • enable
    • disable
    • url
    • destroy
    • length
    • rotate
  • callbacks:
    • select (event: tabsselect (custom))
    • load (event: tabsload (custom))
    • show (event: tabsshow (custom))
    • add (event: tabsadd (custom))
    • remove (event: tabsremove (custom))
    • enable (event: tabsenable (custom))
    • disable (event: tabsdisable (custom))
  • 'ui' object:

 

Specificiations

  • Indices are generally zero-based.
  • select callback: triggers when a tab is selected by event as defined in event option or programmatically via select method. If this function returns false, the requested tab won't become selected.
  • load callback: triggers when an ajax tab successfully has loaded content, either explicitly via load method or implicitly by selecting a tab.
  • show callback: triggers when the selected tab is shown. In case of animation being defined for showing this means after the animation is complete.
  • The aforementioned callbacks are thus triggered in the following order: 1. select, 2. load (ajax tab only), 3. show.
  • add callback: triggers when a new tab has been added via add method.
  • remove callback: triggers when a tab has been removed via remove method.
  • enable callback: triggers when a tab has been enabled via enable method.
  • disable callback: triggers when a tab has been disabled via disable method.
  • There are 4 possibilities to set the initially selected tab:
    • selected option (highest priority)
    • url fragment identifier matching a tab href's fragment identifier: href="#fragment-identifier",
    • from cookie,
    • the according class attribute is already specified in HTML source: <li class="ui-tabs-selected"> (lowest priority)

A possibly arising conflict is resolved by giving each alternative a different priority, as denoted.

  • It is possible to initialize an empty tab set and add tabs later on. 

  • A selected tab cannot be deselected by selecting it a second time unless option deselectable is set to true. 

  • A selected tab cannot be disabled.

  • If the selected tab is being removed the one to the right is selected as long as it is not the last one at the same time - in this case the one to the left is selected (mimicing behavior in Firefox).

  • The type of tab (in-page vs. ajax) is determined automatically from the href attribute of the contained anchor elements - an href being solely a fragment-identfier href="#fragment-identifier" results in an in-page tab, an href pointing to an existing resource href="/path/to/resource.html" results in an ajax tab. External URIs are not supported due to security restrictions with ajax.

 

Css Classes

The following markup is used in tab implementation with added classes in bold (note this is the rendered source):

 

     Sample Markup

 

     <div style="display: block;" id="tabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all">

 

     <ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">

     <li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active">a href="#tabs-1">First</a></li>

     <li class="ui-state-default ui-corner-top"><a href="#tabs-2">Second</a></li>

     <li class="ui-state-default ui-corner-top"><a href="#tabs-3">Third</a></li>

     </ul>

 

     <div id="tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom">Tabs 1 Panel Content</div>

     <div id="tabs-2" class="ui-tabs-hide ui-tabs-panel ui-widget-content ui-corner-bottom">Tabs 2 Panel Content</div>

     <div id="tabs-3" class="ui-tabs-hide ui-tabs-panel ui-widget-content ui-corner-bottom">Tabs 3 Panel Content</div>

 

     </div>

 

     List of Classes - and Explaination:

 

     In the Container Div:

     ui-tabs -

     ui-widget -

     ui-widget-content -

     ui-corner-all -

 

     In the Unordered List that makes up your Tabs:

     ui-tabs-nav -

     ui-helper-reset -

     ui-helper-clearfix-

     ui-widget-header-

     ui-corner-all

 

      In the List tags themselves (these are your actual tabs):

     ui-state-default - 

     ui-corner-top -

     ui-tabs-selected -

     ui-state-active -

 

     In Panels that contain your content:

     ui-tabs-hide -

     ui-tabs-panel -

     ui-widget-content -

     ui-corner-bottom -

 

 

Changes from 1.5, 1.6rc5 in refactor

  • setting all tabs to unselected via value -1 instead of null (deprecated)

 

4 - Markup & Style:

 

4.1 Initial markup examples

 

     (Pre-enhanced HTML markup structure that will be transformed into the final widget. There may be multiple possible HTML markup options per widget: for example, for a slider, radiobuttons, inputs or selects could all be used. )

 

4.2 Recommended transformed HTML markup demo with html and css (live view of svn):

 

View Demo Page: http://jquery-ui.googlecode.com/svn/trunk/tests/static/tabs/tabs.html

 

 

 

 

     (The HTML markup structure and classes that will be used by the scripts in the enhanced version) 

 

4.3 Markup & style browser QA status

 

As of 12/12/08, static markup for this widget renders correctly in the following browsers.  (Correct rendering = true to design, with only small differences across browsers owing to differences in support of rounded corners, and native OS form element and font rendering.)

 

Please update this list as more browsers / platforms are tested.

 

 

XP         

Vista     

Mac 10.5

IE 6

 

 

 

 

IE 7

 

 

 

IE 8

 

 

 

Firefox 2.0.0.18

 

 

 

Firefox 3.0.4

 

 

 

Safari 3.2

 

 

 

Opera 9.1

 

 

 

 

Opera 9.62

 

 

 

 

Chrome 3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    

 

 

 

 

 

 

4.4 Accessibility recommendation

 

 

Potential issues:

  1. tabs are links, but activating the link does not send focus to a fragment identifier corresponding with the start of the tabs content. Does work as expected when javascripted disabled.
  2. Looks like CSS (outline:none) used to supress focus rectangle on links.
  3. currently selected tab is indicated using color, this is lost when high contrast mode is used.
  4. Tabs and tab panel state are not identified programmatically (use of ARIA?).
  5. keyboard navigation via tab rather then arrow keys (see Accessibility discussion: http://groups.google.com/group/jquery-a11y/browse_thread/thread/cc28c74dd22c80e7)

 

Fluid improvement to jQuery UI tabs

 

4.5 CSS & Theme

 

(Description of the CSS classes to be used for all states, how custom theming and Themeroller support will work.) 

 


 

5 - Latest version of plugin:

 

http://code.google.com/p/jquery-ui/source/browse/tags/latest/ui/ui.tabs.js

 


 

6 - Open issues being discussed

 

(Use this area to place things that we're hashing out like featuresand options we're not sure we should include, questions about how this fits into UI and relates to other widgets and utilities, known problems, whether features should be broken across multiple releases, etc.)

 


 

 

 

 

Comments (12)

profile picture

Richard D. Worth said

at 9:11 am on Dec 13, 2008

Should ui-tabs-hide be ui-helper-hidden? Is there any reason it needs to be tabs-specific?

profile picture

scottjehl said

at 9:56 am on Dec 13, 2008

Seems it should have both, assuming it had the ui-tabs-hide class in previous releases. I'm not thrilled about the redundancy, but it follows what we're doing on other components with the addition of framework classes. Also, widget CSS needs a way to refer to elements without using the framework states (right?).

profile picture

Richard D. Worth said

at 10:06 am on Dec 13, 2008

My first thought was that it should be renamed ui-tabs-hidden instead of ui-tabs-hide, for consistency with the framework classes. With as much as is already breaking in this release, I will tend toward cleanliness and consistency rather than backwards compatibility. But the more I thought about it, I can't see a use case for having a specific tabs-hidden class. It's just hidden. It's not hidden in some tabs-specific way. Or I guess that was my question ;) I think it's different than a case like disabled. Since disabled is a visible state, I think it's important to have both ui-draggable-disabled and ui-disabled (as an example). That way you can set a global disabled style with a widget specific override.

profile picture

Richard D. Worth said

at 10:10 am on Dec 13, 2008

As far as consistency with other widgets, this is the only widget specific -hide or -hidden I saw, though other plugins hide things. Like accordion.

profile picture

Jörn Zaefferer said

at 11:28 am on Dec 13, 2008

Accordion currently uses display:none, which probably should be replaced with ui-helper-hidden.

profile picture

kpitn said

at 3:20 pm on Jan 13, 2009

Actually fxAutoHeight is no more an option of tabs, are you considering re integrate this option ?

profile picture

Klaus Hartl said

at 11:43 am on Jan 25, 2009

Remember that it's not only about screen readers but also the ability to print.

profile picture

Jan V said

at 3:48 pm on Jun 1, 2009

If I understand it correctly 'ui-state-active' should be applied upon mousedown and should be removed on mouseup. Otherwise we don't have a state for mousedown. Tabs keep the active state upon click. And Accordion even uses the active state to indicate selected.
I find this inconsistency when I wanted to implement buttons clicks. Tabs, Accordion etc. should remove active state on mouseup and Accordion should use own 'ui-accordion-selected'. Now here is the other issue. Selected uses 'ui-selected'. Should we have general (and reusable) 'ui-state-selected' and each widget could customize it to its needs. Or the' tabs-selected', 'accordion-selected' approach is better.

profile picture

sompylasar said

at 11:04 am on Aug 15, 2009

On Opera 9.65 (Win) ui.tabs sortable demo at http://jqueryui.com/demos/tabs/#sortable behaves glitchy: after drag the dropped tab jumps right and slightly down.
Please, test this case.

profile picture

sompylasar said

at 11:08 am on Aug 15, 2009

profile picture

Matt Smith said

at 7:28 am on Oct 22, 2009

Is there any reason why the tabs widget does not include the fillspace option that the accordian has?

profile picture

Bohdan Ganicky said

at 6:12 am on Jan 4, 2010

Is it possible to implement a "leave" callback? I have a situation in which I need to transfer information from one tab panel to another when switching between them. Now I have to do it manually. Another option could be to put a recently leaved tab information to callback's "ui" object.

You don't have permission to comment on this page.