mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-16 17:59:45 -07:00
116 lines
3.0 KiB
JavaScript
116 lines
3.0 KiB
JavaScript
const storagePrefix = "bitview:learn-section";
|
|
|
|
/** @param {string} id */
|
|
function getStorageKey(id) {
|
|
return `${storagePrefix}:${id}`;
|
|
}
|
|
|
|
/** @param {HTMLElement} section */
|
|
function getDetails(section) {
|
|
return /** @type {HTMLDetailsElement} */ (
|
|
section.querySelector(":scope > details")
|
|
);
|
|
}
|
|
|
|
/** @param {HTMLElement} section */
|
|
function getHash(section) {
|
|
return `#${section.id}`;
|
|
}
|
|
|
|
/**
|
|
* @param {HTMLElement} main
|
|
* @param {HTMLElement} section
|
|
*/
|
|
function getNavDetails(main, section) {
|
|
const anchor = main.querySelector(`nav a[href="${getHash(section)}"]`);
|
|
const summary = anchor?.parentElement;
|
|
|
|
return summary?.localName === "summary" ? summary.parentElement : null;
|
|
}
|
|
|
|
/**
|
|
* @param {HTMLElement} main
|
|
* @param {HTMLElement} section
|
|
*/
|
|
function syncNavSection(main, section) {
|
|
const details = getNavDetails(main, section);
|
|
|
|
if (details) details.toggleAttribute("open", getDetails(section).open);
|
|
}
|
|
|
|
/**
|
|
* @param {HTMLElement} main
|
|
* @param {HTMLElement} section
|
|
*/
|
|
function openSection(main, section) {
|
|
let current = section;
|
|
|
|
while (main.contains(current)) {
|
|
const details = current.querySelector(":scope > details");
|
|
if (details) {
|
|
/** @type {HTMLDetailsElement} */ (details).open = true;
|
|
syncNavSection(main, current);
|
|
}
|
|
|
|
const parent = current.parentElement?.closest("section[id]");
|
|
if (!parent) break;
|
|
current = /** @type {HTMLElement} */ (parent);
|
|
}
|
|
}
|
|
|
|
/** @param {HTMLElement} main */
|
|
export function initSectionDetails(main) {
|
|
const sections = [
|
|
...main.querySelectorAll("section[id]:not([data-numbered='false'])"),
|
|
].map((section) => /** @type {HTMLElement} */ (section));
|
|
|
|
for (const section of sections) {
|
|
const saved = localStorage.getItem(getStorageKey(section.id));
|
|
|
|
getDetails(section).open = saved === "1";
|
|
syncNavSection(main, section);
|
|
}
|
|
|
|
main.addEventListener("toggle", (event) => {
|
|
const details = /** @type {HTMLDetailsElement} */ (event.target);
|
|
const section = /** @type {HTMLElement} */ (details.parentElement);
|
|
if (!section.matches("article section[id]")) return;
|
|
|
|
localStorage.setItem(getStorageKey(section.id), details.open ? "1" : "0");
|
|
syncNavSection(main, section);
|
|
main.dispatchEvent(new Event("sectiontoggle"));
|
|
}, { capture: true });
|
|
|
|
/** @param {string} hash */
|
|
function openHash(hash) {
|
|
const target = document.getElementById(hash.slice(1));
|
|
|
|
if (target && main.contains(target)) openSection(main, target);
|
|
}
|
|
|
|
/** @param {string} hash */
|
|
function toggleHash(hash) {
|
|
const target = document.getElementById(hash.slice(1));
|
|
if (!target || !main.contains(target)) return false;
|
|
|
|
const section = /** @type {HTMLElement} */ (target);
|
|
const details = getDetails(section);
|
|
|
|
if (details.open) {
|
|
details.open = false;
|
|
syncNavSection(main, section);
|
|
return false;
|
|
}
|
|
|
|
openSection(main, section);
|
|
return true;
|
|
}
|
|
|
|
if (window.location.hash) openHash(window.location.hash);
|
|
|
|
return {
|
|
openHash,
|
|
toggleHash,
|
|
};
|
|
}
|