Files
LMS/web/src/main/resources/static/js/ui-state.js
Vladislav Kopnin da464f882a Content sort: autosave without reload; keep page state across reloads
- drag & drop now saves in the background (700 ms debounce) without reloading:
  sections stay open, scroll position is kept; on failure it retries every 3 s,
  and navigator.sendBeacon flushes unsaved changes on page leave
- removed the explicit save button (autosave only), status indicator shows
  «Изменения не сохранены… / Сохранение… / Порядок сохранён»
- new global ui-state.js: restores open <details> and scroll position after any
  reload/redirect within the same page (applies to all pages, not just /learn)
- auto-expand a collapsed chapter/section while hovering during drag
2026-09-16 19:00:03 +03:00

60 lines
2.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Состояние страницы при перезагрузке: открытые <details> и позиция прокрутки.
Нужно, чтобы после сохранения формы или перерисовки страница возвращалась
туда же, а не «схлопывала» разделы и не сбрасывала прокрутку в начало. */
(function () {
var KEY = 'lms-ui-state';
function keyOf(element, index) {
return element.getAttribute('data-chapter-id')
|| element.getAttribute('data-section-id')
|| element.id
|| ('details-' + index);
}
function currentUrl() {
return location.pathname + location.search;
}
function save() {
var open = [];
document.querySelectorAll('details').forEach(function (element, index) {
if (element.open) open.push(keyOf(element, index));
});
try {
sessionStorage.setItem(KEY, JSON.stringify({
url: currentUrl(),
y: window.scrollY || window.pageYOffset || 0,
open: open
}));
} catch (e) { /* приватный режим — просто пропускаем */ }
}
function restore() {
var raw;
try {
raw = sessionStorage.getItem(KEY);
if (raw) sessionStorage.removeItem(KEY);
} catch (e) { return; }
if (!raw) return;
var state;
try { state = JSON.parse(raw); } catch (e) { return; }
// состояние применяем только при возврате на ту же страницу (перезагрузка/redirect)
if (!state || state.url !== currentUrl()) return;
var open = state.open || [];
document.querySelectorAll('details').forEach(function (element, index) {
if (open.indexOf(keyOf(element, index)) >= 0) element.open = true;
});
if (typeof state.y === 'number' && state.y > 0) {
var y = state.y;
requestAnimationFrame(function () { window.scrollTo(0, y); });
setTimeout(function () { window.scrollTo(0, y); }, 80);
}
}
window.addEventListener('beforeunload', save);
document.addEventListener('DOMContentLoaded', restore);
})();