1/** 2 * Cookie Consent Manager 3 * For Ridgecrest Camps (Boys & Girls sites) 4 * GDPR & ePrivacy Compliant 5 * 6 * Manages user cookie consent preferences and controls analytics tracking 7 */ 8 9(function() { 10 'use strict'; 11 12 var KSCookieConsent = { 13 14 // Configuration 15 config: { 16 cookieName: 'ks_cookie_consent', 17 cookieExpireDays: 365, 18 cookiePath: '/', 19 categories: { 20 necessary: { enabled: true, required: true }, 21 analytics: { enabled: false, required: false }, 22 marketing: { enabled: false, required: false } 23 } 24 }, 25 26 /** 27 * Initialize the cookie consent system 28 */ 29 init: function() { 30 // Check if user has already made a choice 31 var consent = this.getConsent(); 32 33 if (consent === null) { 34 // No consent yet, show banner 35 this.showBanner(); 36 } else { 37 // Consent exists, apply preferences 38 this.applyConsent(consent); 39 } 40 41 // Bind event listeners 42 this.bindEvents(); 43 }, 44 45 /** 46 * Get current consent preferences from cookie 47 */ 48 getConsent: function() { 49 var name = this.config.cookieName + '='; 50 var decodedCookie = decodeURIComponent(document.cookie); 51 var ca = decodedCookie.split(';'); 52 53 for(var i = 0; i < ca.length; i++) { 54 var c = ca[i]; 55 while (c.charAt(0) === ' ') { 56 c = c.substring(1); 57 } 58 if (c.indexOf(name) === 0) { 59 try { 60 return JSON.parse(c.substring(name.length, c.length)); 61 } catch(e) { 62 return null; 63 } 64 } 65 } 66 return null; 67 }, 68 69 /** 70 * Set consent preferences in cookie 71 */ 72 setConsent: function(preferences) { 73 var d = new Date(); 74 d.setTime(d.getTime() + (this.config.cookieExpireDays * 24 * 60 * 60 * 1000)); 75 var expires = 'expires=' + d.toUTCString(); 76 var cookieValue = JSON.stringify(preferences); 77 document.cookie = this.config.cookieName + '=' + cookieValue + ';' + expires + ';path=' + this.config.cookiePath + ';SameSite=Lax'; 78 79 console.log('Cookie consent saved:', preferences); 80 }, 81 82 /** 83 * Show the cookie consent banner 84 */ 85 showBanner: function() { 86 var banner = document.querySelector('.ks-cookie-consent-banner'); 87 if (banner) { 88 banner.classList.add('show'); 89 // Set focus to accept button for accessibility 90 setTimeout(function() { 91 var acceptBtn = banner.querySelector('.ks-cookie-consent-btn-accept'); 92 if (acceptBtn) acceptBtn.focus(); 93 }, 100); 94 } 95 }, 96 97 /** 98 * Hide the cookie consent banner 99 */ 100 hideBanner: function() { 101 var banner = document.querySelector('.ks-cookie-consent-banner'); 102 if (banner) { 103 banner.classList.remove('show'); 104 } 105 }, 106 107 /** 108 * Show the settings modal 109 */ 110 showModal: function() { 111 var modal = document.querySelector('.ks-cookie-consent-modal'); 112 if (modal) { 113 modal.classList.add('show'); 114 // Update toggles based on current or default state 115 var consent = this.getConsent() || this.config.categories; 116 this.updateToggles(consent); 117 // Set focus to close button for accessibility 118 setTimeout(function() { 119 var closeBtn = modal.querySelector('.ks-cookie-consent-modal-close'); 120 if (closeBtn) closeBtn.focus(); 121 }, 100); 122 } 123 }, 124 125 /** 126 * Hide the settings modal 127 */ 128 hideModal: function() { 129 var modal = document.querySelector('.ks-cookie-consent-modal'); 130 if (modal) { 131 modal.classList.remove('show'); 132 } 133 }, 134 135 /** 136 * Update toggle switches in modal 137 */ 138 updateToggles: function(preferences) { 139 for (var category in preferences) { 140 var toggle = document.getElementById('ks-cookie-' + category); 141 if (toggle) { 142 toggle.checked = preferences[category].enabled; 143 } 144 } 145 }, 146 147 /** 148 * Accept all cookies 149 */ 150 acceptAll: function() { 151 var preferences = { 152 necessary: { enabled: true, required: true }, 153 analytics: { enabled: true, required: false }, 154 marketing: { enabled: true, required: false }, 155 timestamp: new Date().toISOString() 156 }; 157 158 this.setConsent(preferences); 159 this.applyConsent(preferences); 160 this.hideBanner(); 161 this.hideModal(); 162 }, 163 164 /**
165 * Reject all non-essential cookies 166 */ 167 rejectAll: function() { 168 var preferences = { 169 necessary: { enabled: true, required: true }, 170 analytics: { enabled: false, required: false }, 171 marketing: { enabled: false, required: false }, 172 timestamp: new Date().toISOString() 173 }; 174 175 this.setConsent(preferences); 176 this.applyConsent(preferences); 177 this.hideBanner(); 178 this.hideModal(); 179 }, 180 181 /** 182 * Save custom preferences from modal 183 */ 184 savePreferences: function() { 185 var preferences = { 186 necessary: { 187 enabled: true, 188 required: true 189 }, 190 analytics: { 191 enabled: document.getElementById('ks-cookie-analytics').checked, 192 required: false 193 }, 194 marketing: { 195 enabled: document.getElementById('ks-cookie-marketing').checked, 196 required: false 197 }, 198 timestamp: new Date().toISOString() 199 }; 200 201 this.setConsent(preferences); 202 this.applyConsent(preferences); 203 this.hideBanner(); 204 this.hideModal(); 205 }, 206 207 /** 208 * Apply consent preferences (enable/disable tracking) 209 */ 210 applyConsent: function(preferences) { 211 // Handle Google Analytics 212 if (preferences.analytics && preferences.analytics.enabled) { 213 this.enableAnalytics(); 214 } else { 215 this.disableAnalytics(); 216 } 217 218 // Handle Marketing cookies (if needed in future) 219 if (preferences.marketing && preferences.marketing.enabled) { 220 this.enableMarketing(); 221 } else { 222 this.disableMarketing(); 223 } 224 225 // Dispatch custom event for other scripts to listen to 226 var event; 227 if (typeof(Event) === 'function') { 228 event = new Event('ksCookieConsentChanged', { detail: preferences, bubbles: true, cancelable: true }); 229 } else { 230 // Fallback for older browsers 231 event = document.createEvent('CustomEvent'); 232 event.initCustomEvent('ksCookieConsentChanged', true, true, preferences); 233 } 234 document.dispatchEvent(event); 235 }, 236 237 /** 238 * Enable Google Analytics tracking 239 */ 240 enableAnalytics: function() { 241 console.log('Google Analytics enabled'); 242 243 // Re-enable Universal Analytics (UA-33976323-1 and UA-33976323-2) 244 window['ga-disable-UA-33976323-1'] = false; 245 window['ga-disable-UA-33976323-2'] = false; 246 247 // Enable Google Analytics 4 via gtag consent 248 if (typeof gtag !== 'undefined') { 249 console.log('Google Analytics 4 (G-KZMFK5J97H) enabled'); 250 gtag('consent', 'update', { 251 'analytics_storage': 'granted', 252 'ad_storage': 'denied' // Still deny ad storage unless marketing cookies enabled 253 }); 254 } 255 256 // Re-enable Adobe DTM if present 257 if (typeof _satellite !== 'undefined') { 258 console.log('Adobe DTM enabled'); 259 // Adobe satellite tracking is re-enabled 260 } 261 }, 262 263 /** 264 * Disable Google Analytics tracking 265 */ 266 disableAnalytics: function() { 267 console.log('Google Analytics disabled'); 268 269 // Disable Universal Analytics (both tracking IDs) 270 window['ga-disable-UA-33976323-1'] = true; 271 window['ga-disable-UA-33976323-2'] = true; 272 273 // Disable Google Analytics 4 274 if (typeof gtag !== 'undefined') { 275 console.log('Google Analytics 4 (G-KZMFK5J97H) disabled'); 276 gtag('consent', 'update', { 277 'analytics_storage': 'denied', 278 'ad_storage': 'denied' 279 }); 280 } 281 282 // Delete Google Analytics cookies 283 this.deleteCookie('_ga'); 284 this.deleteCookie('_gid'); 285 this.deleteCookie('_gat'); 286 this.deleteCookie('_gat_gtag_UA_33976323_1'); 287 this.deleteCookie('_gat_gtag_UA_33976323_2'); 288 289 // Note: Adobe DTM tracking cannot be disabled after page load 290 // It would need to be blocked before the script loads 291 }, 292 293 /** 294 * Enable marketing cookies (placeholder for future use) 295 */ 296 enableMarketing: function() { 297 console.log('Marketing cookies enabled'); 298 // Add future marketing tracking code here 299 }, 300 301 /** 302 * Disable marketing cookies 303 */ 304 disableMarketing: function() { 305 console.log('Marketing cookies disabled'); 306 // Add code to disable marketing tracking here 307 }, 308 309 /** 310 * Delete a specific cookie 311 */ 312 deleteCookie: function(name) { 313 document.cookie = name + '=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;'; 314 }, 315 316 /** 317 * Bind event listeners 318 */ 319 bindEvents: function() { 320 var self = this; 321 322 // Accept All button 323 var acceptBtn = document.querySelector('.ks-cookie-consent-btn-accept'); 324 if (acceptBtn) { 325 acceptBtn.addEventListener('click', function(e) { 326 e.preventDefault(); 327 self.acceptAll(); 328 }); 329 } 330 331 // Reject All button 332 var rejectBtn = document.querySelector('.ks-cookie-consent-btn-reject'); 333 if (rejectBtn) { 334 rejectBtn.addEventListener('click', function(e) { 335 e.preventDefault(); 336 self.rejectAll(); 337 }); 338 } 339 340 // Settings button 341 var settingsBtn = document.querySelector('.ks-cookie-consent-btn-settings'); 342 if (settingsBtn) { 343 settingsBtn.addEventListener('click', function(e) { 344 e.preventDefault(); 345 self.showModal(); 346 }); 347 } 348 349 // Modal close button 350 var closeBtn = document.querySelector('.ks-cookie-consent-modal-close'); 351 if (closeBtn) { 352 closeBtn.addEventListener('click', function(e) { 353 e.preventDefault(); 354 self.hideModal(); 355 }); 356 } 357 358 // Modal save preferences button 359 var saveBtn = document.querySelector('.ks-cookie-consent-btn-save'); 360 if (saveBtn) { 361 saveBtn.addEventListener('click', function(e) { 362 e.preventDefault(); 363 self.savePreferences(); 364 }); 365 } 366 367 // Modal accept all button 368 var modalAcceptBtn = document.querySelector('.ks-cookie-consent-modal .ks-cookie-consent-btn-accept'); 369 if (modalAcceptBtn) { 370 modalAcceptBtn.addEventListener('click', function(e) { 371 e.preventDefault(); 372 self.acceptAll(); 373 }); 374 } 375 376 // Close modal when clicking outside 377 var modal = document.querySelector('.ks-cookie-consent-modal'); 378 if (modal) { 379 modal.addEventListener('click', function(e) { 380 if (e.target === modal) { 381 self.hideModal(); 382 } 383 }); 384 } 385 386 // Keyboard accessibility - ESC to close modal 387 document.addEventListener('keydown', function(e) { 388 // Use e.key (modern) with fallback check for older browsers 389 if (e.key === 'Escape' || e.key === 'Esc') { 390 self.hideModal(); 391 } 392 }); 393 } 394 }; 395 396 // Initialize when DOM is ready 397 if (document.readyState === 'loading') { 398 document.addEventListener('DOMContentLoaded', function() { 399 KSCookieConsent.init(); 400 }); 401 } else { 402 KSCookieConsent.init(); 403 } 404 405 // Expose to window for manual control if needed 406 window.KSCookieConsent = KSCookieConsent; 407 408})();
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.