191 lines
5.7 KiB
JavaScript
191 lines
5.7 KiB
JavaScript
(function (ns) {
|
|
'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'
|
|
});
|
|
let dropdownOpen = false;
|
|
let dropdownCloseTimer = null;
|
|
|
|
function isActivation(event) {
|
|
if (event.type === 'keydown') return event.key === 'Enter' || event.key === ' ';
|
|
if (event.type !== 'pointerup') return false;
|
|
if (event.isPrimary === false) return false;
|
|
return event.pointerType !== 'mouse' || event.button === 0;
|
|
}
|
|
|
|
function activate(element, handler) {
|
|
if (!element) return;
|
|
element.addEventListener('pointerup', event => {
|
|
if (!isActivation(event)) return;
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
handler(event);
|
|
});
|
|
element.addEventListener('keydown', event => {
|
|
if (!isActivation(event)) return;
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
handler(event);
|
|
});
|
|
}
|
|
|
|
function setClass(element, className, enabled) {
|
|
if (!element || !element.classList) return;
|
|
element.classList.toggle(className, enabled);
|
|
}
|
|
|
|
function runNextFrame(callback) {
|
|
if (typeof globalThis.requestAnimationFrame === 'function') {
|
|
globalThis.requestAnimationFrame(callback);
|
|
return;
|
|
}
|
|
callback();
|
|
}
|
|
|
|
function schedule(callback, timeout) {
|
|
if (typeof globalThis.setTimeout === 'function') return globalThis.setTimeout(callback, timeout);
|
|
callback();
|
|
return null;
|
|
}
|
|
|
|
function cancelSchedule(timer) {
|
|
if (timer === null || typeof globalThis.clearTimeout !== 'function') return;
|
|
globalThis.clearTimeout(timer);
|
|
}
|
|
|
|
function setDropdownOpen(open) {
|
|
if (!dropdown || !infoButton) return;
|
|
dropdownOpen = open;
|
|
infoButton.setAttribute('aria-expanded', open ? 'true' : 'false');
|
|
cancelSchedule(dropdownCloseTimer);
|
|
dropdownCloseTimer = null;
|
|
|
|
if (open) {
|
|
dropdown.hidden = false;
|
|
runNextFrame(() => setClass(dropdown, 'is-open', true));
|
|
return;
|
|
}
|
|
|
|
setClass(dropdown, 'is-open', false);
|
|
dropdownCloseTimer = schedule(() => {
|
|
if (dropdownOpen) return;
|
|
dropdown.hidden = true;
|
|
}, DROPDOWN_ANIMATION_MS);
|
|
}
|
|
|
|
function toggleDropdown() {
|
|
setDropdownOpen(!dropdownOpen);
|
|
}
|
|
|
|
function elementContains(element, target) {
|
|
if (!element || !target) return false;
|
|
if (element === target) return true;
|
|
return typeof element.contains === 'function' && element.contains(target);
|
|
}
|
|
|
|
function isInsideInfoControl(target) {
|
|
return elementContains(infoButton, target) || elementContains(dropdown, target);
|
|
}
|
|
|
|
function syncStorageToggles() {
|
|
const enabled = ns.PrivacyStorage.isProgressStorageEnabled();
|
|
document.querySelectorAll('.progress-storage-toggle').forEach(toggle => {
|
|
toggle.checked = enabled;
|
|
});
|
|
document.querySelectorAll('.cookie-toggle').forEach(toggle => {
|
|
toggle.checked = false;
|
|
});
|
|
}
|
|
|
|
function showPage(name) {
|
|
const page = document.querySelector(`[data-info-page="${name}"]`);
|
|
if (!page) return;
|
|
|
|
title.textContent = pageTitles[name] ?? 'Informationen';
|
|
document.querySelectorAll('[data-info-page]').forEach(item => {
|
|
item.hidden = item !== page;
|
|
});
|
|
const content = document.querySelector('.info-dialog-content');
|
|
if (content) content.scrollTop = 0;
|
|
}
|
|
|
|
function openDialog(name = 'privacy') {
|
|
const pageName = Object.prototype.hasOwnProperty.call(pageTitles, name) ? name : 'privacy';
|
|
setDropdownOpen(false);
|
|
showPage(pageName);
|
|
syncStorageToggles();
|
|
if (!dialog.open) {
|
|
if (typeof dialog.showModal === 'function') dialog.showModal();
|
|
else dialog.setAttribute('open', '');
|
|
}
|
|
closeButton.focus();
|
|
}
|
|
|
|
function closeDialog() {
|
|
if (typeof dialog.close === 'function') dialog.close();
|
|
else dialog.removeAttribute('open');
|
|
setDropdownOpen(false);
|
|
infoButton.focus();
|
|
}
|
|
|
|
function bindStorageToggles() {
|
|
document.querySelectorAll('.progress-storage-toggle').forEach(toggle => {
|
|
toggle.addEventListener('change', event => {
|
|
const enabled = ns.PrivacyStorage.setProgressStorageEnabled(event.currentTarget.checked);
|
|
syncStorageToggles();
|
|
document.dispatchEvent(new CustomEvent('wegwichtel:progress-storage-changed', {
|
|
detail: { enabled }
|
|
}));
|
|
});
|
|
});
|
|
}
|
|
|
|
activate(infoButton, toggleDropdown);
|
|
activate(closeButton, closeDialog);
|
|
document.querySelectorAll('[data-info-target]').forEach(button => {
|
|
activate(button, () => openDialog(button.dataset.infoTarget));
|
|
});
|
|
|
|
document.addEventListener('pointerup', event => {
|
|
if (!dropdownOpen || isInsideInfoControl(event.target)) return;
|
|
setDropdownOpen(false);
|
|
});
|
|
document.addEventListener('keydown', event => {
|
|
if (!dropdownOpen || event.key !== 'Escape' || dialog.open) return;
|
|
event.preventDefault();
|
|
setDropdownOpen(false);
|
|
infoButton.focus();
|
|
});
|
|
|
|
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();
|
|
|
|
ns.LegalUi = Object.freeze({
|
|
open: openDialog,
|
|
close: closeDialog,
|
|
toggleMenu: toggleDropdown,
|
|
closeMenu: () => setDropdownOpen(false),
|
|
syncStorageToggles
|
|
});
|
|
}(globalThis.Wegwichtel ??= {}));
|