Add consent reopener: floating widget + anchor link trigger

Allow visitors to reopen the cookie preferences modal after making
their choice via a configurable floating button (bottom-right or
right-side vertical) or any anchor link with href="#att-cc-preferences".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 06:13:55 +00:00
parent 6bf9f553de
commit 4adda0ded7
6 changed files with 174 additions and 48 deletions

View File

@@ -1,7 +1,8 @@
/**
* ATT Consent Banner UI
*
* Handles banner display, preferences modal, focus trapping, and user interactions.
* Handles banner display, preferences modal, floating widget, anchor link
* triggers, focus trapping, and user interactions.
* Depends on AttConsent (consent-manager.js) for consent state management.
*/
(function() {
@@ -9,43 +10,12 @@
var banner = document.getElementById('att-cc-banner');
var modal = document.getElementById('att-cc-modal');
var widget = document.getElementById('att-cc-widget');
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"]');
@@ -62,6 +32,7 @@
AttConsent.update(categories);
closeModal();
hideBanner();
showWidget();
});
}
@@ -77,6 +48,59 @@
});
}
// --- Floating widget click handler ---
if (widget) {
widget.addEventListener('click', function() {
openModal();
});
}
// --- Anchor link listener ---
document.addEventListener('click', function(e) {
var link = e.target.closest('a[href="#att-cc-preferences"]');
if (link) {
e.preventDefault();
openModal();
}
});
// --- Initial state ---
if (AttConsent.hasConsent()) {
hideBanner();
showWidget();
} else {
// --- Banner buttons (only needed for first-time visitors) ---
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();
showWidget();
});
}
if (rejectBtn) {
rejectBtn.addEventListener('click', function() {
AttConsent.update({ functional: false, analytics: false, marketing: false });
hideBanner();
showWidget();
});
}
if (prefsBtn) {
prefsBtn.addEventListener('click', function() {
openModal();
});
}
}
// --- Helper functions ---
function hideBanner() {
@@ -84,6 +108,12 @@
banner.classList.add('att-cc-hidden');
}
function showWidget() {
if (widget) {
widget.style.display = '';
}
}
function openModal() {
// Pre-fill checkboxes with existing consent if available.
var existing = AttConsent.getConsent();
@@ -104,9 +134,14 @@
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();
// Return focus to the widget if visible, otherwise the banner prefs button.
if (widget && widget.style.display !== 'none') {
widget.focus();
} else {
var prefsBtn = banner.querySelector('[data-att-cc="preferences"]');
if (prefsBtn) {
prefsBtn.focus();
}
}
}
@@ -162,13 +197,4 @@
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).
}
});
})();