/** * ATT Consent Banner UI * * Handles banner display, preferences modal, focus trapping, and user interactions. * Depends on AttConsent (consent-manager.js) for consent state management. */ (function() { 'use strict'; var banner = document.getElementById('att-cc-banner'); var modal = document.getElementById('att-cc-modal'); if (!banner || !modal) { return; } // If consent already exists, hide the banner immediately. if (AttConsent.hasConsent()) { hideBanner(); return; } // --- Banner buttons --- var acceptBtn = banner.querySelector('[data-att-cc="accept-all"]'); var rejectBtn = banner.querySelector('[data-att-cc="reject-all"]'); var prefsBtn = banner.querySelector('[data-att-cc="preferences"]'); if (acceptBtn) { acceptBtn.addEventListener('click', function() { AttConsent.update({ functional: true, analytics: true, marketing: true }); hideBanner(); }); } if (rejectBtn) { rejectBtn.addEventListener('click', function() { AttConsent.update({ functional: false, analytics: false, marketing: false }); hideBanner(); }); } if (prefsBtn) { prefsBtn.addEventListener('click', function() { openModal(); }); } // --- Modal buttons --- var saveBtn = modal.querySelector('[data-att-cc="save-preferences"]'); var closeBtn = modal.querySelector('[data-att-cc="close-modal"]'); var overlay = modal.querySelector('.att-cc-modal__overlay'); if (saveBtn) { saveBtn.addEventListener('click', function() { var categories = { functional: document.getElementById('att-cc-functional').checked, analytics: document.getElementById('att-cc-analytics').checked, marketing: document.getElementById('att-cc-marketing').checked }; AttConsent.update(categories); closeModal(); hideBanner(); }); } if (closeBtn) { closeBtn.addEventListener('click', function() { closeModal(); }); } if (overlay) { overlay.addEventListener('click', function() { closeModal(); }); } // --- Helper functions --- function hideBanner() { banner.setAttribute('aria-hidden', 'true'); banner.classList.add('att-cc-hidden'); } function openModal() { // Pre-fill checkboxes with existing consent if available. var existing = AttConsent.getConsent(); if (existing) { setCheckbox('att-cc-functional', existing.functional); setCheckbox('att-cc-analytics', existing.analytics); setCheckbox('att-cc-marketing', existing.marketing); } modal.setAttribute('aria-hidden', 'false'); modal.classList.add('att-cc-modal--open'); document.body.classList.add('att-cc-modal-active'); trapFocus(modal); } function closeModal() { modal.setAttribute('aria-hidden', 'true'); modal.classList.remove('att-cc-modal--open'); document.body.classList.remove('att-cc-modal-active'); // Return focus to the preferences button. if (prefsBtn) { prefsBtn.focus(); } } function setCheckbox(id, value) { var el = document.getElementById(id); if (el) { el.checked = !!value; } } /** * Trap keyboard focus within an element. * * @param {HTMLElement} element The container to trap focus in. */ function trapFocus(element) { var focusable = element.querySelectorAll( 'button, [href], input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])' ); if (focusable.length === 0) { return; } var first = focusable[0]; var last = focusable[focusable.length - 1]; first.focus(); function handleKeydown(e) { if (e.key === 'Escape') { closeModal(); element.removeEventListener('keydown', handleKeydown); return; } if (e.key !== 'Tab') { return; } if (e.shiftKey) { if (document.activeElement === first) { last.focus(); e.preventDefault(); } } else { if (document.activeElement === last) { first.focus(); e.preventDefault(); } } } element.addEventListener('keydown', handleKeydown); } // Listen for programmatic consent revocation to re-show banner. document.addEventListener('att_consent_update', function(e) { var cats = e.detail; if (!cats.functional && !cats.analytics && !cats.marketing) { // All denied - consent was effectively revoked, but don't re-show // banner immediately (user just clicked reject). } }); })();