inline source: Menubar Example 1


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"
      xmlns:wairole="http://www.w3.org/2005/01/wai-rdf/GUIRoleTaxonomy#"
      xmlns:aaa="http://www.w3.org/2005/07/aaa">

<head>
  <title>inline: Menubar Example 1</title>


<style type="text/css">
/* CSS Document */

dl.menubar {
  margin: 0px;
  padding: .25em;;
  border: 1px solid black;
  background-color: #CCCCCC;
  width: 20em;
}

dl.menubar > dt {
  padding: .25em;
  display: inline;
}

dl.menubar > dt.selected {
  background: black;
  color: white;
}


dl.menubar > dd
{
  margin: 0;
  padding: 0;
  display: inline;
}

dl.menubar dd dl {
  display: none;
}

dl.menubar dd dl.open {
  position: absolute;
  display: block;
  margin: 0px;
  padding: 0px;
  border: 1px solid black;
  background-color: #CCCCCC;
}

dl.menubar dd dl > dt {
  padding-top: 2px;
  padding-bottom: 2px;
  padding-left: 1em;
  padding-right: 1em;
}


dl.menubar dd dl > dt[aria-checked="true"] {
  background-image: url(../images/checked.gif);
  background-position: -1em center;
  background-repeat:no-repeat;
}

dl.menubar dd dl > dt.selected {
  background: black;
  color: white;
}

dl.menubar dd dl > dt[role="separator"] {
  padding-top: 2px;
  border-bottom: thin solid black;
  margin-bottom: 2px;
}

</style>

<script type="text/javascript">

//globals.js

/**
*
* 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 );

}
//widgets_inline.js

// JavaScript Document


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 ARIA_STATE = "aria-";

/**
* Widgets Object is used to initialize a set of controls
* and provide a conveinence fuction to cancel event propagration
* @construtor
*/

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();
}

//
// convience function for getting the node based on id

function _$( id ) {
  return document.getElementById( id );  
}


//
// 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 ) {
    event.stopPropagation();
    event.preventDefault();
    return false;
  }

  WebBrowser.prototype.target = function( event ) {
  return event.target;
  }
  
  WebBrowser.prototype.attrName = function( event ) {
  return event.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.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;
     };

  }

}

widgets_flag = true;
var widgets = new Widgets();
var browser = new WebBrowser();

function initApp() {
  widgets.init();
}

//menubar1_inline.js

// JavaScript Document

var MENUITEM_NONE = 0;
var MENUITEM_ITEM = 1;
var MENUITEM_RADIO = 2;
var MENUITEM_CHECKBOX = 3;
var MENUITEM_SEPARATOR = 4;


/**
* NODE_LAST_FOCUS keeps track of which form element in the tab panel had last focus
*/

var NODE_LAST_FOCUS = null;

/**
*
* The TabPanel object is used to maintain information about a Tab Panel widget
* including the collection of tab objects
*
* @contructor
*/


function MenuBar( id ) {

  this.id = id;
  this.current_menubar_node  = null;
  this.current_menu_node = null;
  this.current_menuitem_node = null;
  this.current_menuitems;
  this.pulldown_flag = false;
  
}

/**
* init is a subclass of MenuBar and is used to initialize the event handlers and
* tabs in a menu bar.
*
* @member MenuBar
* @return nothing
*/

MenuBar.prototype.init = function() {

  this.node = document.getElementById(this.id);

  var obj = this;

  browser.addEvent(this.node, "focus",     function(event) {handleMenuBarFocusEvent(event,     obj); }, false);
  browser.addEvent(this.node, "click",     function(event) {handleMenuBarClickEvent(event,     obj); }, false);
  browser.addEvent(this.node, "mouseover", function(event) {handleMenuBarMouseOverEvent(event, obj); }, false);
  browser.addEvent(this.node, "keydown",   function(event) {handleMenuBarKeyDownEvent(event,   obj); }, false);

}

/**
* setMenuBarFocus
* Give the menu focus
*
* @param ( menubar ) MenuBar object
* @return none
*/

function setMenuBarFocus( menubar ) {
  menubar.node.focus();
}

/**
* getFirstMenuItem
* This function gets the next menu item in the current menu
*
* @param ( menubar ) MenuBar object
* @return node of new menu item
*/

function getFirstMenuItem( menubar ) {

  var done = false;
  var first_menu_item = menubar.node.firstChild;

  do {
    if( ( first_menu_item.nodeType == Node.ELEMENT_NODE ) &&
        ( first_menu_item.getAttribute("role") == "menuitem" ) ) {
        done = true;      
    } else {
        first_menu_item = nextSiblingElement( first_menu_item );
  }
  
  } while( first_menu_item && !done);

   return first_menu_item;

}

/**
* getLastMenuItem
* This function gets the next menu item in the current menu
*
* @param ( menubar ) MenuBar object
* @return node of new menu item
*/

function getLastMenuItem( menubar ) {

  var done = false;
  var last_menu_item = menubar.node.lastChild;

  do {
    if( ( last_menu_item.nodeType == Node.ELEMENT_NODE ) &&
        ( last_menu_item.getAttribute("role") == "menuitem" ) ) {
        done = true;      
    } else {
        last_menu_item = previousSiblingElement( last_menu_item );
  }
  
  } while( last_menu_item && !done);

  return last_menu_item;

}



/**
* getNextMenuItem
* This function gets the next menu item in the current menubar
*
* @param ( menubar ) MenuBar object
* @return node of new menu item
*/

function getNextMenuItem( menubar ) {

  var done = false;
  var next_menu_item;  

  if( menubar.current_menubar_node == null )
    next_menu_item = menubar.node.firstChild;
  else
    next_menu_item = menubar.current_menubar_node.nextSibling;

  do {
    if( ( next_menu_item.nodeType == Node.ELEMENT_NODE ) &&
        ( next_menu_item.getAttribute("role") == "menuitem" ) ) {
        done = true;      
    } else {
        next_menu_item = nextSiblingElement( next_menu_item );
  }
  
  } while( next_menu_item && !done);

  if( next_menu_item == null )
    next_menu_item = getFirstMenuItem( menubar );

  return next_menu_item;

}


/**
* getPreviousMenuItem
* This function gets the previous menu item in the current menu
*
* @param ( menubar ) MenuBar object
*
* @return node of new menu item
*/

function getPreviousMenuItem( menubar ) {

  var done = false;
  var previous_menu_item;  

  if( menubar.current_menubar_node == null )
    previous_menu_item = menubar.node.lastChild;
  else
    previous_menu_item = menubar.current_menubar_node.previousSibling;

  do {
    if( ( previous_menu_item.nodeType == Node.ELEMENT_NODE ) &&
        ( previous_menu_item.getAttribute("role") == "menuitem" ) ) {
        done = true;      
    } else {
        previous_menu_item = previousSiblingElement( previous_menu_item );
  }
  
  } while( previous_menu_item && !done);

  if( previous_menu_item == null )
    previous_menu_item = getLastMenuItem( menubar );

  return previous_menu_item;

}

/**
* openPreviousMenuItem
*
* @param ( menubar ) MenuBar object
* @param ( menuitem ) MenuItem object
*
* @return node of new menu item
*/

function openPullDownMenu( menubar, menuitem ) {

  var new_menu = nextSiblingElement(menuitem);

  while ( new_menu && new_menu.getAttribute("role") != "menu" ) {
     new_menu = firstChildElement(new_menu);
  }
  
  if( new_menu ) {
    
    new_menu.className = "open";
  
  browser.setNodePosition( new_menu, browser.calculateOffsetLeft( menuitem), (browser.calculateOffsetTop( menuitem) + menuitem.offsetHeight ));

  browser.addEvent(new_menu, "mouseover", function(event) {handleMenuMouseOverEvent(event, menubar); }, false);

  }

  menubar.current_menu_node = new_menu;
  
  menubar.current_menuitems = new Array();
  
  var item_node = firstChildElement( menubar.current_menu_node );  

  do {
    
    if( item_node.nodeType == Node.ELEMENT_NODE ) {
    
    var mi_node     = null;
    var mi_type     = MENUITEM_NONE;
    var mi_checked  = item_node.getAttribute("aria-checked")
    var mi_disabled = item_node.getAttribute("aria-disabled")
    var mi_haspopup = item_node.getAttribute("aria-haspopup");    
    
        if( item_node.getAttribute("role") == "menuitem" ) {
       mi_node = item_node;
       mi_type = MENUITEM_ITEM;
    } // endif
    
        if( item_node.getAttribute("role") == "menuitemradio" ) {
       mi_node = item_node;
       mi_type = MENUITEM_RADIO;
    } // endif
      
        if( item_node.getAttribute("role") == "menuitemcheckbox" ) {
       mi_node = item_node;
       mi_type = MENUITEM_CHECKBOX;
    } // endif

        if( item_node.getAttribute("role") == "separator" ) {
       mi_node = item_node;
       mi_type = MENUITEM_SEPARATOR;
    } // endif

        if( mi_node ) {
      var menuitem = new MenuItem( mi_node.id, mi_type, mi_checked, mi_disabled, mi_haspopup );
      menubar.current_menuitems[menubar.current_menuitems.length] = menuitem;
    }
    
  }  // endif

    item_node = item_node.nextSibling;

  } while( item_node );
  
  return new_menu;

}

/**
* closePullDownMenuItem
*
* @param ( menubar ) MenuBar object
* @param ( menuitem ) MenuItem object
*
* @return node of new menu item
*/

function closePullDownMenu( menubar, menuitem ) {

  var old_menu = nextSiblingElement(menuitem);
  
  while ( old_menu && old_menu.getAttribute("role") != "menu" ) {
     old_menu = firstChildElement(old_menu);
  }

  if( old_menu ) {
    old_menu.className = "";
  
  browser.removeEvent(old_menu, "mouseover", function(event) {handleMenuMouseOverEvent(event, menubar); }, false);

  }
  
  return old_menu;

}



/**
* menuBarUpdateMenuBar  
* Supports moving to the next menu item
*
* @param ( menubar ) MenuBar object
* @return nothing
*/

function menuBarUpdateMenuBar( menubar, new_node ) {

  var last_node  = menubar.current_menubar_node;
  
  // Close old menu item if open
  if( last_node != new_node ) {
  
  // change styling on old menu item
  if( last_node != null )  {
    last_node.className = "";
    
    // Check to see if there is a pull down menu
    
    if( menubar.pulldown_flag &&
      last_node.getAttribute("aria-haspopup") == "true" ) {
      closePullDownMenu( menubar, last_node );
    }

    }

    // Update styling
  if( new_node != null ) {
    new_node.className = "selected";
    menubar.current_menubar_node = new_node;
    
    // Check to see if there is a pull down menu
    
    if( menubar.pulldown_flag &&
      new_node.getAttribute("aria-haspopup") == "true" ) {
      menubar.current_menu_node = openPullDownMenu( menubar, new_node );      
    }    
    
  }  // endif
  
  }  // endif

}

/**
* menuBarUpdateMenu  
* Supports updating the styling of the current menu that is open
*
* @param ( menubar ) MenuBar object
* @return nothing
*/

function menuBarUpdateMenu( menubar, new_menuitem_node ) {

  // see if any other nodes ae currently selected and restore their default styling
  if( menubar.current_menuitem_node &&
    ( menubar.current_menuitem_node.getAttribute("role") != "separator" ) )
    if( menubar.current_menuitem_node.getAttribute("aria-checked") == "true" )
     menubar.current_menuitem_node.className = "checked ";
    else
     menubar.current_menuitem_node.className = "";

  menubar.current_menuitem_node = new_menuitem_node;

  // Set the new node to a selected style
  if( menubar.current_menuitem_node &&
    menubar.current_menuitem_node.getAttribute("role") != "separator" )  
    if( menubar.current_menuitem_node.getAttribute("aria-checked") == "true" )
    menubar.current_menuitem_node.className = "checked selected";
    else
    menubar.current_menuitem_node.className = "selected";
    
  return menubar.current_menuitem_node;  

}



/**
* menuBarKeyLeft  
* Supports moving to the next menu item
*
* @param ( menubar ) MenuBar object
* @return nothing
*/

function menuBarKeyLeftArrow( menubar ) {

  var new_node  = getPreviousMenuItem( menubar );

  menuBarUpdateMenuBar( menubar, new_node );
  
  if( new_node.getAttribute("aria-haspopup") == "true") {
  menuBarKeyDownArrow( menubar );  
  } else {
  new_node.focus();  
  } // endif
  
}

/**
* menuBarKeyRight  
* Supports moving to the previous menu item
*
* @param ( menubar) MenuBar object
* @return nothing
*/

function menuBarKeyRightArrow( menubar ) {

  var new_node = getNextMenuItem( menubar );
  
  menuBarUpdateMenuBar( menubar, new_node );
  
  if( new_node.getAttribute("aria-haspopup") == "true") {
  menuBarKeyDownArrow( menubar );  
  } else {
  new_node.focus();  
  } // endif
  
}

/**
* MenuItem constructor for storing data on a menuitem node
*
* @param ( id ) id of node of menuitem
* @param ( type ) integer indicting the type of menuitem
* @param ( checked ) boolean flag indicating if the menuitem is checked
* @param ( disabled ) boolean flag indicating if the menuitem is disabled
* @param ( haspopup ) boolean flag indicating if the menuitem has a popup menu
* @return nothing
*/

function MenuItem( id, type, checked, disabled, haspopup ) {
        
  this.id       = id;
  this.type     = type;
  this.checked  = checked;
  this.disabled = disabled;
  this.haspopup = haspopup;          
}


/**
* getMenuItems
* Get an array of the current menu items
*
* @param ( menu) menu object
* @return nothing
*/

function getMenuItems( menu_node ) {


  
  return menuitems;

}

/**
* getMenuItemItemIndex
*
*
* @param ( menu ) menu object
* @return -1      If menuitem is not in array
*          >= 0   The index position in the array
*/

function getMenuItemIndex( menubar ) {

  var index = -1;
  var i = 0;
  var done = false;
  
  // Test to see if current menu item selected
  if( menubar.current_menuitem_node ) {
    
    while ( ( i < menubar.current_menuitems.length ) && !done ) {
    
    if( menubar.current_menuitems[i].id == menubar.current_menuitem_node.id ) {
    done = true;
    index = i;
    }
    
    i++;
    }  // end while
  
  } // endif

  return index;

}

/**
* menuBarKeyUp  
* Supports moving to the previous menu item
*
* @param ( menubar) MenuBar object
* @return nothing
*/

function menuBarKeyUpArrow( menubar ) {

  // see if menu has a popup
  if( !menubar.current_menu_node &&
    menubar.current_menubar_node.getAttribute("aria-haspopup") == "true" ) {
      
    menubar.current_menu_node = openPullDownMenu( menubar, menubar.current_menubar_node );
    menubar.pulldown_flag = true;
      
  }  // endif

  if( menubar.current_menu_node ) {
    
    var index = getMenuItemIndex( menubar );
    
    index--;
    
    while( (index >= 0) && (menubar.current_menuitems[index].type == MENUITEM_SEPARATOR ) ){
      index--;
    }
    

      if( (index < 0 ) || ( index >= menubar.current_menuitems.length ) )
      index = menubar.current_menuitems.length - 1;

      var new_node = menuBarUpdateMenu(menubar, document.getElementById(menubar.current_menuitems[index].id) );
    
    new_node.focus();

    
  } // endif


}

/**
* menuBarKeyUp  
* Supports moving to the previous menu item
*
* @param ( menubar) MenuBar object
* @return nothing
*/

function menuBarKeyDownArrow( menubar ) {

  // see if menu has a popup
  if( !menubar.current_menu_node &&
    menubar.current_menubar_node.getAttribute("aria-haspopup") == "true" ) {
      
    menubar.current_menu_node = openPullDownMenu( menubar, menubar.current_menubar_node );
    menubar.pulldown_flag = true;
      
  }  // endif

  if( menubar.current_menu_node ) {
    
    var index = getMenuItemIndex( menubar );
    
    index++;
    
    while( (index < menubar.current_menuitems.length) && (menubar.current_menuitems[index].type == MENUITEM_SEPARATOR ) ){
      index++;
    }
    
      if( (index < 0 ) || ( index >= menubar.current_menuitems.length ) )
      index = 0;

      var new_node = menuBarUpdateMenu(menubar, document.getElementById(menubar.current_menuitems[index].id) );

      new_node.focus();
        
  } // endif

}

/**
* menuBarOnClick  
* Supports moving to the previous menu item
*
* @param ( menubar) MenuBar object
* @return nothing
*/

function menuBarOnClick( menubar ) {

  if( menubar.current_menuitem_node ) {
  
  browser.simulateOnClickEvent( menubar.current_menuitem_node );
        
  } // endif

}

/**
* menuBarClosePulldown
* Close pull down menu if it is open
*
* @param ( menubar) MenuBar object
* @return nothing
*/

function menuBarClosePullDown( menubar ) {

  if( menubar.current_menubar_node ) {

  // Check to see if there is a pull down menu
    
  if( menubar.current_menubar_node.getAttribute("aria-haspopup") == "true" ) {
      closePullDownMenu( menubar, menubar.current_menubar_node );
  }  // endif
        
  menubar.current_menubar_node.focus();
  
  } // endif

}

/**
* menuBarUpdateRadioMenuItems
*
* @param ( menubar) MenuBar object
* @return nothing
*/

function menuBarUpdateRadioMenuItems( menubar ) {

  var node;
  var i = getMenuItemIndex( menubar );
  var j;
  
  //
  // uncheck any other radiomenuitems before current menuitem
  
  j = i-1;
  while( (j >= 0) &&
    ( menubar.current_menuitems[j].type == MENUITEM_RADIO) ) {
    
        node = document.getElementById( menubar.current_menuitems[j].id );

        node.setAttribute("aria-checked", "false" );       
        node.className = "";
      
      j--;

   } // endwhile

    menubar.current_menuitem_node.setAttribute("aria-checked", "true" );       
    menubar.current_menuitem_node.className = "checked";       

  //
  // uncheck any other radiomenuitems before current menuitem
  j = i + 1;
  
  while( (j < menubar.current_menuitems.length) &&
      (menubar.current_menuitems[j].type == MENUITEM_RADIO) ) {

            node = document.getElementById( menubar.current_menuitems[j].id );

            node.setAttribute("aria-checked", "false" );       
            node.className = "";
      
            j++;
      
  } // endwhile

}

/**
* menuBarUpdateCheckboxMenuItems
*
* @param ( menubar) MenuBar object
* @return nothing
*/

function menuBarUpdateCheckboxMenuItems( menubar, checked ) {

  if( checked ) {
    menubar.current_menuitem_node.setAttribute("aria-checked", "true" );       
    menubar.current_menuitem_node.className = "checked";       
  } else {
    menubar.current_menuitem_node.setAttribute("aria-checked", "false" );       
    menubar.current_menuitem_node.className = "";           
  } // endif

}


/**
* menuBarClose
*
* @param ( menubar) MenuBar object
* @return nothing
*/

function menuBarClose( menubar ) {

  menuBarClosePullDown( menubar );

  // reset styling of current menubar item
  if( menubar.current_menubar_node )
     menubar.current_menubar_node.className = "";

  menubar.current_menubar_node = null;
  menubar.current_menu_node = null;
  menubar.current_menubar_node = null;
  menubar.pulldown_flag = false;

}

/**
* handleMenuBarKeyPressEvent
* handleMenuBatKetDownEvent Keyboard commands for the Menubar
*
* @param ( event object ) event
* @param ( MenuBar object) menubar is the MenuBar object associated with the event
* @return boolean false if the event was used by MenuBar, otherwise true
*/

function handleMenuBarKeyDownEvent(event, menubar) {
  var e = event || window.event;

  // If any modifier keys are pressed do not process this event
  if( e.altKey || e.ctrlKey || e.shiftKey )
    return true;

    switch( browser.keyCode( e ) ) {
    
      case KEY_LEFT:
           menuBarKeyLeftArrow( menubar );
           menubar.my_key_flag = false;
           return browser.stopPropagation( e );
           break;

      case KEY_RIGHT:
           menuBarKeyRightArrow( menubar );
       menubar.my_key_flag = false;
       return browser.stopPropagation( e );
           break;

    case KEY_UP:
           menuBarKeyUpArrow( menubar );
       menubar.my_key_flag = false;
       return browser.stopPropagation( e );
           break;

    case KEY_DOWN:
           menuBarKeyDownArrow( menubar );
       menubar.my_key_flag = false;
       return browser.stopPropagation( e );
           break;

    case KEY_ESCAPE:
           menuBarClosePullDown( menubar );
       menubar.pulldown_flag = false;
       menubar.current_menu_node = null;
       menubar.current_menu_node = null;
       menubar.my_key_flag = false;
       return browser.stopPropagation( e );
           break;

    case KEY_ENTER:
           menuBarOnClick( menubar );
           menuBarUpdateMenuBar( menubar, null );
       menubar.my_key_flag = false;
       return browser.stopPropagation( e );
           break;

    case KEY_TAB:
           menuBarClose( menubar );

           break;

  } // endif
  
  return true;
  
}

/**
* handleMenuBarClickEvent
*
* @param ( event object ) event
* @param ( MenuBar object) menubar is the MenuBar object associated with the event
* @return boolean false if the event was used by MenuBar, otherwise true
*/

handleMenuBarClickEvent = function(event, menubar) {
  var e = event || window.event;  
  
  if( browser.target( e ) == menubar.current_menubar_node ) {
    
  if( menubar.current_menubar_node.getAttribute("aria-haspopup") == "true" ) {

     menubar.current_menu_node = openPullDownMenu( menubar, menubar.current_menubar_node );
     menubar.pulldown_flag = true;
    
    }  //endif
    
  }  // endif

  return true;
  
}

/**
* handleMenuBarMouseOver
*
* @param ( event object ) event
* @param ( MenuBar object) menubar is the MenuBar object associated with the event
* @return boolean false if the event was used by MenuBar, otherwise true
*/

handleMenuBarMouseOverEvent = function(event, menubar) {
   var e = event || window.event;

   var n = menubar.node.firstChild;
  
   while( n ) {
    
     if( (n.nodeType == Node.ELEMENT_NODE) &&
       (n.getAttribute("role") == "menuitem" ) ) {
      
       if( n == browser.target( e ) ) {
        menuBarUpdateMenuBar( menubar, n );
        break;
       } // endif
        
     } // endif
    
     n = n.nextSibling;
    
   } // endwhile    

  return true;
  
}

/**
* handleMenuMouseOver
*
* @param ( event object ) event
* @param ( MenuBar object) menubar is the MenuBar object associated with the event
* @return boolean false if the event was used by MenuBar, otherwise true
*/

handleMenuMouseOverEvent = function(event, menubar) {
  var e = event || window.event;  

  if( menubar.current_menuitems ) {
    
    for(var index = 0; index < menubar.current_menuitems.length; index++ ) {

      var n = document.getElementById(menubar.current_menuitems[index].id );

      if( browser.target( e ) == n )  {
         menuBarUpdateMenu( menubar, n );
         break;
      } // endif
    
    } // endfor  
  
  } // endfor

  return true;
  
}


/**
* handleMenuBarFocusEvent
*
* @param ( event object ) event
* @param ( MenuBar object) menubar is the MenuBar object associated with the event
* @return boolean false if the event was used by MenuBar, otherwise true
*/

handleMenuBarFocusEvent = function(event, menubar) {
  var e = event || window.event;  

  if( browser.target( e ) == menubar.node ) {
  
    var new_node = getNextMenuItem( menubar );
    menuBarUpdateMenuBar( menubar, new_node );

  }  // endif
  
  return true;  
  
}

/**
* handleMenuBarBlurEvent
*
* @param ( event object ) event
* @param ( MenuBar object) menubar is the MenuBar object associated with the event
* @return boolean false if the event was used by MenuBar, otherwise true
*/

handleMenuBarBlurEvent = function(event, menubar) {
  var e = event | window.event;
  return true;
  
}


/**
* StyledText Object
*
* @param ( id ) id of text to style
* @return none
*/

function StyledText( id, menu_ids ) {

   this.id = id;
   this.menu_item_ids = menu_ids;

}

/**
* init is a subclass of StyledText
* tabs in a menu bar.
*
* @member StyleText
* @return nothing
*/

StyledText.prototype.init = function() {

  this.node = document.getElementById(this.id);
  this.fontSize = 2;
  this.fontSizes = ['x-small', 'small', 'medium', 'large', 'x-large'];

  var obj = this;

  browser.addEvent(this.node, "keydown",   function(event) {handleStyledTextKeyDownEvent(event, obj); }, false);

}


/**
* handleStyledTextKeyPressEvent
* handleStyledTextKetDownEvent Keyboard commands for the Menubar
*
* @param ( event object ) event
* @param ( StyledText object) stext us a StykedText object associated with the event
* @return boolean false if the event was used by MenuBar, otherwise true
*/

function handleStyledTextKeyDownEvent(event, stext ) {
  var e = event || window.event;

  // If any modifier keys are pressed do not process this event
  if( e.ctrlKey || e.shiftKey )
    return true;

    switch( browser.keyCode( e ) ) {
    
      case KEY_M:
           setMenuBarFocus(stext.menubar);
           return browser.stopPropagation( e );
           break;
      
  } // endif
  
  return true;
  
}

/**
* handleStyledTextSetFont
* handlers changing
*
* @param ( MenuBar object) styled text to hav its font changed
* @param ( StyledText object) styled text to hav its font changed
* @return nothing
*/

function handleStyledTextSetFontFamily( menubar, stext, family ) {

  stext.node.style.fontFamily = family;

  menuBarUpdateRadioMenuItems( menubar );
  
  menuBarClose( menubar );
  
  stext.node.focus();
  
}

/**
* handleStyledTextSetJustification
* handlers changing
*
* @param ( MenuBar object) styled text to hav its font changed
* @param ( StyledText object) styled text to hav its font changed
* @return nothing
*/

function handleStyledTextSetJustification( menubar, stext, justification ) {

  stext.node.style.textAlign = justification;

  menuBarUpdateRadioMenuItems( menubar );
  
  menuBarClose( menubar );
  
  stext.node.focus();
  
}

/**
* handleStyledTextSetFontSize
* handlers changing
*
* @param ( MenuBar object) styled text to hav its font changed
* @param ( StyledText object) styled text to hav its font changed
* @return nothing
*/

function handleStyledTextSetFontSize( menubar, stext, size ) {

  stext.fontSize = size;
  stext.node.style.fontSize = stext.fontSizes[stext.fontSize];

  menuBarUpdateRadioMenuItems( menubar );
  
  menuBarClose( menubar );
  
  stext.node.focus();
  
}

/**
* handleStyledTextFontSizeLarger
* handlers changing
*
* @param ( MenuBar object) styled text to hav its font changed
* @param ( StyledText object) styled text to hav its font changed
* @return nothing
*/

function handleStyledTextFontSizeLarger( menubar, stext) {

  stext.fontSize++;
  
  if( stext.fontSize > 4 )
    stext.fontSize = 4;

  menubar.current_menuitem_node = document.getElementById(stext.menu_item_ids[stext.fontSize]);

  handleStyledTextSetFontSize( menubar, stext, stext.fontSize )  

  menuBarClose( menubar );
  
  stext.node.focus();
  
}

/**
* handleStyledTextFontSizeSmaller
* handlers changing
*
* @param ( MenuBar object) styled text to hav its font changed
* @param ( StyledText object) styled text to hav its font changed
* @return nothing
*/

function handleStyledTextFontSizeSmaller( menubar, stext) {

  stext.fontSize--;
  
  if( stext.fontSize < 0 )
    stext.fontSize = 0;
  
  menubar.current_menuitem_node = document.getElementById(stext.menu_item_ids[stext.fontSize]);
  handleStyledTextSetFontSize( menubar, stext, stext.fontSize )  

  menuBarClose( menubar );
  
  stext.node.focus();
  
}



/**
* handleStyledTextBold
* handlers changing
*
* @param ( MenuBar object) styled text to hav its font changed
* @param ( StyledText object) styled text to hav its font changed
* @return nothing
*/

function handleStyledTextToggleBold( menubar, stext ) {

  if( stext.node.style.fontWeight == "bold" ) {
    stext.node.style.fontWeight = "normal";
    menuBarUpdateCheckboxMenuItems( menubar, false );
  } else {
    stext.node.style.fontWeight = "bold";
    menuBarUpdateCheckboxMenuItems( menubar, true );
  } // endif
  
  menuBarClose( menubar );
  
  stext.node.focus();
  
}

/**
* handleStyledTextItalic
* handlers changing
*
* @param ( MenuBar object) styled text to hav its font changed
* @param ( StyledText object) styled text to hav its font changed
* @return nothing
*/

function handleStyledTextToggleItalic( menubar, stext ) {

  if( stext.node.style.fontStyle == "italic" ) {
    stext.node.style.fontStyle = "normal";
    menuBarUpdateCheckboxMenuItems( menubar, false );
  } else {
    stext.node.style.fontStyle = "italic";
    menuBarUpdateCheckboxMenuItems( menubar, true );
  } // endif
  
  menuBarClose( menubar );
  
  stext.node.focus();
  
}

/**
* handleStyledTextUnderline
* handlers changing
*
* @param ( MenuBar object) styled text to hav its font changed
* @param ( StyledText object) styled text to hav its font changed
* @return nothing
*/

function handleStyledTextToggleUnderline( menubar, stext ) {

  if( stext.node.style.textDecoration == "underline" ) {
    stext.node.style.textDecoration = "none";
    menuBarUpdateCheckboxMenuItems( menubar, false );
  } else {
    stext.node.style.textDecoration = "underline";
    menuBarUpdateCheckboxMenuItems( menubar, true );
  } // endif
  
  menuBarClose( menubar );
  
  stext.node.focus();
  
}
</script>
</head>
<body onload="widgets.init()">
<div role="application">
  <script type="text/javascript">
     var menubar1 = new MenuBar("mb1");
     widgets.add(menubar1);
     var stext1 = new StyledText("st1", ['mi1440', 'mi1450', 'mi1460', 'mi1470', 'mi1480']);
     widgets.add(stext1);
  </script>

  <dl id="mb1"
    class="menubar"
      role="menubar"
      tabindex="0"
      title="Styling Menu">
    <dt id="mi1100"
        role="menuitem"
        tabindex="-1"
        aria-haspopup="true">Font</dt>
    <dd>
      <dl id="m11"
          role="menu">
        <dt id="mi1110"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="true"
            onclick="handleStyledTextSetFontFamily(menubar1, stext1, 'Sans-serif')"
            class="checked">Sans-serif</dt>
        <dt id="mi1120"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="false"
            onclick="handleStyledTextSetFontFamily(menubar1, stext1, 'serif')">Serif</dt>
        <dt id="mi1130"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="false"
            onclick="handleStyledTextSetFontFamily(menubar1, stext1, 'monospace')">Monospace</dt>
        <dt id="mi1140"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="false"
            onclick="handleStyledTextSetFontFamily(menubar1, stext1, 'fantasy')">Fantasy</dt>
      </dl>
    </dd>
    <dt id="mi1200"
        role="menuitem"
        tabindex="-1"
        aria-haspopup="true">Style</dt>
    <dd>
      <dl id="m12"
          class="closed"
          role="menu">
          
        <dt id="mi1210"
            role="menuitemcheckbox"
            tabindex="-1"
            onclick="handleStyledTextToggleItalic(menubar1, stext1)">Italics</dt>
        <dt id="mi1220"
            role="menuitemcheckbox"
            tabindex="-1" onclick="handleStyledTextToggleBold(menubar1, stext1)">Bold</dt>
        <dt id="mi1230"
            role="menuitemcheckbox"
            tabindex="-1"
            onclick="handleStyledTextToggleUnderline(menubar1, stext1)">Underline</dt>
      </dl>
    </dd>
    <dt id="mi1300"
        role="menuitem"
        tabindex="-1"
        aria-haspopup="true">Jusfication</dt>
    <dd>
      <dl id="m13"
          class="closed"
          role="menu"
          title="Justication">
        <dt id="mi1310"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="true"
            onclick="handleStyledTextSetJustification( menubar1, stext1, 'left' )"
            class="checked">Left</dt>
        <dt id="mi1320"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="false"
            onclick="handleStyledTextSetJustification( menubar1, stext1, 'center' )">Centered</dt>
        <dt id="mi1330"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="false"
            onclick="handleStyledTextSetJustification( menubar1, stext1, 'right' )">Right</dt>
        <dt id="mi1340"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="false"
            onclick="handleStyledTextSetJustification( menubar1, stext1, 'justify' )">Justify</dt>
      </dl>
    </dd>  
    <dt id="mi1400"
        role="menuitem"
        tabindex="-1"
        aria-haspopup="true">Size</dt>
    <dd>
      <dl id="m14"
          class="closed"
          role="menu"
          title="Size">
        <dt id="mi1410"
            role="menuitem"
            tabindex="-1"
            onclick="handleStyledTextFontSizeLarger( menubar1, stext1)">Larger</dt>
        <dt id="mi1420"
            role="menuitem"
            tabindex="-1"
            onclick="handleStyledTextFontSizeSmaller( menubar1, stext1)">Smaller</dt>
        <dt id="mi1430"
            role="separator"
            tabindex="-1"
            class="separator"></dt>
        <dt id="mi1440"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="false"
            onclick="handleStyledTextSetFontSize( menubar1, stext1, 0)">X-Small</dt>
        <dt id="mi1450"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="false"
            onclick="handleStyledTextSetFontSize( menubar1, stext1, 1)">Small</dt>
        <dt id="mi1460"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="true"
            onclick="handleStyledTextSetFontSize( menubar1, stext1, 2)">Medium</dt>
        <dt id="mi1470"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="false"
            onclick="handleStyledTextSetFontSize( menubar1, stext1, 3)">Large</dt>
        <dt id="mi1480"
            role="menuitemradio"
            tabindex="-1"
            aria-checked="false"
            onclick="handleStyledTextSetFontSize( menubar1, stext1, 4)">X-Large</dt>
      </dl>
    </dd>
  </dl>

<textarea id="st1" name="st1" style="padding: .5em; border: thin black solid; height: 30em; width: 40em; font-family: sans-serif">
Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.

Now we are engaged in a great civil war, testing whether that nation, or any nation, so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.

But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow, this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us, that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion, that we here highly resolve that these dead shall not have died in vain, that this nation, under God, shall have a new birth of freedom, and that government of the people, by the people, for the people, shall not perish from the earth.
</textarea>
  
<p><a href="http://en.wikipedia.org/wiki/Gettysburg,_Pennsylvania">More information on Gettysburg Address</a></p>
</div></body>
</html>