PageSourceSearch

https://prod-txo.vercel.app/scripts/onetrust-wrapper.js

js prod-txo.vercel.app collected 2026-10-03 07:32:21 UTC 10,031 bytes, 289 lines download raw bytes

1/**
2 * OneTrust OptanonWrapper — loaded externally to reduce inline HTML payload.
3 *
4 * The OneTrust SDK calls `window.OptanonWrapper()` after initialization and on
5 * every consent change. This script defines that global function with:
6 *   - localStorage consent tracking
7 *   - Cookie-settings floating button injection (#ot-sdk-btn)
8 *   - MutationObserver-driven modal-state class toggling
9 *   - Scroll-lock helpers (currently disabled via commented calls)
10 */
11(function () {
12  'use strict';
13
14  function updateConsentGroups() {
15    var activeGroups = window.OnetrustActiveGroups || '';
16    var groups = activeGroups.split(',').filter(function (g) { return g.length > 0; });
17    var consentData = {
18      timestamp: new Date().toISOString(),
19      groups: groups,
20      isAccepted: groups.length > 0,
21    };
22    localStorage.setItem('oneTrustConsent', JSON.stringify(consentData));
23  }
24
25  function ensureCookieSettingsButton() {
26    if (document.getElementById('ot-sdk-btn')) return;
27
28    var btn = document.createElement('button');
29    btn.id = 'ot-sdk-btn';
30    btn.className = 'ot-sdk-show-settings';
31    btn.type = 'button';
32    btn.setAttribute('aria-label', 'Cookie Settings');
33    btn.setAttribute('title', 'Cookie Settings');
34    btn.textContent = '';
35
36    btn.style.position = 'fixed';
37    btn.style.left = '16px';
38    btn.style.bottom = '16px';
39    btn.style.zIndex = '2147483647';
40    btn.style.cursor = 'pointer';
41
42    document.body.appendChild(btn);
43
44    btn.addEventListener('click', function () {
45      btn.classList.add('ot-modal-open');
46    }, true);
47  }
48
49  function isVisible(el) {
50    if (!el) return false;
51    var style = window.getComputedStyle(el);
52    var ariaHidden = el.getAttribute('aria-hidden');
53    if (ariaHidden === 'true') return false;
54    return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';
55  }
56
57  // ---- scroll-lock helpers (kept for future use, currently commented out at call sites) ----
58
59  var __otWheelHandler = null;
60  var __otTouchHandler = null;
61  var __otPrevActiveElement = null;
62
63  function addPointerRedirectors() {
64    if (typeof window === 'undefined') return;
65    var pc = document.getElementById('onetrust-pc-sdk');
66    var banner = document.getElementById('onetrust-banner-sdk');
67    var target = pc || banner;
68    if (!target) return;
69
70    __otWheelHandler = function (e) {
71      try {
72        var t = e.target;
73        if (t instanceof Element && target.contains(t)) return;
74        e.preventDefault();
75        if (e.deltaY) target.scrollTop += e.deltaY;
76      } catch (err) { /* ignore */ }
77    };
78
79    __otTouchHandler = function (e) {
80      try {
81        var t = e.target;
82        if (t instanceof Element && target.contains(t)) return;
83        e.preventDefault();
84      } catch (err) { /* ignore */ }
85    };
86
87    document.addEventListener('wheel', __otWheelHandler, { passive: false, capture: true });
88    document.addEventListener('touchmove', __otTouchHandler, { passive: false, capture: true });
89  }
90
91  function removePointerRedirectors() {
92    if (__otWheelHandler) {
93      document.removeEventListener('wheel', __otWheelHandler, { capture: true });
94      __otWheelHandler = null;
95    }
96    if (__otTouchHandler) {
97      document.removeEventListener('touchmove', __otTouchHandler, { capture: true });
98      __otTouchHandler = null;
99    }
100  }
101
102  function lockBodyScroll() {
103    try {
104      try {
105        if (document.activeElement && document.activeElement instanceof HTMLElement && document.activeElement !== document.body) {
106          __otPrevActiveElement = document.activeElement;
107          try { document.activeElement.blur(); } catch (e) { /* ignore */ }
108        }
109      } catch (err) { /* ignore */ }
110
111      document.body.classList.add('ot-modal-open-body');
112      addPointerRedirectors();
113
114      try {
115        var pcEl = document.getElementById('onetrust-pc-sdk');
116        var bannerEl = document.getElementById('onetrust-banner-sdk');
117        if (pcEl) pcEl.setAttribute('data-lenis-prevent', 'true');
118        if (bannerEl) bannerEl.setAttribute('data-lenis-prevent', 'true');
119      } catch (err) { /* ignore */ }
120    } catch (e) { /* ignore */ }
121  }
122
123  function unlockBodyScroll() {
124    try {
125      document.body.classList.remove('ot-modal-open-body');
126      removePointerRedirectors();
127
128      try {
129        var pcEl2 = document.getElementById('onetrust-pc-sdk');
130        var bannerEl2 = document.getElementById('onetrust-banner-sdk');
131        if (pcEl2) pcEl2.removeAttribute('data-lenis-prevent');
132        if (bannerEl2) bannerEl2.removeAttribute('data-lenis-prevent');
133      } catch (err) { /* ignore */ }
134
135      try {
136        window.requestAnimationFrame(function () {
137          try {
138            if (__otPrevActiveElement && typeof __otPrevActiveElement.focus === 'function') {
139              try { __otPrevActiveElement.focus({ preventScroll: true }); } catch (e) { try { __otPrevActiveElement.focus(); } catch (e2) { /* ignore */ } }
140            }
141          } catch (e) { /* ignore */ }
142          __otPrevActiveElement = null;
143        });
144      } catch (e) {
145        try {
146          if (__otPrevActiveElement && typeof __otPrevActiveElement.focus === 'function') {
147            try { __otPrevActiveElement.focus({ preventScroll: true }); } catch (e2) { try { __otPrevActiveElement.focus(); } catch (e3) { /* ignore */ } }
148          }
149        } catch (err) { /* ignore */ }
150        __otPrevActiveElement = null;
151      }
152    } catch (e) { /* ignore */ }
153  }
154
155  // ---- modal state observer ----
156
157  var lastOpenClickAt = 0;
158
159  function toggleBtnModalOpenClass() {
160    var btn = document.getElementById('ot-sdk-btn');
161    if (!btn) return;
162    var pc = document.getElementById('onetrust-pc-sdk');
163    var banner = document.getElementById('onetrust-banner-sdk');
164    var isAnyOpen = isVisible(pc) || isVisible(banner);
165
166    if (isAnyOpen) {
167      btn.classList.add('ot-modal-open');
168      /*lockBodyScroll();*/
169    } else {
170      if (Date.now() - lastOpenClickAt < 800) return;
171      btn.classList.remove('ot-modal-open');
172      /*unlockBodyScroll();*/
173    }
174  }
175
176  var OBSERVE_MODAL_MAX_RETRIES = 50;
177  var observeModalStateRetryCount = 0;
178
179  function observeModalState() {
180    var targets = [
181      document.getElementById('onetrust-pc-sdk'),
182      document.getElementById('onetrust-banner-sdk'),
183    ].filter(Boolean);
184
185    if (targets.length === 0) {
186      if (observeModalStateRetryCount < OBSERVE_MODAL_MAX_RETRIES) {
187        observeModalStateRetryCount++;
188        setTimeout(observeModalState, 300);
189      }
190      return;
191    }
192
193    toggleBtnModalOpenClass();
194
195    var observer = new MutationObserver(function () {
196      toggleBtnModalOpenClass();
197    });
198    targets.forEach(function (t) {
199      observer.observe(t, { attributes: true, attributeFilter: ['style', 'class', 'aria-hidden'] });
200    });
201
202    try {
203      var docObserver = new MutationObserver(function () {
204        try {
205          var pcNow = document.getElementById('onetrust-pc-sdk');
206          var bannerNow = document.getElementById('onetrust-banner-sdk');
207          var anyNow = isVisible(pcNow) || isVisible(bannerNow);
208          if (!anyNow) {
209            /*unlockBodyScroll();*/
210          }
211        } catch (e) { /* ignore */ }
212      });
213      docObserver.observe(document.documentElement || document.body, { childList: true, subtree: true });
214    } catch (err) { /* ignore */ }
215
216    if (window.OneTrust && typeof OneTrust.OnConsentChanged === 'function') {
217      OneTrust.OnConsentChanged(function () { toggleBtnModalOpenClass(); });
218    }
219
220    document.addEventListener('click', function (e) {
221      var target = e.target;
222      if (!(target instanceof Element)) return;
223      var settingsTrigger = target.closest('.ot-sdk-show-settings, #ot-sdk-btn');
224      var isCloseBtn = target.id === 'close-pc-btn-handler';
225
226      var btnNow = document.getElementById('ot-sdk-btn');
227      var pc = document.getElementById('onetrust-pc-sdk');
228      if (!btnNow || !pc) return;
229
230      if (settingsTrigger && isVisible(pc)) {
231        e.preventDefault();
232        e.stopImmediatePropagation();
233        if (window.OneTrust && typeof window.OneTrust.Close === 'function') {
234          window.OneTrust.Close();
235        } else {
236          var closeBtn = document.getElementById('close-pc-btn-handler');
237          if (closeBtn) closeBtn.click();
238          pc.style.display = 'none';
239          pc.setAttribute('aria-hidden', 'true');
240        }
241        btnNow.classList.remove('ot-modal-open');
242        return;
243      }
244
245      if (settingsTrigger && !isVisible(pc)) {
246        btnNow.classList.add('ot-modal-open');
247        lastOpenClickAt = Date.now();
248        var attempts = 0;
249        var poll = setInterval(function () {
250          attempts++;
251          toggleBtnModalOpenClass();
252          if (attempts > 10) clearInterval(poll);
253        }, 100);
254      }
255
256      if (isCloseBtn) {
257        setTimeout(function () {
258          toggleBtnModalOpenClass();
259        }, 300);
260      }
261    }, true);
262  }
263
264  // ---- main OptanonWrapper implementation ----
265
266  function optanonWrapperImpl() {
267    updateConsentGroups();
268
269    if (window.OneTrust && typeof OneTrust.OnConsentChanged === 'function') {
270      OneTrust.OnConsentChanged(function () {
271        updateConsentGroups();
272      });
273    }
274
275    if (document.readyState === 'complete' || document.readyState === 'interactive') {
276      ensureCookieSettingsButton();
277    } else {
278      document.addEventListener('DOMContentLoaded', ensureCookieSettingsButton);
279    }
280
281    if (document.readyState === 'complete' || document.readyState === 'interactive') {
282      observeModalState();
283    } else {
284      document.addEventListener('DOMContentLoaded', observeModalState);
285    }
286  }
287
288  window.OptanonWrapper = optanonWrapperImpl;
289})();

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.