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