(() => { const labelSlots = () => { document.querySelectorAll('.AdvallyTag').forEach(el => { if (el.dataset.advDevLabeled) return; const classes = [...el.classList].filter(c => c !== 'AdvallyTag' && c !== 'v2'); el.textContent = 'ADVALLY TEST \u2014 ' + (classes.join(' ') || 'Ad Slot'); el.dataset.advDevLabeled = '1'; }); const placeholders = { '__ADVvideoPlaceholder': 'Video Player', '__ADVrecirculationPlaceholder': 'Recirculation Widget', '__ADVquizPlaceholder': 'Quiz Widget' }; Object.entries(placeholders).forEach(([id, label]) => { const el = document.getElementById(id); if (el && !el.dataset.advDevLabeled) { el.textContent = 'ADVALLY TEST \u2014 ' + label; el.dataset.advDevLabeled = '1'; } }); }; if (document.readyState === 'complete') { labelSlots(); } else { window.addEventListener('load', labelSlots); } if (typeof XF !== 'undefined' && typeof XF.on === 'function') { XF.on(document, 'ajax:complete', labelSlots); } })(); {{ phrase('advally_guest_adhesion_message') }} (() => { // rules.js defines advally.scanNew; guard every call so a slow // or blocked CDN load can't throw "advally.scanNew is not a function". var advScanNew = function() { if (typeof advally !== 'undefined' && typeof advally.scanNew === 'function') { advally.scanNew(); } }; if (XF && typeof XF.on == 'function') { // Handle AJAX-loaded content XF.on(document, 'ajax:complete', ({ data }) => { advScanNew(); }); // XF 2.3 fix: Re-scan after page fully loads to ensure // lazy loading is properly initialized for below-fold ads if (document.readyState === 'complete') { setTimeout(advScanNew, 100); } else { window.addEventListener('load', () => { setTimeout(advScanNew, 100); }); } } })(); (() => { if (!window.XF || !XF.History || typeof XF.History.push !== 'function') return; if (XF.History.push.__advallyLightboxGuarded) return; // idempotent, never double-wrap var origPush = XF.History.push; var isUndefinedUrl = function(url) { if (!url) return true; var s = String(url); return s === 'undefined' || /\/undefined$/.test(s); }; var guardedPush = function(state, title, url) { // XF core calls XF.History.push unconditionally when lbHistory is set; // it does NOT gate the pushState on a [data-fancybox-nw] toolbar button // existing. A default toolbar (zoom/fullscreen/close, no nw button) still // reaches this call, so this guard must not require nw either or it misses // exactly the configs where the bug is worst. nw is used best-effort for the // cosmetic href cleanup only. if (isUndefinedUrl(url)) { // Counter + console marker: separates "guard installed and suppressed a // bad url" from "guard never installed". Both states otherwise look // identical from outside. window.__advallyLightboxGuardFired = (window.__advallyLightboxGuardFired || 0) + 1; console.debug('[advally] lightbox history guard: skipped pushState for /undefined url', url); // Same defect writes "undefined" onto this same element's // href in the same code path, just before this call fires — // clean it up if a toolbar happens to be present. var nw = document.querySelector('.fancybox__toolbar [data-fancybox-nw]'); if (nw && nw.getAttribute('href') === 'undefined') { nw.removeAttribute('href'); } return; // skip the pushState — this is the fix } return origPush.call(this, state, title, url); }; guardedPush.__advallyLightboxGuarded = true; XF.History.push = guardedPush; // SECOND INSTALL PATH: the native primitive. Wrapping XF.History.push // only covers callers that route THROUGH XenForo's history API. The core // lightbox also calls window.history.pushState DIRECTLY, and those calls // never reach the wrapper above - measured live with the wrapper installed // and firing while the bad urls kept being minted. The emitter is core // code and must not be forked, so the guard has to cover the primitive. if (window.history && typeof window.history.pushState === 'function' && !window.history.pushState.__advallyLightboxGuarded) { var origNative = window.history.pushState; // DELIBERATELY NARROWER THAN isUndefinedUrl ABOVE, and it must stay that // way. pushState's url argument is optional - omitting it, or passing // undefined/null, legally means "keep the current url". Reusing the falsy // test here would swallow every legitimate no-url pushState on the page // and break real navigation. Only the string shapes actually navigate // somewhere bad, so only they are refused. var isUndefinedUrlString = function(url) { if (url === undefined || url === null) return false; var s = String(url); return s === 'undefined' || /\/undefined$/.test(s); }; var guardedNative = function(state, title, url) { if (isUndefinedUrlString(url)) { window.__advallyLightboxGuardFired = (window.__advallyLightboxGuardFired || 0) + 1; // Separate counter so a readout can tell WHICH path fired. The shared // counter alone cannot distinguish a suppressed framework call from a // suppressed native one, and that distinction is the whole diagnosis. window.__advallyLightboxGuardFiredNative = (window.__advallyLightboxGuardFiredNative || 0) + 1; console.debug('[advally] lightbox history guard: skipped native pushState for /undefined url', url); return; } // apply(this, arguments) rather than a fixed three-argument call: a // two-argument pushState must reach the original AS a two-argument call, // or we convert "keep the current url" into an explicit undefined. return origNative.apply(this, arguments); }; guardedNative.__advallyLightboxGuarded = true; window.history.pushState = guardedNative; } })();
enableSidebarShort
enableSidebarTall
{{ phrase('advally_guest_thread_first_message') }}
container_sidenav_above
container_sidenav_below
forum_overview_top
forum_overview_bottom
forum_view_above_node_list
forum_view_below_node_list
forum_view_above_thread_list
forum_view_below_stickies
forum_view_below_thread_list
thread_view_above_messages
thread_view_below_messages
post_below_content {{$post}}
post_above_content
{{ dump_simple($array) }}