summaryrefslogtreecommitdiff
path: root/src/js/navigation.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/navigation.js')
-rw-r--r--src/js/navigation.js112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/js/navigation.js b/src/js/navigation.js
new file mode 100644
index 0000000..6cc0af9
--- /dev/null
+++ b/src/js/navigation.js
@@ -0,0 +1,112 @@
+/**
+ * File navigation.js.
+ *
+ * Handles toggling the navigation menu for small screens and enables TAB key
+ * navigation support for dropdown menus.
+ */
+( function() {
+ var container, button, menu, links, subMenus, i, len;
+
+ container = document.getElementById( 'site-navigation' );
+ if ( ! container ) {
+ return;
+ }
+
+ button = container.getElementsByTagName( 'button' )[0];
+ if ( 'undefined' === typeof button ) {
+ return;
+ }
+
+ menu = container.getElementsByTagName( 'ul' )[0];
+
+ // Hide menu toggle button if menu is empty and return early.
+ if ( 'undefined' === typeof menu ) {
+ button.style.display = 'none';
+ return;
+ }
+
+ menu.setAttribute( 'aria-expanded', 'false' );
+ if ( -1 === menu.className.indexOf( 'nav-menu' ) ) {
+ menu.className += ' nav-menu';
+ }
+
+ button.onclick = function() {
+ if ( -1 !== container.className.indexOf( 'toggled' ) ) {
+ container.className = container.className.replace( ' toggled', '' );
+ button.setAttribute( 'aria-expanded', 'false' );
+ menu.setAttribute( 'aria-expanded', 'false' );
+ } else {
+ container.className += ' toggled';
+ button.setAttribute( 'aria-expanded', 'true' );
+ menu.setAttribute( 'aria-expanded', 'true' );
+ }
+ };
+
+ // Get all the link elements within the menu.
+ links = menu.getElementsByTagName( 'a' );
+ subMenus = menu.getElementsByTagName( 'ul' );
+
+ // Set menu items with submenus to aria-haspopup="true".
+ for ( i = 0, len = subMenus.length; i < len; i++ ) {
+ subMenus[i].parentNode.setAttribute( 'aria-haspopup', 'true' );
+ }
+
+ // Each time a menu link is focused or blurred, toggle focus.
+ for ( i = 0, len = links.length; i < len; i++ ) {
+ links[i].addEventListener( 'focus', toggleFocus, true );
+ links[i].addEventListener( 'blur', toggleFocus, true );
+ }
+
+ /**
+ * Sets or removes .focus class on an element.
+ */
+ function toggleFocus() {
+ var self = this;
+
+ // Move up through the ancestors of the current link until we hit .nav-menu.
+ while ( -1 === self.className.indexOf( 'nav-menu' ) ) {
+
+ // On li elements toggle the class .focus.
+ if ( 'li' === self.tagName.toLowerCase() ) {
+ if ( -1 !== self.className.indexOf( 'focus' ) ) {
+ self.className = self.className.replace( ' focus', '' );
+ } else {
+ self.className += ' focus';
+ }
+ }
+
+ self = self.parentElement;
+ }
+ }
+
+ /**
+ * Toggles `focus` class to allow submenu access on tablets.
+ */
+ ( function( container ) {
+ var touchStartFn, i,
+ parentLink = container.querySelectorAll( '.menu-item-has-children > a, .page_item_has_children > a' );
+
+ if ( 'ontouchstart' in window ) {
+ touchStartFn = function( e ) {
+ var menuItem = this.parentNode, i;
+
+ if ( ! menuItem.classList.contains( 'focus' ) ) {
+ e.preventDefault();
+ for ( i = 0; i < menuItem.parentNode.children.length; ++i ) {
+ if ( menuItem === menuItem.parentNode.children[i] ) {
+ continue;
+ }
+ menuItem.parentNode.children[i].classList.remove( 'focus' );
+ }
+ menuItem.classList.add( 'focus' );
+ } else {
+ menuItem.classList.remove( 'focus' );
+ }
+ };
+
+ for ( i = 0; i < parentLink.length; ++i ) {
+ parentLink[i].addEventListener( 'touchstart', touchStartFn, false );
+ }
+ }
+ }( container ) );
+} )();