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>
37 lines
1.8 KiB
JavaScript
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();
|
|
}
|