https://www.schlagerradio.de/wp-content/themes/ella-radio-theme/assets/js/accessibility.js?ver=1.6.6
1/** 2 * Accessibility Widget 3 * Ella Radio Theme 4 */ 5 6(function() { 7 'use strict'; 8 9 // Initialize flag to prevent multiple initializations 10 let isInitialized = false; 11 12 // State 13 const state = { 14 fontSize: 100, 15 highContrast: false, 16 readingMode: false, 17 highlightLinks: false, 18 reduceMotion: false 19 }; 20 21 // Load saved settings 22 function loadSettings() { 23 const saved = localStorage.getItem('ella_accessibility_settings'); 24 if (saved) { 25 Object.assign(state, JSON.parse(saved)); 26 applySettings(); 27 } 28 } 29 30 // Save settings 31 function saveSettings() { 32 localStorage.setItem('ella_accessibility_settings', JSON.stringify(state)); 33 } 34 35 // Apply all settings 36 function applySettings() { 37 applyFontSize(); 38 applyHighContrast(); 39 applyReadingMode(); 40 applyLinkHighlight(); 41 applyReduceMotion(); 42 } 43 44 // Font Size 45 function applyFontSize() { 46 document.documentElement.style.fontSize = state.fontSize + '%'; 47 const display = document.querySelector('.font-size-display'); 48 if (display) display.textContent = state.fontSize + '%'; 49 } 50 51 function changeFontSize(delta) { 52 state.fontSize = Math.max(80, Math.min(150, state.fontSize + delta)); 53 applyFontSize(); 54 saveSettings(); 55 } 56 57 // High Contrast 58 function applyHighContrast() { 59 document.body.classList.toggle('high-contrast', state.highContrast); 60 updateToggle('high-contrast-toggle', state.highContrast); 61 } 62 63 // Reading Mode 64 function applyReadingMode() { 65 document.body.classList.toggle('reading-mode', state.readingMode); 66 updateToggle('reading-mode-toggle', state.readingMode); 67 } 68 69 // Link Highlight 70 function applyLinkHighlight() { 71 document.body.classList.toggle('highlight-links', state.highlightLinks); 72 updateToggle('highlight-links-toggle', state.highlightLinks); 73 } 74 75 // Reduce Motion 76 function applyReduceMotion() { 77 document.body.classList.toggle('reduce-motion', state.reduceMotion); 78 updateToggle('reduce-motion-toggle', state.reduceMotion); 79 } 80 81 // Update toggle button state 82 function updateToggle(id, active) { 83 const toggle = document.getElementById(id); 84 if (toggle) { 85 toggle.classList.toggle('active', active); 86 toggle.setAttribute('aria-checked', active); 87 } 88 } 89 90 // Create Widget HTML 91 function createWidget() { 92 93 // Check if widget already exists 94 const existing = document.getElementById('accessibility-widget'); 95 if (existing) { 96 return; 97 } 98 99 const widget = document.createElement('div'); 100 widget.id = 'accessibility-widget'; 101 widget.className = 'accessibility-widget'; 102 widget.setAttribute('role', 'dialog'); 103 widget.setAttribute('aria-label', 'Barrierefreiheit-Einstellungen'); 104 widget.style.display = 'none'; 105 106 widget.innerHTML = ` 107 <div class="accessibility-header"> 108 <div class="accessibility-title"> 109 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 110 <circle cx="12" cy="12" r="10"/> 111 <circle cx="12" cy="8" r="2"/> 112 <path d="M12 14v6M8 18h8"/> 113 </svg> 114 <span>Barrierefreiheit</span> 115 </div> 116 <button class="accessibility-reset" id="accessibility-reset" aria-label="Zurücksetzen"> 117 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 118 <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/> 119 <path d="M21 3v5h-5"/> 120 </svg> 121 Zurücksetzen 122 </button> 123 <button class="accessibility-close" id="accessibility-close" aria-label="SchlieÃen"> 124 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 125 <path d="M18 6L6 18M6 6l12 12"/> 126 </svg> 127 </button> 128 </div> 129 130 <div class="accessibility-content"> 131 <!-- Font Size --> 132 <div class="accessibility-option"> 133 <div class="accessibility-option-header">
134 <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"> 135 <path d="M9 4v3h5v12h3V7h5V4H9zm-6 8h3v7h3v-7h3V9H3v3z"/> 136 </svg> 137 <span>SchriftgröÃe</span> 138 </div> 139 <div class="font-size-controls"> 140 <button id="font-size-decrease" aria-label="Schrift verkleinern"> 141 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 142 <path d="M5 12h14"/> 143 </svg> 144 </button> 145 <span class="font-size-display">100%</span> 146 <button id="font-size-increase" aria-label="Schrift vergröÃern"> 147 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 148 <path d="M12 5v14M5 12h14"/> 149 </svg> 150 </button> 151 </div> 152 </div> 153 154 <!-- High Contrast --> 155 <div class="accessibility-option"> 156 <div class="accessibility-option-header"> 157 <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"> 158 <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8v16z"/> 159 </svg> 160 <span>Hoher Kontrast</span> 161 </div> 162 <button class="accessibility-toggle" id="high-contrast-toggle" role="switch" aria-checked="false"> 163 <span class="toggle-track"> 164 <span class="toggle-thumb"></span> 165 </span> 166 </button> 167 </div> 168 169 <!-- Reading Mode --> 170 <div class="accessibility-option"> 171 <div class="accessibility-option-header"> 172 <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"> 173 <path d="M21 5c-1.11-.35-2.33-.5-3.5-.5-1.95 0-4.05.4-5.5 1.5-1.45-1.1-3.55-1.5-5.5-1.5S2.45 4.9 1 6v14.65c0 .25.25.5.5.5.1 0 .15-.05.25-.05C3.1 20.45 5.05 20 6.5 20c1.95 0 4.05.4 5.5 1.5 1.35-.85 3.8-1.5 5.5-1.5 1.65 0 3.35.3 4.75 1.05.1.05.15.05.25.05.25 0 .5-.25.5-.5V6c-.6-.45-1.25-.75-2-1zm0 13.5c-1.1-.35-2.3-.5-3.5-.5-1.7 0-4.15.65-5.5 1.5V8c1.35-.85 3.8-1.5 5.5-1.5 1.2 0 2.4.15 3.5.5v11.5z"/> 174 </svg> 175 <span>Lesemodus</span> 176 </div> 177 <button class="accessibility-toggle" id="reading-mode-toggle" role="switch" aria-checked="false"> 178 <span class="toggle-track"> 179 <span class="toggle-thumb"></span> 180 </span> 181 </button> 182 </div> 183 184 <!-- Highlight Links --> 185 <div class="accessibility-option"> 186 <div class="accessibility-option-header"> 187 <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"> 188 <path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/> 189 </svg> 190 <span>Links hervorheben</span> 191 </div> 192 <button class="accessibility-toggle" id="highlight-links-toggle" role="switch" aria-checked="false"> 193 <span class="toggle-track"> 194 <span class="toggle-thumb"></span> 195 </span> 196 </button> 197 </div> 198 199 <!-- Reduce Motion --> 200 <div class="accessibility-option"> 201 <div class="accessibility-option-header">
202 <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"> 203 <path d="M18 8h2V6h-2v2zm0 4h2v-2h-2v2zm-2-8v2h2V4h-2zM8 20h2v-2H8v2zm0-4h2v-2H8v2zm8 4h2v-2h-2v2zm-4 0h2v-2h-2v2zm-8 0h2v-2H4v2zm0-4h2v-2H4v2zM2 8h2V6H2v2zm0 4h2v-2H2v2zm8-12v2h2V0h-2zM8 4v2h2V4H8zm-4 0v2h2V4H4z"/> 204 </svg> 205 <span>Animationen stoppen</span> 206 </div> 207 <button class="accessibility-toggle" id="reduce-motion-toggle" role="switch" aria-checked="false"> 208 <span class="toggle-track"> 209 <span class="toggle-thumb"></span> 210 </span> 211 </button> 212 </div> 213 </div> 214 215 <div class="accessibility-footer"> 216 <p>Tastenkürzel: Alt + A (Widget öffnen), Esc (schlieÃen)</p> 217 </div> 218 `; 219 220 document.body.appendChild(widget); 221 } 222 223 // Toggle Widget 224 function toggleWidget(e) { 225 226 if (e) { 227 e.preventDefault(); 228 e.stopPropagation(); 229 } 230 231 const widget = document.getElementById('accessibility-widget'); 232 233 if (!widget) { 234 console.error('â Widget not found!'); 235 return; 236 } 237 238 if (widget.style.display === 'none') { 239 widget.style.display = 'block'; 240 // Don't focus immediately to prevent scroll 241 setTimeout(() => { 242 const firstButton = document.getElementById('font-size-decrease'); 243 if (firstButton) firstButton.focus({ preventScroll: true }); 244 }, 100); 245 } else { 246 widget.style.display = 'none'; 247 } 248 } 249 250 // Reset all settings 251 function resetSettings() { 252 state.fontSize = 100; 253 state.highContrast = false; 254 state.readingMode = false; 255 state.highlightLinks = false; 256 state.reduceMotion = false; 257 applySettings(); 258 saveSettings(); 259 } 260 261 // Event Listeners 262 function initEventListeners() { 263 264 // Open button in footer - EVENT DELEGATION (funktioniert auch nach AJAX-Navigation) 265 document.addEventListener('click', (e) => { 266 const target = e.target.closest('.footer-column .accessibility-toggle'); 267 if (target) { 268 e.preventDefault(); 269 e.stopPropagation(); 270 toggleWidget(e); 271 } 272 }, true); 273 274 // Widget buttons - EVENT DELEGATION 275 document.addEventListener('click', (e) => { 276 // Close button 277 if (e.target.closest('#accessibility-close')) { 278 e.preventDefault(); 279 toggleWidget(e); 280 return; 281 } 282 283 // Reset button 284 if (e.target.closest('#accessibility-reset')) { 285 e.preventDefault(); 286 resetSettings(); 287 return; 288 } 289 290 // Font size decrease 291 if (e.target.closest('#font-size-decrease')) { 292 e.preventDefault(); 293 changeFontSize(-10); 294 return; 295 } 296 297 // Font size increase 298 if (e.target.closest('#font-size-increase')) { 299 e.preventDefault(); 300 changeFontSize(10); 301 return; 302 } 303 304 // High contrast toggle 305 if (e.target.closest('#high-contrast-toggle')) { 306 e.preventDefault(); 307 state.highContrast = !state.highContrast; 308 applyHighContrast(); 309 saveSettings(); 310 return; 311 } 312 313 // Reading mode toggle 314 if (e.target.closest('#reading-mode-toggle')) { 315 e.preventDefault(); 316 state.readingMode = !state.readingMode; 317 applyReadingMode(); 318 saveSettings(); 319 return; 320 } 321 322 // Highlight links toggle 323 if (e.target.closest('#highlight-links-toggle')) { 324 e.preventDefault(); 325 state.highlightLinks = !state.highlightLinks; 326 applyLinkHighlight(); 327 saveSettings(); 328 return; 329 } 330 331 // Reduce motion toggle 332 if (e.target.closest('#reduce-motion-toggle')) { 333 e.preventDefault(); 334 state.reduceMotion = !state.reduceMotion; 335 applyReduceMotion(); 336 saveSettings(); 337 return; 338 } 339 }); 340 341 // Keyboard shortcut: Alt + A 342 document.addEventListener('keydown', (e) => { 343 if (e.altKey && e.key === 'a') { 344 e.preventDefault(); 345 e.stopPropagation(); 346 toggleWidget(e); 347 } 348 349 // Close with Escape 350 if (e.key === 'Escape') { 351 const widget = document.getElementById('accessibility-widget'); 352 if (widget && widget.style.display !== 'none') { 353 e.preventDefault(); 354 toggleWidget(e); 355 } 356 } 357 }); 358 359 // Close when clicking outside - EVENT DELEGATION 360 document.addEventListener('click', (e) => { 361 const widget = document.getElementById('accessibility-widget'); 362 const isOpenBtn = e.target.closest('.footer-column .accessibility-toggle'); 363 364 if (widget && widget.style.display !== 'none' && 365 !widget.contains(e.target) && 366 !isOpenBtn) { 367 toggleWidget(e); 368 } 369 }); 370 } 371 372 // Initialize
373 function init() { 374 375 // Prevent multiple initializations 376 if (isInitialized) { 377 return; 378 } 379 380 try { 381 createWidget(); 382 loadSettings(); 383 initEventListeners(); 384 isInitialized = true; 385 386 // Check if footer button exists 387 const footerBtn = document.querySelector('.footer-column .accessibility-toggle'); 388 } catch (error) { 389 console.error('â Error initializing Accessibility Widget:', error); 390 } 391 } 392 393 // Close widget on Swup navigation 394 document.addEventListener('swup:willReplaceContent', () => { 395 const widget = document.getElementById('accessibility-widget'); 396 if (widget) { 397 widget.style.display = 'none'; 398 } 399 }); 400 401 // Run on DOM ready 402 if (document.readyState === 'loading') { 403 document.addEventListener('DOMContentLoaded', init); 404 } else { 405 init(); 406 } 407 408})();
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.