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.