1"use strict"; 2 3document.addEventListener('DOMContentLoaded', function () { 4 // DOM Elements 5 const consentRoot = document.querySelector('.cookie-consent-root'); 6 const acceptButtons = document.querySelectorAll('.cookie-consent-accept'); 7 const rejectButtons = document.querySelectorAll('.cookie-consent-reject'); 8 const cookieConsentPrefix = consentRoot?.getAttribute('data-cookie-prefix') || 'cookie_consent'; 9 const preferencesCookieName = `${cookieConsentPrefix}_preferences`; 10 11 // Modal Elements 12 const preferencesBtn = document.querySelector('.preferences-btn'); 13 const modal = document.querySelector('.cookie-preferences-modal'); 14 const modalOverlay = document.querySelector('.cookie-preferences-modal-overlay'); 15 const modalClose = document.querySelector('.cookie-preferences-modal-close'); 16 const modalSave = document.querySelector('.cookie-preferences-save'); 17 18 // Initialize banner 19 if (consentRoot) { 20 consentRoot.classList.remove('cookie-consent-hide'); 21 if (consentRoot.classList.contains('cookie-disable-interaction')) { 22 document.documentElement.classList.add('cookie-disable-interaction'); 23 } 24 } 25 26 // Check existing consent 27 const cookieConsent = getCookie(cookieConsentPrefix); 28 if (cookieConsent === 'accepted' || cookieConsent === 'rejected') { 29 hideConsentBanner(); 30 } 31 32 // Accept handler 33 acceptButtons.forEach(button => { 34 button.addEventListener('click', () => { 35 setCookie(cookieConsentPrefix, 'accepted', consentRoot?.getAttribute('data-cookie-lifetime') || 7); 36 setAllPreferences(true); 37 hideConsentBanner(); 38 document.dispatchEvent(new CustomEvent('cookieConsentAccepted')); 39 40 if (typeof loadCookieCategoriesEnabledServices === 'function') { 41 try { 42 loadCookieCategoriesEnabledServices(); 43 } catch (e) { 44 console.info(e); 45 } 46 } 47 }); 48 }); 49 50 // Reject handler 51 rejectButtons.forEach(button => { 52 button.addEventListener('click', () => { 53 setCookie(cookieConsentPrefix, 'rejected', consentRoot?.getAttribute('data-reject-lifetime') || 1); 54 setAllPreferences(false); 55 hideConsentBanner(); 56 document.dispatchEvent(new CustomEvent('cookieConsentRejected')); 57 }); 58 }); 59 60 // Modal controls 61 function showModal() { 62 if (!modal) return; 63 document.body.classList.add('modal-open'); 64 modal.setAttribute('aria-hidden', 'false'); 65 modal.classList.add('is-visible'); 66 67 const savedPreferences = getCookiePreferences(); 68 document.querySelectorAll('.cookie-toggle input:not([disabled])').forEach(toggle => { 69 const category = toggle.dataset.category; 70 toggle.checked = savedPreferences ? savedPreferences[category] !== false : true; 71 }); 72 } 73 74 function hideModal() { 75 if (!modal) return; 76 modal.setAttribute('aria-hidden', 'true'); 77 modal.classList.remove('is-visible'); 78 document.body.classList.remove('modal-open'); 79 } 80 81 function setAllPreferences(accept) { 82 const preferences = {}; 83 document.querySelectorAll('.cookie-toggle input[data-category]').forEach(toggle => { 84 preferences[toggle.dataset.category] = toggle.disabled ? true : accept; 85 }); 86 setCookiePreferences(preferences); 87 } 88 89 // Modal events 90 preferencesBtn?.addEventListener('click', showModal); 91 modalOverlay?.addEventListener('click', hideModal); 92 modalClose?.addEventListener('click', hideModal); 93 94 modalSave?.addEventListener('click', () => { 95 const preferences = {}; 96 document.querySelectorAll('.cookie-toggle input[data-category]').forEach(toggle => { 97 preferences[toggle.dataset.category] = toggle.checked; 98 }); 99 100 setCookiePreferences(preferences); 101 setCookie(cookieConsentPrefix, 'accepted', consentRoot?.getAttribute('data-cookie-lifetime') || 7); 102 103 hideModal(); 104 hideConsentBanner(); 105 document.dispatchEvent(new CustomEvent('cookiePreferencesSaved', { detail: preferences })); 106 document.dispatchEvent(new CustomEvent('cookieConsentAccepted')); 107 108 if (typeof loadCookieCategoriesEnabledServices === 'function') { 109 try { 110 loadCookieCategoriesEnabledServices(); 111 } catch (e) { 112 console.info(e); 113 } 114 } 115 }); 116 117 // Escape key 118 document.addEventListener('keydown', function (e) { 119 if (e.key === 'Escape' && modal?.classList.contains('is-visible')) { 120 hideModal(); 121 } 122 }); 123 124 // Helpers 125 function setCookie(name, value, days) { 126 const date = new Date(); 127 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 128 const expires = "; expires=" + date.toUTCString(); 129 const secureFlag = location.protocol === 'https:' ? "; Secure" : ""; 130 document.cookie = `${name}=${value}; path=/; SameSite=Lax${expires}${secureFlag}`; 131 } 132 133 function getCookie(name) { 134 const nameEQ = name + "="; 135 const cookies = document.cookie.split(';'); 136 for (let cookie of cookies) { 137 cookie = cookie.trim(); 138 if (cookie.indexOf(nameEQ) === 0) { 139 return cookie.substring(nameEQ.length); 140 } 141 } 142 return null; 143 } 144 145 function setCookiePreferences(preferences) { 146 const expires = new Date(); 147 expires.setTime(expires.getTime() + (365 * 24 * 60 * 60 * 1000)); 148 const secureFlag = location.protocol === 'https:' ? "; Secure" : ""; 149 document.cookie = `${preferencesCookieName}=${JSON.stringify(preferences)}; expires=${expires.toUTCString()}; path=/; SameSite=Lax${secureFlag}`; 150 } 151 152 function getCookiePreferences() { 153 const name = `${preferencesCookieName}=`; 154 const decoded = decodeURIComponent(document.cookie); 155 const cookies = decoded.split(';'); 156 for (let cookie of cookies) { 157 cookie = cookie.trim(); 158 if (cookie.indexOf(name) === 0) { 159 try { 160 return JSON.parse(cookie.substring(name.length)); 161 } catch (e) { 162 console.warn('Invalid preferences cookie'); 163 } 164 } 165 } 166 return null; 167 } 168 169 function hideConsentBanner() { 170 if (consentRoot) { 171 consentRoot.classList.add('cookie-consent-hide'); 172 document.documentElement.classList.remove('cookie-disable-interaction'); 173 } 174 hideModal(); 175 } 176 177 // Expose globals 178 window.getCookie = getCookie; 179 window.getCookiePreferences = getCookiePreferences; 180 181 function showHideToggleCookiePreferencesModal() { 182 const modal = document.querySelector('.cookie-preferences-modal'); 183 if (!modal) return; 184 185 const isVisible = modal.classList.contains('is-visible'); 186 if (isVisible) { 187 // Hide modal 188 modal.setAttribute('aria-hidden', 'true'); 189 modal.classList.remove('is-visible'); 190 document.body.classList.remove('modal-open'); 191 } else { 192 // Show modal 193 modal.setAttribute('aria-hidden', 'false'); 194 modal.classList.add('is-visible'); 195 document.body.classList.add('modal-open'); 196 197 // Initialize toggles if needed 198 const savedPreferences = window.getCookiePreferences?.(); 199 document.querySelectorAll('.cookie-toggle input:not([disabled])').forEach(toggle => { 200 const category = toggle.dataset.category; 201 toggle.checked = savedPreferences ? savedPreferences[category] !== false : true; 202 }); 203 } 204 } 205 206 // Expose globally for inline onclick 207 window.showHideToggleCookiePreferencesModal = showHideToggleCookiePreferencesModal; 208 209 document.addEventListener('click', function (e) { 210 if (e.target.classList.contains('showHideToggleCookiePreferencesModal')) { 211 e.preventDefault(); 212 showHideToggleCookiePreferencesModal(); 213 } 214 }); 215 216}); 217 218// Prevent layout shift on modal open 219document.head.insertAdjacentHTML('beforeend', ` 220 <style>
221 .modal-open { 222 overflow: hidden; 223 padding-right: var(--scrollbar-width, 0); 224 } 225 </style> 226`);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.