�PNG  IHDR22?�� pHYs  �� OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*! J�!��Q�EEȠ�����Q, � ��!���������{�kּ������>���� �H3Q5� �B�������.@� $p�d!s�#�~<<+"��x� �M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!�� e�Dh;��V�EX0fK�9�-0IWfH���� � 0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4���������x����6��_-��"bb���ϫp@�t~��,/��;�m��%�h^ �u��f�@����W�p�~<�5�j>{�-�]c�K'Xt����o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A��,���� �`6�B$��BB d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(�� A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2����G1���Q=� �C��7�F� �dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8, �c˱"� ���V����cϱw�E� 6wB aAHXLXN�H� $4� 7 �Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[ �b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w ��Ljg(�gw��L�Ӌ�T071���oUX*�*|�� �J�&�*/T����ު U�U�T��^S}�FU3S� Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_�� c�x,!k ��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN �(���~���)�)�4L�1e\k����X�H�Q�G�6������E�Y��A�J'\'Gg����S�Sݧ �M=:��.�k���Dw�n��^��Lo��y���}/�T�m���G X� $� �<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��= ���Z~s�r:V:ޚΜ�?}����/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z���������ۯ�6�i�ܟ�4�)�Y3s���C�Q��? ��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�������!h�쐭!��Α�i�P~���a�a��~ '���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl������� �{�/�]py�����.,:�@L�N8��A*��%�w%� y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y- �B��TZ(�*�geWf�͉�9���+��̳�ې7�����ᒶ��KW-X潬j9�������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n �ڴ �V����E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa��n��{��4���[���>ɾ�UUM�f�e�I���?�������m]�Nmq����#�׹���=TR��+�G�����w- 6 U����#pDy��� �� :�v�{���vg/jB��F�S��[b[�O�>����z�G��499�?r����C�d�&����ˮ/~�����јѡ�򗓿m|������������x31^�V���w�w��O�| (�h���SЧ��������c3-� cHRMz%������u0�`:�o�_�F5IDATx��ytUս�?�;���fN$$��@B�!�k��� -*�gE���j�O�kQ�ʠ`U�B_ �AÐ0%�Ȕ�@r3ޛ;߳��$�@��v����^�s����������$��ߢ !�W��5�̱'-٘������4�>�Rƫ$�G��0U�H}�_ _� #��k�MJ/=�9Du *ڲ�k�PQ;0��j|�*�$�^컂脛y���>�z×� B��� ��(�:$�ʔ_�6��C!B����MVx��a��ζyY����j��ƋY2�9�F�{r��r�딟F��Q��hY6��� x��[l��RC��������nt@��;P��3��� F�w��7��:�P���ɋ'���mj���Bƪ�$�Q�L��y��߷g��\���z����v5�p�v$�v櫻�`6~K �Y�X����,�:��"�o�e0II"(��,������l_�C���/4�+f�E�!q��:����u����c��樼.UE�@� �]K�W���$-�h]�JG���Dz)�`��.�A/ ���mᏣc�3jK� �!�>���$�Q�!�_�? \�C2(E �M$Z I{�U���s�ǣ���=��@Բe ޻��W�����@ �w����}�9v,)��.}*|"�s��di���,���G�]W�AC�������|<����[��ߕ������K�*�G nߴ!��‹��J�!��6(L�a)��Am��������;adf��:�xm��nh�;֦I��(���o�C~ډa?�=��s����h��E������xp����)���_���t��W�����´;8���`dz=(��@@�+,�;�`�fhl��XȌ�3,uI�~z(J����� �ZX�A����H'�À�㜦�82|��a�n�z2��I���� ���EY�h�ε<�0�q�{��C��v�˅��?"@��χ�x�WS+��N�~�KQ�J�8ل�� _.W��� !TU{�����,��"�� �;�������HI S� ��))�o�1�H�D� ���� (� ;����"Ҕ��,���� �F=���O��&�Ph>�`���y��߲ &S��P�<��'��1s�1cĂ�N����2)����@�u��tv��<�+�-&�����h��[!FSG���' � z z0��<����8d&�����E0�,��<��"!P�b4��� �{S�����X����.�囤���T��hEF��X�q0"-<����h���]�Py*����F⩍��@v�˂�Y08�� .q��a��s����(!<̫1�3�L�H��7sYW�`��qtu�\7��?�@�Y�� %Ka�x�GZ�*W�P��y�����N0r9��Z�c�%���q,��k�����!!,��>���IB��� �x1�Xu�Y���v-���ֺ��N������JP��a�2`�e5��w��u;�6�i���̃��(K���ťa��(l51��JL��O'%���]���ٖ뿉!��{*�p+f ���i8��D�ȑ���ܩ�M��V��ӟz��x�7Z�1i}�^͜���6e����x��)u�d�ˏ�V�eG�\�X1�����=n�U'�~Y����L�\,�(d!x ,�:�TW8� M`r���@��r+v�Q0��>^;˴�VbF��('����� �*O��i��j�Ӆ����^�S3&� ���{������.ی�� N;��NU%d0�Ce\r"�C�b��&t7N�7��� �ȪD�[%l�۪�$��'m?�A9tI�9>��NVL ��� 6v~M�����ъ�B���0����9$&=ώm��W�0���L���&��E���f�f��'+�9��hv��7,���M��6�D�&�^� �����8 D֮�����o��k^z��O��hP�8q�5d*��YVq3�{��������#LX4�?��jP=3�~�؅c�ݰ�̱�ұ��8̲��2�G�����j��έ�9��w7���U�X�w�85C��?!I&���o&����L���I#�^�eV�,�^t5�k� �xs˛\��U�8��."���{���ǵ�l4��ݼ�;��r"���G�/~���gJV�N糦��ZZ^k+NN�D��I$�=OE�z����|*�*{��%k���G��>�`9��b;�s���8,�qs��c��.b��q�%�>r��n�R�Ƨ�%�,�A��le#�8���}; 21�0�b�&�QX�f���q�00����$>�h�N�'�a3��A���/�r ��L5�8�GԲ'�����w;��c#�q1���h$*��V^�k��QĽ�b:i������� ����H F#�_���,��]g����Ը����`RUU���� ��"�qD���>-��ϤI�~��3�̴�����NZ[[555�eeek7�m����YF#[��Đ��R��i��L�H�r ��@��J-�Pŝ��_|�-��6y��ks�V�U~��6���w.����(��0A� 4��f��� /���C�xŊ�ٳ����z=6�����rg���mKo��o�/����a�g���?'9%9��P��斓��~���L{�� �H��{AW��B��$����v�1b�&Mb�ر��ر#�0`�`xMBp! )Z�Nmo�mZ�g�}�eذaWTVV ���'99��C5��&�&+5�bT>|8��PUUETT����&���t��~TE%��'������b�tEGG;RSS�S�N�v��ѯ��t����u1@�ޚ"f��͈���r'L�Ph��m��ƌ�74o��`�x�q�P���NRSS�X,�����l&&&��MFFA!-��`��ҷ�n��Yuu�����x<I�LB%����KԒ50�!�3�bz�����ʸKL���;---�l6[��`��������Ȏ;�����egg4��!D�T��jWujyZ��������K����%����p�^���X,6��sV=�ܖ����6�3�X ���4ҿ��A2�&����_k�;d�� �VfOIEND�B`�
Warning: session_start(): Session cannot be started after headers have already been sent in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 124

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 130

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 131

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 132

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 133

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 134

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 135

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 547

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 548

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 549

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 550

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 551
'use strict'; /* * Opt in (e.g. EU): * default all scripts disabled. * cookie banner * * Opt out (e.g. US): * default all scripts enabled * opt out 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 * */ // Cookie cleanup data - declared at top level to avoid TDZ issues let cmplz_cookie_data = []; let cmplzCleanCookieInterval; /* * Debug logger. Only emits when SCRIPT_DEBUG is enabled (complianz.debug), * so diagnostics stay available for developers without spamming visitors. * @param args */ function cmplz_log( ...args ) { if ( typeof complianz === 'undefined' || ! complianz.debug ) { return; } // eslint-disable-next-line no-console console.warn( ...args ); } /* * Create an element * @param el * @param content * @returns {*} */ function cmplz_create_element( el, content ) { const obj = document.createElement( el ); obj.innerHtml = content; return obj; } /* * Add an event * @param event * @param selector * @param callback * @param context */ function cmplz_add_event( event, selector, callback ) { document.addEventListener( event, ( e ) => { if ( e.target.closest( selector ) ) { callback( e ); } } ); } /* * Check if the element is hidden * @param el * @returns {boolean} */ function cmplz_is_hidden( el ) { return ( el.offsetParent === null ); } function cmplz_html_decode( input ) { const doc = new DOMParser().parseFromString( input, 'text/html' ); return doc.documentElement.textContent; } /* * Sanitize placeholder HTML before injecting it into DOM. * Keeps expected markup but removes scripts and risky attributes. */ function cmplz_sanitize_placeholder_html( input ) { const template = document.createElement( 'template' ); template.innerHTML = String( input || '' ); // Remove active content elements entirely. template.content.querySelectorAll( 'script, iframe, object, embed, link, style, base, meta' ).forEach( ( el ) => { el.remove(); } ); template.content.querySelectorAll( '*' ).forEach( ( el ) => { Array.from( el.attributes ).forEach( ( attr ) => { const attrName = attr.name.toLowerCase(); // Remove inline event handlers like onclick. if ( attrName.indexOf( 'on' ) === 0 ) { el.removeAttribute( attr.name ); return; } // Block javascript: and data: URLs on URL-based attributes. const attrValue = attr.value.trim(); if ( ( attrName === 'href' || attrName === 'src' || attrName === 'xlink:href' ) && /^\s*(javascript:|data:)/i.test( attrValue ) ) { el.removeAttribute( attr.name ); } } ); } ); return template.innerHTML; } /* * Validate dynamic script URLs before assigning to script.src. * Only allow http(s) URLs (including relative URLs resolved by URL()). */ function cmplz_is_safe_script_src( scriptUrl ) { if ( typeof scriptUrl !== 'string' ) { return false; } const trimmed = scriptUrl.trim(); if ( ! trimmed ) { return false; } try { const parsedUrl = new URL( trimmed, window.location.href ); return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:'; } catch ( e ) { return false; } } /* * Focus trap functions for cookie banner modal */ function cmplz_trap_focus() { if ( ! cmplz_banner ) { return; } // Store current active element cmplz_original_active_element = cmplz_banner.ownerDocument.activeElement; // Add class to body for CSS targeting if ( complianz.soft_cookiewall ) { document.body.classList.add( 'cmplz-banner-active' ); } // Add keydown listener at document level so it fires regardless of propagation document.addEventListener( 'keydown', cmplz_handle_tab_navigation ); // Focus first focusable element in banner const focusableElements = cmplz_banner.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); if ( focusableElements.length > 0 ) { focusableElements[ 0 ].focus(); } } function cmplz_handle_tab_navigation( e ) { if ( e.key !== 'Tab' || ! cmplz_banner ) { return; } const focusableElements = Array.from( cmplz_banner.querySelectorAll( 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])' ) ).filter( function( el ) { return el.offsetParent !== null; } ); if ( focusableElements.length === 0 ) { e.preventDefault(); return; } const firstElement = focusableElements[ 0 ]; const lastElement = focusableElements[ focusableElements.length - 1 ]; const activeElement = cmplz_banner.ownerDocument.activeElement; const focusIsInBanner = cmplz_banner.contains( activeElement ); if ( e.shiftKey ) { if ( ! focusIsInBanner || activeElement === firstElement ) { e.preventDefault(); lastElement.focus(); } } else if ( ! focusIsInBanner || activeElement === lastElement ) { e.preventDefault(); firstElement.focus(); } } function cmplz_release_focus_trap() { document.removeEventListener( 'keydown', cmplz_handle_tab_navigation ); // Remove class from body document.body.classList.remove( 'cmplz-banner-active' ); const triggerSource = cmplz_banner_trigger_source; cmplz_banner_trigger_source = 'page-load'; if ( triggerSource === 'manage-consent' ) { // Return focus to the button that opened the dialog if ( cmplz_original_active_element && cmplz_original_active_element.focus ) { try { cmplz_original_active_element.focus(); } catch ( e ) { document.body.focus(); } } } else if ( cmplz_last_input_was_keyboard ) { // Page-load + keyboard: move focus to the skip-navigation link so keyboard // users can proceed. Skipped for mouse/touch to avoid a visible skip-link flash. const skipLink = document.querySelector( 'a[href="#content"], a[href="#main"], a[href="#main-content"], .skip-link' ); if ( skipLink ) { skipLink.focus(); } else { document.body.focus(); } } } /** * Consent Area management for shortcode and block editor */ document.querySelectorAll( '.cmplz-consent-area.cmplz-placeholder' ).forEach( ( cmplzConsentArea ) => { cmplzConsentArea.addEventListener( 'click', ( e ) => { let container = e.target; if ( ! container.classList.contains( 'cmplz-consent-area' ) ) { container = e.target.closest( '.cmplz-consent-area.cmplz-placeholder' ); } if ( container ) { const consentedService = container.getAttribute( 'data-service' ); cmplz_set_service_consent( consentedService, true ); cmplzLoadConsentAreaContent( false, consentedService ); cmplz_enable_category( null, consentedService ); cmplz_set_banner_status( 'dismissed' ); } } ); document.addEventListener( 'cmplz_enable_category', function( consentData ) { const consentedCategory = consentData.detail.category; const consentedService = consentData.detail.service; cmplzLoadConsentAreaContent( consentedCategory, consentedService ); } ); } ); function cmplzLoadConsentAreaContent( consentedCategory, consentedService ) { document.querySelectorAll( '.cmplz-consent-area.cmplz-placeholder' ).forEach( ( obj ) => { const category = obj.getAttribute( 'data-category' ); const service = obj.getAttribute( 'data-service' ); const postId = obj.getAttribute( 'data-post_id' ); const blockId = obj.getAttribute( 'data-block_id' ); if ( consentedCategory === category || consentedService === service ) { //if not stored yet, load. As features in the user object can be changed on updates, we also check for the version const request = new XMLHttpRequest(); request.open( 'GET', complianz.url + 'consent-area/' + postId + '/' + blockId, true ); request.setRequestHeader( 'Content-type', 'application/json' ); request.send(); obj.classList.remove( 'cmplz-placeholder' ); request.onload = function() { obj.innerHTML = JSON.parse( request.response ); //search for script elements and execute them obj.querySelectorAll( 'script' ).forEach( ( scriptEl ) => { cmplz_run_script( scriptEl.innerHTML, category, service, 'inline', scriptEl ); } ); }; } } ); } /* * If an anchor is passed for an element which may load only after an ajax call, make sure it will scroll into view. */ document.addEventListener( 'cmplz_manage_consent_container_loaded', function() { const url = window.location.href; if ( url.indexOf( '#' ) !== -1 ) { const end_pos = url.lastIndexOf( '?' ) !== -1 ? url.lastIndexOf( '?' ) : undefined; const anchor = url.substring( url.indexOf( '#' ) + 1, end_pos ); const element = document.getElementById( anchor ); if ( element ) { const y = element.getBoundingClientRect().top + window.pageYOffset - 200; window.scrollTo( { top: y, behavior: 'smooth' } ); } } } ); /* * prevent caching of the WP Rest API by varnish or other caching tools */ complianz.locale = complianz.locale + '&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 }; const evt = document.createEvent( 'CustomEvent' ); evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); return evt; } CustomEvent.prototype = window.Event.prototype; window.CustomEvent = CustomEvent; }() ); let cmplz_banner;//look this one up when the cookiebanner loads. const cmplz_banner_container = document.getElementById( 'cmplz-cookiebanner-container' ); let cmplz_manage_consent_button; const cmplz_waiting_inline_scripts = []; const cmplz_waiting_scripts = []; const cmplz_fired_scripts = []; let cmplz_placeholder_class_index = 0; let cmplz_all_scripts_hook_fired = false; let cmplz_consent_stored_once = false; const cmplz_fired_category_events = [ 'functional' ]; const cmplz_fired_service_events = []; const cmplz_categories = [ 'functional', 'preferences', 'statistics', 'marketing', ]; // Focus trap variables let cmplz_original_active_element = null; let cmplz_banner_trigger_source = 'page-load'; // 'page-load' | 'manage-consent' // Track the last input modality so we only move focus to the skip link when // the banner was dismissed via keyboard. Mouse/touch users keep their focus // where the click left it, avoiding a visible skip-link flash. let cmplz_last_input_was_keyboard = false; document.addEventListener( 'keydown', function() { cmplz_last_input_was_keyboard = true; }, true ); document.addEventListener( 'pointerdown', function() { cmplz_last_input_was_keyboard = false; }, true ); /* * Get a cookie by name * @param name * @returns {string} */ window.cmplz_get_cookie = function( name ) { if ( typeof document === 'undefined' ) { return ''; } name = complianz.prefix + name; const cookies = document.cookie.split( ';' ); for ( let i = 0; i < cookies.length; i++ ) { const cookie = cookies[ i ].trim(); if ( cookie.startsWith( name + '=' ) ) { return cookie.substring( name.length + 1 ); } } return ''; }; /* * set a cookie * @param name * @param value * @param use_prefix */ window.cmplz_set_cookie = function( name, value, use_prefix ) { if ( typeof document === 'undefined' ) { return; } use_prefix = typeof use_prefix !== 'undefined' ? use_prefix : true; const secure = window.location.protocol === 'https:' ? ';secure' : ''; const date = new Date(); date.setTime( date.getTime() + ( complianz.cookie_expiry * 24 * 60 * 60 * 1000 ) ); const expires = ';expires=' + date.toGMTString(); const domain = cmplz_get_cookie_domain(); const domainString = domain.length > 0 ? `;domain=${ domain }` : ''; const prefix = use_prefix ? complianz.prefix : ''; const cookiePath = cmplz_get_cookie_path(); document.cookie = `${ prefix }${ name }=${ value };SameSite=Lax${ secure }${ expires }${ domainString };path=${ cookiePath }`; }; /* * Check if needle occurs in the haystack * @param needle * @param haystack * @returns {boolean} */ window.cmplz_in_array = function( needle, haystack ) { return haystack.includes( needle ); }; /* * Retrieve the highest level of consent that has been given * * */ window.cmplz_highest_accepted_category = function() { const consentedCategories = cmplz_accepted_categories(); const priorityCategories = [ 'marketing', 'statistics', 'preferences' ]; for ( let i = 0; i < priorityCategories.length; i++ ) { if ( cmplz_in_array( priorityCategories[ i ], consentedCategories ) ) { return priorityCategories[ i ]; } } return 'functional'; }; /* * Sets all accepted categories as class in body */ const cmplz_set_category_as_body_class = () => { const classList = document.body.classList; for ( let i = classList.length - 1; i >= 0; i-- ) { if ( classList[ i ].startsWith( 'cmplz-' ) && classList[ i ] !== 'cmplz-document' ) { classList.remove( classList[ i ] ); } } const cats = cmplz_accepted_categories(); Object.values( cats ).forEach( ( category ) => { if ( typeof category === 'string' ) { classList.add( 'cmplz-' + category ); } } ); const services = cmplz_get_all_service_consents(); Object.entries( services ).forEach( ( [ service, consent ] ) => { if ( consent ) { classList.add( 'cmplz-' + service ); } } ); classList.add( 'cmplz-' + complianz.region, 'cmplz-' + complianz.consenttype ); const event = new CustomEvent( 'cmplz_set_category_as_bodyclass' ); document.dispatchEvent( event ); }; const cmplz_append_css = ( css ) => { const head = document.head || document.getElementsByTagName( 'head' )[ 0 ]; const style = document.createElement( 'style' ); style.setAttribute( 'type', 'text/css' ); style.appendChild( document.createTextNode( css ) ); head.appendChild( style ); }; const cmplz_load_css = ( path ) => { const head = document.head || document.getElementsByTagName( 'head' )[ 0 ]; const targetObj = document.createElement( 'link' ); targetObj.rel = 'stylesheet'; targetObj.type = 'text/css'; targetObj.href = path; head.appendChild( targetObj ); }; /* * Run script, src or inline * @param script //src or inline script * @param category * @param type */ function cmplz_run_script( script, category, service, type, sourceObj ) { const targetObj = document.createElement( 'script' ); if ( type !== 'inline' && cmplz_is_safe_script_src( script ) ) { targetObj.src = script; } else { if ( typeof script !== 'string' ) { script = script.innerHTML; } targetObj.textContent = [ script, 'cmplzScriptLoaded();' ].join( '\n' ); } //check if already fired if ( cmplz_in_array( script, cmplz_fired_scripts ) ) { return; } cmplzCopyAttributes( sourceObj, targetObj ); try { if ( type !== 'inline' ) { targetObj.onload = function() { cmplz_run_after_all_scripts( category, service ); cmplz_maybe_run_waiting_scripts( script, category, service, sourceObj ); }; } else { window.cmplzScriptLoaded = function() { cmplz_run_after_all_scripts( category, service ); cmplz_maybe_run_waiting_scripts( script, category, service, sourceObj ); }; } document.head.appendChild( targetObj ); } catch ( exception ) { //only runs in case of error cmplz_run_after_all_scripts( category, service ); throw 'Something went wrong ' + exception + ' while loading ' + script; } } /* * Check if there are waiting scripts, and if so, run them. * @param script //src or inline script * @param category */ function cmplz_maybe_run_waiting_scripts( script, category, service, sourceObj ) { const waitingScript = cmplz_get_waiting_script( cmplz_waiting_scripts, script ); if ( waitingScript ) { cmplz_run_script( waitingScript, category, service, 'src', sourceObj ); } const waiting_inline_script = cmplz_get_waiting_script( cmplz_waiting_inline_scripts, script ); if ( waiting_inline_script ) { cmplz_run_script( waiting_inline_script, category, service, 'inline', sourceObj ); } } const cmplzLazyLoader = () => { // Get all elements with the "lazy-load" class const cmplzLazyLoadElements = document.querySelectorAll( '.cmplz-blocked-content-container' ); // Create an Intersection Observer instance const cmplzObserver = new IntersectionObserver( ( entries, observer ) => { entries.forEach( ( entry ) => { if ( entry.isIntersecting ) { // When the element is in view, load the background image const element = entry.target; const src = element.getAttribute( 'data-placeholder-image' ); if ( src ) { const index = element.getAttribute( 'data-placeholder_class_index' ); cmplz_append_css( '.cmplz-placeholder-' + index + ' {background-image: url(' + src + ') !important;}' ); cmplz_set_blocked_content_container_aspect_ratio( element, src, index ); } // Stop observing the element observer.unobserve( element ); } } ); } ); // Start observing each lazy-load element cmplzLazyLoadElements.forEach( ( element ) => { cmplzObserver.observe( element ); } ); }; /* * Set placeholder image as background on the parent div, set notice, and handle height. * * */ function cmplz_set_blocked_content_container() { //to prevent this function to twice run on an element, we add an attribute to each element that has been processed. //then skip elements with that element. document.querySelectorAll( '.cmplz-image' ).forEach( ( obj ) => { if ( obj.classList.contains( 'cmplz-processed' ) ) { return; } obj.classList.add( 'cmplz-processed' ); const service = obj.getAttribute( 'data-service' ); const category = obj.getAttribute( 'data-category' ); const blocked_image_container = obj.parentElement; blocked_image_container.classList.add( 'cmplz-blocked-content-container' ); const curIndex = blocked_image_container.getAttribute( 'data-placeholder_class_index' ); //handle browser native lazy load feature if ( obj.getAttribute( 'loading' ) === 'lazy' ) { obj.removeAttribute( 'loading' ); obj.setAttribute( 'data-deferlazy', 1 ); } if ( curIndex === null ) { cmplz_placeholder_class_index++; blocked_image_container.classList.add( 'cmplz-placeholder-' + cmplz_placeholder_class_index, 'cmplz-blocked-content-container' ); blocked_image_container.setAttribute( 'data-placeholder_class_index', cmplz_placeholder_class_index ); cmplz_insert_placeholder_text( blocked_image_container, category, service ); } } ); document.querySelectorAll( '.cmplz-placeholder-element' ).forEach( ( obj ) => { if ( obj.classList.contains( 'cmplz-processed' ) ) { return; } obj.classList.add( 'cmplz-processed' ); const service = obj.getAttribute( 'data-service' ); const category = obj.getAttribute( 'data-category' ); //we set this element as container with placeholder image let blocked_content_container; if ( obj.classList.contains( 'cmplz-iframe' ) ) { //handle browser native lazy load feature if ( obj.getAttribute( 'loading' ) === 'lazy' ) { obj.removeAttribute( 'loading' ); obj.setAttribute( 'data-deferlazy', 1 ); } blocked_content_container = obj.parentElement; } else { blocked_content_container = obj; } const curIndex = blocked_content_container.getAttribute( 'data-placeholder_class_index' ); //if the blocked content container class is already added, don't add it again if ( curIndex === null ) { cmplz_placeholder_class_index++; blocked_content_container.classList.add( 'cmplz-placeholder-' + cmplz_placeholder_class_index, 'cmplz-blocked-content-container' ); blocked_content_container.setAttribute( 'data-placeholder_class_index', cmplz_placeholder_class_index ); cmplz_insert_placeholder_text( blocked_content_container, category, service ); //handle image size for video const src = obj.getAttribute( 'data-placeholder-image' ); if ( src && typeof src !== 'undefined' && src.length ) { //move src to parent, if needed. blocked_content_container.setAttribute( 'data-placeholder-image', src ); } } } ); cmplzLazyLoader(); /* * 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. * 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 */ if ( cmplz_has_consent( 'statistics' ) ) { cmplz_enable_category( 'statistics' ); } if ( cmplz_has_consent( 'marketing' ) ) { cmplz_enable_category( 'marketing' ); } } function cmplz_insert_placeholder_text( container, category, service ) { if ( ! container.querySelector( '.cmplz-blocked-content-notice' ) ) { let placeholder_text = complianz.placeholdertext; category = category || 'marketing'; let body; if ( typeof placeholder_text !== 'undefined' ) { if ( Number( complianz.clean_cookies ) === 1 ) { //make service human readable let service_nicename = service ? service.replace( '-', ' ' ) : ''; service_nicename = service_nicename.charAt( 0 ).toUpperCase() + service_nicename.slice( 1 ); placeholder_text = placeholder_text.replace( '{service}', service_nicename ); body = cmplz_create_element( 'div', placeholder_text ); body.innerHTML = cmplz_sanitize_placeholder_html( placeholder_text ); body.classList.add( 'cmplz-blocked-content-notice' ); const btn = body.querySelector( 'button' ); btn.setAttribute( 'data-service', service ); btn.setAttribute( 'data-category', category ); btn.setAttribute( 'aria-label', complianz.aria_label.replace( '{service}', service_nicename ) ); const pageLinks = complianz.page_links[ complianz.region ]; const link = body.querySelector( '.cmplz-links a' ); if ( pageLinks && pageLinks.hasOwnProperty( 'cookie-statement' ) ) { link.setAttribute( 'href', pageLinks[ 'cookie-statement' ].url ); if ( link.innerText === '{title}' ) { link.innerText = pageLinks[ 'cookie-statement' ].title; } } else if ( link ) { link.parentElement.style.display = 'none'; } } else { const btn = cmplz_create_element( 'button', '' ); const category_nicename = complianz.categories.hasOwnProperty( category ) ? complianz.categories[ category ] : 'marketing'; btn.innerText = placeholder_text.replace( '{category}', category_nicename ); btn.classList.add( 'cmplz-blocked-content-notice', 'cmplz-accept-category', 'cmplz-accept-' + category ); //'cmplz-accept-'+category is deprecated btn.setAttribute( 'data-service', service ); btn.setAttribute( 'data-category', category ); btn.setAttribute( 'aria-label', complianz.aria_label.replace( '{category}', category ) ); body = btn; } if ( container.tagName !== 'VIDEO' ) { container.appendChild( body ); } else { container.parentElement.appendChild( body ); } } } } /* * Set the height of an image relative to the width, depending on the image widht/height aspect ratio. * * * */ function cmplz_set_blocked_content_container_aspect_ratio( container, src, placeholder_class_index ) { if ( container == null ) { return; } // Handle image size for video const img = new Image(); img.addEventListener( 'load', function() { const imgWidth = this.naturalWidth || 1; const imgHeight = this.naturalHeight; const w = container.clientWidth; const h = imgHeight * ( w / imgWidth ); const heightCSS = src.indexOf( 'placeholder.jpg' ) === -1 ? 'height:' + h + 'px;' : ''; cmplz_append_css( '.cmplz-placeholder-' + placeholder_class_index + ' {' + heightCSS + '}' ); } ); 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. * * */ let cmplzResizeTimer; window.addEventListener( 'resize', function() { clearTimeout( cmplzResizeTimer ); cmplzResizeTimer = setTimeout( cmplz_set_blocked_content_container, 500 ); }, true ); /* * we run this function also on an interval, because with ajax loaded content, the placeholders would otherwise not be handled. */ if ( Number( complianz.block_ajax_content ) === 1 ) { setInterval( function() { cmplz_set_blocked_content_container(); }, 2000 ); } /* * Enable scripts that were blocked * * */ function cmplz_enable_category( category, service ) { if ( Number( complianz.tm_categories ) === 1 && category !== '' ) { cmplz_run_tm_event( category ); } const details = {}; details.category = category; details.categories = cmplz_accepted_categories(); details.region = complianz.region; const event = new CustomEvent( 'cmplz_before_category', { detail: details } ); document.dispatchEvent( event ); service = typeof service !== 'undefined' ? service : 'do_not_match'; if ( category === '' ) { category = 'do_not_match'; } if ( category === 'functional' ) { return; } //enable cookies for integrations if ( category === 'marketing' ) { cmplz_set_integrations_cookies(); } //remove accept cookie notice overlay let selector; if ( service !== 'do_not_match' ) { selector = '.cmplz-blocked-content-notice [data-service="' + service + '"]'; } else { selector = Number( complianz.clean_cookies ) !== 1 ? '.cmplz-blocked-content-notice.cmplz-accept-' + category : '.cmplz-blocked-content-notice [data-category="' + category + '"]'; } document.querySelectorAll( selector ).forEach( ( obj ) => { const blockedElementService = obj.getAttribute( 'data-service' ); if ( obj.parentNode.classList.contains( 'cmplz-blocked-content-notice' ) ) { obj = obj.parentNode; } //only remove if the service is not explicitly denied if ( ! cmplz_is_service_denied( blockedElementService ) ) { obj.parentNode.removeChild( obj ); } } ); document.querySelectorAll( '[data-category="' + category + '"], [data-service="' + service + '"]' ).forEach( ( obj ) => { //if a category is activated, but this specific service is denied, skip. const elementService = obj.getAttribute( 'data-service' ); if ( cmplz_is_service_denied( elementService ) ) { return; } //if native class is included, it isn't blocked, so will have run already if ( obj.getAttribute( 'data-category' ) === 'functional' ) { return; } if ( obj.classList.contains( 'cmplz-activated' ) ) { return; } const tagName = obj.tagName; if ( tagName === 'LINK' ) { obj.classList.add( 'cmplz-activated' ); const src = obj.getAttribute( 'data-href' ); cmplz_load_css( src, category ); } else if ( tagName === 'IMG' ) { obj.classList.add( 'cmplz-activated' ); const src = obj.getAttribute( 'data-src-cmplz' ); obj.setAttribute( 'src', src ); //handle browser native lazy load feature if ( obj.getAttribute( 'data-deferlazy' ) ) { obj.setAttribute( 'loading', 'lazy' ); } cmplz_remove_placeholder( obj ); } else if ( tagName === 'IFRAME' ) { obj.classList.add( 'cmplz-activated' ); let src = obj.getAttribute( 'data-src-cmplz' ); const srcAttribute = obj.getAttribute( 'data-cmplz-target' ) ? obj.getAttribute( 'data-cmplz-target' ) : 'src'; //check if there's an autoplay value we need to pass on, if it's added later on by javascript const autoplay = cmplz_get_url_parameter( obj.getAttribute( srcAttribute ), 'autoplay' ); if ( autoplay === '1' ) { src = src + '&autoplay=1'; } //handle browser native lazy load feature if ( obj.getAttribute( 'data-deferlazy' ) ) { obj.setAttribute( 'loading', 'lazy' ); } obj.addEventListener( 'load', () => { cmplz_remove_placeholder( obj ); } ); obj.setAttribute( srcAttribute, src ); } else if ( obj.classList.contains( 'cmplz-placeholder-element' ) ) { obj.classList.add( 'cmplz-activated' ); //other services, no iframe, with placeholders //remove the added classes const cssIndex = obj.getAttribute( 'data-placeholder_class_index' ); obj.classList.remove( 'cmplz-blocked-content-container', 'cmplz-placeholder-' + cssIndex ); } } ); /* * Let's activate the scripts */ //create list of waiting scripts const scriptElements = document.querySelectorAll( 'script[data-category="' + category + '"], script[data-service="' + service + '"]' ); scriptElements.forEach( ( obj ) => { const waitfor = obj.getAttribute( 'data-waitfor' ); const src = obj.getAttribute( 'data-cmplz-src' ); if ( waitfor ) { if ( src ) { cmplz_waiting_scripts[ waitfor ] = src; } else if ( obj.innerText.length > 0 ) { cmplz_waiting_inline_scripts[ waitfor ] = obj; } } //cleanup after adding it to our waiting or scriptElements list. if ( obj.parentElement ) { obj.parentElement.removeChild( obj ); } } ); //scripts: remove text/plain, and move data-src attribute to src attribute scriptElements.forEach( ( obj ) => { //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 const script_mime_type = obj.getAttribute( 'type' ); if ( obj.classList.contains( 'cmplz-activated' ) || ( ! script_mime_type || script_mime_type === 'text/javascript' ) ) { return; } obj.classList.add( 'cmplz-activated' ); const src = obj.getAttribute( 'data-cmplz-src' ); if ( src ) { obj.removeAttribute( 'type' ); //check if this src or txt is in a waiting script. If so, skip. if ( cmplz_is_waiting_script( cmplz_waiting_scripts, src ) ) { return; } if ( obj.getAttribute( 'data-post_scribe_id' ) ) { const psID = '#' + obj.getAttribute( 'data-post_scribe_id' ); const postScribeObj = document.querySelector( psID ); if ( postScribeObj ) { postScribeObj.innerHtml( '' ); postscribe( psID, '' ); } } else { cmplz_run_script( src, category, service, 'src', obj ); } } else if ( obj.innerText.length > 0 ) { //check if this src or txt is in a waiting script. If so, skip. if ( cmplz_is_waiting_script( cmplz_waiting_inline_scripts, obj.innerText ) ) { return; } cmplz_run_script( obj.innerText, category, service, 'inline', obj ); } } ); // if there are no blockable scripts at all, we still want to provide a hook // in most cases, there are blocked scripts, and run_after_all_scripts hook won't be fired yet. In that // case only the category event is fired (if activated), and this function will run // again from the script activation callbacks. cmplz_run_after_all_scripts( category, service ); } /* * remove added classes from the blocked content container * * @param obj */ function cmplz_remove_placeholder( obj ) { const blocked_content_container = obj.closest( '.cmplz-blocked-content-container' ); if ( blocked_content_container ) { const cssIndex = blocked_content_container.getAttribute( 'data-placeholder_class_index' ); blocked_content_container.classList.remove( 'cmplz-blocked-content-container', 'cmplz-placeholder-' + cssIndex ); } obj.classList.remove( 'cmplz-iframe-styles', 'cmplz-iframe', 'video-wrap' ); } /* * check if the passed source has a waiting script that should be executed, and return it if so. * @param waiting_scripts * @param src * @returns {*} */ function cmplz_get_waiting_script( waiting_scripts, src ) { for ( const waitfor in waiting_scripts ) { if ( waiting_scripts.hasOwnProperty( waitfor ) ) { if ( src.indexOf( waitfor ) !== -1 ) { const output = waiting_scripts[ waitfor ]; delete waiting_scripts[ 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 cmplz_array_is_empty( arr ) { for ( const 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 waiting_scripts * @param srcOrScript */ function cmplz_is_waiting_script( waiting_scripts, srcOrScript ) { for ( const waitfor in waiting_scripts ) { if ( waiting_scripts.hasOwnProperty( waitfor ) ) { let waitingScript = waiting_scripts[ waitfor ]; if ( typeof waitingScript !== 'string' ) { waitingScript = waitingScript.innerText; } if ( srcOrScript.indexOf( waitingScript ) !== -1 || waitingScript.indexOf( srcOrScript ) !== -1 ) { return true; } } } return false; } /* * if all scripts have been executed, fire a hook. */ function cmplz_run_after_all_scripts( category, service ) { //fire an event so custom scripts can hook into this. const enableService = service !== 'do_not_match' && ! cmplz_in_array( service, cmplz_fired_service_events ); const enableCategory = category !== 'do_not_match' && ! cmplz_in_array( category, cmplz_fired_category_events ); if ( enableCategory || enableService ) { if ( enableCategory ) { cmplz_fired_category_events.push( category ); } if ( enableService ) { cmplz_fired_service_events.push( service ); } const details = {}; details.category = category; details.service = service; details.categories = cmplz_accepted_categories(); details.services = cmplz_get_all_service_consents(); details.region = complianz.region; const event = new CustomEvent( 'cmplz_enable_category', { detail: details } ); document.dispatchEvent( event ); } if ( ! cmplz_all_scripts_hook_fired && cmplz_array_is_empty( cmplz_waiting_inline_scripts ) && cmplz_array_is_empty( cmplz_waiting_scripts ) ) { const event = new CustomEvent( 'cmplz_run_after_all_scripts', { detail: category, service } ); document.dispatchEvent( event ); cmplz_all_scripts_hook_fired = true; } } /* * Fire an event in Tag Manager * * * */ const cmplz_fired_events = []; function cmplz_run_tm_event( category ) { if ( cmplz_fired_events.indexOf( category ) === -1 ) { cmplz_fired_events.push( category ); window.dataLayer = window.dataLayer || []; window.dataLayer.push( { event: 'cmplz_event_' + category, } ); const event = new CustomEvent( 'cmplz_tag_manager_event', { detail: category } ); document.dispatchEvent( event ); } } /* * Accept all categories */ window.cmplz_accept_all = function() { cmplz_clear_all_service_consents(); cmplz_fire_before_categories_consent( cmplz_categories ); for ( const key in cmplz_categories ) { if ( cmplz_categories.hasOwnProperty( key ) ) { cmplz_set_consent( cmplz_categories[ key ], 'allow' ); } } cmplz_sync_category_checkboxes(); }; function cmplz_fire_before_categories_consent( categories ) { const details = {}; details.categories = categories; details.region = complianz.region; const event = new CustomEvent( 'cmplz_before_categories_consent', { detail: details } ); document.dispatchEvent( event ); } /* * Deny all categories, and reload if needed. */ window.cmplz_deny_all = function() { for ( const key in cmplz_categories ) { if ( cmplz_categories.hasOwnProperty( key ) ) { cmplz_set_consent( cmplz_categories[ key ], 'deny' ); } } const consentLevel = cmplz_highest_accepted_category(); let reload = false; if ( consentLevel !== 'functional' || cmplz_exists_service_consent() ) { reload = true; } if ( cmplz_clear_cookies( 'cmplz_service' ) ) { reload = true; } //has to be after the check if should be reloaded, otherwise that check won't work. cmplz_clear_all_service_consents(); cmplz_integrations_revoke(); cmplz_fire_categories_event(); cmplz_track_status(); const event = new CustomEvent( 'cmplz_revoke', { detail: reload } ); document.dispatchEvent( event ); //we need to let the iab extension handle the reload, otherwise the consent revoke might not be ready yet. if ( ! complianz.tcf_active && reload ) { cmplz_reload_browser_compatible(); } }; /* * If current cookie policy has changed, reset cookie consent * * */ function cmplz_check_cookie_policy_id() { const user_policy_id = cmplz_get_cookie( 'policy_id' ); if ( user_policy_id && ( parseInt( complianz.current_policy_id ) !== parseInt( user_policy_id ) ) ) { cmplz_deny_all(); cmplz_set_banner_status( 'show' ); cmplz_clear_cookies( 'cmplz' ); } } window.conditionally_show_banner = function() { //merge userdata with complianz data, in case a b testing is used with user specific cookie banner data //objects are merged so user_data will override data in complianz object complianz = cmplz_merge_object( complianz, cmplz_user_data ); //check if we need to redirect to another legal document, for a specific region cmplz_maybe_auto_redirect(); cmplz_set_blocked_content_container(); /* * Integration with WordPress, tell what kind of consent type we're using, then fire an event */ window.wp_consent_type = complianz.consenttype; let event = new CustomEvent( 'wp_consent_type_defined' ); document.dispatchEvent( event ); event = new CustomEvent( 'cmplz_before_cookiebanner' ); document.dispatchEvent( event ); if ( Number( complianz.forceEnableStats ) === 1 && complianz.consenttype === 'optin' ) { cmplz_set_consent( 'statistics', 'allow' ); } const rev_cats = cmplz_categories.reverse(); const consented_categories = []; for ( const key in rev_cats ) { if ( rev_cats.hasOwnProperty( key ) ) { const category = cmplz_categories[ key ]; if ( cmplz_has_consent( category ) ) { consented_categories.push( category ); } } } cmplz_fire_before_categories_consent( consented_categories ); for ( const key in consented_categories ) { if ( rev_cats.hasOwnProperty( key ) ) { const category = consented_categories[ key ]; cmplz_enable_category( category ); } } if ( cmplz_exists_service_consent() ) { //if any service is enabled, allow the general services also, because some services are partially 'general' cmplz_enable_category( '', 'general' ); const services = cmplz_get_services_on_page(); for ( const key in services ) { if ( services.hasOwnProperty( key ) ) { const service = services[ key ].service; const category = services[ key ].category; if ( cmplz_has_service_consent( service, category ) ) { document.querySelectorAll( '.cmplz-accept-service[data-service="' + service + '"]' ).forEach( ( obj ) => { obj.checked = true; } ); cmplz_enable_category( '', service ); } } } } cmplz_sync_category_checkboxes(); cmplz_integrations_init(); cmplz_check_cookie_policy_id(); cmplz_set_up_auto_dismiss(); //if we're on the cookie policy page, we dynamically load the applicable revoke checkbox cmplz_load_manage_consent_container(); event = new CustomEvent( 'cmplz_cookie_banner_data', { detail: complianz } ); document.dispatchEvent( event ); //if no categories were saved before, we do it now if ( cmplz_get_cookie( 'saved_categories' ) === '' ) { //for Non optin/optout visitors, and DNT users, we just track the no-warning option if ( complianz.consenttype !== 'optin' && complianz.consenttype !== 'optout' ) { cmplz_track_status(); } else if ( cmplz_do_not_track() ) { cmplz_track_status( 'do_not_track' ); } } cmplz_set_category_as_body_class(); //fire cats event, but do not fire a track, as we do this on exit. cmplz_fire_categories_event(); if ( ! cmplz_do_not_track() ) { if ( complianz.consenttype === 'optin' ) { if ( complianz.forceEnableStats ) { cmplz_enable_category( 'statistics' ); } cmplz_log( 'opt-in' ); show_cookie_banner(); } else if ( complianz.consenttype === 'optout' ) { cmplz_log( 'opt-out' ); show_cookie_banner(); } else { cmplz_log( 'other consent type, no cookie warning' ); //on other consent types, all scripts are enabled by default. cmplz_accept_all(); } } else { cmplz_log( 'global privacy control or do not track detected: no banner.' ); cmplz_track_status( 'do_not_track' ); } }; /** * Check if User has set either GPC or DNT in the browser. * @return {boolean} True if do not track is enabled and GPC or DNT is set. */ function cmplz_do_not_track() { const dnt = 'doNotTrack' in navigator && navigator.doNotTrack === '1'; const gpc = 'globalPrivacyControl' in navigator && navigator.globalPrivacyControl; return !! ( complianz.do_not_track_enabled && ( gpc || dnt ) ); } /* * Get list of services active on the page * @returns {*[]} */ function cmplz_get_services_on_page() { const services = []; document.querySelectorAll( '[data-service]' ).forEach( ( obj ) => { const service = obj.getAttribute( 'data-service' ); const category = obj.getAttribute( 'data-category' ); if ( services.indexOf( service ) === -1 ) { services.push( { category, service, } ); } } ); return services; } /* * Run the actual cookie warning * * */ window.show_cookie_banner = function() { let disableCookiebanner = complianz.disable_cookiebanner || cmplz_is_speedbot(); //do not show banner when manage consent area on cookie policy is visible //when users use only the shortcode, the manage consent container is not active, but the dropdown cookie policy class is. //when the complianz shortcode is used, the dropdown cookie policy class is loaded late because it's loaded with javascript. let tmpDismissCookiebanner = false; if ( document.querySelector( '#cmplz-manage-consent-container' ) || document.querySelector( '.cmplz-dropdown-cookiepolicy' ) ) { tmpDismissCookiebanner = true; } const container = document.getElementById( 'cmplz-cookiebanner-container' ); if ( container ) { document.body.prepend( container ); } const pageLinks = complianz.page_links[ complianz.region ]; //get correct banner, based on banner_id cmplz_banner = document.querySelector( '.cmplz-cookiebanner.banner-' + complianz.user_banner_id + '.' + complianz.consenttype ); if ( ! cmplz_banner ) { disableCookiebanner = true; } cmplz_manage_consent_button = document.querySelector( '#cmplz-manage-consent .cmplz-manage-consent.manage-consent-' + complianz.user_banner_id ); // Reveal the banner once its stylesheet is applied. Idempotent: removing an // already-removed class is a no-op, so calling this more than once is safe. const revealBanner = function() { if ( disableCookiebanner ) { return; } cmplz_banner.classList.remove( 'cmplz-hidden' ); cmplz_manage_consent_button.classList.remove( 'cmplz-hidden' ); // Activate focus trap only if banner is currently shown (not already dismissed) if ( cmplz_get_banner_status() === 'show' ) { cmplz_trap_focus(); // Set focus to the close button when banner is shown const closeButton = cmplz_banner.querySelector( '.cmplz-close' ); if ( closeButton ) { closeButton.focus(); } } }; // Guarantee the banner stylesheet is present and enabled, then reveal. // In the deterministic case the sheet was enqueued server-side and is // already applied, so we reveal immediately (no FOUC). Otherwise the sheet // is injected here and we reveal on load, with a timeout safety net for the // race where the sheet finished loading before the listener attached. const bannerLink = cmplzEnsureBannerCss(); if ( ! disableCookiebanner ) { if ( bannerLink && bannerLink.sheet ) { revealBanner(); } else if ( bannerLink ) { bannerLink.addEventListener( 'load', revealBanner ); setTimeout( revealBanner, 500 ); } else { revealBanner(); } } if ( cmplz_banner && ! disableCookiebanner ) { cmplz_banner.querySelectorAll( '.cmplz-links a:not(.cmplz-external), .cmplz-buttons a:not(.cmplz-external)' ).forEach( ( obj ) => { const docElement = obj; docElement.classList.add( 'cmplz-hidden' ); for ( const pageType in pageLinks ) { if ( pageLinks.hasOwnProperty( pageType ) && docElement.classList.contains( pageType ) ) { docElement.setAttribute( 'href', pageLinks[ pageType ].url + docElement.getAttribute( 'data-relative_url' ) ); if ( docElement.innerText === '{title}' ) { docElement.innerText = cmplz_html_decode( pageLinks[ pageType ].title ); } docElement.classList.remove( 'cmplz-hidden' ); } } } ); cmplz_set_banner_status(); //we don't use the setBannerStatus function here, as we don't want to save it in a cookie now. if ( tmpDismissCookiebanner ) { cmplz_banner.classList.remove( 'cmplz-show' ); cmplz_banner.classList.add( 'cmplz-dismissed' ); cmplz_manage_consent_button.classList.remove( 'cmplz-dismissed' ); cmplz_manage_consent_button.classList.add( 'cmplz-show' ); } } const event = new CustomEvent( 'cmplz_cookie_warning_loaded', { detail: complianz.region } ); document.dispatchEvent( event ); }; /* * Guarantee the banner stylesheet for the current variant is present in the DOM * and enabled. Idempotent — safe to call on first load and after every * client-side (Interactivity API) navigation. * * From WP 6.9 the iAPI router disables any stylesheet absent from the fetched * server HTML by setting CSSStyleSheet.disabled = true (it never removes the * element). When the sheet was enqueued server-side (deterministic single * variant) it survives by design; if the router disabled it we re-enable it * synchronously — zero network, zero flash. When the sheet was injected by JS * (A/B or multiple consent types) we re-enable it, or inject it if missing. * * @returns {HTMLLinkElement|null} the banner , or null if none resolved. */ function cmplzEnsureBannerCss() { //server-enqueued sheet carries the WordPress style handle id. //Invariant: enqueue_banner_css() only enqueues server-side in the deterministic //case (no A/B testing), where user_banner_id resolves to the default banner id //it enqueued under — so this id matches. Under A/B testing the variant differs //per user, nothing is enqueued server-side, and we fall through to the injected/ //inject paths below instead. const handleId = 'cmplz-banner-' + complianz.user_banner_id + '-' + complianz.consenttype + '-css'; const enqueued = document.getElementById( handleId ); if ( enqueued && enqueued.rel === 'stylesheet' ) { if ( enqueued.sheet && enqueued.sheet.disabled ) { enqueued.sheet.disabled = false; } return enqueued; } const css_file_url = complianz.css_file.replace( '{type}', complianz.consenttype ).replace( '{banner_id}', complianz.user_banner_id ); if ( complianz.css_file.indexOf( 'cookiebanner/css/defaults/banner' ) !== -1 ) { cmplz_log( 'Fallback default css file used. Please re-save banner settings, or check file writing permissions in uploads directory' ); } //match an already-injected by filename, ignoring cache-busting query strings const filename = css_file_url.split( '?' )[ 0 ].split( '/' ).pop(); let injected = null; document.querySelectorAll( 'link[rel="stylesheet"]' ).forEach( function( el ) { if ( el.href.split( '?' )[ 0 ].split( '/' ).pop() === filename ) { injected = el; } } ); if ( injected ) { if ( injected.sheet && injected.sheet.disabled ) { injected.sheet.disabled = false; } return injected; } //nothing present yet — inject it (multi-variant first load, or default-CSS fallback) const link = document.createElement( 'link' ); link.href = css_file_url; link.type = 'text/css'; link.rel = 'stylesheet'; document.getElementsByTagName( 'head' )[ 0 ].appendChild( link ); return link; } /* * Re-sync consent state and de-duplicate banner instances after a client-side * navigation. The banner is rendered once in the footer (outside any router * region) so it normally persists untouched; this is a safety pass in case a * theme/plugin wraps it in a router region, which would duplicate it with the * cache-default markup on swap. */ function cmplzSyncConsentState() { const banners = document.querySelectorAll( '.cmplz-cookiebanner' ); //drop copies brought in inside a router region; the footer original persists if ( banners.length > 1 ) { banners.forEach( function( banner ) { if ( banner.closest( '[data-wp-router-region]' ) ) { banner.remove(); } } ); } //re-apply visibility from the stored consent status const dismissed = cmplz_get_banner_status() === 'dismissed'; document.querySelectorAll( '.cmplz-cookiebanner' ).forEach( function( banner ) { banner.classList.toggle( 'cmplz-show', ! dismissed ); banner.classList.toggle( 'cmplz-dismissed', dismissed ); } ); //remove a manage-consent button duplicated inside a region, but only when an //out-of-region original survives. Mirrors the banner guard above: if a theme //wraps the whole page (footer included) in a single router region, the only //copy lives inside it — removing it unconditionally would delete the manage- //consent button with no replacement. const manageBtns = document.querySelectorAll( '#cmplz-manage-consent' ); const hasOriginal = Array.prototype.some.call( manageBtns, function( btn ) { return ! btn.closest( '[data-wp-router-region]' ); } ); if ( hasOriginal ) { manageBtns.forEach( function( btn ) { if ( btn.closest( '[data-wp-router-region]' ) ) { btn.remove(); } } ); } } /* * Arm the client-side navigation hook. On WP 7.0+ the companion script module * (complianz-router.js) drives navigation via the official watch()+state.url * API and notifies us with a DOM event. On WP 6.9 we fall back to a History API * patch, scoped to pages that actually have an iAPI router region. Handlers are * idempotent, so duplicate/extra ticks are harmless. */ function cmplzInitNavigationHook() { if ( ! document.querySelector( '[data-wp-router-region]' ) ) { return; //no iAPI navigation on this page } const onNavigate = function() { cmplzEnsureBannerCss(); cmplzSyncConsentState(); }; if ( complianz.iapi_nav === 'module' ) { //WP 7.0+: the companion module drives navigation via watch() document.addEventListener( 'cmplz_router_navigated', onNavigate ); return; } //WP 6.9 fallback: patch the History API + popstate. //Defer onNavigate so it never runs synchronously inside the iAPI router's //pushState call — a synchronous DOM mutation there triggers the iAPI //MutationObserver, which re-evaluates directives that access private stores //and throws "Cannot unlock a private store with an invalid lock code". const onNavigateDeferred = function() { requestAnimationFrame( function() { onNavigate(); setTimeout( onNavigate, 150 ); } ); }; [ 'pushState', 'replaceState' ].forEach( function( method ) { const original = history[ method ]; history[ method ] = function() { const result = original.apply( this, arguments ); onNavigateDeferred(); return result; }; } ); window.addEventListener( 'popstate', onNavigateDeferred ); } /* * Get the status of the banner: dismissed | show * @returns {string} */ window.cmplz_get_banner_status = function() { return cmplz_get_cookie( 'banner-status' ); }; /* * Set the banner status so it will be either shown or dismissed, and store it in a cookie. * @param status (optional) */ window.cmplz_set_banner_status = function( status ) { let prevStatus = cmplz_get_cookie( 'banner-status' ); status = typeof status !== 'undefined' ? status : prevStatus; if ( status !== prevStatus ) { cmplz_set_cookie( 'banner-status', status ); } if ( status.length === 0 ) { status = 'show'; } if ( status === 'show' ) { prevStatus = 'dismissed'; } else { prevStatus = 'show'; } if ( cmplz_banner && status.length > 0 ) { cmplz_banner.classList.remove( 'cmplz-' + prevStatus ); cmplz_banner.classList.add( 'cmplz-' + status ); if ( cmplz_manage_consent_button ) { cmplz_manage_consent_button.classList.add( 'cmplz-' + prevStatus ); cmplz_manage_consent_button.classList.remove( 'cmplz-' + status ); } } if ( cmplz_banner_container && complianz.soft_cookiewall ) { cmplz_banner_container.classList.remove( 'cmplz-' + prevStatus ); cmplz_banner_container.classList.add( 'cmplz-' + status, 'cmplz-soft-cookiewall' ); } const event = new CustomEvent( 'cmplz_banner_status', { detail: status } ); document.dispatchEvent( event ); cmplz_start_clean(); if ( status === 'show' ) { // Activate focus trap only if soft cookie wall is enabled cmplz_trap_focus(); // Set focus to the close button when banner is shown const closeButton = cmplz_banner.querySelector( '.cmplz-close' ); if ( closeButton ) { closeButton.focus(); } } else { // Release focus trap when banner is dismissed cmplz_release_focus_trap(); } }; /* * Check if current visitor is a bot * * @returns {boolean} */ function cmplz_is_bot() { const 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)'; const reBot = new RegExp( botPattern, 'i' ); const userAgent = navigator.userAgent; return reBot.test( userAgent ); } /* * Check if current visitor is a speedbot * * @returns {boolean} */ function cmplz_is_speedbot() { const userAgent = navigator.userAgent; const speedBotPattern = '(GTmetrix|pingdom|pingbot|Lighthouse)'; const speedBot = new RegExp( speedBotPattern, 'i' ); return speedBot.test( userAgent ); } /* * Check if there is consent for a category or service * @param category * @returns {boolean} */ window.cmplz_has_consent = function( category ) { if ( cmplz_is_bot() ) { return true; } if ( category === 'functional' ) { return true; } let has_consent, value; //if DNT is detected, we should only return the actual cookie value, and not look at the consenttype if ( cmplz_do_not_track() ) { value = cmplz_get_cookie( category ); has_consent = ( value === 'allow' ); return has_consent; } /* * categories */ value = cmplz_get_cookie( category ); if ( ( complianz.consenttype === 'optout' || complianz.consenttype === 'other' ) && value === '' ) { //if it's opt out and no cookie is set we should return true has_consent = true; } else { //all other situations, return only true if value is allow has_consent = ( value === 'allow' ); } return has_consent; }; /* * Check if a service has consent * @param service * @returns {boolean|*} */ window.cmplz_is_service_denied = function( service ) { //Check if it's in the consented services cookie const consented_services_json = cmplz_get_cookie( 'consented_services' ); let consented_services; try { consented_services = JSON.parse( consented_services_json ); } catch ( e ) { consented_services = {}; } if ( ! consented_services.hasOwnProperty( service ) ) { return false; } return ! consented_services[ service ]; }; /* * Check if a service has consent * @param service * @param category * @returns {boolean|*} */ window.cmplz_has_service_consent = function( service, category ) { //Check if it's in the consented services cookie const consented_services_json = cmplz_get_cookie( 'consented_services' ); let consented_services; try { consented_services = JSON.parse( consented_services_json ); } catch ( e ) { consented_services = {}; } if ( ! consented_services.hasOwnProperty( service ) ) { //default to the category return cmplz_has_consent( category ); } return consented_services[ service ]; }; /* * check if there's at least one service with consent * @returns {boolean} */ function cmplz_exists_service_consent() { const consented_services_json = cmplz_get_cookie( 'consented_services' ); let consented_services; try { consented_services = JSON.parse( consented_services_json ); for ( const key in consented_services ) { if ( consented_services.hasOwnProperty( key ) ) { if ( consented_services[ key ] === true ) { return true; } } } } catch ( e ) { return false; } return false; } /* * Set consent for a service * @param service * @param consented */ function cmplz_set_service_consent( service, consented ) { const consented_services_json = cmplz_get_cookie( 'consented_services' ); let consented_services; try { consented_services = JSON.parse( consented_services_json ); } catch ( e ) { consented_services = {}; } consented_services[ service ] = consented; cmplz_set_cookie( 'consented_services', JSON.stringify( consented_services ) ); const details = {}; details.service = service; details.value = consented; details.region = complianz.region; //when the status is changed, we may need to fire scripts again, so we reset it. cmplz_all_scripts_hook_fired = false; const event = new CustomEvent( 'cmplz_status_change_service', { detail: details } ); document.dispatchEvent( event ); } /* * Remove all service consents */ function cmplz_clear_all_service_consents() { cmplz_set_cookie( 'consented_services', '' ); } /* * Get all consented or denied services */ function cmplz_get_all_service_consents() { const consented_services_json = cmplz_get_cookie( 'consented_services' ); let consented_services; try { consented_services = JSON.parse( consented_services_json ); } catch ( e ) { consented_services = {}; } return consented_services; } /* * Get cookie path * @returns {*} */ function cmplz_get_cookie_path() { return typeof complianz.cookie_path !== 'undefined' && complianz.cookie_path !== '' ? complianz.cookie_path : '/'; } /* * retrieve domain to set the cookies on * @returns {string} */ function cmplz_get_cookie_domain() { if ( Number( complianz.set_cookies_on_root ) === 1 && complianz.cookie_domain.length > 3 && ! complianz.cookie_domain.includes( 'localhost' ) ) { return complianz.cookie_domain; } return ''; } /* * Set consent for a category * @param category * @param value */ window.cmplz_set_consent = function( category, value ) { cmplz_set_accepted_cookie_policy_id(); //functional is always allow value = category === 'functional' ? 'allow' : value; const previous_value = cmplz_get_cookie( category ); //keep checkboxes in banner and on cookie policy in sync //do this before the change check to ensure sync: https://github.com/Really-Simple-Plugins/complianz-gdpr/issues/324 const checked = value === 'allow'; document.querySelectorAll( 'input.cmplz-' + category ).forEach( ( obj ) => { obj.checked = checked; } ); //do not trigger a change event if nothing has changed. if ( previous_value === value ) { return; } cmplz_set_cookie( category, value ); if ( value === 'allow' ) { cmplz_enable_category( category ); } cmplz_wp_set_consent( category, value ); if ( category === 'statistics' ) { cmplz_wp_set_consent( 'statistics-anonymous', 'allow' ); } const details = new Object(); details.category = category; details.value = value; details.region = complianz.region; details.categories = cmplz_accepted_categories(); //when the status is changed, we may need to fire scripts again, so we reset it. cmplz_all_scripts_hook_fired = false; const event = new CustomEvent( 'cmplz_status_change', { detail: details } ); document.dispatchEvent( event ); if ( category === 'marketing' && value === 'deny' && previous_value === 'allow' ) { cmplz_integrations_revoke(); //give the code some time to finish, so our track status code can send a signal to the backend. setTimeout( function() { cmplz_reload_browser_compatible(); }, 500 ); } }; /* * In some browsers, like firefox, the reload does not force reload, but keeps cached data, causing e.g. Google Maps to load anyway. */ function cmplz_reload_browser_compatible() { if ( navigator.userAgent.toLowerCase().indexOf( 'firefox' ) > -1 ) { const url = new URL( window.location.href ); url.searchParams.set( 'cmplz-force-reload', Date.now().toString() ); window.location.href = url.toString(); } else { window.location.reload(); } } /* * We use ajax to check the consenttype based on region, otherwise caching could prevent the user specific warning * * */ let cmplz_user_data = []; //check if it's already stored if ( typeof ( Storage ) !== 'undefined' && sessionStorage.cmplz_user_data ) { cmplz_user_data = JSON.parse( sessionStorage.cmplz_user_data ); } //if not stored yet, load. As features in the user object can be changed on updates, we also check for the version if ( Number( complianz.geoip ) === 1 && ( cmplz_user_data.length === 0 || ( cmplz_user_data.version !== complianz.version ) || ( cmplz_user_data.banner_version !== complianz.banner_version ) ) ) { const request = new XMLHttpRequest(); let cmplzUserRegion = cmplz_get_url_parameter( window.location.href, 'cmplz_user_region' ); cmplzUserRegion = cmplzUserRegion ? '&cmplz_user_region=' + cmplzUserRegion : ''; request.open( 'GET', complianz.url + 'banner?' + complianz.locale + cmplzUserRegion, true ); request.setRequestHeader( 'Content-type', 'application/json' ); request.send(); request.onload = function() { cmplz_user_data = JSON.parse( request.response ); sessionStorage.cmplz_user_data = JSON.stringify( cmplz_user_data ); conditionally_show_banner(); }; } else { conditionally_show_banner(); } //keep the banner styled + consistent across Interactivity API client-side navigation cmplzInitNavigationHook(); /* * when ab testing, or using records of consent, we want to keep track of the unique user id */ if ( Number( complianz.store_consent ) === 1 ) { const cmplz_id_cookie = cmplz_get_cookie( 'id' ); let cmplz_id_session = ''; let cmplz_id = ''; if ( typeof ( Storage ) !== 'undefined' && sessionStorage.cmplz_id ) { cmplz_id_session = JSON.parse( sessionStorage.cmplz_id ); } if ( cmplz_id_cookie.length === 0 && cmplz_id_session.length > 0 ) { cmplz_id = cmplz_id_session; cmplz_set_cookie( 'id', cmplz_id ); } if ( cmplz_id_cookie.length > 0 && cmplz_id_session.length === 0 ) { cmplz_id = cmplz_id_cookie; } if ( typeof ( Storage ) !== 'undefined' ) { sessionStorage.cmplz_id = JSON.stringify( cmplz_id ); } } // visibilitychange and pagehide work in more browsers hence we check if they are supported and try to use them document.addEventListener( 'visibilitychange', function() { if ( document.visibilityState === 'hidden' ) { cmplz_track_status_end(); } } ); window.addEventListener( 'pagehide', cmplz_track_status_end, false ); window.addEventListener( 'beforeunload', cmplz_track_status_end, false ); function cmplz_track_status_end() { if ( ! cmplz_consent_stored_once ) { cmplz_track_status(); } } /* * This creates an API which devs can use to trigger actions in complianz. */ document.addEventListener( 'cmplz_consent_action', function( e ) { cmplz_set_consent( e.detail.category, 'allow' ); cmplz_fire_categories_event(); cmplz_track_status(); } ); /* * For both opt-in and opt-out, clicking cmplz-accept should result in accepting all categories */ cmplz_add_event( 'click', '.cmplz-accept', function( e ) { e.preventDefault(); setTimeout( () => { cmplz_accept_all(); cmplz_set_banner_status( 'dismissed' ); cmplz_fire_categories_event(); cmplz_track_status(); }, 0 ); } ); /* * Accept marketing cookies by clicking any other link cookie acceptance from a custom link */ //cmplz-accept-marketing is deprecated cmplz_add_event( 'click', '.cmplz-accept-category, .cmplz-accept-marketing', function( e ) { e.preventDefault(); const obj = e.target; const service = obj.getAttribute( 'data-service' ); let category = obj.getAttribute( 'data-category' ); category = category ? category : 'marketing'; if ( Number( complianz.clean_cookies ) === 1 && typeof service !== 'undefined' && service ) { cmplz_set_service_consent( service, true ); cmplz_enable_category( '', 'general' ); cmplz_enable_category( '', service ); } else { //we're activating a category, so do not need service activation here. // cmplz_enable_category('', 'general'); cmplz_set_consent( category, 'allow' ); } cmplz_set_banner_status( 'dismissed' ); cmplz_fire_categories_event(); cmplz_track_status(); } ); /* * Accept a specific service */ cmplz_add_event( 'click', '.cmplz-accept-service', function( e ) { const obj = e.target; //INPUT should be handled by change event, these are checkboxes on the cookie policy const tagName = obj.tagName; if ( tagName === 'INPUT' ) { return; } const service = obj.getAttribute( 'data-service' ); if ( typeof service !== 'undefined' ) { cmplz_set_service_consent( service, true ); cmplz_enable_category( '', 'general' ); cmplz_enable_category( '', service ); } cmplz_fire_categories_event(); cmplz_track_status(); } ); /* * Accept a specific service */ cmplz_add_event( 'change', '.cmplz-accept-service', function( e ) { const obj = e.target; const tagName = obj.tagName; const service = obj.getAttribute( 'data-service' ); if ( typeof service !== 'undefined' ) { //inputs are from the consent per service option on the cookie policy. if ( tagName === 'INPUT' ) { cmplz_set_banner_status( 'dismissed' ); if ( obj.checked ) { cmplz_set_service_consent( service, true ); cmplz_enable_category( '', service ); } else { cmplz_set_service_consent( service, false ); //give our track status time to finish setTimeout( function() { cmplz_reload_browser_compatible(); }, 500 ); } //if not input, it's a placeholder } else { e.preventDefault(); cmplz_set_service_consent( service, true ); cmplz_enable_category( '', 'general' ); cmplz_enable_category( '', service ); //give our track status time to finish setTimeout( function() { cmplz_reload_browser_compatible(); }, 500 ); } } cmplz_fire_categories_event(); cmplz_track_status(); } ); /* * On the banner, clicking a category should fire the category only after the save button is clicked. * */ cmplz_add_event( 'click', '.cmplz-save-preferences', function( e ) { const obj = e.target; cmplz_banner = obj.closest( '.cmplz-cookiebanner' ); const consented_categories = []; for ( const key in cmplz_categories ) { if ( cmplz_categories.hasOwnProperty( key ) ) { const category = cmplz_categories[ key ]; const categoryElement = cmplz_banner.querySelector( 'input.cmplz-' + category ); if ( categoryElement && categoryElement.checked ) { consented_categories.push( category ); } } } cmplz_fire_before_categories_consent( consented_categories ); for ( const key in cmplz_categories ) { if ( cmplz_categories.hasOwnProperty( key ) ) { const category = cmplz_categories[ key ]; if ( consented_categories.includes( category ) ) { cmplz_set_consent( category, 'allow' ); } else { cmplz_set_consent( category, 'deny' ); } } } cmplz_set_banner_status( 'dismissed' ); cmplz_fire_categories_event(); cmplz_track_status(); } ); cmplz_add_event( 'click', '.cmplz-close', function() { cmplz_set_banner_status( 'dismissed' ); } ); cmplz_add_event( 'click', '.cmplz-view-preferences', function( e ) { const obj = e.target; cmplz_banner = obj.closest( '.cmplz-cookiebanner' ); if ( cmplz_banner.querySelector( '.cmplz-categories' ).classList.contains( 'cmplz-fade-in' ) ) { cmplz_banner.classList.remove( 'cmplz-categories-visible' ); cmplz_banner.querySelector( '.cmplz-categories' ).classList.remove( 'cmplz-fade-in' ); cmplz_banner.querySelector( '.cmplz-view-preferences' ).style.display = 'block'; cmplz_banner.querySelector( '.cmplz-save-preferences' ).style.display = 'none'; } else { cmplz_banner.classList.add( 'cmplz-categories-visible' ); cmplz_banner.querySelector( '.cmplz-categories' ).classList.add( 'cmplz-fade-in' ); cmplz_banner.querySelector( '.cmplz-view-preferences' ).style.display = 'none'; cmplz_banner.querySelector( '.cmplz-save-preferences' ).style.display = 'block'; // Set focus to the first category toggle when preferences are shown const firstCategory = cmplz_banner.querySelector( '.cmplz-categories .cmplz-category' ); if ( firstCategory ) { const toggleBtn = firstCategory.querySelector( '.cmplz-category-toggle' ); if ( toggleBtn ) { toggleBtn.focus(); } } } } ); /* * Toggle category description visibility via the expand/collapse button */ cmplz_add_event( 'click', '.cmplz-category-toggle', function( e ) { const btn = e.target.closest( '.cmplz-category-toggle' ); if ( ! btn ) { return; } const isExpanded = btn.getAttribute( 'aria-expanded' ) === 'true'; btn.setAttribute( 'aria-expanded', String( ! isExpanded ) ); const category = btn.closest( '.cmplz-category' ); if ( category ) { const desc = category.querySelector( '.cmplz-description' ); if ( desc ) { desc.hidden = isExpanded; } } } ); /* * On the cookie policy, clicking a category should fire the category immediately * */ cmplz_add_event( 'change', '.cmplz-manage-consent-container .cmplz-category', function() { for ( const key in cmplz_categories ) { if ( cmplz_categories.hasOwnProperty( key ) ) { const category = cmplz_categories[ key ]; const categoryElement = document.querySelector( '.cmplz-manage-consent-container input.cmplz-' + category ); if ( categoryElement ) { if ( categoryElement.checked ) { cmplz_set_consent( category, 'allow' ); } else { cmplz_set_consent( category, 'deny' ); } cmplz_set_banner_status( 'dismissed' ); cmplz_fire_categories_event(); cmplz_track_status(); } } } } ); cmplz_add_event( 'click', '.cmplz-deny', function( e ) { e.preventDefault(); cmplz_set_banner_status( 'dismissed' ); cmplz_deny_all(); } ); cmplz_add_event( 'click', 'button.cmplz-manage-settings', function( e ) { e.preventDefault(); const catsContainer = document.querySelector( '.cmplz-cookiebanner .cmplz-categories' ); const saveSettings = document.querySelector( '.cmplz-save-settings' ); const manageSettings = document.querySelector( 'button.cmplz-manage-settings' ); if ( ! cmplz_is_hidden( catsContainer ) ) { saveSettings.style.display = 'none'; manageSettings.style.display = 'block'; catsContainer.style.display = 'none'; } else { saveSettings.style.display = 'block'; manageSettings.style.display = 'none'; catsContainer.style.display = 'block'; } } ); cmplz_add_event( 'click', 'button.cmplz-manage-consent', function( e ) { e.preventDefault(); cmplz_banner_trigger_source = 'manage-consent'; cmplz_set_banner_status( 'show' ); } ); /* * Handle dismiss on scroll and dismiss on timeout */ function cmplz_set_up_auto_dismiss() { // If the banner was already dismissed on a previous visit, skip entirely. // Without this guard, the timeout/scroll handlers would call cmplz_deny_all() // on every page load, revoking consent and triggering an infinite reload loop. if ( cmplz_get_banner_status() === 'dismissed' ) { return; } // Handle dismiss on scroll – opt-out only if ( complianz.consenttype === 'optout' && Number( complianz.dismiss_on_scroll ) === 1 ) { const onWindowScroll = function() { if ( window.pageYOffset > Math.floor( 400 ) ) { window.removeEventListener( 'scroll', onWindowScroll ); this.onWindowScroll = null; // User may have explicitly accepted/denied before scrolling enough. if ( cmplz_get_banner_status() === 'dismissed' ) { return; } cmplz_set_banner_status( 'dismissed' ); cmplz_fire_categories_event(); cmplz_track_status(); } }; window.addEventListener( 'scroll', onWindowScroll ); } // Handle dismiss on timeout const delay = parseInt( complianz.dismiss_timeout ); if ( complianz.consenttype === 'optout' && delay > 0 ) { window.setTimeout( function() { // User may have explicitly accepted/denied before the timeout fired. if ( cmplz_get_banner_status() === 'dismissed' ) { return; } cmplz_set_banner_status( 'dismissed' ); cmplz_fire_categories_event(); cmplz_track_status(); }, Math.floor( delay ) ); } } /* * Fire a event wich passes all consented categories * Separated from the actual category consent because we want to bundle it in one event */ function cmplz_fire_categories_event() { const details = new Object(); details.category = cmplz_highest_accepted_category(); details.categories = cmplz_accepted_categories(); details.region = complianz.region; const event = new CustomEvent( 'cmplz_fire_categories', { detail: details } ); document.dispatchEvent( event ); } /* * Track the status of current consent * @param status */ function cmplz_track_status( status ) { let cats = []; status = typeof status !== 'undefined' ? status : false; const event = new CustomEvent( 'cmplz_track_status', { detail: status } ); document.dispatchEvent( event ); if ( ! status ) { cats = cmplz_accepted_categories(); } else { cats = [ status ]; } cmplz_set_category_as_body_class(); let saved_cats, saved_services; try { saved_cats = JSON.parse( cmplz_get_cookie( 'saved_categories' ) ); } catch ( e ) { saved_cats = {}; } try { saved_services = JSON.parse( cmplz_get_cookie( 'saved_services' ) ); } catch ( e ) { saved_services = {}; } const consented_services = cmplz_get_all_service_consents(); //compare current cats with saved cats. When there are no changes, do nothing. if ( cmplz_equals( saved_cats, cats ) && cmplz_equals( saved_services, consented_services ) ) { return; } if ( Number( complianz.store_consent ) !== 1 || cmplz_is_bot() || cmplz_is_speedbot() ) { return; } //keep track of the fact that the status was saved at least once cmplz_set_cookie( 'saved_categories', JSON.stringify( cats ) ); cmplz_set_cookie( 'saved_services', JSON.stringify( consented_services ) ); cmplz_consent_stored_once = true; const data = { consented_categories: cats, consented_services, consenttype: window.wp_consent_type, //store the source consenttype, as our complianz.consenttype will not include optinstats. }; const request = new XMLHttpRequest(); request.open( 'POST', complianz.url + 'track', true ); request.setRequestHeader( 'Content-type', 'application/json' ); request.send( JSON.stringify( data ) ); } /* * Get accepted categories * * @returns {string} */ function cmplz_accepted_categories() { let consentedCategories = cmplz_categories; const consentedTemp = []; //because array filter changes keys, we make a temp arr for ( const key in consentedCategories ) { if ( consentedCategories.hasOwnProperty( key ) ) { const category = consentedCategories[ key ]; if ( cmplz_has_consent( category ) ) { consentedTemp.push( category ); } } } consentedCategories = consentedCategories.filter( function( value ) { return cmplz_in_array( value, consentedTemp ); } ); return consentedCategories; } /* * Enable the checkbox for each category which was enabled * * */ function cmplz_sync_category_checkboxes() { for ( const key in cmplz_categories ) { if ( cmplz_categories.hasOwnProperty( key ) ) { const category = cmplz_categories[ key ]; if ( cmplz_has_consent( category ) || category === 'functional' ) { document.querySelectorAll( 'input.cmplz-' + category ).forEach( ( obj ) => { obj.checked = true; } ); } else { document.querySelectorAll( 'input.cmplz-' + category ).forEach( ( obj ) => { obj.checked = false; } ); } } document.querySelectorAll( '.cmplz-accept-service' ).forEach( ( obj ) => { const service = obj.getAttribute( 'data-service' ); const category = obj.getAttribute( 'data-category' ); if ( cmplz_has_service_consent( service, category ) ) { obj.checked = true; } else if ( cmplz_is_service_denied( service ) ) { obj.checked = false; } else { //no consent on service level, check if it's category has consent. obj.checked = !! cmplz_has_consent( category ); } } ); } } /* * Merge two objects * * */ function cmplz_merge_object( userdata, ajax_data ) { const output = {}; //first, we fill the important data. for ( const key in ajax_data ) { if ( ajax_data.hasOwnProperty( key ) ) { output[ key ] = ajax_data[ key ]; } } //conditionally add static data for ( const key in userdata ) { //only add if not in ajax_data if ( ! ajax_data.hasOwnProperty( key ) || typeof ajax_data[ key ] === 'undefined' ) { if ( userdata.hasOwnProperty( key ) ) { output[ key ] = userdata[ key ]; } } } return output; } /* * Clear all our own cookies, to make sure path issues are resolved. * * */ function cmplz_clear_cookies( cookie_part ) { if ( typeof document === 'undefined' ) { return false; } let foundCookie = false; const secure = window.location.protocol === 'https:' ? ';secure' : ''; const expires = 'expires=' + new Date().toGMTString(); const pathParts = location.pathname.replace( /^\/|\/$/g, '' ).split( '/' ); // Loop through all cookies document.cookie.split( '; ' ).forEach( function( cookie ) { const cookieName = cookie.split( ';' )[ 0 ].split( '=' )[ 0 ]; // If the cookie contains cookie_part, try to delete it if ( cookieName.indexOf( cookie_part ) !== -1 ) { foundCookie = true; const domainParts = window.location.hostname.split( '.' ); const skipLast = domainParts.length > 1; // Clear cookies on root path and subpaths pathParts.forEach( function( pathPart ) { const path = '/' + pathPart; document.cookie = encodeURIComponent( cookieName ) + '=;SameSite=Lax' + secure + ';' + expires + ';domain=.' + domainParts.join( '.' ) + ';path=' + path; document.cookie = encodeURIComponent( cookieName ) + '=;SameSite=Lax' + secure + ';' + expires + ';domain=.' + domainParts.join( '.' ) + ';path=' + path + '/'; } ); // Clear cookies on parent domains while ( domainParts.length > 0 ) { const domain = '.' + domainParts.join( '.' ); domainParts.shift(); if ( skipLast && domainParts.length === 1 ) { domainParts.shift(); } pathParts.forEach( function( pathPart ) { const path = '/' + pathPart; document.cookie = encodeURIComponent( cookieName ) + '=;SameSite=Lax' + secure + ';' + expires + ';domain=' + domain + ';path=' + path; document.cookie = encodeURIComponent( cookieName ) + '=;SameSite=Lax' + secure + ';' + expires + ';domain=' + domain + ';path=' + path + '/'; } ); } } } ); // To prevent a double reload, we preserve the cookie policy id cmplz_set_accepted_cookie_policy_id(); return foundCookie; } /* * * If a policy is accepted, save this in the user policy id * * */ function cmplz_set_accepted_cookie_policy_id() { cmplz_set_cookie( 'policy_id', complianz.current_policy_id ); } /* * For supported integrations, initialize the not consented state * * */ function cmplz_integrations_init() { const cookiesToSet = complianz.set_cookies; //check if we have scripts that need to be set to true on init. for ( const key in cookiesToSet ) { if ( cookiesToSet.hasOwnProperty( key ) && cookiesToSet[ key ][ 1 ] === '1' ) { cmplz_set_cookie( key, cookiesToSet[ key ][ 1 ], false ); } } } /* * For supported integrations, revoke consent * * */ function cmplz_integrations_revoke() { const cookiesToSet = complianz.set_cookies; for ( const key in cookiesToSet ) { if ( cookiesToSet.hasOwnProperty( key ) ) { const revokeValue = cookiesToSet[ key ][ 1 ]; cmplz_set_cookie( key, revokeValue, false ); // A zero/empty revoke value (e.g. integer 0 from some integrations) // means "clear this cookie" — preserves the original == false behaviour. // A meaningful value such as '1' (e.g. dont_track_me) is kept, not cleared. if ( Number( revokeValue ) === 0 ) { cmplz_clear_cookies( key ); } } } } /* * For supported integrations, set consent * * */ function cmplz_set_integrations_cookies() { const cookiesToSet = complianz.set_cookies; for ( const key in cookiesToSet ) { if ( cookiesToSet.hasOwnProperty( key ) ) { cmplz_set_cookie( key, cookiesToSet[ key ][ 0 ], false ); } } } function cmplz_get_url_parameter( sPageURL, sParam ) { if ( ! sPageURL || typeof sPageURL === 'undefined' || sPageURL.indexOf( '?' ) === -1 ) { return false; } const queryString = sPageURL.split( '?' )[ 1 ]; if ( ! queryString ) { return false; } const sURLVariables = queryString.split( '&' ); for ( let i = 0; i < sURLVariables.length; i++ ) { const sParameterName = sURLVariables[ i ].split( '=' ); if ( sParameterName[ 0 ] === sParam ) { return sParameterName[ 1 ] === undefined ? true : decodeURIComponent( sParameterName[ 1 ] ); } } return false; } /* * If the parameter cmplz_region_redirect =true is passed, find the user's region, and redirect. */ function cmplz_maybe_auto_redirect() { const redirect = cmplz_get_url_parameter( window.location.href, 'cmplz_region_redirect' ); const region = cmplz_get_url_parameter( window.location.href, 'cmplz-region' ); if ( redirect && ! region ) { const newUrl = window.location.href.split( '#' )[ 0 ] + '&cmplz-region=' + complianz.region; const hash = window.location.hash; window.location.href = newUrl + hash; } } /* * wrapper to set consent for wp consent API. If consent API is not active, do nothing * @param type * @param value */ function cmplz_wp_set_consent( type, value ) { //wp consent api integration if ( typeof wp_set_consent === 'function' ) { wp_set_consent( type, value ); } } function cmplz_start_clean() { if ( Number( complianz.clean_cookies ) === 1 ) { //check if it's already stored if ( typeof ( Storage ) !== 'undefined' ) { cmplz_cookie_data = JSON.parse( sessionStorage.getItem( 'cmplz_cookie_data' ) ); } //if not stored yet, load. As features in the user object can be changed on updates, we also check for the version if ( ! cmplz_cookie_data || cmplz_cookie_data.length === 0 ) { const request = new XMLHttpRequest(); request.open( 'GET', complianz.url + 'cookie_data', true ); request.setRequestHeader( 'Content-type', 'application/json' ); request.send(); request.onload = function() { cmplz_cookie_data = JSON.parse( request.response ); sessionStorage.setItem( 'cmplz_cookie_data', JSON.stringify( cmplz_cookie_data ) ); cmplz_setup_clean_interval(); }; } else { cmplz_setup_clean_interval(); } } } /* * Execute the cleanup of cookies */ function cmplz_do_cleanup() { const consent_categories = [ 'preferences', 'statistics', 'marketing' ]; for ( const category of consent_categories ) { if ( ! cmplz_has_consent( category ) && cmplz_cookie_data.hasOwnProperty( category ) ) { const services = cmplz_cookie_data[ category ]; for ( const service in services ) { if ( ! cmplz_has_service_consent( service, category ) ) { const cookies = services[ service ]; for ( const item of cookies ) { cmplz_clear_cookies( item ); cmplz_clear_storage( item ); } } } } } } function cmplz_setup_clean_interval() { // if the cookie data array is empty, return, nothing to do. if ( ! cmplz_cookie_data ) { return; } //check if it's already activated if ( cmplzCleanCookieInterval ) { return; } //one straight away, then every second cmplz_do_cleanup(); cmplzCleanCookieInterval = setInterval( cmplz_do_cleanup, 1000 ); } /* * Clear an item from either session or localstorage * @param item */ function cmplz_clear_storage( item ) { if ( typeof ( Storage ) !== 'undefined' ) { if ( localStorage.getItem( item ) ) { localStorage.removeItem( item ); } if ( sessionStorage.getItem( item ) ) { sessionStorage.removeItem( item ); } } } /* * Load revoke options */ function cmplz_load_manage_consent_container() { //don't load manage html code in the block editor const manage_consent_container = document.querySelector( '.cmplz-manage-consent-container' ); const is_block_editor = false;//document.querySelector('.wp-admin .cmplz-unlinked-mode'); if ( manage_consent_container && ! is_block_editor ) { const request = new XMLHttpRequest(); request.open( 'GET', complianz.url + 'manage_consent_html?' + complianz.locale, true ); request.setRequestHeader( 'Content-type', 'application/json' ); request.send(); request.onload = function() { const html = JSON.parse( request.response ); manage_consent_container.insertAdjacentHTML( 'beforeend', html ); cmplz_sync_category_checkboxes(); const nojavascript = document.querySelector( '#cmplz-manage-consent-container-nojavascript' ); nojavascript.style.display = 'none'; manage_consent_container.style.display = 'block'; const event = new CustomEvent( 'cmplz_manage_consent_container_loaded' ); document.dispatchEvent( event ); }; } } /* * Make slider radio's tabable */ cmplz_add_event( 'keypress', '.cmplz-banner-slider label', function( e ) { const keycode = ( e.keyCode ? e.keyCode : e.which ); if ( keycode === 32 ) { e.target.click(); } } ); /* * Make close button closable with enter */ cmplz_add_event( 'keypress', '.cmplz-cookiebanner .cmplz-header .cmplz-close', function( e ) { const keycode = ( e.keyCode ? e.keyCode : e.which ); if ( keycode === 13 ) { e.target.click(); } } ); /* * Compare two arrays * @param array * @returns {boolean} */ function cmplz_equals( array_1, array_2 ) { // If both are objects (not arrays), compare their values properly if ( typeof array_1 === 'object' && array_1 !== null && ! Array.isArray( array_1 ) && typeof array_2 === 'object' && array_2 !== null && ! Array.isArray( array_2 ) ) { // Get all unique keys from both objects const allKeys = [ ...new Set( [ ...Object.keys( array_1 ), ...Object.keys( array_2 ) ] ) ]; // Compare each key's value for ( const key of allKeys ) { if ( array_1[ key ] !== array_2[ key ] ) { return false; } } return true; } // Original array comparison logic if ( ! Array.isArray( array_1 ) ) { array_1 = Object.keys( array_1 ); array_2 = Object.keys( array_2 ); } // if the other array is a falsy value, return if ( ! array_1 || ! array_2 ) { return false; } // compare lengths - can save a lot of time if ( array_1.length !== array_2.length ) { return false; } for ( let i = 0, l = array_1.length; i < l; i++ ) { // Check if we have nested arrays if ( array_1[ i ] instanceof Array && array_2[ i ] instanceof Array ) { // recurse into the nested arrays if ( ! cmplz_equals( array_1[ i ], array_2[ i ] ) ) { return false; } } else if ( array_1[ i ] !== array_2[ i ] ) { return false; } } return true; } /* * Copy all element atributes to the new element */ function cmplzCopyAttributes( source, target ) { const excludes = [ 'type', 'data-service', 'data-category', 'async' ]; Array.from( source.attributes ).forEach( ( attribute ) => { if ( attribute.nodeName === 'data-script-type' && attribute.nodeValue === 'module' ) { target.setAttribute( 'type', 'module' ); target.removeAttribute( 'data-script-type' ); } else if ( ! excludes.includes( attribute.nodeName ) ) { target.setAttribute( attribute.nodeName, attribute.nodeValue ); } } ); } /* * Hooked into jquery */ const cmplz_has_wp_video = document.querySelector( '.cmplz-wp-video-shortcode' ); let cmplz_times_checked = 0; if ( 'undefined' !== typeof window.jQuery ) { jQuery( document ).ready( function( $ ) { if ( cmplz_has_wp_video ) { document.addEventListener( 'cmplz_enable_category', function() { cmplz_activate_wp_video(); } ); const cmplzInterval = setInterval( function() { cmplz_times_checked += 1; if ( document.querySelector( '.cmplz-wp-video-shortcode' ) && cmplz_times_checked < 100 ) { cmplz_activate_wp_video(); } else { clearInterval( cmplzInterval ); } }, 500 ); } /* * WordPress legacy shortcode */ function cmplz_activate_wp_video() { if ( ! document.querySelector( '.cmplz-wp-video-shortcode' ) ) { return; } const categories = cmplz_accepted_categories(); const services = cmplz_get_all_service_consents(); let selectorVideo = ''; const selectorVideos = []; for ( const c_key in categories ) { if ( categories.hasOwnProperty( c_key ) ) { const category = categories[ c_key ]; if ( category === 'functional' ) { break; } selectorVideos.push( '.cmplz-wp-video-shortcode[data-category="' + category + '"]' ); } } for ( const s_key in services ) { if ( services.hasOwnProperty( s_key ) ) { selectorVideos.push( '.cmplz-wp-video-shortcode[data-service="' + s_key + '"]' ); } } selectorVideo = selectorVideos.join( ',' ); let should_initialize_video = false; if ( selectorVideo.length > 0 ) { document.querySelectorAll( selectorVideo ).forEach( ( obj ) => { should_initialize_video = true; obj.setAttribute( 'controls', 'controls' ); obj.classList.add( 'wp-video-shortcode', 'cmplz-processed' ); obj.classList.remove( 'cmplz-wp-video-shortcode' ); obj.closest( '.cmplz-wp-video' ).classList.remove( 'cmplz-wp-video' ); const blocked_notice = obj.closest( '.wp-video' ).querySelector( '.cmplz-blocked-content-notice' ); if ( blocked_notice ) { blocked_notice.parentElement.removeChild( blocked_notice ); } obj.classList.remove( 'cmplz-blocked-content-container' ); } ); } if ( should_initialize_video ) { //in normal setup, this should work. e.g. with primavera theme not, then we init per element. if ( window.wp.mediaelement ) { window.wp.mediaelement.initialize(); } else { const settings = {}; settings.videoWidth = '100%'; settings.videoHeight = '100%'; settings.enableAutosize = true; $( '.wp-video-shortcode' ).mediaelementplayer( settings ); } } } /* * Activate fitvids on the parent element if active * a.o. Beaverbuilder */ document.querySelectorAll( '.cmplz-video.cmplz-activated' ).forEach( ( obj ) => { cmplz_activate_fitvids( obj ); } ); document.addEventListener( 'cmplz_enable_category', function() { document.querySelectorAll( '.cmplz-video.cmplz-activated' ).forEach( ( obj ) => { cmplz_activate_fitvids( obj ); } ); } ); function cmplz_activate_fitvids( obj ) { //turn obj into jquery object const $obj = $( obj ); if ( typeof $obj.parent().fitVids === 'function' ) { $obj.parent().fitVids(); } } } ); }