feat: Implement cookie consent management and improve navigation functionality
This commit is contained in:
+134
-163
@@ -754,6 +754,110 @@
|
||||
(function () {
|
||||
var menuToggle = document.getElementById('mobileMenuToggle');
|
||||
var navLinks = document.getElementById('mainNav');
|
||||
var consentKey = 'cookie_consent_v1';
|
||||
var banner = document.getElementById('cookieBanner');
|
||||
var acceptBtn = document.getElementById('cookieAcceptBtn');
|
||||
var prefsBtn = document.getElementById('cookiePrefsBtn');
|
||||
var prefsModal = document.getElementById('cookiePrefsModal');
|
||||
var analyticsCheckbox = document.getElementById('cookie_analytics');
|
||||
var marketingCheckbox = document.getElementById('cookie_marketing');
|
||||
var prefsSave = document.getElementById('cookiePrefsSave');
|
||||
var prefsAcceptAll = document.getElementById('cookiePrefsAcceptAll');
|
||||
var prefsOnlyNecessary = document.getElementById('cookiePrefsOnlyNecessary');
|
||||
|
||||
function getConsent() {
|
||||
try {
|
||||
var raw = window.localStorage.getItem(consentKey);
|
||||
return raw ? JSON.parse(raw) : null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function applyConsent() {
|
||||
try {
|
||||
var c = getConsent() || {};
|
||||
var analyticsAllowed = !!c.analytics;
|
||||
var marketingAllowed = !!c.marketing;
|
||||
|
||||
document.querySelectorAll('script[type="text/plain"]').forEach(function (node) {
|
||||
var required = node.getAttribute('data-consent') || 'analytics';
|
||||
var allowed = (required === 'analytics' && analyticsAllowed) || (required === 'marketing' && marketingAllowed) || required === 'necessary';
|
||||
if (!allowed) return;
|
||||
|
||||
if (node.getAttribute('data-consent-applied') === '1') return;
|
||||
|
||||
var script = document.createElement('script');
|
||||
if (node.src) script.src = node.src;
|
||||
else script.text = node.textContent || node.innerText || '';
|
||||
|
||||
var type = node.getAttribute('data-script-type');
|
||||
if (type) script.type = type;
|
||||
|
||||
node.parentNode.insertBefore(script, node);
|
||||
node.setAttribute('data-consent-applied', '1');
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('applyConsent error', e);
|
||||
}
|
||||
}
|
||||
|
||||
function saveConsent(obj) {
|
||||
try {
|
||||
window.localStorage.setItem(consentKey, JSON.stringify(obj));
|
||||
document.cookie = 'cookie_consent=' + encodeURIComponent(JSON.stringify(obj)) + '; Max-Age=' + (60 * 60 * 24 * 365) + '; Path=/; SameSite=Strict';
|
||||
applyConsent();
|
||||
} catch (e) {
|
||||
console.error('saveConsent error', e);
|
||||
}
|
||||
}
|
||||
|
||||
function showBannerIfNeeded() {
|
||||
if (banner && !getConsent()) banner.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function openPrefs() {
|
||||
var consent = getConsent() || {};
|
||||
if (analyticsCheckbox) analyticsCheckbox.checked = !!consent.analytics;
|
||||
if (marketingCheckbox) marketingCheckbox.checked = !!consent.marketing;
|
||||
if (prefsModal) prefsModal.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function closePrefs() {
|
||||
if (prefsModal) prefsModal.classList.add('hidden');
|
||||
if (banner) banner.classList.add('hidden');
|
||||
}
|
||||
|
||||
window.printDocument = function () {
|
||||
try { window.print(); } catch (e) { console.error('print error', e); }
|
||||
};
|
||||
|
||||
window.printPdf = function (url) {
|
||||
try {
|
||||
var popup = window.open(url, '_blank');
|
||||
if (!popup) return;
|
||||
var attempts = 0;
|
||||
var timer = setInterval(function () {
|
||||
attempts += 1;
|
||||
try {
|
||||
if (popup.document && (popup.document.readyState === 'complete' || popup.document.readyState === 'interactive')) {
|
||||
popup.focus();
|
||||
popup.print();
|
||||
clearInterval(timer);
|
||||
}
|
||||
} catch (err) {
|
||||
if (attempts > 8) {
|
||||
clearInterval(timer);
|
||||
try { popup.focus(); } catch (focusError) {}
|
||||
}
|
||||
}
|
||||
if (attempts > 30) clearInterval(timer);
|
||||
}, 300);
|
||||
} catch (e) {
|
||||
console.error('printPdf error', e);
|
||||
}
|
||||
};
|
||||
|
||||
if (menuToggle && navLinks) {
|
||||
menuToggle.addEventListener('click', function () {
|
||||
var isExpanded = this.getAttribute('aria-expanded') === 'true';
|
||||
@@ -764,11 +868,10 @@
|
||||
|
||||
navLinks.querySelectorAll('a').forEach(function (link) {
|
||||
link.addEventListener('click', function () {
|
||||
if (navLinks.classList.contains('open')) {
|
||||
menuToggle.setAttribute('aria-expanded', 'false');
|
||||
navLinks.classList.remove('open');
|
||||
navLinks.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
if (!navLinks.classList.contains('open')) return;
|
||||
menuToggle.setAttribute('aria-expanded', 'false');
|
||||
navLinks.classList.remove('open');
|
||||
navLinks.setAttribute('aria-hidden', 'true');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -780,16 +883,6 @@
|
||||
}
|
||||
});
|
||||
|
||||
navLinks.querySelectorAll('a').forEach(function (link) {
|
||||
link.addEventListener('click', function () {
|
||||
if (navLinks.classList.contains('open')) {
|
||||
menuToggle.setAttribute('aria-expanded', 'false');
|
||||
navLinks.classList.remove('open');
|
||||
navLinks.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('resize', function () {
|
||||
if (window.innerWidth > 820 && navLinks.classList.contains('open')) {
|
||||
menuToggle.setAttribute('aria-expanded', 'false');
|
||||
@@ -799,161 +892,39 @@
|
||||
});
|
||||
}
|
||||
|
||||
var banner = document.getElementById("cookieBanner");
|
||||
var acceptBtn = document.getElementById("cookieAcceptBtn");
|
||||
var declineBtn = document.getElementById("cookieDeclineBtn");
|
||||
if (!banner || !acceptBtn || !declineBtn) {
|
||||
return;
|
||||
}
|
||||
if (banner && acceptBtn) {
|
||||
showBannerIfNeeded();
|
||||
|
||||
var consentKey = "cookie_consent_v1";
|
||||
acceptBtn.addEventListener('click', function () {
|
||||
saveConsent({ status: 'accepted', necessary: true, analytics: true, marketing: true, saved_at: Date.now() });
|
||||
banner.classList.add('hidden');
|
||||
});
|
||||
|
||||
function getConsent() {
|
||||
try {
|
||||
var raw = window.localStorage.getItem(consentKey);
|
||||
if (!raw) return null;
|
||||
return JSON.parse(raw);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (prefsBtn) prefsBtn.addEventListener('click', openPrefs);
|
||||
|
||||
function saveConsent(obj) {
|
||||
try {
|
||||
window.localStorage.setItem(consentKey, JSON.stringify(obj));
|
||||
var cookieVal = obj.status || (obj.accepted ? 'accepted' : 'custom');
|
||||
document.cookie = "cookie_consent=" + encodeURIComponent(JSON.stringify(obj)) + "; Max-Age=" + (60 * 60 * 24 * 365) + "; Path=/; SameSite=Strict";
|
||||
// Apply consent immediately: enable any scripts gated by consent
|
||||
applyConsent();
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function showBannerIfNeeded() {
|
||||
var c = getConsent();
|
||||
if (!c) {
|
||||
banner.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
showBannerIfNeeded();
|
||||
|
||||
acceptBtn.addEventListener("click", function () {
|
||||
var obj = { status: 'accepted', necessary: true, analytics: true, marketing: true, saved_at: Date.now() };
|
||||
saveConsent(obj);
|
||||
banner.classList.add("hidden");
|
||||
});
|
||||
|
||||
// Preferences modal handling
|
||||
var prefsBtn = document.getElementById('cookiePrefsBtn');
|
||||
var prefsModal = document.getElementById('cookiePrefsModal');
|
||||
var analyticsCheckbox = document.getElementById('cookie_analytics');
|
||||
var marketingCheckbox = document.getElementById('cookie_marketing');
|
||||
var prefsSave = document.getElementById('cookiePrefsSave');
|
||||
var prefsAcceptAll = document.getElementById('cookiePrefsAcceptAll');
|
||||
var prefsOnlyNecessary = document.getElementById('cookiePrefsOnlyNecessary');
|
||||
|
||||
function openPrefs() {
|
||||
// initialize from existing consent if present
|
||||
var c = getConsent() || {};
|
||||
analyticsCheckbox.checked = !!c.analytics;
|
||||
marketingCheckbox.checked = !!c.marketing;
|
||||
prefsModal.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function closePrefs() {
|
||||
prefsModal.classList.add('hidden');
|
||||
banner.classList.add('hidden');
|
||||
}
|
||||
|
||||
if (prefsBtn) prefsBtn.addEventListener('click', openPrefs);
|
||||
|
||||
prefsSave.addEventListener('click', function () {
|
||||
var obj = { status: 'custom', necessary: true, analytics: !!analyticsCheckbox.checked, marketing: !!marketingCheckbox.checked, saved_at: Date.now() };
|
||||
saveConsent(obj);
|
||||
closePrefs();
|
||||
});
|
||||
|
||||
prefsAcceptAll.addEventListener('click', function () {
|
||||
var obj = { status: 'accepted', necessary: true, analytics: true, marketing: true, saved_at: Date.now() };
|
||||
saveConsent(obj);
|
||||
closePrefs();
|
||||
});
|
||||
|
||||
prefsOnlyNecessary.addEventListener('click', function () {
|
||||
var obj = { status: 'necessary', necessary: true, analytics: false, marketing: false, saved_at: Date.now() };
|
||||
saveConsent(obj);
|
||||
closePrefs();
|
||||
});
|
||||
|
||||
// --- Consent-based script loader -------------------------------------------------
|
||||
// Usage: include scripts that require consent like this in templates:
|
||||
// <script type="text/plain" data-consent="analytics" src="https://www.googletagmanager.com/gtag/js?id=XXX"></script>
|
||||
// or for inline scripts:
|
||||
// <script type="text/plain" data-consent="marketing"> /* fbq or other init code */ </script>
|
||||
function applyConsent() {
|
||||
try {
|
||||
var c = getConsent() || {};
|
||||
var analyticsAllowed = !!c.analytics;
|
||||
var marketingAllowed = !!c.marketing;
|
||||
|
||||
// Find all scripts that were intentionally disabled by using type="text/plain"
|
||||
document.querySelectorAll('script[type="text/plain"]').forEach(function (node) {
|
||||
var required = node.getAttribute('data-consent') || 'analytics';
|
||||
if ((required === 'analytics' && analyticsAllowed) || (required === 'marketing' && marketingAllowed) || required === 'necessary') {
|
||||
var s = document.createElement('script');
|
||||
// copy src or inline content
|
||||
if (node.src) s.src = node.src;
|
||||
else s.text = node.textContent || node.innerText || '';
|
||||
// copy attributes that are safe/needed
|
||||
var type = node.getAttribute('data-script-type');
|
||||
if (type) s.type = type;
|
||||
// append to same parent
|
||||
node.parentNode.insertBefore(s, node);
|
||||
// mark original as applied to avoid double-inserting
|
||||
node.setAttribute('data-consent-applied', '1');
|
||||
}
|
||||
if (prefsSave) prefsSave.addEventListener('click', function () {
|
||||
saveConsent({
|
||||
status: 'custom',
|
||||
necessary: true,
|
||||
analytics: !!(analyticsCheckbox && analyticsCheckbox.checked),
|
||||
marketing: !!(marketingCheckbox && marketingCheckbox.checked),
|
||||
saved_at: Date.now()
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('applyConsent error', e);
|
||||
}
|
||||
closePrefs();
|
||||
});
|
||||
|
||||
if (prefsAcceptAll) prefsAcceptAll.addEventListener('click', function () {
|
||||
saveConsent({ status: 'accepted', necessary: true, analytics: true, marketing: true, saved_at: Date.now() });
|
||||
closePrefs();
|
||||
});
|
||||
|
||||
if (prefsOnlyNecessary) prefsOnlyNecessary.addEventListener('click', function () {
|
||||
saveConsent({ status: 'necessary', necessary: true, analytics: false, marketing: false, saved_at: Date.now() });
|
||||
closePrefs();
|
||||
});
|
||||
}
|
||||
|
||||
// Run once on load in case user already saved consent
|
||||
applyConsent();
|
||||
// Global print helpers
|
||||
window.printDocument = function () {
|
||||
try { window.print(); } catch (e) { console.error('print error', e); }
|
||||
};
|
||||
|
||||
window.printPdf = function (url) {
|
||||
try {
|
||||
var w = window.open(url, '_blank');
|
||||
if (!w) return;
|
||||
// Attempt to print after load; poll for readyState
|
||||
var attempts = 0;
|
||||
var t = setInterval(function () {
|
||||
attempts++;
|
||||
try {
|
||||
if (w.document && (w.document.readyState === 'complete' || w.document.readyState === 'interactive')) {
|
||||
w.focus();
|
||||
w.print();
|
||||
clearInterval(t);
|
||||
}
|
||||
} catch (err) {
|
||||
// cross-domain or plugin viewer may block access; fallback: focus window and leave to user
|
||||
if (attempts > 8) {
|
||||
clearInterval(t);
|
||||
try { w.focus(); } catch (e) {}
|
||||
}
|
||||
}
|
||||
if (attempts > 30) clearInterval(t);
|
||||
}, 300);
|
||||
} catch (e) {
|
||||
console.error('printPdf error', e);
|
||||
}
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user