PageSourceSearch

https://tellmamauk.org/wp-content/cache/wpfc-minified/308d5b79/i1ke0.js

js tellmamauk.org collected 2026-09-24 18:13:30 UTC 59,609 bytes, 1,696 lines download raw bytes

1// source --> https://tellmamauk.org/wp-content/plugins/cookie-law-info/lite/frontend/js/script.js?ver=3.5.4 
2/**
3 * WordPress localize object mapped to a constant.
4 */
5const _ckyStore = window._ckyConfig;
6const _ckyStyle = window._ckyStyles;
7
8_ckyStore._backupNodes = [];
9_ckyStore._resetConsentID = false;
10_ckyStore._bannerState = false;
11_ckyStore._preferenceOriginTag = false;
12_ckyStore._optoutSuccessCountdownInterval = null;
13_ckyStore._optoutSuccessAutoCloseTimer = null;
14_ckyStore._optoutSuccessSubtextTemplate = "";
15
16const CKY_OPTOUT_SUCCESS_DISMISS_MS = 15000;
17const CKY_OPTOUT_SUCCESS_SECONDS = 15;
18
19window.cookieyes = window.cookieyes || {};
20const ref = window.cookieyes;
21ref._ckyConsentStore = new Map();
22
23ref._ckyGetCookieMap = function () {
24    const cookieMap = {};
25    try {
26        document.cookie.split(";").map((cookie) => {
27            const [key, value] = cookie.split("=");
28            if (!key) return;
29            cookieMap[key.trim()] = value;
30            return value;
31        });
32    } catch (error) { }
33    return cookieMap;
34};
35
36const currentCookieMap = ref._ckyGetCookieMap();
37ref._ckyGetFromStore = function (key) {
38    return ref._ckyConsentStore.get(key) || "";
39};
40
41ref._ckySetInStore = function (key, value) {
42    ref._ckyConsentStore.set(key, value);
43    let cookieStringArray = [];
44    for (const [key, value] of ref._ckyConsentStore) {
45        cookieStringArray.push(`${key}:${value}`);
46    }
47    const scriptExpiry =
48        _ckyStore && _ckyStore._expiry
49            ? _ckyStore._expiry
50            : 365;
51    ref._ckySetCookie(
52        "cookieyes-consent",
53        cookieStringArray.join(","),
54        scriptExpiry
55    );
56};
57
58const cookieyesConsentMap = (currentCookieMap["cookieyes-consent"] || "")
59    .split(",")
60    .reduce((prev, curr) => {
61        if (!curr) return prev;
62        const [key, value] = curr.split(":");
63        prev[key] = value;
64        return prev;
65    }, {});
66["consentid", "consent", "action"]
67    .concat(_ckyStore._categories.map(({ slug }) => slug))
68    .map((item) =>
69        ref._ckyConsentStore.set(item, cookieyesConsentMap[item] || "")
70    );
71
72
73/**
74 * Get the value of cookie by it's name.
75 * 
76 * @param {string} name Name of the cookie
77 * @returns {string}
78 */
79ref._ckyGetCookie = function (name) {
80    const value = new RegExp(`${name}=([^;]+)`).exec(document.cookie);
81    return value && Array.isArray(value) && value[1] ? unescape(value[1]) : null;
82}
83
84/**
85 * Set a cookie on document.cookie object.
86 * 
87 * @param {*} name Name of the cookie.
88 * @param {*} value Value to be set.
89 * @param {*} days Expiry in days.
90 * @param {*} domain Cookie domain.
91 */
92ref._ckySetCookie = function (name, value, days = 0, domain = _ckyStore._rootDomain) {
93    const date = new Date();
94    if (!!domain) {
95        domain = `domain=${domain}`;
96    }
97    const toSetTime =
98        days === 0 ? 0 : date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
99    document.cookie = `${name}=${value}; expires=${new Date(
100        toSetTime
101    ).toUTCString()}; path=/;${domain}; SameSite=Strict;`;
102}
103
104function _ckySetConsentID() {
105    const cookieyesID = ref._ckyGetFromStore("consentid");
106    if (cookieyesID) return;
107    const consentID = ref._ckyRandomString(32);
108    ref._ckySetInStore("consentid", consentID);
109    _ckyStore._resetConsentID = true;
110}
111
112const _revisitCkyConsent = function () {
113    const type = _ckyGetType();
114    if (type === 'classic') {
115        _ckyShowBanner();
116    }
117    _ckySetPreferenceAction();
118    _ckyToggleRevisit();
119};
120/**
121 * Search an element by it's data-cky-tag attribute
122 * 
123 * @param {string} tag data-cky-tag of an element. 
124 * @returns {object}
125 */
126function _ckyGetElementByTag(tag) {
127    const item = document.querySelector('[data-cky-tag=' + tag + ']');
128    return item ? item : false;
129}
130
131function _ckyEscapeRegex(literal) {
132    return literal.replace(/[.*+?^${}()[\]\\]/g, "\\$&");
133}
134
135/**
136 * Bind click event to banner elements.
137 * 
138 * @param {string} tag data-cky-tag of the element
139 * @param {function} fn callback function
140 */
141function _ckyAttachListener(selector, fn) {
142    const item = _ckyFindElement(selector);
143    item && item.addEventListener("click", fn);
144}
145
146function _ckyClassAdd() {
147    return _ckyClassAction("add", ...arguments);
148}
149
150function _ckyClassRemove() {
151    return _ckyClassAction("remove", ...arguments);
152}
153
154function _ckyClassToggle() {
155    return _ckyClassAction("toggle", ...arguments);
156}
157
158function _ckyClassAction(action, selector, className, forParent = true) {
159    const item = _ckyFindElement(selector, forParent);
160    return item && item.classList[action](className);
161}
162
163function _ckyFindElement(selector, forParent) {
164    let createdSelector = selector;
165    switch (true) {
166        case selector.startsWith("="):
167            createdSelector = `[data-cky-tag="${selector.substring(1)}"]`;
168            break;
169        default:
170            break;
171    }
172    const element = document.querySelector(createdSelector);
173    if (!element || (forParent && !element.parentElement)) return null;
174    return forParent ? element.parentElement : element;
175}
176/**
177 * Remove an element from the DOM.
178 * 
179 * @param {string} tag data-cky-tag of the element.
180 */
181function _ckyRemoveElement(tag) {
182    const item = _ckyGetElementByTag(tag);
183    item && item.remove();
184}
185
186function _ckyFireEvent(responseCategories) {
187    const consentUpdate = new CustomEvent("cookieyes_consent_update", {
188        detail: responseCategories
189    });
190    document.dispatchEvent(consentUpdate);
191}
192
193/**
194 * Remove styles by it's id.
195 */
196function _ckyRemoveStyles() {
197    const item = document.getElementById('cky-style-inline');
198    item && item.remove();
199}
200
201/**
202 * Generate a random string for logging purposes.
203 * 
204 * @param {integer} length Length of the string to be generated.
205 * @returns 
206 */
207ref._ckyRandomString = function (length, allChars = true) {
208    const chars = `${allChars ? `0123456789` : ""
209        }ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz`;
210    const response = [];
211    for (let i = 0; i < length; i++)
212        response.push(chars[Math.floor(Math.random() * chars.length)]);
213    if (!allChars) return response.join("");
214    return btoa(response.join("")).replace(/\=+$/, "");
215}
216
217/**
218 * Remove banner if necessary.
219 */
220function _ckyRemoveBanner() {
221    _ckyHideBanner();
222    if (_ckyStore._bannerConfig.config.revisitConsent.status === true) {
223        _ckyShowRevisit();
224    }
225}
226
227/**
228 * Initialize the plugin front-end operations.
229 * 
230 * @returns {boolean}
231 */
232function _ckyInitOperations() {
233    _ckyAttachNoticeStyles();
234    _ckyAttachShortCodeStyles();
235    _ckyRenderBanner();
236    _ckySetShowMoreLess();
237    if (!ref._ckyGetFromStore("action") || _ckyPreviewEnabled()) {
238        _ckyShowBanner();
239        _ckySetInitialState();
240        _ckySetConsentID();
241    } else {
242        _ckyRemoveBanner();
243    }
244}
245function _ckyPreviewEnabled() {
246    let params = (new URL(document.location)).searchParams;
247    return params.get("cky_preview") && params.get("cky_preview") === 'true';
248}
249function _ckyToggleAriaExpandStatus(selector, forceDefault = null) {
250    const element = _ckyFindElement(selector);
251
252    if (!element) return;
253
254    if (element.classList.contains('cky-accordion-btn')) {
255        const accordionItem = element.closest('.cky-accordion');
256        if (accordionItem) {
257            const accordionBody = accordionItem.querySelector('.cky-accordion-body');
258            if (accordionBody) {
259                // Generate unique ID for the accordion body if it doesn't have one
260                let bodyId = accordionBody.id;
261                if (!bodyId) {
262                    bodyId = `ckyDetailCategory${accordionItem.id.replace('ckyDetailCategory', '')}Body`;
263                    accordionBody.id = bodyId;
264                }
265                // Always set aria-controls - the relationship is permanent
266                element.setAttribute("aria-controls", bodyId);
267            }
268        }
269    }
270
271    const currentExpanded = element.getAttribute("aria-expanded");
272    const newExpandedValue = forceDefault || (currentExpanded === "true" ? "false" : "true");
273    element.setAttribute("aria-expanded", newExpandedValue);
274}
275/**
276 * Sets the initial state of the plugin.
277 */
278function _ckySetInitialState() {
279    const activeLaw = _ckyGetLaw()
280    ref._ckySetInStore("consent", "no");
281    const ccpaCheckBoxValue = _ckyFindCheckBoxValue();
282    const responseCategories = { accepted: [], rejected: [] };
283    let valueToSet = "yes";
284    for (const category of _ckyStore._categories) {
285        if (
286            (activeLaw === "gdpr" &&
287                !category.isNecessary &&
288                !category.defaultConsent[activeLaw]) ||
289            (activeLaw === "ccpa" &&
290                ccpaCheckBoxValue &&
291                !category.defaultConsent.ccpa)
292        ) {
293            valueToSet = "no";
294        }
295        if (valueToSet === "no") responseCategories.rejected.push(category.slug);
296        else responseCategories.accepted.push(category.slug);
297        ref._ckySetInStore(`${category.slug}`, valueToSet);
298    }
299    _ckyUnblock();
300    _ckyFireEvent(responseCategories);
301}
302
303/**
304 * Add a class based on the banner type and position. Eg: 'cky-banner-top'
305 * 
306 * @returns {boolean}
307 */
308function _ckyAddPositionClass() {
309    const notice = _ckyGetElementByTag('notice');
310    if (!notice) return false;
311    const container = notice.closest('.cky-consent-container');
312    if (!container) return false;
313    
314    container.setAttribute("aria-label", "We value your privacy");
315    container.setAttribute("role", "region");
316    
317    const type = _ckyStore._bannerConfig.settings.type;
318    let position = _ckyStore._bannerConfig.settings.position;
319    let bannerType = type;
320    if (bannerType === 'popup') {
321        position = 'center';
322    }
323    bannerType = (_ckyGetPtype() === "pushdown") ? 'classic' : bannerType;
324    const noticeClass = `cky-${bannerType}-${position}`;
325    container.classList.add(noticeClass);
326    const revisitConsent = _ckyGetElementByTag('revisit-consent');
327    if (!revisitConsent) return false;
328    const revisitPosition = 'cky-revisit-' + _ckyStore._bannerConfig.config.revisitConsent.position;
329    revisitConsent.classList.add(revisitPosition);
330}
331
332/**
333 * Add a class based on the preference center type and position. Eg: 'cky-sidebar-left'
334 * 
335 * @returns {boolean}
336 */
337function _ckyAddPreferenceCenterClass() {
338    const detail = _ckyGetLaw() === 'ccpa' ? _ckyGetElementByTag("optout-popup") : _ckyGetElementByTag("detail");
339    if (!detail) return false;
340    const modal = detail.closest('.cky-modal');
341    if (!modal) return false;
342    if (_ckyGetPtype() !== "pushdown" && _ckyGetPtype() !== "popup") {
343        const pType = _ckyStore._bannerConfig.settings.preferenceCenterType;
344        const modalClass = `cky-${pType}`;
345        modal.classList.add(modalClass);
346    }
347
348    // Ensure ARIA attributes are always present on the preference center div
349    const preferenceCenter = modal.querySelector('.cky-preference-center');
350    if (preferenceCenter) {
351        const preferenceCenterId = _ckyGetLaw() === 'ccpa' ? 'ckyOptoutPreferenceCenter' : 'ckyPreferenceCenter';
352        preferenceCenter.setAttribute('id', preferenceCenterId);
353        preferenceCenter.setAttribute('role', 'dialog');
354        preferenceCenter.setAttribute('aria-modal', 'true');
355        const ariaLabel = _ckyGetLaw() === 'ccpa' ? 'Opt-out Preferences' : 'Customise Consent Preferences';
356        preferenceCenter.setAttribute('aria-label', ariaLabel);
357    }
358}
359
360/**
361 * Initialize the plugin operations.
362 */
363async function _ckyInit() {
364    try {
365        _ckyInitOperations();
366        _ckyRemoveAllDeadCookies();
367        _ckyWatchBannerElement();
368    } catch (err) {
369        console.error(err);
370    }
371}
372
373/**
374 * Domready event, alternative to jQuery(document).ready() function
375 * 
376 * @param {function} callback 
377 * @returns 
378 */
379function _ckyDomReady(callback) {
380    if (typeof document === 'undefined') {
381        return;
382    }
383    if (document.readyState === 'complete' || /** DOMContentLoaded + Images/Styles/etc loaded, so we call directly. */
384        document.readyState === 'interactive' /** DOMContentLoaded fires at this point, so we call directly. */
385    ) {
386        return void callback();
387    } /** DOMContentLoaded has not fired yet, delay callback until then. */
388    document.addEventListener('DOMContentLoaded', callback);
389}
390
391/**
392 * Callback function to Domready event.
393 */
394_ckyDomReady(async function () {
395    try {
396        await _ckyInit();
397    } catch (err) {
398        console.error(err);
399    }
400});
401
402/**
403 * Register event handler for all the action elements.
404 */
405function _ckyRegisterListeners() {
406    for (const { slug } of _ckyStore._categories) {
407        _ckyAttachListener('detail-category-title', () =>
408            document
409                .getElementById(`ckyCategory${slug}`)
410                .classList.toggle("cky-tab-active")
411        );
412    }
413    _ckyAttachListener("=settings-button", () => _ckySetPreferenceAction('settings-button'));
414    _ckyAttachListener("=detail-close", () => _ckyHidePreferenceCenter());
415    _ckyAttachListener("=optout-cancel-button", () => _ckyHidePreferenceCenter());
416    _ckyAttachListener("=close-button", () => _ckyActionClose());
417    _ckyAttachListener("=donotsell-button", () => _ckySetPreferenceAction('donotsell-button'));
418    _ckyAttachListener("=reject-button", _ckyAcceptReject("reject"));
419    _ckyAttachListener("=accept-button", _ckyAcceptReject("all"));
420    _ckyAttachListener("=detail-accept-button", _ckyAcceptReject("all"));
421    _ckyAttachListener("=detail-save-button", _ckyAcceptReject());
422    _ckyAttachListener("=detail-category-preview-save-button", _ckyAcceptReject());
423    _ckyAttachListener("=optout-confirm-button", _ckyHandleOptoutConfirm());
424    _ckyAttachListener("=detail-reject-button", _ckyAcceptReject("reject"));
425    _ckyAttachListener("=revisit-consent", () => _revisitCkyConsent());
426    _ckyAttachListener("=optout-close", () => _ckyHandleOptoutPopupClose());
427}
428
429function _ckyAttachCategoryListeners() {
430    if (!_ckyStore._bannerConfig.config.auditTable.status) return;
431    const categoryNames = _ckyStore._categories.map(({ slug }) => slug);
432    categoryNames.map((category) => {
433        const selector = `#ckyDetailCategory${category}`;
434        const accordionButtonSelector = `${selector}  .cky-accordion-btn`;
435
436        // Set initial aria-controls and aria-expanded for accordion buttons
437        const accordionButton = document.querySelector(accordionButtonSelector);
438        if (accordionButton) {
439            const accordionItem = accordionButton.closest('.cky-accordion');
440            if (accordionItem) {
441                const accordionBody = accordionItem.querySelector('.cky-accordion-body');
442                if (accordionBody) {
443                    // Generate unique ID for the accordion body if it doesn't have one
444                    let bodyId = accordionBody.id;
445                    if (!bodyId) {
446                        bodyId = `ckyDetailCategory${accordionItem.id.replace('ckyDetailCategory', '')}Body`;
447                        accordionBody.id = bodyId;
448                    }
449                    // Always set aria-controls - the relationship is permanent
450                    accordionButton.setAttribute("aria-controls", bodyId);
451                }
452            }
453        }
454
455        _ckyToggleAriaExpandStatus(accordionButtonSelector, "false");
456        _ckyAttachListener(selector, ({ target: { id } }) => {
457            if (
458                id === `ckySwitch${category}` ||
459                !_ckyClassToggle(selector, "cky-accordion-active", false)
460            ) {
461                _ckyToggleAriaExpandStatus(accordionButtonSelector, "false");
462                return;
463            }
464            _ckyToggleAriaExpandStatus(accordionButtonSelector, "true");
465            categoryNames
466                .filter((categoryName) => categoryName !== category)
467                .map(filteredName => {
468                    _ckyClassRemove(
469                        `#ckyDetailCategory${filteredName}`,
470                        "cky-accordion-active",
471                        false
472                    );
473                    _ckyToggleAriaExpandStatus(
474                        `#ckyDetailCategory${filteredName} .cky-accordion-btn`,
475                        "false"
476                    );
477                    return filteredName;
478                });
479        });
480        return category;
481    });
482}
483/**
484 * Add support for accordion tabs on the privacy overview screen.
485 */
486function _ckyInitiAccordionTabs() {
487    document.querySelectorAll(".cky-accordion").forEach((item) => (
488        item.addEventListener('click', function (event) {
489            if (event.target.type === 'checkbox') return;
490            this.classList.toggle('cky-accordion-active');
491        })
492    ));
493}
494
495function _ckyToggleBanner(force = false) {
496    const notice = _ckyGetElementByTag('notice');
497    const container = notice && notice.closest('.cky-consent-container') || false;
498    if (container) {
499        force === true ? container.classList.add('cky-hide') : container.classList.toggle('cky-hide');
500    }
501
502}
503
504function _ckyToggleRevisit(force = false) {
505    const revisit = _ckyGetRevisit();
506    if (revisit) {
507        force === true ? _ckyRevisitHide() : revisit.classList.toggle('cky-revisit-hide');
508    }
509}
510function _ckyGetLaw() {
511    return _ckyStore._bannerConfig.settings.applicableLaw;
512}
513function _ckyGetType() {
514    return _ckyStore._bannerConfig.settings.type;
515}
516function _ckyGetPtype() {
517    if (_ckyGetType() === 'classic') {
518        return 'pushdown';
519    }
520    return _ckyStore._bannerConfig.settings.preferenceCenterType;
521}
522function _ckyGetBanner() {
523    const notice = _ckyGetElementByTag('notice');
524    const container = notice && notice.closest('.cky-consent-container') || false;
525    return container && container || false;
526}
527function _ckyHideBanner() {
528    const notice = _ckyGetBanner();
529    notice && notice.classList.add('cky-hide');
530}
531function _ckyShowBanner() {
532    const notice = _ckyGetBanner();
533    notice && notice.classList.remove('cky-hide');
534}
535function _ckyHideOverLay() {
536    const overlay = document.querySelector('.cky-overlay');
537    overlay && overlay.classList.add('cky-hide');
538}
539function _ckyShowOverLay() {
540    const overlay = document.querySelector('.cky-overlay');
541    overlay && overlay.classList.remove('cky-hide');
542}
543function _ckyToggleOverLay() {
544    const overlay = document.querySelector('.cky-overlay');
545    overlay && overlay.classList.toggle('cky-hide');
546}
547function _ckyGetPreferenceCenter() {
548    if (_ckyGetType() === 'classic') {
549        return _ckyGetBanner();
550    }
551    let element = _ckyGetLaw() === 'ccpa' ? _ckyGetElementByTag("optout-popup") : _ckyGetElementByTag("detail");
552    return element && element.closest('.cky-modal') || false;
553}
554function _ckyHidePreferenceCenter() {
555    _ckyResetOptoutSuccessMessage();
556    const element = _ckyGetPreferenceCenter();
557    element && element.classList.remove(_ckyGetPreferenceClass());
558
559    // ARIA attributes remain always present - only aria-expanded on settings button changes
560    // The modal relationship is permanent, only visibility changes
561
562    if (_ckyGetType() !== 'classic') {
563        _ckyHideOverLay();
564        if (!ref._ckyGetFromStore("action")) _ckyShowBanner();
565    } else {
566        _ckyToggleAriaExpandStatus("=settings-button", "false");
567        _ckyClassRemove("=notice", "cky-consent-bar-expand");
568    }
569    if (ref._ckyGetFromStore("action")) _ckyShowRevisit();
570    const origin = _ckyStore._preferenceOriginTag;
571    origin && _ckySetFocus(origin)
572}
573function _ckyShowPreferenceCenter() {
574    const element = _ckyGetPreferenceCenter();
575    element && element.classList.add(_ckyGetPreferenceClass());
576
577    // Ensure ARIA attributes are always present on the preference center div
578    if (element) {
579        const preferenceCenter = element.querySelector('.cky-preference-center');
580        if (preferenceCenter) {
581            const preferenceCenterId = _ckyGetLaw() === 'ccpa' ? 'ckyOptoutPreferenceCenter' : 'ckyPreferenceCenter';
582            preferenceCenter.setAttribute('id', preferenceCenterId);
583            preferenceCenter.setAttribute('role', 'dialog');
584            preferenceCenter.setAttribute('aria-modal', 'true');
585            const ariaLabel = _ckyGetLaw() === 'ccpa' ? 'Opt-out Preferences' : 'Customise Consent Preferences';
586            preferenceCenter.setAttribute('aria-label', ariaLabel);
587        }
588    }
589
590    if (_ckyGetType() !== 'classic') {
591        _ckyShowOverLay();
592        _ckyHideBanner();
593    } else {
594        _ckyToggleAriaExpandStatus("=settings-button");
595        _ckyClassAdd("=notice", "cky-consent-bar-expand");
596    }
597}
598function _ckyTogglePreferenceCenter() {
599    const element = _ckyGetPreferenceCenter();
600    if (!element) return;
601    element.classList.toggle(_ckyGetPreferenceClass());
602    if (_ckyGetPtype() !== 'pushdown') _ckyToggleOverLay();
603
604    const isOpen = element.classList.contains(_ckyGetPreferenceClass());
605    element.classList.toggle(_ckyGetPreferenceClass());
606    if (_ckyGetType() === 'classic') {
607        const preferenceCenter = element.querySelector('.cky-preference-center');
608        if (preferenceCenter) {
609            const preferenceCenterId = _ckyGetLaw() === 'ccpa' ? 'ckyOptoutPreferenceCenter' : 'ckyPreferenceCenter';
610            preferenceCenter.setAttribute('id', preferenceCenterId);
611            preferenceCenter.setAttribute('role', 'dialog');
612            preferenceCenter.setAttribute('aria-modal', 'true');
613            const ariaLabel = _ckyGetLaw() === 'ccpa' ? 'Opt-out Preferences' : 'Customise Consent Preferences';
614            preferenceCenter.setAttribute('aria-label', ariaLabel);
615        }
616        _ckyToggleAriaExpandStatus("=settings-button");
617        _ckyClassToggle("=notice", "cky-consent-bar-expand");
618    } else {
619        if (!isOpen) {
620            _ckyShowOverLay();
621            _ckyHideBanner();
622        } else {
623            _ckyHideOverLay();
624            if (!ref._ckyGetFromStore("action")) _ckyShowBanner();
625        }
626    }
627    if (ref._ckyGetFromStore("action")) _ckyShowRevisit();
628    const origin = _ckyStore._preferenceOriginTag;
629    origin && _ckySetFocus(origin)
630}
631function _ckyGetPreferenceClass() {
632    return _ckyGetPtype() === 'pushdown' ? 'cky-consent-bar-expand' : 'cky-modal-open';
633}
634
635function _ckyGetRevisit() {
636    const revisit = _ckyGetElementByTag('revisit-consent');
637    return revisit && revisit || false;
638}
639function _ckyHideRevisit() {
640    const revisit = _ckyGetRevisit();
641    revisit && revisit.classList.add('cky-revisit-hide')
642}
643function _ckyShowRevisit() {
644    const revisit = _ckyGetRevisit();
645    revisit && revisit.classList.remove('cky-revisit-hide')
646}
647function _ckySetPreferenceAction(tagName = false) {
648    _ckyStore._preferenceOriginTag = tagName;
649    if (_ckyGetType() === 'classic') {
650        _ckyTogglePreferenceCenter();
651        _ckyToggleAriaExpandStatus("=settings-button");
652    } else {
653        _ckyShowPreferenceCenter();
654    }
655}
656function _ckyGetFocusableElements(element) {
657    const wrapperElement = document.querySelector(`[data-cky-tag="${element}"]`);
658    if (!wrapperElement) return [];
659    const focussableElements = Array.from(
660        wrapperElement.querySelectorAll(
661            'a:not([disabled]), button:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])'
662        )
663    ).filter((element) => element.style.display !== "none");
664    if (focussableElements.length <= 0) return [];
665    return [
666        focussableElements[0],
667        focussableElements[focussableElements.length - 1],
668    ];
669}
670function _ckyLoopFocus() {
671    const activeLaw = _ckyGetLaw();
672    const bannerType = _ckyGetType();
673    if (bannerType === "classic") return;
674    if (bannerType === "popup") {
675        const [firstElementBanner, lastElementBanner] =
676            _ckyGetFocusableElements("notice");
677        _ckyAttachFocusLoop(firstElementBanner, lastElementBanner, true);
678        _ckyAttachFocusLoop(lastElementBanner, firstElementBanner);
679    }
680    const [firstElementPopup, lastElementPopup] = _ckyGetFocusableElements(
681        activeLaw === "ccpa" ? "optout-popup" : "detail"
682    );
683    _ckyAttachFocusLoop(firstElementPopup, lastElementPopup, true);
684    _ckyAttachFocusLoop(lastElementPopup, firstElementPopup);
685}
686function _ckyAttachFocusLoop(element, targetElement, isReverse = false) {
687    if (!element || !targetElement) return;
688    element.addEventListener("keydown", (event) => {
689        if (
690            event.which !== 9 ||
691            (isReverse && !event.shiftKey) ||
692            (!isReverse && event.shiftKey)
693        )
694            return;
695        event.preventDefault();
696        targetElement.focus();
697    });
698}
699
700/**
701 * Replace footer shadow with current preference center background.
702 * 
703 * @param {object} $doc Dom node.
704 * @returns 
705 */
706function _ckySetFooterShadow($doc) {
707    const footer = $doc.querySelector('[data-cky-tag="detail"] .cky-footer-shadow');
708    const preference = $doc.querySelector('[data-cky-tag="detail"]');
709    if (!footer) return;
710    const background = preference && preference.style.backgroundColor || '#ffffff';
711    footer.style.background = `linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, ${background
712        } 100%)`;
713}
714
715/**
716 * Remove all the rejected cookies.
717 * 
718 * @param {object} cookies Cookies list.
719 */
720function _ckyRemoveDeadCookies({ cookies }) {
721    const currentCookieMap = ref._ckyGetCookieMap();
722    for (const { cookieID, domain } of cookies)
723        if (currentCookieMap[cookieID])
724            [domain, ""].map((cookieDomain) =>
725                ref._ckySetCookie(cookieID, "", 0, cookieDomain)
726            );
727}
728function _ckySetPreferenceCheckBoxStates(revisit = false) {
729    for (const category of _ckyStore._categories) {
730        const cookieValue = ref._ckyGetFromStore(category.slug);
731        const checked =
732            cookieValue === "yes" ||
733            (!cookieValue &&
734                category.defaultConsent[_ckyGetLaw()]) || category.isNecessary;
735
736        const disabled = category.isNecessary;
737        const shortCodeData = _ckyStore._shortCodes.find(
738            (code) => code.key === 'cky_category_toggle_label'
739        );
740        const toggleTextFormatted = shortCodeData.content.replace(
741            `[cky_preference_{{category_slug}}_title]`,
742            category.name
743        );
744        _ckySetCheckboxes(
745            category,
746            checked,
747            disabled,
748            toggleTextFormatted,
749            revisit
750        );
751        _ckySetPreferenceState(category);
752    }
753}
754
755function _ckySetCheckboxes(
756    category,
757    checked,
758    disabled,
759    formattedLabel,
760    revisit = false
761) {
762    const toggle = _ckyStore._bannerConfig.config.preferenceCenter.toggle;
763    const activeColor = toggle.states.active.styles['background-color'];
764    const inactiveColor = toggle.states.inactive.styles['background-color'];
765
766    [`ckyCategoryDirect`, `ckySwitch`].map((key) => {
767        const boxElem = document.getElementById(`${key}${category.slug}`);
768        if (!boxElem) return;
769        _ckySetCategoryToggle(
770            boxElem,
771            category,
772            revisit);
773        boxElem.checked = checked;
774        boxElem.disabled = disabled;
775        boxElem.style.backgroundColor = checked ? activeColor : inactiveColor;
776        _ckySetCheckBoxAriaLabel(boxElem, checked, formattedLabel);
777        if (revisit) return;
778        boxElem.addEventListener("change", ({ currentTarget: elem }) => {
779            const isChecked = elem.checked;
780            elem.style.backgroundColor = isChecked ? activeColor : inactiveColor;
781            _ckySetCheckBoxAriaLabel(boxElem, isChecked, formattedLabel);
782        });
783        return boxElem;
784    });
785}
786function _ckySetCategoryToggle(element, category = {}, revisit = false) {
787    if (revisit) return;
788    if (element.parentElement.getAttribute('data-cky-tag') === 'detail-category-toggle') {
789        _ckySetCategoryPreferenceToggle(element, category);
790    } else if (element.parentElement.getAttribute('data-cky-tag') === 'detail-category-preview-toggle') {
791        _ckySetCategoryPreview(element, category);
792    }
793    if (!category.isNecessary) {
794        const categoryName = category.name;
795        const categoryTitle = document.querySelector(`[data-cky-tag="detail-category-title"][aria-label="${categoryName}"]`);
796        if (categoryTitle) {
797            const toggleContainer = categoryTitle.closest('.cky-accordion-item');
798            const necessaryText = toggleContainer.querySelector('.cky-always-active');
799            necessaryText && necessaryText.remove();
800        }
801    }
802}
803function _ckySetCategoryPreferenceToggle(element, category) {
804    let toggleContainer = element.closest('.cky-accordion-item');
805    if (!toggleContainer) return;
806    const toggleSwitch = toggleContainer.querySelector('.cky-switch');
807    if (category.isNecessary) {
808        toggleSwitch && toggleSwitch.remove();
809    } else {
810        if (_ckyGetType() === 'classic' && _ckyStore._bannerConfig.config.categoryPreview.status || (category.cookies && category.cookies.length === 0)) {
811            toggleSwitch && toggleSwitch.remove();
812        }
813    }
814}
815function _ckySetPreferenceState(category) {
816    if (_ckyStore._bannerConfig.config.auditTable.status === false) {
817        const tableElement = document.querySelector(
818            `#ckyDetailCategory${category.slug} [data-cky-tag="audit-table"]`
819        );
820        tableElement && tableElement.remove();
821        const chevronElement = document.querySelector(
822            `#ckyDetailCategory${category.slug} .cky-accordion-chevron`
823        );
824        chevronElement && chevronElement.classList.add("cky-accordion-chevron-hide");
825    }
826}
827function _ckySetCategoryPreview(element, category) {
828    if ((category.cookies && category.cookies.length === 0) && !category.isNecessary)
829        element.parentElement.parentElement.remove();
830}
831
832function _ckySetCheckBoxAriaLabel(boxElem, isChecked, formattedLabel, isCCPA = false) {
833
834    if (!boxElem) return;
835    const keyName = isChecked ? "disable" : "enable";
836    const textCode = `cky_${keyName}_${isCCPA ? "optout" : "category"}_label`;
837    const shortCodeData = _ckyStore._shortCodes.find(
838        (code) => code.key === textCode
839    );
840    if (!shortCodeData) return;
841    const labelText = formattedLabel
842        .replace(/{{status}}/g, keyName)
843        .replace(`[${textCode}]`, shortCodeData.content);
844    boxElem.setAttribute("aria-label", labelText);
845}
846/**
847 * Clear opt-out success countdown timers (interval + timeout).
848 *
849 * @returns {void}
850 */
851function _ckyClearOptoutSuccessTimers() {
852    if (_ckyStore._optoutSuccessCountdownInterval) {
853        clearInterval(_ckyStore._optoutSuccessCountdownInterval);
854        _ckyStore._optoutSuccessCountdownInterval = null;
855    }
856    if (_ckyStore._optoutSuccessAutoCloseTimer) {
857        clearTimeout(_ckyStore._optoutSuccessAutoCloseTimer);
858        _ckyStore._optoutSuccessAutoCloseTimer = null;
859    }
860}
861
862function _ckyIsOptoutSuccessVisible() {
863    const el = _ckyGetElementByTag("optout-success");
864    return !!(el && !el.classList.contains("cky-hide"));
865}
866
867function _ckyDismissOptoutSuccessCountdown() {
868    _ckyRemoveBanner();
869    _ckyHidePreferenceCenter();
870    _ckyAfterConsent();
871}
872
873/**
874 * Show opt-out success UI after save, run countdown, then dismiss banner.
875 *
876 * @returns {void}
877 */
878function _ckyShowOptoutSuccessMessage() {
879    _ckyClearOptoutSuccessTimers();
880
881    const buttonWrapper = _ckyGetElementByTag("optout-buttons");
882    const successMessage = _ckyGetElementByTag("optout-success");
883    const countdownElement = _ckyGetElementByTag("optout-success-subtext");
884    const ccpaCheckbox = document.getElementById("ckyCCPAOptOut");
885
886    if (!buttonWrapper || !successMessage) {
887        _ckyDismissOptoutSuccessCountdown();
888        return;
889    }
890
891    buttonWrapper.style.display = "none";
892    successMessage.classList.remove("cky-hide");
893    successMessage.setAttribute("aria-live", "polite");
894    successMessage.focus();
895    if (ccpaCheckbox) ccpaCheckbox.disabled = true;
896    _ckyClassAdd("=optout-option", "cky-disabled", false);
897
898    const countdownTimerEl =
899        (countdownElement &&
900            countdownElement.querySelector("#ckyCountdownTimer")) ||
901        document.getElementById("ckyCountdownTimer");
902
903    let timeRemaining = CKY_OPTOUT_SUCCESS_SECONDS;
904    if (
905        countdownElement &&
906        !countdownTimerEl &&
907        !_ckyStore._optoutSuccessSubtextTemplate
908    ) {
909        _ckyStore._optoutSuccessSubtextTemplate =
910            countdownElement.textContent ||
911            `Banner closes automatically in ${CKY_OPTOUT_SUCCESS_SECONDS} s...`;
912    }
913    const template = _ckyStore._optoutSuccessSubtextTemplate;
914    const hasDigit = template && /\d+/.test(template);
915    const updateSubtext = () => {
916        if (!countdownElement) return;
917        if (countdownTimerEl) {
918            countdownTimerEl.textContent = String(timeRemaining);
919            return;
920        }
921        countdownElement.textContent = hasDigit
922            ? template.replace(/\d+/, String(timeRemaining))
923            : `Banner closes automatically in ${timeRemaining} s...`;
924    };
925    updateSubtext();
926
927    _ckyStore._optoutSuccessCountdownInterval = setInterval(() => {
928        timeRemaining -= 1;
929        if (timeRemaining >= 0) updateSubtext();
930    }, 1000);
931
932    _ckyStore._optoutSuccessAutoCloseTimer = setTimeout(
933        _ckyDismissOptoutSuccessCountdown,
934        CKY_OPTOUT_SUCCESS_DISMISS_MS
935    );
936}
937
938/**
939 * Reset opt-out success UI (timers, visibility, checkbox, subtext).
940 *
941 * @returns {void}
942 */
943function _ckyResetOptoutSuccessMessage() {
944    _ckyClearOptoutSuccessTimers();
945
946    const buttonWrapper = _ckyGetElementByTag("optout-buttons");
947    const successMessage = _ckyGetElementByTag("optout-success");
948    const countdownElement = _ckyGetElementByTag("optout-success-subtext");
949    const ccpaCheckbox = document.getElementById("ckyCCPAOptOut");
950
951    if (buttonWrapper) buttonWrapper.style.display = "";
952    if (successMessage) successMessage.classList.add("cky-hide");
953    if (ccpaCheckbox) ccpaCheckbox.disabled = false;
954    _ckyClassRemove("=optout-option", "cky-disabled", false);
955    const resetTimerEl =
956        (countdownElement &&
957            countdownElement.querySelector("#ckyCountdownTimer")) ||
958        document.getElementById("ckyCountdownTimer");
959    if (resetTimerEl) {
960        resetTimerEl.textContent = "";
961    } else if (countdownElement && _ckyStore._optoutSuccessSubtextTemplate) {
962        countdownElement.textContent = _ckyStore._optoutSuccessSubtextTemplate;
963    }
964}
965
966/**
967 * Opt-out confirm: if CCPA + opted out, save consent then show success + countdown; else normal save/close.
968 *
969 * @returns {Function} Click handler
970 */
971function _ckyHandleOptoutConfirm() {
972    return () => {
973        if (_ckyGetLaw() !== "ccpa" || !_ckyFindCheckBoxValue()) {
974            _ckyAcceptReject()();
975            return;
976        }
977        _ckyAcceptCookies();
978        _ckyShowOptoutSuccessMessage();
979    };
980}
981
982/**
983 * Opt-out popup close: dismiss countdown if success is visible, else normal close.
984 *
985 * @returns {void}
986 */
987function _ckyHandleOptoutPopupClose() {
988    if (_ckyIsOptoutSuccessVisible()) {
989        ref._ckySetInStore("action", "yes");
990        _ckyDismissOptoutSuccessCountdown();
991        return;
992    }
993    _ckyHidePreferenceCenter();
994}
995
996/**
997 * Render banner after processing.
998 */
999function _ckyRenderBanner() {
1000    const template = document.getElementById('ckyBannerTemplate');
1001    const templateHtml = template.innerHTML;
1002    const doc = new DOMParser().parseFromString(templateHtml, 'text/html');
1003    _ckySetFooterShadow(doc);
1004    document.body.insertAdjacentHTML(
1005        "afterbegin",
1006        doc.body.innerHTML
1007    );
1008    if (_ckyGetType() === "classic") _ckyToggleAriaExpandStatus("=settings-button", "false");
1009    _ckySetPreferenceCheckBoxStates();
1010    _ckyAttachCategoryListeners();
1011    _ckyRegisterListeners();
1012    _ckySetCCPAOptions();
1013    _ckySetPlaceHolder();
1014    _ckyAttachReadMore();
1015    _ckyAttachShowMoreLessStyles();
1016    _ckyAttachAlwaysActiveStyles();
1017    _ckyAttachManualLinksStyles();
1018    _ckyRemoveStyles();
1019    _ckyAddPositionClass();
1020    _ckyAddRtlClass();
1021    _ckySetPoweredBy();
1022    _ckyLoopFocus();
1023    _ckyAddPreferenceCenterClass();
1024}
1025
1026/**
1027 * Accept or reject the consent based on the option.
1028 * 
1029 * @param {string} option Type of consent. 
1030 * @returns {void}
1031 */
1032function _ckyAcceptReject(option = "custom") {
1033    return () => {
1034        _ckyAcceptCookies(option);
1035        _ckyRemoveBanner();
1036        _ckyHidePreferenceCenter();
1037        _ckyAfterConsent();
1038    };
1039}
1040
1041function _ckyActionClose() {
1042    ref._ckySetInStore("action", "yes");
1043    if (_ckyIsOptoutSuccessVisible()) {
1044        _ckyDismissOptoutSuccessCountdown();
1045        return;
1046    }
1047    _ckyRemoveBanner();
1048}
1049/**
1050 * Consent accept callback.
1051 * 
1052 * @param {string} choice  Type of consent.
1053 */
1054function _ckyAcceptCookies(choice = "all") {
1055    const activeLaw = _ckyGetLaw();
1056    const ccpaCheckBoxValue = _ckyFindCheckBoxValue();
1057
1058    ref._ckySetInStore("action", "yes");
1059    if (activeLaw === 'gdpr') {
1060        ref._ckySetInStore("consent", choice === "reject" ? "no" : "yes");
1061    } else {
1062        ref._ckySetInStore("consent", ccpaCheckBoxValue ? "yes" : "no");
1063    }
1064    const responseCategories = { accepted: [], rejected: [] };
1065    for (const category of _ckyStore._categories) {
1066        let valueToSet = "no";
1067        if (activeLaw === 'gdpr') {
1068            valueToSet =
1069                !category.isNecessary &&
1070                    (choice === "reject" ||
1071                        (choice === "custom" && !_ckyFindCheckBoxValue(category.slug)))
1072                    ? "no"
1073                    : "yes";
1074        } else {
1075            valueToSet = ccpaCheckBoxValue && !category.defaultConsent.ccpa ? "no" : "yes";
1076        }
1077        ref._ckySetInStore(`${category.slug}`, valueToSet);
1078        if (valueToSet === "no") {
1079            responseCategories.rejected.push(category.slug);
1080            _ckyRemoveDeadCookies(category);
1081        } else responseCategories.accepted.push(category.slug);
1082    }
1083    _ckyUnblock();
1084    _ckyFireEvent(responseCategories);
1085}
1086function _ckySetShowMoreLess() {
1087    const activeLaw = _ckyGetLaw();
1088    const showCode = _ckyStore._shortCodes.find(
1089        (code) => code.key === "cky_show_desc"
1090    );
1091    const hideCode = _ckyStore._shortCodes.find(
1092        (code) => code.key === "cky_hide_desc"
1093    );
1094
1095    if (!showCode || !hideCode) return;
1096    const hideButtonContent = hideCode.content;
1097    const showButtonContent = showCode.content;
1098
1099    const contentLimit = window.innerWidth < 376 ? 150 : 300;
1100    const element = document.querySelector(
1101        `[data-cky-tag="${activeLaw === "gdpr" ? "detail" : "optout"}-description"]`
1102    );
1103    if (!element) return;
1104    const content = element.textContent;
1105    if (content.length < contentLimit) return;
1106    const contentHTML = element.innerHTML;
1107    const htmlDoc = new DOMParser().parseFromString(contentHTML, "text/html");
1108    const innerElements = htmlDoc.querySelectorAll("body > p");
1109    if (innerElements.length <= 1) return;
1110    let strippedContent = ``;
1111    for (let index = 0; index < innerElements.length; index++) {
1112        if (index === innerElements.length - 1) continue;
1113        const el = innerElements[index];
1114        if (`${strippedContent}${el.outerHTML}`.length > contentLimit)
1115            el.insertAdjacentHTML("beforeend", `...&nbsp;${showButtonContent}`);
1116        strippedContent = `${strippedContent}${el.outerHTML}`;
1117        if (strippedContent.length > contentLimit) break;
1118    }
1119
1120    function showMoreHandler() {
1121        element.innerHTML = `${contentHTML}${hideButtonContent}`;
1122        _ckyAttachListener("=hide-desc-button", showLessHandler);
1123        _ckyAttachShowMoreLessStyles();
1124    }
1125    function showLessHandler() {
1126        element.innerHTML = strippedContent;
1127        _ckyAttachListener("=show-desc-button", showMoreHandler);
1128        _ckyAttachShowMoreLessStyles();
1129    }
1130    showLessHandler();
1131}
1132/**
1133 * Toggle show more or less on click event.
1134 * 
1135 * @param {object} object Object containing toggle buttons and texts.
1136 * @param {*} element Target element.
1137 */
1138function _ckyToggleMoreLess(object, element) {
1139    let {
1140        currentTarget,
1141        target
1142    } = element;
1143    if (target && target.tagName.toUpperCase() !== 'BUTTON') return;
1144    const ariaExpanded = currentTarget.getAttribute('aria-expanded');
1145    const trimmed = ariaExpanded === 'false';
1146    let btn = object.btnTrim;
1147    let text = object.originalText;
1148    if (!trimmed) {
1149        btn = object.btnExpand;
1150        text = object.truncatedText;
1151    }
1152    currentTarget.innerHTML = `${text}${btn}`;
1153    currentTarget.ariaExpanded = trimmed;
1154}
1155
1156/**
1157 * Add styles to the shortcode HTML rendered outside of the banner.
1158 * 
1159 * @returns {void}
1160 */
1161function _ckyAttachShortCodeStyles() {
1162    const shortCodes = _ckyStore._tags;
1163    Array.prototype.forEach.call(shortCodes, function (shortcode) {
1164        document.querySelectorAll('[data-cky-tag=' + shortcode.tag + ']').forEach(function (item) {
1165            let styles = '';
1166            for (const key in shortcode.styles) {
1167                styles += `${key}: ${shortcode.styles[key]};`;
1168            }
1169            item.style.cssText = styles;
1170        });
1171    });
1172}
1173
1174/** Script blocker Version 2 */
1175
1176const _ckyCreateElementBackup = document.createElement;
1177document.createElement = (...args) => {
1178    const createdElement = _ckyCreateElementBackup.call(document, ...args);
1179    if (createdElement.nodeName.toLowerCase() !== "script") return createdElement;
1180    const originalSetAttribute = createdElement.setAttribute.bind(createdElement);
1181    Object.defineProperties(createdElement, {
1182        src: {
1183            get: function () {
1184                return createdElement.getAttribute("src");
1185            },
1186            set: function (value) {
1187                if (_ckyShouldChangeType(createdElement, value))
1188                    originalSetAttribute("type", "javascript/blocked");
1189                originalSetAttribute("src", value);
1190                return true;
1191            },
1192        },
1193        type: {
1194            get: function () {
1195                return createdElement.getAttribute("type");
1196            },
1197            set: function (value) {
1198                value = _ckyShouldChangeType(createdElement)
1199                    ? "javascript/blocked"
1200                    : value;
1201                originalSetAttribute("type", value);
1202                return true;
1203            },
1204        },
1205    });
1206    createdElement.setAttribute = (name, value) => {
1207        if (name === "type" || name === "src")
1208            return (createdElement[name] = value);
1209        originalSetAttribute(name, value);
1210        if (name === "data-cookieyes" && !_ckyShouldChangeType(createdElement))
1211            originalSetAttribute("type", "text/javascript");
1212    };
1213    return createdElement;
1214};
1215
1216function _ckyMutationObserver(mutations) {
1217    for (const { addedNodes } of mutations) {
1218        for (const node of addedNodes) {
1219            if (
1220                !node.src ||
1221                !node.nodeName ||
1222                !["script", "iframe"].includes(node.nodeName.toLowerCase())
1223            )
1224                continue;
1225            try {
1226                const urlToParse = node.src.startsWith("//")
1227                    ? `${window.location.protocol}${node.src}`
1228                    : node.src;
1229                const { hostname, pathname } = new URL(urlToParse);
1230                const cleanedHostname = _ckyCleanHostName(`${hostname}${pathname}`);
1231                _ckyAddProviderToList(node, cleanedHostname);
1232                if (!_ckyShouldBlockProvider(cleanedHostname)) continue;
1233                const uniqueID = ref._ckyRandomString(8, false);
1234                if (node.nodeName.toLowerCase() === "iframe")
1235                    _ckyAddPlaceholder(node, uniqueID);
1236                else {
1237                    node.type = "javascript/blocked";
1238                    const scriptEventListener = function (event) {
1239                        event.preventDefault();
1240                        node.removeEventListener(
1241                            "beforescriptexecute",
1242                            scriptEventListener
1243                        );
1244                    };
1245                    node.addEventListener("beforescriptexecute", scriptEventListener);
1246                }
1247                const position =
1248                    document.head.compareDocumentPosition(node) &
1249                        Node.DOCUMENT_POSITION_CONTAINED_BY
1250                        ? "head"
1251                        : "body";
1252                node.remove();
1253                _ckyStore._backupNodes.push({
1254                    position: position,
1255                    node: node.cloneNode(),
1256                    uniqueID,
1257                });
1258            } catch (error) {
1259            }
1260        }
1261    }
1262}
1263
1264function _ckyUnblock() {
1265    if (navigator.doNotTrack === 1) return;
1266    const ckyconsent = ref._ckyGetFromStore("consent");
1267    if (
1268        _ckyGetLaw() === "gdpr" &&
1269        (!ckyconsent || ckyconsent !== "yes")
1270    )
1271        return;
1272    _ckyStore._backupNodes = _ckyStore._backupNodes.filter(
1273        ({ position, node, uniqueID }) => {
1274            try {
1275                if (_ckyShouldBlockProvider(node.src)) return true;
1276                if (node.nodeName.toLowerCase() === "script") {
1277                    const scriptNode = document.createElement("script");
1278                    scriptNode.src = node.src;
1279                    scriptNode.type = "text/javascript";
1280                    document[position].appendChild(scriptNode);
1281                } else {
1282                    const frame = document.getElementById(uniqueID);
1283                    if (!frame) return false;
1284                    const iframe = document.createElement("iframe");
1285                    iframe.src = node.src;
1286                    iframe.width = frame.offsetWidth;
1287                    iframe.height = frame.offsetHeight;
1288                    frame.parentNode.insertBefore(iframe, frame);
1289                    frame.parentNode.removeChild(frame);
1290                }
1291                return false;
1292            } catch (error) {
1293                console.error(error);
1294                return false;
1295            }
1296        }
1297    );
1298}
1299
1300function _ckyClearListeners() {
1301    _nodeListObserver.disconnect();
1302    document.createElement = _ckyCreateElementBackup;
1303}
1304function _ckyAddProviderToList(node, cleanedHostname) {
1305    const nodeCategory =
1306        node.hasAttribute("data-cookieyes") && node.getAttribute("data-cookieyes");
1307    if (!nodeCategory) return;
1308    const categoryName = nodeCategory.replace("cookieyes-", "");
1309    for (const category of _ckyStore._categories)
1310        if (category.isNecessary && category.slug === categoryName) return;
1311    const provider = _ckyStore._providersToBlock.find(
1312        ({ re }) => re === cleanedHostname
1313    );
1314    if (!provider)
1315        _ckyStore._providersToBlock.push({
1316            re: cleanedHostname,
1317            categories: [categoryName],
1318            fullPath: false,
1319        });
1320    else if (!provider.isOverridden) {
1321        provider.categories = [categoryName];
1322        provider.isOverridden = true;
1323    } else if (!provider.categories.includes(categoryName))
1324        provider.categories.push(categoryName);
1325}
1326
1327const _nodeListObserver = new MutationObserver(_ckyMutationObserver);
1328_nodeListObserver.observe(document.documentElement, {
1329    childList: true,
1330    subtree: true,
1331});
1332function _ckyCleanHostName(name) {
1333    return name.replace(/^www./, "");
1334}
1335
1336function _ckyIsCategoryToBeBlocked(category) {
1337    const cookieValue = ref._ckyGetFromStore(category);
1338    return (
1339        cookieValue === "no" ||
1340        (!cookieValue &&
1341            _ckyStore._categories.some(
1342                (cat) => cat.slug === category && !cat.isNecessary
1343            ))
1344    );
1345}
1346
1347function _ckyShouldBlockProvider(formattedRE) {
1348    const provider = _ckyStore._providersToBlock.find(({ re }) =>
1349        new RegExp(_ckyEscapeRegex(re)).test(formattedRE)
1350    );
1351    return (
1352        provider &&
1353        provider.categories.some((category) => _ckyIsCategoryToBeBlocked(category))
1354    );
1355}
1356function _ckyShouldChangeType(element, src) {
1357    return (
1358        (element.hasAttribute("data-cookieyes") &&
1359            _ckyIsCategoryToBeBlocked(
1360                element.getAttribute("data-cookieyes").replace("cookieyes-", "")
1361            )) ||
1362        _ckyShouldBlockProvider(src ? src : element.src)
1363    );
1364}
1365
1366/**
1367 * Add readmore button to consent notice.
1368 * 
1369 * @returns void
1370 */
1371function _ckyAttachReadMore() {
1372    const readMoreButton = _ckyStore._shortCodes.find(
1373        (code) => code.key === "cky_readmore"
1374    );
1375    if (!readMoreButton.status) return;
1376    const content = readMoreButton.content;
1377    const styles = _ckyStore._bannerConfig.config.readMore.styles;
1378    const readMoreElement = document.querySelector(
1379        '[data-cky-tag="description"]'
1380    );
1381    if (!readMoreElement) return;
1382    if (readMoreElement.childNodes.length > 1) {
1383        const innerElement = document.querySelector(
1384            '[data-cky-tag="description"] p:last-child'
1385        );
1386        innerElement && innerElement.insertAdjacentHTML(
1387            "beforeend",
1388            `&nbsp;${content}`
1389        );
1390    } else {
1391        readMoreElement.insertAdjacentHTML(
1392            "beforeend",
1393            `&nbsp;${content}`
1394        );
1395    }
1396    const placeHolders = document.querySelectorAll(
1397        `[data-cky-tag="readmore-button"]`
1398    );
1399    if (placeHolders.length < 1) return;
1400    Array.from(placeHolders).forEach((placeHolder) => {
1401        for (const style in styles) {
1402            if (!styles[style]) continue;
1403            placeHolder.style[style] = styles[style];
1404        }
1405    });
1406}
1407
1408/**
1409 * Apply styles to show more/show less buttons.
1410 * 
1411 * @returns void
1412 */
1413function _ckyAttachShowMoreLessStyles() {
1414    if (!_ckyStore._bannerConfig.config.showMore || !_ckyStore._bannerConfig.config.showLess) return;
1415    
1416    const showMoreStyles = _ckyStore._bannerConfig.config.showMore.styles;
1417    const showLessStyles = _ckyStore._bannerConfig.config.showLess.styles;
1418    
1419    if (showMoreStyles) {
1420        const showMoreButtons = document.querySelectorAll('[data-cky-tag="show-desc-button"]');
1421        if (showMoreButtons.length > 0) {
1422            Array.from(showMoreButtons).forEach((button) => {
1423                for (const style in showMoreStyles) {
1424                    if (!showMoreStyles[style]) continue;
1425                    button.style[style] = showMoreStyles[style];
1426                }
1427            });
1428        }
1429    }
1430    
1431    if (showLessStyles) {
1432        const showLessButtons = document.querySelectorAll('[data-cky-tag="hide-desc-button"]');
1433        if (showLessButtons.length > 0) {
1434            Array.from(showLessButtons).forEach((button) => {
1435                for (const style in showLessStyles) {
1436                    if (!showLessStyles[style]) continue;
1437                    button.style[style] = showLessStyles[style];
1438                }
1439            });
1440        }
1441    }
1442}
1443
1444/**
1445 * Apply styles to Always Active text.
1446 * 
1447 * @returns void
1448 */
1449function _ckyAttachAlwaysActiveStyles() {
1450    if (!_ckyStore._bannerConfig.config.alwaysActive) return;
1451    
1452    const alwaysActiveStyles = _ckyStore._bannerConfig.config.alwaysActive.styles;
1453    if (!alwaysActiveStyles) return;
1454    
1455    const alwaysActiveElements = document.querySelectorAll('.cky-always-active');
1456    if (alwaysActiveElements.length < 1) return;
1457    Array.from(alwaysActiveElements).forEach((element) => {
1458        for (const style in alwaysActiveStyles) {
1459            if (!alwaysActiveStyles[style]) continue;
1460            element.style[style] = alwaysActiveStyles[style];
1461        }
1462    });
1463}
1464
1465/**
1466 * Apply styles to manually added links.
1467 * 
1468 * @returns void
1469 */
1470function _ckyAttachManualLinksStyles() {
1471    if (!_ckyStore._bannerConfig.config.manualLinks) return;
1472    
1473    const manualLinksStyles = _ckyStore._bannerConfig.config.manualLinks.styles;
1474    if (!manualLinksStyles) return;
1475    
1476    const manualLinks = document.querySelectorAll('.cky-link, a.cky-link, [data-cky-tag="detail"] a, [data-cky-tag="optout-popup"] a, [data-cky-tag="notice"] a');
1477    if (manualLinks.length < 1) return;
1478    Array.from(manualLinks).forEach((link) => {
1479        if (link.getAttribute('data-cky-tag') === 'readmore-button') return;
1480        for (const style in manualLinksStyles) {
1481            if (!manualLinksStyles[style]) continue;
1482            link.style[style] = manualLinksStyles[style];
1483        }
1484        if (manualLinksStyles.color) {
1485            link.style.textDecorationColor = manualLinksStyles.color;
1486        }
1487    });
1488}
1489
1490function _ckyAfterConsent() {
1491    if (_ckyGetLaw() === 'gdpr') _ckySetPreferenceCheckBoxStates(true);
1492
1493    if (_ckyStore._bannerConfig.behaviours.reloadBannerOnAccept === true) {
1494        window.location.reload();
1495    }
1496}
1497
1498function _ckyAttachNoticeStyles() {
1499    if (document.getElementById("cky-style") || !_ckyStyle) return;
1500    document.head.insertAdjacentHTML(
1501        "beforeend",
1502        ` <style id="cky-style">${_ckyStyle.css}</style>`
1503    );
1504}
1505
1506function _ckyFindCheckBoxValue(id = "") {
1507    const elementsToCheck = id
1508        ? [`ckySwitch`, `ckyCategoryDirect`]
1509        : [`ckyCCPAOptOut`];
1510    return elementsToCheck.some((key) => {
1511        const checkBox = document.getElementById(`${key}${id}`);
1512        return checkBox && checkBox.checked;
1513    });
1514}
1515
1516function _ckyAddPlaceholder(htmlElm, uniqueID) {
1517    const shortCodeData = _ckyStore._shortCodes.find(
1518        (code) => code.key === 'cky_video_placeholder'
1519    );
1520    const videoPlaceHolderDataCode = shortCodeData.content;
1521    const { offsetWidth, offsetHeight } = htmlElm;
1522    if (offsetWidth === 0 || offsetHeight === 0) return;
1523    htmlElm.insertAdjacentHTML(
1524        "beforebegin",
1525        `${videoPlaceHolderDataCode}`.replace("[UNIQUEID]", uniqueID)
1526    );
1527    const addedNode = document.getElementById(uniqueID);
1528    addedNode.style.width = `${offsetWidth}px`;
1529    addedNode.style.height = `${offsetHeight}px`;
1530    const innerTextElement = document.querySelector(
1531        `#${uniqueID} .video-placeholder-text-normal`
1532    );
1533    innerTextElement.style.display = "none";
1534    const youtubeID = _ckyGetYoutubeID(htmlElm.src);
1535    if (!youtubeID) return;
1536    addedNode.classList.replace(
1537        "video-placeholder-normal",
1538        "video-placeholder-youtube"
1539    );
1540    addedNode.style.backgroundImage = `linear-gradient(rgba(76,72,72,.7),rgba(76,72,72,.7)),url('https://img.youtube.com/vi/${youtubeID}/maxresdefault.jpg')`;
1541    innerTextElement.classList.replace(
1542        "video-placeholder-text-normal",
1543        "video-placeholder-text-youtube"
1544    );
1545}
1546function _ckyGetYoutubeID(src) {
1547    const match = src.match(
1548        /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
1549    );
1550    if (match && Array.isArray(match) && match[2] && match[2].length === 11)
1551        return match[2];
1552    return false;
1553}
1554
1555function _ckySetPlaceHolder() {
1556    const status = _ckyStore._bannerConfig.config.videoPlaceholder.status;
1557    const styles = _ckyStore._bannerConfig.config.videoPlaceholder.styles;
1558    if (!status) return;
1559    if (!status) return;
1560    const placeHolders = document.querySelectorAll(
1561        `[data-cky-tag="placeholder-title"]`
1562    );
1563    if (placeHolders.length < 1) return;
1564    Array.from(placeHolders).forEach((placeHolder) => {
1565        placeHolder.style.display = "block";
1566        placeHolder.addEventListener("click", () => {
1567            if (ref._ckyGetFromStore("action")) _revisitCkyConsent();
1568        });
1569        for (const style in styles) {
1570            if (!styles[style]) continue;
1571            placeHolder.style[style] = styles[style];
1572        }
1573    });
1574}
1575function _ckyAddRtlClass() {
1576    if (!_ckyStore._rtl) return;
1577    const rtlElements = ['notice', 'detail', 'optout-popup', 'revisit-consent', 'video-placeholder']
1578    rtlElements.forEach(function (item) {
1579        _ckyGetElementByTag(item) && _ckyGetElementByTag(item).classList.add('cky-rtl');
1580    });
1581}
1582
1583function _ckySetFocus(tagName) {
1584    const element = _ckyGetElementByTag(tagName);
1585    if (!element) return;
1586    element.focus();
1587}
1588
1589function _ckySetPoweredBy() {
1590    let position = 'flex-end';
1591    ['detail-powered-by', 'optout-powered-by'].map((key) => {
1592        const element = document.querySelector(
1593            `[data-cky-tag="${key}"]`
1594        );
1595        if (!element) return;
1596        element.style.display = "flex";
1597        element.style.justifyContent = position;
1598        element.style.alignItems = "center";
1599        return element;
1600    });
1601
1602}
1603function _ckyWatchBannerElement() {
1604    document.querySelector("body").addEventListener("click", (event) => {
1605        const selector = ".cky-banner-element, .cky-banner-element *";
1606        if (
1607            event.target.matches
1608                ? event.target.matches(selector)
1609                : event.target.msMatchesSelector(selector)
1610        )
1611            _revisitCkyConsent();
1612    });
1613}
1614
1615function _ckyRemoveAllDeadCookies() {
1616    for (const category of _ckyStore._categories) {
1617        if (ref._ckyGetFromStore(category.slug) !== "yes")
1618            _ckyRemoveDeadCookies(category);
1619    }
1620}
1621
1622function _ckySetCCPAOptions() {
1623    const toggle = _ckyStore._bannerConfig.config.optOption.toggle;
1624    const activeColor = toggle.states.active.styles['background-color'];
1625    const inactiveColor = toggle.states.inactive.styles['background-color'];
1626    _ckyClassRemove("=optout-option", "cky-disabled", false);
1627    const toggleDataCode = _ckyStore._shortCodes.find(
1628        (code) => code.key === "cky_optout_toggle_label"
1629    );
1630    const optOutTitle = _ckyStore._shortCodes.find(
1631        (code) => code.key === "cky_optout_option_title"
1632    );
1633    const formattedLabel = toggleDataCode.content.replace(
1634        `[cky_optout_option_title]`,
1635        optOutTitle.content
1636    );
1637    const checked = ref._ckyGetFromStore("consent") === "yes";
1638    _ckySetCheckBoxInfo(
1639        document.getElementById(`ckyCCPAOptOut`),
1640        formattedLabel,
1641        {
1642            checked,
1643            disabled: false,
1644            addListeners: true,
1645        },
1646        { activeColor, inactiveColor },
1647        true
1648    );
1649}
1650function _ckySetCheckBoxInfo(
1651    boxElem,
1652    formattedLabel,
1653    { checked, disabled, addListeners },
1654    { activeColor, inactiveColor },
1655    isCCPA = false
1656) {
1657    if (!boxElem) return;
1658    if (isCCPA && addListeners)
1659        _ckyAttachListener("=optout-option-title", () => boxElem.click());
1660    boxElem.checked = checked;
1661    boxElem.disabled = disabled;
1662    boxElem.style.backgroundColor = checked ? activeColor : inactiveColor;
1663    _ckySetCheckBoxAriaLabel(boxElem, checked, formattedLabel, isCCPA);
1664    if (!addListeners) return;
1665    boxElem.addEventListener("change", ({ currentTarget: elem }) => {
1666        const isChecked = elem.checked;
1667        elem.style.backgroundColor = isChecked ? activeColor : inactiveColor;
1668        _ckySetCheckBoxAriaLabel(boxElem, isChecked, formattedLabel, isCCPA);
1669    });
1670}
1671
1672window.revisitCkyConsent = () => _revisitCkyConsent();
1673
1674window.getCkyConsent = function () {
1675    const cookieConsent = {
1676        activeLaw: "",
1677        categories: {},
1678        isUserActionCompleted: false,
1679        consentID: "",
1680        languageCode: ""
1681    };
1682
1683    try {
1684        cookieConsent.activeLaw = _ckyGetLaw();
1685
1686        _ckyStore._categories.forEach(category => {
1687            cookieConsent.categories[category.slug] = ref._ckyGetFromStore(category.slug) === "yes";
1688        });
1689
1690        cookieConsent.isUserActionCompleted = ref._ckyGetFromStore("action") === "yes";
1691        cookieConsent.consentID = ref._ckyGetFromStore("consentid") || "";
1692        cookieConsent.languageCode = _ckyStore._language || "";
1693    } catch (e) { }
1694
1695    return cookieConsent;
1696};

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.