-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathinclusive-menu-button.min.js
2 lines (2 loc) · 4.3 KB
/
inclusive-menu-button.min.js
1
2
/*! inclusive-menu-button 0.1.3 — © Heydon Pickering */
(function(global){"use strict";function MenuButton(button,options){options=options||{};this.settings={checkable:"none"};for(var setting in options){if(options.hasOwnProperty(setting)){this.settings[setting]=options[setting]}}this.button=button;this.button.setAttribute("aria-haspopup",true);this.button.setAttribute("aria-expanded",false);this.menuId=this.button.getAttribute("data-inclusive-menu-opens");this.menu=document.getElementById(this.menuId);if(!this.menu){throw new Error("Element `#"+this.menuId+"` not found.")}this.menu.setAttribute("role","menu");this.menu.hidden=true;this.menuItems=this.menu.querySelectorAll("button");if(this.menuItems.length<1){throw new Error("The #"+this.menuId+" menu has no menu items")}this.firstItem=this.menuItems[0];this.lastItem=this.menuItems[this.menuItems.length-1];var focusNext=function(currentItem,startItem){var goingDown=startItem===this.firstItem;function move(elem){return(goingDown?elem.nextElementSibling:elem.previousElementSibling)||startItem}var nextItem=move(currentItem);while(nextItem.disabled){nextItem=move(nextItem)}nextItem.focus()}.bind(this);Array.prototype.forEach.call(this.menuItems,function(menuItem){var active=Array.prototype.filter.call(this.menuItems,function(item){return!item.disabled});if(active.length<1){this.button.disabled=true;return}if(this.settings.checkable==="one"){menuItem.setAttribute("role","menuitemradio")}else if(this.settings.checkable==="many"){menuItem.setAttribute("role","menuitemcheckbox")}else{menuItem.setAttribute("role","menuitem")}menuItem.setAttribute("tabindex","-1");menuItem.addEventListener("keydown",function(e){if(e.keyCode===40){e.preventDefault();focusNext(menuItem,this.firstItem)}if(e.keyCode===38){e.preventDefault();focusNext(menuItem,this.lastItem)}if(e.keyCode===27||e.keyCode===9){this.toggle()}if(e.keyCode===27){e.preventDefault();this.button.focus()}}.bind(this));menuItem.addEventListener("click",function(e){this.choose(menuItem);this.close();this.button.focus()}.bind(this))}.bind(this));this.button.addEventListener("click",this.toggle.bind(this));this.button.addEventListener("keydown",function(e){if(e.keyCode===40){if(this.menu.hidden){this.open()}else{this.menu.querySelector(":not([disabled])").focus()}}if(e.keyCode===38){this.close()}}.bind(this));this._listeners={}}MenuButton.prototype.open=function(){this.button.setAttribute("aria-expanded",true);this.menu.hidden=false;if(this.settings.checkable==="one"){var checked=this.menu.querySelector('[aria-checked="true"]')}if(checked){checked.focus()}else{this.menu.querySelector('[role^="menuitem"]:not([disabled])').focus()}this.outsideClick=function(e){if(!this.menu.contains(e.target)&&!this.button.contains(e.target)){this.close();document.removeEventListener("click",this.outsideClick.bind(this))}}.bind(this);document.addEventListener("click",this.outsideClick.bind(this));this._fire("open");return this};MenuButton.prototype.close=function(){this.button.setAttribute("aria-expanded",false);this.menu.hidden=true;this._fire("close");return this};MenuButton.prototype.toggle=function(){var expanded=this.button.getAttribute("aria-expanded")==="true";return expanded?this.close():this.open()};MenuButton.prototype.choose=function(choice){if(this.settings.checkable==="one"){Array.prototype.forEach.call(this.menuItems,function(menuItem){menuItem.removeAttribute("aria-checked")});choice.setAttribute("aria-checked","true")}if(this.settings.checkable==="many"){var checked=choice.getAttribute("aria-checked")==="true"||false;choice.setAttribute("aria-checked",!checked)}this._fire("choose",choice);return this};MenuButton.prototype._fire=function(type,data){var listeners=this._listeners[type]||[];listeners.forEach(function(listener){listener(data)})};MenuButton.prototype.on=function(type,handler){if(typeof this._listeners[type]==="undefined"){this._listeners[type]=[]}this._listeners[type].push(handler);return this};MenuButton.prototype.off=function(type,handler){var index=this._listeners[type].indexOf(handler);if(index>-1){this._listeners[type].splice(index,1)}return this};if(typeof module!=="undefined"&&typeof module.exports!=="undefined"){module.exports=MenuButton}else if(typeof define==="function"&&define.amd){define("MenuButton",[],function(){return MenuButton})}else if(typeof global==="object"){global.MenuButton=MenuButton}})(this);