accessible-menu
Advanced tools
Comparing version 1.0.6 to 1.1.0
@@ -5,2 +5,25 @@ # Changelog | ||
## [1.1.0](https://github.com/NickDJM/accessible-menu/compare/v1.0.6...v1.1.0) (2020-03-09) | ||
### Features | ||
* add built-in ie11 support to cdn ([0fbba5b](https://github.com/NickDJM/accessible-menu/commit/0fbba5b6620ba6102938e17d08a06b183434b495)), closes [#58](https://github.com/NickDJM/accessible-menu/issues/58) | ||
### Bug Fixes | ||
* **menu:** add handlers for enter/space in root level menus ([4b26192](https://github.com/NickDJM/accessible-menu/commit/4b26192e499b8fa8c97de9683a50b745f4406b07)), closes [#56](https://github.com/NickDJM/accessible-menu/issues/56) | ||
### Build System | ||
* **npm:** fix commitizen ([244e5b1](https://github.com/NickDJM/accessible-menu/commit/244e5b1d9b5a2c5ac9a802740be1ad76e94a6fc1)) | ||
### Documentation | ||
* **general:** add jsfiddle example for the library ([8304580](https://github.com/NickDJM/accessible-menu/commit/8304580fea306610580e1c81fa3cacc64168d82e)) | ||
* **general:** update description ([6427d56](https://github.com/NickDJM/accessible-menu/commit/6427d568c1a386593270a407bdcd1d7d86af9758)) | ||
### [1.0.6](https://github.com/NickDJM/accessible-menu/compare/v1.0.5...v1.0.6) (2020-02-26) | ||
@@ -7,0 +30,0 @@ |
@@ -1,12 +0,171 @@ | ||
"use strict"; | ||
var AccessibleMenu = (function () { | ||
'use strict'; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
// Production steps of ECMA-262, Edition 6, 22.1.2.1 | ||
if (!Array.from) { | ||
Array.from = function () { | ||
var toStr = Object.prototype.toString; | ||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } | ||
var isCallable = function isCallable(fn) { | ||
return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; | ||
}; | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
var toInteger = function toInteger(value) { | ||
var number = Number(value); | ||
var AccessibleMenu = function () { | ||
'use strict'; // Custom validation for params. | ||
if (isNaN(number)) { | ||
return 0; | ||
} | ||
if (number === 0 || !isFinite(number)) { | ||
return number; | ||
} | ||
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); | ||
}; | ||
var maxSafeInteger = Math.pow(2, 53) - 1; | ||
var toLength = function toLength(value) { | ||
var len = toInteger(value); | ||
return Math.min(Math.max(len, 0), maxSafeInteger); | ||
}; // The length property of the from method is 1. | ||
return function from(arrayLike | ||
/*, mapFn, thisArg */ | ||
) { | ||
// 1. Let C be the this value. | ||
var C = this; // 2. Let items be ToObject(arrayLike). | ||
var items = Object(arrayLike); // 3. ReturnIfAbrupt(items). | ||
if (arrayLike == null) { | ||
throw new TypeError('Array.from requires an array-like object - not null or undefined'); | ||
} // 4. If mapfn is undefined, then let mapping be false. | ||
var mapFn = arguments.length > 1 ? arguments[1] : void undefined; | ||
var T; | ||
if (typeof mapFn !== 'undefined') { | ||
// 5. else | ||
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception. | ||
if (!isCallable(mapFn)) { | ||
throw new TypeError('Array.from: when provided, the second argument must be a function'); | ||
} // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. | ||
if (arguments.length > 2) { | ||
T = arguments[2]; | ||
} | ||
} // 10. Let lenValue be Get(items, "length"). | ||
// 11. Let len be ToLength(lenValue). | ||
var len = toLength(items.length); // 13. If IsConstructor(C) is true, then | ||
// 13. a. Let A be the result of calling the [[Construct]] internal method | ||
// of C with an argument list containing the single item len. | ||
// 14. a. Else, Let A be ArrayCreate(len). | ||
var A = isCallable(C) ? Object(new C(len)) : new Array(len); // 16. Let k be 0. | ||
var k = 0; // 17. Repeat, while k < len… (also steps a - h) | ||
var kValue; | ||
while (k < len) { | ||
kValue = items[k]; | ||
if (mapFn) { | ||
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); | ||
} else { | ||
A[k] = kValue; | ||
} | ||
k += 1; | ||
} // 18. Let putStatus be Put(A, "length", len, true). | ||
A.length = len; // 20. Return A. | ||
return A; | ||
}; | ||
}(); | ||
} | ||
if (!Array.includes) { | ||
Array.prototype.includes = function (search) { | ||
return !!~this.indexOf(search); | ||
}; | ||
} | ||
// https://tc39.github.io/ecma262/#sec-array.prototype.find | ||
if (!Array.prototype.find) { | ||
Object.defineProperty(Array.prototype, 'find', { | ||
value: function value(predicate) { | ||
// 1. Let O be ? ToObject(this value). | ||
if (this == null) { | ||
throw TypeError('"this" is null or not defined'); | ||
} | ||
var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). | ||
var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception. | ||
if (typeof predicate !== 'function') { | ||
throw TypeError('predicate must be a function'); | ||
} // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. | ||
var thisArg = arguments[1]; // 5. Let k be 0. | ||
var k = 0; // 6. Repeat, while k < len | ||
while (k < len) { | ||
// a. Let Pk be ! ToString(k). | ||
// b. Let kValue be ? Get(O, Pk). | ||
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). | ||
// d. If testResult is true, return kValue. | ||
var kValue = o[k]; | ||
if (predicate.call(thisArg, kValue, k, o)) { | ||
return kValue; | ||
} // e. Increase k by 1. | ||
k++; | ||
} // 7. Return undefined. | ||
return undefined; | ||
}, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} | ||
function _classCallCheck(instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
} | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
} | ||
// Custom validation for params. | ||
var validate = { | ||
@@ -66,3 +225,2 @@ event: function event(value) { | ||
function preventEvent(event) { | ||
@@ -73,5 +231,4 @@ // Run validation. | ||
event.stopPropagation(); | ||
} // Basic validation for the class. | ||
} | ||
var validate$1 = { | ||
@@ -399,5 +556,4 @@ menuToggleElement: function menuToggleElement(element) { | ||
return MenuToggle; | ||
}(); // Basic validation for the class. | ||
}(); | ||
var validate$2 = { | ||
@@ -463,12 +619,12 @@ menuItemElement: function menuItemElement(element) { | ||
*/ | ||
function MenuItem(_ref2) { | ||
var menuItemElement = _ref2.menuItemElement, | ||
menuLinkElement = _ref2.menuLinkElement, | ||
parentMenu = _ref2.parentMenu, | ||
_ref2$isSubmenuItem = _ref2.isSubmenuItem, | ||
isSubmenuItem = _ref2$isSubmenuItem === void 0 ? false : _ref2$isSubmenuItem, | ||
_ref2$childMenu = _ref2.childMenu, | ||
childMenu = _ref2$childMenu === void 0 ? null : _ref2$childMenu, | ||
_ref2$toggle = _ref2.toggle, | ||
toggle = _ref2$toggle === void 0 ? null : _ref2$toggle; | ||
function MenuItem(_ref) { | ||
var menuItemElement = _ref.menuItemElement, | ||
menuLinkElement = _ref.menuLinkElement, | ||
parentMenu = _ref.parentMenu, | ||
_ref$isSubmenuItem = _ref.isSubmenuItem, | ||
isSubmenuItem = _ref$isSubmenuItem === void 0 ? false : _ref$isSubmenuItem, | ||
_ref$childMenu = _ref.childMenu, | ||
childMenu = _ref$childMenu === void 0 ? null : _ref$childMenu, | ||
_ref$toggle = _ref.toggle, | ||
toggle = _ref$toggle === void 0 ? null : _ref$toggle; | ||
@@ -603,5 +759,4 @@ _classCallCheck(this, MenuItem); | ||
return MenuItem; | ||
}(); // Basic validation for the class. | ||
}(); | ||
var validate$3 = { | ||
@@ -700,21 +855,21 @@ menuElement: function menuElement(element) { | ||
*/ | ||
function Menu(_ref3) { | ||
var menuElement = _ref3.menuElement, | ||
menuItemSelector = _ref3.menuItemSelector, | ||
_ref3$submenuItemSele = _ref3.submenuItemSelector, | ||
submenuItemSelector = _ref3$submenuItemSele === void 0 ? null : _ref3$submenuItemSele, | ||
_ref3$submenuToggleSe = _ref3.submenuToggleSelector, | ||
submenuToggleSelector = _ref3$submenuToggleSe === void 0 ? null : _ref3$submenuToggleSe, | ||
_ref3$submenuSelector = _ref3.submenuSelector, | ||
submenuSelector = _ref3$submenuSelector === void 0 ? null : _ref3$submenuSelector, | ||
_ref3$openClass = _ref3.openClass, | ||
openClass = _ref3$openClass === void 0 ? "show" : _ref3$openClass, | ||
_ref3$isTopLevel = _ref3.isTopLevel, | ||
isTopLevel = _ref3$isTopLevel === void 0 ? true : _ref3$isTopLevel, | ||
_ref3$controllerEleme = _ref3.controllerElement, | ||
controllerElement = _ref3$controllerEleme === void 0 ? null : _ref3$controllerEleme, | ||
_ref3$containerElemen = _ref3.containerElement, | ||
containerElement = _ref3$containerElemen === void 0 ? null : _ref3$containerElemen, | ||
_ref3$parentMenu = _ref3.parentMenu, | ||
parentMenu = _ref3$parentMenu === void 0 ? null : _ref3$parentMenu; | ||
function Menu(_ref) { | ||
var menuElement = _ref.menuElement, | ||
menuItemSelector = _ref.menuItemSelector, | ||
_ref$submenuItemSelec = _ref.submenuItemSelector, | ||
submenuItemSelector = _ref$submenuItemSelec === void 0 ? null : _ref$submenuItemSelec, | ||
_ref$submenuToggleSel = _ref.submenuToggleSelector, | ||
submenuToggleSelector = _ref$submenuToggleSel === void 0 ? null : _ref$submenuToggleSel, | ||
_ref$submenuSelector = _ref.submenuSelector, | ||
submenuSelector = _ref$submenuSelector === void 0 ? null : _ref$submenuSelector, | ||
_ref$openClass = _ref.openClass, | ||
openClass = _ref$openClass === void 0 ? "show" : _ref$openClass, | ||
_ref$isTopLevel = _ref.isTopLevel, | ||
isTopLevel = _ref$isTopLevel === void 0 ? true : _ref$isTopLevel, | ||
_ref$controllerElemen = _ref.controllerElement, | ||
controllerElement = _ref$controllerElemen === void 0 ? null : _ref$controllerElemen, | ||
_ref$containerElement = _ref.containerElement, | ||
containerElement = _ref$containerElement === void 0 ? null : _ref$containerElement, | ||
_ref$parentMenu = _ref.parentMenu, | ||
parentMenu = _ref$parentMenu === void 0 ? null : _ref$parentMenu; | ||
@@ -824,3 +979,3 @@ _classCallCheck(this, Menu); | ||
value: function createMenuItems() { | ||
var _this3 = this; | ||
var _this = this; | ||
@@ -830,17 +985,17 @@ this.menuItemElements.forEach(function (element) { | ||
if (_this3.submenuItemElements.includes(element)) { | ||
if (_this.submenuItemElements.includes(element)) { | ||
// The menu's toggle controller DOM element. | ||
var toggler = element.querySelector(_this3.selector["submenu-toggle"]); // The actual menu DOM element. | ||
var toggler = element.querySelector(_this.selector["submenu-toggle"]); // The actual menu DOM element. | ||
var submenu = element.querySelector(_this3.selector.submenu); // Create the new Menu and initialize it. | ||
var submenu = element.querySelector(_this.selector.submenu); // Create the new Menu and initialize it. | ||
var menu = new Menu({ | ||
menuElement: submenu, | ||
menuItemSelector: _this3.selector["menu-items"], | ||
submenuItemSelector: _this3.selector["submenu-items"], | ||
submenuToggleSelector: _this3.selector["submenu-toggle"], | ||
submenuSelector: _this3.selector.submenu, | ||
openClass: _this3.openClass, | ||
menuItemSelector: _this.selector["menu-items"], | ||
submenuItemSelector: _this.selector["submenu-items"], | ||
submenuToggleSelector: _this.selector["submenu-toggle"], | ||
submenuSelector: _this.selector.submenu, | ||
openClass: _this.openClass, | ||
isTopLevel: false, | ||
parentMenu: _this3 | ||
parentMenu: _this | ||
}); // Create the new MenuToggle. | ||
@@ -852,7 +1007,7 @@ | ||
menu: menu, | ||
openClass: _this3.openClass, | ||
parentMenu: _this3 | ||
openClass: _this.openClass, | ||
parentMenu: _this | ||
}); // Add it to the list of submenu items. | ||
_this3.elements.menuToggles.push(toggle); // Create a new MenuItem. | ||
_this.elements.menuToggles.push(toggle); // Create a new MenuItem. | ||
@@ -863,3 +1018,3 @@ | ||
menuLinkElement: toggler, | ||
parentMenu: _this3, | ||
parentMenu: _this, | ||
isSubmenuItem: true, | ||
@@ -875,7 +1030,7 @@ childMenu: menu, | ||
menuLinkElement: link, | ||
parentMenu: _this3 | ||
parentMenu: _this | ||
}); | ||
} | ||
_this3.elements.menuItems.push(menuItem); | ||
_this.elements.menuItems.push(menuItem); | ||
}); | ||
@@ -890,3 +1045,3 @@ } | ||
value: function handleFocus() { | ||
var _this4 = this; | ||
var _this2 = this; | ||
@@ -896,6 +1051,6 @@ this.menuItems.forEach(function (item) { | ||
item.linkElement.addEventListener("focusin", function () { | ||
if (_this4.currentFocus === "none") { | ||
_this4.currentFocus = "self"; | ||
if (_this2.currentFocus === "none") { | ||
_this2.currentFocus = "self"; | ||
_this4.focusCurrentChild(); | ||
_this2.focusCurrentChild(); | ||
} | ||
@@ -905,6 +1060,6 @@ }); // Set tabIndex for the current menuItem. | ||
item.linkElement.addEventListener("focusout", function () { | ||
if (_this4.currentFocus === "none") { | ||
_this4.blur(); | ||
if (_this2.currentFocus === "none") { | ||
_this2.blur(); | ||
_this4.closeChildren(); | ||
_this2.closeChildren(); | ||
} | ||
@@ -921,3 +1076,3 @@ }); | ||
value: function handleKeydown() { | ||
var _this5 = this; | ||
var _this3 = this; | ||
@@ -931,4 +1086,4 @@ this.element.addEventListener("keydown", function (event) { | ||
if (_this5.isTopLevel) { | ||
if (_this5.currentFocus === "none") { | ||
if (_this3.isTopLevel) { | ||
if (_this3.currentFocus === "none") { | ||
if (key === "Space" || key === "Enter") { | ||
@@ -938,8 +1093,14 @@ // Hitting Space or Enter: | ||
preventEvent(event); | ||
_this5.currentFocus = "self"; | ||
_this3.currentFocus = "self"; | ||
_this5.focusFirstChild(); | ||
_this3.focusFirstChild(); | ||
} | ||
} else if (_this5.currentFocus === "self") { | ||
if (key === "ArrowRight") { | ||
} else if (_this3.currentFocus === "self") { | ||
if (key === "Space" || key === "Enter") { | ||
// Hitting Space or Enter: | ||
// - Activates menu item, causing the link to be activated. | ||
preventEvent(event); | ||
_this3.currentMenuItem.linkElement.click(); | ||
} else if (key === "ArrowRight") { | ||
// Hitting the Right Arrow: | ||
@@ -951,12 +1112,12 @@ // - Moves focus to the next item in the menubar. | ||
var previousChildOpen = _this5.currentMenuItem.isSubmenuItem && _this5.currentMenuItem.toggle.isOpen; | ||
var previousChildOpen = _this3.currentMenuItem.isSubmenuItem && _this3.currentMenuItem.toggle.isOpen; | ||
_this5.focusNextChild(); // Open the newly focussed submenu if applicable. | ||
_this3.focusNextChild(); // Open the newly focussed submenu if applicable. | ||
if (previousChildOpen) { | ||
if (_this5.currentMenuItem.isSubmenuItem) { | ||
_this5.currentMenuItem.toggle.preview(); | ||
if (_this3.currentMenuItem.isSubmenuItem) { | ||
_this3.currentMenuItem.toggle.preview(); | ||
} else { | ||
_this5.closeChildren(); | ||
_this3.closeChildren(); | ||
} | ||
@@ -971,12 +1132,12 @@ } | ||
var _previousChildOpen = _this5.currentMenuItem.isSubmenuItem && _this5.currentMenuItem.toggle.isOpen; | ||
var _previousChildOpen = _this3.currentMenuItem.isSubmenuItem && _this3.currentMenuItem.toggle.isOpen; | ||
_this5.focusPreviousChild(); // Open the newly focussed submenu if applicable. | ||
_this3.focusPreviousChild(); // Open the newly focussed submenu if applicable. | ||
if (_previousChildOpen) { | ||
if (_this5.currentMenuItem.isSubmenuItem) { | ||
_this5.currentMenuItem.toggle.preview(); | ||
if (_this3.currentMenuItem.isSubmenuItem) { | ||
_this3.currentMenuItem.toggle.preview(); | ||
} else { | ||
_this5.closeChildren(); | ||
_this3.closeChildren(); | ||
} | ||
@@ -987,8 +1148,8 @@ } | ||
// - Opens submenu and moves focus to first item in the submenu. | ||
if (_this5.currentMenuItem.isSubmenuItem) { | ||
if (_this3.currentMenuItem.isSubmenuItem) { | ||
preventEvent(event); | ||
_this5.currentMenuItem.toggle.open(); | ||
_this3.currentMenuItem.toggle.open(); | ||
_this5.currentMenuItem.childMenu.focusFirstChild(); | ||
_this3.currentMenuItem.childMenu.focusFirstChild(); | ||
} | ||
@@ -998,8 +1159,8 @@ } else if (key === "ArrowUp") { | ||
// - Opens submenu and moves focus to last item in the submenu. | ||
if (_this5.currentMenuItem.isSubmenuItem) { | ||
if (_this3.currentMenuItem.isSubmenuItem) { | ||
preventEvent(event); | ||
_this5.currentMenuItem.toggle.open(); | ||
_this3.currentMenuItem.toggle.open(); | ||
_this5.currentMenuItem.childMenu.focusLastChild(); | ||
_this3.currentMenuItem.childMenu.focusLastChild(); | ||
} | ||
@@ -1011,3 +1172,3 @@ } else if (key === "Home") { | ||
_this5.focusFirstChild(); | ||
_this3.focusFirstChild(); | ||
} else if (key === "End") { | ||
@@ -1018,8 +1179,8 @@ // Hitting End: | ||
_this5.focusLastChild(); | ||
_this3.focusLastChild(); | ||
} else if (key === "Escape") { | ||
if (_this5.controller !== null) { | ||
if (_this3.controller !== null) { | ||
// Hitting Escape: | ||
// - Closes menu. | ||
_this5.controller.close(); | ||
_this3.controller.close(); | ||
} | ||
@@ -1034,3 +1195,3 @@ } | ||
_this5.currentMenuItem.linkElement.click(); | ||
_this3.currentMenuItem.linkElement.click(); | ||
} else if (key === "Escape") { | ||
@@ -1042,5 +1203,5 @@ // Hitting Escape: | ||
_this5.rootMenu.closeChildren(); | ||
_this3.rootMenu.closeChildren(); | ||
_this5.rootMenu.focusCurrentChild(); | ||
_this3.rootMenu.focusCurrentChild(); | ||
} else if (key === "ArrowRight") { | ||
@@ -1053,15 +1214,15 @@ // Hitting the Right Arrow: | ||
// - Opens submenu of newly focused menubar item, keeping focus on that parent menubar item. | ||
if (_this5.currentMenuItem.isSubmenuItem) { | ||
if (_this3.currentMenuItem.isSubmenuItem) { | ||
preventEvent(event); | ||
_this5.currentMenuItem.toggle.open(); | ||
_this3.currentMenuItem.toggle.open(); | ||
} else { | ||
preventEvent(event); | ||
_this5.rootMenu.closeChildren(); | ||
_this3.rootMenu.closeChildren(); | ||
_this5.rootMenu.focusNextChild(); | ||
_this3.rootMenu.focusNextChild(); | ||
if (_this5.rootMenu.currentMenuItem.isSubmenuItem) { | ||
_this5.rootMenu.currentMenuItem.toggle.preview(); | ||
if (_this3.rootMenu.currentMenuItem.isSubmenuItem) { | ||
_this3.rootMenu.currentMenuItem.toggle.preview(); | ||
} | ||
@@ -1075,14 +1236,14 @@ } | ||
// - Opens submenu of newly focused menubar item, keeping focus on that parent menubar item. | ||
if (_this5.parentMenu.currentMenuItem.isSubmenuItem) { | ||
if (_this3.parentMenu.currentMenuItem.isSubmenuItem) { | ||
preventEvent(event); | ||
_this5.parentMenu.currentMenuItem.toggle.close(); | ||
_this3.parentMenu.currentMenuItem.toggle.close(); | ||
if (_this5.parentMenu === _this5.rootMenu) { | ||
_this5.rootMenu.closeChildren(); | ||
if (_this3.parentMenu === _this3.rootMenu) { | ||
_this3.rootMenu.closeChildren(); | ||
_this5.rootMenu.focusPreviousChild(); | ||
_this3.rootMenu.focusPreviousChild(); | ||
if (_this5.rootMenu.currentMenuItem.isSubmenuItem) { | ||
_this5.rootMenu.currentMenuItem.toggle.preview(); | ||
if (_this3.rootMenu.currentMenuItem.isSubmenuItem) { | ||
_this3.rootMenu.currentMenuItem.toggle.preview(); | ||
} | ||
@@ -1097,3 +1258,3 @@ } | ||
_this5.focusNextChild(); | ||
_this3.focusNextChild(); | ||
} else if (key === "ArrowUp") { | ||
@@ -1105,3 +1266,3 @@ // Hitting the Up Arrow: | ||
_this5.focusPreviousChild(); | ||
_this3.focusPreviousChild(); | ||
} else if (key === "Home") { | ||
@@ -1112,3 +1273,3 @@ // Hitting Home: | ||
_this5.focusFirstChild(); | ||
_this3.focusFirstChild(); | ||
} else if (key === "End") { | ||
@@ -1119,3 +1280,3 @@ // Hitting End: | ||
_this5.focusLastChild(); | ||
_this3.focusLastChild(); | ||
} | ||
@@ -1130,12 +1291,12 @@ } | ||
_this5.focusNextChildWithCharacter(event.key); | ||
_this3.focusNextChildWithCharacter(event.key); | ||
} | ||
if (_this5.currentFocus !== "none") { | ||
if (_this3.currentFocus !== "none") { | ||
if (key === "Tab") { | ||
// Hitting Tab: | ||
// - Moves focus out of the menu. | ||
_this5.rootMenu.blur(); | ||
_this3.rootMenu.blur(); | ||
_this5.rootMenu.closeChildren(); | ||
_this3.rootMenu.closeChildren(); | ||
} | ||
@@ -1152,12 +1313,12 @@ } | ||
value: function handleClick() { | ||
var _this6 = this; | ||
var _this4 = this; | ||
document.addEventListener("click", function (event) { | ||
if (!_this6.element.contains(event.target) && _this6.element !== event.target) { | ||
_this6.blur(); | ||
if (!_this4.element.contains(event.target) && _this4.element !== event.target) { | ||
_this4.blur(); | ||
_this6.closeChildren(); | ||
_this4.closeChildren(); | ||
if (_this6.controller) { | ||
_this6.controller.close(); | ||
if (_this4.controller) { | ||
_this4.controller.close(); | ||
} | ||
@@ -1169,3 +1330,3 @@ } | ||
menuItem.linkElement.addEventListener("click", function () { | ||
_this6.focussedChild = _this6.menuItems.indexOf(menuItem); | ||
_this4.focussedChild = _this4.menuItems.indexOf(menuItem); | ||
}); | ||
@@ -1528,2 +1689,3 @@ }); | ||
return Menu; | ||
}(); | ||
}()); |
@@ -1,1 +0,1 @@ | ||
"use strict";function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}var AccessibleMenu=function(){var e={event:function(e){if(!(e instanceof Event))throw new TypeError("event must be an event.")},keyboardEvent:function(e){if(!(e instanceof KeyboardEvent))throw new TypeError("event must be a keyboard event.")}};function t(t){e.event(t),t.preventDefault(),t.stopPropagation()}var n={menuToggleElement:function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuToggleElement must be an HTML Element.")},parentElement:function(e){if(!(e instanceof HTMLElement))throw new TypeError("parentElement must be an HTML Element.")},menu:function(e){if(!(e instanceof i))throw new TypeError("menu must be a Menu.")},openClass:function(e){if("string"!=typeof e)throw TypeError("openClass must be a string.");if(e.replace(/[_a-zA-Z0-9-]/g,"").length>0)throw Error("openClass must be a valid CSS class.")},parentMenu:function(e){if(null!==e&&!(e instanceof i))throw new TypeError("parentMenu must be a Menu.")}},r=function(){function e(t){var r=t.menuToggleElement,u=t.parentElement,s=t.menu,o=t.openClass,i=void 0===o?"show":o,l=t.parentMenu,c=void 0===l?null:l;_classCallCheck(this,e),n.menuToggleElement(r),n.parentElement(u),n.menu(s),n.openClass(i),n.parentMenu(c),this.domElements={toggle:r,parent:u},this.elements={menu:s,parentMenu:c},this.openClass=i,this.show=!1,this.initialize()}return _createClass(e,[{key:"initialize",value:function(){if(this.element.setAttribute("aria-haspopup","true"),this.element.setAttribute("aria-expanded","false"),this.element.setAttribute("role","button"),""===this.element.id||""===this.menu.element.id){var e=Math.random().toString(36).replace(/[^a-z]+/g,"").substr(0,10),t="".concat(this.element.innerText.toLowerCase().replace(/[^a-zA-Z0-9\s]/g,"").replace(/\s/g,"-"),"-").concat(e);this.element.id=this.element.id||"".concat(t,"-menu-button"),this.menu.element.id=this.menu.element.id||"".concat(t,"-menu")}this.menu.element.setAttribute("aria-labelledby",this.element.id),this.element.setAttribute("aria-controls",this.menu.element.id),this.handleClick()}},{key:"expand",value:function(){this.element.setAttribute("aria-expanded","true"),this.parentElement.classList.add(this.openClass),this.menu.element.classList.add(this.openClass)}},{key:"open",value:function(){this.isOpen=!0,this.expand(),this.closeSiblings(),this.parentMenu&&(this.parentMenu.currentFocus="child"),this.menu.currentFocus="self",this.menu.focusFirstChild()}},{key:"preview",value:function(){this.isOpen=!0,this.expand(),this.closeSiblings(),this.parentMenu&&(this.parentMenu.currentFocus="self",this.parentMenu.focusCurrentChild()),this.menu.currentFocus="none"}},{key:"close",value:function(){this.isOpen&&(this.isOpen=!1,this.element.setAttribute("aria-expanded","false"),this.parentElement.classList.remove(this.openClass),this.menu.element.classList.remove(this.openClass),this.menu.focusFirstChild(),this.closeChildren(),this.menu.blur(),this.parentMenu?(this.parentMenu.currentFocus="self",this.parentMenu.focusCurrentChild()):this.menu.isTopLevel&&this.menu.focusController())}},{key:"toggle",value:function(){this.isOpen?this.close():this.open()}},{key:"closeSiblings",value:function(){var e=this;try{this.parentMenu.menuToggles.forEach((function(t){t!==e&&t.close()}))}catch(e){}}},{key:"closeChildren",value:function(){this.menu.menuToggles.forEach((function(e){return e.close()}))}},{key:"handleClick",value:function(){var e=this;this.element.addEventListener("click",(function(n){t(n),e.toggle()}))}},{key:"element",get:function(){return this.domElements.toggle}},{key:"parentElement",get:function(){return this.domElements.parent}},{key:"menu",get:function(){return this.elements.menu}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"isOpen",get:function(){return this.show},set:function(e){if("boolean"!=typeof e)throw new TypeError("Open state must be true or false.");this.show=e}}]),e}(),u={menuItemElement:function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuItemElement must be an HTML Element.")},menuLinkElement:function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuLinkElement must be an HTML Element.")},parentMenu:function(e){if(!(e instanceof i))throw new TypeError("parentMenu must be a Menu.")},isSubmenuItem:function(e){if("boolean"!=typeof e)throw new TypeError("isSubmenuItem must be true or false")},childMenu:function(e){if(null!==e&&!(e instanceof i))throw new TypeError("childMenu must be a Menu.")},toggle:function(e){if(null!==e&&!(e instanceof r))throw new TypeError("toggle must be a MenuToggle.")}},s=function(){function e(t){var n=t.menuItemElement,r=t.menuLinkElement,s=t.parentMenu,o=t.isSubmenuItem,i=void 0!==o&&o,l=t.childMenu,c=void 0===l?null:l,m=t.toggle,a=void 0===m?null:m;_classCallCheck(this,e),u.menuItemElement(n),u.menuLinkElement(r),u.parentMenu(s),u.isSubmenuItem(i),u.childMenu(c),u.toggle(a),this.domElements={menuItem:n,link:r},this.elements={parentMenu:s,childMenu:c,toggle:a},this.isController=i,this.initialize()}return _createClass(e,[{key:"initialize",value:function(){this.element.setAttribute("role","none"),this.linkElement.setAttribute("role","menuitem"),this.linkElement.tabIndex=-1}},{key:"focus",value:function(){this.linkElement.focus(),this.parentMenu.isTopLevel&&(this.linkElement.tabIndex=0)}},{key:"blur",value:function(){this.linkElement.blur(),this.parentMenu.isTopLevel&&(this.linkElement.tabIndex=-1)}},{key:"element",get:function(){return this.domElements.menuItem}},{key:"linkElement",get:function(){return this.domElements.link}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"childMenu",get:function(){return this.elements.childMenu}},{key:"toggle",get:function(){return this.elements.toggle}},{key:"isSubmenuItem",get:function(){return this.isController}}]),e}(),o={menuElement:function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuElement must be an HTML Element.")},menuItemSelector:function(e){if("string"!=typeof e)throw new TypeError("menuItemSelector must be a CSS selector string.")},hasSubmenus:function(e,t,n){if(null!==e||null!==t||null!==n){if("string"!=typeof e)throw new TypeError("submenuItemSelector must be a CSS selector string.");if("string"!=typeof e)throw new TypeError("submenuToggleSelector must be a CSS selector string.");if("string"!=typeof n)throw new TypeError("submenuSelector must be a CSS selector string.")}},openClass:function(e){if("string"!=typeof e)throw TypeError("openClass must be a string.");if(e.replace(/[_a-zA-Z0-9-]/g,"").length>0)throw Error("openClass must be a valid CSS class.")},isTopLevel:function(e){if("boolean"!=typeof e)throw new TypeError("isTopLevel must be true of false.")},isDropdown:function(e,t){if(null!==e||null!==t){if(!(e instanceof HTMLElement))throw new TypeError("controllerElement must be an HTML Element if containerElement is provided.");if(!(t instanceof HTMLElement))throw new TypeError("containerElement must be an HTML Element if controllerElement is provided.")}},parentMenu:function(e){if(null!==e&&!(e instanceof i))throw new TypeError("parentMenu must be a Menu.")}},i=function(){function n(e){var t=e.menuElement,r=e.menuItemSelector,u=e.submenuItemSelector,s=void 0===u?null:u,i=e.submenuToggleSelector,l=void 0===i?null:i,c=e.submenuSelector,m=void 0===c?null:c,a=e.openClass,h=void 0===a?"show":a,f=e.isTopLevel,d=void 0===f||f,p=e.controllerElement,E=void 0===p?null:p,g=e.containerElement,C=void 0===g?null:g,b=e.parentMenu,M=void 0===b?null:b;_classCallCheck(this,n),o.menuElement(t),o.menuItemSelector(r),o.hasSubmenus(s,l,m),o.openClass(h),o.isTopLevel(d),o.isDropdown(E,C),o.parentMenu(M),this.domElements={menu:t,controller:E,container:C,menuItems:Array.from(t.querySelectorAll(r)).filter((function(e){return e.parentElement===t})),submenuItems:Array.from(t.querySelectorAll(s)).filter((function(e){return e.parentElement===t}))},this.domSelectors={"menu-items":r,"submenu-items":s,"submenu-toggle":l,submenu:m},this.elements={menuItems:[],menuToggles:[],controller:null,parentMenu:M,rootMenu:d?this:null},this.focussedChild=0,this.focusState="none",this.openClass=h,this.root=d,this.initialize()}return _createClass(n,[{key:"initialize",value:function(){if(this.element.setAttribute("role","menubar"),null===this.rootMenu&&this.findRootMenu(this),this.createMenuItems(),this.handleKeydown(),this.handleClick(),this.isTopLevel&&(this.currentMenuItem.linkElement.tabIndex=0,this.handleFocus(),this.controllerElement&&this.containerElement)){var e=new r({menuToggleElement:this.controllerElement,parentElement:this.containerElement,menu:this,openClass:this.openClass});this.elements.controller=e}}},{key:"findRootMenu",value:function(e){if(e.isTopLevel)this.elements.rootMenu=e;else{if(null===e.parentMenu)throw new Error("Cannot find root menu.");this.findRootMenu(e.parentMenu)}}},{key:"createMenuItems",value:function(){var e=this;this.menuItemElements.forEach((function(t){var u;if(e.submenuItemElements.includes(t)){var o=t.querySelector(e.selector["submenu-toggle"]),i=new n({menuElement:t.querySelector(e.selector.submenu),menuItemSelector:e.selector["menu-items"],submenuItemSelector:e.selector["submenu-items"],submenuToggleSelector:e.selector["submenu-toggle"],submenuSelector:e.selector.submenu,openClass:e.openClass,isTopLevel:!1,parentMenu:e}),l=new r({menuToggleElement:o,parentElement:t,menu:i,openClass:e.openClass,parentMenu:e});e.elements.menuToggles.push(l),u=new s({menuItemElement:t,menuLinkElement:o,parentMenu:e,isSubmenuItem:!0,childMenu:i,toggle:l})}else{var c=t.querySelector("a");u=new s({menuItemElement:t,menuLinkElement:c,parentMenu:e})}e.elements.menuItems.push(u)}))}},{key:"handleFocus",value:function(){var e=this;this.menuItems.forEach((function(t){t.linkElement.addEventListener("focusin",(function(){"none"===e.currentFocus&&(e.currentFocus="self",e.focusCurrentChild())})),t.linkElement.addEventListener("focusout",(function(){"none"===e.currentFocus&&(e.blur(),e.closeChildren())}))}))}},{key:"handleKeydown",value:function(){var n=this;this.element.addEventListener("keydown",(function(r){var u=function(t){e.keyboardEvent(t);try{var n=t.key||t.keyCode,r={Enter:"Enter"===n||13===n,Space:" "===n||"Spacebar"===n||32===n,Escape:"Escape"===n||"Esc"===n||27===n,ArrowUp:"ArrowUp"===n||"Up"===n||38===n,ArrowRight:"ArrowRight"===n||"Right"===n||39===n,ArrowDown:"ArrowDown"===n||"Down"===n||40===n,ArrowLeft:"ArrowLeft"===n||"Left"===n||37===n,Home:"Home"===n||36===n,End:"End"===n||35===n,Character:!!n.match(/^[a-zA-Z]{1}$/),Tab:"Tab"===n||9===n};return Object.keys(r).find((function(e){return!0===r[e]}))}catch(e){return""}}(r),s=r.altKey,o=r.crtlKey,i=r.metaKey,l=s||o||i;if(n.isTopLevel){if("none"===n.currentFocus)"Space"!==u&&"Enter"!==u||(t(r),n.currentFocus="self",n.focusFirstChild());else if("self"===n.currentFocus)if("ArrowRight"===u){t(r);var c=n.currentMenuItem.isSubmenuItem&&n.currentMenuItem.toggle.isOpen;n.focusNextChild(),c&&(n.currentMenuItem.isSubmenuItem?n.currentMenuItem.toggle.preview():n.closeChildren())}else if("ArrowLeft"===u){t(r);var m=n.currentMenuItem.isSubmenuItem&&n.currentMenuItem.toggle.isOpen;n.focusPreviousChild(),m&&(n.currentMenuItem.isSubmenuItem?n.currentMenuItem.toggle.preview():n.closeChildren())}else"ArrowDown"===u?n.currentMenuItem.isSubmenuItem&&(t(r),n.currentMenuItem.toggle.open(),n.currentMenuItem.childMenu.focusFirstChild()):"ArrowUp"===u?n.currentMenuItem.isSubmenuItem&&(t(r),n.currentMenuItem.toggle.open(),n.currentMenuItem.childMenu.focusLastChild()):"Home"===u?(t(r),n.focusFirstChild()):"End"===u?(t(r),n.focusLastChild()):"Escape"===u&&null!==n.controller&&n.controller.close()}else"Space"===u||"Enter"===u?(t(r),n.currentMenuItem.linkElement.click()):"Escape"===u?(t(r),n.rootMenu.closeChildren(),n.rootMenu.focusCurrentChild()):"ArrowRight"===u?n.currentMenuItem.isSubmenuItem?(t(r),n.currentMenuItem.toggle.open()):(t(r),n.rootMenu.closeChildren(),n.rootMenu.focusNextChild(),n.rootMenu.currentMenuItem.isSubmenuItem&&n.rootMenu.currentMenuItem.toggle.preview()):"ArrowLeft"===u?n.parentMenu.currentMenuItem.isSubmenuItem&&(t(r),n.parentMenu.currentMenuItem.toggle.close(),n.parentMenu===n.rootMenu&&(n.rootMenu.closeChildren(),n.rootMenu.focusPreviousChild(),n.rootMenu.currentMenuItem.isSubmenuItem&&n.rootMenu.currentMenuItem.toggle.preview())):"ArrowDown"===u?(t(r),n.focusNextChild()):"ArrowUp"===u?(t(r),n.focusPreviousChild()):"Home"===u?(t(r),n.focusFirstChild()):"End"===u&&(t(r),n.focusLastChild());"Character"!==u||l||(t(r),n.focusNextChildWithCharacter(r.key)),"none"!==n.currentFocus&&"Tab"===u&&(n.rootMenu.blur(),n.rootMenu.closeChildren())}))}},{key:"handleClick",value:function(){var e=this;document.addEventListener("click",(function(t){e.element.contains(t.target)||e.element===t.target||(e.blur(),e.closeChildren(),e.controller&&e.controller.close())})),this.menuItems.forEach((function(t){t.linkElement.addEventListener("click",(function(){e.focussedChild=e.menuItems.indexOf(t)}))}))}},{key:"focus",value:function(){this.currentFocus="self",this.element.focus()}},{key:"blur",value:function(){this.currentFocus="none",this.element.blur(),this.isTopLevel&&this.controller&&this.controller.close()}},{key:"focusFirstChild",value:function(){this.blurCurrentChild(),this.focussedChild=0,this.focusCurrentChild()}},{key:"focusLastChild",value:function(){this.blurCurrentChild(),this.focussedChild=this.menuItems.length-1,this.focusCurrentChild()}},{key:"focusNextChild",value:function(){this.focussedChild===this.menuItems.length-1?this.focusFirstChild():(this.blurCurrentChild(),this.focussedChild=this.focussedChild+1,this.focusCurrentChild())}},{key:"focusPreviousChild",value:function(){0===this.focussedChild?this.focusLastChild():(this.blurCurrentChild(),this.focussedChild=this.focussedChild-1,this.focusCurrentChild())}},{key:"focusCurrentChild",value:function(){-1!==this.focussedChild&&this.currentMenuItem.focus()}},{key:"blurCurrentChild",value:function(){-1!==this.focussedChild&&this.currentMenuItem.blur()}},{key:"focusNextChildWithCharacter",value:function(e){for(var t=e.toLowerCase(),n=this.focussedChild+1,r=!1;!r&&n<this.menuItems.length;){this.menuItems[n].element.innerText.toLowerCase().startsWith(t)&&(r=!0,this.focussedChild=n,this.focusCurrentChild()),n++}}},{key:"focusController",value:function(){this.controllerElement&&(this.controllerElement.focus(),this.currentFocus="none")}},{key:"focusContainer",value:function(){this.containerElement&&(this.containerElement.focus(),this.currentFocus="none")}},{key:"closeChildren",value:function(){this.menuToggles.forEach((function(e){return e.close()}))}},{key:"element",get:function(){return this.domElements.menu}},{key:"controllerElement",get:function(){return this.domElements.controller}},{key:"containerElement",get:function(){return this.domElements.container}},{key:"menuItemElements",get:function(){return this.domElements.menuItems}},{key:"submenuItemElements",get:function(){return this.domElements.submenuItems}},{key:"menuItems",get:function(){return this.elements.menuItems}},{key:"menuToggles",get:function(){return this.elements.menuToggles}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"rootMenu",get:function(){return this.elements.rootMenu}},{key:"controller",get:function(){return this.elements.controller}},{key:"selector",get:function(){return this.domSelectors}},{key:"currentFocus",get:function(){return this.focusState},set:function(e){if(!["self","child","none"].includes(e))throw new Error("Focus state must be 'self', 'child', or 'none'.");this.focusState=e}},{key:"openClass",get:function(){return this.submenuOpenClass},set:function(e){if("string"!=typeof e)throw new TypeError("Class must be a string.");this.submenuOpenClass=e}},{key:"currentMenuItem",get:function(){return this.menuItems[this.focussedChild]}},{key:"isTopLevel",get:function(){return this.root}}]),n}();return i}(); | ||
var AccessibleMenu=function(){"use strict";var e,t,n,r;function u(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function o(e,t,n){return t&&i(e.prototype,t),n&&i(e,n),e}Array.from||(Array.from=(e=Object.prototype.toString,t=function(t){return"function"==typeof t||"[object Function]"===e.call(t)},n=Math.pow(2,53)-1,r=function(e){var t=function(e){var t=Number(e);return isNaN(t)?0:0!==t&&isFinite(t)?(t>0?1:-1)*Math.floor(Math.abs(t)):t}(e);return Math.min(Math.max(t,0),n)},function(e){var n=this,u=Object(e);if(null==e)throw new TypeError("Array.from requires an array-like object - not null or undefined");var i,o=arguments.length>1?arguments[1]:void 0;if(void 0!==o){if(!t(o))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(i=arguments[2])}for(var s,l=r(u.length),c=t(n)?Object(new n(l)):new Array(l),m=0;m<l;)s=u[m],c[m]=o?void 0===i?o(s,m):o.call(i,s,m):s,m+=1;return c.length=l,c})),Array.includes||(Array.prototype.includes=function(e){return!!~this.indexOf(e)}),Array.prototype.find||Object.defineProperty(Array.prototype,"find",{value:function(e){if(null==this)throw TypeError('"this" is null or not defined');var t=Object(this),n=t.length>>>0;if("function"!=typeof e)throw TypeError("predicate must be a function");for(var r=arguments[1],u=0;u<n;){var i=t[u];if(e.call(r,i,u,t))return i;u++}},configurable:!0,writable:!0});var s=function(e){if(!(e instanceof Event))throw new TypeError("event must be an event.")},l=function(e){if(!(e instanceof KeyboardEvent))throw new TypeError("event must be a keyboard event.")};function c(e){s(e),e.preventDefault(),e.stopPropagation()}var m=function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuToggleElement must be an HTML Element.")},a=function(e){if(!(e instanceof HTMLElement))throw new TypeError("parentElement must be an HTML Element.")},h=function(e){if(!(e instanceof F))throw new TypeError("menu must be a Menu.")},f=function(e){if("string"!=typeof e)throw TypeError("openClass must be a string.");if(e.replace(/[_a-zA-Z0-9-]/g,"").length>0)throw Error("openClass must be a valid CSS class.")},d=function(e){if(null!==e&&!(e instanceof F))throw new TypeError("parentMenu must be a Menu.")},p=function(){function e(t){var n=t.menuToggleElement,r=t.parentElement,i=t.menu,o=t.openClass,s=void 0===o?"show":o,l=t.parentMenu,c=void 0===l?null:l;u(this,e),m(n),a(r),h(i),f(s),d(c),this.domElements={toggle:n,parent:r},this.elements={menu:i,parentMenu:c},this.openClass=s,this.show=!1,this.initialize()}return o(e,[{key:"initialize",value:function(){if(this.element.setAttribute("aria-haspopup","true"),this.element.setAttribute("aria-expanded","false"),this.element.setAttribute("role","button"),""===this.element.id||""===this.menu.element.id){var e=Math.random().toString(36).replace(/[^a-z]+/g,"").substr(0,10),t="".concat(this.element.innerText.toLowerCase().replace(/[^a-zA-Z0-9\s]/g,"").replace(/\s/g,"-"),"-").concat(e);this.element.id=this.element.id||"".concat(t,"-menu-button"),this.menu.element.id=this.menu.element.id||"".concat(t,"-menu")}this.menu.element.setAttribute("aria-labelledby",this.element.id),this.element.setAttribute("aria-controls",this.menu.element.id),this.handleClick()}},{key:"expand",value:function(){this.element.setAttribute("aria-expanded","true"),this.parentElement.classList.add(this.openClass),this.menu.element.classList.add(this.openClass)}},{key:"open",value:function(){this.isOpen=!0,this.expand(),this.closeSiblings(),this.parentMenu&&(this.parentMenu.currentFocus="child"),this.menu.currentFocus="self",this.menu.focusFirstChild()}},{key:"preview",value:function(){this.isOpen=!0,this.expand(),this.closeSiblings(),this.parentMenu&&(this.parentMenu.currentFocus="self",this.parentMenu.focusCurrentChild()),this.menu.currentFocus="none"}},{key:"close",value:function(){this.isOpen&&(this.isOpen=!1,this.element.setAttribute("aria-expanded","false"),this.parentElement.classList.remove(this.openClass),this.menu.element.classList.remove(this.openClass),this.menu.focusFirstChild(),this.closeChildren(),this.menu.blur(),this.parentMenu?(this.parentMenu.currentFocus="self",this.parentMenu.focusCurrentChild()):this.menu.isTopLevel&&this.menu.focusController())}},{key:"toggle",value:function(){this.isOpen?this.close():this.open()}},{key:"closeSiblings",value:function(){var e=this;try{this.parentMenu.menuToggles.forEach((function(t){t!==e&&t.close()}))}catch(e){}}},{key:"closeChildren",value:function(){this.menu.menuToggles.forEach((function(e){return e.close()}))}},{key:"handleClick",value:function(){var e=this;this.element.addEventListener("click",(function(t){c(t),e.toggle()}))}},{key:"element",get:function(){return this.domElements.toggle}},{key:"parentElement",get:function(){return this.domElements.parent}},{key:"menu",get:function(){return this.elements.menu}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"isOpen",get:function(){return this.show},set:function(e){if("boolean"!=typeof e)throw new TypeError("Open state must be true or false.");this.show=e}}]),e}(),g=function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuItemElement must be an HTML Element.")},E=function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuLinkElement must be an HTML Element.")},y=function(e){if(!(e instanceof F))throw new TypeError("parentMenu must be a Menu.")},b=function(e){if("boolean"!=typeof e)throw new TypeError("isSubmenuItem must be true or false")},C=function(e){if(null!==e&&!(e instanceof F))throw new TypeError("childMenu must be a Menu.")},v=function(e){if(null!==e&&!(e instanceof p))throw new TypeError("toggle must be a MenuToggle.")},M=function(){function e(t){var n=t.menuItemElement,r=t.menuLinkElement,i=t.parentMenu,o=t.isSubmenuItem,s=void 0!==o&&o,l=t.childMenu,c=void 0===l?null:l,m=t.toggle,a=void 0===m?null:m;u(this,e),g(n),E(r),y(i),b(s),C(c),v(a),this.domElements={menuItem:n,link:r},this.elements={parentMenu:i,childMenu:c,toggle:a},this.isController=s,this.initialize()}return o(e,[{key:"initialize",value:function(){this.element.setAttribute("role","none"),this.linkElement.setAttribute("role","menuitem"),this.linkElement.tabIndex=-1}},{key:"focus",value:function(){this.linkElement.focus(),this.parentMenu.isTopLevel&&(this.linkElement.tabIndex=0)}},{key:"blur",value:function(){this.linkElement.blur(),this.parentMenu.isTopLevel&&(this.linkElement.tabIndex=-1)}},{key:"element",get:function(){return this.domElements.menuItem}},{key:"linkElement",get:function(){return this.domElements.link}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"childMenu",get:function(){return this.elements.childMenu}},{key:"toggle",get:function(){return this.elements.toggle}},{key:"isSubmenuItem",get:function(){return this.isController}}]),e}(),w=function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuElement must be an HTML Element.")},k=function(e){if("string"!=typeof e)throw new TypeError("menuItemSelector must be a CSS selector string.")},I=function(e,t,n){if(null!==e||null!==t||null!==n){if("string"!=typeof e)throw new TypeError("submenuItemSelector must be a CSS selector string.");if("string"!=typeof e)throw new TypeError("submenuToggleSelector must be a CSS selector string.");if("string"!=typeof n)throw new TypeError("submenuSelector must be a CSS selector string.")}},T=function(e){if("string"!=typeof e)throw TypeError("openClass must be a string.");if(e.replace(/[_a-zA-Z0-9-]/g,"").length>0)throw Error("openClass must be a valid CSS class.")},S=function(e){if("boolean"!=typeof e)throw new TypeError("isTopLevel must be true of false.")},L=function(e,t){if(null!==e||null!==t){if(!(e instanceof HTMLElement))throw new TypeError("controllerElement must be an HTML Element if containerElement is provided.");if(!(t instanceof HTMLElement))throw new TypeError("containerElement must be an HTML Element if controllerElement is provided.")}},A=function(e){if(null!==e&&!(e instanceof F))throw new TypeError("parentMenu must be a Menu.")},F=function(){function e(t){var n=t.menuElement,r=t.menuItemSelector,i=t.submenuItemSelector,o=void 0===i?null:i,s=t.submenuToggleSelector,l=void 0===s?null:s,c=t.submenuSelector,m=void 0===c?null:c,a=t.openClass,h=void 0===a?"show":a,f=t.isTopLevel,d=void 0===f||f,p=t.controllerElement,g=void 0===p?null:p,E=t.containerElement,y=void 0===E?null:E,b=t.parentMenu,C=void 0===b?null:b;u(this,e),w(n),k(r),I(o,l,m),T(h),S(d),L(g,y),A(C),this.domElements={menu:n,controller:g,container:y,menuItems:Array.from(n.querySelectorAll(r)).filter((function(e){return e.parentElement===n})),submenuItems:Array.from(n.querySelectorAll(o)).filter((function(e){return e.parentElement===n}))},this.domSelectors={"menu-items":r,"submenu-items":o,"submenu-toggle":l,submenu:m},this.elements={menuItems:[],menuToggles:[],controller:null,parentMenu:C,rootMenu:d?this:null},this.focussedChild=0,this.focusState="none",this.openClass=h,this.root=d,this.initialize()}return o(e,[{key:"initialize",value:function(){if(this.element.setAttribute("role","menubar"),null===this.rootMenu&&this.findRootMenu(this),this.createMenuItems(),this.handleKeydown(),this.handleClick(),this.isTopLevel&&(this.currentMenuItem.linkElement.tabIndex=0,this.handleFocus(),this.controllerElement&&this.containerElement)){var e=new p({menuToggleElement:this.controllerElement,parentElement:this.containerElement,menu:this,openClass:this.openClass});this.elements.controller=e}}},{key:"findRootMenu",value:function(e){if(e.isTopLevel)this.elements.rootMenu=e;else{if(null===e.parentMenu)throw new Error("Cannot find root menu.");this.findRootMenu(e.parentMenu)}}},{key:"createMenuItems",value:function(){var t=this;this.menuItemElements.forEach((function(n){var r;if(t.submenuItemElements.includes(n)){var u=n.querySelector(t.selector["submenu-toggle"]),i=new e({menuElement:n.querySelector(t.selector.submenu),menuItemSelector:t.selector["menu-items"],submenuItemSelector:t.selector["submenu-items"],submenuToggleSelector:t.selector["submenu-toggle"],submenuSelector:t.selector.submenu,openClass:t.openClass,isTopLevel:!1,parentMenu:t}),o=new p({menuToggleElement:u,parentElement:n,menu:i,openClass:t.openClass,parentMenu:t});t.elements.menuToggles.push(o),r=new M({menuItemElement:n,menuLinkElement:u,parentMenu:t,isSubmenuItem:!0,childMenu:i,toggle:o})}else{var s=n.querySelector("a");r=new M({menuItemElement:n,menuLinkElement:s,parentMenu:t})}t.elements.menuItems.push(r)}))}},{key:"handleFocus",value:function(){var e=this;this.menuItems.forEach((function(t){t.linkElement.addEventListener("focusin",(function(){"none"===e.currentFocus&&(e.currentFocus="self",e.focusCurrentChild())})),t.linkElement.addEventListener("focusout",(function(){"none"===e.currentFocus&&(e.blur(),e.closeChildren())}))}))}},{key:"handleKeydown",value:function(){var e=this;this.element.addEventListener("keydown",(function(t){var n=function(e){l(e);try{var t=e.key||e.keyCode,n={Enter:"Enter"===t||13===t,Space:" "===t||"Spacebar"===t||32===t,Escape:"Escape"===t||"Esc"===t||27===t,ArrowUp:"ArrowUp"===t||"Up"===t||38===t,ArrowRight:"ArrowRight"===t||"Right"===t||39===t,ArrowDown:"ArrowDown"===t||"Down"===t||40===t,ArrowLeft:"ArrowLeft"===t||"Left"===t||37===t,Home:"Home"===t||36===t,End:"End"===t||35===t,Character:!!t.match(/^[a-zA-Z]{1}$/),Tab:"Tab"===t||9===t};return Object.keys(n).find((function(e){return!0===n[e]}))}catch(e){return""}}(t),r=t.altKey,u=t.crtlKey,i=t.metaKey,o=r||u||i;if(e.isTopLevel){if("none"===e.currentFocus)"Space"!==n&&"Enter"!==n||(c(t),e.currentFocus="self",e.focusFirstChild());else if("self"===e.currentFocus)if("Space"===n||"Enter"===n)c(t),e.currentMenuItem.linkElement.click();else if("ArrowRight"===n){c(t);var s=e.currentMenuItem.isSubmenuItem&&e.currentMenuItem.toggle.isOpen;e.focusNextChild(),s&&(e.currentMenuItem.isSubmenuItem?e.currentMenuItem.toggle.preview():e.closeChildren())}else if("ArrowLeft"===n){c(t);var m=e.currentMenuItem.isSubmenuItem&&e.currentMenuItem.toggle.isOpen;e.focusPreviousChild(),m&&(e.currentMenuItem.isSubmenuItem?e.currentMenuItem.toggle.preview():e.closeChildren())}else"ArrowDown"===n?e.currentMenuItem.isSubmenuItem&&(c(t),e.currentMenuItem.toggle.open(),e.currentMenuItem.childMenu.focusFirstChild()):"ArrowUp"===n?e.currentMenuItem.isSubmenuItem&&(c(t),e.currentMenuItem.toggle.open(),e.currentMenuItem.childMenu.focusLastChild()):"Home"===n?(c(t),e.focusFirstChild()):"End"===n?(c(t),e.focusLastChild()):"Escape"===n&&null!==e.controller&&e.controller.close()}else"Space"===n||"Enter"===n?(c(t),e.currentMenuItem.linkElement.click()):"Escape"===n?(c(t),e.rootMenu.closeChildren(),e.rootMenu.focusCurrentChild()):"ArrowRight"===n?e.currentMenuItem.isSubmenuItem?(c(t),e.currentMenuItem.toggle.open()):(c(t),e.rootMenu.closeChildren(),e.rootMenu.focusNextChild(),e.rootMenu.currentMenuItem.isSubmenuItem&&e.rootMenu.currentMenuItem.toggle.preview()):"ArrowLeft"===n?e.parentMenu.currentMenuItem.isSubmenuItem&&(c(t),e.parentMenu.currentMenuItem.toggle.close(),e.parentMenu===e.rootMenu&&(e.rootMenu.closeChildren(),e.rootMenu.focusPreviousChild(),e.rootMenu.currentMenuItem.isSubmenuItem&&e.rootMenu.currentMenuItem.toggle.preview())):"ArrowDown"===n?(c(t),e.focusNextChild()):"ArrowUp"===n?(c(t),e.focusPreviousChild()):"Home"===n?(c(t),e.focusFirstChild()):"End"===n&&(c(t),e.focusLastChild());"Character"!==n||o||(c(t),e.focusNextChildWithCharacter(t.key)),"none"!==e.currentFocus&&"Tab"===n&&(e.rootMenu.blur(),e.rootMenu.closeChildren())}))}},{key:"handleClick",value:function(){var e=this;document.addEventListener("click",(function(t){e.element.contains(t.target)||e.element===t.target||(e.blur(),e.closeChildren(),e.controller&&e.controller.close())})),this.menuItems.forEach((function(t){t.linkElement.addEventListener("click",(function(){e.focussedChild=e.menuItems.indexOf(t)}))}))}},{key:"focus",value:function(){this.currentFocus="self",this.element.focus()}},{key:"blur",value:function(){this.currentFocus="none",this.element.blur(),this.isTopLevel&&this.controller&&this.controller.close()}},{key:"focusFirstChild",value:function(){this.blurCurrentChild(),this.focussedChild=0,this.focusCurrentChild()}},{key:"focusLastChild",value:function(){this.blurCurrentChild(),this.focussedChild=this.menuItems.length-1,this.focusCurrentChild()}},{key:"focusNextChild",value:function(){this.focussedChild===this.menuItems.length-1?this.focusFirstChild():(this.blurCurrentChild(),this.focussedChild=this.focussedChild+1,this.focusCurrentChild())}},{key:"focusPreviousChild",value:function(){0===this.focussedChild?this.focusLastChild():(this.blurCurrentChild(),this.focussedChild=this.focussedChild-1,this.focusCurrentChild())}},{key:"focusCurrentChild",value:function(){-1!==this.focussedChild&&this.currentMenuItem.focus()}},{key:"blurCurrentChild",value:function(){-1!==this.focussedChild&&this.currentMenuItem.blur()}},{key:"focusNextChildWithCharacter",value:function(e){for(var t=e.toLowerCase(),n=this.focussedChild+1,r=!1;!r&&n<this.menuItems.length;){this.menuItems[n].element.innerText.toLowerCase().startsWith(t)&&(r=!0,this.focussedChild=n,this.focusCurrentChild()),n++}}},{key:"focusController",value:function(){this.controllerElement&&(this.controllerElement.focus(),this.currentFocus="none")}},{key:"focusContainer",value:function(){this.containerElement&&(this.containerElement.focus(),this.currentFocus="none")}},{key:"closeChildren",value:function(){this.menuToggles.forEach((function(e){return e.close()}))}},{key:"element",get:function(){return this.domElements.menu}},{key:"controllerElement",get:function(){return this.domElements.controller}},{key:"containerElement",get:function(){return this.domElements.container}},{key:"menuItemElements",get:function(){return this.domElements.menuItems}},{key:"submenuItemElements",get:function(){return this.domElements.submenuItems}},{key:"menuItems",get:function(){return this.elements.menuItems}},{key:"menuToggles",get:function(){return this.elements.menuToggles}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"rootMenu",get:function(){return this.elements.rootMenu}},{key:"controller",get:function(){return this.elements.controller}},{key:"selector",get:function(){return this.domSelectors}},{key:"currentFocus",get:function(){return this.focusState},set:function(e){if(!["self","child","none"].includes(e))throw new Error("Focus state must be 'self', 'child', or 'none'.");this.focusState=e}},{key:"openClass",get:function(){return this.submenuOpenClass},set:function(e){if("string"!=typeof e)throw new TypeError("Class must be a string.");this.submenuOpenClass=e}},{key:"currentMenuItem",get:function(){return this.menuItems[this.focussedChild]}},{key:"isTopLevel",get:function(){return this.root}}]),e}();return F}(); |
{ | ||
"name": "accessible-menu", | ||
"version": "1.0.6", | ||
"description": "A JavaScript library to help you generate WAI-ARIA accessible menus in the DOM.", | ||
"version": "1.1.0", | ||
"description": "A JavaScript library to help you generate WCAG accessible menus in the DOM.", | ||
"main": "index.js", | ||
@@ -9,14 +9,15 @@ "files": [ | ||
"dist/", | ||
"src/" | ||
"src/eventHandlers.js", | ||
"src/menu.js", | ||
"src/menuItem.js", | ||
"src/menuToggle.js" | ||
], | ||
"scripts": { | ||
"commit": "npx git cz", | ||
"commit": "npx git-cz", | ||
"lint": "npx eslint --ext .js --ignore-path .eslintignore .", | ||
"fix": "npm run lint -- --fix", | ||
"prerelease": "npm run build", | ||
"prerelease": "npm run lint && npm run build", | ||
"release": "git add dist/. && npx standard-version -a", | ||
"bundle": "npx rollup --config .rollup.config.js", | ||
"compile": "npx babel dist/accessibleMenu.js -o dist/accessibleMenu.js", | ||
"minify": "npx terser dist/accessibleMenu.js -c -m -o dist/accessibleMenu.min.js", | ||
"build": "npm run bundle && npm run compile && npm run minify" | ||
"compile:test": "npx babel test/js/main.js -o test/js/main-ie.js", | ||
"build": "npx rollup --config .rollup.config.js" | ||
}, | ||
@@ -49,3 +50,5 @@ "repository": { | ||
"@commitlint/config-conventional": "^8.2.0", | ||
"@rollup/plugin-node-resolve": "^7.1.1", | ||
"commitizen": "^4.0.3", | ||
"cz-conventional-changelog": "^3.1.0", | ||
"eslint": "^6.7.0", | ||
@@ -63,5 +66,13 @@ "eslint-config-prettier": "^6.7.0", | ||
"rollup": "^1.27.4", | ||
"rollup-plugin-babel": "^4.4.0", | ||
"rollup-plugin-terser": "^5.2.0", | ||
"standard-version": "^7.0.1", | ||
"terser": "^4.4.0" | ||
} | ||
}, | ||
"config": { | ||
"commitizen": { | ||
"path": "cz-conventional-changelog" | ||
} | ||
}, | ||
"dependencies": {} | ||
} |
@@ -6,4 +6,6 @@ # accessible-menu | ||
A JavaScript library to help you generate WAI-ARIA accessible menus in the DOM. | ||
A JavaScript library to help you generate WCAG accessible menus in the DOM. | ||
The current reference used is W3C's [Navigation Menubar Example](https://w3c.github.io/aria-practices/examples/menubar/menubar-1/menubar-1.html). | ||
## Browser Support | ||
@@ -13,3 +15,3 @@ | ||
| --------- | --------- | --------- | --------- | --------- | --------- | | ||
| IE11, Edge [*](#internet-explorer-and-edge-support) | last 2 versions| last 2 versions| last 2 versions| last 2 versions| last 2 versions | ||
| IE11, Edge [*](#internet-explorer-and-edge-support) | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions | | ||
@@ -38,3 +40,3 @@ ## Installation | ||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/accessible-menu@1.0.2/dist/accessibleMenu.js"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/accessible-menu@1.1.0/dist/accessibleMenu.js"></script> | ||
``` | ||
@@ -97,7 +99,11 @@ | ||
### Examples | ||
Looking for a working example of accessible-menu? Check out this [jsfiddle](https://jsfiddle.net/NickDJM/yokxg0vr/). | ||
## Internet Explorer and Edge Support | ||
For both IE and Edge support, you will either need to use the CDN option, or run your code through [Babel](https://babeljs.io/). | ||
For both IE and older (non-chromium-based) versions of Edge support, you will either need to use the CDN option, or run your code through [Babel](https://babeljs.io/). | ||
For IE, you will also need to ensure you load [Babel Polyfill](https://babeljs.io/docs/en/babel-polyfill) before loading accessible-menu. | ||
If you are compiling your own code without the help of something like Babel + [core-js](https://www.npmjs.com/package/core-js), you will need polyfills for `Array.from()`, `Array.includes()`, and `Array.find()` for IE11 support. | ||
@@ -104,0 +110,0 @@ ## Versioning |
@@ -475,3 +475,8 @@ import MenuItem from "./menuItem"; | ||
} else if (this.currentFocus === "self") { | ||
if (key === "ArrowRight") { | ||
if (key === "Space" || key === "Enter") { | ||
// Hitting Space or Enter: | ||
// - Activates menu item, causing the link to be activated. | ||
preventEvent(event); | ||
this.currentMenuItem.linkElement.click(); | ||
} else if (key === "ArrowRight") { | ||
// Hitting the Right Arrow: | ||
@@ -478,0 +483,0 @@ // - Moves focus to the next item in the menubar. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
125677
2713
115
24