PageSourceSearch

https://www.zm.gov.lv/modules/contrib/eu_cookie_compliance/js/eu_cookie_compliance.js?tkt2ei

js zm.gov.lv collected 2026-09-24 09:22:22 UTC 68,221 bytes, 1,604 lines download raw bytes

1/**
2 * @file
3 * eu_cookie_compliance.js
4 *
5 * Defines the behavior of the eu cookie compliance banner.
6 *
7 * Statuses:
8 *  null: not yet agreed (or withdrawn), show popup
9 *  0: Disagreed
10 *  1: Agreed, show thank you banner
11 *  2: Agreed
12 */
13
14(function ($, Drupal, drupalSettings, cookies) {
15
16  'use strict';
17  var euCookieComplianceBlockCookies;
18  var cookieValueDisagreed = (typeof drupalSettings.eu_cookie_compliance.cookie_value_disagreed === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_value_disagreed === '') ? '0' : drupalSettings.eu_cookie_compliance.cookie_value_disagreed;
19  var cookieValueAgreedShowThankYou = (typeof drupalSettings.eu_cookie_compliance.cookie_value_agreed_show_thank_you === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_value_agreed_show_thank_you === '') ? '1' : drupalSettings.eu_cookie_compliance.cookie_value_agreed_show_thank_you;
20  var cookieValueAgreed = (typeof drupalSettings.eu_cookie_compliance.cookie_value_agreed === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_value_agreed === '') ? '2' : drupalSettings.eu_cookie_compliance.cookie_value_agreed;
21
22  function setCookie(name,value,settings) {
23    var expires = "";
24
25    if (settings['expires'] !== undefined) {
26      if (typeof (settings['expires']) == 'number') {
27        var date = new Date();
28        settings['expires'] = date.setTime(date.getTime() + (settings['expires']*24*60*60*1000));
29      }
30      expires = "; expires=" + settings['expires'].toUTCString();
31    }
32    var path = (settings['path'] === undefined)?'/':settings['path'];
33    var domain = "";
34    if (settings['domain'] !== undefined) {
35      domain = "; domain=" + settings['domain'];
36    }
37    document.cookie = name + "=" + (value || "")  + expires + "; path=" + path  + domain + "; SameSite=Strict";
38  }
39
40  function getCookie(name) {
41    var ca = document.cookie.split(';');
42    if (name !== undefined) {
43      var nameEQ = name + "=";
44      for (var i = 0; i < ca.length; i++) {
45        var c = ca[i];
46        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
47        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
48      }
49      return null;
50    }
51    return ca;
52  }
53  function eraseCookie(name) {
54    document.cookie = name +'=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
55  }
56
57  Drupal.behaviors.euCookieCompliancePopup = {
58    attach: function (context) {
59      if (typeof drupalSettings.eu_cookie_compliance !== 'undefined') {
60        const element = document.querySelector(drupalSettings.eu_cookie_compliance.containing_element);
61        if (!element) {
62          return;
63        }
64        if (!element.getAttribute('data-eu-cookie-compliance-once')) {
65          element.setAttribute('data-eu-cookie-compliance-once', 'true');
66        } else {
67          return;
68        }
69        // Initialize internal variables.
70        _euccCurrentStatus = self.getCurrentStatus();
71        _euccSelectedCategories = self.getAcceptedCategories();
72        // If configured, check JSON callback to determine if in EU.
73        if (drupalSettings.eu_cookie_compliance.popup_eu_only_js) {
74          if (Drupal.eu_cookie_compliance.showBanner()) {
75            var url = drupalSettings.path.baseUrl + drupalSettings.path.pathPrefix + 'eu-cookie-compliance-check';
76            var data = {};
77            $.getJSON(url, data, function (data) {
78              // If in the EU, show the compliance banner.
79              if (data.in_eu) {
80                Drupal.eu_cookie_compliance.execute();
81              }
82
83              // If not in EU, set an agreed cookie automatically.
84              else {
85                Drupal.eu_cookie_compliance.setStatus(cookieValueAgreed);
86                // Set the geoip_match to false so it can be used elsewhere.
87                drupalSettings.eu_cookie_compliance.geoip_match = false;
88                if (!euCookieComplianceHasLoadedScripts && typeof euCookieComplianceLoadScripts === "function") {
89                  euCookieComplianceLoadScripts();
90                }
91                // Also set all the categories as agreed if applicable, and load
92                // scripts.
93                if (drupalSettings.eu_cookie_compliance.method === 'categories') {
94                  var categories = drupalSettings.eu_cookie_compliance.cookie_categories;
95                  Drupal.eu_cookie_compliance.setAcceptedCategories(categories);
96                  Drupal.eu_cookie_compliance.loadCategoryScripts(categories);
97                }
98              }
99            });
100          }
101        }
102
103        // Otherwise, fallback to standard behavior which is to render the banner.
104        else if (!drupalSettings.eu_cookie_compliance.hide_the_banner) {
105          Drupal.eu_cookie_compliance.execute();
106        }
107        $(element).addClass('eu-cookie-compliance-status-' + Drupal.eu_cookie_compliance.getCurrentStatus());
108      }
109    },
110  };
111
112  // Set up the namespace as a function to store list of arguments in a queue.
113  Drupal.eu_cookie_compliance = Drupal.eu_cookie_compliance || function () {
114    (Drupal.eu_cookie_compliance.queue = Drupal.eu_cookie_compliance.queue || []).push(arguments)
115  };
116  // Initialize the object with some data.
117  Drupal.eu_cookie_compliance.a = +new Date;
118  // A shorter name to use when accessing the namespace.
119  var self = Drupal.eu_cookie_compliance;
120  // Save our cookie preferences locally only.
121  // Used by external scripts to modify data before it is used.
122  var _euccSelectedCategories = [];
123  var _euccCurrentStatus = null;
124  self.updateSelectedCategories = function (categories) {
125    _euccSelectedCategories = categories;
126  }
127  self.updateCurrentStatus = function (status) {
128    _euccCurrentStatus = status;
129  }
130
131  Drupal.eu_cookie_compliance.execute = function () {
132    try {
133      if (!drupalSettings.eu_cookie_compliance.popup_enabled) {
134        return;
135      }
136
137      if (!Drupal.eu_cookie_compliance.cookiesEnabled()) {
138        return;
139      }
140
141      if (!drupalSettings.eu_cookie_compliance.modules_allow_popup) {
142        return;
143      }
144
145      _euccCurrentStatus = Drupal.eu_cookie_compliance.getCurrentStatus();
146
147      if (typeof Drupal.eu_cookie_compliance.getVersion() === 'undefined') {
148        // If version doesn't exist as a cookie, set it to a default one.
149        // For sites who update to this version of the module, it helps to
150        // re-trigger the popup in case you switched to category based consent.
151        // For first time runs, it makes no difference as the other IF statements
152        // below will still cause the popup to trigger
153        // For incrementing the version, it also makes no difference as either it's
154        // a returning user and will have a version set, or it's a new user and
155        // the other checks will trigger it.
156        Drupal.eu_cookie_compliance.setVersion("unknown");
157      }
158
159      if (drupalSettings.eu_cookie_compliance.popup_eu_only === true && drupalSettings.eu_cookie_compliance.geoip_match !== true) {
160        return;
161      }
162
163      var versionChanged = Drupal.eu_cookie_compliance.getVersion() !== drupalSettings.eu_cookie_compliance.cookie_policy_version;
164
165      // Closed if status has a value and the version hasn't changed or user has not agreed.
166      var cookieName = (typeof drupalSettings.eu_cookie_compliance.cookie_name === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_name === '') ? 'cookie-agreed' : drupalSettings.eu_cookie_compliance.cookie_name;
167      var closed = !drupalSettings.eu_cookie_compliance.open_by_default ||
168        (_euccCurrentStatus !== null && !versionChanged || (getCookie(cookieName) === 'null' && drupalSettings.eu_cookie_compliance.settings_tab_enabled));
169
170      // Only worried about OPT_IN / GDPR method at present for the perm. settings tab.
171      if (_euccCurrentStatus === cookieValueDisagreed && drupalSettings.eu_cookie_compliance.settings_tab_enabled && (drupalSettings.eu_cookie_compliance.method === 'opt_in' || drupalSettings.eu_cookie_compliance.method === 'categories')) {
172         Drupal.eu_cookie_compliance.createPopup(drupalSettings.eu_cookie_compliance.popup_html_info, (_euccCurrentStatus !== null));
173         $('.eu-cookie-withdraw-tab').click(Drupal.eu_cookie_compliance.toggleWithdrawBanner);
174         Drupal.eu_cookie_compliance.attachAgreeEvents();
175      }
176      else if ((_euccCurrentStatus === cookieValueDisagreed && drupalSettings.eu_cookie_compliance.method === 'default') || _euccCurrentStatus === null || (_euccCurrentStatus !== cookieValueDisagreed && drupalSettings.eu_cookie_compliance.withdraw_enabled && drupalSettings.eu_cookie_compliance.withdraw_button_on_info_popup) || (_euccCurrentStatus !== cookieValueDisagreed && versionChanged)) {
177        if (drupalSettings.eu_cookie_compliance.withdraw_enabled || !drupalSettings.eu_cookie_compliance.disagree_do_not_show_popup || _euccCurrentStatus === null) {
178          // Detect mobile here and use mobile_popup_html_info, if we have a mobile device.
179          if (window.matchMedia('(max-width: ' + drupalSettings.eu_cookie_compliance.mobile_breakpoint + 'px)').matches && drupalSettings.eu_cookie_compliance.use_mobile_message) {
180            Drupal.eu_cookie_compliance.createPopup(drupalSettings.eu_cookie_compliance.mobile_popup_html_info, closed);
181          }
182          else {
183            Drupal.eu_cookie_compliance.createPopup(drupalSettings.eu_cookie_compliance.popup_html_info, closed);
184          }
185          Drupal.eu_cookie_compliance.initPopup();
186          Drupal.eu_cookie_compliance.resizeListener();
187        }
188      }
189      else if (_euccCurrentStatus === cookieValueAgreedShowThankYou && drupalSettings.eu_cookie_compliance.popup_agreed_enabled) {
190        // Thank you banner.
191        Drupal.eu_cookie_compliance.createPopup(drupalSettings.eu_cookie_compliance.popup_html_agreed);
192        Drupal.eu_cookie_compliance.attachHideEvents();
193      }
194      else if (_euccCurrentStatus === cookieValueAgreed && drupalSettings.eu_cookie_compliance.withdraw_enabled) {
195        if (!drupalSettings.eu_cookie_compliance.withdraw_button_on_info_popup) {
196          Drupal.eu_cookie_compliance.createWithdrawBanner(drupalSettings.eu_cookie_compliance.withdraw_markup);
197          Drupal.eu_cookie_compliance.initPopup();
198          Drupal.eu_cookie_compliance.resizeListener();
199        }
200      }
201    }
202    catch (e) {
203    }
204  };
205
206  Drupal.eu_cookie_compliance.initPopup = function () {
207    Drupal.eu_cookie_compliance.attachAgreeEvents();
208
209    if (drupalSettings.eu_cookie_compliance.method === 'categories') {
210      Drupal.eu_cookie_compliance.setPreferenceCheckboxes(_euccSelectedCategories);
211      Drupal.eu_cookie_compliance.attachSavePreferencesEvents();
212    }
213
214    if (drupalSettings.eu_cookie_compliance.withdraw_enabled) {
215      Drupal.eu_cookie_compliance.attachWithdrawEvents();
216      if (_euccCurrentStatus === cookieValueAgreedShowThankYou || _euccCurrentStatus === cookieValueAgreed) {
217        $('.eu-cookie-withdraw-button').removeClass('visually-hidden');
218        $('.eu-cookie-compliance-reject-button').addClass('visually-hidden');
219      }
220    }
221  }
222
223  Drupal.eu_cookie_compliance.positionTab = function () {
224    if (drupalSettings.eu_cookie_compliance.popup_position) {
225      let totalHeight = $('.eu-cookie-withdraw-tab').outerHeight();
226      if ($('#sliding-popup').length) {
227        totalHeight += $('#sliding-popup').outerHeight();
228      }
229      if ($('.eu-cookie-withdraw-wrapper').length) {
230        $('.eu-cookie-withdraw-tab').css('margin-top', '0');
231      }
232      else {
233        $('.eu-cookie-withdraw-tab').css('margin-top', totalHeight + 'px');
234      }
235    }
236  };
237
238  Drupal.eu_cookie_compliance.createWithdrawBanner = function (html) {
239    var $html = $('<div></div>').html(html);
240    var $banner = $('.eu-cookie-withdraw-banner', $html);
241    $html.attr({
242      'id': 'sliding-popup',
243      'role': 'alertdialog',
244      'aria-describedby': 'popup-text',
245      'aria-label': Drupal.t('Cookie compliance banner'),
246    });
247    $html.addClass('eu-cookie-withdraw-wrapper');
248
249    $html.trigger('eu_cookie_compliance_popup_close');
250
251    if (!drupalSettings.eu_cookie_compliance.popup_use_bare_css && !drupalSettings.eu_cookie_compliance.popup_use_olivero_css) {
252      $banner.height(drupalSettings.eu_cookie_compliance.popup_height)
253          .width(drupalSettings.eu_cookie_compliance.popup_width);
254    }
255    $html.hide();
256    var height = 0;
257    if (drupalSettings.eu_cookie_compliance.popup_position) {
258      $html.prependTo(drupalSettings.eu_cookie_compliance.containing_element);
259      height = parseInt($html.outerHeight());
260
261      $html.show()
262          .addClass('sliding-popup-top')
263          .addClass('clearfix')
264        .css({ top: Drupal.eu_cookie_compliance.getBannerTopHiddenPosition(height)});
265      // For some reason, the tab outerHeight is -10 if we don't use a timeout
266      // function to reveal the tab.
267      setTimeout(function () {
268        var height = $html.outerHeight();
269
270        $html.animate({ top: Drupal.eu_cookie_compliance.getBannerTopHiddenPosition(height) }, drupalSettings.eu_cookie_compliance.popup_delay, null);
271        if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
272          $('body').animate({ 'margin-top': -height + 'px' });
273        }
274      }.bind($html), 0);
275    }
276    else {
277      if (drupalSettings.eu_cookie_compliance.better_support_for_screen_readers) {
278        $html.prependTo(drupalSettings.eu_cookie_compliance.containing_element);
279      }
280      else {
281        $html.appendTo(drupalSettings.eu_cookie_compliance.containing_element);
282      }
283      height = $html.outerHeight();
284      $html.show()
285          .addClass('sliding-popup-bottom')
286          .css({ bottom: -1 * height });
287      // For some reason, the tab outerHeight is -10 if we don't use a timeout
288      // function to reveal the tab.
289      setTimeout(function () {
290        var height = $html.outerHeight();
291
292        $html.animate({ bottom: -1 * (height) }, drupalSettings.eu_cookie_compliance.popup_delay, null);
293      }.bind($html), 0);
294    }
295    $('body').removeClass('eu-cookie-compliance-popup-open');
296    $banner
297        .attr('aria-hidden', true)
298        .find('a, button, input')
299        .attr('tabindex', -1);
300  };
301
302  Drupal.eu_cookie_compliance.getBannerTopPosition = function (height) {
303    let bannerTopPosition;
304    if (drupalSettings.eu_cookie_compliance.fixed_top_position) {
305      bannerTopPosition = 0;
306    }
307    else {
308      return 0;
309    }
310
311    if ($('.toolbar-tray-horizontal.is-active').length) {
312      bannerTopPosition += parseInt($('.toolbar-tray-horizontal.is-active').css('height'));
313    }
314
315    if ($('.toolbar-bar').length && !$('#gin-toolbar-bar').length) {
316      bannerTopPosition += parseInt($('.toolbar-bar').css('height'));
317    }
318
319    return bannerTopPosition + 'px';
320  }
321
322  Drupal.eu_cookie_compliance.getBannerTopHiddenPosition = function (height) {
323    let bannerTopPosition = 0;
324    if (drupalSettings.eu_cookie_compliance.fixed_top_position) {
325      bannerTopPosition = -height;
326    }
327    else {
328      if ($('.toolbar-tray-horizontal.is-active').length) {
329        bannerTopPosition = -parseInt($('.toolbar-tray-horizontal.is-active').css('height'));
330      }
331
332      if ($('.toolbar-bar').length && !$('#gin-toolbar-bar').length) {
333        bannerTopPosition -= parseInt($('.toolbar-bar').css('height'));
334      }
335    }
336
337    return bannerTopPosition + 'px';
338  }
339
340  Drupal.eu_cookie_compliance.getBannerBottomHiddenPosition = function () {
341    return -($('#sliding-popup').outerHeight()) + 'px';
342  }
343
344  Drupal.eu_cookie_compliance.toggleWithdrawBanner = function () {
345    var $wrapper = $('#sliding-popup');
346    var height = parseInt($wrapper.outerHeight());
347    var bannerIsShowing = ($wrapper.find('.eu-cookie-compliance-banner, .eu-cookie-withdraw-banner').is(':visible'));
348    if (bannerIsShowing) {
349      let bannerTop = parseInt($wrapper.css('top'));
350      let containerPadding = parseInt($(drupalSettings.eu_cookie_compliance.containing_element).css('padding-top'));
351      let containerMargin = parseInt($(drupalSettings.eu_cookie_compliance.containing_element).css('margin-top'));
352
353      if (drupalSettings.eu_cookie_compliance.popup_position) {
354        if (drupalSettings.eu_cookie_compliance.fixed_top_position) {
355          bannerIsShowing = !(bannerTop === -height);
356        }
357        else {
358          bannerIsShowing = !(bannerTop === -(containerPadding + containerMargin + he
358ight));
359        }
360      }
361      else {
362        bannerIsShowing = (parseInt($wrapper.css('bottom')) === 0);
363      }
364    }
365    if (drupalSettings.eu_cookie_compliance.popup_position) {
366      if (bannerIsShowing) {
367        if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
368          $('body').animate({ 'margin-top': -height + 'px' }, drupalSettings.eu_cookie_compliance.popup_delay);
369        }
370        $wrapper.animate({ top: Drupal.eu_cookie_compliance.getBannerTopHiddenPosition(height) }, drupalSettings.eu_cookie_compliance.popup_delay).trigger('eu_cookie_compliance_popup_close');
371      }
372      else {
373        // If "Do not show cookie policy when the user clicks the Cookie policy button." is
374        // selected, the inner banner may be hidden.
375        if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
376          $('body').animate({ 'margin-top': '0px' }, drupalSettings.eu_cookie_compliance.popup_delay);
377        }
378        $wrapper.find('.eu-cookie-compliance-banner').show();
379        $wrapper.animate({ top: Drupal.eu_cookie_compliance.getBannerTopPosition(height) }, drupalSettings.eu_cookie_compliance.popup_delay).trigger('eu_cookie_compliance_popup_open');
380      }
381    }
382    else {
383      if (bannerIsShowing) {
384        $wrapper.animate({ 'bottom': -1 * (height) }, drupalSettings.eu_cookie_compliance.popup_delay).trigger('eu_cookie_compliance_popup_close');
385      }
386      else {
387        // If "Do not show cookie policy when the user clicks the Cookie policy button." is
388        // selected, the inner banner may be hidden.
389        $wrapper.find('.eu-cookie-compliance-banner').show();
390        $wrapper.animate({ 'bottom': 0 }, drupalSettings.eu_cookie_compliance.popup_delay).trigger('eu_cookie_compliance_popup_open');
391      }
392    }
393    if (bannerIsShowing) {
394      $('body').removeClass('eu-cookie-compliance-popup-open');
395      $('.eu-cookie-compliance-banner, .eu-cookie-withdraw-banner')
396          .attr('aria-hidden', true)
397          .find('a, button, input')
398          .attr('tabindex', -1);
399    }
400    else {
401      $('body').addClass('eu-cookie-compliance-popup-open');
402      $('.eu-cookie-compliance-banner, .eu-cookie-withdraw-banner')
403          .attr('aria-hidden', false)
404          .find('a, button, input')
405          .attr('tabindex', 0);
406    }
407  };
408
409  Drupal.eu_cookie_compliance.resizeListener = function () {
410    var $wrapper = $('#sliding-popup');
411
412    var debounce = function (func, wait) {
413      var timeout;
414
415      return function executedFunction() {
416        var later = function () {
417          clearTimeout(timeout);
418          func();
419        };
420
421        clearTimeout(timeout);
422        timeout = setTimeout(later, wait);
423      };
424    };
425
426    var checkIfPopupIsClosed = debounce(function () {
427      var wrapperHeight = $wrapper.outerHeight();
428      if (drupalSettings.eu_cookie_compliance.popup_position) {
429        var wrapperTopProperty = parseFloat($wrapper.css('top'));
430        if (wrapperTopProperty < 0) {
431          if ($('body').hasClass('eu-cookie-compliance-popup-open')) {
432            if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
433              $('body').css({ 'margin-top': '0px' });
434            }
435            $wrapper.css('top', Drupal.eu_cookie_compliance.getBannerTopPosition(wrapperHeight));
436          }
437          else {
438            if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
439              $('body').css({ 'margin-top': -wrapperHeight + 'px' });
440            }
441            $wrapper.css('top', Drupal.eu_cookie_compliance.getBannerTopHiddenPosition(wrapperHeight));
442          }
443        }
444        Drupal.eu_cookie_compliance.positionTab();
445      }
446      else {
447        var wrapperBottomProperty = parseFloat($wrapper.css('bottom'));
448        if (wrapperBottomProperty !== 0) {
449          $wrapper.css('bottom', wrapperHeight * -1);
450        }
451      }
452      Drupal.eu_cookie_compliance.positionTab();
453    }, 50);
454
455    setTimeout(function () {
456      checkIfPopupIsClosed();
457    });
458
459    window.addEventListener('resize', checkIfPopupIsClosed);
460  };
461
462  Drupal.eu_cookie_compliance.createPopup = function (html, closed) {
463    // This fixes a problem with jQuery 1.9.
464    var popup = $('<div></div>').html(html);
465    popup.attr({
466      'id': 'sliding-popup',
467      'role': 'alertdialog',
468      'aria-describedby': 'popup-text',
469      'aria-label': Drupal.t('Cookie compliance banner'),
470    });
471    if (!drupalSettings.eu_cookie_compliance.popup_use_bare_css && !drupalSettings.eu_cookie_compliance.popup_use_olivero_css) {
472      popup.height(drupalSettings.eu_cookie_compliance.popup_height)
473          .width(drupalSettings.eu_cookie_compliance.popup_width);
474    }
475
476    popup.hide();
477    var height = 0;
478    if (drupalSettings.eu_cookie_compliance.popup_position) {
479      popup.prependTo(drupalSettings.eu_cookie_compliance.containing_element);
480      height = popup.outerHeight();
481      popup.addClass('sliding-popup-top clearfix')
482        .css({ top: Drupal.eu_cookie_compliance.getBannerTopHiddenPosition(height) });
483
484      if (closed !== true) {
485        popup.show();
486        popup.animate({top: Drupal.eu_cookie_compliance.getBannerTopPosition(height)}, drupalSettings.eu_cookie_compliance.popup_delay, null, function () {
487          popup.trigger('eu_cookie_compliance_popup_open');
488          Drupal.eu_cookie_compliance.positionTab();
489        });
490      }
491      else {
492        if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
493          $('body').css({ 'margin-top': -height + 'px' });
494        }
495        setTimeout(function () {
496          popup.show();
497          Drupal.eu_cookie_compliance.positionTab();
498        }, 0);
499      }
500    }
501    else {
502      if (drupalSettings.eu_cookie_compliance.better_support_for_screen_readers) {
503        popup.prependTo(drupalSettings.eu_cookie_compliance.containing_element);
504      }
505      else {
506        popup.appendTo(drupalSettings.eu_cookie_compliance.containing_element);
507      }
508
509      height = popup.outerHeight();
510      popup.show()
511        .addClass('sliding-popup-bottom')
512        .css({bottom: -1 * height});
513
514      if (closed !== true) {
515        popup.animate({bottom: 0}, drupalSettings.eu_cookie_compliance.popup_delay, null, function () {
516          popup.trigger('eu_cookie_compliance_popup_open');
517        });
518      }
519    }
520    if (closed !== true) {
521      $('body').addClass('eu-cookie-compliance-popup-open');
522      $('.eu-cookie-compliance-banner, .eu-cookie-withdraw-banner')
523          .attr('aria-hidden', false)
524          .find('a, button, input')
525          .attr('tabindex', 0);
526    }
527    else {
528      $('body').removeClass('eu-cookie-compliance-popup-open');
529      $('.eu-cookie-compliance-banner, .eu-cookie-withdraw-banner')
530          .attr('aria-hidden', true)
531          .find('a, button, input')
532          .attr('tabindex', -1);
533    }
534  };
535
536  Drupal.eu_cookie_compliance.attachAgreeEvents = function () {
537    var clickingConfirms = drupalSettings.eu_cookie_compliance.popup_clicking_confirmation;
538    var scrollConfirms = drupalSettings.eu_cookie_compliance.popup_scrolling_confirmation;
539
540    if (drupalSettings.eu_cookie_compliance.method === 'categories' && drupalSettings.eu_cookie_compliance.enable_save_preferences_button) {
541        // The agree button becomes an agree to all categories button when the 'save preferences' button is present.
542        $('.agree-button').click(Drupal.eu_cookie_compliance.acceptAllAction);
543    }
544    else {
545        $('.agree-button').click(Drupal.eu_cookie_compliance.acceptAction);
546    }
547    $('.decline-button').click(Drupal.eu_cookie_compliance.declineAction);
548    $('.eu-cookie-compliance-close-button').click(Drupal.eu_cookie_compliance.closeAction);
549    $('.eu-cookie-compliance-reject-button').click(Drupal.eu_cookie_compliance.rejectAllAction);
550
551    if (clickingConfirms) {
552      $('a, input[type=submit], button[type=submit]').not('.popup-content *').bind('click.euCookieCompliance', Drupal.eu_cookie_compliance.acceptAction);
553    }
554
555    if (scrollConfirms) {
556      var alreadyScrolled = false;
557      var scrollHandler = function () {
558        if (alreadyScrolled) {
559          Drupal.eu_cookie_compliance.acceptAction();
560          $(window).off('scroll', scrollHandler);
561        }
562        else {
563          alreadyScrolled = true;
564        }
565      };
566
567      $(window).bind('scroll', scrollHandler);
568    }
569
570    $('.find-more-button').not('.find-more-button-processed').addClass('find-more-button-processed').click(Drupal.eu_cookie_compliance.moreInfoAction);
571  };
572
573  Drupal.eu_cookie_compliance.closeAction = function () {
574    switch (drupalSettings.eu_cookie_compliance.close_button_action) {
575      case 'close_banner':
576        Drupal.eu_cookie_compliance.toggleWithdrawBanner();
577        break;
578
579      case 'save_preferences':
580        Drupal.eu_cookie_compliance.savePreferencesAction();
581        break;
582
583      case 'reject_all_cookies':
584        Drupal.eu_cookie_compliance.rejectAllAction();
585        break;
586
587      case 'accept_all_cookies':
588        Drupal.eu_cookie_compliance.acceptAllAction();
589        break;
590    }
591  };
592
593  Drupal.eu_cookie_compliance.attachSavePreferencesEvents = function () {
594    $('.eu-cookie-compliance-save-preferences-button').click(Drupal.eu_cookie_compliance.savePreferencesAction);
595  };
596
597  Drupal.eu_cookie_compliance.attachHideEvents = function () {
598    var popupHideAgreed = drupalSettings.eu_cookie_compliance.popup_hide_agreed;
599    var clickingConfirms = drupalSettings.eu_cookie_compliance.popup_clicking_confirmation;
600    $('.hide-popup-button').click(function () {
601          Drupal.eu_cookie_compliance.changeStatus(cookieValueAgreed);
602        }
603    );
604    if (clickingConfirms) {
605      $('a, input[type=submit], button[type=submit]').unbind('click.euCookieCompliance');
606    }
607
608    if (popupHideAgreed) {
609      $('a, input[type=submit], button[type=submit]').bind('click.euCookieComplianceHideAgreed', function () {
610        Drupal.eu_cookie_compliance.changeStatus(cookieValueAgreed);
611      });
612    }
613
614    $('.find-more-button').not('.find-more-button-processed').addClass('find-more-button-processed').click(Drupal.eu_cookie_compliance.moreInfoAction);
615  };
616
617  Drupal.eu_cookie_compliance.attachWithdrawEvents = function () {
618    $('.eu-cookie-withdraw-button').click(Drupal.eu_cookie_compliance.withdrawAction);
619    $('.eu-cookie-withdraw-tab').click(Drupal.eu_cookie_compliance.toggleWithdrawBanner);
620  };
621
622  Drupal.eu_cookie_compliance.acceptAction = function () {
623    var agreedEnabled = drupalSettings.eu_cookie_compliance.popup_agreed_enabled;
624    var nextStatus = cookieValueAgreedShowThankYou;
625    if (!agreedEnabled) {
626      Drupal.eu_cookie_compliance.setStatus(cookieValueAgreedShowThankYou);
627      nextStatus = cookieValueAgreed;
628    }
629
630    if (!euCookieComplianceHasLoadedScripts && typeof euCookieComplianceLoadScripts === "function") {
631      euCookieComplianceLoadScripts();
632    }
633
634    if (typeof euCookieComplianceBlockCookies !== 'undefined') {
635      clearInterval(euCookieComplianceBlockCookies);
636    }
637
638    if (drupalSettings.eu_cookie_compliance.method === 'categories') {
639      // Select Checked categories.
640      var categories = $("#eu-cookie-compliance-categories input:checkbox:checked").map(function () {
641        return $(this).val();
642      }).get();
643      Drupal.eu_cookie_compliance.setAcceptedCategories(categories);
644      // Load scripts for all categories. If no categories selected, none
645      // will be loaded.
646      Drupal.eu_cookie_compliance.loadCategoryScripts(categories);
647      if (!categories.length) {
648        // No categories selected is the same as declining all cookies.
649        nextStatus = cookieValueDisagreed;
650      }
651    }
652
653    Drupal.eu_cookie_compliance.changeStatus(nextStatus);
654
655    if (drupalSettings.eu_cookie_compliance.withdraw_enabled && drupalSettings.eu_cookie_compliance.withdraw_button_on_info_popup) {
656      Drupal.eu_cookie_compliance.attachWithdrawEvents();
657      if (_euccCurrentStatus === cookieValueAgreedShowThankYou || _euccCurrentStatus === cookieValueAgreed) {
658        $('.eu-cookie-withdraw-button').removeClass('visually-hidden');
659        $('.eu-cookie-compliance-reject-button').addClass('visually-hidden');
660      }
661    }
662  };
663
664  Drupal.eu_cookie_compliance.acceptAllAction = function () {
665    var allCategories = drupalSettings.eu_cookie_compliance.cookie_categories;
666    Drupal.eu_cookie_compliance.setPreferenceCheckboxes(allCategories);
667    Drupal.eu_cookie_compliance.acceptAction();
668  }
669
670  Drupal.eu_cookie_compliance.rejectAllAction = function () {
671    Drupal.eu_cookie_compliance.setStatus(cookieValueDisagreed);
672    Drupal.eu_cookie_compliance.setPreferenceCheckboxes([]);
673    Drupal.eu_cookie_compliance.acceptAction();
674  }
675
676  Drupal.eu_cookie_compliance.savePreferencesAction = function () {
677    var categories = $("#eu-cookie-compliance-categories input:checkbox:checked").map(function () {
678      return $(this).val();
679    }).get();
680    var agreedEnabled = drupalSettings.eu_cookie_compliance.popup_agreed_enabled;
681    var nextStatus = cookieValueAgreedShowThankYou;
682    if (!agreedEnabled) {
683      Drupal.eu_cookie_compliance.setStatus(cookieValueAgreedShowThankYou);
684      nextStatus = cookieValueAgreed;
685    }
686
687    /* Necessary to keep the euCookieComplianceLoadScripts() load order consistent on page load. */
688    if (!euCookieComplianceHasLoadedScripts && typeof euCookieComplianceLoadScripts === "function") {
689      euCookieComplianceLoadScripts();
690    }
691    euCookieComplianceHasLoadedScripts = true;
692
693    Drupal.eu_cookie_compliance.setAcceptedCategories(categories);
694    // Load scripts for all categories. If no categories selected, none
695    // will be loaded.
696    Drupal.eu_cookie_compliance.loadCategoryScripts(categories);
697    if (!categories.length) {
698      // No categories selected is the same as declining all cookies.
699      nextStatus = cookieValueDisagreed;
700    }
701
702    Drupal.eu_cookie_compliance.changeStatus(nextStatus);
703  };
704
705  Drupal.eu_cookie_compliance.loadCategoryScripts = function (categories) {
706    for (var cat in categories) {
707      if (euCookieComplianceHasLoadedScriptsForCategory[categories[cat]] !== true && typeof euCookieComplianceLoadScripts === "function") {
708        euCookieComplianceLoadScripts(categories[cat]);
709        euCookieComplianceHasLoadedScriptsForCategory[categories[cat]] = true;
710      }
711    }
712  }
713
714  Drupal.eu_cookie_compliance.declineAction = function () {
715    var set_cookie_session_zero_on_disagree = parseInt(drupalSettings.eu_cookie_compliance.set_cookie_session_zero_on_disagree);
716    if (set_cookie_session_zero_on_disagree) {
717      drupalSettings.eu_cookie_compliance.cookie_session = 1;
718    }
719    Drupal.eu_cookie_compliance.setStatus(cookieValueDisagreed);
720    var popup = $('#sliding-popup');
721    if (popup.hasClass('sliding-popup-top')) {
722      let height = popup.outerHeight();
723      if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
724        $('body').animate({ 'margin-top': -height + 'px' }, drupalSettings.eu_cookie_compliance.popup_delay);
725      }
726      if (drupalSettings.eu_cookie_compliance.settings_tab_enabled) {
727        popup.animate({top: Drupal.eu_cookie_compliance.getBannerTopHiddenPosition(height)}, drupalSettings.eu_cookie_compliance.popup_delay, null).trigger('eu_cookie_compliance_popup_close');
728      }
729      else {
730        popup.animate({top: Drupal.eu_cookie_compliance.getBannerTopHiddenPosition(height)}, drupalSettings.eu_cookie_compliance.popup_delay, null, function () {
731          if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
732            $('body').css({ 'margin-top': 0 });
733          }
734          popup.hide();
735        }).trigger('eu_cookie_compliance_popup_close');
736      }
737    }
738    else {
739      if (drupalSettings.eu_cookie_compliance.settings_tab_enabled) {
740        popup.animate({ bottom: popup.outerHeight() * -1 }, drupalSettings.eu_cookie_compliance.popup_delay, null).trigger('eu_cookie_compliance_popup_close');
741      }
742      else {
743        popup.animate({ bottom: popup.outerHeight() * -1 }, drupalSettings.eu_cookie_compliance.popup_delay, null, function () {
744          popup.hide();
745        }).trigger('eu_cookie_compliance_popup_close');
746      }
747    }
748    $('body').removeClass('eu-cookie-compliance-popup-open');
749    $('.eu-cookie-compliance-banner, .eu-cookie-withdraw-banner')
750        .attr('aria-hidden', true)
751        .find('a, button, input')
752        .attr('tabindex', -1);
753  };
754
755  Drupal.eu_cookie_compliance.withdrawAction = function () {
756    var set_cookie_session_zero_on_disagree = parseInt(drupalSettings.eu_cookie_compliance.set_cookie_session_zero_on_disagree);
757    if (set_cookie_session_zero_on_disagree) {
758      drupalSettings.eu_cookie_compliance.cookie_session = 1;
759    }
760    Drupal.eu_cookie_compliance.setStatus(null);
761    Drupal.eu_cookie_compliance.setAcceptedCategories([]);
762    location.reload();
763  };
764
765  Drupal.eu_cookie_compliance.moreInfoAction = function () {
766    if (drupalSettings.eu_cookie_compliance.disagree_do_not_show_popup) {
767      Drupal.eu_cookie_compliance.setStatus(cookieValueDisagreed);
768      if (drupalSettings.eu_cookie_compliance.withdraw_enabled && drupalSettings.eu_cookie_compliance.withdraw_button_on_info_popup) {
769        $('#sliding-popup .eu-cookie-compliance-banner').trigger('eu_cookie_compliance_popup_close').hide();
770      }
771      else {
772        $('#sliding-popup').trigger('eu_cookie_compliance_popup_close').remove();
773      }
774      $('body').removeClass('eu-cookie-compliance-popup-open');
775      $('.eu-cookie-compliance-banner, .eu-cookie-withdraw-banner')
776          .attr('aria-hidden', true)
777          .find('a, button, input')
778          .attr('tabindex', -1);
779    }
780    else {
781      if (drupalSettings.eu_cookie_compliance.popup_link_new_window) {
782        window.open(drupalSettings.eu_cookie_compliance.popup_link);
783      }
784      else {
785        window.location.href = drupalSettings.eu_cookie_compliance.popup_link;
786      }
787    }
788  };
789
790  Drupal.eu_cookie_compliance.getCookieStatus = function () {
791    var cookieName = (typeof drupalSettings.eu_cookie_compliance.cookie_name === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_name === '') ? 'cookie-agreed' : drupalSettings.eu_cookie_compliance.cookie_name;
792    var currentStatus = getCookie(cookieName);
793    if (typeof currentStatus === 'undefined' || currentStatus === 'null') {
794      currentStatus = null;
795    }
796    return currentStatus;
797  }
798
799  Drupal.eu_cookie_compliance.getCurrentStatus = function () {
800    // Make a new observer & fire it to allow other scripts to hook in.
801    var preStatusLoadObject = new PreStatusLoad();
802    self.handleEvent('preStatusLoad', preStatusLoadObject);
803
804    _euccCurrentStatus = Drupal.eu_cookie_compliance.getCookieStatus();
805
806    // Make a new observer & fire it to allow other scripts to hook in.
807    var postStatusLoadObject = new PostStatusLoad();
808    self.handleEvent('postStatusLoad', postStatusLoadObject);
809
810    return _euccCurrentStatus;
811  };
812
813  Drupal.eu_cookie_compliance.setPreferenceCheckboxes = function (categories) {
814    if (Drupal.eu_cookie_compliance.getCookieStatus() !== null || Drupal.eu_cookie_compliance.getCookieStatus() === cookieValueDisagreed) {
815      // Unset all categories to prevent a problem where the checkboxes with a
816      // default state set would always show up as checked.
817      $("#eu-cookie-compliance-categories input:checkbox").not(":disabled").prop("checked", false);
818    }
819    // Check the appropriate checkboxes.
820    for (var i in categories) {
821      var categoryElement = document.getElementById('cookie-category-' + categories[i]);
822      if (categoryElement !== null) {
823        categoryElement.checked = true;
824      }
825    }
826  }
827
828  Drupal.eu_cookie_compliance.getAcceptedCategories = function () {
829    // Make a new observer & fire it to allow other scripts to hook in.
830    var prePreferencesLoadObject = new PrePreferencesLoad();
831    self.handleEvent('prePreferencesLoad', prePreferencesLoadObject);
832
833    var cookieName = (typeof drupalSettings.eu_cookie_compliance.cookie_name === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_name === '') ? 'cookie-agreed-categories' : drupalSettings.eu_cookie_compliance.cookie_name + '-categories';
834    var storedCategories = getCookie(cookieName);
835
836    if (storedCategories !== null && typeof storedCategories !== 'undefined') {
837      // JS cookie introduced unescaped cookie values.
838      if (storedCategories.indexOf('%') !== -1) {
839        storedCategories = decodeURI(storedCategories).replaceAll(/%2C/g, ',');
840      }
841      _euccSelectedCategories = JSON.parse(storedCategories);
842    }
843    else {
844      _euccSelectedCategories = [];
845    }
846
847    // Merge in required categories if not already present. Mimics old
848    // logic where "fix first category" changed logic in
849    // .hasAgreedWithCategory and this function.
850    for (var _categoryName in drupalSettings.eu_cookie_compliance.cookie_categories_details) {
851      var _category = drupalSettings.eu_cookie_compliance.cookie_categories_details[_categoryName];
852      if (_category.checkbox_default_state === 'required' && $.inArray(_category.id, _euccSelectedCategories) === -1) {
853        _euccSelectedCategories.push(_category.id);
854      }
855    }
856
857    // Make a new observer & fire it to allow other scripts to hook in.
858    var postPreferencesLoadObject = new PostPreferencesLoad();
859    self.handleEvent('postPreferencesLoad', postPreferencesLoadObject);
860
861    return _euccSelectedCategories;
862  };
863
864  Drupal.eu_cookie_compliance.changeStatus = function (value) {
865    var reloadPage = drupalSettings.eu_cookie_compliance.reload_page;
866    var previousState = _euccCurrentStatus;
867    if (_euccCurrentStatus === parseInt(value)) {
868      return;
869    }
870
871    if (drupalSettings.eu_cookie_compliance.popup_position) {
872      let height = $('#sliding-popup').outerHeight();
873      if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
874        $('body').animate({ 'margin-top': -height + 'px' }, drupalSettings.eu_cookie_compliance.popup_delay);
875      }
876      $('.sliding-popup-top').animate({ top: Drupal.eu_cookie_compliance.getBannerTopHiddenPosition(height) }, drupalSettings.eu_cookie_compliance.popup_delay, function () {
877        if (value === cookieValueAgreedShowThankYou && previousState === null && !reloadPage) {
878          if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
879            $('body').animate({ 'margin-top': '0px' }, drupalSettings.eu_cookie_compliance.popup_delay);
880          }
881          $('.sliding-popup-top').not('.eu-cookie-withdraw-wrapper').html(drupalSettings.eu_cookie_compliance.popup_html_agreed).animate({ top: Drupal.eu_cookie_compliance.getBannerTopPosition(height) }, drupalSettings.eu_cookie_compliance.popup_delay);
882          Drupal.eu_cookie_compliance.attachHideEvents();
883        }
884        else if (previousState === cookieValueAgreedShowThankYou) {
885          if (drupalSettings.eu_cookie_compliance.withdraw_enabled && drupalSettings.eu_cookie_compliance.withdraw_button_on_info_popup) {
886            $('#sliding-popup').hide();
887            // Restore popup content.
888            if (window.matchMedia('(max-width: ' + drupalSettings.eu_cookie_compliance.mobile_breakpoint + 'px)').matches && drupalSettings.eu_cookie_compliance.use_mobile_message) {
889              $('.sliding-popup-top').not('.eu-cookie-withdraw-wrapper').html(drupalSettings.eu_cookie_compliance.mobile_popup_html_info);
890            }
891            else {
892              $('.sliding-popup-top').not('.eu-cookie-withdraw-wrapper').html(drupalSettings.eu_cookie_compliance.popup_html_info);
893            }
894            height = $('#sliding-popup').outerHeight();
895            if (!drupalSettings.eu_cookie_compliance.fixed_top_position) {
896              $('body').animate({ 'margin-top': -height + 'px' }, drupalSettings.eu_cookie_compliance.popup_delay);
897            }
898            $('.sliding-popup-top').css('top', Drupal.eu_cookie_compliance.getBannerTopHiddenPosition(height));
899            $('.sliding-popup-top').not('.eu-cookie-withdraw-wrapper').trigger('eu_cookie_compliance_popup_close');
900            Drupal.eu_cookie_compliance.initPopup();
901            Drupal.eu_cookie_compliance.resizeListener();
902            $('#sliding-popup').show();
903          }
904          else {
905            $('.sliding-popup-top').not('.eu-cookie-withdraw-wrapper').trigger('eu_cookie_compliance_popup_close').remove();
906            $('body').css({ 'margin-top': '0px' });
907          }
908          $('body').removeClass('eu-cookie-compliance-popup-open');
909          $('.eu-cookie-compliance-banner, .eu-cookie-withdraw-banner')
910              .attr('aria-hidden', true)
911              .find('a, button, input')
912              .attr('tabindex', -1);
913        }
914        if (drupalSettings.eu_cookie_compliance.withdraw_enabled && !drupalSettings.eu_cookie_compliance.withdraw_button_on_info_popup) {
915          Drupal.eu_cookie_compliance.showWithdrawBanner(value);
916        }
917      });
918    }
919    else {
920      $('.sliding-popup-bottom').animate({ bottom: $('#sliding-popup').outerHeight() * -1 }, drupalSettings.eu_cookie_compliance.popup_delay, function () {
921        if (value === cookieValueAgreedShowThankYou && previousState === null && !reloadPage) {
922          $('.sliding-popup-bottom').not('.eu-cookie-withdraw-wrapper').html(drupalSettings.eu_cookie_compliance.popup_html_agreed).animate({ bottom: 0 }, drupalSettings.eu_cookie_compliance.popup_delay);
923          Drupal.eu_cookie_compliance.attachHideEvents();
924        }
925        else if (previousState === cookieValueAgreedShowThankYou) {
926          $('#sliding-popup').css('display', 'none');
927          if (drupalSettings.eu_cookie_compliance.withdraw_enabled && drupalSettings.eu_cookie_compliance.withdraw_button_on_info_popup) {
928            // Restore popup content.
929            if (window.matchMedia('(max-width: ' + drupalSettings.eu_cookie_compliance.mobile_breakpoint + 'px)').matches && drupalSettings.eu_cookie_compliance.use_mobile_message) {
930              $('.sliding-popup-bottom').not('.eu-cookie-withdraw-wrapper').html(drupalSettings.eu_cookie_compliance.mobile_popup_html_info);
931            }
932            else {
933              $('.sliding-popup-bottom').not('.eu-cookie-withdraw-wrapper').html(drupalSettings.eu_cookie_compliance.popup_html_info);
934            }
935            $('.sliding-popup-bottom').css('bottom', Drupal.eu_cookie_compliance.getBannerBottomHiddenPosition());
936            $('.sliding-popup-bottom').not('.eu-cookie-withdraw-wrapper').trigger('eu_cookie_compliance_popup_close');
937            Drupal.eu_cookie_compliance.initPopup();
938            Drupal.eu_cookie_compliance.resizeListener();
939            $('#sliding-popup').css('display', 'block');
940          }
941          else {
942            $('.sliding-popup-bottom').not('.eu-cookie-withdraw-wrapper').trigger('eu_cookie_compliance_popup_close').remove();
943          }
944          $('body').removeClass('eu-cookie-compliance-popup-open');
945          $('.eu-cookie-compliance-banner, .eu-cookie-withdraw-banner')
946              .attr('aria-hidden', true)
947              .find('a, button, input')
948              .attr('tabindex', -1);
949        }
950        if (drupalSettings.eu_cookie_compliance.withdraw_enabled && !drupalSettings.eu_cookie_compliance.withdraw_button_on_info_popup) {
951          Drupal.eu_cookie_compliance.showWithdrawBanner(value);
952        }
953      });
954    }
955
956    if (drupalSettings.eu_cookie_compliance.reload_page) {
957      var reloadRoutesList;
958      // Checks if there's any route on the settings.
959      if ((reloadRoutesList = drupalSettings.eu_cookie_compliance.reload_routes_list).length !== 0) {
960        var currentPath = drupalSettings.path.currentPath;
961        var match = false;
962
963        // If there are routes specified on the settings, it checks if any of
964        // it matches with the current path.
965        for (var n = 0; !match && n < reloadRoutesList.length; n++) {
966          var regExp = new RegExp(reloadRoutesList[n], "g");
967          match = currentPath.match(regExp) !== null;
968        }
969
970        /*
971         * It will reload the page whether if the current path matches with one of the specified routes and the
972         * reload_options setting is set to "Include", which indicates that all matches should reload; OR if
973         * there's no match and the reload_options settings is set to "Exclude", which indicates that if the
974         * current path doesn't match with one of the specified routes, it should be reloaded.
975         */
976        if ((match && !drupalSettings.eu_cookie_compliance.reload_options) || (!match && drupalSettings.eu_cookie_compliance.reload_options)) {
977          location.reload();
978        }
979      }
980      // If no routes specified, then the page will be always reloaded.
981      else {
982        location.reload();
983      }
984    }
985
986    Drupal.eu_cookie_compliance.setStatus(value);
987  };
988
989  Drupal.eu_cookie_compliance.showWithdrawBanner = function (value) {
990    if (value === cookieValueAgreed && drupalSettings.eu_cookie_compliance.withdraw_enabled) {
991      if (!drupalSettings.eu_cookie_compliance.withdraw_button_on_info_popup) {
992        Drupal.eu_cookie_compliance.createWithdrawBanner(drupalSettings.eu_cookie_compliance.withdraw_markup);
993        Drupal.eu_cookie_compliance.resizeListener();
994      }
995      Drupal.eu_cookie_compliance.attachWithdrawEvents();
996      if (drupalSettings.eu_cookie_compliance.popup_position) {
997        Drupal.eu_cookie_compliance.positionTab();
998      }
999    }
1000  };
1001
1002  Drupal.eu_cookie_compliance.setStatus = function (status) {
1003    // Make a new observer & fire it to allow other scripts to hook in.
1004    var preStatusSaveObject = new PreStatusSave();
1005    self.handleEvent('preStatusSave', preStatusSaveObject);
1006
1007    var date = new Date();
1008    var domain = drupalSettings.eu_cookie_compliance.domain ? drupalSettings.eu_cookie_compliance.domain : '';
1009    var path = drupalSettings.eu_cookie_compliance.domain_all_sites ? '/' : drupalSettings.path.baseUrl;
1010    var cookieName = (typeof drupalSettings.eu_cookie_compliance.cookie_name === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_name === '') ? 'cookie-agreed' : drupalSettings.eu_cookie_compliance.cookie_name;
1011    if (path.length > 1) {
1012      var pathEnd = path.length - 1;
1013      if (path.lastIndexOf('/') === pathEnd) {
1014        path = path.substring(0, pathEnd);
1015      }
1016    }
1017
1018    var cookie_session = parseInt(drupalSettings.eu_cookie_compliance.cookie_session);
1019    if (cookie_session) {
1020      setCookie(cookieName, status, { path: path, domain: domain, sameSite: 'strict' });
1021    }
1022    else {
1023      var lifetime = parseInt(drupalSettings.eu_cookie_compliance.cookie_lifetime);
1024      date.setDate(date.getDate() + lifetime);
1025      setCookie(cookieName, status, { expires: date, path: path, domain: domain, sameSite: 'strict' });
1026    }
1027
1028    var currentStatusClass = 'eu-cookie-compliance-status-' + _euccCurrentStatus;
1029    var nextStatusClass = 'eu-cookie-compliance-status-' + status;
1030    $('.' + currentStatusClass).removeClass(currentStatusClass).addClass(nextStatusClass)
1031
1032    _euccCurrentStatus = status;
1033    $(document).trigger('eu_cookie_compliance.changeStatus', [status]);
1034    // Status set means something happened, update the version.
1035    Drupal.eu_cookie_compliance.setVersion();
1036
1037    // Store consent if applicable.
1038    if (drupalSettings.eu_cookie_compliance.store_consent && ((status === cookieValueAgreedShowThankYou && drupalSettings.eu_cookie_compliance.popup_agreed_enabled) || (status === cookieValueAgreed  && !drupalSettings.eu_cookie_compliance.popup_agreed_enabled))) {
1039      var url = drupalSettings.path.baseUrl + drupalSettings.path.pathPrefix + 'eu-cookie-compliance/store_consent/banner';
1040      $.post(url, {}, function (data) { });
1041    }
1042
1043    // Make a new observer & fire it to allow other scripts to hook in.
1044    var postStatusSaveObject = new PostStatusSave();
1045    self.handleEvent('postStatusSave', postStatusSaveObject);
1046
1047    if (status === cookieValueDisagreed && drupalSettings.eu_cookie_compliance.method === 'opt_out') {
1048      euCookieComplianceBlockCookies = setInterval(Drupal.eu_cookie_compliance.BlockCookies, 5000);
1049    }
1050  };
1051
1052  Drupal.eu_cookie_compliance.setAcceptedCategories = function (categories) {
1053    // Make a new observer & fire it to allow other scripts to hook in.
1054    var prePreferencesSaveObject = new PrePreferencesSave();
1055    self.handleEvent('prePreferencesSave', prePreferencesSaveObject);
1056
1057    var date = new Date();
1058    var domain = drupalSettings.eu_cookie_compliance.domain ? drupalSettings.eu_cookie_compliance.domain : '';
1059    var path = drupalSettings.eu_cookie_compliance.domain_all_sites ? '/' : drupalSettings.path.baseUrl;
1060    var cookieName = (typeof drupalSettings.eu_cookie_compliance.cookie_name === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_name === '') ? 'cookie-agreed-categories' : drupalSettings.eu_cookie_compliance.cookie_name + '-categories';
1061    if (path.length > 1) {
1062      var pathEnd = path.length - 1;
1063      if (path.lastIndexOf('/') === pathEnd) {
1064        path = path.substring(0, pathEnd);
1065      }
1066    }
1067    var categoriesString = JSON.stringify(categories);
1068    var cookie_session = parseInt(drupalSettings.eu_cookie_compliance.cookie_session);
1069    if (cookie_session) {
1070      setCookie(cookieName, categoriesString, { path: path, domain: domain, sameSite: 'strict' });
1071    }
1072    else {
1073      var lifetime = parseInt(drupalSettings.eu_cookie_compliance.cookie_lifetime);
1074      date.setDate(date.getDate() + lifetime);
1075      setCookie(cookieName, categoriesString, { expires: date, path: path, domain: domain, sameSite: 'strict' });
1076    }
1077    _euccSelectedCategories = categories;
1078    $(document).trigger('eu_cookie_compliance.changePreferences', [categories]);
1079
1080    // TODO: Store categories with consent if applicable?
1081    // Make a new observer & fire it to allow other scripts to hook in.
1082    var postPreferencesSaveObject = new PostPreferencesSave();
1083    self.handleEvent('postPreferencesSave', postPreferencesSaveObject);
1084  };
1085
1086  Drupal.eu_cookie_compliance.hasAgreed = function (category) {
1087    var agreed = (_euccCurrentStatus === cookieValueAgreedShowThankYou || _euccCurrentStatus === cookieValueAgreed);
1088
1089    if (category !== undefined && agreed && drupalSettings.eu_cookie_compliance.method === 'categories') {
1090      agreed = Drupal.eu_cookie_compliance.hasAgreedWithCategory(category);
1091    }
1092
1093    return agreed;
1094  };
1095
1096  Drupal.eu_cookie_compliance.hasAgreedWithCategory = function (category) {
1097    return $.inArray(category, _euccSelectedCategories) !== -1;
1098  };
1099
1100  Drupal.eu_cookie_compliance.showBanner = function () {
1101    var showBanner = false;
1102    if ((_euccCurrentStatus === cookieValueDisagreed && drupalSettings.eu_cookie_compliance.method === 'default') || _euccCurrentStatus === null) {
1103      if (!drupalSettings.eu_cookie_compliance.disagree_do_not_show_popup || _euccCurrentStatus === null) {
1104        showBanner = true;
1105      }
1106    }
1107    else if (_euccCurrentStatus === cookieValueAgreedShowThankYou && drupalSettings.eu_cookie_compliance.popup_agreed_enabled) {
1108      showBanner = true;
1109    }
1110    else if (_euccCurrentStatus === cookieValueAgreed && drupalSettings.eu_cookie_compliance.withdraw_enabled) {
1111      showBanner = true;
1112    }
1113
1114    return showBanner;
1115  };
1116
1117  Drupal.eu_cookie_compliance.cookiesEnabled = function () {
1118    var cookieEnabled = (navigator.cookieEnabled);
1119    if (typeof navigator.cookieEnabled === 'undefined' && !cookieEnabled) {
1120      date.setDate(date.getDate() + 100);
1121      setCookie('testcookie', 'testcookie', { expires: date, sameSite: 'strict' });
1122      cookieEnabled = (getCookie('testcookie').indexOf('testcookie') !== -1);
1123    }
1124
1125    return (cookieEnabled);
1126  };
1127
1128  Drupal.eu_cookie_compliance.cookieMatches = function (cookieName, pattern) {
1129    if (cookieName === pattern) {
1130      return true;
1131    }
1132    if (pattern.indexOf('*') < 0) {
1133      return false;
1134    }
1135    try {
1136      var regexp = new RegExp('^' + pattern.replace(/\./g, '\\.').replace(/\*/g, '.+') + '$', 'g');
1137      return regexp.test(cookieName);
1138    }
1139    catch (err) {
1140      return false;
1141    }
1142  };
1143
1144  Drupal.eu_cookie_compliance.isAllowed = function (cookieName) {
1145    // Skip the PHP session cookie.
1146    if (cookieName.indexOf('SESS') === 0 || cookieName.indexOf('SSESS') === 0) {
1147      return true;
1148    }
1149    // Split the allowed cookies.
1150    var euCookieComplianceAllowlist = drupalSettings.eu_cookie_compliance.allowed_cookies.split(/\r\n|\n|\r/g);
1151
1152    // Add the EU Cookie Compliance cookie.
1153    euCookieComplianceAllowlist.push((typeof drupalSettings.eu_cookie_compliance.cookie_name === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_name === '') ? 'cookie-agreed' : drupalSettings.eu_cookie_compliance.cookie_name);
1154    euCookieComplianceAllowlist.push((typeof drupalSettings.eu_cookie_compliance.cookie_name === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_name === '') ? 'cookie-agreed-categories' : drupalSettings.eu_cookie_compliance.cookie_name + '-categories');
1155    euCookieComplianceAllowlist.push((typeof drupalSettings.eu_cookie_compliance.cookie_name === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_name === '') ? 'cookie-agreed-version' : drupalSettings.eu_cookie_compliance.cookie_name + '-version');
1156    // Check if the cookie is allowed.
1157    for (var item in euCookieComplianceAllowlist) {
1158      // Defensively check types for comparison.
1159      if (typeof euCookieComplianceAllowlist[item] === "string") {
1160        if (Drupal.eu_cookie_compliance.cookieMatches(cookieName, euCookieComplianceAllowlist[item])) {
1161          return true;
1162        }
1163        // Handle cookie names that are prefixed with a category.
1164        if (drupalSettings.eu_cookie_compliance.method === 'categories') {
1165          var separatorPos = euCookieComplianceAllowlist[item].indexOf(":");
1166          if (separatorPos !== -1) {
1167            var category = euCookieComplianceAllowlist[item].substr(0, separatorPos);
1168            var wlCookieName = euCookieComplianceAllowlist[item].substr(separatorPos + 1);
1169
1170            if (Drupal.eu_cookie_compliance.cookieMatches(cookieName, wlCookieName) && Drupal.eu_cookie_compliance.hasAgreedWithCategory(category)) {
1171              return true;
1172            }
1173          }
1174        }
1175      }
1176    }
1177
1178    return false;
1179  }
1180
1181  Drupal.eu_cookie_compliance.getVersion = function () {
1182    // Only get cookie-agreed-version version cookie, if user agreed.
1183    if (!Drupal.eu_cookie_compliance.hasAgreed()) {
1184      return false;
1185    }
1186
1187    var cookieName = (typeof drupalSettings.eu_cookie_compliance.cookie_name === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_name === '') ? 'cookie-agreed-version' : drupalSettings.eu_cookie_compliance.cookie_name + '-version';
1188    return getCookie(cookieName);
1189  };
1190
1191  Drupal.eu_cookie_compliance.setVersion = function (force_this_version) {
1192    // Only set cookie-agreed-version version cookie, if user agreed.
1193    if (!Drupal.eu_cookie_compliance.hasAgreed()) {
1194      return false;
1195    }
1196
1197    var date = new Date();
1198    var domain = drupalSettings.eu_cookie_compliance.domain ? drupalSettings.eu_cookie_compliance.domain : '';
1199    var path = drupalSettings.eu_cookie_compliance.domain_all_sites ? '/' : drupalSettings.path.baseUrl;
1200    var cookieName = (typeof drupalSettings.eu_cookie_compliance.cookie_name === 'undefined' || drupalSettings.eu_cookie_compliance.cookie_name === '') ? 'cookie-agreed-version' : drupalSettings.eu_cookie_compliance.cookie_name + '-version';
1201    if (path.length > 1) {
1202      var pathEnd = path.length - 1;
1203      if (path.lastIndexOf('/') === pathEnd) {
1204        path = path.substring(0, pathEnd);
1205      }
1206    }
1207
1208    var eucc_version = (force_this_version !== undefined) ? force_this_version : drupalSettings.eu_cookie_compliance.cookie_policy_version;
1209    var cookie_session = parseInt(drupalSettings.eu_cookie_compliance.cookie_session);
1210    if (cookie_session) {
1211      setCookie(cookieName, eucc_version, { path: path, domain: domain, sameSite: 'strict' });
1212    }
1213    else {
1214      var lifetime = parseInt(drupalSettings.eu_cookie_compliance.cookie_lifetime);
1215      date.setDate(date.getDate() + lifetime);
1216      setCookie(cookieName, eucc_version, { expires: date, path: path, domain: domain, sameSite: 'strict' });
1217    }
1218  };
1219
1220  // Load blocked scripts if the user has agreed to being tracked.
1221  var euCookieComplianceHasLoadedScripts = false;
1222  var euCookieComplianceHasLoadedScriptsForCategory = {};
1223  $(function () {
1224    if (typeof drupalSettings.eu_cookie_compliance !== 'undefined') {
1225      if (Drupal.eu_cookie_compliance.hasAgreed()
1226        || (_euccCurrentStatus === null && drupalSettings.eu_cookie_compliance.method !== 'opt_in' && drupalSettings.eu_cookie_compliance.method !== 'categories')
1227      ) {
1228        if (typeof euCookieComplianceLoadScripts === "function") {
1229          euCookieComplianceLoadScripts();
1230        }
1231        euCookieComplianceHasLoadedScripts = true;
1232
1233        if (drupalSettings.eu_cookie_compliance.method === 'categories') {
1234          Drupal.eu_cookie_compliance.loadCategoryScripts(_euccSelectedCategories);
1235        }
1236      }
1237    }
1238  });
1239
1240  Drupal.eu_cookie_compliance.BlockCookies = function () {
1241    var cookieStatus = Drupal.eu_cookie_compliance.getCookieStatus();
1242    if ((cookieStatus === cookieValueAgreedShowThankYou || cookieStatus === cookieValueAgreed)
1243      && drupalSettings.eu_cookie_compliance.method !== 'categories') {
1244      // Stop blocking the cookies if it's already been agreed to (e.g. in a different tab).
1245      if (typeof euCookieComplianceBlockCookies !== 'undefined') {
1246        clearInterval(euCookieComplianceBlockCookies);
1247        return;
1248      }
1249    }
1250    // Load all cookies from jQuery.
1251    var allCookies = getCookie();
1252
1253    // Check each cookie and try to remove it if it's not allowed.
1254    for (var i in allCookies) {
1255      var remove = true;
1256      var hostname = window.location.hostname;
1257      var cookieRemoved = false;
1258      var index = 0;
1259
1260      remove = !Drupal.eu_cookie_compliance.isAllowed(i);
1261
1262      // Remove the cookie if it's not allowed.
1263      if (remove) {
1264        while (!cookieRemoved && hostname !== '') {
1265          // Attempt to remove.
1266          eraseCookie(i, { domain: '.' + hostname, path: '/' });
1267          cookieRemoved = !getCookie(i);
1268          if (!cookieRemoved) {
1269            eraseCookie(i, { domain: hostname, path: '/' });
1270            cookieRemoved = !getCookie(i);
1271          }
1272
1273          index = hostname.indexOf('.');
1274
1275          // We can be on a sub-domain, so keep checking the main domain as well.
1276          hostname = (index === -1) ? '' : hostname.substring(index + 1);
1277        }
1278
1279        // Some jQuery Cookie versions don't remove cookies well.  Try again
1280        // using plain js.
1281        if (!cookieRemoved) {
1282          document.cookie = i + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/;';
1283        }
1284      }
1285    }
1286  }
1287
1288  // Block cookies when the user hasn't agreed.
1289  if ((typeof drupalSettings.eu_cookie_compliance !== 'undefined') &&
1290    drupalSettings.eu_cookie_compliance.automatic_cookies_removal &&
1291    (
1292      (drupalSettings.eu_cookie_compliance.method === 'opt_in' && (_euccCurrentStatus === null  || !Drupal.eu_cookie_compliance.hasAgreed()))
1293      || (drupalSettings.eu_cookie_compliance.method === 'opt_out' && !Drupal.eu_cookie_compliance.hasAgreed() && _euccCurrentStatus !== null)
1294      || (drupalSettings.eu_cookie_compliance.method === 'categories')
1295    )) {
1296    euCookieComplianceBlockCookies = setInterval(Drupal.eu_cookie_compliance.BlockCookies, 5000);
1297  }
1298
1299  /**
1300   * Filter the event listeners by event name and return the list of handlers.
1301   *
1302   * @param forEventName
1303   *
1304   * @returns {[]}
1305   */
1306  var filterQueue = function (forEventName) {
1307    var handlers = [];
1308    if (typeof Drupal.eu_cookie_compliance !== 'undefined' &&
1309        typeof Drupal.eu_cookie_compliance.queue !== 'undefined' &&
1310        Drupal.eu_cookie_compliance.queue.length) {
1311      // Loop over the list of arguments (objects) pushed into the queue.
1312      for (var i = 0; i < Drupal.eu_cookie_compliance.queue.length; i++) {
1313        if (Drupal.eu_cookie_compliance.queue[i].length) {
1314          var queueItem = Drupal.eu_cookie_compliance.queue[i];
1315          var eventName = queueItem[0];
1316          var eventHandler = queueItem[1];
1317          // If the first element is a string and the second is a function.
1318          if (typeof eventName === 'string' && typeof eventHandler === 'function') {
1319            // And the string matches the event name.
1320            if (eventName === forEventName) {
1321              // Return the functions so they can be executed.
1322              handlers.push(eventHandler);
1323            }
1324          }
1325        }
1326      }
1327    }
1328    return handlers;
1329  }
1330
1331  /**
1332   * Handle event by finding and executing handlers pushed to the queue.
1333   */
1334  self.handleEvent = function (eventName, observer) {
1335    var handlers = filterQueue(eventName);
1336    for (var i = 0; i < handlers.length; i++) {
1337      if (typeof handlers[i] !== 'undefined') {
1338        observer.subscribe(handlers[i]);
1339        observer.fire({
1340          currentStatus: _euccCurrentStatus,
1341          currentCategories: _euccSelectedCategories
1342        });
1343        observer.unsubscribe(handlers[i]);
1344      }
1345    }
1346  };
1347
1348  /**
1349   * Observer: triggered before status gets read from cookie.
1350   */
1351  var PreStatusLoad = (function () {
1352    // Constructor.
1353    var PreStatusLoad = function () {
1354      // Observers.
1355      this.handlers = [];
1356    };
1357    // Convenience var for the prototype.
1358    var prototype = PreStatusLoad.prototype;
1359    prototype.subscribe = function (fn) {
1360      this.handlers.push(fn);
1361    };
1362    prototype.unsubscribe = function (fn) {
1363      this.handlers = this.handlers.filter(
1364          function (item) {
1365            if (item !== fn) {
1366              return item;
1367            }
1368          }
1369      );
1370    };
1371    prototype.fire = function (o, thisObj) {
1372      var scope = thisObj || window;
1373      this.handlers.forEach(function (item) {
1374        item.call(scope, o);
1375      });
1376    };
1377    return PreStatusLoad;
1378  })();
1379
1380  /**
1381   * Observer: when status was read from cookie and stored in private variable.
1382   */
1383  var PostStatusLoad = (function () {
1384    // Constructor.
1385    var PostStatusLoad = function () {
1386      // Observers.
1387      this.handlers = [];
1388    };
1389    // Convenience var for the prototype.
1390    var prototype = PostStatusLoad.prototype;
1391    prototype.subscribe = function (fn) {
1392      this.handlers.push(fn);
1393    };
1394    prototype.unsubscribe = function (fn) {
1395      this.handlers = this.handlers.filter(
1396          function (item) {
1397            if (item !== fn) {
1398              return item;
1399            }
1400          }
1401      );
1402    };
1403    prototype.fire = function (o, thisObj) {
1404      var scope = thisObj || window;
1405      this.handlers.forEach(function (item) {
1406        item.call(scope, o);
1407      });
1408    };
1409    return PostStatusLoad;
1410  })();
1411
1412  /**
1413   * Observer: triggered before status gets saved into cookie.
1414   */
1415  var PreStatusSave = (function () {
1416    // Constructor.
1417    var PreStatusSave = function () {
1418      // Observers.
1419      this.handlers = [];
1420    };
1421    // Convenience var for the prototype.
1422    var prototype = PreStatusSave.prototype;
1423    prototype.subscribe = function (fn) {
1424      this.handlers.push(fn);
1425    };
1426    prototype.unsubscribe = function (fn) {
1427      this.handlers = this.handlers.filter(
1428          function (item) {
1429            if (item !== fn) {
1430              return item;
1431            }
1432          }
1433      );
1434    };
1435    prototype.fire = function (o, thisObj) {
1436      var scope = thisObj || window;
1437      this.handlers.forEach(function (item) {
1438        item.call(scope, o);
1439      });
1440    };
1441    return PreStatusSave;
1442  })();
1443
1444  /**
1445   * Observer: triggered after status was saved into cookie.
1446   */
1447  var PostStatusSave = (function () {
1448    // Constructor.
1449    var PostStatusSave = function () {
1450      // Observers.
1451      this.handlers = [];
1452    };
1453    // Convenience var for the prototype.
1454    var prototype = PostStatusSave.prototype;
1455    prototype.subscribe = function (fn) {
1456      this.handlers.push(fn);
1457    };
1458    prototype.unsubscribe = function (fn) {
1459      this.handlers = this.handlers.filter(
1460          function (item) {
1461            if (item !== fn) {
1462              return item;
1463            }
1464          }
1465      );
1466    };
1467    prototype.fire = function (o, thisObj) {
1468      var scope = thisObj || window;
1469      this.handlers.forEach(function (item) {
1470        item.call(scope, o);
1471      });
1472    };
1473    return PostStatusSave;
1474  })();
1475
1476  /**
1477   * Observer: triggered before categories are read from cookie.
1478   */
1479  var PrePreferencesLoad = (function () {
1480    // Constructor.
1481    var prePreferencesLoad = function () {
1482      // Observers.
1483      this.handlers = [];
1484    };
1485    // Convenience var for the prototype.
1486    var prototype = prePreferencesLoad.prototype;
1487    prototype.subscribe = function (fn) {
1488      this.handlers.push(fn);
1489    };
1490    prototype.unsubscribe = function (fn) {
1491      this.handlers = this.handlers.filter(
1492          function (item) {
1493            if (item !== fn) {
1494              return item;
1495            }
1496          }
1497      );
1498    };
1499    prototype.fire = function (o, thisObj) {
1500      var scope = thisObj || window;
1501      this.handlers.forEach(function (item) {
1502        item.call(scope, o);
1503      });
1504    };
1505    return prePreferencesLoad;
1506  })();
1507
1508  /**
1509   * Observer: triggered after categories were read from cookie.
1510   */
1511  var PostPreferencesLoad = (function () {
1512    // Constructor.
1513    var postPreferencesLoad = function () {
1514      // Observers.
1515      this.handlers = [];
1516    };
1517    // Convenience var for the prototype.
1518    var prototype = postPreferencesLoad.prototype;
1519    prototype.subscribe = function (fn) {
1520      this.handlers.push(fn);
1521    };
1522    prototype.unsubscribe = function (fn) {
1523      this.handlers = this.handlers.filter(
1524          function (item) {
1525            if (item !== fn) {
1526              return item;
1527            }
1528          }
1529      );
1530    };
1531    prototype.fire = function (o, thisObj) {
1532      var scope = thisObj || window;
1533      this.handlers.forEach(function (item) {
1534        item.call(scope, o);
1535      });
1536    };
1537    return postPreferencesLoad;
1538  })();
1539
1540  /**
1541   * Observer: triggered before categories are being saved to cookie.
1542   */
1543  var PrePreferencesSave = (function () {
1544    // Constructor.
1545    var prePreferencesSave = function () {
1546      // Observers.
1547      this.handlers = [];
1548    };
1549    // Convenience var for the prototype.
1550    var prototype = prePreferencesSave.prototype;
1551    prototype.subscribe = function (fn) {
1552      this.handlers.push(fn);
1553    };
1554    prototype.unsubscribe = function (fn) {
1555      this.handlers = this.handlers.filter(
1556          function (item) {
1557            if (item !== fn) {
1558              return item;
1559            }
1560          }
1561      );
1562    };
1563    prototype.fire = function (o, thisObj) {
1564      var scope = thisObj || window;
1565      this.handlers.forEach(function (item) {
1566        item.call(scope, o);
1567      });
1568    };
1569    return prePreferencesSave;
1570  })();
1571
1572  /**
1573   * Observer: triggered after categories were saved to cookie.
1574   */
1575  var PostPreferencesSave = (function () {
1576    // Constructor.
1577    var postPreferencesSave = function () {
1578      // Observers.
1579      this.handlers = [];
1580    };
1581    // Convenience var for the prototype.
1582    var prototype = postPreferencesSave.prototype;
1583    prototype.subscribe = function (fn) {
1584      this.handlers.push(fn);
1585    };
1586    prototype.unsubscribe = function (fn) {
1587      this.handlers = this.handlers.filter(
1588          function (item) {
1589            if (item !== fn) {
1590              return item;
1591            }
1592          }
1593      );
1594    };
1595    prototype.fire = function (o, thisObj) {
1596      var scope = thisObj || window;
1597      this.handlers.forEach(function (item) {
1598        item.call(scope, o);
1599      });
1600    };
1601    return postPreferencesSave;
1602  })();
1603
1604})(jQuery, Drupal, drupalSettings, window.Cookies);

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.