Files
mesh-catalog/modules/mesh-mail-web/internal/web/static/app.js
T
jochen 7e83b99615 issue 1859: serve one script and one stylesheet from the page's own origin (1859.2)
ADR 0515 §6: /static/app.js and /static/app.css are built in and served with their types and nosniff; the
policy allows script and style from the origin alone and connect-src 'self'; no page carries an inline script,
a style or a handler. The script posts the page's forms without a reload and says a failure on the page.
2026-10-22 20:04:26 +02:00

71 lines
2.4 KiB
JavaScript

// The mail page's one script (novox/hq ADR 0515 §6; issue 1859). It talks only to the page's own origin:
// ticking, undoing, reminding and correcting post their form without a reload and put the list (and the
// reading pane) back as the page now answers it. Without it, every form still works by an ordinary post.
// An act that fails is said on the page, with its cause (ADR 0517 §5).
"use strict";
(function () {
function say(text) {
var list = document.getElementById("list");
if (!list) {
return;
}
var p = document.createElement("p");
p.className = "notice failed";
p.setAttribute("role", "alert");
p.textContent = text;
list.insertBefore(p, list.firstChild);
}
// Put back the parts of the page this address answers now.
function refresh() {
return fetch(location.href, { credentials: "same-origin" })
.then(function (r) { return r.text(); })
.then(function (html) {
var fresh = new DOMParser().parseFromString(html, "text/html");
["list", "pane"].forEach(function (id) {
var now = document.getElementById(id);
var next = fresh.getElementById(id);
if (now && next) {
now.replaceWith(document.importNode(next, true));
}
});
});
}
document.addEventListener("submit", function (event) {
var form = event.target;
if (!form.classList || !form.classList.contains("act")) {
return;
}
event.preventDefault();
var buttons = form.querySelectorAll("button");
buttons.forEach(function (b) { b.disabled = true; });
fetch(form.getAttribute("action"), {
method: "POST",
credentials: "same-origin",
headers: { "X-Requested-With": "fetch" },
body: new URLSearchParams(new FormData(form))
})
.then(function (r) {
return r.json().catch(function () { return { failed: "the page answered " + r.status }; });
})
.then(function (answer) {
if (answer.failed) {
buttons.forEach(function (b) { b.disabled = false; });
say(answer.failed);
return;
}
if (answer.go) {
location.assign(answer.go);
return;
}
return refresh();
})
.catch(function (err) {
buttons.forEach(function (b) { b.disabled = false; });
say("That did not reach the page: " + err);
});
});
}());