1(function ($, Drupal, once) { 2 3 'use strict'; 4 5 const ANALYTICS_CONSENT_RETRY_INTERVAL = 250; 6 const ANALYTICS_CONSENT_MAX_ATTEMPTS = 40; 7 let analyticsConsentInitialized = false; 8 9 function setExpanded($panel, $popup, expanded, $button, $buttonWrapper) { 10 if ($button && $button.length) { 11 $button.attr('aria-expanded', expanded ? 'true' : 'false'); 12 } 13 14 if ($buttonWrapper && $buttonWrapper.length) { 15 $buttonWrapper.toggleClass('is-hidden', expanded); 16 } 17 18 $panel.prop('hidden', !expanded); 19 $popup.toggleClass('is-managing-preferences', expanded); 20 21 if (expanded) { 22 const $focusTarget = $panel 23 .find('input, button, a, select, textarea') 24 .filter(':visible:not(:disabled)') 25 .first(); 26 27 if ($focusTarget.length) { 28 $focusTarget.trigger('focus'); 29 } 30 } 31 } 32 33 Drupal.behaviors.cookieBannerManage = { 34 attach: function (context) { 35 once('cookieBannerPanelInit', '#cookie-preferences-panel', context).forEach((element) => { 36 const $panel = $(element); 37 const $popup = $panel.closest('#sliding-popup'); 38 const $wrapper = $panel.prev('.eu-cookie-compliance-manage'); 39 const $panelCloseButtons = $panel.find('.cookie-preferences-close'); 40 const $popupCloseButtons = $popup.find('.cookie-preferences-close').not($panelCloseButtons); 41 const $closeButtons = $panelCloseButtons.add($popupCloseButtons); 42 43 if (!$popup.length) { 44 return; 45 } 46 47 const shouldExpand = $panel.hasClass('is-expanded') || !$panel.is('[hidden]'); 48 if (shouldExpand) { 49 setExpanded($panel, $popup, true, null, $wrapper); 50 } 51 52 if ($closeButtons.length) { 53 $closeButtons.on('click', (event) => { 54 event.preventDefault(); 55 setExpanded($panel, $popup, false, null, $wrapper); 56 }); 57 } 58 }); 59 60 once('cookieBannerManage', '.eu-cookie-compliance-manage-button', context).forEach((element) => { 61 const $button = $(element); 62 const panelId = $button.attr('aria-controls'); 63 const $panel = panelId ? $('#' + panelId) : $(); 64 const popup = element.closest('#sliding-popup'); 65 const $popup = popup ? $(popup) : $(); 66 const $wrapper = $button.closest('.eu-cookie-compliance-manage'); 67 68 if (!$panel.length || !$popup.length) { 69 return; 70 } 71 72 $button.on('click', (event) => { 73 event.preventDefault(); 74 const expanded = $button.attr('aria-expanded') === 'true'; 75 setExpanded($panel, $popup, !expanded, $button, $wrapper); 76 }); 77 78 }); 79 80 once('cookieBannerPopupClose', '#sliding-popup', context).forEach((popupElement) => { 81 const $popup = $(popupElement); 82 $popup.on('eu_cookie_compliance_popup_close.cookieBannerManage', () => { 83 const $panel = $popup.find('#cookie-preferences-panel'); 84 if (!$panel.length) { 85 return; 86 } 87 const $button = $popup.find('.eu-cookie-compliance-manage-button'); 88 const $wrapper = $button.closest('.eu-cookie-compliance-manage'); 89 setExpanded($panel, $popup, false, $button, $wrapper); 90 }); 91 }); 92 } 93 }; 94 95 function hasCookieComplianceApi() { 96 if (!Drupal.eu_cookie_compliance) { 97 return false; 98 } 99 const isCallable = typeof Drupal.eu_cookie_compliance === 'function'; 100 const hasCategoryGetter = typeof Drupal.eu_cookie_compliance.getAcceptedCategories === 'function'; 101 return isCallable && hasCategoryGetter; 102 } 103 104 function getAcceptedCategories() { 105 if (!Drupal.eu_cookie_compliance || typeof Drupal.eu_cookie_compliance.getAcceptedCategories !== 'function') { 106 return []; 107 } 108 109 try { 110 return Drupal.eu_cookie_compliance.getAcceptedCategories() || []; 111 } catch (error) { 112 return []; 113 } 114 } 115 116 function updateAnalyticsConsent(categories) { 117 // Desired behavior (opt-out): treat Analytics as allowed by default, 118 // unless the user has explicitly saved a preference/status that disables it. 119 // 120 // EU Cookie Compliance will NOT include default-checked categories in 121 // getAcceptedCategories() until the user saves/accepts; so we must check 122 // whether the user has made a choice. 123 let hasExplicitChoice = false;
124 if (Drupal.eu_cookie_compliance && typeof Drupal.eu_cookie_compliance.getCookieStatus === 'function') { 125 const status = Drupal.eu_cookie_compliance.getCookieStatus(); 126 hasExplicitChoice = status !== null && typeof status !== 'undefined' && status !== 'null'; 127 } 128 129 const allowAnalytics = !hasExplicitChoice || (Array.isArray(categories) && categories.indexOf('analytics') !== -1); 130 if (typeof window.__iisdUpdateAnalyticsConsent === 'function') { 131 window.__iisdUpdateAnalyticsConsent(allowAnalytics); 132 } 133 else if (typeof window.gtag === 'function') { 134 window.gtag('consent', 'update', { 135 analytics_storage: allowAnalytics ? 'granted' : 'denied' 136 }); 137 } 138 } 139 140 function initAnalyticsConsentBridge() { 141 if (analyticsConsentInitialized) { 142 return true; 143 } 144 145 if (!hasCookieComplianceApi()) { 146 return false; 147 } 148 149 updateAnalyticsConsent(getAcceptedCategories()); 150 151 Drupal.eu_cookie_compliance('postPreferencesSave', function (payload) { 152 updateAnalyticsConsent(payload.currentCategories || []); 153 }); 154 155 Drupal.eu_cookie_compliance('postStatusLoad', function (payload) { 156 updateAnalyticsConsent(payload.currentCategories || getAcceptedCategories()); 157 }); 158 159 analyticsConsentInitialized = true; 160 return true; 161 } 162 163 Drupal.behaviors.cookieBannerAnalyticsConsent = { 164 attach: function (context) { 165 once('cookieBannerAnalyticsConsent', 'body', context).forEach(() => { 166 if (!initAnalyticsConsentBridge()) { 167 let attempts = 0; 168 const retry = setInterval(() => { 169 attempts += 1; 170 if (initAnalyticsConsentBridge()) { 171 clearInterval(retry); 172 } 173 else if (attempts >= ANALYTICS_CONSENT_MAX_ATTEMPTS) { 174 clearInterval(retry); 175 if (typeof console !== 'undefined' && typeof console.warn === 'function') { 176 console.warn('Cookie banner analytics consent bridge failed to initialize.'); 177 } 178 } 179 }, ANALYTICS_CONSENT_RETRY_INTERVAL); 180 } 181 }); 182 } 183 }; 184})(jQuery, Drupal, once); 185
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.