2cf4405ce0
* Don't show the loading indicator when intercepted href="#" links have been clicked (e.g. like buttons, settings tabs)
194 lines
6.5 KiB
JavaScript
194 lines
6.5 KiB
JavaScript
// Bulma CSS fixes and features for nonshy.
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
// Make all off-site hyperlinks open in a new tab.
|
|
(document.querySelectorAll("a") || []).forEach(node => {
|
|
let href = node.attributes.href;
|
|
if (href === undefined) return;
|
|
href = href.textContent;
|
|
if (href.indexOf("http:") === 0 || href.indexOf("https:") === 0) {
|
|
node.target = "_blank";
|
|
}
|
|
});
|
|
|
|
// If we are a PWA in standalone mode, clicking on-site links shows our custom loading spinner.
|
|
if (window.matchMedia('(display-mode: standalone)').matches) {
|
|
const spinner = document.querySelector("#nonshy-pwa-loader");
|
|
(document.querySelectorAll("a, form") || []).forEach(node => {
|
|
// Links: only on-site ones.
|
|
if (node.tagName === 'A') {
|
|
let href = node.attributes.href?.textContent;
|
|
if (!href) return;
|
|
if (node.target === '_blank' || href.indexOf('#') === 0 || href.indexOf(location.pathname) === 0) return;
|
|
}
|
|
|
|
// Show our spinner on click or submit.
|
|
node.addEventListener(node.tagName === 'A' ? 'click' : 'submit', () => {
|
|
spinner.style.display = "block";
|
|
});
|
|
});
|
|
}
|
|
|
|
// Hamburger menu script.
|
|
(function () {
|
|
// Get all "navbar-burger" elements
|
|
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
|
|
|
|
// Add a click event on each of them
|
|
$navbarBurgers.forEach(el => {
|
|
el.addEventListener('click', () => {
|
|
|
|
// Get the target from the "data-target" attribute
|
|
const target = el.dataset.target;
|
|
const $target = document.getElementById(target);
|
|
|
|
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
|
|
el.classList.toggle('is-active');
|
|
$target.classList.toggle('is-active');
|
|
|
|
});
|
|
});
|
|
})();
|
|
|
|
// Allow the "More" drop-down to work on mobile (toggle is-active on click instead of requiring mouseover)
|
|
(function () {
|
|
const menu = document.querySelector("#navbar-more"),
|
|
userMenu = document.querySelector("#navbar-user"),
|
|
activeClass = "is-active";
|
|
|
|
if (!menu) return;
|
|
|
|
// Click the "More" menu to permanently toggle the menu.
|
|
menu.addEventListener("click", (e) => {
|
|
if (menu.classList.contains(activeClass)) {
|
|
menu.classList.remove(activeClass);
|
|
} else {
|
|
menu.classList.add(activeClass);
|
|
}
|
|
e.stopPropagation();
|
|
});
|
|
|
|
// Touching the user drop-down button toggles it.
|
|
if (userMenu !== null) {
|
|
userMenu.addEventListener("touchstart", (e) => {
|
|
// On mobile/tablet screens they had to hamburger menu their way here anyway, let it thru.
|
|
if (screen.width < 1024) {
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
if (userMenu.classList.contains(activeClass)) {
|
|
userMenu.classList.remove(activeClass);
|
|
} else {
|
|
userMenu.classList.add(activeClass);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Touching a link from the user menu lets it click thru.
|
|
(document.querySelectorAll(".navbar-dropdown") || []).forEach(node => {
|
|
node.addEventListener("touchstart", (e) => {
|
|
e.stopPropagation();
|
|
});
|
|
});
|
|
|
|
// Clicking the rest of the body will close an active navbar-dropdown.
|
|
(document.addEventListener("click", (e) => {
|
|
(document.querySelectorAll(".navbar-dropdown.is-active, .navbar-item.is-active") || []).forEach(node => {
|
|
node.classList.remove(activeClass);
|
|
});
|
|
}));
|
|
})();
|
|
|
|
// Dropdown menus.
|
|
(document.querySelectorAll(".dropdown") || []).forEach(node => {
|
|
// If this dropdown is near the bottom of the page, make it open upwards.
|
|
if (!node.classList.contains("is-up") && !node.classList.contains("is-right")) {
|
|
let offsetTop = node.offsetTop,
|
|
body = document.body,
|
|
html = document.documentElement,
|
|
pageHeight = Math.max(body.scrollHeight, body.offsetHeight,
|
|
html.clientHeight, html.scrollHeight, html.offsetHeight,
|
|
);
|
|
if (pageHeight - offsetTop < 450) {
|
|
node.classList.add("is-up");
|
|
}
|
|
}
|
|
|
|
const button = node.querySelector("button");
|
|
button.addEventListener("click", (e) => {
|
|
node.classList.toggle("is-active");
|
|
})
|
|
});
|
|
|
|
// Common event handlers for bulma modals.
|
|
(document.querySelectorAll(".modal-background, .modal-close, .photo-modal") || []).forEach(node => {
|
|
const target = node.closest(".modal");
|
|
if (target.classList.contains("vue-managed") || target.classList.contains("nonshy-important-modal")) {
|
|
return;
|
|
}
|
|
node.addEventListener("click", () => {
|
|
target.classList.remove("is-active");
|
|
});
|
|
});
|
|
|
|
// Collapsible cards for mobile view (e.g. People Search filters box)
|
|
(document.querySelectorAll(".card.nonshy-collapsible-mobile") || []).forEach(node => {
|
|
const header = node.querySelector(".card-header"),
|
|
body = node.querySelector(".card-content"),
|
|
icon = header.querySelector("button.card-header-icon > .icon > i"),
|
|
always = node.classList.contains("nonshy-collapsible-always");
|
|
|
|
// Icon classes.
|
|
const iconExpanded = "fa-angle-up",
|
|
iconContracted = "fa-angle-down";
|
|
|
|
// If we are already on mobile, hide the body now.
|
|
if (screen.width <= 768 || always) {
|
|
body.style.display = "none";
|
|
if (icon !== null) {
|
|
icon.classList.remove(iconExpanded);
|
|
icon.classList.add(iconContracted);
|
|
}
|
|
}
|
|
|
|
// Add click toggle handler to the header.
|
|
header.addEventListener("click", () => {
|
|
if (body.style.display === "none") {
|
|
body.style.display = "block";
|
|
if (icon !== null) {
|
|
icon.classList.remove(iconContracted);
|
|
icon.classList.add(iconExpanded);
|
|
}
|
|
} else {
|
|
body.style.display = "none";
|
|
if (icon !== null) {
|
|
icon.classList.remove(iconExpanded);
|
|
icon.classList.add(iconContracted);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// Reveal all blurred images on click.
|
|
(document.querySelectorAll(".blurred-explicit") || []).forEach(node => {
|
|
node.addEventListener("click", e => {
|
|
if (node.classList.contains("blurred-explicit")) {
|
|
node.classList.remove("blurred-explicit");
|
|
if (node.tagName !== "VIDEO") {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
}
|
|
});
|
|
|
|
// Video tag: autoplay is disabled when blurred, onClick doesn't fire,
|
|
// set the handler for onPlay.
|
|
node.addEventListener("play", e => {
|
|
if (node.classList.contains("blurred-explicit")) {
|
|
node.classList.remove("blurred-explicit");
|
|
}
|
|
});
|
|
});
|
|
});
|