'; } function wireButton(f) { var doc; try { doc = f.contentDocument; } catch (e) { return; } if (!doc || !(f.hasAttribute('data-consentinel-src') || f.hasAttribute('data-consentinel-placeholder'))) return; doc.addEventListener('click', function (e) { var b = e.target && e.target.closest && e.target.closest('[data-consentinel-allow]'); if (!b) return; document.dispatchEvent(new CustomEvent('consentinel:embed-allow', { detail: { category: b.getAttribute('data-consentinel-allow') } })); }); } function blockFrame(f, rule, src) { f.setAttribute('data-consentinel-blocked', rule.id); // A frame that already carries srcdoc never fetched its src (srcdoc // wins), so there is nothing to hold and no placeholder to draw. if (f.hasAttribute('srcdoc')) { try { f.removeAttribute('src'); } catch (e) {} return; } f.setAttribute('data-consentinel-src', src); try { f.removeAttribute('src'); } catch (e) {} var reachable = frameReachable(f); if (reachable && !f.__cxWired) { f.__cxWired = true; f.addEventListener('load', function () { wireButton(f); }); } f.setAttribute('srcdoc', placeholderDoc(rule, reachable)); } function releaseFrame(f) { var src = f.getAttribute('data-consentinel-src'); f.removeAttribute('data-consentinel-src'); f.removeAttribute('data-consentinel-blocked'); // Order matters: While srcdoc is present it wins over src, so the // placeholder must go first or the embed never loads. f.removeAttribute('srcdoc'); if (src) { f.setAttribute('src', src); } } // Script-built embeds (Elementor's Video widget builds a YouTube player // from the IFrame API; Calendly's inline widget builds its frame from // widget.js) have NO iframe while their script is held, so blockFrame() // never runs and the visitor would see an empty box. Rules may name the // CONTAINER such a widget renders into; while the rule blocks, the // container gets the same placeholder in a frame of its own. function placeContainers(rule) { if (!rule || !rule.containers || !rule.containers.length || !document.querySelectorAll) return; var run = function () { if (!shouldBlock(rule)) return; for (var i = 0; i < rule.containers.length; i++) { var boxes; try { boxes = document.querySelectorAll(rule.containers[i]); } catch (e) { continue; } for (var j = 0; j < boxes.length; j++) { var box = boxes[j]; if (box.querySelector('iframe')) continue; // already has a frame (ours, or a held one) var ph = nativeCreate('iframe'); nativeSetAttribute.call(ph, 'data-consentinel-placeholder', rule.id); nativeSetAttribute.call(ph, 'title', rule.name || EMBED.fallback || ''); ph.style.cssText = 'display:block;width:100%;height:100%;min-height:220px;border:0;'; ph.addEventListener('load', function () { wireButton(this); }); nativeSetAttribute.call(ph, 'srcdoc', placeholderDoc(rule, true)); box.appendChild(ph); } } }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', run); } else { run(); } } function removeReleasedPlaceholders() { var phs = document.querySelectorAll ? document.querySelectorAll('iframe[data-consentinel-placeholder]') : []; for (var i = 0; i < phs.length; i++) { var id = phs[i].getAttribute('data-consentinel-placeholder'); for (var r = 0; r < RULES.length; r++) { if (RULES[r].id === id && !shouldBlock(RULES[r])) { phs[i].parentNode.removeChild(phs[i]); break; } } } } // A loader the SERVER already gated (script_loader_tag, or output-buffer // gating) arrives as type="text/plain" data-consentinel-gated and never // passes through interceptScript()/neutralize(), so nothing above would // draw its container placeholder. Check once the document is parsed. document.addEventListener('DOMContentLoaded', function () { for (var r = 0; r < RULES.length; r++) { var rule = RULES[r]; if (!rule.containers || !shouldBlock(rule)) continue; if (document.querySelector('script[data-consentinel-gated="' + String(rule.id).replace(/["\\]/g, '') + '"]')) { placeContainers(rule); } } }); // Run on every consent change. Releases what is now allowed and — the // withdrawal half — empties a RUNNING embed whose category was just // denied, instead of leaving it live until banner.js reloads the page. function syncFrames() { removeReleasedPlaceholders(); var frames = document.getElementsByTagName('iframe'); for (var i = 0; i < frames.length; i++) { var f = frames[i]; if (f.hasAttribute('data-consentinel-placeholder')) continue; var held = f.getAttribute('data-consentinel-src'); if (held) { if (!shouldBlock(ruleForUrl(held))) { releaseFrame(f); } continue; } var live = f.getAttribute('src'); var rule = ruleForUrl(live); if (shouldBlock(rule)) { blockFrame(f, rule, live); } } } if (window.MutationObserver) { var mo = new MutationObserver(function (muts) { for (var i = 0; i < muts.length; i++) { var added = muts[i].addedNodes; if (muts[i].type === 'attributes') { // A src assigned to a frame ALREADY in the page — lazy-load // plugins swap data-src → src on scroll. Our own release sets // src too, but by then the rule no longer blocks, so this is a // no-op for it. var t = muts[i].target; if (t && t.tagName === 'IFRAME' && !t.hasAttribute('data-consentinel-placeholder')) { neutralize(t); } continue; } for (var j = 0; j < added.length; j++) { neutralize(added[j]); } } }); try { mo.observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] }); } catch (e) {} } // ---- text/plain activation (manual tagging path) -------------------- function activate(cat) { var nodes = document.querySelectorAll('script[type="text/plain"][data-consent="' + cat + '"]'); nodes.forEach(function (node) { var fresh = nativeCreate('script'); for (var i = 0; i < node.attributes.length; i++) { var a = node.attributes[i]; if (a.name === 'type' || a.name === 'data-consent') continue; fresh.setAttribute(a.name, a.value); } if (node.src) { fresh.src = node.src; } else { fresh.text = node.text; } node.parentNode.replaceChild(fresh, node); }); } // ---- release deferred 'until' scripts once consent is given --------- function releaseDeferred() { var still = []; deferred.forEach(function (d) { if (shouldBlock(d.rule)) { still.push(d); return; } var fresh = nativeCreate('script'); var el = d.el; for (var i = 0; i < el.attributes.length; i++) { var a = el.attributes[i]; if (a.name === 'type' || a.name === 'src' || a.name === 'data-consentinel-blocked') continue; fresh.setAttribute(a.name, a.value); } fresh.src = d.src; // native element => loads normally now that it's allowed var parent = el.parentNode || document.head || document.documentElement; parent.appendChild(fresh); if (el.parentNode) { el.parentNode.removeChild(el); } }); deferred = still; } window.Consentinel.apply = function (state) { current = state || current; window.Consentinel.state = current; Object.keys(current).forEach(function (cat) { if (current[cat]) activate(cat); }); releaseDeferred(); syncFrames(); document.dispatchEvent(new CustomEvent('consentinel:applied', { detail: current })); }; // Auto-apply whatever consent already exists on page load. if (current && Object.keys(current).length) { document.addEventListener('DOMContentLoaded', function () { window.Consentinel.apply(current); }); } })();

Rialto Capital

Investing in real estate properties, loans, and securities throughout the capital structure