1/** 2 * Easy Social Feed - GDPR Consent Checking 3 * Shared across all modules (Facebook, Instagram, etc.) 4 * 5 * @package EasySocialFeed 6 * @since 6.8.0 7 */ 8 9(function($) { 10 'use strict'; 11 12 var FEED_CONTAINER_SELECTOR = [ 13 '.efbl_feed_wraper', 14 '.esf_insta_feed_wraper', 15 '.esf-instagram-feed', 16 '.esf-twitter-feed', 17 '.esf-tw-feed', 18 '.esf-youtube-feed', 19 '.esf-yt-feed', 20 '.esf-tiktok-feed' 21 ].join(', '); 22 23 var LOAD_MORE_SELECTOR = [ 24 '.efbl_load_more_holder', 25 '[class*="__load-more"]', 26 '.esf-instagram-feed__load-more', 27 '.esf-twitter-feed__load-more', 28 '.esf-youtube-feed__load-more', 29 '.esf-tiktok-feed__load-more' 30 ].join(', '); 31 32 /** 33 * Check if user has given consent through various GDPR plugins 34 * 35 * @param {jQuery} container Feed container element 36 * @return {boolean} True if consent given, false otherwise 37 */ 38 function checkConsent(container) { 39 // Get flags from data attribute. 40 var flags = container.attr('data-esf-flags') || ''; 41 var hasGdpr = flags.indexOf('gdpr') > -1; 42 43 // If GDPR not enabled, return true (allow all). 44 if (!hasGdpr) { 45 return true; 46 } 47 48 var consentGiven = false; 49 50 // Check WPConsent. 51 if (typeof window.WPConsent !== 'undefined') { 52 consentGiven = window.WPConsent.hasConsent('marketing'); 53 if (consentGiven !== null && consentGiven !== undefined) { 54 return consentGiven; 55 } 56 } 57 58 // Check CookieYes. 59 if (typeof window.cookieyes !== 'undefined') { 60 try { 61 if (typeof window.cookieyes._ckyConsentStore !== 'undefined' && 62 typeof window.cookieyes._ckyConsentStore.get !== 'undefined') { 63 consentGiven = window.cookieyes._ckyConsentStore.get('functional') === 'yes'; 64 if (consentGiven !== null && consentGiven !== undefined) { 65 return consentGiven; 66 } 67 } 68 } catch (e) { 69 // Continue to next method. 70 } 71 } 72 73 // Check GDPR Cookie Consent (WebToffee). 74 if (typeof CLI_Cookie !== 'undefined') { 75 try { 76 if (CLI_Cookie.read(CLI_ACCEPT_COOKIE_NAME) !== null) { 77 // Backwards compatibility. 78 if (CLI_Cookie.read('cookielawinfo-checkbox-non-necessary') !== null) { 79 consentGiven = CLI_Cookie.read('cookielawinfo-checkbox-non-necessary') === 'yes'; 80 if (consentGiven !== null && consentGiven !== undefined) { 81 return consentGiven; 82 } 83 } 84 if (CLI_Cookie.read('cookielawinfo-checkbox-necessary') !== null) { 85 consentGiven = CLI_Cookie.read('cookielawinfo-checkbox-necessary') === 'yes'; 86 if (consentGiven !== null && consentGiven !== undefined) { 87 return consentGiven; 88 } 89 } 90 } 91 } catch (e) { 92 // Continue to next method. 93 } 94 } 95 96 // Check Cookie Notice (dFactory). 97 if (typeof window.cnArgs !== 'undefined') { 98 try { 99 var value = '; ' + document.cookie; 100 var parts = value.split('; cookie_notice_accepted='); 101 if (parts.length === 2) { 102 var val = parts.pop().split(';').shift(); 103 consentGiven = (val === 'true'); 104 if (consentGiven !== null && consentGiven !== undefined) { 105 return consentGiven; 106 } 107 } 108 } catch (e) { 109 // Continue to next method. 110 } 111 } 112 113 // Check Complianz. 114 if (typeof window.complianz !== 'undefined' || typeof window.cookieconsent !== 'undefined') { 115 try { 116 consentGiven = esfGetCookie('cmplz_marketing') === 'allow'; 117 if (consentGiven !== null && consentGiven !== undefined) { 118 return consentGiven; 119 } 120 } catch (e) { 121 // Continue to next method. 122 } 123 } 124 125 // Check Cookiebot. 126 if (typeof window.Cookiebot !== 'undefined') { 127 try { 128 consentGiven = Cookiebot.consented; 129 if (consentGiven !== null && consentGiven !== undefined) { 130 return consentGiven; 131 } 132 } catch (e) { 133 // Continue to next method. 134 } 135 } 136 137 // Check Borlabs Cookie. 138 if (typeof window.BorlabsCookie !== 'undefined') { 139 try { 140 consentGiven = window.BorlabsCookie.checkCookieConsent('facebook') || 141 window.BorlabsCookie.checkCookieConsent('marketing'); 142 if (consentGiven !== null && consentGiven !== undefined) { 143 return consentGiven; 144 } 145 } catch (e) { 146 // Continue to next method. 147 } 148 } 149 150 // Check Moove GDPR Popup. 151 try { 152 var mooveCookie = esfGetCookie('moove_gdpr_popup'); 153 if (mooveCookie) { 154 var moove_gdpr_popup = JSON.parse(decodeURIComponent(mooveCookie)); 155 consentGiven = typeof moove_gdpr_popup.thirdparty !== 'undefined' && 156 moove_gdpr_popup.thirdparty === '1'; 157 if (consentGiven !== null && consentGiven !== undefined) { 158 return consentGiven; 159 } 160 } 161 } catch (e) { 162 // Continue to next method. 163 } 164 165 // Check Real Cookie Banner (async, handled via events). 166 if (typeof window.consentApi !== 'undefined') { 167 try { 168 // This is async, so we'll handle it separately. 169 } catch (e) { 170 // Continue. 171 } 172 } 173 174 // Default: no consent. 175 return false;
176 } 177 178 /** 179 * Determine GDPR mode for a container based on its flags. 180 * 181 * @param {jQuery} container Feed container element 182 * @return {string} 'yes' | 'auto' | 'none' 183 */ 184 function getGdprMode(container) { 185 var flagsAttr = container.attr('data-esf-flags') || ''; 186 var flags = flagsAttr ? flagsAttr.split(',') : []; 187 188 // Zero-third-party and always-enabled GDPR never unlock remotes. 189 if (flags.indexOf('gdpr_yes') > -1 || flags.indexOf('gdpr_zero_third_party') > -1) { 190 return 'yes'; 191 } 192 193 if (flags.indexOf('gdpr_auto') > -1) { 194 return 'auto'; 195 } 196 197 return 'none'; 198 } 199 200 /** 201 * Hide load-more UI for GDPR-restricted containers. 202 * 203 * @param {jQuery} container Feed container 204 * @return {void} 205 */ 206 function hideLoadMore(container) { 207 container.find(LOAD_MORE_SELECTOR).hide(); 208 } 209 210 /** 211 * Helper function to read cookies. 212 * 213 * @param {string} cname Cookie name 214 * @return {string} Cookie value or empty string 215 */ 216 function esfGetCookie(cname) { 217 var name = cname + '='; 218 var cArr = document.cookie.split(';'); 219 220 for (var i = 0; i < cArr.length; i++) { 221 var c = cArr[i].trim(); 222 if (c.indexOf(name) === 0) { 223 return c.substring(name.length, c.length); 224 } 225 } 226 227 return ''; 228 } 229 230 /** 231 * Enable full features when consent is given. 232 * 233 * @param {jQuery} container Feed container 234 */ 235 function enableFullFeatures(container) { 236 var mode = getGdprMode(container); 237 238 // In "yes" / zero-TP mode we never load real images from CDN, 239 // and we also keep Load More disabled to avoid additional API calls. 240 if (mode === 'yes') { 241 return; 242 } 243 244 // Remove admin notices. 245 container.find('.esf-gdpr-notice').remove(); 246 247 // Replace images. 248 container.find('.esf-no-consent').each(function() { 249 var $element = $(this); 250 var realImageUrl = $element.attr('data-image-url'); 251 252 if (realImageUrl) { 253 // Update <img> tag if present. 254 var $img = $element.is('img') ? $element : $element.find('img'); 255 if ($img.length) { 256 $img.attr('src', realImageUrl); 257 } 258 259 // Always update background-image on the container as well. 260 $element.css('background-image', 'url(' + realImageUrl + ')'); 261 262 $element.removeClass('esf-no-consent'); 263 $element.removeAttr('data-image-url'); 264 } 265 }); 266 267 // Show load more button if present. 268 container.find(LOAD_MORE_SELECTOR).show(); 269 } 270 271 /** 272 * Initial consent check on page load. 273 */ 274 function initConsentCheck() { 275 var $containers = $(FEED_CONTAINER_SELECTOR); 276 277 // Initial check for all feed containers. 278 $containers.each(function() { 279 var $container = $(this); 280 var flags = $container.attr('data-esf-flags') || ''; 281 var mode = getGdprMode($container); 282 283 if (flags.indexOf('gdpr') > -1) { 284 // If mode is "yes" (or zero-TP) then GDPR is always enforced and 285 // consent does not change behaviour. Hide Load More 286 // permanently and skip consent checks. 287 if (mode === 'yes') { 288 // Always enforced: hide Load More permanently and never load external media. 289 hideLoadMore($container); 290 return; 291 } 292 293 // For "auto" mode, first check immediately if consent is already present 294 // (e.g. user accepted on a previous visit). This avoids a visible flash 295 // of placeholder images when the page is reloaded after consent. 296 var immediateConsent = checkConsent($container); 297 if (immediateConsent) { 298 // Consent already given: enable full features right away and keep 299 // Load More visible. No need to hide it or wait. 300 enableFullFeatures($container); 301 return; 302 } 303 304 // No consent yet: hide Load More by default until consent is confirmed. 305 hideLoadMore($container); 306 307 // Delay to allow consent plugins to initialize, then re-check. 308 setTimeout(function() { 309 var consent = checkConsent($container); 310 if (consent) { 311 enableFullFeatures($container); 312 } 313 }, 250); 314 } 315 }); 316 317 // Fallback polling: some consent plugins do not fire JS events, 318 // so periodically re-check consent for a short period. 319 var attempts = 0; 320 var maxAttempts = 30;
320 // ~60 seconds if interval is 2000ms. 321 var pollInterval = 2000; 322 323 var intervalId = setInterval(function() { 324 attempts++; 325 326 $containers.each(function() { 327 var $container = $(this); 328 var flags = $container.attr('data-esf-flags') || ''; 329 var mode = getGdprMode($container); 330 331 if (flags.indexOf('gdpr') === -1) { 332 return; 333 } 334 335 // Skip "yes" / zero-TP mode: always GDPR-limited, consent 336 // does not unlock external media. 337 if (mode === 'yes') { 338 return; 339 } 340 341 // Only bother if placeholders are still present. 342 if ($container.find('.esf-no-consent').length === 0) { 343 return; 344 } 345 346 if (checkConsent($container)) { 347 enableFullFeatures($container); 348 } 349 }); 350 351 if (attempts >= maxAttempts) { 352 clearInterval(intervalId); 353 } 354 }, pollInterval); 355 } 356 357 358 /** 359 * Callback when consent is toggled. 360 * 361 * @param {boolean} isConsent Whether consent was given 362 */ 363 function afterConsentToggled(isConsent) { 364 if (isConsent) { 365 $(FEED_CONTAINER_SELECTOR).each(function() { 366 var $container = $(this); 367 var flags = $container.attr('data-esf-flags') || ''; 368 var mode = getGdprMode($container); 369 370 if (flags.indexOf('gdpr') === -1) { 371 return; 372 } 373 374 // Skip "yes" / zero-TP mode: it always stays GDPR-limited. 375 if (mode === 'yes') { 376 return; 377 } 378 379 enableFullFeatures($container); 380 }); 381 } 382 } 383 384 // Initialize on document ready. 385 $(document).ready(function() { 386 initConsentCheck(); 387 388 // Helper to re-enable full features after consent from various plugins. 389 function triggerAfterConsent() { 390 // Small delay so consent plugin can update its cookies/state. 391 setTimeout(function() { 392 afterConsentToggled(true); 393 }, 1000); 394 } 395 396 // Cookie Notice by dFactory. 397 $('#cookie-notice a').on('click', function() { 398 triggerAfterConsent(); 399 }); 400 401 // GDPR Cookie Consent by WebToffee (Cookie Law Info bar). 402 $('#cookie-law-info-bar a').on('click', function() { 403 triggerAfterConsent(); 404 }); 405 406 // GDPR Cookie Consent by WebToffee (preference checkboxes / notice buttons). 407 $('.cli-user-preference-checkbox, .cky-notice button').on('click', function() { 408 triggerAfterConsent(); 409 }); 410 411 // Cookiebot by Cybot A/S. 412 $(window).on('CookiebotOnAccept', function() { 413 triggerAfterConsent(); 414 }); 415 416 // Complianz by Really Simple Plugins (buttons). 417 $('.cmplz-btn').on('click', function() { 418 if (typeof window.cmplz_accepted_categories === 'function') { 419 setTimeout(function() { 420 var accepted = window.cmplz_accepted_categories(); 421 if ($.isArray(accepted) && accepted.indexOf('marketing') > -1) { 422 afterConsentToggled(true); 423 } 424 }, 1000); 425 } else { 426 triggerAfterConsent(); 427 } 428 }); 429 430 // Complianz events. 431 $(document).on('cmplzEnableScripts', function(event) { 432 if (event.detail === 'marketing') { 433 afterConsentToggled(true); 434 } 435 }); 436 437 $(document).on('cmplzFireCategories', function(event) { 438 if (event.detail && event.detail.category === 'marketing') { 439 afterConsentToggled(true); 440 } 441 }); 442 443 // Borlabs Cookie by Borlabs. 444 $(document).on('borlabs-cookie-consent-saved', function() { 445 triggerAfterConsent(); 446 }); 447 448 // Real Cookie Banner by devowl.io. 449 if (typeof window.consentApi !== 'undefined') { 450 window.consentApi.consent('easy-social-feed').then(function() { 451 triggerAfterConsent(); 452 }).catch(function() { 453 // Ignore errors from consentApi. 454 }); 455 } 456 457 // Moove GDPR Popup. 458 $('.moove-gdpr-infobar-allow-all').on('click', function() { 459 triggerAfterConsent(); 460 }); 461 462 // WPConsent events. 463 if (typeof window.addEventListener !== 'undefined') { 464 window.addEventListener('wpconsent_consent_saved', function() { 465 setTimeout(function() { 466 if (typeof window.WPConsent !== 'undefined') { 467 afterConsentToggled(window.WPConsent.hasConsent('marketing')); 468 } 469 }, 1000); 470 }); 471 472 window.addEventListener('wpconsent_consent_updated', function() { 473 setTimeout(function() { 474 if (typeof window.WPConsent !== 'undefined') { 475 afterConsentToggled(window.WPConsent.hasConsent('marketing')); 476 } 477 }, 1000); 478 }); 479 } 480 }); 481 482 // Event listeners for consent changes (examples). 483 if (typeof window.addEventListener !== 'undefined') { 484 // WPConsent. 485 window.addEventListener('wpconsent_consent_saved', function() { 486 setTimeout(function() { 487 if (typeof window.WPConsent !== 'undefined') { 488 afterConsentToggled(window.WPConsent.hasConsent('marketing')); 489 } 490 }, 1000); 491 }); 492 493 window.addEventListener('wpconsent_consent_updated', function() { 494 setTimeout(function() { 495 if (typeof window.WPConsent !== 'undefined') { 496 afterConsentToggled(window.WPConsent.hasConsent('marketing')); 497 } 498 }, 1000); 499 }); 500 } 501 502 // Complianz. 503 $(document).on('cmplzEnableScripts', function(event) { 504 if (event.detail === 'marketing') { 505 afterConsentToggled(true); 506 } 507 }); 508 509 // Borlabs Cookie. 510 $(document).on('borlabs-cookie-consent-saved', function() { 511 afterConsentToggled(true); 512 }); 513 514 // Real Cookie Banner. 515 if (typeof window.consentApi !== 'undefined') { 516 window.consentApi.consent('easy-social-feed').then(function() { 517 setTimeout(function() { 518 afterConsentToggled(true); 519 }, 1000); 520 }); 521 } 522 523 // Moove Agency. 524 $(document).on('click', '.moove-gdpr-infobar-allow-all', function() { 525 setTimeout(function() { 526 afterConsentToggled(true); 527 }, 1000); 528 }); 529 530 // Expose functions globally for potential module-specific scripts. 531 window.ESFGDPR = { 532 checkConsent: checkConsent, 533 enableFullFeatures: enableFullFeatures, 534 afterConsentToggled: afterConsentToggled 535 }; 536 537})(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.