// Title search runs entirely in the browser: the full list is already in the // DOM, so filtering it needs no request. (function () { function applyFilter() { var box = document.getElementById("search"); if (!box) return; var needle = box.value.trim().toLowerCase(); document.querySelectorAll(".card").forEach(function (card) { var title = (card.dataset.title || "").toLowerCase(); card.hidden = needle !== "" && title.indexOf(needle) === -1; }); } document.addEventListener("input", function (e) { if (e.target && e.target.id === "search") applyFilter(); }); // htmx replaces the list on a tab switch, so re-apply to the new cards. document.body.addEventListener("htmx:afterSwap", applyFilter); })(); function setActiveTab(el) { el.parentElement.querySelectorAll("[role=tab]").forEach(function (t) { t.classList.toggle("active", t === el); }); } // The chapter-edit form and the delete confirm row are the two per-card // disclosure panels; only one makes sense open at a time. function closeCardPanels(key) { var form = document.getElementById("chapter-form-" + key); var confirm = document.getElementById("confirm-row-" + key); if (form) form.hidden = true; if (confirm) confirm.hidden = true; } function toggleChapterForm(key) { var form = document.getElementById("chapter-form-" + key); if (!form) return; var opening = form.hidden; closeCardPanels(key); form.hidden = !opening; if (!form.hidden) form.querySelector("input").focus(); } function toggleConfirmRow(key) { var row = document.getElementById("confirm-row-" + key); if (!row) return; var opening = row.hidden; closeCardPanels(key); row.hidden = !opening; } // A failed favourite/chapter/delete request leaves the card in place (htmx // does not swap on a non-2xx response) but otherwise gives no sign anything // went wrong. Surface it inline instead of leaving the tap looking ignored. (function () { function showError(elt, message) { var card = elt.closest(".card"); var slot = card && card.querySelector(".error-inline"); if (!slot) return; slot.textContent = message; slot.hidden = false; clearTimeout(slot._hideTimer); slot._hideTimer = setTimeout(function () { slot.hidden = true; }, 5000); } document.body.addEventListener("htmx:responseError", function (e) { showError(e.detail.elt, "Couldn't save — try again."); }); document.body.addEventListener("htmx:sendError", function (e) { showError(e.detail.elt, "No connection — try again."); }); })();