View
 

Tabs

Page history last edited by Richard D. Worth 3 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 git):

 

View Demo Page: http://view.jqueryui.com/master/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 recommendations 

 
Required ARIA Markup:
  • role="tablist" for the outer container element
  • role="tab" for each tab element
  • role="tabpanel" on each tab panel element
  • aria-selected="true/false" for each tab, depending on whether the tab is currently the active one in the tablist
  • aria-expanded="true/false" for each tab panel, depending on whether the corresponding tab is currently expanded. This is specifically important for tabs that allow each tab to be collapsed.
  • aria-controls="<ID>" on each tab, references the ID of the tab's corresponding panel element
  • aria-labelledby="<ID>" on each tab panel, references the ID of the panel's corresponding tab element (in other words, the tab provides the accessible name for the panel)
  • aria-live="polite" on tab panels that load remote content
  • aria-busy="true/false" on tab panels with remote contents. The value will be "true" while the panel contents are loading, indicating to assistive technology that the content is not available yet. 

 

Keyboard Accessibility:

 

To comply with the DHTML Styleguide, the following keystrokes need to be supported:

  • For tab elements:
    • Left / Up arrow: Select and focus previous tab (if first tab has been reached, wrap to the last)
    • Right / Down Arrow: Select and focus next tab (if last tab has been reached, wrap to the first)
    • Ctrl + arrow keys: Change focus to the next / previous tab without selecting it. This is useful to allow (screen reader) users to explore the available tabs without triggering remote content (as this could have a high performance in bandwidth and delay). The Space /Enter key can then be used on the focused, unselected tab to select and expand it. 
    • Home: Select and focus first tab
    • End: Select and focus last tab
    • Enter / Space: Toggle the tab's expanded state (for tabs that allow each tab to be collapsed)
    • alt + del: Delete the currently selected tab (for tabs that allow this)
  • Inside Tab Panel:
    • Alt + Del: Delete the currently selected tab (for tabs that allow this)
    • Ctrl + PageUp: Select, expand and focus the tab associated with the previous tab panel (or wrap to the last)
    • Ctrl + PageDown: Select, expand and focus the tab associated with the next tab panel (or wrap to the first)
    • Ctrl + Up Arrow: Focus tab coresponding to the currently opened panel

 

A choice needs to be made between two types of keyboard interaction:

  1. Each tab is part of the web page's tab order, the Enter key is used to activate a tab (the way the JQuery tabs worked originally)
  2. Only the selected tab is part of the tab order, the arrow keys are used to change the selected tab (as recommended in the key strokes section above)

There has already been some discussion about the ideal keyboard model for tabs, which describes the benefits and disadvantages of both options. Ideally this discussion should be reopened to reach concensus. 

 

Potential issues:
  1. When a tab receives focus this needs to be indicated visually
  2. The selected tab needs to be indicated in a way that does not depend on color alone and remains visible in high contrast mode

 

Felix Nagel has created a plugin (ui.ariaTabs) that applies many of the recommendations above, and this should be used as a start for implementing accessibility changes 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 (16)

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 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.

profile picture

Scott González said

at 11:19 am on Mar 18, 2010

Can't you do this with the select event?

profile picture

fnagel said

at 4:07 am on Apr 15, 2010

Ive updated my accessibility "addon" for the UI tabs widget: http://github.com/fnagel/jQuery-Accessible-RIA

profile picture

fnagel said

at 11:46 am on Jun 7, 2010

Some people requested history support for UI Tabs. Ive tested a few history plugins and i liked jQuery Addresss the most. It works fine cross brower and is well documented, so I decided to add Asuals history plugin to to my jQuery UI ARIA widgets (which includes a jQuery UI Tabs addon for accessibility features).

Please see links below for further information.
http://www.felixnagel.com/blog/artikel/2010/06/06/jquery-aria-with-browser-history-support-tabs-lightbox-and-sortable-tables/
http://www.asual.com/jquery/address/

profile picture

Matt Travi said

at 3:01 pm on Jun 22, 2010

Although this is marked as complete, extending to include an option for vertical tabs is mentioned. Is there a time-line for this? Should something other than complete be used to mark the state of this widget if it is still expected to be extended?

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