From cbe50b1a2855e98d104e68b45c8aeba58c0edd72 Mon Sep 17 00:00:00 2001 From: Florian Zumpe Date: Sat, 29 Aug 2026 16:22:32 +0200 Subject: [PATCH] fix missing info dialog selectors --- public/js/legal-ui.js | 80 +++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 25 deletions(-) diff --git a/public/js/legal-ui.js b/public/js/legal-ui.js index 2459c7a..9c1939c 100644 --- a/public/js/legal-ui.js +++ b/public/js/legal-ui.js @@ -2,16 +2,26 @@ 'use strict'; const DROPDOWN_ANIMATION_MS = 180; - const dialog = document.getElementById('info-dialog'); - const title = document.getElementById('info-dialog-title'); - const dropdown = document.getElementById('info-dropdown'); - const closeButton = document.getElementById('info-close'); - const infoButton = document.getElementById('info-button'); const pageTitles = Object.freeze({ privacy: 'Datenschutzerklärung', imprint: 'Impressum', technology: 'Cookies und Technik' }); + + const dialog = document.getElementById('info-dialog'); + const title = document.getElementById('info-dialog-title') + ?? dialog?.querySelector('h1, h2, .info-dialog-title') + ?? null; + const dropdown = document.getElementById('info-dropdown') + ?? document.querySelector('.info-dropdown') + ?? null; + const infoButton = document.getElementById('info-button') + ?? document.querySelector('[aria-controls="info-dropdown"], .info-button') + ?? null; + const closeButton = document.getElementById('info-close') + ?? dialog?.querySelector('[data-info-close], .info-close, .info-dialog-close, button[aria-label="Dialog schließen"], button[aria-label="Schließen"]') + ?? null; + let dropdownOpen = false; let dropdownCloseTimer = null; @@ -23,7 +33,7 @@ } function activate(element, handler) { - if (!element) return; + if (!element || typeof element.addEventListener !== 'function') return; element.addEventListener('pointerup', event => { if (!isActivation(event)) return; event.preventDefault(); @@ -96,8 +106,18 @@ return elementContains(infoButton, target) || elementContains(dropdown, target); } + function isProgressStorageEnabled() { + if (!ns.PrivacyStorage || typeof ns.PrivacyStorage.isProgressStorageEnabled !== 'function') return false; + return ns.PrivacyStorage.isProgressStorageEnabled(); + } + + function setProgressStorageEnabled(enabled) { + if (!ns.PrivacyStorage || typeof ns.PrivacyStorage.setProgressStorageEnabled !== 'function') return false; + return ns.PrivacyStorage.setProgressStorageEnabled(enabled); + } + function syncStorageToggles() { - const enabled = ns.PrivacyStorage.isProgressStorageEnabled(); + const enabled = isProgressStorageEnabled(); document.querySelectorAll('.progress-storage-toggle').forEach(toggle => { toggle.checked = enabled; }); @@ -110,7 +130,7 @@ const page = document.querySelector(`[data-info-page="${name}"]`); if (!page) return; - title.textContent = pageTitles[name] ?? 'Informationen'; + if (title) title.textContent = pageTitles[name] ?? 'Informationen'; document.querySelectorAll('[data-info-page]').forEach(item => { item.hidden = item !== page; }); @@ -118,7 +138,13 @@ if (content) content.scrollTop = 0; } + function focusSafely(element) { + if (!element || typeof element.focus !== 'function') return; + element.focus({ preventScroll: true }); + } + function openDialog(name = 'privacy') { + if (!dialog) return; const pageName = Object.prototype.hasOwnProperty.call(pageTitles, name) ? name : 'privacy'; setDropdownOpen(false); showPage(pageName); @@ -127,20 +153,22 @@ if (typeof dialog.showModal === 'function') dialog.showModal(); else dialog.setAttribute('open', ''); } - closeButton.focus(); + focusSafely(closeButton ?? dialog); } function closeDialog() { - if (typeof dialog.close === 'function') dialog.close(); - else dialog.removeAttribute('open'); + if (dialog) { + if (typeof dialog.close === 'function') dialog.close(); + else dialog.removeAttribute('open'); + } setDropdownOpen(false); - infoButton.focus(); + focusSafely(infoButton); } function bindStorageToggles() { document.querySelectorAll('.progress-storage-toggle').forEach(toggle => { toggle.addEventListener('change', event => { - const enabled = ns.PrivacyStorage.setProgressStorageEnabled(event.currentTarget.checked); + const enabled = setProgressStorageEnabled(event.currentTarget.checked); syncStorageToggles(); document.dispatchEvent(new CustomEvent('wegwichtel:progress-storage-changed', { detail: { enabled } @@ -160,22 +188,24 @@ setDropdownOpen(false); }); document.addEventListener('keydown', event => { - if (!dropdownOpen || event.key !== 'Escape' || dialog.open) return; + if (!dropdownOpen || event.key !== 'Escape' || dialog?.open) return; event.preventDefault(); setDropdownOpen(false); - infoButton.focus(); + focusSafely(infoButton); }); - dialog.addEventListener('pointerup', event => { - if (event.target !== dialog || !isActivation(event)) return; - event.preventDefault(); - event.stopPropagation(); - closeDialog(); - }); - dialog.addEventListener('cancel', event => { - event.preventDefault(); - closeDialog(); - }); + if (dialog) { + dialog.addEventListener('pointerup', event => { + if (event.target !== dialog || !isActivation(event)) return; + event.preventDefault(); + event.stopPropagation(); + closeDialog(); + }); + dialog.addEventListener('cancel', event => { + event.preventDefault(); + closeDialog(); + }); + } bindStorageToggles(); syncStorageToggles();