| ;(function () { |
| 'use strict' |
| |
| var navContainer = document.querySelector('.nav-container') |
| var navToggle = document.querySelector('.nav-toggle') |
| |
| navToggle.addEventListener('click', showNav) |
| // NOTE don't let click events propagate outside of nav container |
| navContainer.addEventListener('click', concealEvent) |
| |
| var menuPanel = navContainer.querySelector('[data-panel=menu]') |
| if (!menuPanel) return |
| var nav = navContainer.querySelector('.nav') |
| |
| var currentPageItem = menuPanel.querySelector('.is-current-page') |
| if (currentPageItem) { |
| activateCurrentPath(currentPageItem) |
| scrollItemToMidpoint(menuPanel, currentPageItem.querySelector('.nav-link')) |
| } else { |
| menuPanel.scrollTop = 0 |
| } |
| |
| find(menuPanel, '.nav-item-toggle').forEach(function (btn) { |
| var li = btn.parentElement |
| btn.addEventListener('click', toggleActive.bind(li)) |
| var navItemSpan = findNextElement(btn, '.nav-text') |
| if (navItemSpan) { |
| navItemSpan.style.cursor = 'pointer' |
| navItemSpan.addEventListener('click', toggleActive.bind(li)) |
| } |
| }) |
| |
| nav.querySelector('.context').addEventListener('click', function () { |
| var currentPanel = nav.querySelector('.is-active[data-panel]') |
| var activatePanel = currentPanel.dataset.panel === 'menu' ? 'explore' : 'menu' |
| currentPanel.classList.toggle('is-active') |
| nav.querySelector('[data-panel=' + activatePanel + ']').classList.toggle('is-active') |
| }) |
| |
| // NOTE prevent text from being selected by double click |
| menuPanel.addEventListener('mousedown', function (e) { |
| if (e.detail > 1) e.preventDefault() |
| }) |
| |
| function activateCurrentPath (navItem) { |
| var ancestorClasses |
| var ancestor = navItem.parentNode |
| while (!(ancestorClasses = ancestor.classList).contains('nav-menu')) { |
| if (ancestor.tagName === 'LI' && ancestorClasses.contains('nav-item')) { |
| ancestorClasses.add('is-active', 'is-current-path') |
| } |
| ancestor = ancestor.parentNode |
| } |
| navItem.classList.add('is-active') |
| } |
| |
| function toggleActive () { |
| this.classList.toggle('is-active') |
| } |
| |
| function showNav (e) { |
| if (navToggle.classList.contains('is-active')) return hideNav(e) |
| var html = document.documentElement |
| html.classList.add('is-clipped--nav') |
| navToggle.classList.add('is-active') |
| navContainer.classList.add('is-active') |
| html.addEventListener('click', hideNav) |
| concealEvent(e) |
| } |
| |
| function hideNav (e) { |
| var html = document.documentElement |
| html.classList.remove('is-clipped--nav') |
| navToggle.classList.remove('is-active') |
| navContainer.classList.remove('is-active') |
| html.removeEventListener('click', hideNav) |
| concealEvent(e) |
| } |
| |
| // NOTE don't let event get picked up by window click listener |
| function concealEvent (e) { |
| e.stopPropagation() |
| } |
| |
| function scrollItemToMidpoint (panel, el) { |
| var rect = panel.getBoundingClientRect() |
| var effectiveHeight = rect.height |
| var navStyle = window.getComputedStyle(nav) |
| if (navStyle.position === 'sticky') effectiveHeight -= rect.top - parseFloat(navStyle.top) |
| panel.scrollTop = Math.max(0, (el.getBoundingClientRect().height - effectiveHeight) * 0.5 + el.offsetTop) |
| } |
| |
| function find (from, selector) { |
| return [].slice.call(from.querySelectorAll(selector)) |
| } |
| |
| function findNextElement (from, selector) { |
| var el |
| if ('nextElementSibling' in from) { |
| el = from.nextElementSibling |
| } else { |
| el = from |
| while ((el = el.nextSibling) && el.nodeType !== 1); |
| } |
| return el && selector ? el[el.matches ? 'matches' : 'msMatchesSelector'](selector) && el : el |
| } |
| })() |