tarinai/js/game_dialogs.js
2026-07-29 20:52:11 +09:00

76 lines
3.4 KiB
JavaScript

"use strict";
(function (global) {
const queue = [];
let active = null;
function ensureDialog() {
let dialog = document.getElementById("gameConfirmDialog");
if (dialog) return dialog;
dialog = document.createElement("div");
dialog.id = "gameConfirmDialog";
dialog.className = "field-dialog game-confirm-dialog hidden";
dialog.setAttribute("role", "alertdialog");
dialog.setAttribute("aria-modal", "true");
dialog.setAttribute("aria-labelledby", "gameConfirmDialogTitle");
dialog.setAttribute("aria-describedby", "gameConfirmDialogMessage");
dialog.innerHTML = `
<div class="field-dialog-panel game-confirm-panel">
<h2 id="gameConfirmDialogTitle"></h2>
<p id="gameConfirmDialogMessage" class="field-dialog-lead game-confirm-message"></p>
<div class="field-dialog-actions game-confirm-actions">
<button class="btn" data-game-dialog-cancel type="button"></button>
<button class="btn primary" data-game-dialog-confirm type="button"></button>
</div>
</div>`;
document.body.appendChild(dialog);
dialog.addEventListener("click", event => {
if (!active) return;
if (event.target === dialog || event.target.closest("[data-game-dialog-cancel]")) settle(false);
else if (event.target.closest("[data-game-dialog-confirm]")) settle(true);
});
dialog.addEventListener("tarinai:dialog-close-request", () => { if (active) settle(false); });
return dialog;
}
function pump() {
if (active || !queue.length) return;
active = queue.shift();
const dialog = ensureDialog();
const title = dialog.querySelector("#gameConfirmDialogTitle");
const message = dialog.querySelector("#gameConfirmDialogMessage");
const confirmButton = dialog.querySelector("[data-game-dialog-confirm]");
const cancelButton = dialog.querySelector("[data-game-dialog-cancel]");
if (title) title.textContent = active.options.title || "\u78ba\u8a8d";
if (message) message.textContent = active.options.message || "";
if (confirmButton) {
confirmButton.textContent = active.options.confirmText || "\u5b9f\u884c";
confirmButton.classList.toggle("danger", Boolean(active.options.danger));
confirmButton.classList.toggle("primary", !active.options.danger);
}
if (cancelButton) cancelButton.textContent = active.options.cancelText || "\u30ad\u30e3\u30f3\u30bb\u30eb";
if (global.TarinaiManagedDialogs?.open) global.TarinaiManagedDialogs.open(dialog, active.restoreFocus);
else { dialog.classList.remove("hidden"); dialog.setAttribute("aria-hidden", "false"); }
global.setTimeout(() => confirmButton?.focus?.(), 0);
}
function settle(accepted) {
if (!active) return;
const current = active;
active = null;
const dialog = document.getElementById("gameConfirmDialog");
if (global.TarinaiManagedDialogs?.close) global.TarinaiManagedDialogs.close(dialog);
else { dialog?.classList.add("hidden"); dialog?.setAttribute("aria-hidden", "true"); current.restoreFocus?.focus?.(); }
current.resolve(Boolean(accepted));
global.setTimeout(pump, 0);
}
function confirm(options = {}) {
return new Promise(resolve => {
queue.push({ options: { ...options }, resolve, restoreFocus: document.activeElement || null });
pump();
});
}
global.TarinaiGameDialogs = Object.freeze({ confirm });
})(typeof window !== "undefined" ? window : globalThis);