Files
go-nc-exapp/dialog.js
T
konrad 0a387815a0 Add a Dialog an ExApp page can open for a message, confirm, or prompt.
The page waits for the choice. App navigation includes the same piece.
2026-09-28 21:10:20 +02:00

129 lines
3.7 KiB
JavaScript

(function () {
var dialog = document.getElementById("exapp-dialog");
if (!dialog || dialog.getAttribute("data-ready") === "1") return;
dialog.setAttribute("data-ready", "1");
var panel = document.getElementById("exapp-dialog-panel");
var heading = document.getElementById("exapp-dialog-heading");
var severity = document.getElementById("exapp-dialog-severity");
var message = document.getElementById("exapp-dialog-message");
var field = document.getElementById("exapp-dialog-value");
var cancelBtn = document.getElementById("exapp-dialog-cancel");
var agreeBtn = document.getElementById("exapp-dialog-agree");
var queue = [];
var busy = false;
var finish = null;
function textOf(value) {
return value == null ? "" : String(value);
}
function trimmed() {
return field.value.trim();
}
function refreshAgree() {
agreeBtn.disabled = !field.hidden && trimmed() === "";
}
function settle(result) {
var done = finish;
finish = null;
if (dialog.open) dialog.close();
busy = false;
if (done) done(result);
pump();
}
function decline() {
if (!finish) return;
var kind = dialog.getAttribute("data-kind");
if (kind === "confirm") settle(false);
else if (kind === "prompt") settle(null);
else settle(undefined);
}
function agree() {
if (!finish || agreeBtn.disabled) return;
var kind = dialog.getAttribute("data-kind");
if (kind === "confirm") settle(true);
else if (kind === "prompt") settle(trimmed());
else settle(undefined);
}
cancelBtn.addEventListener("click", function (e) {
e.stopPropagation();
decline();
});
agreeBtn.addEventListener("click", function (e) {
e.stopPropagation();
agree();
});
field.addEventListener("input", refreshAgree);
dialog.addEventListener("cancel", function (e) {
e.preventDefault();
decline();
});
dialog.addEventListener("click", function (e) {
if (e.target === dialog) decline();
});
dialog.addEventListener("keydown", function (e) {
if (e.key !== "Enter") return;
e.preventDefault();
agree();
});
panel.addEventListener("click", function (e) {
e.stopPropagation();
});
function show(kind, opts, done) {
opts = opts || {};
finish = done;
dialog.setAttribute("data-kind", kind);
var head = textOf(opts.heading);
heading.textContent = head;
heading.hidden = head === "";
message.textContent = textOf(opts.text);
var sev = "";
if (kind === "message") {
sev = opts.severity === "warning" || opts.severity === "error" ? opts.severity : "info";
dialog.setAttribute("data-severity", sev);
} else {
dialog.removeAttribute("data-severity");
}
severity.textContent = sev;
severity.hidden = sev === "";
var isPrompt = kind === "prompt";
field.hidden = !isPrompt;
field.value = isPrompt ? textOf(opts.value) : "";
cancelBtn.hidden = kind === "message";
agreeBtn.textContent = kind !== "message" && opts.agree ? textOf(opts.agree) : "OK";
agreeBtn.classList.toggle("destructive", kind === "confirm" && !!opts.destructive);
refreshAgree();
if (!dialog.open) dialog.showModal();
if (isPrompt) field.focus();
else if (!agreeBtn.disabled) agreeBtn.focus();
}
function pump() {
if (busy || queue.length === 0) return;
busy = true;
queue.shift()();
}
function enqueue(kind, opts) {
return new Promise(function (resolve) {
queue.push(function () {
show(kind, opts, resolve);
});
pump();
});
}
window.exappDialog = {
message: function (opts) { return enqueue("message", opts); },
confirm: function (opts) { return enqueue("confirm", opts); },
prompt: function (opts) { return enqueue("prompt", opts); }
};
})();