I’ll build this as a standalone advanced cookie-notice chunk for RX Theme: privacy-safe defaults, accessibility, consent categories, Google Consent Mode hooks, localStorage/cookie fallback, and reusable public API.
My dear friend, create this file:
assets/static-js/static-chunks-js/chunk-025-cookie-notice.js
Then paste this full advanced code inside it.
/*!
* RX Theme - Advanced Cookie Notice Chunk
* File: assets/static-js/static-chunks-js/chunk-025-cookie-notice.js
* Version: 1.0.0
*
* Features:
* - Lightweight vanilla JavaScript
* - GDPR-style consent banner
* - Accept all / reject all / save preferences
* - Consent categories: necessary, analytics, marketing, preferences
* - LocalStorage + cookie fallback
* - Google Consent Mode compatible dataLayer push
* - Accessibility friendly modal
* - Keyboard support
* - Public API: window.RXCookieNotice
*/
(function () {
'use strict';
/**
* Prevent double loading
*/
if (window.RXCookieNotice && window.RXCookieNotice.__loaded) {
return;
}
/**
* Main configuration
*/
var RX_COOKIE_CONFIG = {
storageKey: 'rx_theme_cookie_consent',
cookieName: 'rx_theme_cookie_consent',
version: '1.0.0',
expireDays: 180,
showDelay: 600,
bannerPosition: 'bottom', // bottom, top, center
autoBlock: false,
siteName: document.title || 'RX Theme',
categories: {
necessary: {
label: 'Necessary cookies',
description:
'These cookies are required for basic website functions such as security, page navigation, form protection, login state, and accessibility.',
required: true,
defaultValue: true
},
preferences: {
label: 'Preference cookies',
description:
'These cookies remember choices such as theme mode, language, layout, font size, and other display preferences.',
required: false,
defaultValue: false
},
analytics: {
label: 'Analytics cookies',
description:
'These cookies help us understand how visitors use the website, which pages are helpful, and how we can improve speed and content quality.',
required: false,
defaultValue: false
},
marketing: {
label: 'Marketing cookies',
description:
'These cookies may be used to measure campaigns, personalize content, or support third-party advertising tools.',
required: false,
defaultValue: false
}
},
text: {
title: 'Cookie preferences',
message:
'We use cookies to improve your browsing experience, measure website performance, and provide useful content. You can accept all cookies, reject optional cookies, or choose your preferences.',
acceptAll: 'Accept all',
rejectAll: 'Reject optional',
customize: 'Customize',
save: 'Save preferences',
close: 'Close',
back: 'Back',
privacyPolicy: 'Privacy Policy',
manageButton: 'Cookie settings'
},
links: {
privacyPolicyUrl: '/privacy-policy/'
},
classNames: {
root: 'rx-cookie-notice',
overlay: 'rx-cookie-overlay',
banner: 'rx-cookie-banner',
modal: 'rx-cookie-modal',
hidden: 'rx-cookie-hidden',
manageButton: 'rx-cookie-manage-button'
},
debug: false
};
/**
* Utility helpers
*/
var RXCookieUtils = {
log: function () {
if (!RX_COOKIE_CONFIG.debug) return;
if (window.console && typeof window.console.log === 'function') {
console.log.apply(console, ['[RX Cookie Notice]'].concat([].slice.call(arguments)));
}
},
now: function () {
return new Date().toISOString();
},
safeJsonParse: function (value) {
try {
return JSON.parse(value);
} catch (error) {
return null;
}
},
safeJsonStringify: function (value) {
try {
return JSON.stringify(value);
} catch (error) {
return '';
}
},
escapeHtml: function (value) {
return String(value || '')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
},
hasLocalStorage: function () {
try {
var key = '__rx_cookie_test__';
window.localStorage.setItem(key, key);
window.localStorage.removeItem(key);
return true;
} catch (error) {
return false;
}
},
setCookie: function (name, value, days) {
var expires = '';
var secure = window.location.protocol === 'https:' ? '; Secure' : '';
if (days) {
var date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
expires = '; expires=' + date.toUTCString();
}
document.cookie =
encodeURIComponent(name) +
'=' +
encodeURIComponent(value) +
expires +
'; path=/; SameSite=Lax' +
secure;
},
getCookie: function (name) {
var nameEQ = encodeURIComponent(name) + '=';
var cookies = document.cookie ? document.cookie.split(';') : [];
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i];
while (cookie.charAt(0) === ' ') {
cookie = cookie.substring(1);
}
if (cookie.indexOf(nameEQ) === 0) {
return decodeURIComponent(cookie.substring(nameEQ.length));
}
}
return null;
},
removeCookie: function (name) {
document.cookie =
encodeURIComponent(name) +
'=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; SameSite=Lax';
},
dispatch: function (eventName, detail) {
var event;
try {
event = new CustomEvent(eventName, {
detail: detail || {},
bubbles: true
});
} catch (error) {
event = document.createEvent('CustomEvent');
event.initCustomEvent(eventName, true, true, detail || {});
}
document.dispatchEvent(event);
},
focusFirst: function (container) {
if (!container) return;
var focusable = container.querySelector(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
if (focusable) {
focusable.focus();
}
},
trapFocus: function (container, event) {
if (!container || event.key !== 'Tab') return;
var focusable = container.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
if (!focusable.length) return;
var first = focusable[0];
var last = focusable[focusable.length - 1];
if (event.shiftKey && document.activeElement === first) {
event.preventDefault();
last.focus();
} else if (!event.shiftKey && document.activeElement === last) {
event.preventDefault();
first.focus();
}
}
};
/**
* Storage layer
*/
var RXCookieStorage = {
get: function () {
var raw = null;
if (RXCookieUtils.hasLocalStorage()) {
raw = window.localStorage.getItem(RX_COOKIE_CONFIG.storageKey);
}
if (!raw) {
raw = RXCookieUtils.getCookie(RX_COOKIE_CONFIG.cookieName);
}
if (!raw) return null;
var parsed = RXCookieUtils.safeJsonParse(raw);
if (!parsed || !parsed.categories) {
return null;
}
return parsed;
},
set: function (data) {
var value = RXCookieUtils.safeJsonStringify(data);
if (!value) return false;
if (RXCookieUtils.hasLocalStorage()) {
window.localStorage.setItem(RX_COOKIE_CONFIG.storageKey, value);
}
RXCookieUtils.setCookie(
RX_COOKIE_CONFIG.cookieName,
value,
RX_COOKIE_CONFIG.expireDays
);
return true;
},
clear: function () {
if (RXCookieUtils.hasLocalStorage()) {
window.localStorage.removeItem(RX_COOKIE_CONFIG.storageKey);
}
RXCookieUtils.removeCookie(RX_COOKIE_CONFIG.cookieName);
}
};
/**
* Consent logic
*/
var RXConsent = {
getDefaultCategories: function () {
var result = {};
var categories = RX_COOKIE_CONFIG.categories;
Object.keys(categories).forEach(function (key) {
result[key] = !!categories[key].defaultValue;
});
return result;
},
getAllAcceptedCategories: function () {
var result = {};
var categories = RX_COOKIE_CONFIG.categories;
Object.keys(categories).forEach(function (key) {
result[key] = true;
});
return result;
},
getOnlyRequiredCategories: function () {
var result = {};
var categories = RX_COOKIE_CONFIG.categories;
Object.keys(categories).forEach(function (key) {
result[key] = !!categories[key].required;
});
return result;
},
normalizeCategories: function (input) {
var result = {};
var categories = RX_COOKIE_CONFIG.categories;
Object.keys(categories).forEach(function (key) {
if (categories[key].required) {
result[key] = true;
} else {
result[key] = !!input[key];
}
});
return result;
},
createConsentObject: function (categories, source) {
return {
version: RX_COOKIE_CONFIG.version,
siteName: RX_COOKIE_CONFIG.siteName,
source: source || 'unknown',
categories: RXConsent.normalizeCategories(categories || {}),
createdAt: RXCookieUtils.now(),
updatedAt: RXCookieUtils.now()
};
},
isExpiredOrOutdated: function (consent) {
if (!consent) return true;
if (consent.version !== RX_COOKIE_CONFIG.version) return true;
if (!consent.createdAt) return false;
var created = new Date(consent.createdAt).getTime();
var now = Date.now();
var maxAge = RX_COOKIE_CONFIG.expireDays * 24 * 60 * 60 * 1000;
return now - created > maxAge;
},
hasConsent: function () {
var consent = RXCookieStorage.get();
return !!consent && !RXConsent.isExpiredOrOutdated(consent);
},
getConsent: function () {
var consent = RXCookieStorage.get();
if (!consent || RXConsent.isExpiredOrOutdated(consent)) {
return null;
}
return consent;
},
saveConsent: function (categories, source) {
var existing = RXCookieStorage.get();
var consent = RXConsent.createConsentObject(categories, source);
if (existing && existing.createdAt) {
consent.createdAt = existing.createdAt;
}
consent.updatedAt = RXCookieUtils.now();
RXCookieStorage.set(consent);
RXConsent.applyConsent(consent);
RXCookieUtils.dispatch('rxCookieConsentUpdated', consent);
return consent;
},
acceptAll: function () {
return RXConsent.saveConsent(
RXConsent.getAllAcceptedCategories(),
'accept_all'
);
},
rejectAll: function () {
return RXConsent.saveConsent(
RXConsent.getOnlyRequiredCategories(),
'reject_all'
);
},
reset: function () {
RXCookieStorage.clear();
RXCookieUtils.dispatch('rxCookieConsentReset', {});
},
isAllowed: function (category) {
var consent = RXConsent.getConsent();
if (!consent || !consent.categories) {
return !!RX_COOKIE_CONFIG.categories[category]?.required;
}
return !!consent.categories[category];
},
applyConsent: function (consent) {
if (!consent || !consent.categories) return;
RXConsent.updateHtmlAttributes(consent);
RXConsent.pushDataLayer(consent);
RXConsent.runAllowedScripts(consent);
},
updateHtmlAttributes: function (consent) {
var root = document.documentElement;
root.setAttribute('data-rx-cookie-consent', 'set');
Object.keys(consent.categories).forEach(function (key) {
root.setAttribute(
'data-rx-consent-' + key,
consent.categories[key] ? 'yes' : 'no'
);
});
},
pushDataLayer: function (consent) {
window.dataLayer = window.dataLayer || [];
var analyticsGranted = consent.categories.analytics ? 'granted' : 'denied';
var marketingGranted = consent.categories.marketing ? 'granted' : 'denied';
var preferencesGranted = consent.categories.preferences ? 'granted' : 'denied';
window.dataLayer.push({
event: 'rx_cookie_consent_update',
rx_cookie_consent: consent.categories
});
window.dataLayer.push({
event: 'default_consent',
ad_storage: marketingGranted,
ad_user_data: marketingGranted,
ad_personalization: marketingGranted,
analytics_storage: analyticsGranted,
functionality_storage: preferencesGranted,
personalization_storage: preferencesGranted,
security_storage: 'granted'
});
if (typeof window.gtag === 'function') {
window.gtag('consent', 'update', {
ad_storage: marketingGranted,
ad_user_data: marketingGranted,
ad_personalization: marketingGranted,
analytics_storage: analyticsGranted,
functionality_storage: preferencesGranted,
personalization_storage: preferencesGranted,
security_storage: 'granted'
});
}
},
runAllowedScripts: function (consent) {
var scripts = document.querySelectorAll('script[type="text/plain"][data-rx-cookie-category]');
scripts.forEach(function (script) {
var category = script.getAttribute('data-rx-cookie-category');
if (!category || !consent.categories[category]) {
return;
}
if (script.getAttribute('data-rx-cookie-loaded') === '1') {
return;
}
var newScript = document.createElement('script');
Array.prototype.slice.call(script.attributes).forEach(function (attr) {
if (
attr.name !== 'type' &&
attr.name !== 'data-rx-cookie-category' &&
attr.name !== 'data-rx-cookie-loaded'
) {
newScript.setAttribute(attr.name, attr.value);
}
});
if (script.src) {
newScript.src = script.src;
} else {
newScript.text = script.text || script.textContent || script.innerHTML || '';
}
script.setAttribute('data-rx-cookie-loaded', '1');
script.parentNode.insertBefore(newScript, script.nextSibling);
});
}
};
/**
* UI manager
*/
var RXCookieUI = {
root: null,
banner: null,
modal: null,
overlay: null,
lastFocusedElement: null,
init: function () {
RXCookieUI.injectStyles();
RXCookieUI.createManageButton();
if (!RXConsent.hasConsent()) {
window.setTimeout(function () {
RXCookieUI.showBanner();
}, RX_COOKIE_CONFIG.showDelay);
} else {
RXConsent.applyConsent(RXConsent.getConsent());
}
RXCookieUI.bindGlobalEvents();
},
injectStyles: function () {
if (document.getElementById('rx-cookie-notice-style')) {
return;
}
var css = `
.rx-cookie-hidden {
display: none !important;
}
.rx-cookie-notice,
.rx-cookie-notice *,
.rx-cookie-overlay,
.rx-cookie-overlay * {
box-sizing: border-box;
}
.rx-cookie-banner {
position: fixed;
left: 16px;
right: 16px;
bottom: 16px;
z-index: 999999;
max-width: 1120px;
margin: 0 auto;
padding: 20px;
border-radius: 18px;
background: #ffffff;
color: #172033;
box-shadow: 0 20px 60px rgba(15, 23, 42, 0.24);
border: 1px solid rgba(15, 23, 42, 0.10);
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.rx-cookie-banner[data-position="top"] {
top: 16px;
bottom: auto;
}
.rx-cookie-banner[data-position="center"] {
top: 50%;
bottom: auto;
transform: translateY(-50%);
max-width: 720px;
}
.rx-cookie-banner__inner {
display: grid;
grid-template-columns: 1fr auto;
gap: 20px;
align-items: center;
}
.rx-cookie-banner__title {
margin: 0 0 8px;
font-size: 18px;
line-height: 1.3;
font-weight: 700;
}
.rx-cookie-banner__message {
margin: 0;
font-size: 14px;
line-height: 1.7;
color: #475569;
}
.rx-cookie-banner__link {
color: #075985;
text-decoration: underline;
text-underline-offset: 3px;
}
.rx-cookie-actions {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: flex-end;
}
.rx-cookie-btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 42px;
padding: 10px 16px;
border-radius: 999px;
border: 1px solid transparent;
background: #f1f5f9;
color: #0f172a;
font-size: 14px;
font-weight: 700;
line-height: 1.2;
cursor: pointer;
transition: transform 160ms ease, box-shadow 160ms ease, background 160ms ease;
}
.rx-cookie-btn:hover {
transform: translateY(-1px);
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.15);
}
.rx-cookie-btn:focus {
outline: 3px solid rgba(14, 165, 233, 0.35);
outline-offset: 2px;
}
.rx-cookie-btn--primary {
background: #0f766e;
color: #ffffff;
}
.rx-cookie-btn--dark {
background: #0f172a;
color: #ffffff;
}
.rx-cookie-btn--ghost {
background: transparent;
color: #334155;
border-color: rgba(15, 23, 42, 0.15);
}
.rx-cookie-overlay {
position: fixed;
inset: 0;
z-index: 1000000;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
background: rgba(15, 23, 42, 0.58);
backdrop-filter: blur(6px);
}
.rx-cookie-modal {
width: min(720px, 100%);
max-height: min(760px, 90vh);
overflow: auto;
border-radius: 22px;
background: #ffffff;
color: #172033;
box-shadow: 0 30px 90px rgba(0, 0, 0, 0.35);
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.rx-cookie-modal__header {
display: flex;
justify-content: space-between;
gap: 16px;
align-items: flex-start;
padding: 24px 24px 12px;
border-bottom: 1px solid rgba(15, 23, 42, 0.08);
}
.rx-cookie-modal__title {
margin: 0;
font-size: 22px;
line-height: 1.3;
}
.rx-cookie-modal__desc {
margin: 10px 0 0;
color: #475569;
font-size: 14px;
line-height: 1.7;
}
.rx-cookie-modal__close {
width: 40px;
height: 40px;
border-radius: 999px;
border: 1px solid rgba(15, 23, 42, 0.12);
background: #f8fafc;
color: #0f172a;
cursor: pointer;
font-size: 20px;
line-height: 1;
}
.rx-cookie-modal__body {
padding: 18px 24px;
}
.rx-cookie-category {
display: grid;
grid-template-columns: 1fr auto;
gap: 16px;
padding: 16px 0;
border-bottom: 1px solid rgba(15, 23, 42, 0.08);
}
.rx-cookie-category:last-child {
border-bottom: 0;
}
.rx-cookie-category__title {
margin: 0 0 6px;
font-size: 16px;
line-height: 1.4;
font-weight: 700;
}
.rx-cookie-category__desc {
margin: 0;
color: #64748b;
font-size: 14px;
line-height: 1.7;
}
.rx-cookie-switch {
position: relative;
display: inline-flex;
width: 54px;
height: 30px;
flex: 0 0 auto;
}
.rx-cookie-switch input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.rx-cookie-slider {
position: absolute;
inset: 0;
cursor: pointer;
border-radius: 999px;
background: #cbd5e1;
transition: background 160ms ease;
}
.rx-cookie-slider::before {
content: "";
position: absolute;
width: 24px;
height: 24px;
left: 3px;
top: 3px;
border-radius: 50%;
background: #ffffff;
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.25);
transition: transform 160ms ease;
}
.rx-cookie-switch input:checked + .rx-cookie-slider {
background: #0f766e;
}
.rx-cookie-switch input:checked + .rx-cookie-slider::before {
transform: translateX(24px);
}
.rx-cookie-switch input:disabled + .rx-cookie-slider {
cursor: not-allowed;
opacity: 0.7;
}
.rx-cookie-modal__footer {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 10px;
padding: 18px 24px 24px;
border-top: 1px solid rgba(15, 23, 42, 0.08);
}
.rx-cookie-manage-button {
position: fixed;
left: 16px;
bottom: 16px;
z-index: 999998;
width: 46px;
height: 46px;
border-radius: 999px;
border: 1px solid rgba(15, 23, 42, 0.12);
background: #ffffff;
color: #0f172a;
box-shadow: 0 10px 28px rgba(15, 23, 42, 0.18);
cursor: pointer;
font-size: 20px;
display: none;
align-items: center;
justify-content: center;
}
.rx-cookie-manage-button.is-visible {
display: inline-flex;
}
@media (max-width: 768px) {
.rx-cookie-banner {
left: 10px;
right: 10px;
bottom: 10px;
padding: 16px;
border-radius: 16px;
}
.rx-cookie-banner__inner {
grid-template-columns: 1fr;
}
.rx-cookie-actions {
justify-content: stretch;
}
.rx-cookie-btn {
width: 100%;
}
.rx-cookie-category {
grid-template-columns: 1fr;
}
.rx-cookie-modal__footer {
justify-content: stretch;
}
}
@media (prefers-color-scheme: dark) {
.rx-cookie-banner,
.rx-cookie-modal,
.rx-cookie-manage-button {
background: #0f172a;
color: #f8fafc;
border-color: rgba(255, 255, 255, 0.12);
}
.rx-cookie-banner__message,
.rx-cookie-modal__desc,
.rx-cookie-category__desc {
color: #cbd5e1;
}
.rx-cookie-btn--ghost {
color: #f8fafc;
border-color: rgba(255, 255, 255, 0.18);
}
.rx-cookie-modal__close {
background: #1e293b;
color: #f8fafc;
border-color: rgba(255, 255, 255, 0.14);
}
.rx-cookie-modal__header,
.rx-cookie-modal__footer,
.rx-cookie-category {
border-color: rgba(255, 255, 255, 0.10);
}
}
`;
var style = document.createElement('style');
style.id = 'rx-cookie-notice-style';
style.textContent = css;
document.head.appendChild(style);
},
createBanner: function () {
if (RXCookieUI.banner) return RXCookieUI.banner;
var config = RX_COOKIE_CONFIG;
var privacyLink = '';
if (config.links.privacyPolicyUrl) {
privacyLink =
' <a class="rx-cookie-banner__link" href="' +
RXCookieUtils.escapeHtml(config.links.privacyPolicyUrl) +
'">' +
RXCookieUtils.escapeHtml(config.text.privacyPolicy) +
'</a>';
}
var banner = document.createElement('div');
banner.className = config.classNames.banner;
banner.setAttribute('role', 'region');
banner.setAttribute('aria-label', 'Cookie notice');
banner.setAttribute('data-position', config.bannerPosition);
banner.innerHTML =
'<div class="rx-cookie-banner__inner">' +
'<div class="rx-cookie-banner__content">' +
'<h2 class="rx-cookie-banner__title">' +
RXCookieUtils.escapeHtml(config.text.title) +
'</h2>' +
'<p class="rx-cookie-banner__message">' +
RXCookieUtils.escapeHtml(config.text.message) +
privacyLink +
'</p>' +
'</div>' +
'<div class="rx-cookie-actions">' +
'<button type="button" class="rx-cookie-btn rx-cookie-btn--ghost" data-rx-cookie-action="customize">' +
RXCookieUtils.escapeHtml(config.text.customize) +
'</button>' +
'<button type="button" class="rx-cookie-btn" data-rx-cookie-action="reject">' +
RXCookieUtils.escapeHtml(config.text.rejectAll) +
'</button>' +
'<button type="button" class="rx-cookie-btn rx-cookie-btn--primary" data-rx-cookie-action="accept">' +
RXCookieUtils.escapeHtml(config.text.acceptAll) +
'</button>' +
'</div>' +
'</div>';
document.body.appendChild(banner);
RXCookieUI.banner = banner;
banner.addEventListener('click', RXCookieUI.handleBannerClick);
return banner;
},
showBanner: function () {
var banner = RXCookieUI.createBanner();
banner.classList.remove(RX_COOKIE_CONFIG.classNames.hidden);
},
hideBanner: function () {
if (RXCookieUI.banner) {
RXCookieUI.banner.classList.add(RX_COOKIE_CONFIG.classNames.hidden);
}
RXCookieUI.showManageButton();
},
handleBannerClick: function (event) {
var button = event.target.closest('[data-rx-cookie-action]');
if (!button) return;
var action = button.getAttribute('data-rx-cookie-action');
if (action === 'accept') {
RXConsent.acceptAll();
RXCookieUI.hideBanner();
}
if (action === 'reject') {
RXConsent.rejectAll();
RXCookieUI.hideBanner();
}
if (action === 'customize') {
RXCookieUI.openModal();
}
},
createModal: function () {
var config = RX_COOKIE_CONFIG;
if (RXCookieUI.overlay) return RXCookieUI.overlay;
var overlay = document.createElement('div');
overlay.className = config.classNames.overlay + ' ' + config.classNames.hidden;
overlay.setAttribute('role', 'presentation');
var modal = document.createElement('div');
modal.className = config.classNames.modal;
modal.setAttribute('role', 'dialog');
modal.setAttribute('aria-modal', 'true');
modal.setAttribute('aria-labelledby', 'rx-cookie-modal-title');
var currentConsent = RXConsent.getConsent();
var activeCategories = currentConsent
? currentConsent.categories
: RXConsent.getDefaultCategories();
var categoriesHtml = Object.keys(config.categories)
.map(function (key) {
var item = config.categories[key];
var checked = activeCategories[key] ? 'checked' : '';
var disabled = item.required ? 'disabled' : '';
var requiredText = item.required ? ' Required' : '';
return (
'<div class="rx-cookie-category">' +
'<div>' +
'<h3 class="rx-cookie-category__title">' +
RXCookieUtils.escapeHtml(item.label) +
'</h3>' +
'<p class="rx-cookie-category__desc">' +
RXCookieUtils.escapeHtml(item.description + requiredText) +
'</p>' +
'</div>' +
'<label class="rx-cookie-switch" aria-label="' +
RXCookieUtils.escapeHtml(item.label) +
'">' +
'<input type="checkbox" data-rx-cookie-category-input="' +
RXCookieUtils.escapeHtml(key) +
'" ' +
checked +
' ' +
disabled +
'>' +
'<span class="rx-cookie-slider"></span>' +
'</label>' +
'</div>'
);
})
.join('');
modal.innerHTML =
'<div class="rx-cookie-modal__header">' +
'<div>' +
'<h2 class="rx-cookie-modal__title" id="rx-cookie-modal-title">' +
RXCookieUtils.escapeHtml(config.text.title) +
'</h2>' +
'<p class="rx-cookie-modal__desc">' +
RXCookieUtils.escapeHtml(config.text.message) +
'</p>' +
'</div>' +
'<button type="button" class="rx-cookie-modal__close" data-rx-cookie-modal-close aria-label="' +
RXCookieUtils.escapeHtml(config.text.close) +
'">×</button>' +
'</div>' +
'<div class="rx-cookie-modal__body">' +
categoriesHtml +
'</div>' +
'<div class="rx-cookie-modal__footer">' +
'<button type="button" class="rx-cookie-btn rx-cookie-btn--ghost" data-rx-cookie-modal-action="reject">' +
RXCookieUtils.escapeHtml(config.text.rejectAll) +
'</button>' +
'<button type="button" class="rx-cookie-btn rx-cookie-btn--dark" data-rx-cookie-modal-action="save">' +
RXCookieUtils.escapeHtml(config.text.save) +
'</button>' +
'<button type="button" class="rx-cookie-btn rx-cookie-btn--primary" data-rx-cookie-modal-action="accept">' +
RXCookieUtils.escapeHtml(config.text.acceptAll) +
'</button>' +
'</div>';
overlay.appendChild(modal);
document.body.appendChild(overlay);
RXCookieUI.overlay = overlay;
RXCookieUI.modal = modal;
overlay.addEventListener('click', RXCookieUI.handleModalClick);
document.addEventListener('keydown', RXCookieUI.handleKeydown);
return overlay;
},
openModal: function () {
var overlay = RXCookieUI.createModal();
RXCookieUI.lastFocusedElement = document.activeElement;
RXCookieUI.syncModalInputs();
overlay.classList.remove(RX_COOKIE_CONFIG.classNames.hidden);
document.documentElement.style.overflow = 'hidden';
window.setTimeout(function () {
RXCookieUtils.focusFirst(RXCookieUI.modal);
}, 30);
},
closeModal: function () {
if (RXCookieUI.overlay) {
RXCookieUI.overlay.classList.add(RX_COOKIE_CONFIG.classNames.hidden);
}
document.documentElement.style.overflow = '';
if (
RXCookieUI.lastFocusedElement &&
typeof RXCookieUI.lastFocusedElement.focus === 'function'
) {
RXCookieUI.lastFocusedElement.focus();
}
},
syncModalInputs: function () {
if (!RXCookieUI.modal) return;
var currentConsent = RXConsent.getConsent();
var activeCategories = currentConsent
? currentConsent.categories
: RXConsent.getDefaultCategories();
var inputs = RXCookieUI.modal.querySelectorAll('[data-rx-cookie-category-input]');
inputs.forEach(function (input) {
var key = input.getAttribute('data-rx-cookie-category-input');
if (RX_COOKIE_CONFIG.categories[key]?.required) {
input.checked = true;
input.disabled = true;
} else {
input.checked = !!activeCategories[key];
}
});
},
getModalValues: function () {
var values = {};
var inputs = RXCookieUI.modal.querySelectorAll('[data-rx-cookie-category-input]');
inputs.forEach(function (input) {
var key = input.getAttribute('data-rx-cookie-category-input');
values[key] = !!input.checked;
});
return RXConsent.normalizeCategories(values);
},
handleModalClick: function (event) {
var closeButton = event.target.closest('[data-rx-cookie-modal-close]');
var actionButton = event.target.closest('[data-rx-cookie-modal-action]');
if (event.target === RXCookieUI.overlay || closeButton) {
RXCookieUI.closeModal();
return;
}
if (!actionButton) return;
var action = actionButton.getAttribute('data-rx-cookie-modal-action');
if (action === 'accept') {
RXConsent.acceptAll();
RXCookieUI.hideBanner();
RXCookieUI.closeModal();
}
if (action === 'reject') {
RXConsent.rejectAll();
RXCookieUI.hideBanner();
RXCookieUI.closeModal();
}
if (action === 'save') {
RXConsent.saveConsent(RXCookieUI.getModalValues(), 'save_preferences');
RXCookieUI.hideBanner();
RXCookieUI.closeModal();
}
},
handleKeydown: function (event) {
if (!RXCookieUI.overlay) return;
if (RXCookieUI.overlay.classList.contains(RX_COOKIE_CONFIG.classNames.hidden)) return;
if (event.key === 'Escape') {
RXCookieUI.closeModal();
}
RXCookieUtils.trapFocus(RXCookieUI.modal, event);
},
createManageButton: function () {
if (document.querySelector('.' + RX_COOKIE_CONFIG.classNames.manageButton)) {
return;
}
var button = document.createElement('button');
button.type = 'button';
button.className = RX_COOKIE_CONFIG.classNames.manageButton;
button.setAttribute('aria-label', RX_COOKIE_CONFIG.text.manageButton);
button.title = RX_COOKIE_CONFIG.text.manageButton;
button.innerHTML = '🍪';
button.addEventListener('click', function () {
RXCookieUI.openModal();
});
document.body.appendChild(button);
if (RXConsent.hasConsent()) {
RXCookieUI.showManageButton();
}
},
showManageButton: function () {
var button = document.querySelector('.' + RX_COOKIE_CONFIG.classNames.manageButton);
if (button) {
button.classList.add('is-visible');
}
},
bindGlobalEvents: function () {
document.addEventListener('rxOpenCookieSettings', function () {
RXCookieUI.openModal();
});
document.addEventListener('click', function (event) {
var opener = event.target.closest('[data-rx-open-cookie-settings]');
if (!opener) return;
event.preventDefault();
RXCookieUI.openModal();
});
}
};
/**
* Public API
*/
window.RXCookieNotice = {
__loaded: true,
config: RX_COOKIE_CONFIG,
init: function (customConfig) {
if (customConfig && typeof customConfig === 'object') {
RXCookieNotice.configure(customConfig);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', RXCookieUI.init);
} else {
RXCookieUI.init();
}
return window.RXCookieNotice;
},
configure: function (customConfig) {
customConfig = customConfig || {};
Object.keys(customConfig).forEach(function (key) {
if (
typeof customConfig[key] === 'object' &&
customConfig[key] !== null &&
!Array.isArray(customConfig[key]) &&
typeof RX_COOKIE_CONFIG[key] === 'object'
) {
RX_COOKIE_CONFIG[key] = Object.assign({}, RX_COOKIE_CONFIG[key], customConfig[key]);
} else {
RX_COOKIE_CONFIG[key] = customConfig[key];
}
});
return window.RXCookieNotice;
},
openSettings: function () {
RXCookieUI.openModal();
},
closeSettings: function () {
RXCookieUI.closeModal();
},
acceptAll: function () {
var consent = RXConsent.acceptAll();
RXCookieUI.hideBanner();
return consent;
},
rejectAll: function () {
var consent = RXConsent.rejectAll();
RXCookieUI.hideBanner();
return consent;
},
save: function (categories) {
var consent = RXConsent.saveConsent(categories || {}, 'api_save');
RXCookieUI.hideBanner();
return consent;
},
getConsent: function () {
return RXConsent.getConsent();
},
hasConsent: function () {
return RXConsent.hasConsent();
},
isAllowed: function (category) {
return RXConsent.isAllowed(category);
},
reset: function () {
RXConsent.reset();
RXCookieUI.showBanner();
}
};
/**
* Auto init
*/
window.RXCookieNotice.init();
})();
To open cookie settings from any footer link or button, use this HTML:
<a href="#" data-rx-open-cookie-settings>
Cookie settings
</a>
To block optional scripts until consent, use this pattern:
<script
type="text/plain"
data-rx-cookie-category="analytics"
src="https://example.com/analytics.js">
</script>
Available categories:
necessary
preferences
analytics
marketing
For your RX Theme, this chunk is best loaded with defer:
wp_enqueue_script(
'rx-cookie-notice',
get_template_directory_uri() . '/assets/static-js/static-chunks-js/chunk-025-cookie-notice.js',
array(),
'1.0.0',
true
);
This file is now ready as an advanced reusable cookie notice system for your RX Theme.