Files
KantSites/public/assets/video.js
T
kantarciandClaude Opus 5.5 1b25100dec Translate the video toggle and guard loops without one
The pause and play labels were missing from the kant_t dictionary, so
English and Turkish pages showed them in German. video.js now skips a
data-video-loop without its toggle instead of throwing and leaving every
later video still, and the design panel puts size and spacing first for
the video block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 07:46:22 +01:00

37 lines
1.8 KiB
JavaScript

/*
* Schleifenvideos: im Hintergrund einer Sektion oder im Video-Baustein.
*
* Abgespielt wird erst von hier aus, nicht mit autoplay im HTML. So lädt die Seite zuerst ihren
* Inhalt, das Video folgt danach (preload="none"), und es läuft nur, solange es zu sehen ist.
* Wer „Bewegung reduzieren“ eingestellt hat oder Daten sparen will, bekommt das Standbild und kann
* das Video selbst starten. Der Knopf gehört dazu: Bewegung, die länger als fünf Sekunden läuft,
* muss sich anhalten lassen (WCAG 2.2.2). Ohne Skript bleibt das Standbild.
*/
const reduced = matchMedia('(prefers-reduced-motion: reduce)');
const saving = navigator.connection?.saveData === true;
for (const video of document.querySelectorAll('[data-video-loop]')) {
const toggle = video.parentElement.querySelector(':scope > .video-toggle');
// Ein data-video-loop aus „Eigenes HTML“ hat keinen Knopf; ohne ihn bleibt es beim Standbild.
if (!toggle) continue;
let wanted = !reduced.matches && !saving;
let visible = false;
const paint = () => {
toggle.classList.toggle('is-paused', !wanted);
toggle.setAttribute('aria-label', wanted ? toggle.dataset.pause : toggle.dataset.play);
};
const sync = () => {
if (!wanted || !visible) { video.pause(); return; }
video.play().catch(error => {
// Ein Anhalten mitten im Starten ist kein Fehler. Verweigert der Browser das Abspielen,
// etwa im Stromsparmodus, zeigt der Knopf die Wahrheit.
if (error.name === 'NotAllowedError') { wanted = false; paint(); }
});
};
toggle.hidden = false;
toggle.addEventListener('click', () => { wanted = !wanted; paint(); sync(); });
reduced.addEventListener('change', () => { if (reduced.matches) { wanted = false; paint(); sync(); } });
new IntersectionObserver(([entry]) => { visible = entry.isIntersecting; sync(); }).observe(video);
paint();
}