Tabpanel Navigation Menu
Tabpanel Example 2: Multiselect
Validate DOM (HTML5)
Happy Time Pizza On-line Ordering System
Keyboard Shortcuts
- Left: Move to previous tab when focus is in tablist
- Up: Move to previous tab when focus is in tablist
- Right: Move to next tab when focus is in tablist
- Down: Move to next tab when focus is in tablist
- Home: Show first tab when focus is on tab buttons
- End: Show last tab tab when focus is on tab buttons
- Space: Toggle the visibility of the panel
- Control+PageUp: Move focus to previous tab in tablist
- Control+PageDown: Move focus to next tab in tablist
- Control+Up: Move focus to tab of current tab panel
ARIA Roles and Properties
-
Roles:
role="application"
role="tablist"
role="tab"
role="tabpanel"
- States and properties:
aria-multiselect
aria-expanded
aria-labelledby
aria-hidden
HTML Source Code
Show HTML Source Code: tabpanel2.inc
<div role="application">
<script type="text/javascript">
var tabpanel1 = new TabPanelMultiselect("tabpanel_1");
widgets.add(tabpanel1);
var tab1 = new Tab("tab_1", "panel_1");
tabpanel1.add(tab1);
var tab2 = new Tab("tab_2", "panel_2");
tabpanel1.add(tab2);
var tab3 = new Tab("tab_3", "panel_3");
tabpanel1.add(tab3);
var tab4 = new Tab("tab_4", "panel_4");
tabpanel1.add(tab4);
</script>
<h2>Happy Time Pizza On-line Ordering System</h2>
<form>
<dl class="tablist" role="tablist" aria-multiselect="true" id="tabpanel_1" class="tabpanel">
<dt id="tab_1" role="tab" tabindex="0" aria-expanded="false">Crust Options</dt>
<dd id="panel_1" role="tabpanel" aria-labelledby="tab_1" aria-hidden="true">
<ul class="controlList">
<li><label><input type="radio" name="crust" value="crust1"/>Deep Dish</label></li>
<li><label><input type="radio" name="crust" value="crust1"/>Thick and cheesey</label></li>
<li><label><input type="radio" name="crust" value="crust1"/>Thick and spicey</label></li>
<li><label><input type="radio" name="crust" value="crust1"/>Classic thin</label></li>
<li><label><input type="radio" name="crust" value="crust1"/>Foot stamped (New)</label></li>
</ul>
</dd>
<dt id="tab_2" role="tab" tabindex="0" aria-expanded="true">Vege Options</dt>
<dd id="panel_2" role="tabpanel" aria-labelledby="tab_2" aria-hidden="false">
<ul class="controlList">
<li><label><input type="checkbox" name="vege1"/>Black Olives</label></li>
<li><label><input type="checkbox" name="vege2"/>Green Olives</label></li>
<li><label><input type="checkbox" name="vege3"/>Green Peppers</label></li>
<li><label><input type="checkbox" name="vege4"/>Mushrooms</label></li>
<li><label><input type="checkbox" name="vege5"/>Black Olives</label></li>
<li><label><input type="checkbox" name="vege6"/>Onions</label></li>
<li><label><input type="checkbox" name="vege7"/>Pineapple</label></li>
</ul>
<dt id="tab_3" role="tab" tabindex="0" aria-expanded="false">Carnivore Options</dt>
<dd id="panel_3" role="tabpanel" aria-labelledby="tab_3" aria-hidden="true">
<ul class="controlList">
<li><label><input type="checkbox" name="meat1"/>Hamburger</label></li>
<li><label><input type="checkbox" name="meat2"/>Ham</label></li>
<li><label><input type="checkbox" name="meat3"/>Itailian Sausage</label></li>
<li><label><input type="checkbox" name="meat4"/>Pepporroni</label></li>
</ul>
</dd>
<dt id="tab_4" role="tab" tabindex="0" aria-expanded="false">Delivery Options</dt>
<dd id="panel_4" role="tabpanel" aria-labelledby="tab_4" aria-hidden="true">
<ul class="controlList">
<li><label><input type="radio" name="delivery" value="delivery1"/>Eat in</label></li>
<li><label><input type="radio" name="delivery" value="delivery2"/>Carry out</label></li>
<li><label><input type="radio" name="delivery" value="delivery3"/>Delivery</label></li>
<li><label><input type="radio" name="delivery" value="delivery4"/>Overnight mail</label></li>
</ul>
</dd>
</dl>
</form>
</div>
Javascript Source Code
Show Javascript Source Code: globals.js
<script type="text/javascript">
/**
*
* The Globale Variables
*/
if (!window.Node) {
var Node = { // If there is no Node object, define one
ELEMENT_NODE: 1, // with the following properties and values.
ATTRIBUTE_NODE: 2, // Note that these are HTML node types only.
TEXT_NODE: 3, // For XML-specific nodes, you need to add
COMMENT_NODE: 8, // other constants here.
DOCUMENT_NODE: 9,
DOCUMENT_FRAGMENT_NODE: 11
}
}
var KEY_PAGEUP = 33;
var KEY_PAGEDOWN = 34;
var KEY_END = 35;
var KEY_HOME = 36;
var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_RIGHT = 39;
var KEY_DOWN = 40;
var KEY_SPACE = 32;
var KEY_TAB = 9;
var KEY_BACKSPACE = 8;
var KEY_DELETE = 46;
var KEY_ENTER = 13;
var KEY_INSERT = 45;
var KEY_ESCAPE = 27;
var KEY_F1 = 112;
var KEY_F2 = 113;
var KEY_F3 = 114;
var KEY_F4 = 115;
var KEY_F5 = 116;
var KEY_F6 = 117;
var KEY_F7 = 118;
var KEY_F8 = 119;
var KEY_F9 = 120;
var KEY_F10 = 121;
var KEY_M = 77;
var NS_XHTML = "http://www.w3.org/1999/xhtml"
var NS_STATE = "http://www.w3.org/2005/07/aaa";
// **********************************************
// *
// * Commonly used helper functions
// *
// **********************************************
/**
*
* nextSiblingElement
*
* @contructor
*/
function nextSiblingElement( node ) {
var next_node = node.nextSibling;
while( next_node
&& (next_node.nodeType != Node.ELEMENT_NODE) ) {
next_node = next_node.nextSibling;
} // endwhile
return next_node;
}
/**
*
* previousSiblingElement
*
* @param ( node ) node object for which you are looking for the next sibling element node
*
* @return ( node) next sibling or "null"
*/
function previousSiblingElement( node ) {
var next_node = node.previousSibling;
while( next_node
&& (next_node.nodeType != Node.ELEMENT_NODE) ) {
next_node = next_node.previousSibling;
} // endwhile
return next_node;
}
/**
*
* firstChildElement
*
* @param ( node ) node object for which you are looking for the first child element node
*
* @return ( node) next sibling or "null"
*/
function firstChildElement( node ) {
var next_node = node.firstChild;
while( next_node
&& (next_node.nodeType != Node.ELEMENT_NODE) ) {
next_node = next_node.nextSibling;
} // endwhile
return next_node;
}
/**
*
* getTextContentOfNode
*
* @contructor
*/
function getTextContentOfNode( node ) {
var next_node = node.firstChild;
var str = "";
while( next_node ) {
if( (next_node.nodeType == Node.TEXT_NODE ) &&
(next_node.length > 0 )
)
str += next_node.data;
next_node = next_node.nextSibling;
} // endwhile
return str;
}
/**
*
* setTextContentOfNode
*
* @contructor
*/
function setTextContentOfNode( node, text ) {
// Generate a new text node with the text value
var text_node = document.createTextNode(text);
// Remove child nodes to remove text
while (node.firstChild) {
node.removeChild(node.firstChild);
} // while
// Append new text to the container element
node.appendChild( text_node );
}
</script>
Show Javascript Source Code: widgets.js
<script type="text/javascript">
// JavaScript Document
// Widgets is a way to initialize widgets in the ARIA examples
function Widgets() {
this.widgets = new Array();
}
/**
* add is member of the Widgets Object
* and used add a widget ot the list of widgets to be intitialized
* as part of the onload event
* The controls array is the list of controls to initialize
* @member Enable
* @return none
*/
Widgets.prototype.add = function(obj) {
this.widgets[this.widgets.length] = obj;
}
/**
* init is member of the Widgets Object
* and is called by the onload event to initialize widgets in the web resource
* The controls array is the list of controls to initialize
* @member Enable
* @return none
*/
Widgets.prototype.init = function() {
for(var i = 0; i < this.widgets.length; i++ )
this.widgets[i].init();
}
var widgets = new Widgets();
function initApp() {
widgets.init();
}
</script>
Show Javascript Source Code: browser.js
<script type="text/javascript">
// JavaScript Document
// This module is to abstract browser dependencies
// This makes the widget code cleaner and earier to read by making most browser specfic coding
// in one place rather han scatered throghot documents
var ARIA_STATE = "aria-";
//
// WebBrowser object to abstract accessibility API differences between web standards supporting browsers and Internet Explorer 7.0
//
// The state variable keeps track of current state of checkbox
function WebBrowser() {
}
//
// keyCode is a function to get the keycode from a keypress event
//
// @param ( event object) event is an event object
//
// @return ( keycode )
WebBrowser.prototype.keyCode = function( event ) {
var e = event || window.event;
return e.keyCode;
}
/**
* OnClick Event Simulator
*
* @param ( node ) DOM node object
* @return nothing
*/
if( document.createEvent ) {
// If a web standards based browser implement this function
WebBrowser.prototype.simulateOnClickEvent = function( node ) {
// W3C DOM Events way to trigger a "click" event
var e = document.createEvent('MouseEvents');
e.initEvent( 'click', true, true );
node.dispatchEvent( e );
}
} else {
// If a Microsoft IE based browser implement this function
WebBrowser.prototype.simulateOnClickEvent = function( node ) {
var e = document.createEventObject();
node.fireEvent( "onclick", e );
} // endif
}
if ( document.addEventListener ) {
// If a web standards based browser implement this function
WebBrowser.prototype.setMouseCapture = function( node, clickHandler, downHandler, moveHandler, upHandler ) {
if( clickHandler )
document.addEventListener( "click", clickHandler, true );
if( downHandler )
document.addEventListener( "mousedown", downHandler, true );
if( moveHandler )
document.addEventListener( "mousemove", moveHandler, true );
if( upHandler)
document.addEventListener( "mouseup", upHandler, true );
}
WebBrowser.prototype.releaseMouseCapture = function( node, clickHandler, downHandler, moveHandler, upHandler ) {
if( upHandler)
document.removeEventListener( "mouseup", upHandler, true );
if( moveHandler )
document.removeEventListener( "mousemove", moveHandler, true );
if( downHandler )
document.removeEventListener( "mousedown", downHandler, true );
if( clickHandler )
document.removeEventListener( "click", clickHandler, true );
}
} else {
// If a Microsoft IE based browser implement this function
WebBrowser.prototype.setMouseCapture = function( node, clickHandler, downHandler, moveHandler, upHandler ) {
node.setCapture();
if( clickHandler)
node.attachEvent( "onclick", clickHandler );
if( downHandler)
node.attachEvent( "onmousedown", downHandler );
if( moveHandler )
node.attachEvent( "onmousemove", moveHandler );
if( upHandler )
node.attachEvent( "onmouseup", upHandler );
} // endif
WebBrowser.prototype.releaseMouseCapture = function( node, clickHandler, downHandler, moveHandler, upHandler ) {
if( upHandler )
node.detachEvent( "onmouseup", upHandler );
if( moveHandler )
node.detachEvent( "onmousemove", moveHandler );
if( downHandler)
node.detachEvent( "onmousedown", downHandler );
if( clickHandler)
node.detachEvent( "onclick", clickHandler );
node.releaseCapture();
} // endif
}
if (typeof document.documentElement.setAttributeNS != 'undefined') {
WebBrowser.prototype.stopPropagation = function( event ) {
if( event.stopPropagation )
event.stopPropagation();
if( event.preventDefault )
event.preventDefault();
return false;
}
WebBrowser.prototype.target = function( event ) {
return event.target;
}
WebBrowser.prototype.attrName = function( event ) {
return event.attrName;
}
WebBrowser.prototype.testAttrName = function( event , attrName) {
return event.attrName == attrName;
}
WebBrowser.prototype.charCode = function(event) {
return event.charCode;
}
WebBrowser.prototype.calculateOffsetLeft = function( node ) {
return node.offsetLeft;
}
WebBrowser.prototype.calculateOffsetTop = function( node ) {
return node.offsetTop;
}
WebBrowser.prototype.pageX = function( e ) {
return e.pageX;
}
WebBrowser.prototype.pageY = function( e ) {
return e.pageY;
}
WebBrowser.prototype.setNodePosition = function(node,left,top) {
node.style.left = left+"px";
node.style.top = top+"px";
}
} else {
WebBrowser.prototype.stopPropagation = function( event ) {
event.cancelBubble = true;
event.returnValue = false;
return false;
}
WebBrowser.prototype.charCode = function(event) {
return window.browser.keyCode( event );
}
WebBrowser.prototype.target = function( event ) {
return event.srcElement;
}
WebBrowser.prototype.attrName = function( event ) {
return event.propertyName;
}
WebBrowser.prototype.testAttrName = function( event , attrName) {
var str = attrName;
if( attrName.indexOf("aria-") >=0 ) {
str = attrName.replace(/aria-/,"");
var node = document.getElementById('test1');
if( node )
node.innerHTML = str.substr(0,1).toUpperCase();
var len = str.length;
str = "aria" + str.substr(0,1).toUpperCase() + str.substr(1, len);
var node = document.getElementById('test2');
// if( node )
// node.innerHTML = node.innerHTML + "<li>" + str + "</li>";
}
return event.propertyName == str;
}
WebBrowser.prototype.calculateOffsetLeft = function(node) {
var offset = 0;
while( node ) {
offset += node.offsetLeft;
node = node.offsetParent;
}
return offset;
}
WebBrowser.prototype.calculateOffsetTop = function(node) {
var offset = 0;
while( node ) {
offset = offset + node.offsetTop;
node = node.offsetParent;
}
return offset;
}
WebBrowser.prototype.pageX = function( e ) {
return e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
}
WebBrowser.prototype.pageY = function( e ) {
return e.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
}
WebBrowser.prototype.setNodePosition = function(node,left,top) {
offsetx = 0;
offsety = 0;
nnode = node.offsetParent
while( nnode ) {
offsetx = offsetx + nnode.offsetLeft;
offsety = offsety + nnode.offsetTop;
nnode = nnode.offsetParent;
}
node.style.left = left-offsetx+"px";
node.style.top = top-offsety+"px";
}
};
if (document.addEventListener) {
// Functions for W3C Standards compliant implementation of adding event handlers
WebBrowser.prototype.addEvent = function(elmTarget, sEventName, fCallback) {
elmTarget.addEventListener(sEventName, fCallback, false);
returnValue = true;
};
WebBrowser.prototype.removeEvent = function(elmTarget, sEventName, fCallback) {
elmTarget.removeEventListener(sEventName, fCallback, false);
returnValue = true;
};
WebBrowser.prototype.addChangeEvent = function(elmTarget, fCallback) {
elmTarget.addEventListener("DOMAttrModified", fCallback, false);
returnValue = true;
};
} else {
if(document.attachEvent) {
// IE Specific Event handler functions
WebBrowser.prototype.addEvent = function(elmTarget, sEventName, fCallback) {
returnValue = elmTarget.attachEvent('on' + sEventName, fCallback);
};
WebBrowser.prototype.removeEvent = function(elmTarget, sEventName, fCallback) {
returnValue = elmTarget.detachEvent('on' + sEventName, fCallback);
};
WebBrowser.prototype.addChangeEvent = function(elmTarget, fCallback) {
returnValue = elmTarget.attachEvent("onpropertychange", fCallback);
};
} else {
// For browsers that do not support W3C or IE event functions
WebBrowser.prototype.addEvent = function(elmTarget, sEventName, fCallback) {
return false;
};
WebBrowser.prototype.removeEvent = function(elmTarget, sEventName, fCallback) {
return false;
};
WebBrowser.prototype.addChangeEvent = function(elmTarget, fCallback) {
return false;
};
}
}
var browser = new WebBrowser();
</script>
Show Javascript Source Code: tabpanel2.js
<script type="text/javascript">
// JavaScript Document
/**
*
* The TabPanelMultiselect object is used to maintain information about a Tab Panel widget
* including the collection of tab objects
*
* @contructor
*/
function TabPanelMultiselect( id ) {
this.id = id;
this.tabs = new Array();
this.current_tab = 0;
}
/**
* init is a subclass of TabPanelMultiselect and is used to initialize the event handlers and
* tabs in a tab panel.
*
* @member TabPanelMultiselect
* @return nothing
*/
TabPanelMultiselect.prototype.init = function() {
this.node = document.getElementById(this.id);
var obj = this;
browser.addEvent(this.node, "click", function(event) {handleTabPanelMultiselectClickEvent(event, obj); }, false);
browser.addEvent(this.node, "keydown", function(event) {handleTabPanelMultiselectKeyDownEvent(event, obj); }, true);
for(var i = 0; i < this.tabs.length; i++ )
this.tabs[i].init( this, i );
this.tabs[0].node.tabIndex = 0;
}
/**
* add is a subclass of TabPanelMultiselect
* The tab obj is added to the list of tabs in a Tab Panel object
*
* @member TabPanelMultiselect
* @param ( Tab Object) obj
* @return nothing
*/
TabPanelMultiselect.prototype.add = function(obj) {
this.tabs.push( obj );
}
/**
*
* The Tab object is used to maintain information about a panel in a Tab Panel widget
* including the node of the last control that had focus in the tab panel
*
* @params ( IDREF ) tab_id the id of the tab control container element
* @params ( IDREF ) panel_id the id of the panel container element
* @contructor
*/
function Tab( tab_id, panel_id ) {
this.tab_id = tab_id;
this.panel_id = panel_id;
}
/**
* init is a subclass of Tab
* The init function currentlt doesn't do anything right now
*
* @member TabPanelMultiselect
* @return nothing
*/
Tab.prototype.init = function( tab_panel, num ) {
this.tab_num = num;
this.node = document.getElementById( this.tab_id );
this.node_panel = document.getElementById( this.panel_id );
this.node.tabIndex = -1;
var obj1 = this;
var obj2 = tab_panel;
browser.addEvent(this.node, "focus", function(event) {handleTabFocusEvent(event, obj1, obj2); }, false);
}
/**
* nextTabPanelMultiselect moves to the next tab panel
* Updates the current tab panel index
* If panel was selected before in current session focus is moved to last control with focus
* Used by keyboard event handlers to change currrent tab panel
*
* @param ( TabPanelMultiselect object) tab_panel is the TabPanelMultiselect object associated with the event
* @return nothing
*/
tabPanelMultiselectNext = function( tab_panel ) {
if( tab_panel.current_tab < (tab_panel.tabs.length - 1) ) {
tabPanelMultiselectMoveTo( tab_panel, (tab_panel.current_tab + 1) );
} // endif
}
/**
* previousTabPanelMultiselect moves to the previous tab panel
* Updates the current tab panel index
* If panel was selected before in current session focus is moved to last control with focus
* Used by keyboard event handlers to change currrent tab panel
*
* @param ( TabPanelMultiselect object) tab_panel is the TabPanelMultiselect object associated with the event
* @return nothing
*/
tabPanelMultiselectPrevious = function( tab_panel ) {
if( tab_panel.current_tab > 0 ) {
tabPanelMultiselectMoveTo( tab_panel, (tab_panel.current_tab - 1) );
} // endif
}
/**
* tabPanelMultiselectMoveTo moves to the previous tab panel
* Updates the current tab panel index
* Used by keyboard event handlers to change currrent tab panel
* If panel was selected before in current session focus is moved to last control with focus
*
* @param ( TabPanelMultiselect object) tab_panel is the TabPanelMultiselect object associated with the event
* @param ( TabPanelMultiselect object) index is the index in the panel list of the selected panel
* @return nothing
*/
function tabPanelMultiselectMoveTo( tab_panel, index ) {
if( index < 0 )
index = 0;
if( index >= tab_panel.tabs.length )
index = tab_panel.tabs.length - 1;
if( (index >= 0 ) && ( index < tab_panel.tabs.length ) ) {
for(var i=0; i < tab_panel.tabs.length; i++ ) {
tab_panel.tabs[i].node.tabIndex = -1;
} // end for
// Move keyboad focus
tab_panel.tabs[index].node.tabIndex = 0;;
tab_panel.tabs[index].node.focus();
} // endif
}
/**
* tabPanelMultiselectToogleExpanded
*
* @param ( DOM node )
* @return nothing
*/
function tabPanelMultiselectToggleExpanded( tab_panel ) {
var current_tab = tab_panel.tabs[tab_panel.current_tab];
if( current_tab.node.getAttribute("aria-expanded") == "true") {
current_tab.node.setAttribute("aria-expanded", "false");
current_tab.node_panel.setAttribute("aria-hidden", "true");
} else {
current_tab.node.setAttribute("aria-expanded", "true");
current_tab.node_panel.setAttribute("aria-hidden", "false");
} // endif
current_tab.node.className += "";
current_tab.node_panel.className += "";
}
/**
* indexNodeInTabList checcks to see if the node the event ocurred on is in the list of tab in the tab panel
*
* @param ( DOM node ) node_target of the element the event occured on
* @param ( TabPanel object) tab_panel is the TabPanel object associated with the event
* @return index of tab panel of current event target; -1 if node target is not in list
*/
function indexOfNodeInTabList ( node_target, tab_panel ) {
var index = -1;
for(var i = 0; i < tab_panel.tabs.length; i++ ) {
if( node_target == tab_panel.tabs[i].node ) {
index = i;
} // endif
} // endfor
return index;
}
/**
* isNodeInTabList checcks to see if the node the event ocurred on is in the list of tabs in the tab panel
*
* @param ( DOM node ) node_target of the element the event occured on
* @param ( TabPanel object) tab_panel is the TabPanel object associated with the event
* @return boolean true if the node is in the tab list, otherwise false
*/
function isNodeInTabList ( node_target, tab_panel ) {
var flag = false;
for(var i = 0; !flag && (i < tab_panel.tabs.length); i++ ) {
if( node_target == tab_panel.tabs[i].node ) {
flag = true;
} //endif
} // endfor
// alert(flag);
return flag;
}
/**
* findTabForTabPanel
*
* @param ( DOM node ) node_target of the element the event occured on
* @param ( TabPanel object) tab_panel is the TabPanel object associated with the event
* @return boolean true if the node is in the tab list, otherwise false
*/
function getTabForTabPanel( node_target, tab_panel ) {
var index = null;
// Find node with role=tabpanel
var node = node_target.parentNode;
while( node &&
( node.getAttribute('role') != "tabpanel")
) {
node = node.parentNode;
} // end while
// alert( node.id );
if( node ) {
var tab_id = node.getAttribute("aria-labelledby");
if( tab_id )
node = document.getElementById( tab_id );
index = indexOfNodeInTabList ( node , tab_panel );
} // endif
return index;
}
/**
* handleTabPanelMultiselectKeyDownEvent
* Keyboard commands for the Tab Panel
*
* @param ( event object ) event
* @param ( TabPanelMultiselect object) tab_panel is the TabPanelMultiselect object associated with the event
* @return boolean false if the event was used by Tab Panel, otherwisee true
*/
function handleTabPanelMultiselectKeyDownEvent(event, tab_panel) {
var e = event || window.event;
// Save information about a modifier key being pressed
// May want to ignore keyboard events that include modifier keys
var no_modifier_pressed_flag = !e.ctrlKey && !e.shiftKey && !e.altKey;
var control_modifier_pressed_flag = e.ctrlKey && !e.shiftKey && !e.altKey;
switch( e.keyCode ) {
case KEY_UP:
if( !isNodeInTabList( browser.target(e), tab_panel ) && control_modifier_pressed_flag ) {
var tab_index = getTabForTabPanel(browser.target(e), tab_panel );
if( tab_index != null )
tabPanelMultiselectMoveTo( tab_panel, tab_index );
return browser.stopPropagation(e);
} // endif
case KEY_LEFT:
if( isNodeInTabList( browser.target(e), tab_panel ) && no_modifier_pressed_flag ) {
tabPanelMultiselectPrevious( tab_panel);
return browser.stopPropagation(event);
} // endif
break;
case KEY_RIGHT:
case KEY_DOWN:
if( isNodeInTabList( browser.target(e), tab_panel ) && no_modifier_pressed_flag ) {
tabPanelMultiselectNext( tab_panel);
return browser.stopPropagation(e);
} // endif
break;
case KEY_HOME:
if( isNodeInTabList( browser.target(e), tab_panel ) && no_modifier_pressed_flag ) {
tabPanelMultiselectMoveTo( tab_panel, 0 );
return browser.stopPropagation(e);
}
break;
case KEY_END:
if( isNodeInTabList( browser.target(e), tab_panel ) && no_modifier_pressed_flag ) {
tabPanelMultiselectMoveTo( tab_panel, (tab_panel.tabs.length - 1) );
return browser.stopPropagation(e);
}
break;
case KEY_SPACE:
case KEY_ENTER:
if( isNodeInTabList( browser.target(e), tab_panel ) && no_modifier_pressed_flag ) {
tabPanelMultiselectToggleExpanded( tab_panel );
return browser.stopPropagation(e);
} // endif
break;
case KEY_PAGEDOWN:
if( control_modifier_pressed_flag ) {
if( isNodeInTabList( browser.target(e), tab_panel ) ) {
tabPanelMultiselectMoveTo( tab_panel, (tab_panel.current_tab+1) );
} else {
var tab_index = getTabForTabPanel( browser.target(e), tab_panel );
if( tab_index != null )
tabPanelMultiselectMoveTo( tab_panel, (tab_index+1) );
} // endif
return browser.stopPropagation(e);
} // endif
break;
case KEY_PAGEUP:
if( control_modifier_pressed_flag ) {
if( isNodeInTabList( browser.target(e), tab_panel ) ) {
tabPanelMultiselectMoveTo( tab_panel, (tab_panel.current_tab-1) );
} else {
var tab_index = getTabForTabPanel( browser.target(e), tab_panel );
if( tab_index != null )
tabPanelMultiselectMoveTo( tab_panel, tab_index );
} // endif
return browser.stopPropagation(e);
} // endif
break;
}
return true;
}
/**
* handleTabPanelMultiselectClickEvent
* handlers changing tab panels when the user uses the mouse to select a tab
*
* @param ( event object ) event
* @param ( TabPanelMultiselect object) tab_panel is the TabPanelMultiselect object associated with the event
* @return boolean false if the event was used by Tab Panel, otherwisee true
*/
handleTabPanelMultiselectClickEvent = function(event, tab_panel) {
var e = event || window.event;
var index = indexOfNodeInTabList( browser.target(e), tab_panel);
if( index >= 0 ) {
tabPanelMultiselectMoveTo( tab_panel, index );
tabPanelMultiselectToggleExpanded( tab_panel );
return browser.stopPropagation(e);
} // endif
return true;
}
/**
* handleTabFocusEvent
*
* @param ( event object ) event
* @param ( Tab object ) tab
* @param ( TabPanelMultiselect object) tab_panel is the TabPanelMultiselect object associated with the event
*
* @return boolean false if the event was used by Tab Panel, otherwisee true
*/
handleTabFocusEvent = function(event, tab, tab_panel) {
var e = event || window.event;
tab_panel.current_tab = tab.tab_num;
return browser.stopPropagation(e);
return true;
}
</script>
CSS Source Code
Show CSS Source Code: tabpanel2.css
<style type="text/css">
/* CSS Document */
input:focus,
input:active {
outline: 1px solid black;
}
dl.tablist {
margin: 0;
padding: 0;
list-style: none;
border-bottom: thin solid black;
width: 20em;
}
dl.tablist dt {
margin: 0;
border-top: thin solid black;
border-left: thin solid black;
border-right: thin solid black;
padding-left: 1.25em;
padding-right: 1em;
padding-top: .25em;
padding-bottom: .125em;
font-weight: bold;
background-color: #0099CC;
color: white;
background-repeat:no-repeat;
background-position: 3px center;
background-image: url(images/contracted.gif);
}
dl.tablist dt:hover,
dl.tablist dt:active,
dl.tablist dt:focus {
background-color: #006699;
color: white;
}
dl.tablist dt[aria-expanded="true"] {
background-repeat:no-repeat;
background-position: 3px center;
background-image: url(images/expanded.gif);
}
dl dd {
margin: 0;
padding: 0;
padding-top: .25em;
padding-bottom: .5em;
padding-left: 1.25em;
border-top: thin solid black;
border-left: thin solid black;
border-right: thin solid black;
}
dl.tablist dt[aria-expanded="false"] + dd {
display: none;
}
dl.tablist dt[aria-expanded="true"] + dd {
display: block;
}
dl.tablist dd ul {
margin: 0;
padding: 0;
list-style: none;
}
</style>