770 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			770 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<html>
 | 
						|
<head>
 | 
						|
<style type="text/css">
 | 
						|
.tabpanel {
 | 
						|
  margin: 20px;
 | 
						|
  padding: 0;
 | 
						|
  height: 1%; /* IE fix for float bug */
 | 
						|
}
 | 
						|
.tablist {
 | 
						|
  margin: 0 0px;
 | 
						|
  padding: 0;
 | 
						|
  list-style: none;
 | 
						|
}
 | 
						|
 | 
						|
.tab {
 | 
						|
 | 
						|
  margin: .2em 1px 0 0;
 | 
						|
  padding: 10px;
 | 
						|
  height: 1em;
 | 
						|
  font-weight: bold;
 | 
						|
  background-color: #ec9;
 | 
						|
 | 
						|
  border: 1px solid black;
 | 
						|
  -webkit-border-radius-topright: 5px;
 | 
						|
  -webkit-border-radius-topleft: 5px;
 | 
						|
  -moz-border-radius-topright: 5px;
 | 
						|
  -moz-border-radius-topleft: 5px;
 | 
						|
  border-radius-topright: 5px;
 | 
						|
  border-radius-topleft: 5px;
 | 
						|
 | 
						|
  float: left;
 | 
						|
  display: inline; /* IE float bug fix */
 | 
						|
}
 | 
						|
 | 
						|
.panel {
 | 
						|
  clear: both;
 | 
						|
  display: block;
 | 
						|
  margin: 0 0 0 0;
 | 
						|
  padding: 10px;
 | 
						|
  width: 600px;
 | 
						|
  border: 1px solid black;
 | 
						|
 | 
						|
  -webkit-border-radius-topright: 10px;
 | 
						|
  -webkit-border-radius-bottomleft: 10px;
 | 
						|
  -webkit-border-radius-bottomright: 10px;
 | 
						|
  -moz-border-radius-topright: 10px;
 | 
						|
  -moz-border-radius-bottomleft: 10px;
 | 
						|
  -moz-border-radius-bottomright: 10px;
 | 
						|
  border-radius-topright: 10px;
 | 
						|
  border-radius-bottomleft: 10px;
 | 
						|
  border-radius-bottomright: 10px;
 | 
						|
}
 | 
						|
 | 
						|
ul.controlList {
 | 
						|
  list-style-type: none;
 | 
						|
}
 | 
						|
 | 
						|
li.selected {
 | 
						|
  color: black;
 | 
						|
  background-color: #fff;
 | 
						|
  border-bottom: 1px solid white;
 | 
						|
}
 | 
						|
 | 
						|
.focus {
 | 
						|
  margin-top: 0;
 | 
						|
  height: 1.2em;
 | 
						|
}
 | 
						|
 | 
						|
.accordian {
 | 
						|
  margin: 0;
 | 
						|
  float: none;
 | 
						|
  -webkit-border-radius: 0;
 | 
						|
  -moz-border-radius: 0;
 | 
						|
  border-radius: 0;
 | 
						|
  width: 600px;
 | 
						|
}
 | 
						|
 | 
						|
.hidden {
 | 
						|
  position: absolute;
 | 
						|
  left: -300em;
 | 
						|
  top: -30em;
 | 
						|
}
 | 
						|
</style>
 | 
						|
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
 | 
						|
<script type="text/javascript">
 | 
						|
$(document).ready(function() {
 | 
						|
 | 
						|
  var panel1 = new tabpanel("tabpanel1", false);
 | 
						|
  //var panel2 = new tabpanel("accordian1", true);
 | 
						|
});
 | 
						|
 | 
						|
//
 | 
						|
// keyCodes() is an object to contain keycodes needed for the application
 | 
						|
//
 | 
						|
function keyCodes() {
 | 
						|
  // Define values for keycodes
 | 
						|
  this.tab        = 9;
 | 
						|
  this.enter      = 13;
 | 
						|
  this.esc        = 27;
 | 
						|
 | 
						|
  this.space      = 32;
 | 
						|
  this.pageup     = 33;
 | 
						|
  this.pagedown   = 34;
 | 
						|
  this.end        = 35;
 | 
						|
  this.home       = 36;
 | 
						|
 | 
						|
  this.left       = 37;
 | 
						|
  this.up         = 38;
 | 
						|
  this.right      = 39;
 | 
						|
  this.down       = 40; 
 | 
						|
 | 
						|
} // end keyCodes
 | 
						|
 | 
						|
//
 | 
						|
// tabpanel() is a class constructor to create a ARIA-enabled tab panel widget.
 | 
						|
//
 | 
						|
// @param (id string) id is the id of the div containing the tab panel.
 | 
						|
//
 | 
						|
// @param (accordian boolean) accordian is true if the tab panel should operate
 | 
						|
//         as an accordian; false if a tab panel
 | 
						|
//
 | 
						|
// @return N/A
 | 
						|
//
 | 
						|
// Usage: Requires a div container and children as follows:
 | 
						|
//
 | 
						|
//         1. tabs/accordian headers have class 'tab'
 | 
						|
//
 | 
						|
//         2. panels are divs with class 'panel'
 | 
						|
//
 | 
						|
function tabpanel(id, accordian) {
 | 
						|
 | 
						|
  // define the class properties
 | 
						|
  
 | 
						|
  this.panel_id = id; // store the id of the containing div
 | 
						|
  this.accordian = accordian; // true if this is an accordian control
 | 
						|
  this.$panel = $('#' + id);  // store the jQuery object for the panel
 | 
						|
  this.keys = new keyCodes(); // keycodes needed for event handlers
 | 
						|
  this.$tabs = this.$panel.find('.tab'); // Array of panel tabs.
 | 
						|
  this.$panels = this.$panel.children('.panel'); // Array of panel.
 | 
						|
 | 
						|
  // Bind event handlers
 | 
						|
  this.bindHandlers();
 | 
						|
 | 
						|
  // Initialize the tab panel
 | 
						|
  this.init();
 | 
						|
 | 
						|
} // end tabpanel() constructor
 | 
						|
 | 
						|
//
 | 
						|
// Function init() is a member function to initialize the tab/accordian panel. Hides all panels. If a tab
 | 
						|
// has the class 'selected', makes that panel visible; otherwise, makes first panel visible.
 | 
						|
//
 | 
						|
// @return N/A
 | 
						|
//
 | 
						|
tabpanel.prototype.init = function() {
 | 
						|
  var $tab; // the selected tab - if one is selected
 | 
						|
 | 
						|
  // add aria attributes to the panel container
 | 
						|
  this.$panel.attr('aria-multiselectable', this.accordian);
 | 
						|
 | 
						|
  // add aria attributes to the panels
 | 
						|
  this.$panels.attr('aria-hidden', 'true');
 | 
						|
 | 
						|
  // hide all the panels
 | 
						|
  this.$panels.hide();
 | 
						|
 | 
						|
  // get the selected tab
 | 
						|
  $tab = this.$tabs.filter('.selected');
 | 
						|
 | 
						|
  if ($tab == undefined) {
 | 
						|
    $tab = this.$tabs.first();
 | 
						|
    $tab.addClass('selected');
 | 
						|
  }
 | 
						|
 | 
						|
  // show the panel that the selected tab controls and set aria-hidden to false
 | 
						|
  this.$panel.find('#' + $tab.attr('aria-controls')).show().attr('aria-hidden', 'false');
 | 
						|
 | 
						|
} // end init()
 | 
						|
 | 
						|
//
 | 
						|
// Function switchTabs() is a member function to give focus to a new tab or accordian header.
 | 
						|
// If it's a tab panel, the currently displayed panel is hidden and the panel associated with the new tab
 | 
						|
// is displayed.
 | 
						|
//
 | 
						|
// @param ($curTab obj) $curTab is the jQuery object of the currently selected tab
 | 
						|
//
 | 
						|
// @param ($newTab obj) $newTab is the jQuery object of new tab to switch to
 | 
						|
//
 | 
						|
// @param (activate boolean) activate is true if focus should be set on an element in the panel; false if on tab
 | 
						|
//
 | 
						|
// @return N/A
 | 
						|
//
 | 
						|
tabpanel.prototype.switchTabs = function($curTab, $newTab) {
 | 
						|
 | 
						|
  // Remove the highlighting from the current tab
 | 
						|
  $curTab.removeClass('selected');
 | 
						|
  $curTab.removeClass('focus');
 | 
						|
 | 
						|
  // remove tab from the tab order
 | 
						|
  $curTab.attr('tabindex', '-1');
 | 
						|
 | 
						|
  // update the aria attributes
 | 
						|
  
 | 
						|
  // Highlight the new tab
 | 
						|
  $newTab.addClass('selected');
 | 
						|
 | 
						|
  // If this is a tab panel, swap displayed tabs
 | 
						|
  if (this.accordian == false) {
 | 
						|
    // hide the current tab panel and set aria-hidden to true
 | 
						|
    this.$panel.find('#' + $curTab.attr('aria-controls')).hide().attr('aria-hidden', 'true');
 | 
						|
 | 
						|
    // show the new tab panel and set aria-hidden to false
 | 
						|
    this.$panel.find('#' + $newTab.attr('aria-controls')).show().attr('aria-hidden', 'false');
 | 
						|
  }
 | 
						|
 | 
						|
  // Make new tab navigable
 | 
						|
  $newTab.attr('tabindex', '0');
 | 
						|
 | 
						|
  // give the new tab focus
 | 
						|
  $newTab.focus();
 | 
						|
 | 
						|
} // end switchTabs()
 | 
						|
 | 
						|
//
 | 
						|
// Function togglePanel() is a member function to display or hide the panel associated with an accordian header
 | 
						|
//
 | 
						|
// @param ($tab obj) $tab is the jQuery object of the currently selected tab
 | 
						|
//
 | 
						|
// @return N/A
 | 
						|
//
 | 
						|
tabpanel.prototype.togglePanel = function($tab) {
 | 
						|
 | 
						|
  $panel = this.$panel.find('#' + $tab.attr('aria-controls'));
 | 
						|
 | 
						|
  if ($panel.attr('aria-hidden') == 'true') {
 | 
						|
    $panel.slideDown(100);
 | 
						|
    $panel.attr('aria-hidden', 'false');
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    $panel.slideUp(100);
 | 
						|
    $panel.attr('aria-hidden', 'true');
 | 
						|
  }
 | 
						|
} // end togglePanel()
 | 
						|
 | 
						|
//
 | 
						|
// Function bindHandlers() is a member function to bind event handlers for the tabs
 | 
						|
//
 | 
						|
// @return N/A
 | 
						|
//
 | 
						|
tabpanel.prototype.bindHandlers = function() {
 | 
						|
 | 
						|
  var thisObj = this; // Store the this pointer for reference
 | 
						|
 | 
						|
  //////////////////////////////
 | 
						|
  // Bind handlers for the tabs / accordian headers
 | 
						|
 | 
						|
  // bind a tab keydown handler
 | 
						|
  this.$tabs.keydown(function(e) {
 | 
						|
    return thisObj.handleTabKeyDown($(this), e);
 | 
						|
  });
 | 
						|
 | 
						|
  // bind a tab keypress handler
 | 
						|
  this.$tabs.keypress(function(e) {
 | 
						|
    return thisObj.handleTabKeyPress($(this), e);
 | 
						|
  });
 | 
						|
 | 
						|
  // bind a tab click handler
 | 
						|
  this.$tabs.click(function(e) {
 | 
						|
    return thisObj.handleTabClick($(this), e);
 | 
						|
  });
 | 
						|
 | 
						|
  // bind a tab focus handler
 | 
						|
  this.$tabs.focus(function(e) {
 | 
						|
    return thisObj.handleTabFocus($(this), e);
 | 
						|
  });
 | 
						|
 | 
						|
  // bind a tab blur handler
 | 
						|
  this.$tabs.blur(function(e) {
 | 
						|
    return thisObj.handleTabBlur($(this), e);
 | 
						|
  });
 | 
						|
 | 
						|
  /////////////////////////////
 | 
						|
  // Bind handlers for the panels
 | 
						|
  
 | 
						|
  // bind a keydown handlers for the panel focusable elements
 | 
						|
  this.$panels.keydown(function(e) {
 | 
						|
    return thisObj.handlePanelKeyDown($(this), e);
 | 
						|
  });
 | 
						|
 | 
						|
  // bind a keypress handler for the panel
 | 
						|
  this.$panels.keypress(function(e) {
 | 
						|
    return thisObj.handlePanelKeyPress($(this), e);
 | 
						|
  });
 | 
						|
 | 
						|
} // end bindHandlers()
 | 
						|
 | 
						|
//
 | 
						|
// Function handleTabKeyDown() is a member function to process keydown events for a tab
 | 
						|
//
 | 
						|
// @param ($tab obj) $tab is the jquery object of the tab being processed
 | 
						|
//
 | 
						|
// @paran (e obj) e is the associated event object
 | 
						|
//
 | 
						|
// @return (boolean) Returns true if propagating; false if consuming event
 | 
						|
//
 | 
						|
tabpanel.prototype.handleTabKeyDown = function($tab, e) {
 | 
						|
 | 
						|
  if (e.altKey) {
 | 
						|
    // do nothing
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (e.keyCode) {
 | 
						|
    case this.keys.enter:
 | 
						|
    case this.keys.space: {
 | 
						|
 | 
						|
      // Only process if this is an accordian widget
 | 
						|
      if (this.accordian == true) {
 | 
						|
        // display or collapse the panel
 | 
						|
        this.togglePanel($tab);
 | 
						|
 | 
						|
        e.stopPropagation();
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    case this.keys.left:
 | 
						|
    case this.keys.up: {
 | 
						|
 | 
						|
      var thisObj = this;
 | 
						|
      var $prevTab; // holds jQuery object of tab from previous pass
 | 
						|
      var $newTab; // the new tab to switch to
 | 
						|
 | 
						|
      if (e.ctrlKey) {
 | 
						|
        // Ctrl+arrow moves focus from panel content to the open
 | 
						|
        // tab/accordian header.
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        var curNdx = this.$tabs.index($tab);
 | 
						|
 | 
						|
        if (curNdx == 0) {
 | 
						|
          // tab is the first one:
 | 
						|
          // set newTab to last tab
 | 
						|
          $newTab = this.$tabs.last();
 | 
						|
        }
 | 
						|
        else {
 | 
						|
          // set newTab to previous
 | 
						|
          $newTab = this.$tabs.eq(curNdx - 1);
 | 
						|
        }
 | 
						|
 | 
						|
        // switch to the new tab
 | 
						|
        this.switchTabs($tab, $newTab);
 | 
						|
      }
 | 
						|
 | 
						|
      e.stopPropagation();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    case this.keys.right:
 | 
						|
    case this.keys.down: {
 | 
						|
 | 
						|
      var thisObj = this;
 | 
						|
      var foundTab = false; // set to true when current tab found in array
 | 
						|
      var $newTab; // the new tab to switch to
 | 
						|
 | 
						|
      var curNdx = this.$tabs.index($tab);
 | 
						|
 | 
						|
      if (curNdx == this.$tabs.last().index()) {
 | 
						|
        // tab is the last one:
 | 
						|
        // set newTab to first tab
 | 
						|
        $newTab = this.$tabs.first();
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        // set newTab to next tab
 | 
						|
        $newTab = this.$tabs.eq(curNdx + 1);
 | 
						|
      }
 | 
						|
 | 
						|
      // switch to the new tab
 | 
						|
      this.switchTabs($tab, $newTab);
 | 
						|
 | 
						|
      e.stopPropagation();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    case this.keys.home: {
 | 
						|
 | 
						|
      // switch to the first tab
 | 
						|
      this.switchTabs($tab, this.$tabs.first());
 | 
						|
 | 
						|
      e.stopPropagation();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    case this.keys.end: {
 | 
						|
 | 
						|
      // switch to the last tab
 | 
						|
      this.switchTabs($tab, this.$tabs.last());
 | 
						|
 | 
						|
      e.stopPropagation();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
} // end handleTabKeyDown()
 | 
						|
 | 
						|
//
 | 
						|
// Function handleTabKeyPress() is a member function to process keypress events for a tab.
 | 
						|
//
 | 
						|
//
 | 
						|
// @param ($tab obj) $tab is the jquery object of the tab being processed
 | 
						|
//
 | 
						|
// @paran (e obj) e is the associated event object
 | 
						|
//
 | 
						|
// @return (boolean) Returns true if propagating; false if consuming event
 | 
						|
//
 | 
						|
tabpanel.prototype.handleTabKeyPress = function($tab, e) {
 | 
						|
 | 
						|
  if (e.altKey) {
 | 
						|
    // do nothing
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (e.keyCode) {
 | 
						|
    case this.keys.enter:
 | 
						|
    case this.keys.space:
 | 
						|
    case this.keys.left:
 | 
						|
    case this.keys.up:
 | 
						|
    case this.keys.right:
 | 
						|
    case this.keys.down:
 | 
						|
    case this.keys.home:
 | 
						|
    case this.keys.end: {
 | 
						|
      e.stopPropagation();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    case this.keys.pageup:
 | 
						|
    case this.keys.pagedown: {
 | 
						|
 | 
						|
      // The tab keypress handler must consume pageup and pagedown
 | 
						|
      // keypresses to prevent Firefox from switching tabs
 | 
						|
      // on ctrl+pageup and ctrl+pagedown
 | 
						|
 | 
						|
      if (!e.ctrlKey) {
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
 | 
						|
      e.stopPropagation();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
 | 
						|
} // end handleTabKeyPress()
 | 
						|
 | 
						|
//
 | 
						|
// Function handleTabClick() is a member function to process click events for tabs
 | 
						|
//
 | 
						|
// @param ($tab object) $tab is the jQuery object of the tab being processed
 | 
						|
//
 | 
						|
// @paran (e object) e is the associated event object
 | 
						|
//
 | 
						|
// @return (boolean) returns true
 | 
						|
//
 | 
						|
tabpanel.prototype.handleTabClick = function($tab, e) {
 | 
						|
 | 
						|
  // Remove the highlighting from all tabs
 | 
						|
  this.$tabs.removeClass('selected');
 | 
						|
 | 
						|
  // remove all tabs from the tab order
 | 
						|
  this.$tabs.attr('tabindex', '-1');
 | 
						|
 | 
						|
  // hide all tab panels
 | 
						|
  this.$panels.hide();
 | 
						|
  
 | 
						|
  // Highlight the clicked tab
 | 
						|
  $tab.addClass('selected');
 | 
						|
 | 
						|
  // show the clicked tab panel
 | 
						|
  this.$panel.find('#' + $tab.attr('aria-controls')).show();
 | 
						|
 | 
						|
  // make clicked tab navigable
 | 
						|
  $tab.attr('tabindex', '0');
 | 
						|
 | 
						|
  // give the tab focus
 | 
						|
  $tab.focus();
 | 
						|
 | 
						|
  return true;
 | 
						|
 | 
						|
} // end handleTabClick()
 | 
						|
 | 
						|
//
 | 
						|
// Function handleTabFocus() is a member function to process focus events for tabs
 | 
						|
//
 | 
						|
// @param ($tab object) $tab is the jQuery object of the tab being processed
 | 
						|
//
 | 
						|
// @paran (e object) e is the associated event object
 | 
						|
//
 | 
						|
// @return (boolean) returns true
 | 
						|
//
 | 
						|
tabpanel.prototype.handleTabFocus = function($tab, e) {
 | 
						|
 | 
						|
  // Add the focus class to the tab
 | 
						|
  $tab.addClass('focus');
 | 
						|
 | 
						|
  return true;
 | 
						|
 | 
						|
} // end handleTabFocus()
 | 
						|
 | 
						|
//
 | 
						|
// Function handleTabBlur() is a member function to process blur events for tabs
 | 
						|
//
 | 
						|
// @param ($tab object) $tab is the jQuery object of the tab being processed
 | 
						|
//
 | 
						|
// @paran (e object) e is the associated event object
 | 
						|
//
 | 
						|
// @return (boolean) returns true
 | 
						|
//
 | 
						|
tabpanel.prototype.handleTabBlur = function($tab, e) {
 | 
						|
 | 
						|
  // Remove the focus class to the tab
 | 
						|
  $tab.removeClass('focus');
 | 
						|
 | 
						|
  return true;
 | 
						|
 | 
						|
} // end handleTabBlur()
 | 
						|
 | 
						|
 | 
						|
/////////////////////////////////////////////////////////
 | 
						|
// Panel Event handlers
 | 
						|
//
 | 
						|
 | 
						|
//
 | 
						|
// Function handlePanelKeyDown() is a member function to process keydown events for a panel
 | 
						|
//
 | 
						|
// @param ($elem obj) $elem is the jquery object of the element being processed
 | 
						|
//
 | 
						|
// @paran (e obj) e is the associated event object
 | 
						|
//
 | 
						|
// @return (boolean) Returns true if propagating; false if consuming event
 | 
						|
//
 | 
						|
tabpanel.prototype.handlePanelKeyDown = function($elem, e) {
 | 
						|
 | 
						|
  if (e.altKey) {
 | 
						|
    // do nothing
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (e.keyCode) {
 | 
						|
    case this.keys.esc: {
 | 
						|
      e.stopPropagation();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    case this.keys.left:
 | 
						|
    case this.keys.up: {
 | 
						|
 | 
						|
      if (!e.ctrlKey) {
 | 
						|
        // do not process
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
  
 | 
						|
      // get the jQuery object of the tab
 | 
						|
      var $tab = $('#' + $elem.attr('aria-labeledby'));
 | 
						|
 | 
						|
      // Move focus to the tab
 | 
						|
      $tab.focus();
 | 
						|
 | 
						|
      e.stopPropagation();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    case this.keys.pageup: {
 | 
						|
 | 
						|
      var $newTab;
 | 
						|
 | 
						|
      if (!e.ctrlKey) {
 | 
						|
        // do not process
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
 | 
						|
      // get the jQuery object of the tab
 | 
						|
      var $tab = this.$tabs.filter('.selected');
 | 
						|
 | 
						|
      // get the index of the tab in the tab list
 | 
						|
      var curNdx = this.$tabs.index($tab);
 | 
						|
 | 
						|
      if (curNdx == 0) {
 | 
						|
        // this is the first tab, set focus on the last one
 | 
						|
        $newTab = this.$tabs.last();
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        // set focus on the previous tab
 | 
						|
        $newTab = this.$tabs.eq(curNdx - 1);
 | 
						|
      }
 | 
						|
 | 
						|
      // switch to the new tab
 | 
						|
      this.switchTabs($tab, $newTab);
 | 
						|
 | 
						|
      e.stopPropagation();
 | 
						|
      e.preventDefault();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    case this.keys.pagedown: {
 | 
						|
 | 
						|
      var $newTab;
 | 
						|
 | 
						|
      if (!e.ctrlKey) {
 | 
						|
        // do not process
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
 | 
						|
      // get the jQuery object of the tab
 | 
						|
      var $tab = $('#' + $elem.attr('aria-labeledby'));
 | 
						|
 | 
						|
      // get the index of the tab in the tab list
 | 
						|
      var curNdx = this.$tabs.index($tab);
 | 
						|
 | 
						|
      if (curNdx == this.$tabs.last().index()) {
 | 
						|
        // this is the last tab, set focus on the first one
 | 
						|
        $newTab = this.$tabs.first();
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        // set focus on the next tab
 | 
						|
        $newTab = this.$tabs.eq(curNdx + 1);
 | 
						|
      }
 | 
						|
 | 
						|
      // switch to the new tab
 | 
						|
      this.switchTabs($tab, $newTab);
 | 
						|
 | 
						|
      e.stopPropagation();
 | 
						|
      e.preventDefault();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
 | 
						|
} // end handlePanelKeyDown()
 | 
						|
 | 
						|
//
 | 
						|
// Function handlePanelKeyPress() is a member function to process keypress events for a panel
 | 
						|
//
 | 
						|
// @param ($elem obj) $elem is the jquery object of the element being processed
 | 
						|
//
 | 
						|
// @paran (e obj) e is the associated event object
 | 
						|
//
 | 
						|
// @return (boolean) Returns true if propagating; false if consuming event
 | 
						|
//
 | 
						|
tabpanel.prototype.handlePanelKeyPress = function($elem, e) {
 | 
						|
 | 
						|
  if (e.altKey) {
 | 
						|
    // do nothing
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (e.ctrlKey && (e.keyCode == this.keys.pageup || e.keyCode == this.keys.pagedown)) {
 | 
						|
      e.stopPropagation();
 | 
						|
      e.preventDefault();
 | 
						|
      return false;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (e.keyCode) {
 | 
						|
    case this.keys.esc: {
 | 
						|
      e.stopPropagation();
 | 
						|
      e.preventDefault();
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
 | 
						|
} // end handlePanelKeyPress()
 | 
						|
 | 
						|
// focusable is a small jQuery extension to add a :focusable selector. It is used to
 | 
						|
// get a list of all focusable elements in a panel. Credit to ajpiano on the jQuery forums.
 | 
						|
//
 | 
						|
$.extend($.expr[':'], {
 | 
						|
  focusable: function(element) {
 | 
						|
    var nodeName = element.nodeName.toLowerCase();
 | 
						|
    var tabIndex = $(element).attr('tabindex');
 | 
						|
 | 
						|
    // the element and all of its ancestors must be visible
 | 
						|
    if (($(element)[nodeName == 'area' ? 'parents' : 'closest'](':hidden').length) == true) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    // If tabindex is defined, its value must be greater than 0
 | 
						|
    if (!isNaN(tabIndex) && tabIndex < 0) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    // if the element is a standard form control, it must not be disabled
 | 
						|
    if (/input|select|textarea|button|object/.test(nodeName) == true) {
 | 
						|
 | 
						|
             return !element.disabled;
 | 
						|
    }
 | 
						|
 | 
						|
    // if the element is a link, href must be defined
 | 
						|
    if ((nodeName == 'a' ||  nodeName == 'area') == true) {
 | 
						|
 | 
						|
      return (element.href.length > 0);
 | 
						|
    }
 | 
						|
             
 | 
						|
    // this is some other page element that is not normally focusable.
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
});
 | 
						|
</script>
 | 
						|
</head>
 | 
						|
<body>
 | 
						|
<div role="application">
 | 
						|
 | 
						|
<h2>Happy Time Pizza On-line Ordering System</h2>
 | 
						|
 | 
						|
<form>
 | 
						|
<div id="tabpanel1" class="tabpanel">
 | 
						|
 | 
						|
  <ul class="tablist" role="tablist">
 | 
						|
    <li id="tab1" class="tab selected" aria-controls="panel1" role="tab">Crust</li>
 | 
						|
    <li id="tab2" class="tab" aria-controls="panel2" role="tab">Veggies</li>
 | 
						|
    <li id="tab3" class="tab" aria-controls="panel3" role="tab">Carnivore</li>
 | 
						|
    <li id="tab4" class="tab" aria-controls="panel4" role="tab">Delivery</li>
 | 
						|
  </ul>
 | 
						|
 | 
						|
  <div id="panel1" class="panel" aria-labeledby="tab1" role="tabpanel">
 | 
						|
    <h3>Select Crust</h3>
 | 
						|
     
 | 
						|
          <ul class="controlList">
 | 
						|
            <li><label><input type="radio" name="crust" value="crust1" />Deep Dish</label></li>
 | 
						|
            <li><label><input type="radio" name="crust" value="crust2" checked="checked" />Thick and cheesy</label></li>
 | 
						|
            <li><label><input type="radio" name="crust" value="crust3" />Thick and spicy</label></li>
 | 
						|
            <li><label><input type="radio" name="crust" value="crust4" />Thin</label></li>
 | 
						|
         </ul>
 | 
						|
  </div>
 | 
						|
 | 
						|
  <div id="panel2" class="panel" aria-labeledby="tab2" role="tabpanel">
 | 
						|
    <h3>Select Vegetables</h3>  
 | 
						|
     
 | 
						|
         <ul class="controlList">
 | 
						|
            <li><label><input type="checkbox" name="veg" value="black olives" />Black Olives</label></li>
 | 
						|
            <li><label><input type="checkbox" name="veg" value="green olives" />Green Olives</label></li>
 | 
						|
            <li><label><input type="checkbox" name="veg" value="green peppers" />Green Peppers</label></li>
 | 
						|
            <li><label><input type="checkbox" name="veg" value="mushrooms" />Mushrooms</label></li>
 | 
						|
            <li><label><input type="checkbox" name="veg" value="onions" />Onions</label></li>
 | 
						|
            <li><label><input type="checkbox" name="veg" value="pineapple" />Pineapple</label></li>
 | 
						|
         </ul>
 | 
						|
  </div>
 | 
						|
 | 
						|
  <div id="panel3" class="panel" aria-labeledby="tab3" role="tabpanel">
 | 
						|
    <h3>Select Carnivore Options</h3>
 | 
						|
     
 | 
						|
          <ul class="controlList">
 | 
						|
            <li><label><input type="checkbox" name="meat" value="pepperoni" />Pepperoni</label></li>
 | 
						|
            <li><label><input type="checkbox" name="meat" value="sausage" />Italian Sausage</label></li>
 | 
						|
            <li><label><input type="checkbox" name="meat" value="ham" />Ham</label></li>
 | 
						|
            <li><label><input type="checkbox" name="meat" value="hamburger" />Hamburger</label></li>
 | 
						|
          </ul>
 | 
						|
  </div>
 | 
						|
 | 
						|
  <div id="panel4" class="panel" aria-labeledby="tab4" role="tabpanel">
 | 
						|
     <h3>Select Delivery Method</h3>
 | 
						|
     
 | 
						|
    <ul class="controlList">
 | 
						|
      <li><label><input type="radio" name="delivery" value="delivery1" checked="checked" />Delivery</label></li>
 | 
						|
      <li><label><input type="radio" name="delivery" value="delivery2" />Eat in</label></li>
 | 
						|
      <li><label><input type="radio" name="delivery" value="delivery3" />Carry out</label></li>
 | 
						|
      <li><label><input type="radio" name="delivery" value="delivery4" />Overnight mail</label></li>
 | 
						|
    </ul>
 | 
						|
  </div>
 | 
						|
</div>
 | 
						|
</form>
 | 
						|
</div>
 | 
						|
</body>
 | 
						|
</html>
 |