'use strict';
/**
* consent management plugin sets cookie when consent category value changes
*
*/
// wp_set_consent('marketing', 'allow');
/*
* Opt in (e.g. EU):
* default all scripts disabled.
* cookie banner
*
* Opt out (e.g. US):
* default all scripts enabled
* information cookie banner
*
* Other regions:
* default all scripts enabled
* no banner
*
* */
/*
* For examples to edit the behaviour of the banner, please see https://github.com/really-Simple-Plugins/complianz-integrations
* */
jQuery(document).ready(function ($) {
//prevent caching of the WP Rest API by varnish or other caching tools
complianz.url = complianz.url + '&token='+Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
/**
* CustomEvent() polyfill
* https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
*/
(function () {
if (typeof window.CustomEvent === 'function') return false;
function CustomEvent(event, params) {
params = params || { bubbles: false, cancelable: false, detail: undefined };
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
})();
var ccStatus;
var ccName;
var ccStatsEnabled = false;
var ccAllEnabled = false;
var waitingInlineScripts = [];
var waitingScripts = [];
var placeholderClassIndex = 0;
var curClass = '';
var cmplzAllScriptsHookFired = false;
var cmplzLocalhostWarningShown = false;
var cmplzCategories = [
'cmplz_functional',
'cmplz_prefs',
'cmplz_stats',
'cmplz_marketing',
];
/**
* Show manage consent area
*/
$('#cmplz-manage-consent-container-nojavascript').hide();
$('#cmplz-manage-consent-container').show();
/**
* prevent scroll to top behaviour because of missing href tag
*/
$(document).on('click', '.cc-btn-no-href', function (e) {
e.preventDefault();
});
/**
* Sets the current status as body class
*/
function setStatusAsBodyClass(status) {
var ccBody = $('body');
ccBody.removeClass(curClass);
ccBody.addClass('cmplz-status-' + status);
ccBody.addClass('cmplz-' + complianz.region );
ccBody.addClass('cmplz-' + complianz.consenttype );
curClass = 'cmplz-status-' + status;
}
/**
* This creates an API which devs can use to trigger actions in complianz.
*/
document.addEventListener('cmplz_consent_action', function (e) {
cmplzFireCategories( e.detail.category , true);
cmplzSyncCategoryCheckboxes();
cmplzSaveCategoriesSelection();
});
/**
* Set placeholder image as background on the parent div, set notice, and handle height.
*
* */
function setBlockedContentContainer() {
//to prevent this function to twice on an element, we add an attribute to each element that has been processed.
//then skip elements with that element.
$('.cmplz-image').each(function (i, obj) {
if ( $(this).hasClass('cmplz-processed') ) return;
$(this).addClass('cmplz-processed' );
var blockedImageContainer = $(this).parent();
blockedImageContainer.addClass('cmplz-blocked-content-container');
//handle browser native lazy load feature
if ($(this).attr('loading') === 'lazy' ) {
$(this).removeAttr('loading');
$(this).data('deferlazy', 1);
}
//insert placeholder text
if (cmplzGetHighestAcceptance() !== 'marketing' && !blockedImageContainer.find(".cmplz-blocked-content-notice").length) {
var placeholderText = complianz.placeholdertext;
if (typeof placeholderText !== 'undefined') blockedImageContainer.append('');
}
});
$('.cmplz-placeholder-element').each(function () {
if ( $(this).hasClass('cmplz-processed') ) return;
$(this).addClass('cmplz-processed' );
//we set this element as container with placeholder image
var blockedContentContainer;
if ($(this).hasClass('cmplz-iframe')) {
//handle browser native lazy load feature
if ($(this).attr('loading') === 'lazy' ) {
$(this).removeAttr('loading');
$(this).data('deferlazy', 1);
}
blockedContentContainer = $(this).parent();
} else {
blockedContentContainer = $(this);
}
var curIndex = blockedContentContainer.data('placeholderClassIndex');
//if the blocked content container class is already added, don't add it again
if (typeof curIndex === 'undefined') {
placeholderClassIndex++;
blockedContentContainer.addClass('cmplz-placeholder-' + placeholderClassIndex);
blockedContentContainer.addClass('cmplz-blocked-content-container');
blockedContentContainer.data('placeholderClassIndex', placeholderClassIndex);
//insert placeholder text
if (cmplzGetHighestAcceptance() !== 'marketing' && !blockedContentContainer.find(".cmplz-blocked-content-notice").length) {
var placeholderText = complianz.placeholdertext;
if (typeof placeholderText !== 'undefined') blockedContentContainer.append('');
}
//handle image size for video
var src = $(this).data('placeholder-image');
if (typeof src !== 'undefined' && src.length) {
src = src.replace('url(', '').replace(')', '').replace(/\"/gi, "");
$('head').append('');
setBlockedContentContainerAspectRatio($(this), src, placeholderClassIndex);
}
}
});
/**
* 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.
* We're assuming that statistics scripts won't be loaded with ajax, so we only load marketing level scripts
*
*/
if ( cmplzGetHighestAcceptance() === 'marketing') {
cmplzEnableMarketing();
}
}
/**
* Set the height of an image relative to the width, depending on the image widht/height aspect ratio.
*
*
* */
function setBlockedContentContainerAspectRatio(container, src, placeholderClassIndex) {
if (typeof container === 'undefined') return;
//we set the first parent div as container with placeholder image
var blockedContentContainer = container.parent();
//handle image size for video
var img = new Image();
img.addEventListener("load", function () {
var imgWidth = this.naturalWidth;
var imgHeight = this.naturalHeight;
//prevent division by zero.
if (imgWidth === 0) imgWidth = 1;
var w = blockedContentContainer.width();
var h = imgHeight * (w / imgWidth);
var heightCSS = '';
if (src.indexOf('placeholder.jpg') === -1) {
heightCSS = 'height:' + h + 'px;';
}
$('head').append('');
});
img.src = src;
}
/**
* Keep window aspect ratio in sync when window resizes
* To lower the number of times this code is executed, it is done with a timeout.
*
* */
var resizeTimer;
$(window).on( "resize", function() {
clearTimeout(resizeTimer);
//resizeTimer = setTimeout( setBlockedContentContainer, 100);
});
/**
* we run this function also on an interval, because with ajax loaded content, the placeholders would otherwise not be handled.
*/
//if ( complianz.block_ajax_content == 1 ) {
setInterval(function () {
setBlockedContentContainer();
}, 2000);
//}
/**
* Enable scripts that were blocked
*
* */
function cmplzEnableMarketing() {
var event = new CustomEvent('cmplzRunBeforeAllScripts' );
document.dispatchEvent(event);
//check if the stats were already running. Don't enable in case of categories, as it should be handled by cmplzFireCategories
if (complianz.use_categories === 'no' && !ccStatsEnabled) {
cmplzEnableStats();
}
//enable cookies for integrations
cmplzIntegrationsConsent();
//styles
$('.cmplz-style-element').each(function (i, obj) {
if ( $(this).hasClass('cmplz-activated') ) return;
$(this).addClass('cmplz-activated' );
var src = $(this).data('href');
$('head').append('');
});
//remove accept cookie notice overlay
$('.cmplz-blocked-content-notice').each(function () {
$(this).remove();
});
//blocked images
$('.cmplz-image').each(function (i, obj) {
if ( $(this).hasClass('cmplz-activated') ) return;
$(this).addClass('cmplz-activated' );
var src = $(this).data('src-cmplz');
$(this).attr('src', src);
//handle browser native lazy load feature
if ($(this).data('deferlazy')) {
$(this).attr('loading', 'lazy');
}
});
$('.cmplz-iframe').each(function (i, obj) {
if ( $(this).hasClass('cmplz-activated') ) return;
$(this).addClass('cmplz-activated' );
var src = $(this).data('src-cmplz');
//check if there's an autoplay value we need to pass on
var autoplay = cmplzGetUrlParameter($(this).attr('src'), 'autoplay');
if (autoplay === '1') src = src + '&autoplay=1';
$(this).attr('src', src).on( 'load' , function () {
//fitvids integration, a.o. Beaverbuilder
if (typeof $(this).parent().fitVids == 'function') {
$(this).parent().fitVids();
}
var curElement = $(this);
//handle browser native lazy load feature
if ($(this).data('deferlazy')) {
$(this).attr('loading', 'lazy');
}
//we get the closest, not the parent, because a script could have inserted a div in the meantime.
var blockedContentContainer = $(this).closest('.cmplz-blocked-content-container');
//now remove the added classes
blockedContentContainer.animate({"background-image": "url('')"}, 400, function () {
var cssIndex = blockedContentContainer.data('placeholderClassIndex');
blockedContentContainer.removeClass('cmplz-blocked-content-container');
blockedContentContainer.removeClass('cmplz-placeholder-' + cssIndex);
curElement.removeClass('cmplz-iframe-styles');
curElement.removeClass('cmplz-iframe');
//in some cases the videowrap gets added to the iframe
curElement.removeClass('video-wrap');
curElement.removeClass('cmplz-hidden');
});
});
});
//other services, no iframe, with placeholders
$('.cmplz-noframe').each(function (i, obj) {
if ( $(this).hasClass('cmplz-activated') ) return;
$(this).addClass('cmplz-activated' );
var blockedContentContainer = $(this);
//remove the added classes
var cssIndex = blockedContentContainer.data('placeholderClassIndex');
blockedContentContainer.removeClass('cmplz-blocked-content-container');
blockedContentContainer.removeClass('cmplz-noframe');
blockedContentContainer.removeClass('cmplz-placeholder-' + cssIndex);
});
//first, create list of waiting scripts
var scriptElements = $('.cmplz-script');
scriptElements.each(function (i, obj) {
var waitfor = $(this).data('waitfor');
var src = $(this).attr('src');
if (src && src.length) {
if (typeof (waitfor) !== "undefined") {
waitingScripts[waitfor] = src;
}
} else if ($(this).text().length) {
if (typeof (waitfor) !== "undefined") {
waitingInlineScripts[waitfor] = $(this);
}
}
});
//scripts: set "cmplz-script classes to type="text/javascript"
scriptElements.each(function (i, obj) {
if ( $(this).hasClass('cmplz-activated') ) return;
$(this).addClass('cmplz-activated' );
//do not run stats scripts yet. We leave that to the dedicated stats function cmplzEnableStats()
if ($(this).hasClass('cmplz-stats')) return true;
var src = $(this).attr('src');
if (src && src.length) {
$(this).attr('type', 'text/javascript');
//check if this src or txt is in a waiting script. If so, skip.
if (cmplzIsWaitingScript(waitingScripts, src)) {
return;
}
if (typeof $(this).data('post_scribe_id') !== 'undefined') {
var psID = '#' + $(this).data('post_scribe_id');
if ($(psID).length) {
$(psID).html('');
$(function () {
postscribe(psID, '');
});
}
} else {
$.getScript(src)
.done(function (s, Status) {
var allScriptsExecuted = true;
//check if we have waiting scripts
var waitingScript = cmplzGetWaitingScript(waitingScripts, src);
if (waitingScript) {
allScriptsExecuted = false;
$.getScript(waitingScript).done(function (script, textStatus) {
cmplzRunAfterAllScripts();
}).fail(function (jqxhr, settings, exception) {
console.warn("Something went wrong " + exception);
});
}
var waitingInlineScript = cmplzGetWaitingScript(waitingInlineScripts, src);
if (waitingInlineScript) {
allScriptsExecuted = false;
cmplzRunInlineScript(waitingInlineScript);
}
//maybe all scripts are already done
if (allScriptsExecuted) cmplzRunAfterAllScripts();
})
.fail(function (jqxhr, settings, exception) {
console.warn("Something went wrong " + exception);
});
}
} else if ($(this).text().length) {
//check if this src or txt is in a waiting script. If so, skip.
if (cmplzIsWaitingScript(waitingInlineScripts, $(this).text())) {
return;
}
cmplzRunInlineScript($(this));
}
});
if (!ccAllEnabled) {
//fire an event so custom scripts can hook into this.
var event = new CustomEvent('cmplzEnableScripts', { detail: 'marketing' });
document.dispatchEvent(event);
//javascript event
var event = document.createEvent('Event');
event.initEvent('cmplzEnableScriptsMarketing', true, true);
document.dispatchEvent(event);
//if there are no blockable scripts at all, we still want to provide a hook
//in most cases, this script fires too early, and won't run yet. In that
//case it's run from the script activation callbacks.
cmplzRunAfterAllScripts();
ccAllEnabled = true;
}
}
/**
* check if the passed source has a waiting script that should be executed, and return it if so.
* @param waitingScripts
* @param src
* @returns {*}
*/
function cmplzGetWaitingScript(waitingScripts, src) {
for (var waitfor in waitingScripts) {
var waitingScript;//recaptcha/api.js, waitfor="gregaptcha"
if (waitingScripts.hasOwnProperty(waitfor)) {
waitingScript = waitingScripts[waitfor];
if (typeof waitingScript !== 'string') {
waitingScript = waitingScript.text();
}
if (src.indexOf(waitfor) !== -1) {
var output = waitingScripts[waitfor];
delete waitingScripts[waitfor];
return output;
}
}
}
return false;
}
/**
* Because we need a key=>value array in javascript, the .length check for an empty array doesn't work.
* @param arr
* @returns {boolean}
*/
function cmplzArrayIsEmpty(arr) {
for (var key in arr) {
if (arr.hasOwnProperty(key)) {
return false;
}
}
return true;
}
/**
* Check if the passed src or script is waiting for another script and should not execute
* @param waitingScripts
* @param srcOrScript
*/
function cmplzIsWaitingScript(waitingScripts, srcOrScript) {
for (var waitfor in waitingScripts) {
if (waitingScripts.hasOwnProperty(waitfor)) {
var waitingScript = waitingScripts[waitfor];
if (typeof waitingScript !== 'string') waitingScript = waitingScript.text();
if (srcOrScript.indexOf(waitingScript) !== -1 || waitingScript.indexOf(srcOrScript) !== -1) {
return true;
}
}
}
return false;
}
/**
* if all scripts have been executed, fire a hook.
*/
function cmplzRunAfterAllScripts() {
if (!cmplzAllScriptsHookFired && cmplzArrayIsEmpty(waitingInlineScripts) && cmplzArrayIsEmpty(waitingScripts) ) {
var event = new CustomEvent( 'cmplzRunAfterAllScripts' );
document.dispatchEvent(event);
cmplzAllScriptsHookFired = true;
}
}
/**
* run inline script
* @param script
*/
function cmplzRunInlineScript(script) {
$('