Files
MatchLiveTv/backend/public/confirm-forms.js
T
eminuxandCursor 1d97271555 Aggiunge i18n IT/EN/FR/DE/ES, pagine pubbliche squadre e UX archivio.
Il selettore lingua funziona sul web e sulle app native; su Android la preferenza è persistita e applicata al riavvio. Incluse anche eliminazione replay a scope e campi pagina pubblica squadra.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 19:30:44 +02:00

312 lines
11 KiB
JavaScript

(function () {
var pendingForm = null;
var pendingScope = null;
var dialog = null;
function ensureDialog() {
if (dialog) return dialog;
dialog = document.createElement("div");
dialog.className = "site-confirm";
dialog.setAttribute("role", "dialog");
dialog.setAttribute("aria-modal", "true");
dialog.setAttribute("aria-labelledby", "site-confirm-title");
dialog.hidden = true;
dialog.innerHTML =
'<div class="site-confirm__backdrop" data-confirm-cancel></div>' +
'<div class="site-confirm__panel site-confirm__panel--choices">' +
' <p class="site-confirm__eyebrow">Conferma richiesta</p>' +
' <h2 class="site-confirm__title" id="site-confirm-title">Sei sicuro?</h2>' +
' <p class="site-confirm__message" id="site-confirm-message"></p>' +
' <div class="site-confirm__choices" id="site-confirm-choices" hidden>' +
' <button type="button" class="site-confirm__choice" data-confirm-scope="site">' +
" <span class=\"site-confirm__choice-label\">Solo dal sito</span>" +
" <span class=\"site-confirm__choice-hint\" data-hint-site>Il video resta su YouTube</span>" +
" </button>" +
' <button type="button" class="site-confirm__choice" data-confirm-scope="youtube">' +
" <span class=\"site-confirm__choice-label\">Solo da YouTube</span>" +
" <span class=\"site-confirm__choice-hint\" data-hint-youtube>Resta disponibile sul sito</span>" +
" </button>" +
' <button type="button" class="site-confirm__choice site-confirm__choice--danger" data-confirm-scope="both">' +
" <span class=\"site-confirm__choice-label\">Da sito e YouTube</span>" +
" <span class=\"site-confirm__choice-hint\" data-hint-both>Eliminazione completa</span>" +
" </button>" +
" </div>" +
' <div class="site-confirm__actions">' +
' <button type="button" class="btn btn-secondary site-confirm__btn" data-confirm-cancel>Annulla</button>' +
' <button type="button" class="btn btn-primary site-confirm__btn site-confirm__btn--danger" data-confirm-ok>Elimina</button>' +
" </div>" +
"</div>";
document.body.appendChild(dialog);
dialog.addEventListener("click", function (event) {
var target = event.target;
if (!(target instanceof Element)) return;
if (target.closest("[data-confirm-cancel]")) {
closeDialog();
return;
}
var scopeBtn = target.closest("[data-confirm-scope]");
if (scopeBtn) {
if (scopeBtn.disabled || scopeBtn.getAttribute("aria-disabled") === "true") return;
submitPending(scopeBtn.getAttribute("data-confirm-scope"));
return;
}
if (target.closest("[data-confirm-ok]")) {
submitPending(pendingScope || "both");
}
});
document.addEventListener("keydown", function (event) {
if (!dialog || dialog.hidden) return;
if (event.key === "Escape") {
event.preventDefault();
closeDialog();
}
});
return dialog;
}
function setChoiceVisible(btn, visible) {
if (!(btn instanceof HTMLElement)) return;
btn.hidden = !visible;
if (!visible) {
btn.disabled = true;
btn.setAttribute("aria-disabled", "true");
}
}
function setChoiceEnabled(btn, enabled) {
if (!(btn instanceof HTMLButtonElement)) return;
btn.disabled = !enabled;
btn.setAttribute("aria-disabled", enabled ? "false" : "true");
btn.classList.toggle("site-confirm__choice--disabled", !enabled);
}
function openDialog(message, options) {
options = options || {};
var hasSite = options.hasSite !== false;
var hasYoutube = !!options.hasYoutube;
var canSite = hasSite;
var canYoutube = hasYoutube;
var canBoth = hasSite && hasYoutube;
var choiceCount = (canSite ? 1 : 0) + (canYoutube ? 1 : 0) + (canBoth ? 1 : 0);
// Una sola destinazione disponibile → conferma semplice, senza elenco
var multi = !!options.multi && choiceCount > 1;
if (canBoth) pendingScope = "both";
else if (canSite) pendingScope = "site";
else if (canYoutube) pendingScope = "youtube";
else pendingScope = "both";
var el = ensureDialog();
var titleEl = el.querySelector("#site-confirm-title");
var messageEl = el.querySelector("#site-confirm-message");
var okBtn = el.querySelector("[data-confirm-ok]");
var choicesEl = el.querySelector("#site-confirm-choices");
var siteBtn = el.querySelector('[data-confirm-scope="site"]');
var youtubeBtn = el.querySelector('[data-confirm-scope="youtube"]');
var bothBtn = el.querySelector('[data-confirm-scope="both"]');
var hintSite = el.querySelector("[data-hint-site]");
var hintYoutube = el.querySelector("[data-hint-youtube]");
var hintBoth = el.querySelector("[data-hint-both]");
var panel = el.querySelector(".site-confirm__panel");
if (titleEl) {
if (multi) {
titleEl.textContent = "Cosa vuoi eliminare?";
} else if (pendingScope === "youtube") {
titleEl.textContent = "Eliminare da YouTube?";
} else if (pendingScope === "site") {
titleEl.textContent = "Eliminare dal sito?";
} else {
titleEl.textContent = /elimin/i.test(message)
? "Eliminare definitivamente?"
: "Confermi questa operazione?";
}
}
if (messageEl) {
if (multi) {
messageEl.textContent =
"Scegli dove rimuovere il replay. L'operazione è irreversibile.";
} else if (pendingScope === "youtube") {
messageEl.textContent =
"Il video verrà rimosso da YouTube. Il replay resterà disponibile sul sito.";
} else if (pendingScope === "site") {
messageEl.textContent = hasYoutube
? "Il replay verrà rimosso dal sito. Il video su YouTube resterà online."
: "Stai per eliminare definitivamente questo replay dal sito. L'operazione è irreversibile.";
} else {
messageEl.textContent = message;
}
}
if (choicesEl) choicesEl.hidden = !multi;
if (panel) panel.classList.toggle("site-confirm__panel--choices", multi);
if (okBtn instanceof HTMLElement) {
okBtn.hidden = multi;
if (pendingScope === "youtube") okBtn.textContent = "Elimina da YouTube";
else if (pendingScope === "site") okBtn.textContent = "Elimina dal sito";
else okBtn.textContent = /elimin/i.test(message) ? "Elimina" : "Conferma";
}
setChoiceVisible(siteBtn, canSite);
setChoiceVisible(youtubeBtn, canYoutube);
setChoiceVisible(bothBtn, canBoth);
if (multi) {
setChoiceEnabled(siteBtn, canSite);
setChoiceEnabled(youtubeBtn, canYoutube);
setChoiceEnabled(bothBtn, canBoth);
if (hintSite) {
hintSite.textContent = canYoutube
? "Il video resta su YouTube"
: "Rimuove i file dal sito";
}
if (hintYoutube) {
hintYoutube.textContent = canSite
? "Resta disponibile sul sito"
: "Rimuove solo il video YouTube";
}
if (hintBoth) hintBoth.textContent = "Eliminazione completa";
}
el.hidden = false;
document.body.classList.add("site-confirm-open");
if (multi) {
var focusBtn = canSite ? siteBtn : canYoutube ? youtubeBtn : bothBtn;
if (focusBtn instanceof HTMLElement) focusBtn.focus();
} else if (okBtn instanceof HTMLElement) {
okBtn.focus();
}
}
function closeDialog() {
if (!dialog) return;
dialog.hidden = true;
document.body.classList.remove("site-confirm-open");
pendingForm = null;
pendingScope = null;
}
function ensureHiddenInput(form, name, value) {
var input = form.querySelector('input[name="' + name + '"]');
if (!(input instanceof HTMLInputElement)) {
input = document.createElement("input");
input.type = "hidden";
input.name = name;
form.appendChild(input);
}
input.value = value;
}
function submitPending(scope) {
var form = pendingForm;
if (form && form.closest(".replay-archive")) {
saveArchiveScrollPosition();
}
closeDialog();
if (!form) return;
ensureHiddenInput(form, "delete_scope", scope || "both");
form.dataset.confirmAccepted = "1";
if (typeof form.requestSubmit === "function") {
form.requestSubmit();
} else {
form.submit();
}
}
document.addEventListener(
"submit",
function (event) {
var form = event.target;
if (!(form instanceof HTMLFormElement)) return;
if (form.dataset.confirmAccepted === "1") {
delete form.dataset.confirmAccepted;
return;
}
var message =
form.getAttribute("data-confirm") ||
form.getAttribute("data-turbo-confirm");
if (!message) return;
event.preventDefault();
event.stopImmediatePropagation();
pendingForm = form;
pendingScope = "both";
var mode = form.getAttribute("data-confirm-mode") || "";
var isReplayDelete =
mode === "delete-replay" || mode === "delete-replay-youtube";
var hasYoutube =
form.getAttribute("data-has-youtube") === "1" ||
mode === "delete-replay-youtube";
var hasSiteAttr = form.getAttribute("data-has-site");
var hasSite = hasSiteAttr == null ? true : hasSiteAttr === "1";
openDialog(message, {
multi: isReplayDelete,
hasYoutube: hasYoutube,
hasSite: hasSite
});
},
true
);
// Dopo submit nell'archivio replay, resta alla stessa altezza di scroll
// (il redirect ricarica la pagina e altrimenti torna in cima).
var SCROLL_KEY = "matchlivetv.replayArchive.scrollY";
function saveArchiveScrollPosition() {
try {
sessionStorage.setItem(
SCROLL_KEY,
String(window.scrollY || window.pageYOffset || 0)
);
} catch (err) {
/* ignore */
}
}
function saveArchiveScroll(event) {
var form = event.target;
if (!(form instanceof HTMLFormElement)) return;
if (!form.closest(".replay-archive")) return;
var needsConfirm =
form.getAttribute("data-confirm") ||
form.getAttribute("data-turbo-confirm");
// Con confirm lo scroll si salva in submitPending, dopo la scelta nel dialog
if (needsConfirm) return;
saveArchiveScrollPosition();
}
function restoreArchiveScroll() {
try {
var raw = sessionStorage.getItem(SCROLL_KEY);
if (raw == null) return;
sessionStorage.removeItem(SCROLL_KEY);
var top = parseInt(raw, 10);
if (isNaN(top)) return;
window.scrollTo(0, top);
requestAnimationFrame(function () {
window.scrollTo(0, top);
});
} catch (err) {
/* ignore */
}
}
document.addEventListener("submit", saveArchiveScroll, true);
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", restoreArchiveScroll);
} else {
restoreArchiveScroll();
}
})();