Unterseiten: Fußball-Übersicht, Mannschaften, Jugend, Verein, Rechtliches
Neue Seiten + Routen: fussball, fussball/{erste-mannschaft,zweite-mannschaft,
damen}, jugendfussball, verein, impressum, datenschutz. Dazu die Komponenten
team, team-cards/-roster/-photo/-bento, faq/faq-contact, key-facts, age-groups,
cta-band, training-location und der contact-slider.
Daten in teams/fussball/jugend/verein.json; club.json um Vorstand, Bankdaten,
Datenschutz-Kontakt erweitert. person-grid bekommt $names-Filter, partner-grid
einen Intro-Stil. Seiten setzen $meta['schema'] via team_/page_schema.
Styles für alle neuen Komponenten in components.css.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KDQZ6FuchNUh2bxSW9PeNv
This commit is contained in:
75
public/assets/js/contact-slider.js
Normal file
75
public/assets/js/contact-slider.js
Normal file
@@ -0,0 +1,75 @@
|
||||
/* Ansprechpartner-Mini-Slider: zeigt bei mehreren Kontakten nur eine Karte und
|
||||
wechselt automatisch durch. Progressive Enhancement:
|
||||
- ohne JS bleiben alle Karten gestapelt sichtbar (kein Info-Verlust),
|
||||
- bei prefers-reduced-motion findet keine Enhancement/Auto-Rotation statt
|
||||
(alle Karten bleiben sichtbar),
|
||||
- Pause bei Hover/Fokus, Punkte zur manuellen Auswahl. */
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var root = document.querySelector('[data-contact-slider]');
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
|
||||
var slides = Array.prototype.slice.call(root.querySelectorAll('[data-contact-slide]'));
|
||||
if (slides.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bewegungsreduzierung: nicht enhancen → alle Karten bleiben sichtbar.
|
||||
if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dots = Array.prototype.slice.call(root.querySelectorAll('[data-contact-dot]'));
|
||||
var INTERVAL = 5000;
|
||||
var current = 0;
|
||||
var timer = null;
|
||||
|
||||
function show(n) {
|
||||
current = (n + slides.length) % slides.length;
|
||||
slides.forEach(function (slide, idx) {
|
||||
var active = idx === current;
|
||||
slide.hidden = !active;
|
||||
slide.classList.toggle('is-active', active);
|
||||
});
|
||||
dots.forEach(function (dot, idx) {
|
||||
if (idx === current) {
|
||||
dot.setAttribute('aria-current', 'true');
|
||||
} else {
|
||||
dot.removeAttribute('aria-current');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function stop() {
|
||||
if (timer) {
|
||||
window.clearInterval(timer);
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function start() {
|
||||
stop();
|
||||
timer = window.setInterval(function () {
|
||||
show(current + 1);
|
||||
}, INTERVAL);
|
||||
}
|
||||
|
||||
dots.forEach(function (dot, idx) {
|
||||
dot.addEventListener('click', function () {
|
||||
show(idx);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
root.addEventListener('mouseenter', stop);
|
||||
root.addEventListener('mouseleave', start);
|
||||
root.addEventListener('focusin', stop);
|
||||
root.addEventListener('focusout', start);
|
||||
|
||||
root.classList.add('contact-slider--ready');
|
||||
show(0);
|
||||
start();
|
||||
})();
|
||||
Reference in New Issue
Block a user