diff --git a/examples/menubar/menubar-2/css/menubarAction.css b/examples/menubar/menubar-2/css/menubarAction.css deleted file mode 100644 index 111aa19f22..0000000000 --- a/examples/menubar/menubar-2/css/menubarAction.css +++ /dev/null @@ -1,128 +0,0 @@ -ul[role="menubar"] { - margin: 0; - margin-top: 0.5em; - margin-bottom: 0.5em; - padding: 0.25em; - font-size: 110%; - list-style: none; - background-color: #eee; -} - -ul[role="menubar"] li { - margin: 0; - padding: 0; - list-style: none; -} - -ul[role="menubar"] > li { - display: inline; - position: relative; -} - -ul[role="menubar"] > li > [role="menuitem"]::after { - content: url('../images/down-arrow-brown.png'); - padding-left: 0.25em; -} - -ul[role="menubar"] ul[role="menu"] { - display: none; - position: absolute; - margin: 0; - padding: 0; -} - -ul[role="menubar"] ul[role="group"] { - margin: 0; - padding: 0; -} - -ul[role="menubar"] li[aria-disabled="true"] { - color: #666; - text-decoration: line-through; -} - -ul[role="menubar"] [role="menuitem"], -ul[role="menubar"] [role="menuitemcheckbox"], -ul[role="menubar"] [role="menuitemradio"], -ul[role="menubar"] [role="separator"] { - padding: 0.25em; - background-color: #eee; - border: 2px solid #eee; - color: black; -} - -ul[role="menubar"] ul li[role="menuitem"], -ul[role="menubar"] ul li[role="menuitemcheckbox"], -ul[role="menubar"] ul li[role="menuitemradio"], -ul[role="menubar"] ul li[role="separator"] { - padding-left: 1.5em; - width: 8em; -} - -ul[role="menubar"] [role="separator"] { - padding-top: 0.15em; - background-image: url('../images/separator.png'); - background-position: center; - background-repeat: repeat-x; -} - -ul[role="menubar"] [role="menuitem"]:focus, -ul[role="menubar"] [role="menuitem"][aria-expanded="true"] { - background-color: black; - color: white; - border: 2px solid black; - outline: none; -} - -ul[role="menubar"]:not(.focus) [role="menuitem"]:hover { - background-color: #444; - color: white; -} - -ul[role="menubar"] [role="menu"] [role="menuitem"]:focus, -ul[role="menubar"] [role="menu"] [role="menuitemcheckbox"]:focus, -ul[role="menubar"] [role="menu"] [role="menuitemradio"]:focus { - background-color: black; - color: white; - outline: none; -} - -ul[role="menubar"] [role="menuitemcheckbox"][aria-checked='true'], -ul[role="menubar"] [role="menuitemradio"][aria-checked='true'] { - padding-left: 0.5em; - padding-right: 1.25em; -} - -ul[role="menubar"] [role="menuitemcheckbox"][aria-checked='true']::before { - content: url('../images/check-brown.png'); - padding-right: 0.3em; -} - -ul[role="menubar"] [role="menuitemradio"][aria-checked='true']::before { - content: url('../images/dot-brown.png'); - padding-right: 0.3em; -} - -/* -* Text area styles -*/ -.italic { - font-style: italic; -} - -.bold { - font-weight: bold; -} - -.underline { - text-decoration: underline; -} - -#textarea1 { - padding: 0.5em; - border: 1px solid black; - height: 400px; - width: 70%; - font-size: medium; - font-family: sans-serif; -} diff --git a/examples/menubar/menubar-2/images/check-brown.png b/examples/menubar/menubar-2/images/check-brown.png deleted file mode 100644 index 2f1f5ff85a..0000000000 Binary files a/examples/menubar/menubar-2/images/check-brown.png and /dev/null differ diff --git a/examples/menubar/menubar-2/images/dot-brown.png b/examples/menubar/menubar-2/images/dot-brown.png deleted file mode 100644 index d0e8512a42..0000000000 Binary files a/examples/menubar/menubar-2/images/dot-brown.png and /dev/null differ diff --git a/examples/menubar/menubar-2/images/down-arrow-brown.png b/examples/menubar/menubar-2/images/down-arrow-brown.png deleted file mode 100644 index fe3e38aa31..0000000000 Binary files a/examples/menubar/menubar-2/images/down-arrow-brown.png and /dev/null differ diff --git a/examples/menubar/menubar-2/images/separator.png b/examples/menubar/menubar-2/images/separator.png deleted file mode 100644 index a837fbce93..0000000000 Binary files a/examples/menubar/menubar-2/images/separator.png and /dev/null differ diff --git a/examples/menubar/menubar-2/js/MenubarAction.js b/examples/menubar/menubar-2/js/MenubarAction.js deleted file mode 100644 index 2e25faf2b5..0000000000 --- a/examples/menubar/menubar-2/js/MenubarAction.js +++ /dev/null @@ -1,212 +0,0 @@ -/* -* This content is licensed according to the W3C Software License at -* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document -* -* File: MenubarAction.js -* -* Desc: Menubar widget that implements ARIA Authoring Practices -*/ - -'use strict'; - -/* -* @constructor MenubarAction -* -* @desc -* Wrapper object for a menubar -* -* @param domNode -* The DOM element node that serves as the menubar container. -* Each child element of domNode that represents a menubaritem -* must be an A element. -*/ -var MenubarAction = function (domNode) { - var msgPrefix = 'Menubar constructor argument domNode '; - - // Check whether domNode is a DOM element - if (!(domNode instanceof Element)) { - throw new TypeError(msgPrefix + 'is not a DOM Element.'); - } - - // Check whether domNode has descendant elements - if (domNode.childElementCount === 0) { - throw new Error(msgPrefix + 'has no element children.'); - } - - // Check whether domNode's descendant elements contain A elements - var e = domNode.firstElementChild; - while (e) { - var menubarItem = e.firstElementChild; - if (menubarItem && menubarItem.tagName !== 'A') { - throw new Error(msgPrefix + 'has child elements that are not A elements.'); - } - e = e.nextElementSibling; - } - - this.domNode = domNode; - - this.menubarItems = []; // see Menubar init method - this.firstChars = []; // see Menubar init method - - this.firstItem = null; // see Menubar init method - this.lastItem = null; // see Menubar init method -}; - -/* -* @method MenubarAction.prototype.init -* -* @desc -* Adds ARIA role to the menubar node -* Traverse menubar children for A elements to configure each A element as an ARIA menuitem -* and populate menuitems array. Initialize firstItem and lastItem properties. -*/ -MenubarAction.prototype.init = function (actionManager) { - var menubarItem, menuElement, textContent, numItems; - - this.actionManager = actionManager; - - this.domNode.setAttribute('role', 'menubar'); - - this.domNode.addEventListener('focusin', this.handleFocusin.bind(this)); - this.domNode.addEventListener('focusout', this.handleFocusout.bind(this)); - - // Traverse the element children of the menubar domNode: configure each with - // menuitem role behavior and store reference in menuitems array. - var e = this.domNode.firstElementChild; - - while (e) { - menuElement = e.firstElementChild; - - if (menuElement && menuElement.tagName === 'A') { - menubarItem = new MenubarItemAction(menuElement, this); - menubarItem.init(); - this.menubarItems.push(menubarItem); - textContent = menuElement.textContent.trim(); - this.firstChars.push(textContent.substring(0, 1).toLowerCase()); - } - - e = e.nextElementSibling; - } - - // Use populated menuitems array to initialize firstItem and lastItem. - numItems = this.menubarItems.length; - if (numItems > 0) { - this.firstItem = this.menubarItems[0]; - this.lastItem = this.menubarItems[numItems - 1]; - } - this.firstItem.domNode.tabIndex = 0; -}; - -/* FOCUS MANAGEMENT METHODS */ - -MenubarAction.prototype.setFocusToItem = function (newItem, hover) { - var isOpen = false; - var hasFocus = this.domNode.contains(document.activeElement); - for (var i = 0; i < this.menubarItems.length; i++) { - var mbi = this.menubarItems[i]; - isOpen = isOpen || (mbi.popupMenu && mbi.popupMenu.isOpen()); - if (!hover || hasFocus) { - mbi.domNode.tabIndex = -1; - } - if (mbi.popupMenu) { - mbi.popupMenu.close(); - } - } - if (!hover || hasFocus) { - newItem.domNode.focus(); - newItem.domNode.tabIndex = 0; - } - if (isOpen && newItem.popupMenu) { - newItem.popupMenu.open(); - } -}; - -MenubarAction.prototype.setFocusToFirstItem = function () { - this.setFocusToItem(this.firstItem); -}; -MenubarAction.prototype.setFocusToLastItem = function () { - this.setFocusToItem(this.lastItem); -}; - -MenubarAction.prototype.setFocusToPreviousItem = function (currentItem) { - var newItem, index; - - if (currentItem === this.firstItem) { - newItem = this.lastItem; - } - else { - index = this.menubarItems.indexOf(currentItem); - newItem = this.menubarItems[ index - 1 ]; - } - - this.setFocusToItem(newItem); -}; - -MenubarAction.prototype.setFocusToNextItem = function (currentItem) { - var newItem, index; - - if (currentItem === this.lastItem) { - newItem = this.firstItem; - } - else { - index = this.menubarItems.indexOf(currentItem); - newItem = this.menubarItems[ index + 1 ]; - } - this.setFocusToItem(newItem); -}; - -MenubarAction.prototype.setFocusByFirstCharacter = function (currentItem, char) { - var start, index; - - char = char.toLowerCase(); - - // Get start index for search based on position of currentItem - start = this.menubarItems.indexOf(currentItem) + 1; - if (start === this.menubarItems.length) { - start = 0; - } - - // Check remaining slots in the menu - index = this.getIndexFirstChars(start, char); - - // If not found in remaining slots, check from beginning - if (index === -1) { - index = this.getIndexFirstChars(0, char); - } - - // If match was found... - if (index > -1) { - this.menubarItems[index].domNode.focus(); - this.menubarItems[index].domNode.tabIndex = 0; - currentItem.tabIndex = -1; - } -}; - -MenubarAction.prototype.getIndexFirstChars = function (startIndex, char) { - for (var i = startIndex; i < this.firstChars.length; i++) { - if (char === this.firstChars[i]) { - return i; - } - } - return -1; -}; - -MenubarAction.prototype.handleFocusin = function (event) { - // if the menubar or any of its menus has focus, add styling hook for hover - this.domNode.classList.add('focus'); -}; - -MenubarAction.prototype.handleFocusout = function (event) { - // if the next element to get focus is not in the menubar or its menus, then close menu - if (!this.domNode.contains(event.relatedTarget)) { - for (var i = 0; i < this.menubarItems.length; i++) { - var mbi = this.menubarItems[i]; - if (mbi.popupMenu && mbi.popupMenu.isOpen()) { - mbi.popupMenu.close(); - } - } - } - // remove styling hook for hover on menubar item - this.domNode.classList.remove('focus'); -}; - diff --git a/examples/menubar/menubar-2/js/MenubarItemAction.js b/examples/menubar/menubar-2/js/MenubarItemAction.js deleted file mode 100644 index 20a6e65fcb..0000000000 --- a/examples/menubar/menubar-2/js/MenubarItemAction.js +++ /dev/null @@ -1,169 +0,0 @@ -/* -* This content is licensed according to the W3C Software License at -* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document -* -* File: MenubarItemAction.js -* -* Desc: Menubar Menuitem widget that implements ARIA Authoring Practices -*/ - -'use strict'; - -/* -* @constructor MenubarItemAction -* -* @desc -* Object that configures menubar item elements by setting tabIndex -* and registering itself to handle pertinent events. -* -* @param domNode -* The DOM element node that serves as the menubar item container. -* The menubarObj is responsible for checking that it has -* requisite metadata, e.g. role="menuitem". -* -* @param menubarObj -* The MenubarAction object that is a delegate for the menubar DOM element -* that contains the menubar item element. -*/ -var MenubarItemAction = function (domNode, menubarObj) { - - this.menubar = menubarObj; - this.domNode = domNode; - this.popupMenu = false; - - this.keyCode = Object.freeze({ - 'TAB': 9, - 'RETURN': 13, - 'ESC': 27, - 'SPACE': 32, - 'PAGEUP': 33, - 'PAGEDOWN': 34, - 'END': 35, - 'HOME': 36, - 'LEFT': 37, - 'UP': 38, - 'RIGHT': 39, - 'DOWN': 40 - }); -}; - -MenubarItemAction.prototype.init = function () { - this.domNode.tabIndex = -1; - - this.domNode.addEventListener('keydown', this.handleKeydown.bind(this)); - this.domNode.addEventListener('click', this.handleClick.bind(this)); - this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this)); - - // initialize pop up menus - - var nextElement = this.domNode.nextElementSibling; - - if (nextElement && nextElement.tagName === 'UL') { - this.popupMenu = new PopupMenuAction(nextElement, this, this.menubar.actionManager); - this.popupMenu.init(); - } - -}; - -MenubarItemAction.prototype.handleKeydown = function (event) { - var tgt = event.currentTarget, - char = event.key, - flag = false; - - function isPrintableCharacter (str) { - return str.length === 1 && str.match(/\S/); - } - - switch (event.keyCode) { - case this.keyCode.SPACE: - case this.keyCode.RETURN: - case this.keyCode.DOWN: - if (this.popupMenu) { - this.popupMenu.open(); - this.popupMenu.setFocusToFirstItem(); - flag = true; - } - break; - - case this.keyCode.ESC: - if (this.popupMenu) { - this.popupMenu.close(); - } - flag = true; - break; - - case this.keyCode.LEFT: - this.menubar.setFocusToPreviousItem(this); - flag = true; - break; - - case this.keyCode.RIGHT: - this.menubar.setFocusToNextItem(this); - flag = true; - break; - - case this.keyCode.UP: - if (this.popupMenu) { - this.popupMenu.open(); - this.popupMenu.setFocusToLastItem(); - flag = true; - } - break; - - case this.keyCode.HOME: - case this.keyCode.PAGEUP: - this.menubar.setFocusToFirstItem(); - if (this.popupMenu) { - this.popupMenu.close(); - } - flag = true; - break; - - case this.keyCode.END: - case this.keyCode.PAGEDOWN: - this.menubar.setFocusToLastItem(); - if (this.popupMenu) { - this.popupMenu.close(); - } - flag = true; - break; - - default: - if (isPrintableCharacter(char)) { - this.menubar.setFocusByFirstCharacter(this, char); - flag = true; - } - break; - } - - if (flag) { - event.stopPropagation(); - event.preventDefault(); - } -}; - -MenubarItemAction.prototype.handleClick = function (event) { - if (this.popupMenu) { - if (!this.popupMenu.isOpen()) { - // clicking on menubar item opens menu (closes open menu first) - for (var i = 0; i < this.menubar.menubarItems.length; i++) { - var mbi = this.menubar.menubarItems[i]; - if (mbi.popupMenu && mbi.popupMenu.isOpen()) { - mbi.popupMenu.close(); - break; - } - } - this.popupMenu.open(); - } - else { - // clicking again on same menubar item closes menu - this.popupMenu.close(); - } - // prevent scroll to top of page when anchor element is clicked - event.preventDefault(); - } -}; - -MenubarItemAction.prototype.handleMouseover = function (event) { - this.menubar.setFocusToItem(this, true); -}; diff --git a/examples/menubar/menubar-2/js/PopupMenuAction.js b/examples/menubar/menubar-2/js/PopupMenuAction.js deleted file mode 100644 index ecd8d5e624..0000000000 --- a/examples/menubar/menubar-2/js/PopupMenuAction.js +++ /dev/null @@ -1,255 +0,0 @@ -/* -* This content is licensed according to the W3C Software License at -* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document -* -* File: PopupMenuAction.js -* -* Desc: Popup menu widget that implements ARIA Authoring Practices -*/ - -'use strict'; - -/* -* @constructor PopupMenuAction -* -* @desc -* Wrapper object for a simple popup menu (without nested submenus) -* -* @param domNode -* The DOM element node that serves as the popup menu container. Each -* child element of domNode that represents a menuitem must have a -* 'role' attribute with value 'menuitem'. -* -* @param controllerObj -* The object that is a wrapper for the DOM element that controls the -* menu, e.g. a button element, with an 'aria-controls' attribute that -* references this menu's domNode. See MenuButton.js -* -* The controller object is expected to have the following properties: -* 1. domNode: The controller object's DOM element node, needed for -* retrieving positioning information. -*/ -var PopupMenuAction = function (domNode, controllerObj, actionManager) { - var elementChildren, - msgPrefix = 'PopupMenu constructor argument domNode '; - - // Check whether domNode is a DOM element - if (!(domNode instanceof Element)) { - throw new TypeError(msgPrefix + 'is not a DOM Element.'); - } - - // Check whether domNode has child elements - if (domNode.childElementCount === 0) { - throw new Error(msgPrefix + 'has no element children.'); - } - - this.domNode = domNode; - this.controller = controllerObj; - this.actionManager = actionManager; - - this.menuitems = []; // see PopupMenu init method - this.firstChars = []; // see PopupMenu init method - - this.firstItem = null; // see PopupMenu init method - this.lastItem = null; // see PopupMenu init method -}; - -/* -* @method PopupMenuAction.prototype.init -* -* @desc -* Traverse domNode children to configure each menuitem and populate menuitems -* array. Initialize firstItem and lastItem properties. -*/ -PopupMenuAction.prototype.init = function () { - var childElement, menuElement, firstChildElement, menuItem, textContent, numItems, label; - - // Configure the domNode itself - this.domNode.tabIndex = -1; - - this.domNode.setAttribute('role', 'menu'); - - if (!this.domNode.getAttribute('aria-labelledby') && !this.domNode.getAttribute('aria-label') && !this.domNode.getAttribute('title')) { - label = this.controller.domNode.innerHTML; - this.domNode.setAttribute('aria-label', label); - } - - // Traverse the element children of domNode: configure each with - // menuitem role behavior and store reference in menuitems array. - var menuElements = this.domNode.getElementsByTagName('LI'); - - for (var i = 0; i < menuElements.length; i++) { - - menuElement = menuElements[i]; - - if (!menuElement.firstElementChild && menuElement.getAttribute('role') !== 'separator') { - menuItem = new MenuItem(menuElement, this); - menuItem.init(); - this.menuitems.push(menuItem); - textContent = menuElement.textContent.trim(); - this.firstChars.push(textContent.substring(0, 1).toLowerCase()); - } - - } - - // Use populated menuitems array to initialize firstItem and lastItem. - numItems = this.menuitems.length; - if (numItems > 0) { - this.firstItem = this.menuitems[0]; - this.lastItem = this.menuitems[numItems - 1]; - } -}; - -PopupMenuAction.prototype.updateMenuStates = function () { - - var item = this.domNode.querySelector('[data-option="font-larger"]'); - if (item) { - if (this.actionManager.isMaxFontSize()) { - item.setAttribute('aria-disabled', 'true'); - } - else { - item.setAttribute('aria-disabled', 'false'); - } - } - - item = this.domNode.querySelector('[data-option="font-smaller"]'); - if (item) { - if (this.actionManager.isMinFontSize()) { - item.setAttribute('aria-disabled', 'true'); - } - else { - item.setAttribute('aria-disabled', 'false'); - } - } - - // Update the radio buttons for font, in case they were updated using the larger - // smaller font menu items - - var rbs = this.domNode.querySelectorAll('[data-option="font-size"] [role=menuitemradio]'); - - for (var i = 0; i < rbs.length; i++) { - var rb = rbs[i]; - - if (this.actionManager.fontSize === rb.textContent.toLowerCase()) { - rb.setAttribute('aria-checked', 'true'); - } - else { - rb.setAttribute('aria-checked', 'false'); - } - } - -}; - -/* FOCUS MANAGEMENT METHODS */ - -PopupMenuAction.prototype.setFocusToController = function (command) { - if (typeof command !== 'string') { - command = ''; - } - if (command === 'previous') { - this.controller.menubar.setFocusToPreviousItem(this.controller); - } - else if (command === 'next') { - this.controller.menubar.setFocusToNextItem(this.controller); - } - else { - this.controller.domNode.focus(); - } -}; - -PopupMenuAction.prototype.setFocusToItem = function (item) { - item.domNode.focus(); -}; - -PopupMenuAction.prototype.setFocusToFirstItem = function () { - this.firstItem.domNode.focus(); -}; - -PopupMenuAction.prototype.setFocusToLastItem = function () { - this.lastItem.domNode.focus(); -}; - -PopupMenuAction.prototype.setFocusToPreviousItem = function (currentItem) { - var index; - - if (currentItem === this.firstItem) { - this.lastItem.domNode.focus(); - } - else { - index = this.menuitems.indexOf(currentItem); - this.menuitems[index - 1].domNode.focus(); - } -}; - -PopupMenuAction.prototype.setFocusToNextItem = function (currentItem) { - var index; - - if (currentItem === this.lastItem) { - this.firstItem.domNode.focus(); - } - else { - index = this.menuitems.indexOf(currentItem); - this.menuitems[index + 1].domNode.focus(); - } -}; - -PopupMenuAction.prototype.setFocusByFirstCharacter = function (currentItem, char) { - var start, index; - - char = char.toLowerCase(); - - // Get start index for search based on position of currentItem - start = this.menuitems.indexOf(currentItem) + 1; - if (start === this.menuitems.length) { - start = 0; - } - - // Check remaining slots in the menu - index = this.getIndexFirstChars(start, char); - - // If not found in remaining slots, check from beginning - if (index === -1) { - index = this.getIndexFirstChars(0, char); - } - - // If match was found... - if (index > -1) { - this.menuitems[index].domNode.focus(); - } -}; - -PopupMenuAction.prototype.getIndexFirstChars = function (startIndex, char) { - for (var i = startIndex; i < this.firstChars.length; i++) { - if (char === this.firstChars[i]) { - return i; - } - } - return -1; -}; - -/* MENU DISPLAY METHODS */ - -PopupMenuAction.prototype.open = function () { - // get position and bounding rectangle of controller object's DOM node - var rect = this.controller.domNode.getBoundingClientRect(); - - // set CSS properties - this.domNode.style.position = 'absolute'; - this.domNode.style.top = (rect.height - 1) + 'px'; - this.domNode.style.left = '0px'; - this.domNode.style.zIndex = 100; - this.domNode.style.display = 'block'; - - // set aria-expanded attribute - this.controller.domNode.setAttribute('aria-expanded', 'true'); -}; - -PopupMenuAction.prototype.isOpen = function () { - return this.controller.domNode.getAttribute('aria-expanded') === 'true'; -}; - -PopupMenuAction.prototype.close = function () { - this.domNode.style.display = 'none'; - this.domNode.style.zIndex = 0; - this.controller.domNode.setAttribute('aria-expanded', 'false'); -}; diff --git a/examples/menubar/menubar-2/js/PopupMenuItemAction.js b/examples/menubar/menubar-2/js/PopupMenuItemAction.js deleted file mode 100644 index f8ad9c8e11..0000000000 --- a/examples/menubar/menubar-2/js/PopupMenuItemAction.js +++ /dev/null @@ -1,208 +0,0 @@ -/* -* This content is licensed according to the W3C Software License at -* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document -* -* File: MenuItem.js -* -* Desc: Popup Menu Menuitem widget that implements ARIA Authoring Practices -*/ - -'use strict'; - -/* -* @constructor MenuItem -* -* @desc -* Wrapper object for a simple menu item in a popup menu -* -* @param domNode -* The DOM element node that serves as the menu item container. -* The menuObj PopupMenu is responsible for checking that it has -* requisite metadata, e.g. role="menuitem". -* -* @param menuObj -* The object that is a wrapper for the PopupMenu DOM element that -* contains the menu item DOM element. See PopupMenu.js -*/ -var MenuItem = function (domNode, menuObj) { - - this.domNode = domNode; - this.menu = menuObj; - - this.keyCode = Object.freeze({ - 'TAB': 9, - 'RETURN': 13, - 'ESC': 27, - 'SPACE': 32, - 'PAGEUP': 33, - 'PAGEDOWN': 34, - 'END': 35, - 'HOME': 36, - 'LEFT': 37, - 'UP': 38, - 'RIGHT': 39, - 'DOWN': 40 - }); -}; - -MenuItem.prototype.init = function () { - this.domNode.tabIndex = -1; - - if (!this.domNode.getAttribute('role')) { - this.domNode.setAttribute('role', 'menuitem'); - } - - this.domNode.addEventListener('keydown', this.handleKeydown.bind(this)); - this.domNode.addEventListener('click', this.handleClick.bind(this)); - this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this)); -}; - -MenuItem.prototype.activateMenuitem = function (node) { - - var role = node.getAttribute('role'); - var value = node.textContent; - var option = node.getAttribute('data-option'); - var item; - // flag is used to signal whether a menu should close or not - // i.e. don't close if checkbox or radio menuitem is toggled - var flag = true; - - if (typeof option !== 'string') { - option = node.parentNode.getAttribute('data-option'); - } - - if (role === 'menuitem') { - this.menu.actionManager.setOption(option, value); - } - else { - if (role === 'menuitemcheckbox') { - if (node.getAttribute('aria-checked') === 'true') { - this.menu.actionManager.setOption(option, false); - node.setAttribute('aria-checked', 'false'); - } - else { - this.menu.actionManager.setOption(option, true); - node.setAttribute('aria-checked', 'true'); - } - flag = false; - } - else { - if (role === 'menuitemradio') { - - this.menu.actionManager.setOption(option, value); - - item = node.parentNode.firstElementChild; - while (item) { - if (item.getAttribute('role') === 'menuitemradio') { - item.setAttribute('aria-checked', 'false'); - } - item = item.nextElementSibling; - } - node.setAttribute('aria-checked', 'true'); - flag = false; - } - } - } - - this.menu.updateMenuStates(); - - return flag; - -}; - -/* EVENT HANDLERS */ - -MenuItem.prototype.handleKeydown = function (event) { - var tgt = event.currentTarget, - char = event.key, - flag = false; - - function isPrintableCharacter (str) { - return str.length === 1 && str.match(/\S/); - } - - switch (event.keyCode) { - case this.keyCode.SPACE: - if (this.activateMenuitem(tgt)) { - this.menu.setFocusToController(); - this.menu.close(); - } - flag = true; - break; - - case this.keyCode.RETURN: - this.activateMenuitem(tgt); - this.menu.setFocusToController(); - this.menu.close(); - flag = true; - break; - - case this.keyCode.ESC: - this.menu.setFocusToController(); - this.menu.close(); - flag = true; - break; - - case this.keyCode.UP: - this.menu.setFocusToPreviousItem(this); - flag = true; - break; - - case this.keyCode.DOWN: - this.menu.setFocusToNextItem(this); - flag = true; - break; - - case this.keyCode.LEFT: - this.menu.setFocusToController('previous'); - this.menu.close(); - flag = true; - break; - - case this.keyCode.RIGHT: - this.menu.setFocusToController('next'); - this.menu.close(); - flag = true; - break; - - case this.keyCode.HOME: - case this.keyCode.PAGEUP: - this.menu.setFocusToFirstItem(); - flag = true; - break; - - case this.keyCode.END: - case this.keyCode.PAGEDOWN: - this.menu.setFocusToLastItem(); - flag = true; - break; - - case this.keyCode.TAB: - this.menu.setFocusToController(); - this.menu.close(); - // allow tab and shift+tab to navigate out of menu bar - break; - - default: - if (isPrintableCharacter(char)) { - this.menu.setFocusByFirstCharacter(this, char); - flag = true; - } - break; - } - - if (flag) { - event.stopPropagation(); - event.preventDefault(); - } -}; - -MenuItem.prototype.handleClick = function (event) { - this.activateMenuitem(event.currentTarget); - this.menu.setFocusToController(); - this.menu.close(); -}; - -MenuItem.prototype.handleMouseover = function (event) { - this.menu.setFocusToItem(this); -}; diff --git a/examples/menubar/menubar-2/js/menubar-2-init.js b/examples/menubar/menubar-2/js/menubar-2-init.js deleted file mode 100644 index ddca7a1db3..0000000000 --- a/examples/menubar/menubar-2/js/menubar-2-init.js +++ /dev/null @@ -1,17 +0,0 @@ -/* -* This content is licensed according to the W3C Software License at -* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document -* -* File: menubar-2-init.js -* -* Desc: Creates a menubar to control the styling of text in a textarea element -*/ - -'use strict'; - -window.addEventListener('load', function () { - var menubar = new MenubarAction(document.getElementById('menubar1')); - var styleManager = new StyleManager('textarea1'); - menubar.init(styleManager); -}); - diff --git a/examples/menubar/menubar-2/js/styleManager.js b/examples/menubar/menubar-2/js/styleManager.js deleted file mode 100644 index edf65cf90f..0000000000 --- a/examples/menubar/menubar-2/js/styleManager.js +++ /dev/null @@ -1,166 +0,0 @@ -/* -* This content is licensed according to the W3C Software License at -* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document -* -* File: TextStyling.js -* -* Desc: Styling functions for changing the style of an item -*/ - -'use strict'; - -var StyleManager = function (id) { - this.node = document.getElementById(id); - this.fontSize = 'medium'; -}; - -StyleManager.prototype.setFontFamily = function (value) { - this.node.style.fontFamily = value; -}; - -StyleManager.prototype.setTextDecoration = function (value) { - this.node.style.textDecoration = value; -}; - -StyleManager.prototype.setTextAlign = function (value) { - this.node.style.textAlign = value; -}; - -StyleManager.prototype.setFontSize = function (value) { - this.fontSize = value; - this.node.style.fontSize = value; -}; - -StyleManager.prototype.setColor = function (value) { - this.node.style.color = value; -}; - -StyleManager.prototype.setBold = function (flag) { - - if (flag) { - this.node.style.fontWeight = 'bold'; - } - else { - this.node.style.fontWeight = 'normal'; - } -}; - -StyleManager.prototype.setItalic = function (flag) { - - if (flag) { - this.node.style.fontStyle = 'italic'; - } - else { - this.node.style.fontStyle = 'normal'; - } -}; - -StyleManager.prototype.fontSmaller = function () { - - switch (this.fontSize) { - case 'small': - this.setFontSize('x-small'); - break; - - case 'medium': - this.setFontSize('small'); - break; - - case 'large': - this.setFontSize('medium'); - break; - - case 'x-large': - this.setFontSize('large'); - break; - - default: - break; - - } // end switch -}; - -StyleManager.prototype.fontLarger = function () { - - switch (this.fontSize) { - case 'x-small': - this.setFontSize('small'); - break; - - case 'small': - this.setFontSize('medium'); - break; - - case 'medium': - this.setFontSize('large'); - break; - - case 'large': - this.setFontSize('x-large'); - break; - - default: - break; - - } // end switch -}; - -StyleManager.prototype.isMinFontSize = function () { - return this.fontSize === 'x-small'; -}; - -StyleManager.prototype.isMaxFontSize = function () { - return this.fontSize === 'x-large'; -}; - -StyleManager.prototype.setOption = function (option, value) { - - option = option.toLowerCase(); - if (typeof value === 'string') { - value = value.toLowerCase(); - } - - switch (option) { - - case 'font-bold': - this.setBold(value); - break; - - case 'font-color': - this.setColor(value); - break; - - case 'font-family': - this.setFontFamily(value); - break; - - case 'font-smaller': - this.fontSmaller(); - break; - - case 'font-larger': - this.fontLarger(); - break; - - case 'font-size': - this.setFontSize(value); - break; - - case 'font-italic': - this.setItalic(value); - break; - - case 'text-align': - this.setTextAlign(value); - break; - - case 'text-decoration': - this.setTextDecoration(value); - break; - - default: - break; - - } // end switch - -}; diff --git a/examples/menubar/menubar-2/menubar-2.html b/examples/menubar/menubar-2/menubar-2.html deleted file mode 100644 index ab7280cc95..0000000000 --- a/examples/menubar/menubar-2/menubar-2.html +++ /dev/null @@ -1,798 +0,0 @@ - - - - - Editor Menubar Example | WAI-ARIA Authoring Practices 1.2 - - - - - - - - - - - - - - - - - - - -
-

Editor Menubar Example

-

- The following example demonstrates using the - menubar design pattern - to provide access to sets of actions. - Each item in the below menubar identifies a category of text formatting actions that can be executed from its submenu. - The submenus also demonstrate menuitemradio and menuitemcheckbox elements. -

-

Similar examples include:

- - -
-

Example

- -
- - -
- -

- More information on - Gettysburg Address -

- - -
- -
- -
-

Accessibility Features

-
    -
  1. Users of assistive technologies can identify which format settings are selected because they are represented by menu item radio and menu item checkbox elements that have a checked state.
  2. -
  3. Disabled menu items are demonstrated in the font size menu, which includes two disabled menuitems.
  4. -
  5. The down arrow and checked icons are made compatible with high contrast mode and hidden from screen readers by using the CSS content property to render images.
  6. -
  7. - Like desktop menubars, submenus open on mouse hover over a parent item in the menubar only if another submenu is already open. - That is, if all submenus are closed, a click on a parent menu item is required to display a submenu. - Minimizing automatic popups makes exploring with a screen magnifier easier. -
  8. -
  9. - In general, moving focus in response to mouse hover is avoided in accessible widgets; it causes unexpected context changes for keyboard users. - However, like desktop menubars, there are two conditions in this example menubar where focus moves in response to hover in order to help maintain context for users who use both keyboard and mouse: -
      -
    1. After a parent menu item in the menubar has been activated and the user hovers over a different parent item in the menubar, focus will follow hover.
    2. -
    3. When a submenu is open and the user hovers over an item in the submenu, focus follows hover.
    4. -
    -
  10. -
-
- -
-

Keyboard Support

-

Menubar

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyFunction
- Space
Enter -
Opens submenu and moves focus to first item in the submenu.
- Escape - - If a submenu is open, closes it. Otherwise, does nothing. -
- Right Arrow - -
    -
  • Moves focus to the next item in the menubar.
  • -
  • If focus is on the last item, moves focus to the first item.
  • -
-
- Left Arrow - -
    -
  • Moves focus to the previous item in the menubar.
  • -
  • If focus is on the first item, moves focus to the last item.
  • -
-
- Down Arrow - Opens submenu and moves focus to first item in the submenu.
- Up Arrow - Opens submenu and moves focus to last item in the submenu.
- Home - Moves focus to first item in the menubar.
- End - Moves focus to last item in the menubar.
- Character - -
    -
  • Moves focus to next item in the menubar having a name that starts with the typed character.
  • -
  • If none of the items have a name starting with the typed character, focus does not move.
  • -
-
- -

Submenu

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyFunction
- Space
Enter -
Activates menu item, causing action to be executed, e.g., bold text, change font.
- Escape - -
    -
  • Closes submenu.
  • -
  • Moves focus to parent menubar item.
  • -
-
- Right Arrow - -
    -
  • Closes submenu.
  • -
  • Moves focus to next item in the menubar.
  • -
  • Opens submenu of newly focused menubar item, keeping focus on that parent menubar item.
  • -
-
- Left Arrow - -
    -
  • Closes submenu.
  • -
  • Moves focus to previous item in the menubar.
  • -
  • Opens submenu of newly focused menubar item, keeping focus on that parent menubar item.
  • -
-
- Down Arrow - -
    -
  • Moves focus to the next item in the submenu.
  • -
  • If focus is on the last item, moves focus to the first item.
  • -
-
- Up Arrow - -
    -
  • Moves focus to previous item in the submenu.
  • -
  • If focus is on the first item, moves focus to the last item.
  • -
-
- Home - Moves focus to the first item in the submenu.
- End - Moves focus to the last item in the submenu.
- Character - -
    -
  • Moves focus to the next item having a name that starts with the typed character.
  • -
  • If none of the items have a name starting with the typed character, focus does not move.
  • -
-
-
- -
-

Role, Property, State, and Tabindex Attributes

-

Menubar

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RoleAttributeElementUsage
- menubar - - ul - -
    -
  • Identifies the element as a menubar container for a set of menuitem elements.
  • -
  • Is not focusable because focus is managed using roving tabindex.
  • -
-
- aria-label="string" - - - ul - -
    -
  • - Defines an accessible name for the menubar. -
  • -
  • Helps assistive technology users understand the purpose of the menubar and - distinguish it from any other menubars or similar elements on the page.
  • -
-
- menuitem - - a - -
    -
  • Identifies the element as a menu item within the menubar.
  • -
  • Accessible name comes from the text content.
  • -
-
- tabindex="-1" - - a - - Makes the menuitem element keyboard focusable but - not part of the Tab sequence of the page. -
- tabindex="0" - - a - -
    -
  • - Makes the menuitem element keyboard focusable and - part of the tab sequence of the page. -
  • -
  • - Only one menuitem in the menubar has tabindex="0". -
  • -
  • - When the page loads, the first item in the menubar has tabindex="0". -
  • -
  • - Focus is managed using roving tabindex. -
  • -
-
- aria-haspopup="true" - - a - - Indicates that the menuitem has a submenu. -
- aria-expanded="true" - - a - Indicates the menu is open.
- aria-expanded="false" - - a - Indicates the submenu is closed.
-

Submenu

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RoleAttributeElementUsage
- menu - - ul - -
    -
  • Identifies the element as a menu container for a set of menu items.
  • -
  • Is not focusable because focus is managed using roving tabindex.
  • -
-
- aria-label="string" - - ul - - Defines an accessible name for the menu. -
- menuitem - - li - -
    -
  • Identifies the element as an item in the submenu.
  • -
  • Accessible name comes from the text content.
  • -
-
- tabindex="-1" - - li - - Makes the item focusable but not part of the page tab sequence. -
- aria-disabled="false" - - li - - Used on the font size "Smaller" and "Larger" options to indicate they are active. -
- aria-disabled="true" - - li - - Used on the font size "Smaller" and "Larger" options to indicate one of the options is not active because the largest or smallest font has been selected. -
- menuitemcheckbox - - li - -
    -
  • Identifies the element as a menuitemcheckbox.
  • -
  • Accessible name comes from the text content.
  • -
-
- tabindex="-1" - - li - - Makes the menuitemcheckbox focusable but not part of the page tab sequence. -
- aria-checked="true" - - li - -
    -
  • - Indicates that the menuitemcheckbox is checked. -
  • -
  • - The visual appearance of the selected state is synchronized with the aria-checked value using CSS attribute selectors. -
  • -
-
- aria-checked="false" - - li - -
    -
  • - Indicates that the menuitemcheckbox is NOT checked. -
  • -
  • - The visual appearance of the selected state is synchronized with the aria-checked value using CSS attribute selectors. -
  • -
-
- separator - - li - -
    -
  • Identifies the element as a visual separator between groups of items within a menu, such as groups of menuitemradio or menuitemcheckbox elements.
  • -
  • Is not focusable but may be perceivable by a screen reader user when using a reading cursor that does not depend on focus.
  • -
-
- group - - ul - -
    -
  • - Identifies the element as a container for a set of menuitemradio elements. -
  • -
  • - Enables browsers to compute values of aria-setsize and aria-posinset. -
  • -
-
- aria-label="string" - - ul - - Provides an accessible name for the group of menu items. -
- menuitemradio - - li - -
    -
  • - Identifies the element as a menuitemradio element. -
  • -
  • - When all items in a submenu are members of the same radio group, - the group is defined by the menu element; a group element is not necessary. -
  • -
  • - Accessible name is computed from the text content. -
  • -
-
- tabindex="-1" - - li - - Makes the menuitemradio focusable but not part of the page tab sequence. -
- aria-checked="true" - - li - -
    -
  • - Indicates the menuitemradio is checked. -
  • -
  • - The visual appearance of the selected state is synchronized with the aria-checked value using CSS attribute selectors. -
  • -
-
- aria-checked="false" - - li - -
    -
  • - Indicates that the menuitemradio is NOT checked. -
  • -
  • - The visual appearance of the selected state is synchronized with the aria-checked value using CSS attribute selectors. -
  • -
-
-
- -
-

Javascript and CSS Source Code

- -
- -
-

HTML Source Code

- -
- - - - -
-
- - - -