|
/* DOM nodes */ |
|
var mainNav = document.querySelector('.js-main-nav'), |
|
navigationList = document.querySelector('.js-navigation-list'), |
|
navigationLinks = document.querySelectorAll('.js-navigation-link'), |
|
navDetector = document.querySelector('.js-nav-detection'); |
|
|
|
/* Let the browser know it might need to help with the paint perf */ |
|
var hintBrowser = function() { |
|
navigationList.style.willChange = 'transform'; |
|
}; |
|
|
|
var removeHint = function() { |
|
navigationList.style.willChange = 'auto'; |
|
}; |
|
|
|
/* hide the menu to screenreaders, it's already visually hidden */ |
|
navigationList.setAttribute('aria-hidden', 'true'); |
|
|
|
/* Set the initial tabindex of the navigation links to -1 in small viewports */ |
|
Array.prototype.forEach.call(navigationLinks, function(link) { |
|
if(window.getComputedStyle(link).getPropertyValue('padding-top') !== '0px') { |
|
link.tabIndex = -1; |
|
} |
|
}) |
|
|
|
/* Set the tabindex of each navigation link to -1 |
|
* in small viewports so they can't be tabbed through when closed. |
|
* This happens when the viewport changes width affecting nav layout */ |
|
var checkNavOrientation = function() { |
|
if(window.getComputedStyle(navDetector, ':after').getPropertyValue('content')) { |
|
Array.prototype.forEach.call(navigationLinks, function(link) { |
|
link.tabIndex = 0; |
|
}); |
|
} else { |
|
Array.prototype.forEach.call(navigationLinks, function(link) { |
|
if(!navigationList.classList.contains('is-visible')) { |
|
link.tabIndex = -1; |
|
} |
|
}); |
|
} |
|
}; |
|
navDetector.addEventListener('webkitTransitionEnd', checkNavOrientation, false); |
|
navDetector.addEventListener('transitionend', checkNavOrientation, false); |
|
|
|
/* create menu button */ |
|
var createButton = function() { |
|
var button = document.createElement('button'), |
|
text = document.createElement('span'); |
|
button.type = 'button'; |
|
button.setAttribute('aria-expanded', false); |
|
button.setAttribute('aria-controls', 'navigation-list'); |
|
button.className = 'nav__toggle'; |
|
button.setAttribute('aria-label', 'Menu'); |
|
text.textContent = 'Menu'; |
|
text.className = 'nav__toggle-text'; |
|
text.setAttribute('aria-hidden', 'true'); |
|
button.appendChild(text); |
|
button.addEventListener('click', toggleLinks); |
|
button.addEventListener('mouseenter', hintBrowser); |
|
button.addEventListener('focus', hintBrowser); |
|
return button; |
|
}; |
|
|
|
/* Toggle navigation links in and out of view in small viewports */ |
|
var toggleLinks = function(e) { |
|
e.stopPropagation(); |
|
var expanded = this.getAttribute('aria-expanded') === 'true' || false, |
|
hidden = navigationList.getAttribute('aria-hidden') === 'true' || false; |
|
this.setAttribute('aria-expanded', !expanded); |
|
navigationList.setAttribute('aria-hidden', !hidden); |
|
navigationList.classList.toggle('is-visible'); |
|
Array.prototype.forEach.call(navigationLinks, function(link) { |
|
link.tabIndex = link.tabIndex === -1 ? 0 : -1; |
|
}); |
|
if(!navigationList.classList.contains('is-visible')) { |
|
removeHint(); |
|
} |
|
}; |
|
|
|
/* Close navigation when a click happens outside it */ |
|
var closeNav = function(e) { |
|
if(e.target !== 'a.nav__link.js-navigation-link') { |
|
navigationList.classList.remove('is-visible'); |
|
Array.prototype.forEach.call(navigationLinks, function(link) { |
|
link.tabIndex = -1; |
|
}); |
|
} |
|
}; |
|
|
|
/* Add listener to close on presses outside the nav */ |
|
if(window.matchMedia('(max-width:54.375em)').matches) { |
|
document.body.addEventListener('click', closeNav); |
|
document.body.addEventListener('click', removeHint); |
|
} |
|
|
|
/* insert button into DOM and hide links */ |
|
mainNav.insertBefore(createButton(), navigationList); |