Commit 8c44a093 authored by Dan Allen's avatar Dan Allen

merge !88

resolves #86 drop nav state functionality
parents c37fc009 44b788ca
Pipeline #72088166 passed with stages
in 4 minutes and 23 seconds
.nav-container {
display: none;
position: fixed;
top: var(--navbar-height);
left: 0;
width: 100%;
font-size: 0.9375rem;
z-index: var(--z-index-nav);
visibility: hidden;
}
@media screen and (min-width: 769px) {
......@@ -19,14 +19,14 @@
.nav-container {
font-size: 0.8125rem;
flex: none;
display: block;
position: static;
top: 0;
visibility: visible;
}
}
.nav-container.is-active {
display: block;
visibility: visible;
}
.nav {
......
......@@ -4,153 +4,94 @@
var navContainer = document.querySelector('.nav-container')
var navToggle = document.querySelector('.nav-toggle')
navToggle.addEventListener('click', toggleNavigation)
// don't let click events propagate outside of nav container
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 navState = getNavState()
var menuState = getMenuState(navState, navContainer.dataset.component, navContainer.dataset.version)
navContainer.querySelector('.context').addEventListener('click', function () {
var currentPanel = navContainer.querySelector('.is-active[data-panel]')
var activatePanel = currentPanel.dataset.panel === 'menu' ? 'explore' : 'menu'
currentPanel.classList.toggle('is-active')
navContainer.querySelector('[data-panel=' + activatePanel + ']').classList.toggle('is-active')
})
var currentPageItem = menuPanel.querySelector('.is-current-page')
if (currentPageItem) {
activateCurrentPath(currentPageItem)
scrollItemToMidpoint(menuPanel, currentPageItem.querySelector('.nav-link'))
} else {
menuPanel.scrollTop = 0
}
find('.nav-item-toggle', menuPanel).forEach(function (btn) {
find(menuPanel, '.nav-item-toggle').forEach(function (btn) {
var li = btn.parentElement
btn.addEventListener('click', function () {
li.classList.toggle('is-active')
menuState.expandedItems = getExpandedItems()
saveNavState()
})
btn.addEventListener('click', toggleActive.bind(li))
var navItemSpan = findNextElement(btn, '.nav-text')
if (navItemSpan) {
navItemSpan.style.cursor = 'pointer'
navItemSpan.addEventListener('click', function () {
li.classList.toggle('is-active')
menuState.expandedItems = getExpandedItems()
saveNavState()
})
navItemSpan.addEventListener('click', toggleActive.bind(li))
}
})
find('.nav-item', menuPanel).forEach(function (item, idx) {
item.setAttribute('data-id', 'menu-' + item.dataset.depth + '-' + idx)
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')
})
var expandedItems = menuState.expandedItems || (menuState.expandedItems = [])
if (expandedItems.length) {
find(
expandedItems
.map(function (itemId) {
return '.nav-item[data-id="' + itemId + '"]'
})
.join(','),
menuPanel
).forEach(function (item) {
item.classList.add('is-active')
})
}
var currentPageItem = menuPanel.querySelector('.is-current-page')
if (currentPageItem) {
activateCurrentPath(currentPageItem).forEach(function (itemId) {
if (expandedItems.indexOf(itemId) < 0) expandedItems.push(itemId)
})
}
saveNavState()
scrollItemIntoView(menuState.scroll || 0, menuPanel, currentPageItem && currentPageItem.querySelector('.nav-link'))
menuPanel.addEventListener('scroll', function () {
menuState.scroll = Math.round(menuPanel.scrollTop)
saveNavState()
// NOTE prevent text from being selected by double click
menuPanel.addEventListener('mousedown', function (e) {
if (e.detail > 1) e.preventDefault()
})
function activateCurrentPath (navItem) {
var ids = [navItem.dataset.id]
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')
ids.push(ancestor.dataset.id)
}
ancestor = ancestor.parentNode
}
navItem.classList.add('is-active')
return ids
}
function toggleNavigation (e) {
if (navToggle.classList.contains('is-active')) return closeNavigation(e)
document.documentElement.classList.add('is-clipped--nav')
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')
window.addEventListener('click', closeNavigation)
// don't let this event get picked up by window click listener
html.addEventListener('click', hideNav)
concealEvent(e)
}
function closeNavigation (e) {
if (e.which === 3 || e.button === 2) return
document.documentElement.classList.remove('is-clipped--nav')
function hideNav (e) {
var html = document.documentElement
html.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
html.removeEventListener('click', hideNav)
concealEvent(e)
}
// NOTE don't let event get picked up by window click listener
function concealEvent (e) {
e.stopPropagation()
}
function getExpandedItems () {
return find('.is-active', menuPanel).map(function (item) {
return item.dataset.id
})
}
function getNavState () {
var data = window.sessionStorage.getItem('nav-state')
return data && (data = JSON.parse(data)).__version__ === '1' ? data : { __version__: '1' }
}
function getMenuState (navState, component, version) {
var key = version + '@' + component
return navState[key] || (navState[key] = {})
}
function saveNavState () {
window.sessionStorage.setItem('nav-state', JSON.stringify(navState))
}
function scrollItemIntoView (scrollPosition, parent, el) {
if (!el) return (parent.scrollTop = scrollPosition)
var margin = 10
//var y = el.getBoundingClientRect().top - parent.getBoundingClientRect().top
var y = el.offsetTop
if (y < scrollPosition) {
parent.scrollTop = y - margin
} else if (y - parent.offsetHeight + el.offsetHeight > scrollPosition) {
parent.scrollTop = y - parent.offsetHeight + el.offsetHeight + margin
} else {
parent.scrollTop = scrollPosition
}
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 (selector, from) {
return [].slice.call((from || document).querySelectorAll(selector))
function find (from, selector) {
return [].slice.call(from.querySelectorAll(selector))
}
function findNextElement (from, selector) {
......
......@@ -12,7 +12,7 @@
e.stopPropagation()
})
window.addEventListener('click', function () {
document.documentElement.addEventListener('click', function () {
selector.classList.remove('is-active')
})
})()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment