<div id="" class="hide " hidden>
<li class="" style="">
<a class="">
</a>
</li>
<li class="" style="">
<a class="">
</a>
</li>
<li class="" style="">
<a class="">
</a>
</li>
</div>
{{#if list}}
<ul id="{{id}}" class="hide {{modifier}}" {{#if hidden}}hidden{{/if}}>
{{> @children}}
</ul>
{{else}}
<div id="{{id}}" class="hide {{modifier}}" {{#if hidden}}hidden{{/if}}>
{{> @children}}
</div>
{{/if}}
{
"id": null,
"modifier": null,
"list": null,
"hidden": "false",
"children": [
{
"component": "li",
"context": {
"children": [
{
"component": "link",
"href": "#"
}
]
}
},
{
"component": "li",
"context": {
"children": [
{
"component": "link",
"href": "#"
}
]
}
},
{
"component": "li",
"context": {
"children": [
{
"component": "link",
"href": "#"
}
]
}
}
]
}
import each from '../../../modules/util/each';
export function toggleHidden(control, target) {
// reverse hidden on dropdown and control
target.hidden = !target.hidden;
control.setAttribute('aria-expanded', !target.hidden);
}
export default function dropdownBehavior(control) {
const dropdown = document.getElementById(control.getAttribute('aria-controls'));
const links = dropdown.querySelectorAll('a, button');
//initial attribute setup
control.setAttribute('aria-expanded', !dropdown.hidden);
//control behavior
control.addEventListener('click', event => {
// Clicks and enter open/close dropdown
event.preventDefault();
toggleHidden(control, dropdown);
});
control.addEventListener('keydown', event => {
// Space will open and close dropdown, escape will close the dropdown if the menu is not hidden
if (event.keyCode === 32 || (event.keyCode === 27 && !dropdown.hidden)) {
event.preventDefault();
toggleHidden(control, dropdown);
}
});
//if dropdown is open, losing focus of control and not entering dropdown will close it.
control.addEventListener('focusout', event => {
if (event.relatedTarget && !dropdown.hidden) {
let isInThisDropdown = false;
each(links, link => {
if (event.relatedTarget === link) isInThisDropdown = true;
});
if (event.relatedTarget === control) isInThisDropdown = true;
if (!isInThisDropdown) toggleHidden(control, dropdown);
} else if (!event.relatedTarget && !dropdown.hidden) {
toggleHidden(control, dropdown);
}
});
each(links, link => {
link.addEventListener('keydown', event => {
// Escape inside the dropdown will close the dropdown and focus the control
if (event.keyCode === 27) {
//we prevent default, so we don't exit maximized screens on safari
event.preventDefault();
toggleHidden(control, dropdown);
control.focus();
}
});
link.addEventListener('focusout', event => {
if (event.relatedTarget) {
let isInThisDropdown = false;
each(links, link => {
if (event.relatedTarget === link) isInThisDropdown = true;
});
if (event.relatedTarget === control) isInThisDropdown = true;
if (!isInThisDropdown) toggleHidden(control, dropdown);
} else if (!event.relatedTarget && !dropdown.hidden) {
toggleHidden(control, dropdown);
}
});
});
}
Creates container that can appear & dissappear with a control
<a>
or <button>
as a control.js-dropdown-control
class to the control.aria-controls
attribute.<a
class="js-dropdown-control"
aria-controls="menu1"
href="https://upload.wikimedia.org/wikipedia/commons/c/c7/Gary_Busey_%281976%29.jpg"
>
link-text
</a>
hidden
on pageload, and the dh
class, to make sure that hidden works.<div>
<a
class="js-dropdown-control"
aria-controls="menu1"
href="https://upload.wikimedia.org/wikipedia/commons/c/c7/Gary_Busey_%281976%29.jpg"
>
Open Menu
</a>
<ul id="menu1" class="dh" hidden>
<li>
<a href="https://www.youtube.com/watch?v=k4KKD_SuLRY">Wild in the Streets</a>
</li>
<li>
<a href="https://www.youtube.com/watch?v=ebW8YA-jq5A">Angels Hard as They Come</a>
</li>
<li>
<a href="https://www.youtube.com/watch?v=nB95pK8TgYw">The Magnificent Seven Ride!</a>
</li>
<li>
<a href="https://www.youtube.com/watch?v=VcCjU3fZTis">The Last American Hero</a>
</li>
</ul>
</div>