1(function($) { 2 $(document).ready(function() { 3 var addon_script_delay_2 = typeof moove_frontend_gdpr_scripts !== 'undefined' && typeof moove_frontend_gdpr_scripts.script_delay !== 'undefined' && parseInt( moove_frontend_gdpr_scripts.script_delay ) ? parseInt( moove_frontend_gdpr_scripts.script_delay ) : 0; 4 5 function addon_script_2_init() { 6 try { 7 8 if ( typeof moove_frontend_gdpr_scripts.ifbc !== 'undefined' ) { 9 if ( typeof moove_frontend_gdpr_scripts.ifbc_excl !== 'undefined' ) { 10 var ifb_excl = JSON.parse( moove_frontend_gdpr_scripts.ifbc_excl ); 11 } else { 12 var ifb_excl = {}; 13 } 14 function gdpr_ifbc_js_block_iframes( ) { 15 $(document).find('iframe').each(function() { 16 if ( ! $(this).attr('data-gdpr-iframesrc') ) { 17 var src = $(this).attr('src'); 18 if ( src ) { 19 var change_iframe = true; 20 for (var i = ifb_excl.length - 1; i >= 0; i--) { 21 if ( src.indexOf( ifb_excl[i] ) >= 0 ) { 22 change_iframe = false; 23 } 24 } 25 26 if ( change_iframe ) { 27 var gdpr_src = moove_frontend_gdpr_scripts.ajaxurl; 28 var block_src = gdpr_src + '?action=gdpr_iframe_blocker&src=' + src; 29 $(this).attr('src', block_src); 30 $(this).attr('data-gdpr-iframesrc', src); 31 $(this).closest('.fb-video').addClass('fb-blocked-gdpr'); 32 } 33 } 34 } 35 }); 36 } 37 38 function gdpr_restrict_iframes() { 39 if ( typeof $(document).moove_gdpr_read_cookies !== 'undefined' ) { 40 var cookies = $(document).moove_gdpr_read_cookies(); 41 if ( cookies ) { 42 if ( moove_frontend_gdpr_scripts.ifbc === 'strict' && cookies && parseInt( cookies.strict ) === 0 ) { 43 gdpr_ifbc_js_block_iframes(); 44 } 45 46 if ( moove_frontend_gdpr_scripts.ifbc === 'thirdparty' && cookies && parseInt( cookies.thirdparty ) === 0 ) { 47 gdpr_ifbc_js_block_iframes(); 48 } 49 50 if ( moove_frontend_gdpr_scripts.ifbc === 'advanced' && cookies && parseInt( cookies.advanced ) === 0 ) { 51 gdpr_ifbc_js_block_iframes(); 52 } 53 } else { 54 gdpr_ifbc_js_block_iframes(); 55 } 56 } 57 } 58 gdpr_restrict_iframes(); 59 60 var gdpr_observe_DOM = (function(){ 61 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; 62 63 return function( obj, callback ){ 64 if( !obj || obj.nodeType !== 1 ) return; 65 66 if( MutationObserver ){ 67 // define a new observer 68 var mutationObserver = new MutationObserver(callback) 69 70 // have the observer observe for changes in children 71 mutationObserver.observe( obj, { childList:true, subtree:true }) 72 return mutationObserver 73 } 74 75 // browser support fallback 76 else if( window.addEventListener ){ 77 obj.addEventListener('DOMNodeInserted', callback, false) 78 obj.addEventListener('DOMNodeRemoved', callback, false) 79 } 80 } 81 })(); 82 83 gdpr_observe_DOM( document.getElementsByTagName("html")[0], function(m){ 84 var addedNodes = []; 85 86 m.forEach(record => record.addedNodes.length & addedNodes.push(...record.addedNodes)) 87 88 if ( addedNodes && addedNodes.length > 0 ) { 89 addedNodes.forEach(item => { 90 if ( item.tagName === 'IFRAME' ) { 91 gdpr_restrict_iframes(); 92 } 93 }); 94 } 95 }); 96 97 } 98 } catch( err ) { 99 console.warn(err); 100 } 101 102 function gdpr_cookie_compliance_setup_get_session( event_type ) { 103 var gdpr_uvid_session = false; 104 105 if ( typeof( sessionStorage ) !== "undefined" ) { 106 gdpr_uvid_session = sessionStorage.getItem("gdpr_uvid"); 107 if ( ! gdpr_uvid_session ) { 108 sessionStorage.setItem( "gdpr_uvid", moove_frontend_gdpr_scripts.gdpr_uvid ); 109 gdpr_uvid_session = sessionStorage.getItem("gdpr_uvid"); 110 } 111 } 112 113 return gdpr_uvid_session; 114 } 115 116 function gdpr_cookie_compliance_get_cookies(){ 117 var pairs = document.cookie.split(";"); 118 var cookies = {}; 119 for (var i=0; i<pairs.length; i++){ 120 var pair = pairs[i].split("="); 121 cookies[(pair[0]+'').trim()] = unescape(pair[1]); 122 } 123 return cookies; 124 } 125 126 $(document).on('click','.gdpr-cd-details-toggle', function(e){ 127 e.preventDefault(); 128 var _this = $(this); 129 _this.toggleClass('cd-details-open'); 130 _this.parent().find('.gdpr-table-responsive-cnt').toggle(); 131 132 }); 133 134 function gdpr_cookie_compliance_set_cookies(name, value, days){ 135 var expires; 136 if (days) { 137 var date = new Date(); 138 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 139 expires = "; expires=" + date.toGMTString(); 140 } else { 141 expires = ""; 142 } 143 144 document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/"; 145 (JSON.parse(value)); 146 } 147 148 var started = false;
149 var timeout_req = 200; 150 var gdpr_timeout = 0; 151 var analytics_inserted = []; 152 $.fn.gdpr_cookie_compliance_analytics = function(event, extras) { 153 if ( typeof ( analytics_inserted[event] ) === 'undefined' || analytics_inserted[event] !== JSON.stringify( extras ) ) { 154 analytics_inserted[event] = JSON.stringify( extras ); 155 if ( moove_frontend_gdpr_scripts.stats_enabled ) { 156 var gdpr_uvid_session = gdpr_cookie_compliance_setup_get_session( event ); 157 158 if ( !started ) { 159 gdpr_timeout = 0; 160 } else { 161 gdpr_timeout = gdpr_timeout + timeout_req; 162 } 163 started = true; 164 165 if ( event === 'script_inject' ) { 166 if ( typeof( localStorage ) !== "undefined" ) { 167 gdpr_uvid_session = localStorage.getItem("gdpr_uvid"); 168 if ( ! gdpr_uvid_session ) { 169 localStorage.setItem( "gdpr_uvid", moove_frontend_gdpr_scripts.gdpr_uvid ); 170 gdpr_uvid_session = sessionStorage.getItem("gdpr_uvid"); 171 } else { 172 if ( typeof( sessionStorage ) !== "undefined" ) { 173 _gdpr_uvid_session = sessionStorage.getItem("gdpr_uvid"); 174 if ( ! _gdpr_uvid_session ) { 175 _gdpr_uvid_session.setItem( "gdpr_uvid", moove_frontend_gdpr_scripts.gdpr_uvid ); 176 gdpr_uvid_session = sessionStorage.getItem("gdpr_uvid"); 177 } 178 _event = 'existing_session'; 179 _extras = ''; 180 try { 181 jQuery().gdpr_cookie_compliance_analytics_with_uvid( _event, _extras, _gdpr_uvid_session ); 182 jQuery().gdpr_cookie_compliance_analytics_with_uvid( 'script_injected', extras, _gdpr_uvid_session ); 183 } catch(err) { 184 // error 185 } 186 } 187 } 188 } 189 } 190 setTimeout( function(){ 191 if ( gdpr_uvid_session && event ) { 192 $.post( 193 moove_frontend_gdpr_scripts.ajaxurl, 194 { 195 action: "moove_gdpr_premium_save_analytics", 196 event: event, 197 extras: extras, 198 gdpr_uvid: gdpr_uvid_session, 199 }, 200 function( msg ) { 201 // console.warn(gdpr_uvid_session); 202 if ( gdpr_timeout >= timeout_req ) { 203 gdpr_timeout = gdpr_timeout - timeout_req; 204 } 205 } 206 ); 207 } 208 }, gdpr_timeout ); 209 } 210 } 211 } 212 213 $.fn.gdpr_cookie_compliance_consent_log = function( value ) { 214 if ( moove_frontend_gdpr_scripts.consent_log_enabled ) { 215 $.post( 216 moove_frontend_gdpr_scripts.ajaxurl, 217 { 218 action: "save_consent_log", 219 extras: value, 220 }, 221 function( msg ) { 222 var obj = ( typeof msg === 'string' ) ? JSON.parse( msg ) : msg; 223 if ( 'true' === obj.success ) { 224 localStorage.setItem( "gdpr_consent_id", obj.consent_log_id ); 225 localStorage.setItem( "gdpr_consent_date", obj.timestamp ); 226 check_consent_id_toggle(); 227 } 228 } 229 ); 230 } 231 } 232 233 $.fn.gdpr_cookie_compliance_analytics_with_uvid = function(event, extras, uvid) { 234 if ( moove_frontend_gdpr_scripts.stats_enabled ) { 235 var gdpr_uvid_session = uvid; 236 if ( !started ) { 237 gdpr_timeout = 0; 238 } else { 239 gdpr_timeout = gdpr_timeout + timeout_req; 240 } 241 started = true; 242 243 setTimeout( function(){ 244 if ( gdpr_uvid_session && event ) { 245 $.post( 246 moove_frontend_gdpr_scripts.ajaxurl, 247 { 248 action: "moove_gdpr_premium_save_analytics", 249 event: event, 250 extras: extras, 251 gdpr_uvid: gdpr_uvid_session, 252 }, 253 function( msg ) { 254 // console.warn(gdpr_uvid_session); 255 if ( gdpr_timeout >= timeout_req ) { 256 gdpr_timeout = gdpr_timeout - timeout_req; 257 } 258 } 259 ); 260 } 261 }, gdpr_timeout ); 262 263 } 264 } 265 } 266
267 function check_consent_id_toggle() { 268 if ( moove_frontend_gdpr_scripts.consent_log_enabled && typeof( localStorage ) !== "undefined" ) { 269 var gdpr_consent_id = localStorage.getItem("gdpr_consent_id"); 270 var gdpr_consent_date = localStorage.getItem("gdpr_consent_date"); 271 if ( gdpr_consent_id && gdpr_consent_date ) { 272 $('#privacy_overview').find('.gdpr-cd-box-cid').remove(); 273 var pcontent = $('#privacy_overview').find('.moove-gdpr-tab-main-content'); 274 pcontent.append('<span class="gdpr-cd-details-toggle gdpr-cd-box-cid"><span class="cd-t-show">Show consent details</span><span class="cd-t-close">Hide consent details</span><span class="cd-t-icon"></span></span>'); 275 pcontent.append('<div class="gdpr-cd-box gdpr-table-responsive-cnt gdpr-cd-box-cid" style="display: none;"><p><small><strong>Your consent date:</strong> '+gdpr_consent_date+'</small><br/><small><strong>Consent ID:</strong> '+gdpr_consent_id+'<small></p></div>'); 276 } 277 } 278 } 279 280 check_consent_id_toggle(); 281 282 /** 283 * reCAPTCHA blocker. 284 * 285 * The markup is served blocked to everyone so it stays cache-safe, which means 286 * granting consent has to restore it live - the plugin only reloads the page 287 * when consent is withdrawn, never when it is given. 288 */ 289 function gdpr_recaptcha_blocker() { 290 var blocker_cat = typeof moove_frontend_gdpr_scripts !== 'undefined' && typeof moove_frontend_gdpr_scripts.recaptcha_blocker !== 'undefined' ? moove_frontend_gdpr_scripts.recaptcha_blocker : false; 291 292 if ( ! blocker_cat ) { 293 return; 294 } 295 296 var poll_timer = false; 297 var dom_observer = false; 298 299 // Until the main plugin has registered its cookie reader we cannot tell 300 // "no consent" apart from "not asked yet". Rendering the blocked box on that 301 // unknown is what made it flash up and then get replaced. 302 function gdpr_recaptcha_consent_known() { 303 return typeof $(document).moove_gdpr_read_cookies !== 'undefined'; 304 } 305 306 function gdpr_recaptcha_has_consent() { 307 if ( ! gdpr_recaptcha_consent_known() ) { 308 return false; 309 } 310 var cookies = $(document).moove_gdpr_read_cookies(); 311 return cookies && parseInt( cookies[ blocker_cat ] ) === 1; 312 } 313 314 function gdpr_recaptcha_blocked_nodes() { 315 return document.querySelectorAll('script[type="text/plain"][data-gdpr-blocked]'); 316 } 317 318 // Scripts must run in document order, and an external script has to finish 319 // loading before the inline init code that depends on grecaptcha runs. 320 function gdpr_recaptcha_restore( nodes, index ) { 321 if ( index >= nodes.length ) { 322 return; 323 } 324 325 var blocked = nodes[ index ]; 326 var restored = document.createElement('script'); 327 328 for ( var i = 0; i < blocked.attributes.length; i++ ) { 329 var attr = blocked.attributes[ i ]; 330 if ( attr.name === 'type' || attr.name === 'data-gdpr-blocked' || attr.name === 'data-gdpr-src' ) { 331 continue; 332 } 333 restored.setAttribute( attr.name, attr.value ); 334 } 335 336 var src = blocked.getAttribute('data-gdpr-src'); 337 338 if ( src ) { 339 restored.onload = restored.onerror = function() { 340 gdpr_recaptcha_restore( nodes, index + 1 ); 341 }; 342 restored.src = src; 343 blocked.parentNode.replaceChild( restored, blocked ); 344 } else { 345 restored.text = blocked.textContent; 346 blocked.parentNode.replaceChild( restored, blocked ); 347 gdpr_recaptcha_restore( nodes, index + 1 ); 348 } 349 } 350 351 function gdpr_recaptcha_unblock() { 352 // Consent is usually given from the button inside the placeholder, so the 353 // focused element is about to be destroyed. Remember where the visitor was 354 // to avoid dropping them back to the top of the document. 355 var active = document.activeElement; 356 var focused_slot = active ? $(active).closest('.gdpr-recaptcha-slot')[0] : null; 357 358 // The widget renders into this container, so it has to be emptied before 359 // the script runs - not merely hidden. 360 $('.gdpr-recaptcha-slot').empty().removeClass('gdpr-recaptcha-slot'); 361 $('.gdpr-blocked-recaptcha').remove(); 362 363 if ( focused_slot ) { 364 focused_slot.setAttribute( 'tabindex', '-1' ); 365 focused_slot.focus(); 366 } 367 368 gdpr_recaptcha_restore( gdpr_recaptcha_blocked_nodes(), 0 ); 369 370 if ( poll_timer ) { 371 clearInterval( poll_timer ); 372 poll_timer = false;
373 } 374 375 if ( dom_observer ) { 376 dom_observer.disconnect(); 377 dom_observer = false; 378 } 379 380 // Clears the "accept cookies before sending" error and re-renders, so the 381 // visitor does not have to reload to get a working form. 382 if ( nf_consent_ctx && typeof window.nf_reload_after_cookie_consent === 'function' ) { 383 window.nf_reload_after_cookie_consent( nf_consent_ctx.submitFieldID, nf_consent_ctx.layoutView ); 384 nf_consent_ctx = false; 385 } 386 } 387 388 // A v2 widget leaves an empty gap when blocked, so the slot gets a placeholder 389 // matching the iframe blocker. v3 is invisible and the submission still goes 390 // through via the server-side bypass, so it needs nothing. 391 function gdpr_recaptcha_notice() { 392 var markup = typeof moove_frontend_gdpr_scripts.recaptcha_placeholder !== 'undefined' ? moove_frontend_gdpr_scripts.recaptcha_placeholder : ''; 393 394 if ( ! markup ) { 395 return; 396 } 397 398 // A queued observer callback can outlive the moment consent arrives, so 399 // re-check here rather than trusting the caller. 400 if ( gdpr_recaptcha_has_consent() ) { 401 return; 402 } 403 404 // Template markup is not live DOM - Ninja Forms and friends keep their 405 // widget container inside <script type="text/template"> until render. 406 $(document).find('.g-recaptcha, .wpcf7-recaptcha, [data-sitekey]').not('script *').each(function() { 407 var slot = $(this); 408 var tag = ( this.tagName || '' ).toLowerCase(); 409 410 if ( slot.hasClass('gdpr-recaptcha-slot') ) { 411 return; 412 } 413 414 // Invisible reCAPTCHA hangs data-sitekey off the submit button itself, 415 // so filling the element would destroy the control. It has no visible 416 // widget to stand in for either, exactly like v3. 417 if ( tag !== 'div' && tag !== 'span' ) { 418 return; 419 } 420 421 if ( slot.attr('data-size') === 'invisible' ) { 422 return; 423 } 424 425 // Nested matches would otherwise get a placeholder each. 426 if ( slot.find('.gdpr-blocked-recaptcha').length || slot.closest('.gdpr-blocked-recaptcha').length ) { 427 return; 428 } 429 430 slot.addClass('gdpr-recaptcha-slot').html( markup ); 431 432 // Injected hidden, revealed on the next frame, so it eases in instead 433 // of popping into an area the visitor is already looking at. 434 var box = slot.find('.gdpr-blocked-recaptcha'); 435 window.requestAnimationFrame ? window.requestAnimationFrame(function() { 436 box.addClass('gdpr-rcp-visible'); 437 }) : box.addClass('gdpr-rcp-visible'); 438 }); 439 } 440 441 /** 442 * Ninja Forms consent integration. 443 * 444 * v3 and invisible v2 have no widget to put a placeholder into, so there is 445 * nothing to show the visitor - the form simply fails on submit. Ninja Forms 446 * solves this itself: it blocks the submit, explains why, and exposes hooks 447 * for a consent plugin to declare the blocker and offer a way to accept. 448 */ 449 var nf_consent_ctx = false; 450 451 document.addEventListener('nf_consent_status_check', function( e ) { 452 if ( ! e.detail || ! e.detail.services || gdpr_recaptcha_has_consent() ) { 453 return; 454 } 455 456 // Ninja Forms only offers its consent UI when a named service - not just 457 // its own "missing_cookie" - is reporting the block. 458 if ( e.detail.services.indexOf('moove_gdpr') === -1 ) { 459 e.detail.services.push('moove_gdpr'); 460 } 461 }); 462 463 document.addEventListener('nf_consent_link', function( e ) { 464 if ( ! e.detail || ! e.detail.element || gdpr_recaptcha_has_consent() ) { 465 return; 466 } 467 468 // Kept so the form can be re-rendered once consent arrives. 469 nf_consent_ctx = { 470 submitFieldID: e.detail.submitFieldID, 471 layoutView: e.detail.layoutView 472 }; 473 474 var label = typeof moove_frontend_gdpr_scripts.recaptcha_accept !== 'undefined' ? moove_frontend_gdpr_scripts.recaptcha_accept : 'Accept'; 475 var button = document.createElement('a'); 476 477 button.href = '#'; 478 button.className = 'gdpr-shr-button button-green gdpr-rcp-accept'; 479 button.textContent = label; 480 481 e.detail.element.appendChild( button ); 482 }); 483 484 $(document).on('click', '.gdpr-rcp-accept', function(e) { 485 e.preventDefault(); 486 $('.moove-gdpr-infobar-allow-all').first().trigger('click'); 487 }); 488 489 $(document).on('click', '.gdpr-rcp-reject', function(e) { 490 e.preventDefault(); 491 $('.moove-gdpr-infobar-reject-btn, .moove-gdpr-modal-reject-all').first().trigger('click'); 492 }); 493 494 $(document).on('click', '.gdpr-rcp-settings', function(e) { 495 e.preventDefault(); 496 $('[data-href="#moove_gdpr_cookie_modal"]').first().trigger('click'); 497 }); 498 499 // Form builders that render fields client-side (Ninja Forms, and any Backbone 500 // or React driven form) insert the widget container long after ready, so a 501 // single pass at load time finds nothing to place the notice into. 502 function gdpr_recaptcha_watch_dom() { 503 var Observer = window.MutationObserver || window.WebKitMutationObserver; 504 505 if ( ! Observer ) { 506 return false;
507 } 508 509 var pending = false; 510 var observer = new Observer(function( records ) { 511 var added = false; 512 513 for ( var i = 0; i < records.length; i++ ) { 514 if ( records[i].addedNodes && records[i].addedNodes.length ) { 515 added = true; 516 break; 517 } 518 } 519 520 if ( ! added || pending ) { 521 return; 522 } 523 524 // Our own injection mutates the DOM too - defer so the batch settles 525 // and we do not re-enter on every inserted node. 526 pending = true; 527 setTimeout(function() { 528 pending = false; 529 gdpr_recaptcha_notice(); 530 }, 100); 531 }); 532 533 observer.observe( document.body, { childList: true, subtree: true } ); 534 535 return observer; 536 } 537 538 /** 539 * Act only once the consent state is actually known. 540 * 541 * Returns true when the visitor has consented and nothing further is needed. 542 */ 543 function gdpr_recaptcha_apply() { 544 if ( ! gdpr_recaptcha_consent_known() ) { 545 return false; 546 } 547 548 if ( gdpr_recaptcha_has_consent() ) { 549 gdpr_recaptcha_unblock(); 550 return true; 551 } 552 553 gdpr_recaptcha_notice(); 554 555 if ( ! dom_observer ) { 556 dom_observer = gdpr_recaptcha_watch_dom(); 557 } 558 559 return false; 560 } 561 562 // One timer covers both waits: the main plugin initialising, and the visitor 563 // consenting later. It stops as soon as consent arrives, so it costs nothing 564 // once the decision is made. 565 if ( ! gdpr_recaptcha_apply() ) { 566 poll_timer = setInterval(function() { 567 if ( gdpr_recaptcha_apply() ) { 568 clearInterval( poll_timer ); 569 poll_timer = false; 570 } 571 }, 200); 572 } 573 } 574 575 gdpr_recaptcha_blocker(); 576 577 if ( addon_script_delay_2 > 0 ) { 578 setTimeout( function(){ 579 addon_script_2_init() 580 }, addon_script_delay_2 ); 581 } else { 582 addon_script_2_init(); 583 } 584 }); 585})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.