Рефакторинг структуры проекта: шаблоны, статика и модули приложения
This commit is contained in:
92
static/js/admin.js
Normal file
92
static/js/admin.js
Normal file
@@ -0,0 +1,92 @@
|
||||
(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();
|
||||
})();
|
||||
Reference in New Issue
Block a user