Continues the Bookshelf history. The three plugins tracked there are consolidated into umbra-bookshelf/ and this repository becomes the canonical home for the plugin and the theme. bd-bookshelf/ -> theme/ separate artifact, name unchanged (root specs) -> umbra-bookshelf/spec/ aligned to Umbra Bookshelf old plugin zips -> archive/pre-umbra-releases/ Adds a repository README and drops the Bookshelf closure notice.
119 lines
3.7 KiB
JavaScript
119 lines
3.7 KiB
JavaScript
// Copyright 2026 Umbra Tools (umbratools.com)
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
/**
|
|
* Navigation JavaScript
|
|
*
|
|
* @package BD_Murphy
|
|
*/
|
|
(function() {
|
|
'use strict';
|
|
|
|
var container, button, menu, links, i, len;
|
|
|
|
container = document.getElementById('site-nav');
|
|
if (!container) {
|
|
return;
|
|
}
|
|
|
|
button = container.getElementsByClassName('menu-toggle')[0];
|
|
if ('undefined' === typeof button) {
|
|
return;
|
|
}
|
|
|
|
menu = container.getElementsByTagName('ul')[0];
|
|
|
|
if (menu.classList.contains('nav-menu') && window.innerWidth < 768) {
|
|
menu.classList.add('nav-menu-hidden');
|
|
}
|
|
|
|
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');
|
|
menu.classList.add('nav-menu-hidden');
|
|
} else {
|
|
container.className += ' toggled';
|
|
button.setAttribute('aria-expanded', 'true');
|
|
menu.setAttribute('aria-expanded', 'true');
|
|
menu.classList.remove('nav-menu-hidden');
|
|
}
|
|
};
|
|
|
|
// Close menu on click outside
|
|
document.addEventListener('click', function(event) {
|
|
if (!container.contains(event.target)) {
|
|
container.classList.remove('toggled');
|
|
button.setAttribute('aria-expanded', 'false');
|
|
menu.setAttribute('aria-expanded', 'false');
|
|
menu.classList.add('nav-menu-hidden');
|
|
}
|
|
});
|
|
|
|
// Keyboard navigation
|
|
links = menu.getElementsByTagName('a');
|
|
for (i = 0, len = links.length; i < len; i++) {
|
|
links[i].addEventListener('focus', toggleFocus, true);
|
|
links[i].addEventListener('blur', toggleFocus, true);
|
|
}
|
|
|
|
function toggleFocus() {
|
|
var self = this;
|
|
while (-1 === self.className.indexOf('menu-item')) {
|
|
if ('undefined' === typeof self.parentElement) {
|
|
break;
|
|
}
|
|
self = self.parentElement;
|
|
}
|
|
|
|
if (self.classList.contains('current-menu-item')) {
|
|
return;
|
|
}
|
|
|
|
var dropdown = self.querySelector('.sub-menu');
|
|
if (dropdown) {
|
|
dropdown.classList.toggle('focus');
|
|
}
|
|
|
|
var siblings = self.parentElement.children;
|
|
for (i = 0; i < siblings.length; i++) {
|
|
if (siblings[i] !== self) {
|
|
siblings[i].classList.remove('focus');
|
|
}
|
|
}
|
|
|
|
self.classList.toggle('focus');
|
|
}
|
|
|
|
// Sticky nav scroll effect
|
|
var banner = document.querySelector('.header-banner');
|
|
if (banner && document.body.classList.contains('has-sticky-nav')) {
|
|
window.addEventListener('scroll', function() {
|
|
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
if (scrollTop > banner.offsetHeight) {
|
|
container.classList.add('scrolled');
|
|
} else {
|
|
container.classList.remove('scrolled');
|
|
}
|
|
}, { passive: true });
|
|
}
|
|
|
|
// Escape key closes menu
|
|
document.addEventListener('keydown', function(event) {
|
|
if (event.key === 'Escape' && container.classList.contains('toggled')) {
|
|
container.classList.remove('toggled');
|
|
button.setAttribute('aria-expanded', 'false');
|
|
menu.setAttribute('aria-expanded', 'false');
|
|
menu.classList.add('nav-menu-hidden');
|
|
button.focus();
|
|
}
|
|
});
|
|
|
|
})();
|