diff --git a/aria-practices.html b/aria-practices.html
index b030c3da9e..10de549342 100644
--- a/aria-practices.html
+++ b/aria-practices.html
@@ -1935,8 +1935,8 @@
Example
diff --git a/examples/menubar/css/menubar-navigation.css b/examples/menubar/css/menubar-navigation.css
new file mode 100644
index 0000000000..90b8f004b2
--- /dev/null
+++ b/examples/menubar/css/menubar-navigation.css
@@ -0,0 +1,121 @@
+.menubar-navigation {
+ margin: 0;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ padding: 7px;
+ font-size: 110%;
+ list-style: none;
+ background-color: #eee;
+ border: #eee solid 1px;
+ border-radius: 5px;
+}
+
+.menubar-navigation li {
+ margin: 0;
+ padding: 0;
+ border: 0 solid black;
+ list-style: none;
+}
+
+.menubar-navigation > li {
+ display: inline-block;
+ position: relative;
+}
+
+.menubar-navigation > li li {
+ display: block;
+}
+
+.menubar-navigation [role="menu"] [role="menuitem"],
+.menubar-navigation [role="menu"] [role="separator"] {
+ display: block;
+ width: 12em;
+ margin: 0;
+}
+
+.menubar-navigation [role="menuitem"],
+.menubar-navigation [role="separator"] {
+ padding: 6px;
+ background-color: #eee;
+ border: 0px solid #eee;
+ color: black;
+ border-radius: 5px;
+}
+
+.menubar-navigation [role="menuitem"] svg {
+ fill: currentColor;
+ stroke: currentColor;
+}
+
+.menubar-navigation [role="menuitem"] svg.down {
+ padding-left: 0.125em;
+}
+
+.menubar-navigation [role="menuitem"] svg.right {
+ position: absolute;
+ padding-top: 0.35em;
+ right: 0.75em;
+}
+
+.menubar-navigation [role="menuitem"][aria-expanded="true"] svg.down {
+ transform: rotate(180deg);
+}
+
+.menubar-navigation [role="menuitem"][aria-expanded="true"] svg.right {
+ transform: rotate(90deg) translate(5px, -5px);
+}
+
+.menubar-navigation > li > [role="menuitem"] {
+ display: inline-block;
+}
+
+.menubar-navigation [role="menu"] {
+ display: none;
+ position: absolute;
+ margin: 0;
+ padding: 0;
+}
+
+.menubar-navigation [role="group"] {
+ margin: 0;
+ padding: 0;
+}
+
+.menubar-navigation [role="menu"] {
+ display: none;
+}
+
+.menubar-navigation [role="separator"] {
+ padding-top: 3px;
+ background-image: url('../images/separator.svg');
+ background-position: center;
+ background-repeat: repeat-x;
+}
+
+/* focus styling */
+
+.menubar-navigation.focus {
+ padding: 6px;
+ border: #034575 solid 2px;
+}
+
+.menubar-navigation [role="menu"] {
+ padding: 7px 4px;
+ border: 2px solid #034575;
+ border-radius: 5px;
+ background-color: #eee;
+}
+
+.menubar-navigation [role="menuitem"][aria-expanded="true"],
+.menubar-navigation [role="menuitem"]:focus,
+.menubar-navigation [role="menuitem"]:hover {
+ background: #034575;
+ color: #fff;
+ outline: none;
+}
+
+.menubar-navigation [role="menuitem"]:focus,
+.menubar-navigation [role="menuitem"]:hover {
+ padding: 2px;
+ border: 4px solid #034575;
+}
diff --git a/examples/menubar/images/down-arrow-focus.svg b/examples/menubar/images/down-arrow-focus.svg
index f637806269..8f6ea66370 100644
--- a/examples/menubar/images/down-arrow-focus.svg
+++ b/examples/menubar/images/down-arrow-focus.svg
@@ -1,4 +1,4 @@
-
+
-
-
\ No newline at end of file
+
+
diff --git a/examples/menubar/images/down-arrow.svg b/examples/menubar/images/down-arrow.svg
index c30c32e123..a0a2556a5e 100644
--- a/examples/menubar/images/down-arrow.svg
+++ b/examples/menubar/images/down-arrow.svg
@@ -1,4 +1,4 @@
-
+
-
-
\ No newline at end of file
+
+
diff --git a/examples/menubar/images/separator.svg b/examples/menubar/images/separator.svg
index db78906f72..b4b39760b2 100644
--- a/examples/menubar/images/separator.svg
+++ b/examples/menubar/images/separator.svg
@@ -1,4 +1,4 @@
-
-
-
-
+
+
+
+
diff --git a/examples/menubar/images/up-arrow.svg b/examples/menubar/images/up-arrow.svg
new file mode 100644
index 0000000000..d034dad152
--- /dev/null
+++ b/examples/menubar/images/up-arrow.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/examples/menubar/js/menubar-navigation.js b/examples/menubar/js/menubar-navigation.js
new file mode 100644
index 0000000000..860943ec4f
--- /dev/null
+++ b/examples/menubar/js/menubar-navigation.js
@@ -0,0 +1,619 @@
+/*
+* This content is licensed according to the W3C Software License at
+* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
+*
+* File: menubar-navigation.js
+*
+* Desc: Creates a menubar of hierarchical set of links
+*/
+
+'use strict';
+
+var MenubarNavigation = function (domNode) {
+
+ this.domNode = domNode;
+
+
+ this.popups = [];
+ this.menuitemGroups = {};
+ this.menuOrientation = {};
+ this.isPopup = {};
+ this.isPopout = {};
+ this.openPopups = false;
+
+ this.firstChars = {}; // see Menubar init method
+ this.firstMenuitem = {}; // see Menubar init method
+ this.lastMenuitem = {}; // see Menubar init method
+
+ this.initMenu(domNode, 0);
+
+ domNode.addEventListener('focusin', this.handleMenubarFocusin.bind(this));
+ domNode.addEventListener('focusout', this.handleMenubarFocusout.bind(this));
+
+ window.addEventListener('mousedown', this.handleBackgroundMousedown.bind(this), true);
+};
+
+MenubarNavigation.prototype.getMenuitems = function(domNode, depth) {
+ var nodes = [];
+
+ var initMenu = this.initMenu.bind(this);
+ var menuitemGroups = this.menuitemGroups;
+ var popups = this.popups;
+
+ function findMenuitems(node) {
+ var role, flag;
+
+ while (node) {
+ flag = true;
+ role = node.getAttribute('role');
+
+ if (role) {
+ role = role.trim().toLowerCase();
+ }
+
+ switch (role) {
+ case 'menu':
+ node.tabIndex = -1;
+ initMenu(node, depth + 1);
+ flag = false;
+ break;
+
+ case 'menuitem':
+ if (node.getAttribute('aria-haspopup') === 'true') {
+ popups.push(node);
+ }
+ nodes.push(node);
+ break;
+
+ default:
+ break;
+ }
+
+ if (flag && node.firstElementChild && node.firstElementChild.tagName !== 'svg') {
+ findMenuitems(node.firstElementChild);
+ }
+
+ node = node.nextElementSibling;
+ }
+ }
+
+ findMenuitems(domNode.firstElementChild);
+
+ return nodes;
+};
+
+MenubarNavigation.prototype.initMenu = function (menu, depth) {
+ var menuitems, menuitem, role, nextElement;
+
+ var menuId = this.getMenuId(menu);
+
+ menuitems = this.getMenuitems(menu, depth);
+ this.menuOrientation[menuId] = this.getMenuOrientation(menu);
+
+ this.isPopup[menuId] = (menu.getAttribute('role') === 'menu') && (depth === 1);
+ this.isPopout[menuId] = (menu.getAttribute('role') === 'menu') && (depth > 1);
+
+ this.menuitemGroups[menuId] = [];
+ this.firstChars[menuId] = [];
+ this.firstMenuitem[menuId] = null;
+ this.lastMenuitem[menuId] = null;
+
+ for(var i = 0; i < menuitems.length; i++) {
+ menuitem = menuitems[i];
+ role = menuitem.getAttribute('role');
+
+ if (role.indexOf('menuitem') < 0) {
+ continue;
+ }
+
+ menuitem.tabIndex = -1;
+ this.menuitemGroups[menuId].push(menuitem);
+ this.firstChars[menuId].push(menuitem.textContent.trim().toLowerCase()[0]);
+
+ menuitem.addEventListener('keydown', this.handleKeydown.bind(this));
+ menuitem.addEventListener('click', this.handleMenuitemClick.bind(this));
+
+ menuitem.addEventListener('mouseover', this.handleMenuitemMouseover.bind(this));
+
+ if( !this.firstMenuitem[menuId]) {
+ if (this.hasPopup(menuitem)) {
+ menuitem.tabIndex = 0;
+ }
+ this.firstMenuitem[menuId] = menuitem;
+ }
+ this.lastMenuitem[menuId] = menuitem;
+
+ }
+};
+
+MenubarNavigation.prototype.setFocusToMenuitem = function (menuId, newMenuitem) {
+
+ this.closePopupAll(newMenuitem);
+
+ if (this.menuitemGroups[menuId]) {
+ this.menuitemGroups[menuId].forEach(function(item) {
+ if (item === newMenuitem) {
+ item.tabIndex = 0;
+ newMenuitem.focus();
+ }
+ else {
+ item.tabIndex = -1;
+ }
+ });
+ }
+};
+
+MenubarNavigation.prototype.setFocusToFirstMenuitem = function (menuId, currentMenuitem) {
+ this.setFocusToMenuitem(menuId, this.firstMenuitem[menuId]);
+};
+
+MenubarNavigation.prototype.setFocusToLastMenuitem = function (menuId, currentMenuitem) {
+ this.setFocusToMenuitem(menuId, this.lastMenuitem[menuId]);
+};
+
+MenubarNavigation.prototype.setFocusToPreviousMenuitem = function (menuId, currentMenuitem) {
+ var newMenuitem, index;
+
+ if (currentMenuitem === this.firstMenuitem[menuId]) {
+ newMenuitem = this.lastMenuitem[menuId];
+ }
+ else {
+ index = this.menuitemGroups[menuId].indexOf(currentMenuitem);
+ newMenuitem = this.menuitemGroups[menuId][ index - 1 ];
+ }
+
+ this.setFocusToMenuitem(menuId, newMenuitem);
+
+ return newMenuitem;
+};
+
+MenubarNavigation.prototype.setFocusToNextMenuitem = function (menuId, currentMenuitem) {
+ var newMenuitem, index;
+
+ if (currentMenuitem === this.lastMenuitem[menuId]) {
+ newMenuitem = this.firstMenuitem[menuId];
+ }
+ else {
+ index = this.menuitemGroups[menuId].indexOf(currentMenuitem);
+ newMenuitem = this.menuitemGroups[menuId][ index + 1 ];
+ }
+ this.setFocusToMenuitem(menuId, newMenuitem);
+
+ return newMenuitem;
+};
+
+MenubarNavigation.prototype.setFocusByFirstCharacter = function (menuId, currentMenuitem, char) {
+ var start, index;
+
+ char = char.toLowerCase();
+
+ // Get start index for search based on position of currentItem
+ start = this.menuitemGroups[menuId].indexOf(currentMenuitem) + 1;
+ if (start >= this.menuitemGroups[menuId].length) {
+ start = 0;
+ }
+
+ // Check remaining slots in the menu
+ index = this.getIndexFirstChars(menuId, start, char);
+
+ // If not found in remaining slots, check from beginning
+ if (index === -1) {
+ index = this.getIndexFirstChars(menuId, 0, char);
+ }
+
+ // If match was found...
+ if (index > -1) {
+ this.setFocusToMenuitem(menuId, this.menuitemGroups[menuId][index]);
+ }
+};
+
+// Utitlities
+
+MenubarNavigation.prototype.getIndexFirstChars = function (menuId, startIndex, char) {
+ for (var i = startIndex; i < this.firstChars[menuId].length; i++) {
+ if (char === this.firstChars[menuId][i]) {
+ return i;
+ }
+ }
+ return -1;
+};
+
+MenubarNavigation.prototype.isPrintableCharacter = function(str) {
+ return str.length === 1 && str.match(/\S/);
+};
+
+MenubarNavigation.prototype.getIdFromAriaLabel = function(node) {
+ var id = node.getAttribute('aria-label')
+ if (id) {
+ id = id.trim().toLowerCase().replace(' ', '-').replace('/', '-');
+ }
+ return id;
+};
+
+
+MenubarNavigation.prototype.getMenuOrientation = function(node) {
+
+ var orientation = node.getAttribute('aria-orientation');
+
+ if (!orientation) {
+ var role = node.getAttribute('role');
+
+ switch (role) {
+ case 'menubar':
+ orientation = 'horizontal';
+ break;
+
+ case 'menu':
+ orientation = 'vertical';
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return orientation;
+};
+
+MenubarNavigation.prototype.getMenuId = function(node) {
+
+ var id = false;
+ var role = node.getAttribute('role');
+
+ while (node && (role !== 'menu') && (role !== 'menubar')) {
+ node = node.parentNode;
+ if (node) {
+ role = node.getAttribute('role');
+ }
+ }
+
+ if (node) {
+ id = role + '-' + this.getIdFromAriaLabel(node);
+ }
+
+ return id;
+};
+
+MenubarNavigation.prototype.getMenu = function(menuitem) {
+
+ var id = false;
+ var menu = menuitem;
+ var role = menuitem.getAttribute('role');
+
+ while (menu && (role !== 'menu') && (role !== 'menubar')) {
+ menu = menu.parentNode
+ if (menu) {
+ role = menu.getAttribute('role');
+ }
+ }
+
+ return menu;
+};
+
+// Popup menu methods
+
+MenubarNavigation.prototype.isAnyPopupOpen = function () {
+ for (var i = 0; i < this.popups.length; i++) {
+ if (this.popups[i].getAttribute('aria-expanded') === 'true') {
+ return true;
+ }
+ }
+ return false;
+};
+
+MenubarNavigation.prototype.openPopup = function (menuId, menuitem) {
+
+ // set aria-expanded attribute
+ var popupMenu = menuitem.nextElementSibling;
+
+ var rect = menuitem.getBoundingClientRect();
+
+ // Set CSS properties
+ if (this.isPopup[menuId]) {
+ popupMenu.parentNode.style.position = 'relative';
+ popupMenu.style.display = 'block';
+ popupMenu.style.position = 'absolute';
+ popupMenu.style.left = (rect.width + 6) + 'px';
+ popupMenu.style.top = '0px';
+ popupMenu.style.zIndex = 100;
+ }
+ else {
+ popupMenu.style.display = 'block';
+ popupMenu.style.position = 'absolute';
+ popupMenu.style.left = '0px';
+ popupMenu.style.top = (rect.height + 8)+ 'px';
+ popupMenu.style.zIndex = 100;
+ }
+
+ menuitem.setAttribute('aria-expanded', 'true');
+
+ return this.getMenuId(popupMenu);
+
+};
+
+MenubarNavigation.prototype.closePopout = function (menuitem) {
+ var menu,
+ menuId = this.getMenuId(menuitem),
+ cmi = menuitem;
+
+ while (this.isPopup[menuId] || this.isPopout[menuId]) {
+ menu = this.getMenu(cmi);
+ cmi = menu.previousElementSibling;
+ menuId = this.getMenuId(cmi);
+ cmi.setAttribute('aria-expanded', 'false');
+ menu.style.display = 'none';
+ }
+ cmi.focus();
+ return cmi;
+};
+
+MenubarNavigation.prototype.closePopup = function (menuitem) {
+ var menu,
+ menuId = this.getMenuId(menuitem),
+ cmi = menuitem;
+
+ if (this.isMenubar(menuId)) {
+ if (this.isOpen(menuitem)) {
+ menuitem.setAttribute('aria-expanded', 'false');
+ menuitem.nextElementSibling.style.display = 'none';
+ }
+ }
+ else {
+ menu = this.getMenu(menuitem);
+ cmi = menu.previousElementSibling;
+ cmi.setAttribute('aria-expanded', 'false');
+ cmi.focus();
+ menu.style.display = 'none';
+ }
+
+ return cmi;
+};
+
+MenubarNavigation.prototype.doesNotContain = function (popup, menuitem) {
+ if (menuitem) {
+ return !popup.nextElementSibling.contains(menuitem);
+ }
+ return true;
+};
+
+MenubarNavigation.prototype.closePopupAll = function (menuitem) {
+ if (typeof menuitem !== 'object') {
+ menuitem = false;
+ }
+ for (var i = 0; i < this.popups.length; i++) {
+ var popup = this.popups[i];
+ if (this.doesNotContain(popup, menuitem) && this.isOpen(popup)) {
+ var cmi = popup.nextElementSibling;
+ if (cmi) {
+ popup.setAttribute('aria-expanded', 'false');
+ cmi.style.display = 'none';
+ }
+ }
+ }
+};
+
+MenubarNavigation.prototype.hasPopup = function (menuitem) {
+ return menuitem.getAttribute('aria-haspopup') === 'true';
+};
+
+MenubarNavigation.prototype.isOpen = function (menuitem) {
+ return menuitem.getAttribute('aria-expanded') === 'true';
+};
+
+MenubarNavigation.prototype.isMenubar = function (menuId) {
+ return !this.isPopup[menuId] && !this.isPopout[menuId];
+};
+
+MenubarNavigation.prototype.isMenuHorizontal = function (menuitem) {
+ return this.menuOrientation[menuitem] === 'horizontal';
+};
+
+MenubarNavigation.prototype.hasFocus = function () {
+ return this.domNode.classList.contains('focus');
+};
+
+// Menu event handlers
+
+MenubarNavigation.prototype.handleMenubarFocusin = function (event) {
+ // if the menubar or any of its menus has focus, add styling hook for hover
+ this.domNode.classList.add('focus');
+};
+
+MenubarNavigation.prototype.handleMenubarFocusout = function (event) {
+ // remove styling hook for hover on menubar item
+ this.domNode.classList.remove('focus');
+};
+
+MenubarNavigation.prototype.handleKeydown = function (event) {
+ var tgt = event.currentTarget,
+ key = event.key,
+ flag = false,
+ menuId = this.getMenuId(tgt),
+ id,
+ popupMenuId,
+ mi,
+ role,
+ option,
+ value;
+
+ var isAnyPopupOpen = this.isAnyPopupOpen();
+
+ switch (key) {
+ case ' ':
+ case 'Enter':
+ if (this.hasPopup(tgt)) {
+ this.openPopups = true;
+ popupMenuId = this.openPopup(menuId, tgt);
+ this.setFocusToFirstMenuitem(popupMenuId);
+ }
+ else {
+ if (tgt.href !== '#') {
+ this.closePopupAll();
+ window.location.href=tgt.href;
+ }
+ }
+ flag = true;
+ break;
+
+ case 'Esc':
+ case 'Escape':
+ this.openPopups = false;
+ this.closePopup(tgt);
+ flag = true;
+ break;
+
+ case 'Up':
+ case 'ArrowUp':
+ if (this.isMenuHorizontal(menuId)) {
+ if (this.hasPopup(tgt)) {
+ this.openPopups = true;
+ popupMenuId = this.openPopup(menuId, tgt);
+ this.setFocusToLastMenuitem(popupMenuId);
+ }
+ }
+ else {
+ this.setFocusToPreviousMenuitem(menuId, tgt);
+ }
+ flag = true;
+ break;
+
+ case 'ArrowDown':
+ case 'Down':
+ if (this.isMenuHorizontal(menuId)) {
+ if (this.hasPopup(tgt)) {
+ this.openPopups = true;
+ popupMenuId = this.openPopup(menuId, tgt);
+ this.setFocusToFirstMenuitem(popupMenuId);
+ }
+ }
+ else {
+ this.setFocusToNextMenuitem(menuId, tgt);
+ }
+ flag = true;
+ break;
+
+ case 'Left':
+ case 'ArrowLeft':
+ if (this.isMenuHorizontal(menuId)) {
+ mi = this.setFocusToPreviousMenuitem(menuId, tgt);
+ if (isAnyPopupOpen) {
+ this.openPopup(menuId, mi);
+ }
+ }
+ else {
+ if (this.isPopout[menuId]) {
+ mi = this.closePopup(tgt);
+ id = this.getMenuId(mi);
+ mi = this.setFocusToMenuitem(id, mi);
+ }
+ else {
+ mi = this.closePopup(tgt);
+ id = this.getMenuId(mi);
+ mi = this.setFocusToPreviousMenuitem(id, mi);
+ this.openPopup(id, mi);
+ }
+ }
+ flag = true;
+ break;
+
+ case 'Right':
+ case 'ArrowRight':
+ if (this.isMenuHorizontal(menuId)) {
+ mi = this.setFocusToNextMenuitem(menuId, tgt);
+ if (isAnyPopupOpen) {
+ this.openPopup(menuId, mi);
+ }
+ }
+ else {
+ if (this.hasPopup(tgt)) {
+ popupMenuId = this.openPopup(menuId, tgt);
+ this.setFocusToFirstMenuitem(popupMenuId);
+ }
+ else {
+ mi = this.closePopout(tgt);
+ id = this.getMenuId(mi);
+ mi = this.setFocusToNextMenuitem(id, mi);
+ this.openPopup(id, mi);
+ }
+ }
+ flag = true;
+ break;
+
+ case 'Home':
+ case 'PageUp':
+ this.setFocusToFirstMenuitem(menuId, tgt);
+ flag = true;
+ break;
+
+ case 'End':
+ case 'PageDown':
+ this.setFocusToLastMenuitem(menuId, tgt);
+ flag = true;
+ break;
+
+ case 'Tab':
+ this.openPopups = false;
+ this.closePopup(tgt);
+ break;
+
+ default:
+ if (this.isPrintableCharacter(key)) {
+ this.setFocusByFirstCharacter(menuId, tgt, key);
+ flag = true;
+ }
+ break;
+ }
+
+ if (flag) {
+ event.stopPropagation();
+ event.preventDefault();
+ }
+};
+
+MenubarNavigation.prototype.handleMenuitemClick = function (event) {
+ var tgt = event.currentTarget;
+ var menuId = this.getMenuId(tgt);
+
+ if (this.hasPopup(tgt)) {
+ if (this.isOpen(tgt)) {
+ this.closePopup(tgt);
+ }
+ else {
+ this.closePopupAll(tgt);
+ this.openPopup(menuId, tgt);
+ }
+ event.stopPropagation();
+ event.preventDefault();
+ }
+};
+
+MenubarNavigation.prototype.handleMenuitemMouseover = function (event) {
+ var tgt = event.currentTarget;
+ var menuId = this.getMenuId(tgt);
+
+ if (this.hasFocus()) {
+ this.setFocusToMenuitem(menuId, tgt);
+ }
+
+ if (this.isAnyPopupOpen() || this.hasFocus()) {
+ this.closePopupAll(tgt);
+ if (this.hasPopup(tgt)) {
+ this.openPopup(menuId, tgt);
+ }
+ }
+};
+
+MenubarNavigation.prototype.handleBackgroundMousedown = function (event) {
+ if (!this.domNode.contains(event.target)) {
+ this.closePopupAll();
+ }
+};
+
+// Initialize menubar editor
+
+window.addEventListener('load', function () {
+ var menubarNavs = document.querySelectorAll('.menubar-navigation');
+ for(var i=0; i < menubarNavs.length; i++) {
+ var menubarNav = new MenubarNavigation(menubarNavs[i]);
+ }
+});
diff --git a/examples/menubar/mb-about.html b/examples/menubar/mb-about.html
new file mode 100644
index 0000000000..4ba20cae85
--- /dev/null
+++ b/examples/menubar/mb-about.html
@@ -0,0 +1,32 @@
+
+
+
+ Menubar Example Landing Page: About
+
+
+
+
+
+
+ Menubar Example Landing Page
+
+
+ About
+ Back to menubar
example
+
+
Overview
+ Back to menubar
example
+
+
Administration
+ Back to menubar
example
+
+
Facts
+ Back to menubar
example
+
+
Campus Tours
+ Back to menubar
example
+
+
+
+
+
diff --git a/examples/menubar/mb-academics.html b/examples/menubar/mb-academics.html
new file mode 100644
index 0000000000..6befba7337
--- /dev/null
+++ b/examples/menubar/mb-academics.html
@@ -0,0 +1,52 @@
+
+
+
+ Menubar Example Landing Page: Academics
+
+
+
+
+
+
+ Menubar Example Landing Page
+
+
+
+ Academics
+ Back to menubar
example
+
+
Colleges & Schools
+ Back to menubar
example
+
+
+
Programs of Study
+ Back to menubar
example
+
+
+
Honors Programs
+ Back to menubar
example
+
+
+
Online Courses
+ Back to menubar
example
+
+
+
Course Explorer
+ Back to menubar
example
+
+
+
Register for Class
+ Back to menubar
example
+
+
+
Academic Calendar
+ Back to menubar
example
+
+
+
Transcripts
+ Back to menubar
example
+
+
+
+
+
diff --git a/examples/menubar/mb-admissions.html b/examples/menubar/mb-admissions.html
new file mode 100644
index 0000000000..9c7cba1aec
--- /dev/null
+++ b/examples/menubar/mb-admissions.html
@@ -0,0 +1,39 @@
+
+
+
+ Menubar Example Landing Page: Admissions
+
+
+
+
+
+
+ Menubar Example Landing Page
+
+
+ Admissions
+ Back to menubar
example
+
+
Apply
+ Back to menubar
example
+
+
Tuition
+ Back to menubar
example
+
+
Sign Up
+ Back to menubar
example
+
+
Visit
+ Back to menubar
example
+
+
Photo Tour
+ Back to menubar
example
+
+
Connect
+ Back to menubar
example
+
+
+
+
+
+
diff --git a/examples/menubar/menubar-1/css/menubarLinks.css b/examples/menubar/menubar-1/css/menubarLinks.css
deleted file mode 100644
index 7e7869e8ea..0000000000
--- a/examples/menubar/menubar-1/css/menubarLinks.css
+++ /dev/null
@@ -1,69 +0,0 @@
-ul[role="menubar"] {
- margin: 10px;
- padding: 10px;
- font-size: 110%;
- list-style: none;
- background-color: #eee;
-}
-
-ul[role="menubar"] [role="menuitem"],
-ul[role="menubar"] [role="separator"] {
- padding: 0.25em;
- background-color: #eee;
- border: 2px solid #eee;
-}
-
-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"]:hover,
-ul[role="menubar"] [role="separator"]:focus,
-ul[role="menubar"] [role="separator"]:hover {
- background-color: black;
- color: white;
-}
-
-ul[role="menubar"] a[role="menuitem"] {
- text-decoration: none;
- color: black;
-}
-
-ul[role="menubar"] li {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-ul[role="menubar"] > li {
- display: inline;
- position: relative;
-}
-
-ul[role="menubar"] > li > a::after {
- content: url('../images/down-arrow-brown.png');
- padding-left: 0.25em;
-}
-
-ul[role="menubar"] ul[role="menu"] {
- display: none;
- position: absolute;
- top: -2px;
- left: 0;
- margin: 0;
- padding: 0;
-}
-
-ul[role="menubar"] ul[role="menu"] li a {
- display: block;
- width: 10em;
-}
-
-ul[role="menubar"] ul[role="menu"] a[aria-haspopup="true"]::after {
- content: url('../images/right-arrow-brown.png');
- padding-right: 2em;
-}
diff --git a/examples/menubar/menubar-1/images/down-arrow-brown.png b/examples/menubar/menubar-1/images/down-arrow-brown.png
deleted file mode 100644
index fe3e38aa31..0000000000
Binary files a/examples/menubar/menubar-1/images/down-arrow-brown.png and /dev/null differ
diff --git a/examples/menubar/menubar-1/images/down-arrow-gray.png b/examples/menubar/menubar-1/images/down-arrow-gray.png
deleted file mode 100644
index f5d34f2e07..0000000000
Binary files a/examples/menubar/menubar-1/images/down-arrow-gray.png and /dev/null differ
diff --git a/examples/menubar/menubar-1/images/right-arrow-brown.png b/examples/menubar/menubar-1/images/right-arrow-brown.png
deleted file mode 100644
index 9808455aea..0000000000
Binary files a/examples/menubar/menubar-1/images/right-arrow-brown.png and /dev/null differ
diff --git a/examples/menubar/menubar-1/images/right-arrow-gray.png b/examples/menubar/menubar-1/images/right-arrow-gray.png
deleted file mode 100644
index b2fe4e3401..0000000000
Binary files a/examples/menubar/menubar-1/images/right-arrow-gray.png and /dev/null differ
diff --git a/examples/menubar/menubar-1/images/separator.paint b/examples/menubar/menubar-1/images/separator.paint
deleted file mode 100644
index 9e313a1cc1..0000000000
Binary files a/examples/menubar/menubar-1/images/separator.paint and /dev/null differ
diff --git a/examples/menubar/menubar-1/images/separator.png b/examples/menubar/menubar-1/images/separator.png
deleted file mode 100644
index a837fbce93..0000000000
Binary files a/examples/menubar/menubar-1/images/separator.png and /dev/null differ
diff --git a/examples/menubar/menubar-1/js/MenubarItemLinks.js b/examples/menubar/menubar-1/js/MenubarItemLinks.js
deleted file mode 100644
index 091c44df7c..0000000000
--- a/examples/menubar/menubar-1/js/MenubarItemLinks.js
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
-* This content is licensed according to the W3C Software License at
-* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
-*/
-
-'use strict';
-
-var MenubarItem = function (domNode, menuObj) {
-
- this.menu = menuObj;
- this.domNode = domNode;
- this.popupMenu = false;
-
- this.hasFocus = false;
- this.hasHover = false;
-
- this.isMenubarItem = true;
-
- 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
- });
-};
-
-MenubarItem.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('focus', this.handleFocus.bind(this));
- this.domNode.addEventListener('blur', this.handleBlur.bind(this));
- this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this));
- this.domNode.addEventListener('mouseout', this.handleMouseout.bind(this));
-
- // Initialize pop up menus
-
- var nextElement = this.domNode.nextElementSibling;
-
- if (nextElement && nextElement.tagName === 'UL') {
- this.popupMenu = new PopupMenu(nextElement, this);
- this.popupMenu.init();
- }
-
-};
-
-MenubarItem.prototype.handleKeydown = function (event) {
- var tgt = event.currentTarget,
- char = event.key,
- flag = false,
- clickEvent;
-
- 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.LEFT:
- this.menu.setFocusToPreviousItem(this);
- flag = true;
- break;
-
- case this.keyCode.RIGHT:
- this.menu.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.menu.setFocusToFirstItem();
- flag = true;
- break;
-
- case this.keyCode.END:
- case this.keyCode.PAGEDOWN:
- this.menu.setFocusToLastItem();
- flag = true;
- break;
-
- case this.keyCode.TAB:
- this.popupMenu.close(true);
- break;
-
- case this.keyCode.ESC:
- this.popupMenu.close(true);
- break;
-
- default:
- if (isPrintableCharacter(char)) {
- this.menu.setFocusByFirstCharacter(this, char);
- flag = true;
- }
- break;
- }
-
- if (flag) {
- event.stopPropagation();
- event.preventDefault();
- }
-};
-
-MenubarItem.prototype.handleClick = function (event) {
- if (this.popupMenu) {
- // for menuitem with menu, prevent default anchor behavior on click
- // (which jumps to top of page for href="#" in some browsers)
- event.preventDefault();
- }
-};
-
-MenubarItem.prototype.setExpanded = function (value) {
- if (value) {
- this.domNode.setAttribute('aria-expanded', 'true');
- }
- else {
- this.domNode.setAttribute('aria-expanded', 'false');
- }
-};
-
-MenubarItem.prototype.handleFocus = function (event) {
- this.menu.hasFocus = true;
-};
-
-MenubarItem.prototype.handleBlur = function (event) {
- this.menu.hasFocus = false;
-};
-
-MenubarItem.prototype.handleMouseover = function (event) {
- this.hasHover = true;
- this.popupMenu.open();
-};
-
-MenubarItem.prototype.handleMouseout = function (event) {
- this.hasHover = false;
- setTimeout(this.popupMenu.close.bind(this.popupMenu, false), 300);
-};
diff --git a/examples/menubar/menubar-1/js/MenubarLinks.js b/examples/menubar/menubar-1/js/MenubarLinks.js
deleted file mode 100644
index ef5e68ee01..0000000000
--- a/examples/menubar/menubar-1/js/MenubarLinks.js
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
-* This content is licensed according to the W3C Software License at
-* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
-*/
-
-'use strict';
-
-var Menubar = function (domNode) {
- var elementChildren,
- msgPrefix = 'Menubar constructor argument menubarNode ';
-
- // Check whether menubarNode is a DOM element
- if (!(domNode instanceof Element)) {
- throw new TypeError(msgPrefix + 'is not a DOM Element.');
- }
-
- // Check whether menubarNode has descendant elements
- if (domNode.childElementCount === 0) {
- throw new Error(msgPrefix + 'has no element children.');
- }
-
- // Check whether menubarNode has A elements
- var e = domNode.firstElementChild;
- while (e) {
- var menubarItem = e.firstElementChild;
- if (e && menubarItem && menubarItem.tagName !== 'A') {
- throw new Error(msgPrefix + 'has child elements are not A elements.');
- }
- e = e.nextElementSibling;
- }
-
- this.isMenubar = true;
-
- 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
-
- this.hasFocus = false; // See MenubarItem handleFocus, handleBlur
- this.hasHover = false; // See Menubar handleMouseover, handleMouseout
-};
-
-/*
-* @method Menubar.prototype.init
-*
-* @desc
-* Adds ARIA role to the menubar node
-* Traverse menubar children for A elements to configure each A element as a ARIA menuitem
-* and populate menuitems array. Initialize firstItem and lastItem properties.
-*/
-Menubar.prototype.init = function () {
- var menubarItem, childElement, menuElement, textContent, numItems;
-
-
- // Traverse the element children of menubarNode: configure each with
- // menuitem role behavior and store reference in menuitems array.
- var elem = this.domNode.firstElementChild;
-
- while (elem) {
- menuElement = elem.firstElementChild;
-
- if (elem && menuElement && menuElement.tagName === 'A') {
- menubarItem = new MenubarItem(menuElement, this);
- menubarItem.init();
- this.menubarItems.push(menubarItem);
- textContent = menuElement.textContent.trim();
- this.firstChars.push(textContent.substring(0, 1).toLowerCase());
- }
-
- elem = elem.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 */
-
-Menubar.prototype.setFocusToItem = function (newItem) {
- var flag = false;
-
- for (var i = 0; i < this.menubarItems.length; i++) {
- var mbi = this.menubarItems[i];
-
- if (mbi.domNode.tabIndex == 0) {
- flag = mbi.domNode.getAttribute('aria-expanded') === 'true';
- }
-
- mbi.domNode.tabIndex = -1;
- if (mbi.popupMenu) {
- mbi.popupMenu.close();
- }
- }
-
- newItem.domNode.focus();
- newItem.domNode.tabIndex = 0;
-
- if (flag && newItem.popupMenu) {
- newItem.popupMenu.open();
- }
-};
-
-Menubar.prototype.setFocusToFirstItem = function (flag) {
- this.setFocusToItem(this.firstItem);
-};
-
-Menubar.prototype.setFocusToLastItem = function (flag) {
- this.setFocusToItem(this.lastItem);
-};
-
-Menubar.prototype.setFocusToPreviousItem = function (currentItem) {
- var index, newItem;
-
- if (currentItem === this.firstItem) {
- newItem = this.lastItem;
- }
- else {
- index = this.menubarItems.indexOf(currentItem);
- newItem = this.menubarItems[ index - 1 ];
- }
-
- this.setFocusToItem(newItem);
-
-};
-
-Menubar.prototype.setFocusToNextItem = function (currentItem) {
- var index, newItem;
-
- if (currentItem === this.lastItem) {
- newItem = this.firstItem;
- }
- else {
- index = this.menubarItems.indexOf(currentItem);
- newItem = this.menubarItems[ index + 1 ];
- }
-
- this.setFocusToItem(newItem);
-
-};
-
-Menubar.prototype.setFocusByFirstCharacter = function (currentItem, char) {
- var start, index;
- var flag = currentItem.domNode.getAttribute('aria-expanded') === 'true';
-
- 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.setFocusToItem(this.menubarItems[ index ]);
- }
-};
-
-Menubar.prototype.getIndexFirstChars = function (startIndex, char) {
- for (var i = startIndex; i < this.firstChars.length; i++) {
- if (char === this.firstChars[ i ]) {
- return i;
- }
- }
- return -1;
-};
-
diff --git a/examples/menubar/menubar-1/js/PopupMenuItemLinks.js b/examples/menubar/menubar-1/js/PopupMenuItemLinks.js
deleted file mode 100644
index 2e9e661580..0000000000
--- a/examples/menubar/menubar-1/js/PopupMenuItemLinks.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
-*/
-
-'use strict';
-
-var MenuItem = function (domNode, menuObj) {
-
- if (typeof menuObj !== 'object') {
- menuObj = false;
- }
-
- this.domNode = domNode;
- this.menu = menuObj;
- this.popupMenu = false;
- this.isMenubarItem = 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
- });
-};
-
-MenuItem.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('focus', this.handleFocus.bind(this));
- this.domNode.addEventListener('blur', this.handleBlur.bind(this));
- this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this));
- this.domNode.addEventListener('mouseout', this.handleMouseout.bind(this));
-
- // Initialize flyout menu
-
- var nextElement = this.domNode.nextElementSibling;
-
- if (nextElement && nextElement.tagName === 'UL') {
- this.popupMenu = new PopupMenu(nextElement, this);
- this.popupMenu.init();
- }
-
-};
-
-MenuItem.prototype.isExpanded = function () {
- return this.domNode.getAttribute('aria-expanded') === 'true';
-};
-
-/* EVENT HANDLERS */
-
-MenuItem.prototype.handleKeydown = function (event) {
- var tgt = event.currentTarget,
- char = event.key,
- flag = false,
- clickEvent;
-
- function isPrintableCharacter (str) {
- return str.length === 1 && str.match(/\S/);
- }
-
- switch (event.keyCode) {
- case this.keyCode.SPACE:
- case this.keyCode.RETURN:
- if (this.popupMenu) {
- this.popupMenu.open();
- this.popupMenu.setFocusToFirstItem();
- }
- else {
-
- // Create simulated mouse event to mimic the behavior of ATs
- // and let the event handler handleClick do the housekeeping.
- try {
- clickEvent = new MouseEvent('click', {
- 'view': window,
- 'bubbles': true,
- 'cancelable': true
- });
- }
- catch (err) {
- if (document.createEvent) {
- // DOM Level 3 for IE 9+
- clickEvent = document.createEvent('MouseEvents');
- clickEvent.initEvent('click', true, true);
- }
- }
- tgt.dispatchEvent(clickEvent);
- }
-
- 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', true);
- this.menu.close(true);
- flag = true;
- break;
-
- case this.keyCode.RIGHT:
- if (this.popupMenu) {
- this.popupMenu.open();
- this.popupMenu.setFocusToFirstItem();
- }
- else {
- this.menu.setFocusToController('next', true);
- this.menu.close(true);
- }
- 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.ESC:
- this.menu.setFocusToController();
- this.menu.close(true);
- flag = true;
- break;
-
- case this.keyCode.TAB:
- this.menu.setFocusToController();
- break;
-
- default:
- if (isPrintableCharacter(char)) {
- this.menu.setFocusByFirstCharacter(this, char);
- flag = true;
- }
- break;
- }
-
- if (flag) {
- event.stopPropagation();
- event.preventDefault();
- }
-};
-
-MenuItem.prototype.setExpanded = function (value) {
- if (value) {
- this.domNode.setAttribute('aria-expanded', 'true');
- }
- else {
- this.domNode.setAttribute('aria-expanded', 'false');
- }
-};
-
-MenuItem.prototype.handleClick = function (event) {
- this.menu.setFocusToController();
- this.menu.close(true);
- if (this.popupMenu) {
- // for menuitem with menu, prevent default anchor behavior on click
- // (which jumps to top of page for href="#" in some browsers)
- event.preventDefault();
- }
-};
-
-MenuItem.prototype.handleFocus = function (event) {
- this.menu.hasFocus = true;
-};
-
-MenuItem.prototype.handleBlur = function (event) {
- this.menu.hasFocus = false;
- setTimeout(this.menu.close.bind(this.menu, false), 300);
-};
-
-MenuItem.prototype.handleMouseover = function (event) {
- this.menu.hasHover = true;
- this.menu.open();
- if (this.popupMenu) {
- this.popupMenu.hasHover = true;
- this.popupMenu.open();
- }
-};
-
-MenuItem.prototype.handleMouseout = function (event) {
- if (this.popupMenu) {
- this.popupMenu.hasHover = false;
- this.popupMenu.close(true);
- }
-
- this.menu.hasHover = false;
- setTimeout(this.menu.close.bind(this.menu, false), 300);
-};
diff --git a/examples/menubar/menubar-1/js/PopupMenuLinks.js b/examples/menubar/menubar-1/js/PopupMenuLinks.js
deleted file mode 100644
index d0edfd6404..0000000000
--- a/examples/menubar/menubar-1/js/PopupMenuLinks.js
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
-* This content is licensed according to the W3C Software License at
-* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
-*/
-
-'use strict';
-
-var PopupMenu = function (domNode, controllerObj) {
- 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.');
- }
- // Check whether domNode descendant elements have A elements
- var childElement = domNode.firstElementChild;
- while (childElement) {
- var menuitem = childElement.firstElementChild;
- if (menuitem && menuitem === 'A') {
- throw new Error(msgPrefix + 'has descendant elements that are not A elements.');
- }
- childElement = childElement.nextElementSibling;
- }
-
- this.isMenubar = false;
-
- this.domNode = domNode;
- this.controller = controllerObj;
-
- 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
-
- this.hasFocus = false; // See MenuItem handleFocus, handleBlur
- this.hasHover = false; // See PopupMenu handleMouseover, handleMouseout
-};
-
-/*
-* @method PopupMenu.prototype.init
-*
-* @desc
-* Add domNode event listeners for mouseover and mouseout. Traverse
-* domNode children to configure each menuitem and populate menuitems
-* array. Initialize firstItem and lastItem properties.
-*/
-PopupMenu.prototype.init = function () {
- var childElement, menuElement, menuItem, textContent, numItems, label;
-
- // Configure the domNode itself
-
- this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this));
- this.domNode.addEventListener('mouseout', this.handleMouseout.bind(this));
-
- // Traverse the element children of domNode: configure each with
- // menuitem role behavior and store reference in menuitems array.
- childElement = this.domNode.firstElementChild;
-
- while (childElement) {
- menuElement = childElement.firstElementChild;
-
- if (menuElement && menuElement.tagName === 'A') {
- menuItem = new MenuItem(menuElement, this);
- menuItem.init();
- this.menuitems.push(menuItem);
- textContent = menuElement.textContent.trim();
- this.firstChars.push(textContent.substring(0, 1).toLowerCase());
- }
- childElement = childElement.nextElementSibling;
- }
-
- // 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 ];
- }
-};
-
-/* EVENT HANDLERS */
-
-PopupMenu.prototype.handleMouseover = function (event) {
- this.hasHover = true;
-};
-
-PopupMenu.prototype.handleMouseout = function (event) {
- this.hasHover = false;
- setTimeout(this.close.bind(this, false), 1);
-};
-
-/* FOCUS MANAGEMENT METHODS */
-
-PopupMenu.prototype.setFocusToController = function (command, flag) {
-
- if (typeof command !== 'string') {
- command = '';
- }
-
- function setFocusToMenubarItem (controller, close) {
- while (controller) {
- if (controller.isMenubarItem) {
- controller.domNode.focus();
- return controller;
- }
- else {
- if (close) {
- controller.menu.close(true);
- }
- controller.hasFocus = false;
- }
- controller = controller.menu.controller;
- }
- return false;
- }
-
- if (command === '') {
- if (this.controller && this.controller.domNode) {
- this.controller.domNode.focus();
- }
- return;
- }
-
- if (!this.controller.isMenubarItem) {
- this.controller.domNode.focus();
- this.close();
-
- if (command === 'next') {
- var menubarItem = setFocusToMenubarItem(this.controller, false);
- if (menubarItem) {
- menubarItem.menu.setFocusToNextItem(menubarItem, flag);
- }
- }
- }
- else {
- if (command === 'previous') {
- this.controller.menu.setFocusToPreviousItem(this.controller, flag);
- }
- else if (command === 'next') {
- this.controller.menu.setFocusToNextItem(this.controller, flag);
- }
- }
-
-};
-
-PopupMenu.prototype.setFocusToFirstItem = function () {
- this.firstItem.domNode.focus();
-};
-
-PopupMenu.prototype.setFocusToLastItem = function () {
- this.lastItem.domNode.focus();
-};
-
-PopupMenu.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();
- }
-};
-
-PopupMenu.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();
- }
-};
-
-PopupMenu.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();
- }
-};
-
-PopupMenu.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 */
-
-PopupMenu.prototype.open = function () {
- // Get position and bounding rectangle of controller object's DOM node
- var rect = this.controller.domNode.getBoundingClientRect();
-
- // Set CSS properties
- if (!this.controller.isMenubarItem) {
- this.domNode.parentNode.style.position = 'relative';
- this.domNode.style.display = 'block';
- this.domNode.style.position = 'absolute';
- this.domNode.style.left = rect.width + 'px';
- this.domNode.style.zIndex = 100;
- }
- else {
- this.domNode.style.display = 'block';
- this.domNode.style.position = 'absolute';
- this.domNode.style.top = (rect.height - 1) + 'px';
- this.domNode.style.zIndex = 100;
- }
-
- this.controller.setExpanded(true);
-
-};
-
-PopupMenu.prototype.close = function (force) {
-
- var controllerHasHover = this.controller.hasHover;
-
- var hasFocus = this.hasFocus;
-
- for (var i = 0; i < this.menuitems.length; i++) {
- var mi = this.menuitems[i];
- if (mi.popupMenu) {
- hasFocus = hasFocus | mi.popupMenu.hasFocus;
- }
- }
-
- if (!this.controller.isMenubarItem) {
- controllerHasHover = false;
- }
-
- if (force || (!hasFocus && !this.hasHover && !controllerHasHover)) {
- this.domNode.style.display = 'none';
- this.domNode.style.zIndex = 0;
- this.controller.setExpanded(false);
- }
-};
diff --git a/examples/menubar/menubar-1/mb-about.html b/examples/menubar/menubar-1/mb-about.html
deleted file mode 100644
index c8a2d369cb..0000000000
--- a/examples/menubar/menubar-1/mb-about.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
- Menubar Example Landing Page: About
-
-
-
-
-
-
- Menubar Example Landing Page
-
-
- About
- Back to menubar
example
-
-
Overview
- Back to menubar
example
-
-
Administration
- Back to menubar
example
-
-
Facts
- Back to menubar
example
-
-
Campus Tours
- Back to menubar
example
-
-
-
-
-
diff --git a/examples/menubar/menubar-1/mb-academics.html b/examples/menubar/menubar-1/mb-academics.html
deleted file mode 100644
index c0a80d69d0..0000000000
--- a/examples/menubar/menubar-1/mb-academics.html
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
- Menubar Example Landing Page: Academics
-
-
-
-
-
-
- Menubar Example Landing Page
-
-
-
- Academics
- Back to menubar
example
-
-
Colleges & Schools
- Back to menubar
example
-
-
-
Programs of Study
- Back to menubar
example
-
-
-
Honors Programs
- Back to menubar
example
-
-
-
Online Courses
- Back to menubar
example
-
-
-
Course Explorer
- Back to menubar
example
-
-
-
Register for Class
- Back to menubar
example
-
-
-
Academic Calendar
- Back to menubar
example
-
-
-
Transcripts
- Back to menubar
example
-
-
-
-
-
diff --git a/examples/menubar/menubar-1/mb-admissions.html b/examples/menubar/menubar-1/mb-admissions.html
deleted file mode 100644
index b2805416c6..0000000000
--- a/examples/menubar/menubar-1/mb-admissions.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
- Menubar Example Landing Page: Admissions
-
-
-
-
-
-
- Menubar Example Landing Page
-
-
- Admissions
- Back to menubar
example
-
-
Apply
- Back to menubar
example
-
-
Tuition
- Back to menubar
example
-
-
Sign Up
- Back to menubar
example
-
-
Visit
- Back to menubar
example
-
-
Photo Tour
- Back to menubar
example
-
-
Connect
- Back to menubar
example
-
-
-
-
-
-
\ No newline at end of file
diff --git a/examples/menubar/menubar-editor.html b/examples/menubar/menubar-editor.html
index 8414e8efc8..563f2e688e 100644
--- a/examples/menubar/menubar-editor.html
+++ b/examples/menubar/menubar-editor.html
@@ -46,7 +46,7 @@ Editor Menubar Example
Similar examples include:
diff --git a/examples/menubar/menubar-1/menubar-1.html b/examples/menubar/menubar-navigation.html
similarity index 80%
rename from examples/menubar/menubar-1/menubar-1.html
rename to examples/menubar/menubar-navigation.html
index 9b72510beb..fb7f7024dc 100644
--- a/examples/menubar/menubar-1/menubar-1.html
+++ b/examples/menubar/menubar-navigation.html
@@ -1,55 +1,59 @@
-
-Navigation Menubar Example | WAI-ARIA Authoring Practices 1.2
+
+ Navigation Menubar Example | WAI-ARIA Authoring Practices 1.2
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
Navigation Menubar Example
The following implementation of the
- design pattern for menubar
+ design pattern for menubar
demonstrates a menubar that provides site navigation menus.
Each item in the menubar represents a section of a web site for a mythical university and opens a submenu containing menu items that link to pages within that section.
Similar examples include:
-
+
@@ -168,8 +199,14 @@ Example
Accessibility Features
+ To help communicate that the arrow keys are available for directional navigation within the menubar and its submenus, a border is added to the menubar container when focus is within the menubar.
+ To support operating system high contrast settings:
+
+ Focus is highlighted by adding and removing a border around the menu item with focus.
+ The arrow icons indicating the current state of expandable menus use in-line SVG images with the CSS currentColor
value for the fill
and stroke
properties of the polygon
element.
+
+
Since the menubar presents a site navigation system, it is wrapped in a navigation region implemented with a nav
element that has an aria-label
that matches the label on the menubar.
- The down arrow and right arrow icons are made compatible with high contrast mode and hidden from screen readers by using the CSS content
property to render images.
@@ -249,7 +286,8 @@ Menubar
-Submenu
+
+ Submenu
@@ -264,8 +302,8 @@ Submenu
- Activates menu item, causing the link to be activated.
- NOTE: the links go to dummy pages; use the browser go-back function to return to this menubar example page.
+ If the item is a parent menu item, opens submenu and moves focus to first item in the submenu.
+ Otherwise, activates menu item, which navigates to a dummy page. NOTE: use browser go-back function to return to this page.
@@ -617,22 +655,8 @@ Submenu
Javascript and CSS Source Code
@@ -652,7 +676,7 @@ HTML Source Code
- Menu or Menubar Design Pattern in WAI-ARIA Authoring Practices 1.2
+ Menu or Menubar Design Pattern in WAI-ARIA Authoring Practices 1.2