93 lines
3.2 KiB
JavaScript
93 lines
3.2 KiB
JavaScript
(function () {
|
|
const matrixForm = document.getElementById("matrixForm");
|
|
const matrixScroll = document.getElementById("matrixScroll");
|
|
const matrixTable = document.getElementById("matrixTable");
|
|
const topScroll = document.getElementById("matrixHScroll");
|
|
const topScrollInner = document.getElementById("matrixHScrollInner");
|
|
if (!matrixForm || !matrixScroll || !matrixTable || !topScroll || !topScrollInner) return;
|
|
|
|
let isDirty = false;
|
|
let syncing = false;
|
|
let saveTimer = null;
|
|
let saveInFlight = false;
|
|
|
|
function markDirty() {
|
|
isDirty = true;
|
|
}
|
|
|
|
function updateTopScrollWidth() {
|
|
topScrollInner.style.width = matrixTable.scrollWidth + "px";
|
|
}
|
|
|
|
function syncScrollFromTop() {
|
|
if (syncing) return;
|
|
syncing = true;
|
|
matrixScroll.scrollLeft = topScroll.scrollLeft;
|
|
syncing = false;
|
|
}
|
|
|
|
function syncScrollFromMatrix() {
|
|
if (syncing) return;
|
|
syncing = true;
|
|
topScroll.scrollLeft = matrixScroll.scrollLeft;
|
|
syncing = false;
|
|
}
|
|
|
|
async function autoSaveMatrix() {
|
|
if (saveInFlight) return;
|
|
saveInFlight = true;
|
|
try {
|
|
const formData = new FormData(matrixForm);
|
|
const response = await fetch(window.location.href, {
|
|
method: "POST",
|
|
body: formData,
|
|
credentials: "same-origin",
|
|
});
|
|
if (!response.ok) throw new Error("save failed");
|
|
isDirty = false;
|
|
} catch (error) {
|
|
} finally {
|
|
saveInFlight = false;
|
|
}
|
|
}
|
|
|
|
matrixForm.addEventListener("change", (event) => {
|
|
if (!(event.target && event.target.matches('input[type="checkbox"]'))) return;
|
|
markDirty();
|
|
if (saveTimer) clearTimeout(saveTimer);
|
|
saveTimer = setTimeout(autoSaveMatrix, 250);
|
|
});
|
|
|
|
matrixForm.addEventListener("submit", () => {
|
|
isDirty = false;
|
|
});
|
|
|
|
window.addEventListener("beforeunload", (event) => {
|
|
if (!isDirty) return;
|
|
event.preventDefault();
|
|
event.returnValue = "";
|
|
});
|
|
|
|
document.addEventListener("click", (event) => {
|
|
const anchor = event.target.closest("a");
|
|
if (!anchor || !isDirty) return;
|
|
const ok = window.confirm("Есть несохраненные изменения матрицы. Нажмите OK, чтобы остаться и сначала сохранить.");
|
|
if (!ok) return;
|
|
event.preventDefault();
|
|
});
|
|
|
|
document.addEventListener("submit", (event) => {
|
|
const form = event.target;
|
|
if (!form || form === matrixForm || !isDirty) return;
|
|
const ok = window.confirm("Есть несохраненные изменения матрицы. Нажмите OK, чтобы остаться и сначала сохранить.");
|
|
if (!ok) return;
|
|
event.preventDefault();
|
|
});
|
|
|
|
topScroll.addEventListener("scroll", syncScrollFromTop);
|
|
matrixScroll.addEventListener("scroll", syncScrollFromMatrix);
|
|
window.addEventListener("resize", updateTopScrollWidth);
|
|
updateTopScrollWidth();
|
|
syncScrollFromMatrix();
|
|
})();
|