PageSourceSearch

https://vallummag.com/wp-content/plugins/complianz-gdpr/cookiebanner/js/complianz.js?ver=1790855909

js vallummag.com collected 2026-10-01 12:00:45 UTC 75,385 bytes, 2,382 lines download raw bytes

1'use strict';
2/*
3 * Opt in (e.g. EU):
4 * default all scripts disabled.
5 * cookie banner
6 *
7 * Opt out (e.g. US):
8 * default all scripts enabled
9 * opt out cookie banner
10 *
11 * Other regions:
12 * default all scripts enabled
13 * no banner
14 *
15 *
16 * For examples to edit the behaviour of the banner, please see https://github.com/really-Simple-Plugins/complianz-integrations
17 * */
18
19/*
20 * Create an element
21 * @param el
22 * @param content
23 * @returns {*}
24 */
25function cmplz_create_element(el, content) {
26	let obj = document.createElement(el);
27	obj.innerHtml = content;
28	return obj;
29}
30
31/*
32 * Add an event
33 * @param event
34 * @param selector
35 * @param callback
36 * @param context
37 */
38function cmplz_add_event(event, selector, callback ) {
39	document.addEventListener(event, e => {
40		if ( e.target.closest(selector) ) {
41			callback(e);
42		}
43	});
44}
45
46/*
47 * Check if the element is hidden
48 * @param el
49 * @returns {boolean}
50 */
51function cmplz_is_hidden(el) {
52	return (el.offsetParent === null)
53}
54
55function cmplz_html_decode(input) {
56	var doc = new DOMParser().parseFromString(input, "text/html");
57	return doc.documentElement.textContent;
58}
59/**
60 * Consent Area management for shortcode and block editor
61 */
62document.querySelectorAll('.cmplz-consent-area.cmplz-placeholder').forEach(cmplzConsentArea => {
63	cmplzConsentArea.addEventListener('click', e => {
64		let container = e.target;
65		if ( !container.classList.contains('cmplz-consent-area') ) {
66			container = e.target.closest('.cmplz-consent-area.cmplz-placeholder');
67		}
68		if (container) {
69			let consentedService = container.getAttribute('data-service');
70			cmplz_set_service_consent(consentedService, true);
71			cmplzLoadConsentAreaContent(false, consentedService);
72			cmplz_enable_category(null, consentedService);
73			cmplz_set_banner_status('dismissed');
74		}
75
76	});
77
78	document.addEventListener("cmplz_enable_category", function(consentData) {
79		var consentedCategory = consentData.detail.category;
80		var consentedService = consentData.detail.service;
81		cmplzLoadConsentAreaContent(consentedCategory, consentedService)
82	});
83});
84
85function cmplzLoadConsentAreaContent(consentedCategory, consentedService){
86	document.querySelectorAll('.cmplz-consent-area.cmplz-placeholder').forEach(obj => {
87		let category = obj.getAttribute('data-category');
88		let service = obj.getAttribute('data-service');
89		let postId = obj.getAttribute('data-post_id');
90		let blockId = obj.getAttribute('data-block_id');
91		if ( consentedCategory === category || consentedService === service ) {
92			//if not stored yet, load. As features in the user object can be changed on updates, we also check for the version
93			let request = new XMLHttpRequest();
94			request.open('GET', complianz.url+'consent-area/'+postId+'/'+blockId, true);
95			request.setRequestHeader('Content-type', 'application/json');
96			request.send();
97			obj.classList.remove('cmplz-placeholder');
98			request.onload = function() {
99				obj.innerHTML = JSON.parse(request.response);
100				//search for script elements and execute them
101				obj.querySelectorAll('script').forEach(scriptEl => {
102					cmplz_run_script(scriptEl.innerHTML, category, service, 'inline', scriptEl);
103				})
104			};
105		}
106	});
107}
108
109/*
110 * If an anchor is passed for an element which may load only after an ajax call, make sure it will scroll into view.
111 */
112document.addEventListener('cmplz_manage_consent_container_loaded', function(e){
113	let url = window.location.href;
114	if ( url.indexOf('#') != -1 ) {
115		let end_pos = url.lastIndexOf("?") != -1 ? url.lastIndexOf("?") : undefined;
116		var anchor = url.substring(url.indexOf("#") + 1, end_pos);
117		const element = document.getElementById(anchor);
118		if (element) {
119			const y = element.getBoundingClientRect().top + window.pageYOffset - 200;
120			window.scrollTo({top: y, behavior: 'smooth'});
121		}
122	}
123});
124
125/*
126 * prevent caching of the WP Rest API by varnish or other caching tools
127 */
128complianz.locale = complianz.locale + '&token='+Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
129
130/*
131 * CustomEvent() polyfill
132 * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
133 */
134(function () {
135	if (typeof window.CustomEvent === 'function') return false;
136	function CustomEvent(event, params) {
137		params = params || { bubbles: false, cancelable: false, detail: undefined };
138		var evt = document.createEvent('CustomEvent');
139		evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
140		return evt;
141	}
142	CustomEvent.prototype = window.Event.prototype;
143	window.CustomEvent = CustomEvent;
144})();
145
146let cmplz_banner;//look this one up when the cookiebanner loads.
147let cmplz_banner_container = document.getElementById('cmplz-cookiebanner-container');
148let cmplz_manage_consent_button;
149let cmplz_waiting_inline_scripts = [];
150let cmplz_waiting_scripts = [];
151let cmplz_fired_scripts = [];
152let cmplz_placeholder_class_index = 0;
153let cmplz_all_scripts_hook_fired = false;
154let cmplz_consent_stored_once = false;
155let cmplz_fired_category_events = ['functional'];
156let cmplz_fired_service_events = [];
157let cmplz_categories = [
158	'functional',
159	'preferences',
160	'statistics',
161	'marketing',
162];
163
164/*
165 * Get a cookie by name
166 * @param name
167 * @returns {string}
168 */
169
170window.cmplz_get_cookie = function (name) {
171	if (typeof document === "undefined") {
172		return "";
173	}
174	name = complianz.prefix + name;
175	const value = "; " + document.cookie;
176	const parts = value.split("; " + name + "=");
177	if ( parts.length === 2 ) {
178		return parts.pop().split(";").shift();
179	}
180
181	return "";
182};
183
184/*
185 * set a cookie
186 * @param name
187 * @param value
188 * @param use_prefix
189 */
190
191window.cmplz_set_cookie = function(name, value, use_prefix) {
192	if (typeof document === 'undefined') {
193		return;
194	}
195	if (typeof use_prefix === 'undefined') {
196		use_prefix = true;
197	}
198	let secure = ";secure";
199	let date = new Date();
200	date.setTime(date.getTime() + (complianz.cookie_expiry * 24 * 60 * 60 * 1000));
201	let expires = ";expires=" + date.toGMTString();
202
203	if (window.location.protocol !== "https:") secure = '';
204
205	let domain = cmplz_get_cookie_domain();
206	if (domain.length > 0) {
207		domain = ";domain=" + domain;
208	}
209	let prefix = '';
210	if ( use_prefix ) {
211		prefix = complianz.prefix;
212	}
213	document.cookie = prefix+name + "=" + value + ";SameSite=Lax" + secure + expires + domain + ";path="+cmplz_get_cookie_path();
214}
215
216/*
217 * Check if needle occurs in the haystack
218 * @param needle
219 * @param haystack
220 * @returns {boolean}
221 */
222window.cmplz_in_array = function(needle, haystack) {
223	let length = haystack.length;
224	for(let i = 0; i < length; i++) {
225		if(haystack[i] == needle) return true;
226	}
227	return false;
228}
229
230/*
231 * Retrieve the highest level of consent that has been given
232 *
233 * */
234
235window.cmplz_highest_accepted_category = function() {
236	var consentedCategories = cmplz_accepted_categories();
237	if (cmplz_in_array( 'marketing', consentedCategories )) {
238		return 'marketing';
239	}
240
241	if (cmplz_in_array( 'statistics', consentedCategories )) {
242		return 'statistics';
243	}
244
245	if (cmplz_in_array( 'preferences', consentedCategories )) {
246		return 'preferences';
247	}
248
249	return 'functional';
250}
251
252/*
253 * Sets all accepted categories as class in body
254 */
255
256function cmplz_set_category_as_body_class() {
257	let classList = document.body.className.split(/\s+/);
258	for (let i = 0; i < classList.length; i++) {
259		if ( classList[i].indexOf('cmplz-') !== -1 && classList[i] !== 'cmplz-document' ) {
260			document.body.classList.remove( classList[i] );
261		}
262	}
263
264	let cats = cmplz_accepted_categories();
265	for (let i in cats) {
266		if ( cats.hasOwnProperty(i) ) {
267			document.body.classList.add('cmplz-' + cats[i]);
268		}
269	}
270
271	let services = cmplz_get_all_service_consents();
272	for (let service in services) {
273		if ( services.hasOwnProperty(service) && services[service]) {
274			document.body.classList.add('cmplz-' + service);
275		}
276	}
277
278	document.body.classList.add('cmplz-' + complianz.region);
279	document.body.classList.add('cmplz-' + complianz.consenttype);
280	let event = new CustomEvent('cmplz_set_category_as_bodyclass');
281	document.dispatchEvent(event);
282}
283
284function cmplz_append_css(css){
285	let head = document.getElementsByTagName('head')[0];
286	let style = document.createElement('style');
287	style.setAttribute('type', 'text/css');
288	if (style.styleSheet) {   // IE
289		style.styleSheet.cssText = css;
290	} else {                // the world
291		style.appendChild(document.createTextNode(css));
292	}
293	head.appendChild(style);
294}
295
296function cmplz_load_css( path ) {
297	let targetObj = document.createElement("link")
298	targetObj.setAttribute("rel", "stylesheet")
299	targetObj.setAttribute("type", "text/css")
300	targetObj.setAttribute("href", path)
301	document.getElementsByTagName("head")[0].appendChild(targetObj)
302}
303
304/*
305 * Run script, src or inline
306 * @param script //src or inline script
307 * @param category
308 * @param type
309 */
310
311function cmplz_run_script( script, category, service, type, sourceObj ) {
312	let targetObj = document.createElement("script");
313	if ( type !== 'inline' ) {
314		targetObj.setAttribute("src", script);
315	} else {
316		if (typeof script !== 'string') {
317			script = script.innerHTML;
318		}
319		targetObj.innerHTML = [script, 'cmplzScriptLoaded();'].join('\n');
320	}
321
322	if ( script.includes("import") ) {
323		targetObj.setAttribute("type", "module");
324	}
325
326	//check if already fired
327	if ( cmplz_in_array( script, cmplz_fired_scripts) ) {
328		return;
329	}
330
331	cmplzCopyAttributes(sourceObj, targetObj);
332
333	try {
334		if (type!=='inline') {
335			targetObj.onload = function () {
336				cmplz_run_after_all_scripts(category, service);
337				cmplz_maybe_run_waiting_scripts(script, category, service, sourceObj);
338			}
339		} else {
340			window.cmplzScriptLoaded = function() {
341				cmplz_run_after_all_scripts(category, service);
342				cmplz_maybe_run_waiting_scripts(script, category, service, sourceObj);
343			}
344		}
345		let header = document.getElementsByTagName("head")[0];
346		header.appendChild(targetObj);
347
348	} catch(exception) {
349		//only runs in case of error
350		cmplz_run_after_all_scripts(category, service);
351		throw "Something went wrong " + exception + " while loading "+script;
352	}
353
354}
355
356
357/*
358 * Check if there are waiting scripts, and if so, run them.
359 * @param script //src or inline script
360 * @param category
361 */
362
363function cmplz_maybe_run_waiting_scripts( script, category, service, sourceObj ){
364	let waitingScript = cmplz_get_waiting_script(cmplz_waiting_scripts, script);
365	if ( waitingScript ) {
366		cmplz_run_script( waitingScript, category, service, 'src', sourceObj );
367	}
368
369	let waiting_inline_script = cmplz_get_waiting_script(cmplz_waiting_inline_scripts, script);
370	if (waiting_inline_script) {
371		cmplz_run_script(waiting_inline_script, category, service, 'inline', sourceObj);
372	}
373}
374
375const cmplzLazyLoader = () => {
376	// Get all elements with the "lazy-load" class
377	const cmplzLazyLoadElements = document.querySelectorAll('.cmplz-blocked-content-container');
378
379	// Create an Intersection Observer instance
380	const cmplzObserver = new IntersectionObserver((entries, observer) => {
381		entries.forEach((entry) => {
382			if (entry.isIntersecting) {
383				// When the element is in view, load the background image
384				const element = entry.target;
385				let src = element.getAttribute('data-placeholder-image');
386				let index = element.getAttribute('data-placeholder_class_index');
387				cmplz_append_css('.cmplz-placeholder-' + index + ' {background-image: url(' + src + ') !important;}');
388				cmplz_set_blocked_content_container_aspect_ratio(element, src, index);
389				// Stop observing the element
390				observer.unobserve(element);
391			}
392
393		});
394	});
395
396	// Start observing each lazy-load element
397	cmplzLazyLoadElements.forEach((element) => {
398		cmplzObserver.observe(element);
399	});
400}
401
402/*
403 * Set placeholder image as background on the parent div, set notice, and handle height.
404 *
405 * */
406
407function cmplz_set_blocked_content_container() {
408	//to prevent this function to twice run on an element, we add an attribute to each element that has been processed.
409	//then skip elements with that element.
410	document.querySelectorAll('.cmplz-image').forEach(obj => {
411		if ( obj.classList.contains('cmplz-processed') ) {
412			return;
413		}
414		obj.classList.add('cmplz-processed' );
415		let service = obj.getAttribute('data-service');
416		let category = obj.getAttribute('data-category');
417		let blocked_image_container = obj.parentElement;
418		blocked_image_container.classList.add('cmplz-blocked-content-container');
419		let curIndex = blocked_image_container.getAttribute('data-placeholder_class_index');
420		//handle browser native lazy load feature
421		if (obj.getAttribute('loading') === 'lazy' ) {
422			obj.removeAttribute('loading');
423			obj.setAttribute('data-deferlazy', 1);
424		}
425
426		if ( curIndex == null ) {
427			cmplz_placeholder_class_index++;
428			blocked_image_container.classList.add('cmplz-placeholder-' + cmplz_placeholder_class_index);
429			blocked_image_container.classList.add('cmplz-blocked-content-container');
430			blocked_image_container.setAttribute('data-placeholder_class_index', cmplz_placeholder_class_index);
431			cmplz_insert_placeholder_text(blocked_image_container, category, service);
432		}
433	});
434
435	document.querySelectorAll('.cmplz-placeholder-element').forEach(obj => {
436		if ( obj.classList.contains('cmplz-processed') ) {
437			return;
438		}
439		obj.classList.add('cmplz-processed' );
440		let service = obj.getAttribute('data-service');
441		let category = obj.getAttribute('data-category');
442
443		//we set this element as container with placeholder image
444		let blocked_content_container;
445		if ( obj.classList.contains('cmplz-iframe')) {
446			//handle browser native lazy load feature
447			if ( obj.getAttribute('loading') === 'lazy' ) {
448				obj.removeAttribute('loading');
449				obj.setAttribute('data-deferlazy', 1);
450			}
451			blocked_content_container = obj.parentElement;
452		} else {
453			blocked_content_container = obj;
454		}
455		let curIndex = blocked_content_container.getAttribute('data-placeholder_class_index');
456		//if the blocked content container class is already added, don't add it again
457		if ( curIndex == null ) {
458			cmplz_placeholder_class_index++;
459			blocked_content_container.classList.add('cmplz-placeholder-' + cmplz_placeholder_class_index);
460			blocked_content_container.classList.add('cmplz-blocked-content-container');
461			blocked_content_container.setAttribute('data-placeholder_class_index', cmplz_placeholder_class_index);
462			cmplz_insert_placeholder_text(blocked_content_container, category, service);
463			//handle image size for video
464			let src = obj.getAttribute('data-placeholder-image');
465			if (src && typeof src !== 'undefined' && src.length ) {
466				//move src to parent, if needed.
467				blocked_content_container.setAttribute('data-placeholder-image', src);
468			}
469		}
470	});
471
472	cmplzLazyLoader();
473
474	/*
475	 * In some cases, like ajax loaded content, the placeholders are initialized again. In that case, the scripts may need to be fired again as well.
476	 * In case of an opt-out region and Do Not Track, a consent check will return 'allow', because it doesn't take DNT into account
477	 */
478
479	if ( cmplz_has_consent('statistics') ) {
480		cmplz_enable_category('statistics');
481	}
482
483	if ( cmplz_has_consent('marketing') ) {
484		cmplz_enable_category('marketing');
485	}
486
487}
488
489function cmplz_insert_placeholder_text(container, category, service ){
490	if ( !container.querySelector( ".cmplz-blocked-content-notice" ) ) {
491		let placeholder_text = complianz.placeholdertext;
492		category = category ? category : 'marketing';
493		let body;
494		if ( typeof placeholder_text !== 'undefined' ) {
495			if ( complianz.clean_cookies == 1 ) {
496				//make service human readable
497				let service_nicename = service ? service.replace('-', ' ') : '';
498				service_nicename = service_nicename.charAt(0).toUpperCase() + service_nicename.slice(1);
499				placeholder_text = placeholder_text.replace('{service}', service_nicename);
500				body = cmplz_create_element('div', placeholder_text);
501				body.innerHTML = placeholder_text;
502				body.classList.add('cmplz-blocked-content-notice');
503				let btn = body.querySelector('button');
504				btn.setAttribute('data-service', service);
505				btn.setAttribute('data-category', category);
506				btn.setAttribute( 'aria-label', complianz.aria_label.replace('{service}', service_nicename) );
507				let pageLinks = complianz.page_links[complianz.region];
508				let link = body.querySelector('.cmplz-links a');
509				if ( pageLinks && pageLinks.hasOwnProperty('cookie-statement') ) {
510					link.setAttribute('href', pageLinks['cookie-statement']['url']);
511					if (link.innerText === '{title}') {
512						link.innerText = pageLinks['cookie-statement']['title'];
513					}
514				}
515			} else {
516				let btn = cmplz_create_element('button', '');
517				let category_nicename = 'marketing';
518				if (complianz.categories.hasOwnProperty(category)){
519					category_nicename = complianz.categories[category];
520				}
521
522				placeholder_text = placeholder_text.replace('{category}', category_nicename);
523				btn.innerText = placeholder_text;
524				btn.classList.add('cmplz-blocked-content-notice');
525				btn.classList.add('cmplz-accept-category');
526
527				//deprecated
528				btn.classList.add('cmplz-accept-'+category);
529				btn.setAttribute('data-service', service );
530				btn.setAttribute('data-category', category );
531				btn.setAttribute( 'aria-label', complianz.aria_label.replace('{category}', category) );
532				body=btn;
533			}
534
535			if ( container.tagName!=='VIDEO' ) {
536				container.appendChild(body);
537			} else{
538				container.parentElement.appendChild(body);
539			}
540
541		}
542	}
543}
544
545/*
546 * Set the height of an image relative to the width, depending on the image widht/height aspect ratio.
547 *
548 *
549 * */
550
551function cmplz_set_blocked_content_container_aspect_ratio(container, src, placeholder_class_index) {
552	if ( container == null ) return;
553
554	//handle image size for video
555	let img = new Image();
556	img.addEventListener("load", function () {
557		let imgWidth = this.naturalWidth;
558		let imgHeight = this.naturalHeight;
559
560		//prevent division by zero.
561		if (imgWidth === 0) imgWidth = 1;
562		let w = container.clientWidth;
563		let h = imgHeight * (w / imgWidth);
564
565		let heightCSS = '';
566		if (src.indexOf('placeholder.jpg') === -1) {
567			heightCSS = 'height:' + h + 'px;';
568		}
569		cmplz_append_css('.cmplz-placeholder-' + placeholder_class_index + ' {' + heightCSS + '}');
570	});
571	img.src = src;
572}
573/*
574 * Keep window aspect ratio in sync when window resizes
575 * To lower the number of times this code is executed, it is done with a timeout.
576 *
577 * */
578
579var cmplzResizeTimer;
580window.addEventListener('resize', function(event) {
581	clearTimeout(cmplzResizeTimer);
582	cmplzResizeTimer = setTimeout( cmplz_set_blocked_content_container, 500);
583}, true);
584
585/*
586 * 	we run this function also on an interval, because with ajax loaded content, the placeholders would otherwise not be handled.
587 */
588if ( complianz.block_ajax_content == 1 ) {
589	setInterval(function () {
590		cmplz_set_blocked_content_container();
591	}, 2000);
592}
593
594/*
595 * Check if there are any blocked scripts on the page
596 * @returns {boolean}
597 */
598function cmplz_has_blocked_scripts(){
599	let scriptElements = document.querySelectorAll('script[data-category], script[data-service]');
600	return scriptElements.length>0;
601}
602/*
603 * Enable scripts that were blocked
604 *
605 * */
606
607function cmplz_enable_category(category, service) {
608	if ( complianz.tm_categories == 1 && category !== '') {
609		cmplz_run_tm_event(category);
610	}
611
612	service = typeof service !== 'undefined' ? service : 'do_not_match';
613	if ( category === '' ) category = 'do_not_match';
614
615	if ( category === 'functional' ) {
616		return;
617	}
618	//enable cookies for integrations
619	if ( category === 'marketing' ) {
620		cmplz_set_integrations_cookies();
621	}
622
623	//remove accept cookie notice overlay
624	let selector;
625	if (service !== 'do_not_match') {
626		selector = '.cmplz-blocked-content-notice [data-service="'+service+'"]';
627	} else {
628		selector = complianz.clean_cookies!=1 ? '.cmplz-blocked-content-notice.cmplz-accept-'+category : '.cmplz-blocked-content-notice [data-category="'+category+'"]';
629	}
630	document.querySelectorAll(selector).forEach(obj => {
631		let blockedElementService = obj.getAttribute('data-service');
632		if (obj.parentNode.classList.contains('cmplz-blocked-content-notice')) {
633			obj = obj.parentNode;
634		}
635		//only remove if the service is not explicitly denied
636		if ( !cmplz_is_service_denied(blockedElementService) ) {
637			obj.parentNode.removeChild(obj);
638		}
639	});
640
641	document.querySelectorAll('[data-category="'+category+'"], [data-service="'+service+'"]').forEach(obj => {
642		//if a category is activated, but this specific service is denied, skip.
643		let elementService = obj.getAttribute('data-service');
644		if ( cmplz_is_service_denied(elementService) ) {
645			return;
646		}
647
648		//if native class is included, it isn't blocked, so will have run already
649		if ( obj.getAttribute('data-category') === 'functional' ) {
650			return;
651		}
652
653		if ( obj.classList.contains('cmplz-activated') ) {
654			return;
655		}
656
657		let tagName = obj.tagName;
658		if (tagName==='LINK'){
659			obj.classList.add('cmplz-activated' );
660			let src = obj.getAttribute('data-href');
661			cmplz_load_css( src, category);
662		} else if (tagName ==='IMG'){
663			obj.classList.add('cmplz-activated' );
664			let src = obj.getAttribute('data-src-cmplz');
665			obj.setAttribute('src', src);
666			//handle browser native lazy load feature
667			if ( obj.getAttribute('data-deferlazy') ) {
668				obj.setAttribute('loading', 'lazy');
669			}
670			cmplz_remove_placeholder(obj);
671		}
672		else if (tagName==='IFRAME'){
673			obj.classList.add('cmplz-activated' );
674			let src = obj.getAttribute('data-src-cmplz');
675			let srcAttribute = obj.getAttribute('data-cmplz-target') ? obj.getAttribute('data-cmplz-target') : 'src';
676
677			//check if there's an autoplay value we need to pass on, if it's added later on by javascript
678			let autoplay = cmplz_get_url_parameter(obj.getAttribute(srcAttribute), 'autoplay');
679			if ( autoplay === '1' ) src = src + '&autoplay=1';
680			//handle browser native lazy load feature
681			if ( obj.getAttribute('data-deferlazy') ) {
682				obj.setAttribute('loading', 'lazy');
683			}
684
685			obj.addEventListener('load', () => {
686				cmplz_remove_placeholder(obj);
687			});
688			obj.setAttribute(srcAttribute, src);
689		} else if (obj.classList.contains('cmplz-placeholder-element')) {
690			obj.classList.add('cmplz-activated' );
691			//other services, no iframe, with placeholders
692			//remove the added classes
693			let cssIndex = obj.getAttribute('data-placeholder_class_index');
694			obj.classList.remove('cmplz-blocked-content-container');
695			obj.classList.remove('cmplz-placeholder-' + cssIndex);
696		}
697	});
698
699	/*
700	 * Let's activate the scripts
701	 */
702
703	//create list of waiting scripts
704	let scriptElements = document.querySelectorAll('script[data-category="'+category+'"], script[data-service="'+service+'"]');
705	scriptElements.forEach(obj => {
706		let waitfor = obj.getAttribute('data-waitfor');
707		let src = obj.getAttribute('data-cmplz-src');
708		if ( waitfor ) {
709			if ( src ) {
710				cmplz_waiting_scripts[waitfor] = src;
711			} else if ( obj.innerText.length > 0 ) {
712				cmplz_waiting_inline_scripts[waitfor] = obj;
713			}
714		}
715
716		//cleanup after adding it to our waiting or scriptElements list.
717		if (obj.parentElement) {
718			obj.parentElement.removeChild(obj);
719		}
720	});
721
722	//scripts: remove text/plain, and move data-src attribute to src attribute
723	scriptElements.forEach(obj => {
724		//we don't want already activate scripts to fire, but also we don't want scripts that weren't blocked to fire. Hence the check for type
725		let script_mime_type = obj.getAttribute('type');
726		if ( obj.classList.contains('cmplz-activated') || ( !script_mime_type || script_mime_type==='text/javascript' ) ) {
727			return;
728		}
729		obj.classList.add('cmplz-activated' );
730		let src = obj.getAttribute('data-cmplz-src');
731		if ( src ) {
732			obj.removeAttribute('type');
733			//check if this src or txt is in a waiting script. If so, skip.
734			if ( cmplz_is_waiting_script(cmplz_waiting_scripts, src) ) {
735				return;
736			}
737
738			if ( obj.getAttribute('data-post_scribe_id') ) {
739				let psID = '#' + obj.getAttribute('data-post_scribe_id');
740				let postScribeObj = document.querySelector(psID);
741				if ( postScribeObj ) {
742					postScribeObj.innerHtml('');
743					postscribe(psID, '<script src=' + src + '></script>');
744				}
745			} else {
746				cmplz_run_script(src, category, service, 'src', obj );
747			}
748
749		} else if (obj.innerText.length > 0 ) {
750			//check if this src or txt is in a waiting script. If so, skip.
751			if (cmplz_is_waiting_script(cmplz_waiting_inline_scripts, obj.innerText )) {
752				return;
753			}
754
755			cmplz_run_script( obj.innerText, category, service, 'inline', obj );
756		}
757	});
758
759	// if there are no blockable scripts at all, we still want to provide a hook
760	// in most cases, there are blocked scripts, and run_after_all_scripts hook won't be fired yet. In that
761	// case only the category event is fired (if activated), and this function will run
762	// again from the script activation callbacks.
763	cmplz_run_after_all_scripts(category, service);
764}
765
766/*
767 * remove added classes from the blocked content container
768 *
769 * @param obj
770 */
771function cmplz_remove_placeholder(obj){
772	//we get the closest, not the parent, because a script could have inserted a div in the meantime.
773	let blocked_content_container = obj.closest('.cmplz-blocked-content-container');
774	if ( blocked_content_container ) {
775		let cssIndex = blocked_content_container.getAttribute('data-placeholder_class_index');
776		blocked_content_container.classList.remove('cmplz-blocked-content-container');
777		blocked_content_container.classList.remove('cmplz-placeholder-' + cssIndex);
778	}
779	obj.classList.remove('cmplz-iframe-styles');
780	obj.classList.remove('cmplz-iframe');
781	obj.classList.remove('video-wrap');
782}
783
784/*
785 * check if the passed source has a waiting script that should be executed, and return it if so.
786 * @param waiting_scripts
787 * @param src
788 * @returns {*}
789 */
790
791function cmplz_get_waiting_script( waiting_scripts, src ) {
792	for ( let waitfor in waiting_scripts ) {
793		if ( waiting_scripts.hasOwnProperty(waitfor)) {
794			if ( src.indexOf(waitfor) !== -1 ) {
795				let output = waiting_scripts[waitfor];
796				delete waiting_scripts[waitfor];
797				return output;
798			}
799		}
800	}
801	return false;
802}
803
804/*
805 * Because we need a key=>value array in javascript, the .length check for an empty array doesn't work.
806 * @param arr
807 * @returns {boolean}
808 */
809
810function cmplz_array_is_empty(arr) {
811	for (let key in arr) {
812		if (arr.hasOwnProperty(key)) {
813			return false;
814		}
815	}
816	return true;
817}
818
819/*
820 * Check if the passed src or script is waiting for another script and should not execute
821 * @param waiting_scripts
822 * @param srcOrScript
823 */
824
825function cmplz_is_waiting_script(waiting_scripts, srcOrScript) {
826	for (let waitfor in waiting_scripts) {
827		if ( waiting_scripts.hasOwnProperty(waitfor) ) {
828			let waitingScript = waiting_scripts[waitfor];
829			if (typeof waitingScript !== 'string') waitingScript = waitingScript.innerText;
830
831			if (srcOrScript.indexOf(waitingScript) !== -1 || waitingScript.indexOf(srcOrScript) !== -1) {
832				return true;
833			}
834		}
835	}
836	return false;
837}
838
839/*
840 * if all scripts have been executed, fire a hook.
841 */
842
843function cmplz_run_after_all_scripts(category, service) {
844	//fire an event so custom scripts can hook into this.
845	let enableService = service!=='do_not_match' && !cmplz_in_array(service, cmplz_fired_service_events );
846	let enableCategory = category!=='do_not_match' && !cmplz_in_array( category, cmplz_fired_category_events );
847	if ( enableCategory ||  enableService ) {
848		if (enableCategory) {
849			cmplz_fired_category_events.push(category);
850		}
851		if (enableService) {
852			cmplz_fired_service_events.push(service);
853		}
854		let details = {};
855		details.category = category;
856		details.service = service;
857		details.categories = cmplz_accepted_categories();
858		details.services = cmplz_get_all_service_consents();
859		details.region = complianz.region;
860
861		let event = new CustomEvent('cmplz_enable_category', { detail: details });
862		document.dispatchEvent(event);
863	}
864
865	if ( !cmplz_all_scripts_hook_fired && cmplz_array_is_empty(cmplz_waiting_inline_scripts) && cmplz_array_is_empty(cmplz_waiting_scripts) ) {
866		let event = new CustomEvent('cmplz_run_after_all_scripts', { detail: category, service:service});
867		document.dispatchEvent(event);
868		cmplz_all_scripts_hook_fired = true;
869	}
870}
871
872/*
873 * Fire an event in Tag Manager
874 *
875 *
876 * */
877
878let cmplz_fired_events = [];
879function cmplz_run_tm_event(category) {
880	if (cmplz_fired_events.indexOf(category) === -1) {
881		cmplz_fired_events.push(category);
882		window.dataLayer = window.dataLayer || [];
883		//deprecated notice for 7.0
884		if ( complianz.prefix.indexOf('rt_')!==-1 ) {
885			window.dataLayer.push({
886				'event': complianz.prefix+'event_'+category,
887			});
888			console.log('Tag Manager events with prefix cmplz_rt_ will be deprecated 
888in 7.0. The cmplz_rt_ prefix will be dropped from Tag Manager events.');
889		}
890
891		window.dataLayer.push({
892			'event': 'cmplz_event_'+category
893		});
894		let event = new CustomEvent('cmplz_tag_manager_event', { detail: category });
895		document.dispatchEvent(event);
896	}
897}
898
899/*
900 * Function to handle backward compatibility
901 *
902 */
903
904function cmplz_legacy(){
905	let has_recaptcha = false;
906	document.querySelectorAll('[data-service=recaptcha]').forEach(obj => {
907		obj.setAttribute('data-service', 'google-recaptcha');
908		has_recaptcha=true;
909	});
910
911	if ( has_recaptcha ) {
912		console.log('recaptcha as service name is deprecated. Please rename the service in your custom html to google-recaptcha');
913		document.body.classList.add( 'cmplz-google-recaptcha' );
914	}
915}
916
917/*
918 * Accept all categories
919 */
920window.cmplz_accept_all = function(){
921	cmplz_clear_all_service_consents();
922	for (var key in cmplz_categories) {
923		if ( cmplz_categories.hasOwnProperty(key) ) {
924			cmplz_set_consent(cmplz_categories[key], 'allow');
925		}
926	}
927	cmplz_sync_category_checkboxes();
928}
929
930window.conditionally_show_banner = function() {
931	//merge userdata with complianz data, in case a b testing is used with user specific cookie banner data
932	//objects are merged so user_data will override data in complianz object
933	complianz = cmplz_merge_object( complianz, cmplz_user_data );
934	//check if we need to redirect to another legal document, for a specific region
935	cmplz_maybe_auto_redirect();
936	cmplz_set_blocked_content_container();
937	cmplz_legacy();
938
939	/*
940	 * Integration with WordPress, tell what kind of consent type we're using, then fire an event
941	 */
942
943	window.wp_consent_type = complianz.consenttype;
944	let event = new CustomEvent('wp_consent_type_defined');
945	document.dispatchEvent( event );
946	event = new CustomEvent('cmplz_before_cookiebanner' );
947	document.dispatchEvent(event);
948	if ( complianz.forceEnableStats == 1 && complianz.consenttype === 'optin' ) {
949		cmplz_set_consent('statistics', 'allow');
950	}
951
952	let rev_cats = cmplz_categories.reverse();
953	for (let key in rev_cats) {
954		if ( rev_cats.hasOwnProperty(key) ) {
955			let category = cmplz_categories[key];
956			if ( cmplz_has_consent(category) ) {
957				cmplz_enable_category(category);
958			}
959		}
960	}
961	if ( cmplz_exists_service_consent() ) {
962		//if any service is enabled, allow the general services also, because some services are partially 'general'
963		cmplz_enable_category('', 'general');
964		let services = cmplz_get_services_on_page();
965		for (let key in services) {
966			if ( services.hasOwnProperty(key) ) {
967				let service = services[key].service;
968				let category = services[key].category;
969				if ( cmplz_has_service_consent( service, category )) {
970					document.querySelectorAll('.cmplz-accept-service[data-service=' + service + ']').forEach(obj => {
971						obj.checked = true;
972					});
973					cmplz_enable_category('', service);
974				}
975			}
976		}
977	}
978
979	cmplz_sync_category_checkboxes();
980	cmplz_integrations_init();
981	cmplz_check_cookie_policy_id();
982	cmplz_set_up_auto_dismiss();
983
984	//if we're on the cookie policy page, we dynamically load the applicable revoke checkbox
985	cmplz_load_manage_consent_container();
986
987	event = new CustomEvent('cmplz_cookie_banner_data', { detail: complianz });
988	document.dispatchEvent(event);
989
990	//if no categories were saved before, we do it now
991	if ( cmplz_get_cookie('saved_categories') === '' ) {
992		//for Non optin/optout visitors, and DNT users, we just track the no-warning option
993		if ( complianz.consenttype !== 'optin' && complianz.consenttype !== 'optout' ) {
994			cmplz_track_status( 'no_warning' );
995		} else if ( cmplz_do_not_track() ) {
996			cmplz_track_status('do_not_track' );
997		}
998	}
999
1000	cmplz_set_category_as_body_class();
1001	//fire cats event, but do not fire a track, as we do this on exit.
1002	cmplz_fire_categories_event();
1003	if ( !cmplz_do_not_track() ) {
1004		if (complianz.consenttype === 'optin') {
1005			if (complianz.forceEnableStats) {
1006				cmplz_enable_category('statistics');
1007			}
1008			console.log('opt-in');
1009			show_cookie_banner();
1010		} else if (complianz.consenttype === 'optout') {
1011			console.log('opt-out');
1012			show_cookie_banner();
1013		} else {
1014			console.log('other consent type, no cookie warning');
1015			//on other consent types, all scripts are enabled by default.
1016			cmplz_accept_all();
1017			// cmplz_fire_categories_event();
1018		}
1019	} else {
1020		console.log('global privacy control or do not track detected: no banner.');
1021		cmplz_track_status( 'do_not_track' );
1022	}
1023}
1024
1025/**
1026 * Check if User has set either GPC or DNT in the browser.
1027 * @returns {boolean}
1028 */
1029function cmplz_do_not_track(){
1030	let dnt = 'doNotTrack' in navigator && navigator.doNotTrack === '1';
1031	let gpc = 'globalPrivacyControl' in navigator && navigator.globalPrivacyControl;
1032	return !!(complianz.do_not_track_enabled && (gpc || dnt));
1033}
1034
1035/*
1036 * Get list of services active on the page
1037 * @returns {*[]}
1038 */
1039function cmplz_get_services_on_page(){
1040	let services=[];
1041	document.querySelectorAll('[data-service]').forEach(obj => {
1042		let service = obj.getAttribute('data-service');
1043		let category = obj.getAttribute('data-category');
1044		if ( services.indexOf(service)==-1 ) {
1045			services.push({
1046				'category': category,
1047				'service':service,
1048			});
1049		}
1050	});
1051	return services;
1052}
1053
1054/*
1055 * Run the actual cookie warning
1056 *
1057 * */
1058
1059window.show_cookie_banner = function () {
1060	let disableCookiebanner = complianz.disable_cookiebanner || cmplz_is_speedbot();
1061	//do not show banner when manage consent area on cookie policy is visible
1062	//when users use only the shortcode, the manage consent container is not active, but the dropdown cookie policy class is.
1063	//when the complianz shortcode is used, the dropdown cookie policy class is loaded late because it's loaded with javascript.
1064	let tmpDismissCookiebanner = false;
1065	if ( document.querySelector('#cmplz-manage-consent-container') || document.querySelector('.cmplz-dropdown-cookiepolicy') ) {
1066		tmpDismissCookiebanner = true;
1067	}
1068
1069	var fragment = document.createDocumentFragment();
1070	let container = document.getElementById('cmplz-cookiebanner-container');
1071	if (container) {
1072		fragment.appendChild(container);
1073		document.body.prepend(fragment);
1074	}
1075
1076	let link = document.createElement("link");
1077	let pageLinks = complianz.page_links[complianz.region];
1078	//get correct banner, based on banner_id
1079	cmplz_banner = document.querySelector('.cmplz-cookiebanner.banner-'+complianz.user_banner_id+'.'+complianz.consenttype);
1080	if ( !cmplz_banner ) {
1081		disableCookiebanner = true;
1082	}
1083	cmplz_manage_consent_button = document.querySelector('#cmplz-manage-consent .cmplz-manage-consent.manage-consent-'+complianz.user_banner_id);
1084	let css_file_url = complianz.css_file.replace('{type}', complianz.consenttype ).replace('{banner_id}', complianz.user_banner_id);
1085	if ( complianz.css_file.indexOf('cookiebanner/css/defaults/banner') != -1 ) {
1086		console.log('Fallback default css file used. Please re-save banner settings, or check file writing permissions in uploads directory');
1087	}
1088
1089	link.href = css_file_url;
1090	link.type = "text/css";
1091	link.rel = "stylesheet";
1092	link.onload = function () {
1093		if ( !disableCookiebanner ) {
1094			cmplz_banner.classList.remove('cmplz-hidden');
1095			cmplz_manage_consent_button.classList.remove('cmplz-hidden');
1096		}
1097	}
1098	document.getElementsByTagName("head")[0].appendChild(link);
1099	if ( cmplz_banner && !disableCookiebanner ) {
1100		cmplz_banner.querySelectorAll('.cmplz-links a:not(.cmplz-external), .cmplz-buttons a:not(.cmplz-external)').forEach(obj => {
1101			let docElement = obj;
1102			docElement.classList.add('cmplz-hidden');
1103			for (let pageType in pageLinks ) {
1104				if (pageLinks.hasOwnProperty(pageType) && docElement.classList.contains(pageType)) {
1105					docElement.setAttribute('href', pageLinks[pageType]['url'] + docElement.getAttribute('data-relative_url'));
1106					if ( docElement.innerText === '{title}') {
1107						docElement.innerText = cmplz_html_decode(pageLinks[pageType]['title']);
1108					}
1109					docElement.classList.remove('cmplz-hidden');
1110				}
1111			}
1112		});
1113
1114		cmplz_set_banner_status();
1115		//we don't use the setBannerStatus function here, as we don't want to save it in a cookie now.
1116		if ( tmpDismissCookiebanner ) {
1117			cmplz_banner.classList.remove('cmplz-show');
1118			cmplz_banner.classList.add('cmplz-dismissed');
1119			cmplz_manage_consent_button.classList.remove('cmplz-dismissed');
1120			cmplz_manage_consent_button.classList.add('cmplz-show');
1121		}
1122	}
1123
1124	let event = new CustomEvent('cmplz_cookie_warning_loaded', {detail: complianz.region});
1125	document.dispatchEvent(event);
1126}
1127/*
1128 * Get the status of the banner: dismissed | show
1129 * @returns {string}
1130 */
1131window.cmplz_get_banner_status = function (){
1132	return cmplz_get_cookie('banner-status');
1133}
1134
1135/*
1136 * Set the banner status so it will be either shown or dismissed, and store it in a cookie.
1137 * @param status (optional)
1138 */
1139
1140window.cmplz_set_banner_status = function ( status ){
1141	let prevStatus = cmplz_get_cookie('banner-status');
1142	status = typeof status !== 'undefined' ? status : prevStatus;
1143	if ( status !== prevStatus ) {
1144		cmplz_set_cookie( 'banner-status', status );
1145	}
1146	if (status.length===0){
1147		status = 'show';
1148	}
1149
1150	if (status==='show') {
1151		prevStatus = 'dismissed';
1152	} else {
1153		prevStatus = 'show';
1154	}
1155
1156	if ( cmplz_banner && status.length>0 ) {
1157		cmplz_banner.classList.remove('cmplz-'+prevStatus);
1158		cmplz_banner.classList.add('cmplz-'+status );
1159		if ( cmplz_manage_consent_button ) {
1160			cmplz_manage_consent_button.classList.add('cmplz-'+prevStatus);
1161			cmplz_manage_consent_button.classList.remove('cmplz-'+status);
1162		}
1163	}
1164
1165	if ( cmplz_banner_container && complianz.soft_cookiewall ) {
1166		cmplz_banner_container.classList.remove('cmplz-'+prevStatus);
1167		cmplz_banner_container.classList.add('cmplz-'+status );
1168		cmplz_banner_container.classList.add('cmplz-soft-cookiewall');
1169	}
1170	let event = new CustomEvent('cmplz_banner_status', { detail: status });
1171	document.dispatchEvent(event);
1172	cmplz_start_clean();
1173}
1174
1175/*
1176 * Check if current visitor is a bot
1177 *
1178 * @returns {boolean}
1179 */
1180function cmplz_is_bot(){
1181	var botPattern = "(googlebot\/|Googlebot-Mobile|Googlebot-Image|Google favicon|Mediapartners-Google|bingbot|slurp|java|wget|curl|Commons-HttpClient|Python-urllib|libwww|httpunit|nutch|phpcrawl|msnbot|jyxobot|FAST-WebCrawler|FAST Enterprise Crawler|biglotron|teoma|convera|seekbot|gigablast|exabot|ngbot|ia_archiver|GingerCrawler|webmon |httrack|webcrawler|grub.org|UsineNouvelleCrawler|antibot|netresearchserver|speedy|fluffy|bibnum.bnf|findlink|msrbot|panscient|yacybot|AISearchBot|IOI|ips-agent|tagoobot|MJ12bot|dotbot|woriobot|yanga|buzzbot|mlbot|yandexbot|purebot|Linguee Bot|Voyager|CyberPatrol|voilabot|baiduspider|citeseerxbot|spbot|twengabot|postrank|turnitinbot|scribdbot|page2rss|sitebot|linkdex|Adidxbot|blekkobot|ezooms|dotbot|Mail.RU_Bot|discobot|heritrix|findthatfile|europarchive.org|NerdByNature.Bot|sistrix crawler|ahrefsbot|Aboundex|domaincrawler|wbsearchbot|summify|ccbot|edisterbot|seznambot|ec2linkfinder|gslfbot|aihitbot|intelium_bot|facebookexternalhit|yeti|RetrevoPageAnalyzer|lb-spider|sogou|lssbot|careerbot|wotbox|wocbot|ichiro|DuckDuckBot|lssrocketcrawler|drupact|webcompanycrawler|acoonbot|openindexspider|gnam gnam spider|web-archive-net.com.bot|backlinkcrawler|coccoc|integromedb|content crawler spider|toplistbot|seokicks-robot|it2media-domain-crawler|ip-web-crawler.com|siteexplorer.info|elisabot|proximic|changedetection|blexbot|arabot|WeSEE:Search|niki-bot|CrystalSemanticsBot|rogerbot|360Spider|psbot|InterfaxScanBot|Lipperhey SEO Service|CC Metadata Scaper|g00g1e.net|GrapeshotCrawler|urlappendbot|brainobot|fr-crawler|binlar|SimpleCrawler|Livelapbot|Twitterbot|cXensebot|smtbot|bnf.fr_bot|A6-Indexer|ADmantX|Facebot|Twitterbot|OrangeBot|memorybot|AdvBot|MegaIndex|SemanticScholarBot|ltx71|nerdybot|xovibot|BUbiNG|Qwantify|archive.org_bot|Applebot|TweetmemeBot|crawler4j|findxbot|SemrushBot|yoozBot|lipperhey|y!j-asr|Domain Re-Animator Bot|AddThis)";
1182	var reBot = new RegExp(botPattern, 'i');
1183	var userAgent = navigator.userAgent;
1184	return reBot.test(userAgent);
1185}
1186/*
1187 * Check if current visitor is a speedbot
1188 *
1189 * @returns {boolean}
1190 */
1191function cmplz_is_speedbot(){
1192	var userAgent = navigator.userAgent;
1193	var speedBotPattern = "(GTmetrix|pingdom|pingbot|Lighthouse)";
1194	var speedBot = new RegExp(speedBotPattern, 'i');
1195	return speedBot.test(userAgent);
1196}
1197
1198/*
1199 * Check if there is consent for a category or service
1200 * @param category
1201 * @returns {boolean}
1202 */
1203window.cmplz_has_consent = function ( category ){
1204	if ( cmplz_is_bot() ) {
1205		return true;
1206	}
1207
1208	if ( category === 'functional' ) {
1209		return true;
1210	}
1211	let has_consent, value;
1212
1213	//if DNT is detected, we should only return the actual cookie value, and not look at the consenttype
1214	if ( cmplz_do_not_track() ){
1215		value = cmplz_get_cookie(category);
1216		has_consent = (value === 'allow');
1217		return has_consent;
1218	}
1219
1220	/*
1221	 * categories
1222	 */
1223	value = cmplz_get_cookie(category);
1224	if ( (complianz.consenttype === 'optout' || complianz.consenttype === 'other') && value === '') {
1225		//if it's opt out and no cookie is set we should return true
1226		has_consent = true;
1227	} else {
1228		//all other situations, return only true if value is allow
1229		has_consent = (value === 'allow');
1230	}
1231
1232	return has_consent;
1233}
1234
1235/*
1236 * Check if a service has consent
1237 * @param service
1238 * @returns {boolean|*}
1239 */
1240window.cmplz_is_service_denied = function ( service ) {
1241	//Check if it's in the consented services cookie
1242	var consented_services_json = cmplz_get_cookie('consented_services');
1243	var consented_services;
1244	try {
1245		consented_services = JSON.parse(consented_services_json);
1246	} catch (e) {
1247		consented_services = {};
1248	}
1249
1250	if ( !consented_services.hasOwnProperty( service ) ){
1251		return false;
1252	} else {
1253		return !consented_services[service];
1254	}
1255}
1256
1257/*
1258 * Check if a service has consent
1259 * @param service
1260 * @param category
1261 * @returns {boolean|*}
1262 */
1263window.cmplz_has_service_consent = function ( service, category ) {
1264	//Check if it's in the consented services cookie
1265	var consented_services_json = cmplz_get_cookie('consented_services');
1266	var consented_services;
1267	try {
1268		consented_services = JSON.parse(consented_services_json);
1269	} catch (e) {
1270		consented_services = {};
1271	}
1272
1273	if ( !consented_services.hasOwnProperty( service ) ){
1274		//default to the category
1275		return cmplz_has_consent( category );
1276	} else {
1277		return consented_services[service];
1278	}
1279}
1280
1281/*
1282 * check if there's at least one service with consent
1283 * @returns {boolean}
1284 */
1285function cmplz_exists_service_consent(){
1286	var consented_services_json = cmplz_get_cookie('consented_services');
1287	var consented_services;
1288	try {
1289		consented_services = JSON.parse(consented_services_json);
1290		for (const key in consented_services) {
1291			if ( consented_services.hasOwnProperty(key) ) {
1292				if (consented_services[key] == true) {
1293					return true;
1294				}
1295			}
1296		}
1297	} catch (e) {
1298		return false;
1299	}
1300	return false;
1301}
1302
1303/*
1304 * Set consent for a service
1305 * @param service
1306 * @param consented
1307 */
1308function cmplz_set_service_consent( service, consented ){
1309	var consented_services_json = cmplz_get_cookie('consented_services');
1310	var consented_services;
1311	try {
1312		consented_services = JSON.parse(consented_services_json);
1313	} catch (e) {
1314		consented_services = {};
1315	}
1316	consented_services[service] = consented;
1317	cmplz_set_cookie('consented_services', JSON.stringify(consented_services) );
1318	let details = {};
1319	details.service = service;
1320	details.value = consented;
1321	details.region = complianz.region;
1322	//when the status is changed, we may need to fire scripts again, so we reset it.
1323	cmplz_all_scripts_hook_fired = false;
1324	let event = new CustomEvent('cmplz_status_change_service', { detail: details });
1325	document.dispatchEvent(event);
1326}
1327
1328/*
1329 * Remove all service consents
1330 */
1331function cmplz_clear_all_service_consents(){
1332	cmplz_set_cookie('consented_services', '');
1333}
1334
1335/*
1336 * Get all consented or denied services
1337 */
1338
1339function cmplz_get_all_service_consents(){
1340	var consented_services_json = cmplz_get_cookie('consented_services');
1341	var consented_services;
1342	try {
1343		consented_services = JSON.parse(consented_services_json);
1344	} catch (e) {
1345		consented_services = {};
1346	}
1347	return consented_services;
1348}
1349/*
1350 * Get cookie path
1351 * @returns {*}
1352 */
1353function cmplz_get_cookie_path(){
1354	return typeof complianz.cookie_path !== 'undefined' && complianz.cookie_path !== '' ? complianz.cookie_path : '/';
1355}
1356
1357/*
1358 * retrieve domain to set the cookies on
1359 * @returns {string}
1360 */
1361function cmplz_get_cookie_domain(){
1362	var domain = '';
1363	if ( complianz.set_cookies_on_root == 1 && complianz.cookie_domain.length>3){
1364		domain = complianz.cookie_domain;
1365	}
1366	if (domain.indexOf('localhost') !== -1 ) {
1367		domain = '';
1368	}
1369	return domain;
1370}
1371
1372/*
1373 * Set consent for a category
1374 * @param category
1375 * @param value
1376 */
1377window.cmplz_set_consent = function (category, value){
1378	cmplz_set_accepted_cookie_policy_id();
1379
1380	//functional is always allow
1381	value = category==='functional' ? 'allow' : value;
1382	let previous_value = cmplz_get_cookie(category);
1383
1384	//keep checkboxes in banner and on cookie policy in sync
1385	//do this before the change check to ensure sync: https://github.com/Really-Simple-Plugins/complianz-gdpr/issues/324
1386	let checked = value === 'allow';
1387	document.querySelectorAll('input.cmplz-'+category).forEach(obj => {
1388		obj.checked = checked;
1389	});
1390
1391	//do not trigger a change event if nothing has changed.
1392	if ( previous_value === value ) {
1393		return;
1394	}
1395
1396	cmplz_set_cookie(category, value);
1397	if ( value === 'allow' ) {
1398		cmplz_enable_category(category);
1399	}
1400
1401	cmplz_wp_set_consent(category, value);
1402	if ( category === 'statistics' ) {
1403		cmplz_wp_set_consent('statistics-anonymous', 'allow');
1404	}
1405
1406	let details = new Object();
1407	details.category = category;
1408	details.value = value;
1409	details.region = complianz.region;
1410	details.categories = cmplz_accepted_categories();
1411	//when the status is changed, we may need to fire scripts again, so we reset it.
1412	cmplz_all_scripts_hook_fired = false;
1413	let event = new CustomEvent('cmplz_status_change', { detail: details });
1414	document.dispatchEvent(event);
1415	if ( category === 'marketing' && value === 'deny' && previous_value === 'allow' ) {
1416		cmplz_integrations_revoke();
1417		//give the code some time to finish, so our track status code can send a signal to the backend.
1418		setTimeout(function(){
1419			cmplz_reload_browser_compatible()
1420		}, 500);
1421	}
1422}
1423
1424/*
1425* In some browsers, like firefox, the reload does not force reload, but keeps cached data, causing e.g. Google Maps to load anyway.
1426*/
1427function cmplz_reload_browser_compatible(){
1428	if( navigator.userAgent.toLowerCase().indexOf('firefox') > -1 ){
1429		const url = new URL(window.location.href);
1430		url.searchParams.set('cmplz-force-reload', Date.now().toString());
1431		window.location.href = url.toString();
1432	} else {
1433		window.location.reload();
1434	}
1435}
1436
1437/*
1438 * We use ajax to check the consenttype based on region, otherwise caching could prevent the user specific warning
1439 *
1440 * */
1441
1442var cmplz_user_data = [];
1443//check if it's already stored
1444if (typeof (Storage) !== "undefined" && sessionStorage.cmplz_user_data) {
1445	cmplz_user_data = JSON.parse(sessionStorage.cmplz_user_data);
1446}
1447
1448//if not stored yet, load. As features in the user object can be changed on updates, we also check for the version
1449if ( complianz.geoip == 1 && (cmplz_user_data.length == 0 || (cmplz_user_data.version !== complianz.version) || (cmplz_user_data.banner_version !== complianz.banner_version)) ) {
1450
1451	let request = new XMLHttpRequest();
1452	let cmplzUserRegion = cmplz_get_url_parameter(window.location.href, 'cmplz_user_region');
1453	cmplzUserRegion = cmplzUserRegion ? '&cmplz_user_region=' + cmplzUserRegion : '';
1454	request.open('GET', complianz.url+'banner?'+complianz.locale+cmplzUserRegion, true);
1455	request.setRequestHeader('Content-type', 'application/json');
1456	request.send();
1457	request.onload = function() {
1458		cmplz_user_data = JSON.parse(request.response);
1459		sessionStorage.cmplz_user_data = JSON.stringify(cmplz_user_data);
1460		conditionally_show_banner();
1461	};
1462} else {
1463	conditionally_show_banner();
1464}
1465
1466/*
1467 *  when ab testing, or using records of consent, we want to keep track of the unique user id
1468 */
1469
1470if ( complianz.store_consent == 1 ) {
1471	var cmplz_id_cookie = cmplz_get_cookie('id');
1472	var cmplz_id_session = '';
1473	var cmplz_id = '';
1474	if (typeof (Storage) !== "undefined" && sessionStorage.cmplz_id) {
1475		cmplz_id_session = JSON.parse(sessionStorage.cmplz_id);
1476	}
1477
1478	if ( cmplz_id_cookie.length == 0 && cmplz_id_session.length > 0 ) {
1479		cmplz_id = cmplz_id_session;
1480		cmplz_set_cookie('id', cmplz_id );
1481	}
1482
1483	if ( cmplz_id_cookie.length > 0 && cmplz_id_session.length == 0 ) {
1484		cmplz_id = cmplz_id_cookie;
1485	}
1486
1487	if ( typeof (Storage) !== "undefined" ) {
1488		sessionStorage.cmplz_id = JSON.stringify(cmplz_id);
1489	}
1490}
1491
1492// visibilitychange and pagehide work in more browsers hence we check if they are supported and try to use them
1493document.addEventListener('visibilitychange', function () {
1494	if ( document.visibilityState === 'hidden' ) {
1495		cmplz_track_status_end();
1496	}
1497});
1498window.addEventListener("pagehide", cmplz_track_status_end, false );
1499window.addEventListener("beforeunload", cmplz_track_status_end, false );
1500
1501function cmplz_track_status_end(){
1502	if ( !cmplz_consent_stored_once ) {
1503		cmplz_track_status();
1504	}
1505}
1506
1507/*
1508 * This creates an API which devs can use to trigger actions in complianz.
1509 */
1510document.addEventListener('cmplz_consent_action', function (e) {
1511	cmplz_set_consent( e.detail.category , 'allow' );
1512	cmplz_fire_categories_event();
1513	cmplz_track_status();
1514});
1515
1516/*
1517 * Deny all categories, and reload if needed.
1518 */
1519window.cmplz_deny_all = function(){
1520	for (var key in cmplz_categories) {
1521		if ( cmplz_categories.hasOwnProperty(key) ) {
1522			cmplz_set_consent(cmplz_categories[key], 'deny');
1523		}
1524	}
1525	var consentLevel = cmplz_highest_accepted_category();
1526	var reload = false;
1527
1528	if (consentLevel !== 'functional' || cmplz_exists_service_consent() ) {
1529		reload = true;
1530	}
1531	if ( cmplz_clear_cookies('cmplz_service') ) {
1532		reload = true;
1533	}
1534
1535	//has to be after the check if should be reloaded, otherwise that check won't work.
1536	cmplz_clear_all_service_consents();
1537	cmplz_integrations_revoke();
1538	cmplz_fire_categories_event();
1539	cmplz_track_status();
1540
1541	let event = new CustomEvent('cmplz_revoke', { detail: reload });
1542	document.dispatchEvent(event);
1543
1544	//we need to let the iab extension handle the reload, otherwise the consent revoke might not be ready yet.
1545	if ( !complianz.tcf_active && reload ) {
1546		cmplz_reload_browser_compatible();
1547	}
1548}
1549
1550/*
1551 * For both opt-in and opt-out, clicking cmplz-accept should result in accepting all categories
1552 */
1553cmplz_add_event('click', '.cmplz-accept', function(e){
1554	e.preventDefault();
1555	cmplz_accept_all();
1556	cmplz_set_banner_status('dismissed');
1557	cmplz_fire_categories_event();
1558	cmplz_track_status();
1559});
1560
1561/*
1562 *  Accept marketing cookies by clicking any other link cookie acceptance from a custom link
1563 */
1564
1565//cmplz-accept-marketing is deprecated
1566cmplz_add_event('click', '.cmplz-accept-category, .cmplz-accept-marketing', function(e){
1567	e.preventDefault();
1568	let obj = e.target;
1569	var service = obj.getAttribute('data-service');
1570	var category = obj.getAttribute('data-category');
1571	category = category ? category : 'marketing';
1572	if ( complianz.clean_cookies == 1 && typeof service !== 'undefined' && service ){
1573		cmplz_set_service_consent(service, true);
1574		cmplz_enable_category('', 'general');
1575		cmplz_enable_category('', service);
1576	} else {
1577		//we're activating a category, so do not need service activation here.
1578		// cmplz_enable_category('', 'general');
1579		cmplz_set_consent( category, 'allow' );
1580	}
1581	cmplz_set_banner_status('dismissed');
1582	cmplz_fire_categories_event();
1583	cmplz_track_status();
1584});
1585
1586/*
1587 * Accept a specific service
1588 */
1589cmplz_add_event('click', '.cmplz-accept-service', function(e){
1590	let obj = e.target;
1591	//INPUT should be handled by change event, these are checkboxes on the cookie policy
1592	let tagName = obj.tagName;
1593	if ( tagName === 'INPUT' ) {
1594		return;
1595	}
1596	let service = obj.getAttribute('data-service');
1597	if ( typeof service !== 'undefined' ){
1598		cmplz_set_service_consent(service, true);
1599		cmplz_enable_category('', 'general');
1600		cmplz_enable_category('', service);
1601	}
1602	cmplz_fire_categories_event();
1603	cmplz_track_status();
1604});
1605/*
1606 * Accept a specific service
1607 */
1608cmplz_add_event('change', '.cmplz-accept-service', function(e){
1609	let obj = e.target;
1610	let tagName = obj.tagName;
1611	let service = obj.getAttribute('data-service');
1612	if ( typeof service !== 'undefined' ) {
1613		//inputs are from the consent per service option on the cookie policy.
1614		if ( tagName === 'INPUT' ) {
1615			cmplz_set_banner_status('dismissed');
1616			if ( obj.checked ){
1617				cmplz_set_service_consent(service, true);
1618				cmplz_enable_category('', service);
1619			} else {
1620				cmplz_set_service_consent(service, false);
1621				//give our track status time to finish
1622				setTimeout(function(){
1623					cmplz_reload_browser_compatible()
1624				}, 500);
1625			}
1626			//if not input, it's a placeholder
1627		} else {
1628			e.preventDefault();
1629			cmplz_set_service_consent(service, true);
1630			cmplz_enable_category('', 'general');
1631			cmplz_enable_category('', service);
1632
1633			//give our track status time to finish
1634			setTimeout(function(){
1635				cmplz_reload_browser_compatible()
1636			}, 500);
1637		}
1638	}
1639	cmplz_fire_categories_event();
1640	cmplz_track_status();
1641});
1642
1643
1644
1645/*
1646 * On the banner, clicking a category should fire the category only after the save button is clicked.
1647 *
1648 */
1649cmplz_add_event('click', '.cmplz-save-preferences', function(e){
1650	let obj = e.target;
1651	cmplz_banner = obj.closest('.cmplz-cookiebanner');
1652	for (var key in cmplz_categories) {
1653		if ( cmplz_categories.hasOwnProperty(key) ) {
1654			var category = cmplz_categories[key];
1655			var categoryElement = cmplz_banner.querySelector('input.cmplz-' + category);
1656			if (categoryElement) {
1657				if (categoryElement.checked) {
1658					cmplz_set_consent(category, 'allow');
1659				} else {
1660					cmplz_set_consent(category, 'deny');
1661				}
1662			}
1663		}
1664	}
1665	cmplz_set_banner_status('dismissed');
1666	cmplz_fire_categories_event();
1667	cmplz_track_status();
1668});
1669
1670cmplz_add_event('click', '.cmplz-close', function(e){
1671	cmplz_set_banner_status('dismissed');
1672});
1673
1674cmplz_add_event('click', '.cmplz-view-preferences', function(e){
1675	let obj = e.target;
1676	cmplz_banner = obj.closest('.cmplz-cookiebanner');
1677	if ( cmplz_banner.querySelector('.cmplz-categories').classList.contains('cmplz-fade-in')) {
1678		cmplz_banner.classList.remove('cmplz-categories-visible');
1679		cmplz_banner.querySelector('.cmplz-categories' ).classList.remove('cmplz-fade-in');
1680		cmplz_banner.querySelector('.cmplz-view-preferences' ).style.display = 'block';
1681		cmplz_banner.querySelector('.cmplz-save-preferences' ).style.display = 'none';
1682	} else {
1683		cmplz_banner.classList.add('cmplz-categories-visible');
1684		cmplz_banner.querySelector('.cmplz-categories' ).classList.add('cmplz-fade-in');
1685		cmplz_banner.querySelector('.cmplz-view-preferences' ).style.display = 'none';
1686		cmplz_banner.querySelector('.cmplz-save-preferences' ).style.display = 'block';
1687	}
1688});
1689/*
1690 * On the cookie policy, clicking a category should fire the category immediately
1691 *
1692 */
1693cmplz_add_event('change', '.cmplz-manage-consent-container .cmplz-category', function(e){
1694	for (var key in cmplz_categories) {
1695		if ( cmplz_categories.hasOwnProperty(key) ) {
1696			var category = cmplz_categories[key];
1697			var categoryElement = document.querySelector('.cmplz-manage-consent-container input.cmplz-' + category);
1698			if (categoryElement) {
1699				if (categoryElement.checked) {
1700					cmplz_set_consent(category, 'allow');
1701				} else {
1702					cmplz_set_consent(category, 'deny');
1703				}
1704				cmplz_set_banner_status('dismissed');
1705				cmplz_fire_categories_event();
1706				cmplz_track_status();
1707			}
1708		}
1709	}
1710
1711});
1712
1713cmplz_add_event('click', '.cmplz-deny', function(e){
1714	e.preventDefault();
1715	cmplz_set_banner_status('dismissed');
1716	cmplz_deny_all();
1717
1718});
1719
1720cmplz_add_event('click', 'button.cmplz-manage-settings', function(e){
1721	e.preventDefault();
1722	var catsContainer = document.querySelector('.cmplz-cookiebanner .cmplz-categories');
1723	var saveSettings = document.querySelector('.cmplz-save-settings');
1724	var manageSettings = document.querySelector('button.cmplz-manage-settings');
1725	if ( !cmplz_is_hidden(catsContainer) ){
1726		saveSettings.style.display='none';
1727		manageSettings.style.display = 'block';
1728		catsContainer.style.display='none';
1729	} else {
1730		saveSettings.style.display = 'block';
1731		manageSettings.style.display='none';
1732		catsContainer.style.display = 'block';
1733	}
1734});
1735
1736cmplz_add_event('click', 'button.cmplz-manage-consent', function(e){
1737	e.preventDefault();
1738	cmplz_set_banner_status('show');
1739});
1740
1741/*
1742 * Handle dismiss on scroll and dismiss on timeout
1743 */
1744function cmplz_set_up_auto_dismiss() {
1745	if ( complianz.consenttype === 'optout' ) {
1746		if ( complianz.dismiss_on_scroll==1 ) {
1747			var onWindowScroll = function(evt) {
1748				if (window.pageYOffset > Math.floor(400)) {
1749					cmplz_set_banner_status('dismissed');
1750					cmplz_fire_categories_event();
1751					cmplz_track_status();
1752					window.removeEventListener('scroll', onWindowScroll);
1753					this.onWindowScroll = null;
1754				}
1755			};
1756			window.addEventListener('scroll', onWindowScroll);
1757		}
1758
1759		var delay = parseInt(complianz.dismiss_timeout);
1760		if ( delay > 0 ) {
1761			var cmplzDismissTimeout = window.setTimeout(function () {
1762				cmplz_set_banner_status('dismissed');
1763				cmplz_fire_categories_event();
1764				cmplz_track_status();
1765			}, Math.floor(delay));
1766		}
1767	}
1768}
1769
1770/*
1771 * Fire a event wich passes all consented categories
1772 * Separated from the actual category consent because we want to bundle it in one event
1773 */
1774function cmplz_fire_categories_event(){
1775	let details = new Object();
1776	details.category = cmplz_highest_accepted_category();
1777	details.categories = cmplz_accepted_categories();
1778	details.region = complianz.region;
1779	let event = new CustomEvent('cmplz_fire_categories', { detail: details });
1780	document.dispatchEvent(event);
1781}
1782/*
1783 * Track the status of current consent
1784 * @param status
1785 */
1786
1787function cmplz_track_status( status ) {
1788	var cats = [];
1789	status = typeof status !== 'undefined' ? status : false;
1790
1791	let event = new CustomEvent('cmplz_track_status', { detail: status });
1792	document.dispatchEvent(event);
1793
1794	if ( !status ) {
1795		cats = cmplz_accepted_categories();
1796	} else {
1797		cats = [status];
1798	}
1799	cmplz_set_category_as_body_class();
1800	var saved_cats, saved_services;
1801	try {saved_cats = JSON.parse(cmplz_get_cookie('saved_categories'));} catch (e) {saved_cats = {};}
1802	try {saved_services = JSON.parse(cmplz_get_cookie('saved_services'));} catch (e) {saved_services = {};}
1803	var consented_services = cmplz_get_all_service_consents();
1804
1805	//compare current cats with saved cats. When there are no changes, do nothing.
1806	if (cmplz_equals(saved_cats, cats) && cmplz_equals(saved_services, consented_services)) {
1807		return;
1808	}
1809
1810	if ( complianz.store_consent != 1 || cmplz_is_bot() || cmplz_is_speedbot() ) {
1811		return;
1812	}
1813
1814	//keep track of the fact that the status was saved at least once
1815	cmplz_set_cookie('saved_categories', JSON.stringify(cats));
1816	cmplz_set_cookie('saved_services', JSON.stringify(consented_services));
1817	cmplz_consent_stored_once = true;
1818
1819	let data;
1820	let request = new XMLHttpRequest();
1821	request.open('POST', complianz.url+'track', true);
1822	data = {
1823		'consented_categories': cats,
1824		'consented_services':consented_services,
1825		'consenttype': window.wp_consent_type,//store the source consenttype, as our complianz.consenttype will not include optinstats.
1826	};
1827
1828	request.setRequestHeader('Content-type', 'application/json');
1829	request.send(JSON.stringify(data));
1830
1831}
1832
1833/*
1834 * Get accepted categories
1835 *
1836 * @returns {string}
1837 */
1838function cmplz_accepted_categories() {
1839	var consentedCategories = cmplz_categories;
1840	var consentedTemp = [];
1841
1842	//because array filter changes keys, we make a temp arr
1843	for (var key in consentedCategories) {
1844		if ( consentedCategories.hasOwnProperty(key) ) {
1845			var category = consentedCategories[key];
1846			if (cmplz_has_consent(category)) {
1847				consentedTemp.push(category);
1848			}
1849		}
1850	}
1851
1852	consentedCategories = consentedCategories.filter(function(value, index, consentedCategories){
1853		return cmplz_in_array(value, consentedTemp);
1854	});
1855	return consentedCategories;
1856}
1857
1858/*
1859 * Enable the checkbox for each category which was enabled
1860 *
1861 * */
1862
1863function cmplz_sync_category_checkboxes() {
1864	for ( var key in cmplz_categories ) {
1865		if ( cmplz_categories.hasOwnProperty(key) ) {
1866			var category = cmplz_categories[key];
1867			if ( cmplz_has_consent(category) || category === 'functional' ) {
1868				document.querySelectorAll('input.cmplz-' + category).forEach(obj => {
1869					obj.checked = true;
1870				});
1871			} else {
1872				document.querySelectorAll('input.cmplz-' + category).forEach(obj => {
1873					obj.checked = false;
1874				});
1875			}
1876		}
1877
1878		document.querySelectorAll('.cmplz-accept-service').forEach(obj => {
1879			let service = obj.getAttribute('data-service');
1880			let category = obj.getAttribute('data-category');
1881			if ( cmplz_has_service_consent( service, category ) ) {
1882				obj.checked = true;
1883			} else if ( cmplz_is_service_denied( service ) ) {
1884				obj.checked = false;
1885			} else {
1886				//no consent on service level, check if it's category has consent.
1887				let category = obj.getAttribute('data-category' );
1888				obj.checked = !!cmplz_has_consent(category);
1889			}
1890		});
1891	}
1892}
1893
1894/*
1895 * Merge two objects
1896 *
1897 * */
1898
1899function cmplz_merge_object(userdata, ajax_data) {
1900	var output = [];
1901	//first, we fill the important data.
1902	for (key in ajax_data) {
1903		if (ajax_data.hasOwnProperty(key)) output[key] = ajax_data[key];
1904	}
1905
1906	//conditionally add static data
1907	for (var key in userdata) {
1908		//only add if not in ajax_data
1909		if (!ajax_data.hasOwnProperty(key) || typeof ajax_data[key] === 'undefined') {
1910			if (userdata.hasOwnProperty(key)) output[key] = userdata[key];
1911		}
1912	}
1913
1914	return output;
1915}
1916
1917/*
1918 * If current cookie policy has changed, reset cookie consent
1919 *
1920 * */
1921
1922function cmplz_check_cookie_policy_id() {
1923	var user_policy_id = cmplz_get_cookie('policy_id');
1924	if (user_policy_id && (complianz.current_policy_id !== user_policy_id) ) {
1925		cmplz_clear_cookies('cmplz');
1926	}
1927}
1928
1929/*
1930 * Clear all our own cookies, to make sure path issues are resolved.
1931 *
1932 *
1933 */
1934function cmplz_clear_cookies(cookie_part){
1935	var foundCookie = false;
1936
1937	if (typeof document === 'undefined') {
1938		return foundCookie;
1939	}
1940	var secure = ";secure";
1941	var date = new Date();
1942	date.setTime(date.getTime() - (24 * 60 * 60 * 1000));
1943	var expires = ";expires=" + date.toGMTString();
1944	if (window.location.protocol !== "https:") secure = '';
1945	let cookies = document.cookie.split("; ");
1946	let pathname = location.pathname;
1947	let pathParts = pathname.replace(/^\/|\/$/g, '').split('/');
1948
1949	//loop through all cookies
1950	for (var i = 0; i < cookies.length; i++) {
1951		let cookieName = cookies[i].split(";")[0].split("=")[0];
1952		let host = window.location.hostname;
1953		var domainParts = host.split(".");
1954		//if we have more than one result in the array, we can skip the last one, as it will be the .com/.org extension
1955		let skip_last = domainParts.length > 1;
1956		//if the cookie contains cookie_part, try to delete it
1957		if ( cookieName.indexOf(cookie_part) !==-1 ) {
1958			foundCookie = true;
1959			let cookieBaseDomain = encodeURIComponent(cookieName) + '=;SameSite=Lax' + secure + expires +';domain=;path=';
1960			document.cookie = cookieBaseDomain + '/';
1961			//and on paths on root
1962			while ( pathParts.length > 0) {
1963				var path = pathParts.join('/');
1964				if ( path.length>0 ) {
1965					document.cookie = cookieBaseDomain + '/' + path;
1966					document.cookie = cookieBaseDomain + '/' + path + '/';
1967				}
1968				pathParts.pop();
1969			};
1970			while ( domainParts.length > 0) {
1971				let cookieBase 		 = encodeURIComponent(cookieName) + '=;SameSite=Lax' + secure + expires +';domain=.' + domainParts.join('.') + ';path=';
1972				document.cookie = cookieBase+ '/';
1973				while (pathParts.length > 0) {
1974					var path = pathParts.join('/');
1975					if ( path.length>0 ) {
1976						document.cookie = cookieBase + '/' + path;
1977						document.cookie = cookieBase + '/' + path + '/';
1978					}
1979					pathParts.pop();
1980				};
1981
1982				domainParts.shift();
1983				//prevents setting cookies on .com/.org
1984				if (skip_last && domainParts.length==1) domainParts.shift();
1985			}
1986		}
1987	}
1988
1989	//to prevent a double reload, we preserve the cookie policy id.
1990	cmplz_set_accepted_cookie_policy_id();
1991	return foundCookie;
1992}
1993
1994/*
1995 *
1996 * If a policy is accepted, save this in the user policy id
1997 *
1998 * */
1999
2000function cmplz_set_accepted_cookie_policy_id() {
2001	cmplz_set_cookie('policy_id', complianz.current_policy_id);
2002}
2003
2004/*
2005 * For supported integrations, initialize the not consented state
2006 *
2007 * */
2008
2009function cmplz_integrations_init() {
2010	var cookiesToSet = complianz.set_cookies;
2011	//check if we have scripts that need to be set to true on init.
2012	for (var key in cookiesToSet) {
2013		if (cookiesToSet.hasOwnProperty(key) && cookiesToSet[key][1] === '1') {
2014			cmplz_set_cookie(key, cookiesToSet[key][1], false);
2015		}
2016	}
2017}
2018
2019/*
2020 * For supported integrations, revoke consent
2021 *
2022 * */
2023function cmplz_integrations_revoke() {
2024	var cookiesToSet = complianz.set_cookies;
2025	for (var key in cookiesToSet) {
2026		if (cookiesToSet.hasOwnProperty(key)) {
2027			cmplz_set_cookie(key, cookiesToSet[key][1], false);
2028			if ( cookiesToSet[key][1] == false ){
2029				cmplz_clear_cookies(key);
2030			}
2031		}
2032	}
2033}
2034
2035/*
2036 * For supported integrations, set consent
2037 *
2038 * */
2039
2040function cmplz_set_integrations_cookies() {
2041	var cookiesToSet = complianz.set_cookies;
2042	for (var key in cookiesToSet) {
2043		if (cookiesToSet.hasOwnProperty(key)) {
2044			cmplz_set_cookie(key, cookiesToSet[key][0], false);
2045		}
2046	}
2047}
2048
2049function cmplz_get_url_parameter(sPageURL, sParam) {
2050	if ( !sPageURL || typeof sPageURL === 'undefined' ) {
2051		return false;
2052	}
2053
2054	if ( sPageURL.indexOf('?')==-1) {
2055		return false;
2056	}
2057
2058	var queryString = sPageURL.split('?');
2059	if (queryString.length == 1) return false;
2060
2061	var sURLVariables = queryString[1].split('&'),
2062		sParameterName,
2063		i;
2064	for (i = 0; i < sURLVariables.length; i++) {
2065		if ( sURLVariables.hasOwnProperty(i) ) {
2066			sParameterName = sURLVariables[i].split('=');
2067			if (sParameterName[0] === sParam) {
2068				return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
2069			}
2070		}
2071	}
2072	return false;
2073}
2074
2075/*
2076 * If the parameter cmplz_region_redirect =true is passed, find the user's region, and redirect.
2077 */
2078function cmplz_maybe_auto_redirect() {
2079	var redirect = cmplz_get_url_parameter(window.location.href, 'cmplz_region_redirect');
2080	var region = cmplz_get_url_parameter(window.location.href, 'cmplz-region');
2081	if (redirect && !region) {
2082		window.location.href = window.location.href + '&cmplz-region=' + complianz.region;
2083	}
2084}
2085
2086/*
2087 * wrapper to set consent for wp consent API. If consent API is not active, do nothing
2088 * @param type
2089 * @param value
2090 */
2091function cmplz_wp_set_consent(type, value) {
2092	//wp consent api integration
2093	if (typeof wp_set_consent == 'function') {
2094		wp_set_consent(type, value);
2095	}
2096}
2097
2098var cmplz_cookie_data = [];
2099var cmplzCleanCookieInterval;
2100function cmplz_start_clean(){
2101	if ( complianz.clean_cookies == 1 ) {
2102		//check if it's already stored
2103		if (typeof (Storage) !== "undefined" ) {
2104			cmplz_cookie_data = JSON.parse( sessionStorage.getItem('cmplz_cookie_data') );
2105		}
2106		//if not stored yet, load. As features in the user object can be changed on updates, we also check for the version
2107		if ( !cmplz_cookie_data || cmplz_cookie_data.length == 0 ) {
2108			let request = new XMLHttpRequest();
2109			request.open('GET', complianz.url+'cookie_data', true);
2110			request.setRequestHeader('Content-type', 'application/json');
2111			request.send();
2112			request.onload = function() {
2113				cmplz_cookie_data = JSON.parse(request.response);
2114				sessionStorage.setItem('cmplz_cookie_data', JSON.stringify(cmplz_cookie_data) );
2115				cmplz_setup_clean_interval();
2116			};
2117		} else {
2118			cmplz_setup_clean_interval();
2119		}
2120	}
2121}
2122
2123/*
2124* Execute the cleanup of cookies
2125*/
2126function cmplz_do_cleanup(){
2127	let consent_categories = [
2128		'preferences',
2129		'statistics',
2130		'marketing',
2131	];
2132	for (var i in consent_categories) {
2133		let category = consent_categories[i];
2134		if ( !cmplz_has_consent(category) && cmplz_cookie_data.hasOwnProperty(category) ) {
2135			let services = cmplz_cookie_data[category];
2136			for (var service in services) {
2137				if ( !cmplz_has_service_consent(service, category) ) {
2138					let cookies = services[service];
2139					for (var j in cookies) {
2140						let item = cookies[j];
2141						cmplz_clear_cookies(item);
2142						cmplz_clear_storage(item);
2143					}
2144				}
2145			}
2146		}
2147	}
2148}
2149
2150function cmplz_setup_clean_interval(){
2151	// if the cookie data array is empty, return, nothing to do.
2152	if ( !cmplz_cookie_data ) {
2153		return;
2154	}
2155	//check if it's already activated
2156	if ( cmplzCleanCookieInterval ) {
2157		return;
2158	}
2159	//one straight away, then every second
2160	cmplz_do_cleanup();
2161	cmplzCleanCookieInterval = setInterval(cmplz_do_cleanup, 1000 );
2162}
2163
2164/*
2165 * Clear an item from either session or localstorage
2166 * @param item
2167 */
2168function cmplz_clear_storage(item){
2169	if (typeof (Storage) !== "undefined" ) {
2170		if ( localStorage.getItem(item) ) {
2171			localStorage.removeItem(item);
2172		}
2173		if ( sessionStorage.getItem(item) ) {
2174			sessionStorage.removeItem(item);
2175		}
2176	}
2177}
2178/*
2179 * Load revoke options
2180 */
2181
2182function cmplz_load_manage_consent_container() {
2183	//don't load manage html code in the block editor
2184	let manage_consent_container = document.querySelector('.cmplz-manage-consent-container');
2185	let is_block_editor = false;//document.querySelector('.wp-admin .cmplz-unlinked-mode');
2186	if ( manage_consent_container && !is_block_editor ) {
2187
2188		let request = new XMLHttpRequest();
2189		request.open('GET', complianz.url+'manage_consent_html?'+complianz.locale, true);
2190		request.setRequestHeader('Content-type', 'application/json');
2191		request.send();
2192		request.onload = function() {
2193			let html = JSON.parse(request.response);
2194			manage_consent_container.insertAdjacentHTML( 'beforeend', html );
2195			cmplz_sync_category_checkboxes();
2196			let nojavascript = document.querySelector('#cmplz-manage-consent-container-nojavascript')
2197			nojavascript.style.display = 'none';
2198			manage_consent_container.style.display = 'block';
2199			let event = new CustomEvent('cmplz_manage_consent_container_loaded');
2200			document.dispatchEvent(event);
2201		};
2202	}
2203}
2204
2205/*
2206 * Make slider radio's tabable
2207 */
2208
2209cmplz_add_event('keypress', '.cmplz-banner-slider label', function(e){
2210	var keycode = (e.keyCode ? e.keyCode : e.which);
2211	if (keycode == 32) {
2212		document.activeElement.click();
2213	}
2214});
2215
2216/*
2217 * Make close button closable with enter
2218 */
2219cmplz_add_event('keypress', '.cmplz-cookiebanner .cmplz-header .cmplz-close', function(e){
2220	var keycode = (e.keyCode ? e.keyCode : e.which);
2221	if ( keycode == 13 ) {
2222		document.activeElement.click();
2223	}
2224});
2225
2226/*
2227 * Compare two arrays
2228 * @param array
2229 * @returns {boolean}
2230 */
2231function cmplz_equals (array_1, array_2) {
2232	if ( !Array.isArray(array_1) ) {
2233		array_1 = Object.keys(array_1);
2234		array_2 = Object.keys(array_2);
2235	}
2236	// if the other array is a falsy value, return
2237	if (!array_1 || !array_2)
2238		return false;
2239
2240	// compare lengths - can save a lot of time
2241	if (array_1.length != array_2.length)
2242		return false;
2243
2244	for (var i = 0, l=array_1.length; i < l; i++) {
2245		// Check if we have nested arrays
2246		if (array_1[i] instanceof Array && array_2[i] instanceof Array) {
2247			// recurse into the nested arrays
2248			if (!cmplz_equals(array_1[i], array_2[i]))
2249				return false;
2250		}
2251		else if (array_1[i] != array_2[i]) {
2252			// Warning - two different object instances will never be equal: {x:20} != {x:20}
2253			return false;
2254		}
2255	}
2256	return true;
2257}
2258
2259/*
2260* Copy all element atributes to the new element
2261*/
2262function cmplzCopyAttributes(source, target) {
2263	return Array.from(source.attributes).forEach(attribute => {
2264		//don't copy the type attribute
2265		let excludes = ['type', 'data-service', 'data-category', 'async'];
2266		if (  attribute.nodeName === 'data-script-type' && attribute.nodeValue === 'module' ) {
2267			target.setAttribute('type', 'module',);
2268			target.removeAttribute('data-script-type');
2269		}
2270
2271		if ( !excludes.includes(attribute.nodeName) ) {
2272			target.setAttribute(
2273				attribute.nodeName,
2274				attribute.nodeValue,
2275			);
2276		}
2277	});
2278}
2279
2280/*
2281 * Hooked into jquery
2282 */
2283let cmplz_has_wp_video = document.querySelector('.cmplz-wp-video-shortcode');
2284let cmplz_times_checked = 0;
2285if ('undefined' != typeof window.jQuery) {
2286	jQuery(document).ready(function ($) {
2287		if ( cmplz_has_wp_video ) {
2288			document.addEventListener("cmplz_enable_category", function (consentData) {
2289				cmplz_activate_wp_video();
2290			});
2291
2292			var cmplzInterval = setInterval(function(){
2293				cmplz_times_checked+=1;
2294				if ( document.querySelector('.cmplz-wp-video-shortcode') && cmplz_times_checked<100) {
2295					cmplz_activate_wp_video();
2296				} else {
2297					clearInterval(cmplzInterval);
2298				}
2299			}, 500);
2300		}
2301
2302		/*
2303		 * WordPress legacy shortcode
2304		 */
2305		function cmplz_activate_wp_video(again) {
2306			if ( !document.querySelector('.cmplz-wp-video-shortcode') ) {
2307				return;
2308			}
2309			let categories = cmplz_accepted_categories();
2310			let services = cmplz_get_all_service_consents();
2311			let selectorVideo = '';
2312			let selectorVideos = [];
2313			for (var c_key in categories) {
2314				if (categories.hasOwnProperty(c_key)) {
2315					let category = categories[c_key];
2316					if (category==='functional') {
2317						break;
2318					}
2319					selectorVideos.push('.cmplz-wp-video-shortcode[data-category="'+category+'"]');
2320				}
2321			}
2322			for (var s_key in services) {
2323				if (services.hasOwnProperty(s_key)) {
2324					selectorVideos.push('.cmplz-wp-video-shortcode[data-service=' + s_key + ']');
2325				}
2326			}
2327			selectorVideo = selectorVideos.join(',');
2328			let should_initialize_video = false;
2329			if ( selectorVideo.length>0 ) {
2330				document.querySelectorAll(selectorVideo).forEach(obj => {
2331					should_initialize_video = true;
2332					obj.setAttribute('controls', 'controls');
2333					obj.classList.add('wp-video-shortcode');
2334					obj.classList.add('cmplz-processed');
2335					obj.classList.remove('cmplz-wp-video-shortcode');
2336					obj.closest('.cmplz-wp-video').classList.remove('cmplz-wp-video');
2337
2338					let blocked_notice = obj.closest('.wp-video').querySelector('.cmplz-blocked-content-notice');
2339					if (blocked_notice) {
2340						blocked_notice.parentElement.removeChild(blocked_notice);
2341					}
2342					obj.classList.remove('cmplz-blocked-content-container');
2343				});
2344			}
2345
2346			if ( should_initialize_video ) {
2347				//in normal setup, this should work. e.g. with primavera theme not, then we init per element.
2348				if (window.wp.mediaelement) {
2349					window.wp.mediaelement.initialize()
2350				} else {
2351					let settings={};
2352					settings.videoWidth='100%';
2353					settings.videoHeight='100%';
2354					settings.enableAutosize=true;
2355					$( '.wp-video-shortcode' ).mediaelementplayer( settings );
2356				}
2357			}
2358		}
2359
2360		/*
2361		 * Activate fitvids on the parent element if active
2362		 *  a.o. Beaverbuilder
2363		 */
2364		document.querySelectorAll('.cmplz-video.cmplz-activated').forEach(obj => {
2365			cmplz_activate_fitvids(obj);
2366		});
2367
2368		document.addEventListener("cmplz_enable_category", function (e) {
2369			document.querySelectorAll('.cmplz-video.cmplz-activated').forEach(obj => {
2370				cmplz_activate_fitvids(obj);
2371			});
2372		});
2373
2374		function cmplz_activate_fitvids(obj){
2375			//turn obj into jquery object
2376			let $obj = $(obj);
2377			if (typeof $obj.parent().fitVids === 'function') {
2378				$obj.parent().fitVids();
2379			}
2380		}
2381	});
2382}

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.