dropdown menu
by slawe
HTML
<div class="dropdown" data-directive="dropdown">
<span data-behaviour="label" id="foo">Menu</span>
<div data-behaviour="menu">
<ul>
<li>
<a data-behaviour="option" href="">Option 1</a>
</li>
<li>
<a data-behaviour="option" href="">Option 2</a>
</li>
<li>
<a data-behaviour="option" href="">Option 3</a>
</li>
</ul>
</div>
</div>
CSS
body {
font:normal 1.25em/1.5 Arial, sans-serif;
}
:focus {
outline:1px dotted #EF9600;
outline-offset:1px;
}
/* Dropdown widget */
.dropdown {
width:10em;
border:1px solid #CCC;
}
.dropdown a,
.dropdown > span {
display:block;
padding:.25em .5em;
text-decoration:none;
color:#000;
background-color:#FFF;
}
.dropdown.is-closed > span:after {
content:' \21D2';
}
.dropdown.is-open > span:after {
content:' \21D3';
}
.dropdown a:hover,
.dropdown a:focus {
color:#07B4BA;
background-color:#EEE;
}
.dropdown ul {
margin:0;
padding:0;
list-style-type:0;
}
JavaScript
(function (name, context, definition) {
if (typeof define === 'function' && define.amd) {
define(definition);
}
else if (typeof module !== 'undefined' && module.exports) {
module.exports = definition();
}
else {
context[name] = definition();
}
})('Dropdown', this, function() {
/**
* Dropdown
* @description Dropdown menus. Keyboard accessible with ARIA hints.
* @constructor
* @param element
*/
var Dropdown = function(element) {
this.target = element;
this.label = element.querySelector('[data-behaviour=label]');
this.menu = element.querySelector('[data-behaviour=menu]');
this.options = element.querySelectorAll('[data-behaviour=option]');
if (this.open === undefined) {
this._init();
}
};
/**
* Init
* @private
*/
Dropdown.prototype._init = function() {
var i, len;
var self = this;
this.target.className+= ' is-closed';
this.label.style.cursor = 'pointer';
this.label.setAttribute('tabindex', 0);
this.label.setAttribute('role', 'button');
this.label.setAttribute('aria-expanded', false);
this.listener = function(e) {
var isMouse = e.type === 'click';
var isTouch = e.type === 'touchend' && e.changedTouches.length === 1;
var isKeyboard = e.type === 'keyup' && e.keyCode === 13;
if (isMouse || isTouch || isKeyboard) {
if (e.preventDefault) {
e.preventDefault();
}
else {
e.returnValue = false;
}
self.toggle();
}
};
var events = ['click', 'touchend'];
// If the label is 'clickable' then keyboard support should be implied
// <http://bit.ly/Zgip9P>
var nodeType = this.label.tagName.toLowerCase();
if (nodeType !==...