PageSourceSearch

https://www.iisd.org/themes/custom/iisd/assets/js/cookie-banner.js?tls933

js iisd.org collected 2026-09-24 08:27:43 UTC 6,456 bytes, 185 lines download raw bytes

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.