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