nc-planner/scripts/menu-bar.js

110 lines
3.6 KiB
JavaScript

import { positionAsTooltip } from "./tooltip.js";
import { registerLoadCallback } from "./main.js";
let activeMenuBar = null;
registerLoadCallback(() => {
document.querySelectorAll(".menu-bar").forEach(menuBar => {
menuBar.querySelectorAll("button").forEach(button => {
button.setAttribute("tabindex", "-1");
button.replaceChildren(createAltSpan(button, button.innerText));
button.addEventListener("click", e => {
menuBar.classList.remove("active");
menuBar.querySelectorAll(".active")
.forEach(elem => elem.classList.remove("active"));
activeMenuBar = null;
});
button.addEventListener("mouseenter", () => {
if (!activeMenuBar) return;
button.parentElement.querySelectorAll(".active")
.forEach(elem => elem.classList.remove("active"));
});
});
menuBar.querySelectorAll("[data-section]").forEach(section => {
const button = document.createElement("button");
button.setAttribute("tabindex", "-1");
button.dataset.forSection = "";
button.appendChild(createAltSpan(section, section.dataset.section));
section.parentElement.insertBefore(button, section);
section.addEventListener("click", e => e.stopPropagation());
button.addEventListener("click", e => e.stopPropagation());
function updateActive() {
if (!activeMenuBar) return;
button.parentElement.querySelectorAll(".active")
.forEach(elem => elem.classList.remove("active"));
button.classList.add("active");
section.classList.add("active");
positionAsTooltip(button, section, {
horizontal: section.parentElement === menuBar ? "left" : "right",
vertical: section.parentElement === menuBar ? "bottom" : "top",
});
}
if (section.parentElement === menuBar) {
button.addEventListener("click", () => {
if (section.classList.contains("active")) {
menuBar.classList.remove("active");
menuBar.querySelectorAll(".active")
.forEach(elem => elem.classList.remove("active"));
activeMenuBar = null;
} else {
menuBar.querySelectorAll(".active")
.forEach(elem => elem.classList.remove("active"));
menuBar.classList.add("active");
section.classList.add("active");
window.addEventListener("click", handleGlobalClick);
activeMenuBar = menuBar;
updateActive();
}
});
}
button.addEventListener("mouseenter", updateActive);
});
});
// TODO: keyboard navigation with alt and arrow keys
});
function handleGlobalClick() {
console.log("Global clicked");
if (!activeMenuBar) return;
activeMenuBar.classList.remove("active");
activeMenuBar.querySelectorAll(".active")
.forEach(section => section.classList.remove("active"));
activeMenuBar = null;
window.removeEventListener("click", handleGlobalClick);
}
function createAltSpan(element, text) {
const altKey = element.dataset.alt;
if (!altKey) {
const span = document.createElement("span");
span.appendChild(document.createTextNode(text));
return span;
}
const [ , before, key, after ] = new RegExp(`^(.*)(${altKey})(.*)$`, "i").exec(text);
const span = document.createElement("span");
if (before) {
span.appendChild(document.createTextNode(before));
}
const underlineSpan = document.createElement("span");
underlineSpan.innerText = key;
underlineSpan.classList.add("alt-key");
span.appendChild(underlineSpan);
if (after) {
span.appendChild(document.createTextNode(after));
}
return span;
}