service detail change - md docs and toggable sections.

This commit is contained in:
JiriUhlir
2026-08-03 11:47:38 +02:00
parent f67a3fc993
commit eb7ee612c3
4 changed files with 613 additions and 105 deletions
+81
View File
@@ -126,6 +126,87 @@ document.addEventListener("click", (event) => {
}
});
// Sbalitelné sekce detailu služby: odkaz s kotvou (#metadata) musí cílovou sekci i otevřít,
// jinak by prohlížeč skočil na zavřený <details> a uživatel by neviděl žádný obsah.
function openHashSection() {
let hash = window.location.hash.slice(1);
if (!hash) {
return;
}
try {
hash = decodeURIComponent(hash);
} catch (error) {
return;
}
const target = document.getElementById(hash);
if (!target) {
return;
}
let node = target;
while (node) {
if (node.tagName === "DETAILS") {
node.open = true;
}
node = node.parentElement;
}
target.scrollIntoView();
}
window.addEventListener("hashchange", openHashSection);
document.addEventListener("DOMContentLoaded", openHashSection);
// Obsah načítaný až při rozbalení (seznam .md souborů a jejich náhledy). Načte se jen jednou;
// při chybě se příznak vrátí, aby šlo zkusit znovu dalším rozbalením.
function loadLazyPanel(panel) {
if (panel.dataset.lazyLoaded === "1") {
return;
}
panel.dataset.lazyLoaded = "1";
const url = panel.dataset.lazySrc;
panel.innerHTML = '<p class="muted">Načítám obsah</p>';
fetch(url, { headers: { "X-Requested-With": "fetch" } })
.then((response) => {
if (!response.ok) {
throw new Error("HTTP " + response.status);
}
return response.text();
})
.then((text) => {
panel.innerHTML = text;
})
.catch((error) => {
panel.dataset.lazyLoaded = "";
const message = document.createElement("p");
message.className = "alert alert-danger";
message.textContent = "Obsah se nepodařilo načíst: " + (error.message || error);
panel.replaceChildren(message);
});
}
// Událost toggle nebublá, proto ji odchytáváme v capture fázi na dokumentu.
document.addEventListener(
"toggle",
(event) => {
const details = event.target;
if (typeof HTMLDetailsElement === "undefined" || !(details instanceof HTMLDetailsElement) || !details.open) {
return;
}
// Jen panely patřící přímo této sekci - vnořené soubory se načtou až po svém rozbalení.
for (const panel of details.querySelectorAll("[data-lazy-src]")) {
if (panel.closest("details") === details) {
loadLazyPanel(panel);
}
}
},
true
);
function setFormDisabled(form, disabled) {
for (const field of form.querySelectorAll("input, select, textarea, button")) {
field.disabled = disabled;