From 102f68e75bdfc7efb63025700f51107002c8e66c Mon Sep 17 00:00:00 2001 From: Dan Allen Date: Fri, 17 Nov 2017 20:10:27 -0700 Subject: [PATCH] add JavaScript for navigation menu --- src/css/navigation-domain.css | 1 + src/js/01-navigation.js | 122 ++++++++++++++++++++++++++++++++++++++++ src/partials/footer-scripts.hbs | 1 + 3 files changed, 124 insertions(+) create mode 100644 src/js/01-navigation.js diff --git a/src/css/navigation-domain.css b/src/css/navigation-domain.css index 9d7b10a..9168177 100644 --- a/src/css/navigation-domain.css +++ b/src/css/navigation-domain.css @@ -27,6 +27,7 @@ html.is-clipped--nav { list-style: none; margin: 0; padding: 0; + width: 100%; } .nav-list .nav-list { diff --git a/src/js/01-navigation.js b/src/js/01-navigation.js new file mode 100644 index 0000000..df8d00f --- /dev/null +++ b/src/js/01-navigation.js @@ -0,0 +1,122 @@ +;(function () { + 'use strict' + + var navContainer = document.querySelector('.navigation-container') + var navToggle = document.querySelector('.navigation-toggle') + var domainNav = navContainer.querySelector('[data-panel=domain]') + var state = getState() || {} + + navContainer.querySelector('.current').addEventListener('click', function () { + var currentPanel = document.querySelector('.navigation .is-active[data-panel]') + var selectPanel = currentPanel.dataset.panel === 'domain' ? 'explore' : 'domain' + currentPanel.classList.toggle('is-active') + document.querySelector('.navigation [data-panel=' + selectPanel + ']').classList.toggle('is-active') + }) + + navToggle.addEventListener('click', toggleNavigation) + // don't let click events propagate outside of navigation container + navContainer.addEventListener('click', concealEvent) + + find('.nav-menu').forEach(function (navTree) { + var panel = navTree.parentElement.dataset.panel + find('.nav-item', navTree).forEach(function (item, idx) { + item.setAttribute('data-id', [panel, item.dataset.depth, idx].join('-')) + }) + }) + + find('.nav-toggle').forEach(function (btn) { + var li = btn.parentElement + btn.addEventListener('click', function () { + li.classList.toggle('is-active') + state.expandedItems = getExpandedItems() + saveState() + }) + }) + + if (!state.expandedItems) { + state.expandedItems = getExpandedItems() + saveState() + } + + state.expandedItems.forEach(function (itemId) { + var item = document.querySelector('.nav-item[data-id="' + itemId + '"]') + if (item) { + item.classList.add('is-active') + } + }) + + saveState() + + scrollItemIntoView(state.scroll || 0, domainNav, document.querySelector('.nav-menu .is-current-page .nav-link')) + domainNav.addEventListener('scroll', function () { + state.scroll = Math.round(domainNav.scrollTop) + saveState() + }) + + function toggleNavigation (e) { + if (navToggle.classList.contains('is-active')) { + return closeNavigation(e) + } + document.documentElement.classList.add('is-clipped--nav') + navToggle.classList.add('is-active') + navContainer.classList.add('is-active') + window.addEventListener('click', closeNavigation) + // don't let this event get picked up by window click listener + concealEvent(e) + } + + function closeNavigation (e) { + if (e.which === 3 || e.button === 2) return + document.documentElement.classList.remove('is-clipped--nav') + navToggle.classList.remove('is-active') + navContainer.classList.remove('is-active') + window.removeEventListener('click', closeNavigation) + // don't let this event get picked up by window click listener + concealEvent(e) + } + + function concealEvent (e) { + e.stopPropagation() + } + + function getExpandedItems () { + return find('.nav-menu .is-active').map(function (item) { + return item.dataset.id + }) + } + + function getState (domain, version) { + var data = window.sessionStorage.getItem('nav-state') + if (data) { + return JSON.parse(data) + } + } + + function saveState () { + window.sessionStorage.setItem('nav-state', JSON.stringify(state)) + } + + function scrollItemIntoView (scrollPosition, parent, el) { + if (el === null) { + return (parent.scrollTop = scrollPosition) + } + + var margin = 10 + + var overTheTop = el.offsetTop - scrollPosition < 0 + var belowTheBottom = el.offsetTop - scrollPosition + el.offsetHeight > parent.offsetHeight + + if (overTheTop) { + parent.scrollTop = el.offsetTop - margin + } else if (belowTheBottom) { + parent.scrollTop = el.offsetTop - (parent.offsetHeight - el.offsetHeight) + margin + } else { + parent.scrollTop = scrollPosition + } + } + + function find (selector, from) { + from = from || document + return [].slice.call(from.querySelectorAll(selector)) + } +})() diff --git a/src/partials/footer-scripts.hbs b/src/partials/footer-scripts.hbs index 385a43b..9e9f561 100644 --- a/src/partials/footer-scripts.hbs +++ b/src/partials/footer-scripts.hbs @@ -1,2 +1,3 @@ + -- 2.11.0