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