left4me/l4d2web/static/js/file-tree.js
mwiegand 2ab54a3800
fix(l4d2-web): file tree fetches in plain JS — vendored htmx is a stub
The vendored static/vendor/htmx.min.js turned out to be a 33-byte
placeholder, so the hx-get/hx-target/hx-trigger attributes on the
overlay file tree's folder buttons were inert: clicks rotated the
chevron (own JS) but never fetched. Switch the lazy-load to a
~30-line plain-JS handler in static/js/file-tree.js that fetches
button.dataset.filesUrl on first expand and dedupes via dataset.loaded.
Update the spec/plan to match. Route + partial contracts unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 20:23:04 +02:00

40 lines
1.6 KiB
JavaScript

// Lazy-loaded collapsible file tree on overlay detail pages.
//
// One delegated click handler on document. Each `.file-tree-toggle` button
// carries `data-files-url`. First expand fires a fetch and innerHTMLs the
// returned partial into the next `.file-tree-children`; subsequent clicks
// just toggle visibility — no re-fetch.
(function () {
document.addEventListener("click", function (event) {
const button = event.target.closest(".file-tree-toggle");
if (!button) return;
const children = button.nextElementSibling;
if (!children || !children.classList.contains("file-tree-children")) return;
const wasExpanded = button.getAttribute("aria-expanded") === "true";
button.setAttribute("aria-expanded", wasExpanded ? "false" : "true");
children.hidden = wasExpanded;
if (wasExpanded) return; // collapsing — nothing to fetch
if (button.dataset.loaded === "1") return; // already populated
const url = button.dataset.filesUrl;
if (!url) return;
button.dataset.loaded = "1"; // optimistic — prevents duplicate fetches on rapid clicks
fetch(url, { headers: { Accept: "text/html" }, credentials: "same-origin" })
.then(function (response) {
if (!response.ok) throw new Error("HTTP " + response.status);
return response.text();
})
.then(function (html) {
children.innerHTML = html;
})
.catch(function (err) {
delete button.dataset.loaded; // allow retry
children.innerHTML =
'<p class="muted">Failed to load directory contents.</p>';
console.error("file-tree:", err);
});
});
})();