/* Werbe-/Sponsoren-Banner-Slider: Auto-Rotation über die Fortschrittsanimation des aktiven Indikators (animationend → nächste Folie). Barrierefreiheit: - explizite Pause/Play-Taste (WCAG 2.2.2 „Pause, Stop, Hide"), - zusätzlich Pause bei Hover/Fokus (Komfort), - aria-live: im Autoplay "off" (kein Vorlese-Spam), bei Pause/manuell "polite", - bei prefers-reduced-motion läuft keine Animation → keine Auto-Rotation; Indikatoren bleiben per Klick bedienbar, die Pause-Taste entfällt. */ (function () { 'use strict'; var root = document.querySelector('[data-banner]'); if (!root) { return; } var track = root.querySelector('#ad-banner-track'); var slides = Array.prototype.slice.call(root.querySelectorAll('[data-banner-slide]')); var dots = Array.prototype.slice.call(root.querySelectorAll('[data-banner-dot]')); var controls = root.querySelector('[data-banner-controls]'); var toggle = root.querySelector('[data-banner-toggle]'); var toggleLabel = root.querySelector('[data-banner-toggle-label]'); if (slides.length <= 1) { return; } var reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; var index = 0; var hoverPaused = false; var userPaused = false; function syncPaused() { // Bei reduzierter Bewegung gilt jeder Wechsel als manuell → ansagen. var paused = hoverPaused || userPaused || reduce; root.classList.toggle('is-paused', paused); if (track) { track.setAttribute('aria-live', paused ? 'polite' : 'off'); } } function activate(i) { index = (i % slides.length + slides.length) % slides.length; slides.forEach(function (slide, n) { // Sichtbarkeit per Klasse → CSS blendet über (siehe .is-enhanced). slide.classList.toggle('is-active', n === index); }); dots.forEach(function (dot, n) { var on = n === index; dot.classList.toggle('is-active', on); if (on) { dot.setAttribute('aria-current', 'true'); } else { dot.removeAttribute('aria-current'); } }); } // Sobald die Fortschrittsanimation des aktiven Indikators durchgelaufen ist, // zur nächsten Folie wechseln. (Beim Wechsel wird die alte Animation // abgebrochen → 'animationcancel', nicht 'animationend' → kein Doppelsprung.) root.addEventListener('animationend', function (event) { if (event.animationName === 'ad-progress') { activate(index + 1); } }); // Pause bei Hover/Fokus. root.addEventListener('mouseenter', function () { hoverPaused = true; syncPaused(); }); root.addEventListener('mouseleave', function () { hoverPaused = false; syncPaused(); }); root.addEventListener('focusin', function () { hoverPaused = true; syncPaused(); }); root.addEventListener('focusout', function (event) { if (!root.contains(event.relatedTarget)) { hoverPaused = false; syncPaused(); } }); dots.forEach(function (dot, n) { dot.addEventListener('click', function () { activate(n); }); }); // Steuerung einblenden (ohne JS bleibt sie verborgen, da funktionslos). if (controls) { controls.hidden = false; } // Pause/Play nur anbieten, wenn überhaupt automatisch rotiert wird. if (toggle && !reduce) { toggle.hidden = false; toggle.addEventListener('click', function () { userPaused = !userPaused; toggle.setAttribute('aria-pressed', String(userPaused)); if (toggleLabel) { toggleLabel.textContent = userPaused ? 'Automatischen Wechsel fortsetzen' : 'Automatischen Wechsel pausieren'; } syncPaused(); }); } // Crossfade aktivieren: Slides stapeln (CSS) und Sichtbarkeit per Klasse // steuern. Vorher gesetzte hidden-Attribute (No-JS-Fallback) entfernen. root.classList.add('is-enhanced'); slides.forEach(function (slide) { slide.hidden = false; }); activate(0); syncPaused(); })();