1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-11 04:36:48 +00:00

refactor(templates): the shared page scripts load from static files

A step towards a Content-Security-Policy without inline scripts. The
scripts every page or many pages share now load from static files: the
error focus of base.html, the please-wait dialog, the sign-in forms'
password toggle and busy button, the jobs pages' reload while a job
runs, and the start of the job panel and of the VM list's state poll,
whose values come as json_script data. Cancel links go back through a
data-history-back attribute instead of a javascript: URL. The IE8
html5shiv/respond.js block, X-UA-Compatible and shrink-to-fit are gone:
no supported browser reads them.
This commit is contained in:
catborise 2026-11-02 08:47:58 +03:00
parent ab15fafe9c
commit 393aecb8f1
23 changed files with 112 additions and 137 deletions

7
static/js/back_links.js Normal file
View file

@ -0,0 +1,7 @@
// A link marked data-history-back goes back to the previous page.
document.addEventListener("click", function (event) {
if (event.target.closest("[data-history-back]")) {
event.preventDefault();
history.back();
}
});

20
static/js/error_focus.js Normal file
View file

@ -0,0 +1,20 @@
// After a refused submission, start at the error. The places an error
// can be, most specific first: a refused field, its form's summary, an
// open dialog's copy of the messages (the page's are behind it), the
// page's messages. A page that sets itself up first has
// data-error-focus="manual" and calls this when it is ready.
const ERROR_PLACES = [".is-invalid", ".form-errors", ".modal.show .modal-messages .alert-danger",
"#messages .alert-danger"];
function focusFirstError() {
for (const selector of ERROR_PLACES) {
const target = [...document.querySelectorAll(selector)].find(e => e.offsetParent !== null);
if (target) {
if (!target.matches("input, select, textarea")) target.tabIndex = -1;
target.focus();
return;
}
}
}
window.focusFirstError = focusFirstError;
if (document.body.dataset.errorFocus !== "manual") focusFirstError();

19
static/js/login_form.js Normal file
View file

@ -0,0 +1,19 @@
// The sign-in forms (login, OTP login): the eye button shows or hides the
// password; while the form is sent, its button is disabled and says so.
document.getElementById("btn-toggle-pwd").addEventListener("click", function () {
var password = document.getElementById("id_password");
var shown = password.type === "password";
password.type = shown ? "text" : "password";
var icon = document.getElementById("toggle-icon");
icon.classList.toggle("bi-eye", !shown);
icon.classList.toggle("bi-eye-slash", shown);
});
document.getElementById("form-signin").addEventListener("submit", function () {
var button = document.getElementById("btn-signin");
button.disabled = true;
var spinner = document.createElement("span");
spinner.className = "spinner-border spinner-border-sm me-2";
spinner.setAttribute("aria-hidden", "true");
button.replaceChildren(spinner, button.dataset.busyText);
});

15
static/js/please_wait.js Normal file
View file

@ -0,0 +1,15 @@
// The please-wait dialog (pleasewaitdialog.html) of a page that submits a long request.
function showPleaseWaitDialog() {
var pleaseModal = new bootstrap.Modal(document.getElementById('pleaseWaitDialog'), {
keyboard: false
});
pleaseModal.show();
backgroundJobRunning = true;
}
function hidePleaseWaitDialog() {
var pleaseModal = new bootstrap.Modal(document.getElementById('pleaseWaitDialog'), {
keyboard: false
})
pleaseModal.hide();
backgroundJobRunning = false;
}

View file

@ -0,0 +1,2 @@
// Starts following the VM list's states (vm_states_poll.html).
followVmStates(JSON.parse(document.getElementById("vm-states-url").textContent));