123 lines
4.2 KiB
JavaScript
123 lines
4.2 KiB
JavaScript
(() => {
|
|
"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();
|
|
}
|
|
|
|
const passwordToggle = document.querySelector("[data-password-toggle]");
|
|
if (passwordToggle) {
|
|
const password = document.getElementById(
|
|
passwordToggle.getAttribute("aria-controls"),
|
|
);
|
|
passwordToggle.addEventListener("click", () => {
|
|
const showing = password.type === "text";
|
|
password.type = showing ? "password" : "text";
|
|
passwordToggle.textContent = showing ? "显示" : "隐藏";
|
|
passwordToggle.setAttribute("aria-pressed", String(!showing));
|
|
});
|
|
}
|
|
|
|
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();
|
|
});
|
|
}
|
|
})();
|