- Cursor-Effekt im Hero entfernt (Messfadenkreuz, Temperatur-Skala, Maus-Wärmespur); Wärmebild läuft nur noch ruhig im Hintergrund - Preloader, Laufbänder, Intro, Ablauf-Block, Kennzahlen, Footer-CTA, kursive Akzentwörter, Verlaufstext und Nummern-Pillen entfernt - Texte in allen Abschnitten deutlich gekürzt, schlichte Überschriften - Leistungen: auf Handy/Tablet wischbare Kärtchen mit Zähler und Pfeilen - Neue, zusammenhängende Illustrationen für die fünf Leistungs-Kärtchen - Heizungs-Finder ohne Prozent-Balken, kürzere Ergebnistexte - Energie-Haus: Tabs als Wischleiste am Handy, kein Autoplay - GSAP, ScrollTrigger, SplitText, Lenis und Instrument Serif entfernt - Barrierefreiheit: Kontrast, Fokusring, Fokus im Kartenstapel, Telefon-Button mit Namen, Menü sperrt Hintergrund - Cache-Busting (?v=20261004) für CSS und JS, README aktualisiert Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
84 lines
3.3 KiB
JavaScript
84 lines
3.3 KiB
JavaScript
/* ==========================================================================
|
||
Olzinger – Energie-Haus
|
||
Tabs + Hotspots steuern, welches System im Hausschnitt hervorgehoben wird.
|
||
========================================================================== */
|
||
(function (w, d) {
|
||
'use strict';
|
||
|
||
var root = d.querySelector('[data-house]');
|
||
if (!root) return;
|
||
|
||
var tabs = Array.prototype.slice.call(root.querySelectorAll('[role="tab"]'));
|
||
var parts = Array.prototype.slice.call(root.querySelectorAll('.part'));
|
||
var hotspots = Array.prototype.slice.call(root.querySelectorAll('.hotspot'));
|
||
var systems = Array.prototype.slice.call(root.querySelectorAll('.sys'));
|
||
var order = tabs.map(function (t) { return t.getAttribute('data-part'); });
|
||
var reduce = w.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||
var current = null;
|
||
|
||
hotspots.forEach(function (h) {
|
||
h.setAttribute('aria-controls', 'part-' + h.getAttribute('data-part'));
|
||
});
|
||
|
||
function activate(id, focusTab) {
|
||
if (id === current) return;
|
||
current = id;
|
||
root.setAttribute('data-active', id);
|
||
tabs.forEach(function (t) {
|
||
var on = t.getAttribute('data-part') === id;
|
||
t.setAttribute('aria-selected', on ? 'true' : 'false');
|
||
t.tabIndex = on ? 0 : -1;
|
||
if (on && focusTab) t.focus();
|
||
// Auf dem Handy liegen die Tabs in einer Wischleiste: aktiven Tab sichtbar halten
|
||
if (on && t.parentNode.scrollWidth > t.parentNode.clientWidth) {
|
||
var bar = t.parentNode;
|
||
bar.scrollTo({ left: t.offsetLeft - (bar.clientWidth - t.offsetWidth) / 2, behavior: reduce ? 'auto' : 'smooth' });
|
||
}
|
||
});
|
||
parts.forEach(function (p) {
|
||
var on = p.getAttribute('data-part') === id;
|
||
p.hidden = !on;
|
||
p.classList.toggle('is-active', on);
|
||
});
|
||
hotspots.forEach(function (h) {
|
||
var on = h.getAttribute('data-part') === id;
|
||
h.classList.toggle('is-active', on);
|
||
h.setAttribute('aria-pressed', on ? 'true' : 'false');
|
||
});
|
||
systems.forEach(function (s) { s.classList.toggle('is-on', s.getAttribute('data-sys') === id); });
|
||
}
|
||
|
||
tabs.forEach(function (t) {
|
||
t.addEventListener('click', function () { activate(t.getAttribute('data-part'), false); });
|
||
});
|
||
hotspots.forEach(function (h) {
|
||
h.addEventListener('click', function () { activate(h.getAttribute('data-part'), false); });
|
||
});
|
||
|
||
// Tastatursteuerung nach WAI-ARIA Tabs-Pattern
|
||
var tablist = root.querySelector('[role="tablist"]');
|
||
if (tablist) {
|
||
tablist.addEventListener('keydown', function (e) {
|
||
var i = order.indexOf(current), n = order.length, to = -1;
|
||
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') to = (i + 1) % n;
|
||
else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') to = (i - 1 + n) % n;
|
||
else if (e.key === 'Home') to = 0;
|
||
else if (e.key === 'End') to = n - 1;
|
||
if (to < 0) return;
|
||
e.preventDefault();
|
||
activate(order[to], true);
|
||
});
|
||
}
|
||
|
||
// SVG-Animationen (Strömungen, Lüfter) nur laufen lassen, solange das Haus sichtbar ist
|
||
if ('IntersectionObserver' in w) {
|
||
new IntersectionObserver(function (entries) {
|
||
root.classList.toggle('is-inview', entries[0].isIntersecting);
|
||
}, { threshold: 0 }).observe(root);
|
||
} else {
|
||
root.classList.add('is-inview');
|
||
}
|
||
|
||
activate(order[0], false);
|
||
})(window, document);
|