// Live-Refresh für Container mit data-refresh="" und data-interval="" function startAutoRefresh() { document.querySelectorAll("[data-refresh]").forEach((el) => { const url = el.dataset.refresh; const interval = parseInt(el.dataset.interval || "2000", 10); const tick = async () => { try { const r = await fetch(url, { headers: { "Accept": "text/html" } }); if (r.ok) el.innerHTML = await r.text(); } catch (e) { /* netzkurz weg, nicht weiter schlimm */ } }; tick(); setInterval(tick, interval); }); } // Forms mit data-action posten und Antwort in data-target rendern function wireScanForms() { document.querySelectorAll("form[data-action]").forEach((form) => { form.addEventListener("submit", async (ev) => { ev.preventDefault(); const btn = form.querySelector("button[type=submit]"); const target = document.querySelector(form.dataset.target); btn.disabled = true; if (target) target.textContent = "läuft…"; try { const r = await fetch(form.dataset.action, { method: "POST" }); const j = await r.json().catch(() => null); if (target) { if (j) { target.textContent = `gescannt: ${j.scanned} · neu: ${j.added} · aktualisiert: ${j.updated} · entfernt: ${j.removed}`; } else { target.textContent = r.ok ? "fertig" : "Fehler"; } } // Seite neu laden, damit die Tabelle die neuen Einträge zeigt if (r.ok) setTimeout(() => location.reload(), 800); } catch (e) { if (target) target.textContent = "Fehler: " + e; } finally { btn.disabled = false; } }); }); } document.addEventListener("DOMContentLoaded", () => { startAutoRefresh(); wireScanForms(); });