PageSourceSearch

https://genussla.de/wp-content/themes/genussla/assets/js/accessible.js?ver=1782131758

js genussla.de collected 2026-10-08 14:56:16 UTC 42,416 bytes, 1,227 lines download raw bytes

1/* Globale Cookie-Optionen */
2const COOKIE_SET_OPTS = { expires: 365, path: '/' };
3const COOKIE_REMOVE_OPTS = { path: '/' };
4
5/* Body-Toogle für CSS-Manipulation */ 
6/************************************/
7function toggleBody(className) {
8	var body = document.body;
9	if (body.classList.contains(className)) {
10		body.classList.remove(className);
11	} else {
12		body.classList.add(className);
13	}
14}
15
16/* Blaufilter-Regel */
17/********************/
18function changeBluescale(value) {
19	Cookies.set('acc_bluescale', value, COOKIE_SET_OPTS);
20	var elementToChange = document.getElementById("shader-bluefilter");
21	var transparencyValue = value / 10;
22	if (transparencyValue === 0) {
23		elementToChange.style.display = "none";
24	} else if (transparencyValue >= 0.1 && transparencyValue <= 1.0) {
25		elementToChange.style.display = "block";
26	}
27	elementToChange.style.backgroundColor = "rgba(245, 168, 93, " + transparencyValue + ")";
28}
29function resetBluescale(){
30	var elementToChange = document.getElementById("shader-bluefilter");
31	elementToChange.style.display = "none";
32	Cookies.remove('acc_bluescale', COOKIE_REMOVE_OPTS);
33	var bluefilterSlider = document.getElementById('bluefilterAcc');
34	bluefilterSlider.value = 0;
35}
36
37/* Greyscale-Regel */
38/*******************/
39function changeGreyscale(value) {
40	Cookies.set('acc_greyscale', value, COOKIE_SET_OPTS);
41	var elementToChange = document.getElementById("shader-greyscale");
42	var transparencyValue = value;
43	if (value === 0) {
44		elementToChange.style.display = "none";
45	} else if (value >= 0.05 && value <= 1.0) {
46		elementToChange.style.display = "block";
47	}
48	elementToChange.style.backgroundColor = "rgba(0, 0, 0, " + value + ")";
49}
50function resetGreyscale(){
51	var elementToChange = document.getElementById("shader-greyscale");
52	elementToChange.style.display = "none";
53	Cookies.remove('acc_greyscale', COOKIE_REMOVE_OPTS);
54	var greyscaleSlider = document.getElementById('greyscaleAcc');
55	greyscaleSlider.value = 0;
56}
57
58/* Saturation-Regel */
59/********************/
60function changeSaturation(value) {
61	var elementToChange = document.getElementById("shader-saturation");
62	if (!elementToChange) return;
63
64	var rawValue = parseFloat(value);
65	if (!Number.isFinite(rawValue)) rawValue = 0;
66
67	// Support both old 0..10 and current 0..1 slider values.
68	var transparencyValue = rawValue > 1 ? (rawValue / 10) : rawValue;
69	transparencyValue = Math.min(Math.max(transparencyValue, 0), 1);
70
71	Cookies.set('acc_saturation', transparencyValue, COOKIE_SET_OPTS);
72
73	if (transparencyValue <= 0) {
74		elementToChange.style.display = "none";
75	} else {
76		elementToChange.style.display = "block";
77	}
78	elementToChange.style.backgroundColor = "rgba(0, 255, 0, " + transparencyValue + ")";
79}
80function resetSaturation(){
81	var elementToChange = document.getElementById("shader-saturation");
82	if (elementToChange) {
83		elementToChange.style.display = "none";
84	}
85	Cookies.remove('acc_saturation', COOKIE_REMOVE_OPTS);
86	var saturationSlider = document.getElementById('saturationAcc');
87	if (saturationSlider) saturationSlider.value = 0;
88}
89
90/* Kontrast einstellen */
91/***********************/
92function getContrastTargets() {
93	if (!document.body) return [];
94	var targets = Array.from(document.body.children).filter(function(el) {
95		if (!el || !el.matches) return false;
96		return !el.matches('header, #accesible, .modal-backdrop, #accScreenreaderPanel, #shader-bluefilter, #shader-greyscale, #shader-saturation, #acc-colorweakness-overlay, script, style, link, meta, title');
97	});
98	var standardNavigation = document.querySelector('header > #nav');
99	if (standardNavigation) targets.push(standardNavigation);
100	return targets;
101}
102
103function changeContrast(value) {
104	Cookies.set('acc_contrast', value, COOKIE_SET_OPTS);
105	var contrastValue = parseFloat(value);
106	var targets = getContrastTargets();
107	targets.forEach(function(target) {
108		target.style.setProperty('filter', 'contrast(' + contrastValue + ')');
109	});
110}
111function resetContrast(){
112	var targets = getContrastTargets();
113	targets.forEach(function(target) {
114		target.style.removeProperty('filter');
115	});
116	Cookies.remove('acc_contrast', COOKIE_REMOVE_OPTS);
117	var contrastSlider = document.getElementById('contrastAcc');
118	contrastSlider.value = 0;
119}
120
121/* function changeFontsize(size) {
122    if (size === 1.0) {
123        Cookies.remove('acc_fontsize');
124        document.body.classList.remove('accFontSizeActive');
125    } else {
126        Cookies.set('acc_fontsize', size);
127        document.body.classList.add('accFontSizeActive');
128    }
129
130    const selector = 'p, ul, li, span, a, small, h1, h2, h3, h4, h5, h6, b, img';
131    const all = Array.from(document.querySelectorAll(selector));
132    all.forEach(el => {
133        if (el.closest('.excludeAcc')) return;
134        if (el.tagName.toLowerCase() === 'a' && el.closest('p, li, h1, h2, h3, h4, h5, h6')) {
135            return;
136        }
137        if (el.tagName.toLowerCase() === 'img') {
138            if (!(el.closest('p') || el.closest('a'))) return;
139            if (!el.dataset.baseWidth || !el.dataset.baseHeight) {
140                const baseW = el.naturalWidth || el.offsetWidth || 0;
141                const baseH = el.naturalHeight || el.offsetHeight || 0;
142                if (baseW > 0) el.dataset.baseWidth = baseW;
143                if (baseH > 0) el.dataset.baseHeight = baseH;
144            }
145            if (size === 1.0) {
146                el.style.removeProperty('width');
147                el.style.removeProperty('height');
148            } else {
149                const baseW = parseFloat(el.dataset.baseWidth || el.offsetWidth);
150                const baseH = parseFloat(el.dataset.baseHeight || el.offsetHeight);
151                if (baseW > 0) {
152                    el.style.setProperty('width', (baseW * size) + "px", 'important');
153                }
154                if (baseH > 0) {
155                    el.style.setProperty('height', (baseH * size) + "px", 'important');
156                }
157            }
158            return;
159        }
160        if (!el.dataset.baseFontsize) {
161            const computed = window.getComputedStyle(el).fontSize;
162            el.dataset.baseFontsize = parseFloat(computed);
163        }
164        if (size === 1.0) {
165            el.style.removeProperty('font-size');
166        } else {
167            const base = parseFloat(el.dataset.baseFontsize);
168            const newSize = base * size;
169            el.style.setProperty('font-size', newSize + "px", 'important');
170        }
171    });
172}
173
174function resetFontsize() {
175    const selector = 'p, ul, li, span, a, small, h1, h2, h3, h4, h5, h6, b, img';
176    const all = Array.from(document.querySelectorAll(selector));
177    all.forEach(el => {
178        if (el.closest('.excludeAcc')) return;
179        if (el.tagName.toLowerCase() === 'a' && el.closest('p, li, h1, h2, h3, h4, h5, h6')) {
180            return;
181        }
182        if (el.tagName.toLowerCase() === 'img' && (el.closest('p') || el.closest('a'))) {
183            el.style.removeProperty('width');
184            el.style.removeProperty('height');
185            return;
186        }
187        el.style.removeProperty('font-size');
188    });
189    Cookies.remove('acc_fontsize');
190    document.body.classList.remove('accFontSizeActive');
191    const fontsizeSlider = document.getElementById('fontsizeAcc');
192    if (fontsizeSlider) fontsizeSlider.value = 1.0;
193}
194
195function changeLinespacing(size){
196    Cookies.set('acc_linespacing', size, COOKIE_SET_OPTS);
197    document.querySelectorAll('p').forEach(el => {
198        if (el.closest('.excludeAcc')) return;
199        el.style.lineHeight = size + "em";
200    });
201    const newSmall = size * 0.875;
202    document.querySelectorAll('small').forEach(el => {
203        if (el.closest('.excludeAcc')) return;
204        el.style.lineHeight = newSmall + "em";
205    });
206    const newH1 = size * 42;
207    document.querySelectorAll('h1').forEach(el => {
208        if (el.closest('.excludeAcc')) return;
209        el.style.lineHeight = newH1 + "px";
210    });
211    const newH2 = size * 34;
212    document.querySelectorAll('h2').forEach(el => {
213        if (el.closest('.excludeAcc')) return;
214        el.style.lineHeight = newH2 + "px";
215    });
216    const newH4 = size * 18;
217    document.querySelectorAll('h4').forEach(el => {
218        if (el.closest('.excludeAcc')) return;
219        el.style.lineHeight = newH4 + "px";
220    });
221    document.querySelectorAll('li').forEach(el => {
222        if (el.closest('.excludeAcc')) return;
223        el.style.lineHeight = size + "em";
224    });
225    const newSpanFact = size * 14;
226    document.querySelectorAll('.entr.tour .entr-facts div').forEach(el => {
227        if (el.closest('.excludeAcc')) return;
228        el.style.lineHeight = newSpanFact + "px";
229    });
230}
231
232function resetLinespacing(){
233    var size = 1.8;
234    document.querySelectorAll('p').forEach(el => {
235        if (el.closest('.excludeAcc')) return;
236        el.style.lineHeight = size + "em";
237    });
238    const newSmall = size * 0.875;
239    document.querySelectorAll('small').forEach(el => {
240        if (el.closest('.excludeAcc')) return;
241        el.style.lineHeight = newSmall + "em";
242    });
243    const newH1 = size * 42;
244    document.querySelectorAll('h1').forEach(el => {
245        if (el.closest('.excludeAcc')) return;
246        el.style.lineHeight = newH1 + "px";
247    });
248    const newH2 = size * 34;
249    document.querySelectorAll('h2').forEach(el => {
250        if (el.closest('.excludeAcc')) return;
251        el.style.lineHeight = newH2 + "px";
252    });
253    const newH4 = size * 18;
254    document.querySelectorAll('h4').forEach(el => {
255        if (el.closest('.excludeAcc')) return;
256        el.style.lineHeight = newH4 + "px";
257    });
258    document.querySelectorAll('li').forEach(el => {
259        if (el.closest('.excludeAcc')) return;
260        el.style.lineHeight = size + "em";
261    });
262    const newSpanFact = size * 14;
263    document.querySelectorAll('.entr.tour .entr-facts div').forEach(el => {
264        if (el.closest('.excludeAcc')) return;
265        el.style.lineHeight = newSpanFact + "px";
266    });
267    Cookies.remove('acc_linespacing', COOKIE_REMOVE_OPTS);
268    var linespacingSlider = document.getElementById('linespacingAcc');
269    if (linespacingSlider) linespacingSlider.value = 1.8;
270} */
271
272/* Schriftgröße und Zeilenabstand */
273/**********************************/
274(() => {
275    const COOKIE_KEY_SCALE = 'acc_fontsize';
276    const LEGACY_COOKIE_LS = 'acc_linespacing';
277    const COOKIE_SET_OPTS = (typeof window.COOKIE_SET_OPTS !== 'undefined')
278    ? window.COOKIE_SET_OPTS
279    : { expires: 365, sameSite: 'Lax' };
280    const COOKIE_REMOVE_OPTS = (typeof window.COOKIE_REMOVE_OPTS !== 'undefined')
281    ? window.COOKIE_REMOVE_OPTS
282    : { sameSite: 'Lax' };
283    const BASE_LS = 1.8;
284    const BASE_SMALL_F = 0.875;
285    const BASE_H1_PX = 42;
286    const BASE_H2_PX = 34;
287    const BASE_H4_PX = 18;
288    const BASE_FACTS_PX = 14;
289    const BNAV_MIN_FS = 18;
290    const DOWNLOADS_MIN_FS = 18;
291    const BNAV_MIN_SELECTOR = '.label, .mainmenu__item, .sidemenu__item, .menu__item-link, .menu__item-hoverlink';
292    // const TEXT_SELECTOR = 'p, ul, li, span, a, small, h1, h2, h3, h4, h5, h6, b';
293    const TEXT_SELECTOR = 'p, ul, li, span, a, small, h1, h2, h3, h4, h5, h6, b, label, select, option, button';
294    const EXCLUDE_SEL   = '.excludeAcc, .pill-button, #accesible, #accScreenreaderPanel';
295    const clamp = (n, min, max) => Math.min(Math.max(n, min), max);
296    const isInside = (el, selector) => !!el.closest(selector);
297    const enforceBnavMinFont = (el) => (
298        !!el.closest('#bnav') && (
299            el.matches(BNAV_MIN_SELECTOR) || !!el.closest(BNAV_MIN_SELECTOR)
300        )
301    );
302    const enforceDownloadsMinFont = (el) => !!el.closest('#downloads');
303    const getNumberPx = (val) => {
304        const x = parseFloat(val);
305        return Number.isFinite(x) ? x : NaN;
306    };
307    let pendingScale = 1.0;
308    let rafId = null;
309    function scheduleApplyScale(scale) {
310        pendingScale = scale;
311        if (rafId != null) return;
312        rafId = requestAnimationFrame(() => {
313            rafId = null;
314            applyScale(pendingScale);
315        });
316    }
317    function applyScale(scale) {
318        const s = scale;
319        if (s === 1.0) {
320            document.body.classList.remove('accFontSizeActive');
321        } else {
322            document.body.classList.add('accFontSizeActive');
323        }
324        const all = document.querySelectorAll(TEXT_SELECTOR);
325        all.forEach((el) => {
326            if (isInside(el, EXCLUDE_SEL)) return;
327            const tag = el.tagName.toLowerCase();
328            if (tag === 'a' && el.closest('p, li, h1, h2, h3, h4, h5, h6')) return;
329            if (!el.dataset.baseFontsize) {
330                const compFS = getNumberPx(getComputedStyle(el).fontSize);
331                if (Number.isFinite(compFS)) {
332                    el.dataset.baseFontsize = String(compFS);
333                }
334            }
335            const baseFS = parseFloat(el.dataset.baseFontsize || '');
336            const bnavMin = enforceBnavMinFont(el) ? BNAV_MIN_FS : 0;
337            const downloadsMin = enforceDownloadsMinFont(el) ? DOWNLOADS_MIN_FS : 0;
338            const requiredMin = Math.max(bnavMin, downloadsMin);
339            if (s === 1.0) {
340                if (requiredMin > 0 && Number.isFinite(baseFS) && baseFS < requiredMin) {
341                    el.style.setProperty('font-size', requiredMin + 'px', 'important');
342                } else {
343                    el.style.removeProperty('font-size');
344                }
345            } else if (Number.isFinite(baseFS)) {
346                let newFontSize = baseFS * s;
347                if (requiredMin > 0) {
348                    newFontSize = Math.max(newFontSize, requiredMin);
349                }
350                el.style.setProperty('font-size', newFontSize + 'px', 'important');
351            }
352            let targetLHpx = null;
353            if (tag === 'p' || tag === 'li') {
354                if (Number.isFinite(baseFS)) {
355                    targetLHpx = baseFS * BASE_LS * s;
356                }
357            } else if (tag === 'small') {
358                if (Number.isFinite(baseFS)) {
359                    targetLHpx = baseFS * (BASE_LS * BASE_SMALL_F) * s;
360                }
361            } else if (tag === 'h1') {
362                targetLHpx = BASE_LS * BASE_H1_PX * s;
363            } else if (tag === 'h2') {
364                targetLHpx = BASE_LS * BASE_H2_PX * s;
365            } else if (tag === 'h4') {
366                targetLHpx = BASE_LS * BASE_H4_PX * s;
367            }
368            if (el.matches('.entr.tour .entr-facts div')) {
369                targetLHpx = BASE_LS * BASE_FACTS_PX * s;
370            }
371            if (s === 1.0) {
372                el.style.removeProperty('line-height');
373            } else if (Number.isFinite(targetLHpx)) {
374                el.style.setProperty('line-height', targetLHpx + 'px', 'important');
375            }
376        });
377    }
378    window.changeFontsize = function changeFontsize(scaleLike) {
379        const raw = parseFloat(scaleLike);
380        const s = clamp(Number.isFinite(raw) ? raw : 1.0, 0.5, 3.0);
381        if (s === 1.0) {
382            if (window.Cookies?.remove) Cookies.remove(COOKIE_KEY_SCALE, COOKIE_REMOVE_OPTS);
383        } else {
384            if (window.Cookies?.set) Cookies.set(COOKIE_KEY_SCALE, s, COOKIE_SET_OPTS);
385        }
386        scheduleApplyScale(s);
387    };
388    window.resetFontsize = function resetFontsize() {
389        const elements = document.querySelectorAll(TEXT_SELECTOR);
390        elements.forEach((el) => {
391            if (isInside(el, EXCLUDE_SEL)) return;
392            el.style.removeProperty('font-size');
393            el.style.removeProperty('line-height');
394        });
395        if (window.Cookies?.remove) {
396            Cookies.remove(COOKIE_KEY_SCALE, COOKIE_REMOVE_OPTS);
397            Cookies.remove(LEGACY_COOKIE_LS, COOKIE_REMOVE_OPTS);
398        }
399        document.body.classList.remove('accFontSizeActive');
400        const slider = document.getElementById('fontsizeAcc');
401        if (slider) slider.value = 1.0;
402        scheduleApplyScale(1.0);
403    };
404        function migrateLegacyCookieIfNeeded() {
405            if (!window.Cookies?.get) return null;
406            const legacy = Cookies.get(LEGACY_COOKIE_LS);
407            if (!legacy) return null;
408            const legacySize = parseFloat(legacy);
409            if (!Number.isFinite(legacySize) || legacySize <= 0) {
410                Cookies.remove(LEGACY_COOKIE_LS, COOKIE_REMOVE_OPTS);
411                return null;
412            }
413            const scale = clamp(legacySize / BASE_LS, 0.5, 3.0);
414            Cookies.set(COOKIE_KEY_SCALE, scale, COOKIE_SET_OPTS);
415            Cookies.remove(LEGACY_COOKIE_LS, COOKIE_REMOVE_OPTS);
416            return scale;
417        }
418        function initFromCookieOrDefault() {
419            let scale = 1.0;
420            const migrated = migrateLegacyCookieIfNeeded();
421            if (migrated != null) {
422                scale = migrated;
423            } else if (window.Cookies?.get) {
424                const saved = parseFloat(Cookies.get(COOKIE_KEY_SCALE) || '');
425                if (Number.isFinite(saved) && saved > 0) {
426                    scale = saved;
427                }
428            }
429            const slider = document.getElementById('fontsizeAcc');
430            if (slider) slider.value = String(scale);
431            applyScale(scale);
432        }
433        if (document.readyState === 'loading') {
434            document.addEventListener('DOMContentLoaded', initFromCookieOrDefault, { once: true });
435        } else {
436            initFromCookieOrDefault();
437        }
438    }
439)();
440
441/* Vorlesefunktion */
442/*******************/
443var lastSelectedReadableText = '';
444var lastAccessibilityTrigger = null;
445var accScreenreaderDrag = {
446	isDragging: false,
447	offsetX: 0,
448	offsetY: 0
449};
450
451function initAccessibilityModalFocus() {
452	var modalEl = document.getElementById('accesible');
453	if (!modalEl) return;
454
455	document.addEventListener('click', function(event) {
456		var trigger = event.target.closest('.openModalBtn');
457		if (trigger) {
458			lastAccessibilityTrigger = trigger;
459		}
460	});
461
462	modalEl.addEventListener('shown.bs.modal', function() {
463		modalEl.setAttribute('aria-hidden', 'false');
464		var closeButton = modalEl.querySelector('.acc-modal-close');
465		if (closeButton) closeButton.focus();
466	});
467
468	modalEl.addEventListener('hidden.bs.modal', function() {
469		modalEl.setAttribute('aria-hidden', 'true');
470		if (lastAccessibilityTrigger && document.contains(lastAccessibilityTrigger)) {
471			lastAccessibilityTrigger.focus();
472		}
473	});
474}
475
476if (document.readyState === 'loading') {
477	document.addEventListener('DOMContentLoaded', initAccessibilityModalFocus, { once: true });
478} else {
479	initAccessibilityModalFocus();
480}
481
482function setScreenreaderStatus(message) {
483	var status = document.getElementById('accScreenreaderStatus');
484	if (status) {
485		status.textContent = message;
486	}
487}
488
489function cleanupAccessibilityModalArtifacts() {
490	document.body.classList.remove('modal-open');
491	document.body.style.removeProperty('padding-right');
492	document.querySelectorAll('.modal-backdrop').forEach(function(backdrop) {
493		backdrop.remove();
494	});
495}
496
497function closeAccessibilityModalForReading() {
498	var modalEl = document.getElementById('accesible');
499	if (!modalEl) {
500		return;
501	}
502
503	if (window.bootstrap && window.bootstrap.Modal) {
504		var instance = window.bootstrap.Modal.getInstance(modalEl);
505		if (instance) {
506			instance.hide();
507		}
508	}
509
510	modalEl.classList.remove('show');
511	modalEl.style.display = 'none';
512	modalEl.setAttribute('aria-hidden', 'true');
513
514	setTimeout(cleanupAccessibilityModalArtifacts, 180);
515}
516
517function openScreenreaderPanel() {
518	closeAccessibilityModalForReading();
519	var panel = document.getElementById('accScreenreaderPanel');
520	if (panel) {
521		panel.hidden = false;
522		if (!panel.dataset.positioned) {
523			panel.style.top = '96px';
524			panel.style.right = '16px';
525			panel.style.left = 'auto';
526			panel.dataset.positioned = 'true';
527		}
528		window.setTimeout(function() {
529			var closeButton = panel.querySelector('.acc-screenreader-close');
530			if (closeButton) closeButton.focus();
531		}, 220);
532	}
533	setScreenreaderStatus('Text markieren und auf "Vorlesen starten" klicken.');
534}
535
536function closeScreenreaderPanel() {
537	stopSelectedText();
538	var panel = document.getElementById('accScreenreaderPanel');
539	if (panel) {
540		panel.hidden = true;
541	}
542}
543
544function readSelectedText() {
545	var selectedText = getSelectedText();
546	if (!selectedText) {
547		selectedText = lastSelectedReadableText;
548	}
549	if (!selectedText) {
550		setScreenreaderStatus('Bitte markiere zuerst einen Text auf der Seite.');
551		return;
552	}
553	speakText(selectedText);
554}
555
556function getSelectedText() {
557	var text = '';
558	if (typeof window.getSelection !== 'undefined') {
559		text = window.getSelection().toString();
560	} else if (typeof document.selection !== 'undefined' && document.selection.type === 'Text') {
561		text = document.selection.createRange().text;
562	}
563	return text.trim();
564}
565
566function speakText(text) {
567	if (!('speechSynthesis' in window) || typeof window.SpeechSynthesisUtterance === 'undefined') {
568		setScreenreaderStatus('Vorlesen wird von diesem Browser nicht unterstuetzt.');
569		return;
570	}
571
572	var utterance = new SpeechSynthesisUtterance(text);
573	var lang = document.documentElement.lang || 'de';
574	utterance.lang = lang;
575
576	var voices = window.speechSynthesis.getVoices();
577	var voice = voices.find(function(v) { return v.lang && v.lang.indexOf(lang) === 0; });
578	if (voice) {
579		utterance.voice = voice;
580	}
581
582	utterance.onstart = function() {
583		setScreenreaderStatus('Vorlesen gestartet.');
584	};
585	utterance.onend = function() {
586		setScreenreaderStatus('Vorlesen beendet.');
587	};
588	utterance.onerror = function() {
589		setScreenreaderStatus('Vorlesen konnte nicht gestartet werden.');
590	};
591
592	window.speechSynthesis.cancel();
593	window.speechSynthesis.speak(utterance);
594}
595
596function stopSelectedText() {
597	if ('speechSynthesis' in window) {
598		window.speechSynthesis.cancel();
599	}
600	setScreenreaderStatus('Vorlesen gestoppt.');
601}
602
603function clampScreenreaderPosition(panel, left, top) {
604	var maxLeft = Math.max(8, window.innerWidth - panel.offsetWidth - 8);
605	var maxTop = Math.max(8, window.innerHeight - panel.offsetHeight - 8);
606	return {
607		left: Math.min(Math.max(8, left), maxLeft),
608		top: Math.min(Math.max(8, top), maxTop)
609	};
610}
611
612function startScreenreaderDrag(clientX, clientY) {
613	var panel = document.getElementById('accScreenreaderPanel');
614	if (!panel || panel.hidden) {
615		return;
616	}
617	var rect = panel.getBoundingClientRect();
618	if (rect.width === 0 || rect.height === 0) {
619		return;
620	}
621	accScreenreaderDrag.isDragging = true;
622	accScreenreaderDrag.offsetX = clientX - rect.left;
623	accScreenreaderDrag.offsetY = clientY - rect.top;
624	document.body.classList.add('acc-screenreader-dragging');
625}
626
627function moveScreenreaderDrag(clientX, clientY) {
628	if (!accScreenreaderDrag.isDragging) {
629		return;
630	}
631	var panel = document.getElementById('accScreenreaderPanel');
632	if (!panel) {
633		return;
634	}
635	var nextLeft = clientX - accScreenreaderDrag.offsetX;
636	var nextTop = clientY - accScreenreaderDrag.offsetY;
637	var clamped = clampScreenreaderPosition(panel, nextLeft, nextTop);
638	panel.style.left = clamped.left + 'px';
639	panel.style.top = clamped.top + 'px';
640	panel.style.right = 'auto';
641}
642
643function stopScreenreaderDrag() {
644	accScreenreaderDrag.isDragging = false;
645	document.body.classList.remove('acc-screenreader-dragging');
646}
647
648function initScreenreaderPanelInteractions() {
649	if (window.__accScreenreaderPanelInit) {
650		return;
651	}
652	window.__accScreenreaderPanelInit = true;
653
654	document.addEventListener('selectionchange', function() {
655		var selected = getSelectedText();
656		if (selected) {
657			lastSelectedReadableText = selected;
658			setScreenreaderStatus('Text markiert. Klicke auf "Vorlesen starten".');
659		}
660	});
661
662	var handle = document.getElementById('accScreenreaderDragHandle');
663	if (handle) {
664		handle.addEventListener('mousedown', function(event) {
665			if (event.button !== 0) {
666				return;
667			}
668			event.preventDefault();
669			startScreenreaderDrag(event.clientX, event.clientY);
670		});
671
672		handle.addEventListener('touchstart', function(event) {
673			if (!event.touches || !event.touches.length) {
674				return;
675			}
676			startScreenreaderDrag(event.touches[0].clientX, event.touches[0].clientY);
677		}, { passive: true });
678	}
679
680	document.addEventListener('mousemove', function(event) {
681		moveScreenreaderDrag(event.clientX, event.clientY);
682	});
683	document.addEventListener('touchmove', function(event) {
684		if (!event.touches || !event.touches.length) {
685			return;
686		}
687		moveScreenreaderDrag(event.touches[0].clientX, event.touches[0].clientY);
688	}, { passive: true });
689
690	document.addEventListener('mouseup', stopScreenreaderDrag);
691	document.addEventListener('touchend', stopScreenreaderDrag, { passive: true });
692
693	window.addEventListener('keydown', function(event) {
694		if (event.key === 'Escape') {
695			closeScreenreaderPanel();
696		}
697	});
698
699	window.addEventListener('resize', function() {
700		var panel = document.getElementById('accScreenreaderPanel');
701		if (!panel || panel.hidden) {
702			return;
703		}
704		var rect = panel.getBoundingClientRect();
705		var clamped = clampScreenreaderPosition(panel, rect.left, rect.top);
706		panel.style.left = clamped.left + 'px';
707		panel.style.top = clamped.top + 'px';
708		panel.style.right = 'auto';
709	});
710}
711
712if (document.readyState === 'loading') {
713	document.addEventListener('DOMContentLoaded', initScreenreaderPanelInteractions, { once: true });
714} else {
715	initScreenreaderPanelInteractions();
716}
717
718/* Lichtbar einblenden */
719/***********************/
720function showLightbar() {
721    var checkbox = document.getElementById('lightbarAcc');
722    var lightbartop = document.getElementById('light-bar-top');
723    var lightbarbottom = document.getElementById('light-bar-bottom');
724    if (checkbox.checked) {
725        lightbartop.style.display = 'block';
726        lightbarbottom.style.display = 'block';
727        Cookies.set('acc_lightbar', 'true', COOKIE_SET_OPTS);
728    } else {
729        lightbartop.style.display = 'none';
730        lightbarbottom.style.display = 'none';
731        Cookies.set('acc_lightbar', 'false', COOKIE_SET_OPTS);
732    }
733}
734function resetLightbar() {
735    var checkbox = document.getElementById('lightbarAcc');
736    var lightbartop = document.getElementById('light-bar-top');
737    var lightbarbottom = document.getElementById('light-bar-bottom');
738    checkbox.checked = false;
739    lightbartop.style.display = 'none';
740    lightbarbottom.style.display = 'none';
741    Cookies.remove('acc_lightbar', COOKIE_REMOVE_OPTS);
742}
743function updatePositionDisplay(event) {
744    var lightbartop = document.getElementById('light-bar-top');
745    var lightbarbottom = document.getElementById('light-bar-bottom');
746    var mouseYBtm = window.innerHeight - event.clientY;
747    var mouseYTop = event.clientY;
748    var offsetYBtm = mouseYBtm - 100;
749    var offsetYTop = mouseYTop - 100;
750    lightbarbottom.style.height = offsetYBtm + 'px';
751    lightbartop.style.height = offsetYTop + 'px';
752}
753document.addEventListener("DOMContentLoaded", function() {
754    var checkbox = document.getElementById('lightbarAcc');
755    var lightbartop = document.getElementById('light-bar-top');
756    var lightbarbottom = document.getElementById('light-bar-bottom');
757    if (Cookies.get('acc_lightbar') === 'true') {
758        checkbox.checked = true;
759        lightbartop.style.display = 'block';
760        lightbarbottom.style.display = 'block';
761    } else {
762        checkbox.checked = false;
763        lightbartop.style.display = 'none';
764        lightbarbottom.style.display = 'none';
765    }
766});
767window.addEventListener('mousemove', updatePositionDisplay);
768
769
770function convertLegacyActionButtonToSwitch(buttonId, labelId, defaultLabel, onchangeFn) {
771    var oldEl = document.getElementById(buttonId);
772    if (!oldEl || oldEl.tagName.toLowerCase() !== 'button') {
773        return;
774    }
775
776    var labelCard = document.createElement('label');
777    labelCard.className = 'acc-switch-card';
778    labelCard.setAttribute('for', buttonId);
779
780    var labelSpan = document.createElement('span');
781    labelSpan.id = labelId;
782    labelSpan.textContent = defaultLabel;
783
784    var input = document.createElement('input');
785    input.className = 'acc-switch-input';
786    input.type = 'checkbox';
787    input.id = buttonId;
788    input.setAttribute('onchange', onchangeFn + '()');
789
790    // Preserve visible state from legacy button text/cookies if present.
791    var legacyText = (oldEl.textContent || '').toLowerCase();
792    if (buttonId === 'nopicAcc') {
793        input.checked = legacyText.indexOf('einblenden') !== -1 || oldEl.dataset.hidden === 'true';
794    }
795    if (buttonId === 'animationAcc') {
796        input.checked = legacyText.indexOf('einschalten') !== -1;
797    }
798
799    var ui = document.createElement('span');
800    ui.className = 'acc-switch-ui';
801    ui.setAttribute('aria-hidden', 'true');
802
803    labelCard.appendChild(labelSpan);
804    labelCard.appendChild(input);
805    labelCard.appendChild(ui);
806
807    oldEl.replaceWith(labelCard);
808}
809
810function normalizeConcentrationSwitches() {
811    convertLegacyActionButtonToSwitch('nopicAcc', 'nopicAccLabel', 'Bilder ausblenden', 'toggleImages');
812    convertLegacyActionButtonToSwitch('animationAcc', 'animationAccLabel', 'Animationen ausschalten', 'toggleAnimation');
813}
814
815if (document.readyState === 'loading') {
816    document.addEventListener('DOMContentLoaded', normalizeConcentrationSwitches, { once: true });
817} else {
818    normalizeConcentrationSwitches();
819}
820/* Hidden Images */
821/* ************* */
822function setImagesHidden(hidden) {
823    var elements = document.getElementsByTagName('*');
824    var checkbox = document.getElementById('nopicAcc');
825    var label = document.getElementById('nopicAccLabel');
826
827    for (var i = 0; i < elements.length; i++) {
828        var el = elements[i];
829        var tag = el.tagName;
830
831        if (tag === 'IMG') {
832            if (hidden) {
833                if (!el.classList.contains('activeNoPicFilter')) el.classList.add('activeNoPicFilter');
834                el.style.visibility = 'hidden';
835            } else {
836                el.classList.remove('activeNoPicFilter');
837                el.style.removeProperty('visibility');
838            }
839            continue;
840        }
841
842        if (tag === 'CANVAS') {
843            if (hidden) {
844                if (!el.classList.contains('activeNoPicFilter')) el.classList.add('activeNoPicFilter');
845                el.style.visibility = 'hidden';
846            } else {
847                el.classList.remove('activeNoPicFilter');
848                el.style.removeProperty('visibility');
849            }
850            continue;
851        }
852
853        var bg = window.getComputedStyle(el).backgroundImage;
854        if (hidden) {
855            if (bg && bg !== 'none') {
856                if (!el.dataset.bgImage) {
857                    el.dataset.bgImage = bg;
858                }
859                el.classList.add('has-background-image', 'activeNoPicFilter');
860                el.style.backgroundImage = 'none';
861            }
862        } else {
863            if (el.classList.contains('has-background-image') || el.classList.contains('activeNoPicFilter')) {
864                el.classList.remove('has-background-image', 'activeNoPicFilter');
865                if (el.dataset.bgImage) {
866                    el.style.backgroundImage = el.dataset.bgImage;
867                    delete el.dataset.bgImage;
868                } else {
869                    el.style.removeProperty('background-image');
870                }
871            }
872        }
873    }
874
875    if (checkbox) {
876        checkbox.checked = hidden;
877        checkbox.dataset.hidden = hidden ? 'true' : 'false';
878    }
879    if (label) {
880        label.textContent = hidden ? 'Bilder einblenden' : 'Bilder ausblenden';
881    }
882
883    document.body.classList.toggle('accImagesHiddenActive', hidden);
884    Cookies.set('acc_toggleImages', hidden ? 'true' : 'false', COOKIE_SET_OPTS);
885}
886
887function resetImagesHidden() {
888    setImagesHidden(false);
889    Cookies.remove('acc_toggleImages', COOKIE_REMOVE_OPTS);
890}
891
892function toggleImages() {
893    var checkbox = document.getElementById('nopicAcc');
894    if (checkbox) {
895        setImagesHidden(checkbox.checked);
896    } else {
897        var current = Cookies.get('acc_toggleImages') === 'true';
898        setImagesHidden(!current);
899    }
900}
901
902/* Turn off Animation */
903/**********************/
904function applyAnimationState(disabled) {
905    var elements = document.getElementsByTagName('*');
906    var checkbox = document.getElementById('animationAcc');
907    var label = document.getElementById('animationAccLabel');
908
909    for (var i = 0; i < elements.length; i++) {
910        var element = elements[i];
911        if (disabled) {
912            if (element.classList.contains('reveal')) {
913                if (!element.getAttribute('data-original-class')) {
914                    element.setAttribute('data-original-class', element.className);
915                }
916                element.classList.remove('reveal');
917            }
918        } else {
919            var originalClass = element.getAttribute('data-original-class');
920            if (originalClass && originalClass.indexOf('reveal') !== -1) {
921                element.className = originalClass;
922                element.removeAttribute('data-original-class');
923            }
924        }
925    }
926
927    var fogs = document.getElementsByClassName('fog-bg');
928    for (var j = 0; j < fogs.length; j++) {
929        fogs[j].style.display = disabled ? 'block' : 'none';
930    }
931
932    var classTargets = ['omj-cta', 'covercontainer', 'vertical-line'];
933    for (var k = 0; k < classTargets.length; k++) {
934        var items = document.getElementsByClassName(classTargets[k]);
935        for (var m = 0; m < items.length; m++) {
936            items[m].classList.toggle('no-animate', disabled);
937        }
938    }
939
940    if (checkbox) {
941        checkbox.checked = disabled;
942    }
943    if (label) {
944        label.textContent = disabled ? 'Animationen einschalten' : 'Animationen ausschalten';
945    }
946
947    Cookies.set('acc_animation', disabled ? 'true' : 'false', COOKIE_SET_OPTS);
948}
949
950function toggleAnimation() {
951    var checkbox = document.getElementById('animationAcc');
952    if (checkbox) {
953        applyAnimationState(checkbox.checked);
954    } else {
955        var current = Cookies.get('acc_animation') === 'true';
956        applyAnimationState(!current);
957    }
958}
959
960function resetAnimation() {
961    applyAnimationState(false);
962    Cookies.remove('acc_animation', COOKIE_REMOVE_OPTS);
963}
964/* Farbschwaechen-Modi */
965/**********************/
966const COLOR_WEAKNESS_MODES = ['protanomalyAcc', 'deuteranomalyAcc', 'tritanomalyAcc'];
967const COLOR_WEAKNESS_CLASS_MAP = {
968    protanomalyAcc: 'acc-cw-protanomaly',
969    deuteranomalyAcc: 'acc-cw-deuteranomaly',
970    tritanomalyAcc: 'acc-cw-tritanomaly'
971};
972const COLOR_WEAKNESS_ALL_CLASSES = ['acc-cw-protanomaly', 'acc-cw-deuteranomaly', 'acc-cw-tritanomaly'];
973
974function normalizeColorWeaknessMode(mode) {
975    var map = {
976        protanomaly: 'protanomalyAcc',
977        deuteranomaly: 'deuteranomalyAcc',
978        tritanomaly: 'tritanomalyAcc'
979    };
980    return map[mode] || mode;
981}
982
983function getColorWeaknessOverlay() {
984    return document.getElementById('acc-colorweakness-overlay');
985}
986
987function clearColorWeaknessTargetClasses() {
988    document.querySelectorAll('.acc-colorweakness-target').forEach(function (el) {
989        el.classList.remove('acc-colorweakness-target');
990        COLOR_WEAKNESS_ALL_CLASSES.forEach(function (cls) {
991            el.classList.remove(cls);
992        });
993    });
994}
995
996function getColorWeaknessTargets() {
997    var baseTargets = Array.from(document.querySelectorAll('img, video, canvas, .bg-cover, .covercontainer'));
998    var bgTargets = [];
999    document.querySelectorAll('section, article, div, li, a, figure').forEach(function (el) {
1000        if (el.closest('#accesible, #accScreenreaderPanel, .excludeAcc')) {
1001            return;
1002        }
1003        var bg = window.getComputedStyle(el).backgroundImage;
1004        if (bg && bg !== 'none') {
1005            bgTargets.push(el);
1006        }
1007    });
1008    return Array.from(new Set(baseTargets.concat(bgTargets)));
1009}
1010
1011function applyColorWeaknessMode(modeId) {
1012    var modeClass = COLOR_WEAKNESS_CLASS_MAP[modeId] || '';
1013    var overlay = getColorWeaknessOverlay();
1014
1015    clearColorWeaknessTargetClasses();
1016    document.body.classList.remove('acc-colorweakness-active');
1017    COLOR_WEAKNESS_ALL_CLASSES.forEach(function (cls) {
1018        document.body.classList.remove(cls);
1019    });
1020
1021    if (overlay) {
1022        overlay.className = 'acc-colorweakness-overlay';
1023    }
1024
1025    if (!modeClass) {
1026        Cookies.remove('acc_colorweakness', COOKIE_REMOVE_OPTS);
1027        return;
1028    }
1029
1030    getColorWeaknessTargets().forEach(function (el) {
1031        el.classList.add('acc-colorweakness-target', modeClass);
1032    });
1033
1034    document.body.classList.add('acc-colorweakness-active', modeClass);
1035
1036    if (overlay) {
1037        overlay.classList.add('is-active', modeClass);
1038    }
1039
1040    Cookies.set('acc_colorweakness', modeId, COOKIE_SET_OPTS);
1041}
1042
1043function resetColorWeakness() {
1044    COLOR_WEAKNESS_MODES.forEach(function (id) {
1045        var cb = document.getElementById(id);
1046        if (cb) cb.checked = false;
1047    });
1048    applyColorWeaknessMode('');
1049}
1050
1051function toggleColorMode(selectedId) {
1052    COLOR_WEAKNESS_MODES.forEach(function (id) {
1053        if (id !== selectedId) {
1054            var cbOther = document.getElementById(id);
1055            if (cbOther) cbOther.checked = false;
1056        }
1057    });
1058
1059    var checkbox = document.getElementById(selectedId);
1060    if (!checkbox || !checkbox.checked) {
1061        applyColorWeaknessMode('');
1062        return;
1063    }
1064
1065    applyColorWeaknessMode(selectedId);
1066}
1067
1068document.addEventListener('DOMContentLoaded', function () {
1069    var savedMode = normalizeColorWeaknessMode(Cookies.get('acc_colorweakness'));
1070    if (COLOR_WEAKNESS_MODES.includes(savedMode)) {
1071        var savedCb = document.getElementById(savedMode);
1072        if (savedCb) savedCb.checked = true;
1073        applyColorWeaknessMode(savedMode);
1074    }
1075});
1076
1077/* Lade- und Uebertragsfunktion */
1078/*******************************/
1079document.addEventListener("DOMContentLoaded", function(event){
1080  var bluescale = Cookies.get('acc_bluescale');
1081  if (bluescale && bluescale.length > 0){
1082    changeBluescale(bluescale);
1083    var sliderBluescale = document.getElementById('bluefilterAcc');
1084    if (sliderBluescale) sliderBluescale.value = bluescale;
1085  }
1086
1087  // --- Bilder-Zustand ANWENDEN, nicht toggeln ---
1088  var hideImages = Cookies.get('acc_toggleImages') === 'true';
1089  setImagesHidden(hideImages);
1090
1091  var lightbar = Cookies.get('acc_lightbar');
1092  if (lightbar && lightbar === 'true'){
1093    showLightbar();
1094  }
1095
1096  var toggleAnim = Cookies.get('acc_animation') === 'true';
1097  applyAnimationState(toggleAnim);
1098
1099  var greyscale = Cookies.get('acc_greyscale');
1100  if (greyscale && greyscale.length > 0){
1101    changeGreyscale(greyscale);
1102    var sliderGreyscale = document.getElementById('greyscaleAcc');
1103    if (sliderGreyscale) sliderGreyscale.value = greyscale;
1104  }
1105
1106  var contrast = Cookies.get('acc_contrast');
1107  if (contrast && contrast.length > 0){
1108    changeContrast(contrast);
1109    var sliderContrast = document.getElementById('contrastAcc');
1110    if (sliderContrast) sliderContrast.value = contrast;
1111  }
1112
1113  var saturation = Cookies.get('acc_saturation');
1114  if (saturation && saturation.length > 0){
1115    changeSaturation(saturation);
1116    var sliderSaturation = document.getElementById('saturationAcc');
1117    if (sliderSaturation) sliderSaturation.value = saturation;
1118  }
1119  var colorweakness = normalizeColorWeaknessMode(Cookies.get('acc_colorweakness'));
1120  if (COLOR_WEAKNESS_MODES.includes(colorweakness)) {
1121    var colorCb = document.getElementById(colorweakness);
1122    if (colorCb) colorCb.checked = true;
1123    applyColorWeaknessMode(colorweakness);
1124  }
1125var fontsize = Cookies.get('acc_fontsize');
1126  if (fontsize && fontsize.length > 0){
1127    changeFontsize(fontsize);
1128    var sliderFontsize = document.getElementById('fontsizeAcc');
1129    if (sliderFontsize) sliderFontsize.value = fontsize;
1130  }
1131
1132  var linespacing = Cookies.get('acc_linespacing');
1133  if (linespacing && linespacing.length > 0 && typeof changeLinespacing === 'function'){
1134    changeLinespacing(linespacing);
1135    var sliderLinespacing = document.getElementById('linespacingAcc');
1136    // (Mini-Fix für falsches Zuweisen war bereits hier korrigiert, bleibt erhalten)
1137    if (sliderLinespacing) sliderLinespacing.value = linespacing;
1138  }
1139});
1140
1141/* Zurücksetzen */
1142/****************/
1143function resetAcc(){
1144	resetBluescale();
1145	resetGreyscale();
1146	resetSaturation();
1147	resetContrast();
1148	resetFontsize();
1149	// resetLinespacing();
1150	resetLightbar();
1151	resetColorWeakness();	
1152	resetAnimation();
1153	resetImagesHidden();
1154}
1155
1156/* Keyboard focus visibility */
1157/*****************************/
1158(function initKeyboardFocusMode() {
1159    function setKeyboardMode() {
1160        if (!document.body) return;
1161        document.body.classList.add('using-keyboard');
1162        document.body.classList.remove('using-mouse');
1163    }
1164
1165    function setPointerMode() {
1166        if (!document.body) return;
1167        document.body.classList.remove('using-keyboard');
1168        document.body.classList.add('using-mouse');
1169    }
1170
1171    document.addEventListener('keydown', function (event) {
1172        if (event.key === 'Tab') {
1173            setKeyboardMode();
1174        }
1175    });
1176
1177    document.addEventListener('mousedown', setPointerMode, true);
1178    document.addEventListener('touchstart', setPointerMode, { passive: true, capture: true });
1179})();
1180
1181/* Third-party button accessible names */
1182/*************************************/
1183(function ensureThirdPartyButtonLabels() {
1184    var CLOSE_BTN_SELECTOR = 'button#pc-sb-close.pc-icon-btn';
1185    var CLOSE_BTN_LABEL = 'Sidebar schliessen';
1186
1187    function setAccessibleName(button, label) {
1188        if (!button) return;
1189        var current = (button.getAttribute('aria-label') || '').trim();
1190        if (!current) {
1191            button.setAttribute('aria-label', label);
1192        }
1193        var currentTitle = (button.getAttribute('title') || '').trim();
1194        if (!currentTitle) {
1195            button.setAttribute('title', label);
1196        }
1197    }
1198
1199    function applyLabels() {
1200        var closeBtn = document.querySelector(CLOSE_BTN_SELECTOR);
1201        if (closeBtn) {
1202            setAccessibleName(closeBtn, CLOSE_BTN_LABEL);
1203        }
1204    }
1205
1206    if (document.readyState === 'loading') {
1207        document.addEventListener('DOMContentLoaded', applyLabels, { once: true });
1208    } else {
1209        applyLabels();
1210    }
1211
1212    var rafPending = false;
1213    var observer = new MutationObserver(function () {
1214        if (rafPending) return;
1215        rafPending = true;
1216        requestAnimationFrame(function () {
1217            rafPending = false;
1218            applyLabels();
1219        });
1220    });
1221
1222    observer.observe(document.documentElement, { childList: true, subtree: true });
1223})();
1224
1225
1226
1227

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.