(() => { "use strict"; const focusError = document.querySelector("[data-error-field]"); if (focusError) { focusError.focus(); } else { const summary = document.querySelector("[data-error-summary]"); if (summary) summary.focus(); } document.querySelectorAll("[data-loading-form]").forEach((form) => { form.addEventListener("submit", () => { form.setAttribute("aria-busy", "true"); const button = form.querySelector("button[type='submit']"); if (!button) return; button.disabled = true; button.textContent = button.dataset.loadingLabel || "正在加载…"; }); }); document.querySelectorAll("[data-submit-form]").forEach((form) => { form.addEventListener("submit", () => { form.dataset.submitting = "true"; const button = form.querySelector("[data-submit-button]"); if (!button) return; button.disabled = true; button.textContent = button.dataset.loadingLabel || "正在提交…"; }); }); const fileInput = document.querySelector("input[type='file'][name='image']"); const image = document.querySelector("[data-image-preview]"); const placeholder = document.querySelector("[data-image-placeholder]"); const imageName = document.querySelector("[data-image-name]"); let previewURL = ""; if (fileInput && image && placeholder && imageName) { fileInput.addEventListener("change", () => { if (previewURL) URL.revokeObjectURL(previewURL); const file = fileInput.files && fileInput.files[0]; if (!file) { image.hidden = true; placeholder.hidden = false; imageName.textContent = "选择后在本地预览"; return; } previewURL = URL.createObjectURL(file); image.src = previewURL; image.hidden = false; placeholder.hidden = true; imageName.textContent = `${file.name} · ${(file.size / 1024).toFixed(1)} KB`; }); window.addEventListener("pagehide", () => { if (previewURL) URL.revokeObjectURL(previewURL); }); } const dirtyForm = document.querySelector("[data-dirty-form]"); const leaveDialog = document.querySelector("[data-leave-dialog]"); let dirty = false; let destination = ""; if (dirtyForm && leaveDialog) { dirtyForm.addEventListener("input", () => { dirty = true; }); dirtyForm.addEventListener("change", () => { dirty = true; }); dirtyForm.addEventListener("submit", () => { dirty = false; }); document.querySelectorAll("a[href]").forEach((link) => { link.addEventListener("click", (event) => { if (!dirty || link.hasAttribute("data-discard")) return; const target = new URL(link.href, window.location.href); if (target.origin !== window.location.origin) return; event.preventDefault(); destination = target.href; leaveDialog.showModal(); leaveDialog.querySelector("[data-stay]").focus(); }); }); leaveDialog.querySelector("[data-stay]").addEventListener("click", () => { leaveDialog.close(); }); leaveDialog.querySelector("[data-discard]").addEventListener("click", (event) => { event.preventDefault(); dirty = false; window.location.assign(destination || "/tasks"); }); } const openCancel = document.querySelector("[data-open-cancel]"); const cancelDialog = document.querySelector("[data-cancel-dialog]"); if (openCancel && cancelDialog) { openCancel.addEventListener("click", () => { cancelDialog.showModal(); cancelDialog.querySelector("[data-keep-task]").focus(); }); cancelDialog.querySelector("[data-keep-task]").addEventListener("click", () => { cancelDialog.close(); openCancel.focus(); }); } })();