PageSourceSearch

https://www.numarkcu.org/wp-content/themes/idea-numarkcu/library/js/page-banner.js

js numarkcu.org collected 2026-09-24 12:17:29 UTC 12,824 bytes, 312 lines download raw bytes

1jQuery( function($) {
2
3    /**
4     * Ad slides resolve to either the ad or the fallback within a bounded
5     * window, then lock that choice for good.
6     *
7     * Earlier version: fallback shown immediately, ad crossfaded in whenever
8     * it arrived — which could be several seconds later, and read as content
9     * getting swapped out from under the visitor rather than a deliberate
10     * design. This trades that for a short (AD_RESOLVE_TIMEOUT) pause where
11     * neither is visible, in exchange for guaranteeing nothing ever gets
12     * replaced once shown. _page_banner.scss keeps both faded out
13     * (opacity, not display) during the pause so the slide still holds the
14     * fallback image's height — no layout jump either way it resolves.
15     *
16     * Watch, rather than race: theme.delay-scripts.php holds most
17     * third-party scripts back until first interaction or a 5s timeout, and
18     * on touch devices there is no mousemove to trigger that early — but the
19     * ad script itself is explicitly excluded from that delay so it can
20     * still resolve inside this window. A MutationObserver reacts the
21     * moment its content arrives, with a fast interval as a backstop for
22     * content that changes size without mutating (e.g. an <img> finishing
23     * decode).
24     *
25     * The ad is the priority, not speed: if the first slide is still
26     * deciding, the slider holds autoplay there rather than rotating away
27     * from (or resolving to the fallback in place of) an ad that just needs
28     * a bit more time — see the holdAutoplay logic below. AD_RESOLVE_TIMEOUT
29     * is a generous upper bound for genuinely slow connections, matching
30     * theme.delay-scripts.php's own 5s allowance elsewhere; a real ad load
31     * measured around ~1.2s, so this is headroom, not the expected case.
32     * watchForBlockedAdNetwork() below is the one thing allowed to cut this
33     * short — waiting out the full timeout is pointless when the ad network
34     * is confirmed blocked rather than just slow.
35     */
36    var AD_RESOLVE_TIMEOUT = 5000;
37
38    var $adSliders  = $('section.page-banner .slides').filter( function() {
39        return $(this).find('.slide.has-ad-fallback').length > 0;
40    });
41
42    if ( $adSliders.length ) {
43
44        var resolvedSlides = new WeakSet();
45        var timedSlides     = new WeakSet();
46        var adObserver;
47
48        /**
49         * Locks a slide to whichever outcome resolves first — ad content
50         * detected, or the bounded wait running out. One-way and idempotent:
51         * once a slide has resolved, nothing here touches it again, so a
52         * late-arriving ad after a fallback timeout is simply ignored rather
53         * than swapping the visible content.
54         */
55        function resolveSlide( slide, outcome ) {
56
57            if ( resolvedSlides.has( slide ) ) {
58                return;
59            }
60
61            resolvedSlides.add( slide );
62            slide.classList.add( 'resolved-' + outcome );
63
64            if ( 'ad' === outcome ) {
65                slide.classList.add('ad-loaded'); // kept for anything else keyed to this class
66            }
67
68            /**
69             * Resolving changes the slide's height (whichever of the ad/
70             * fallback loses leaves the flow), so slick has to remeasure —
71             * otherwise the track keeps the old height and leaves a gap
72             * under the banner. Goes through the existing debounced resize
73             * handler below.
74             */
75            $( window ).trigger('resize');
76
77            // Lets the slick-init code (a separate block, run later) resume
78            // autoplay once whichever slide it's holding on has settled.
79            $( slide ).trigger('adslide:resolved');
80        }
81
82        /**
83         * Fast-fail: some browsers' built-in tracking prevention (confirmed
84         * on Microsoft Edge) let segmint.min.js itself load fine, then
85         * silently block its later calls to connect.segmint.net — the ones
86         * that actually decide and serve the ad. That failure never shows up
87         * as slowness we can measure; the script just never gets to inject
88         * anything, so every visitor it affects would otherwise sit out the
89         * full AD_RESOLVE_TIMEOUT for an ad that was never coming.
90         *
91         * Watches fetch, XHR, and plain <script>/<img> requests — it's not
92         * known which of these segmint uses for its own calls, and ad/beacon
93         * scripts commonly use any of the three — for an error targeting its
94         * domain, and resolves every still-pending ad slide to the fallback
95         * immediately rather than waiting. onBlocked is safe to call
96         * multiple times or after slides have already resolved; resolveSlide
97         * ignores anything already settled.
98         */
99        function watchForBlockedAdNetwork( adHostPattern, onBlocked ) {
100
101            var flagged = false;
102
103            function flag() {
104                if ( flagged ) { return; }
105                flagged = true;
106                onBlocked();
107            }
108
109            if ( window.fetch ) {
110
111                var origFetch = window.fetch;
112
113                window.fetch = function( input ) {
114
115                    var url = ( 'string' === typeof input ) ? input : ( input && input.url ) || '';
116
117                    return origFetch.apply( this, arguments ).catch( function( err ) {
118                        if ( adHostPattern.test( url ) ) { flag(); }
119                        throw err;
120                    });
121                };
122            }
123
124            var origOpen = XMLHttpRequest.prototype.open;
125
126            XMLHttpRequest.prototype.open = function( method, url ) {
127                if ( adHostPattern.test( url || '' ) ) {
128                    this.addEventListener( 'error', flag );
129                }
130                return origOpen.apply( this, arguments );
131            };
132
133            if ( window.MutationObserver ) {
134
135                new MutationObserver( function( mutations ) {
136
137                    mutations.forEach( function( mutation ) {
138
139                        Array.prototype.forEach.call( mutation.addedNodes || [], function( node ) {
140
141                            if ( 1 !== node.nodeType ) { return; }
142
143                            var els = ( 'SCRIPT' === node.tagName || 'IMG' === node.tagName ) ?
144                                [ node ] :
145                                ( node.querySelectorAll ? Array.prototype.slice.call( node.querySelectorAll('script[src], img[src]') ) : [] );
146
147                            els.forEach( function( el ) {
148
149                                var src = el.src || el.getAttribute('src') || '';
150
151                                if ( adHostPattern.test( src ) ) {
152                                    el.addEventListener( 'error', flag );
153                                }
154                            });
155                        });
156                    });
157
158                }).observe( document.documentElement, { childList: true, subtree: true } );
159            }
160        }
161
162        /**
163         * Re-run rather than resolved once, because two things arrive late
164         * and out of order: the ad script itself, and slick's clones of the
165         * slides. A clone taken before the ad landed carries an empty
166         * .slide-ad of its own and needs its own bounded wait — so this
167         * can't be a single global decision.
168         */
169        function syncAdSlides() {
170
171            $('.slide.has-ad-fallback').each( function() {
172
173                var slide = this;
174
175                if ( resolvedSlides.has( slide ) ) {
176                    return;
177                }
178
179                // Start this slide's bounded wait the first time it's seen.
180                if ( ! timedSlides.has( slide ) ) {
181
182                    timedSlides.add( slide );
183
184                    setTimeout( function() {
185                        resolveSlide( slide, 'fallback' );
186                    }, AD_RESOLVE_TIMEOUT );
187                }
188
189                var ad = $( slide ).children('.slide-ad')[0];
190
191                if ( ! ad ) {
192                    return;
193                }
194
195                /**
196                 * .slide-ad is stretched to fill the slide, so its own offsetHeight
197                 * is always non-zero and tells us nothing. Measure what the ad
198                 * injected instead — a container the script created but never
199                 * filled has no child with real height.
200                 */
201                var rendered = Array.prototype.some.call( ad.children, function( el ) {
202                    return el.offsetHeight > 0;
203                });
204
205                if ( rendered ) {
206                    resolveSlide( slide, 'ad' );
207                }
208            });
209        }
210
211        watchForBlockedAdNetwork( /segmint\.net/i, function() {
212
213            $('.slide.has-ad-fallback').each( function() {
214                resolveSlide( this, 'fallback' );
215            });
216        });
217
218        syncAdSlides();
219
220        if ( window.MutationObserver ) {
221
222            adObserver = new MutationObserver( syncAdSlides );
223
224            $adSliders.each( function() {
225                adObserver.observe( this, { childList: true, subtree: true } );
226            });
227        }
228
229        // Backstop for content that changes size without mutating the DOM,
230        // e.g. an <img> inside the ad finishing decode.
231        var adBackstop = setInterval( syncAdSlides, 200 );
232
233        // Every slide seen by now is resolved (ad detected, or its own
234        // timeout fired) well within this window; nothing left to watch for.
235        setTimeout( function() {
236            clearInterval( adBackstop );
237            if ( adObserver ) { adObserver.disconnect(); }
238        }, AD_RESOLVE_TIMEOUT + 2000 );
239    }
240
241    $('section.page-banner.type-slider').each( function() {
242
243        var pageSlider = $(this).find('.slides');
244        var pageSlides = pageSlider.find('.slide');
245
246        if ( pageSlides.length > 1 ) {
247
248            pageSlider.on( 'setPosition', function( slick ) {
249
250                // Check if screen width is above 768px (tablet size and above)
251                if (window.innerWidth > 768) {
252
253                    if ( typeof pageSlider.resizerQueue !== 'undefined' ) {
254                        clearTimeout( pageSlider.resizerQueue );
255                    }
256
257                    pageSlider.resizerQueue = setTimeout( function() {
258                        pageSlider.find('.slide').css( 'height', '' );
259                        var setHeight = pageSlider.find('.slick-track').height();
260                        pageSlides.height( setHeight );
261                    }, 200, pageSlider );
262                }
263            });
264
265            var settings = {
266                fade            : ( pageSlider.data('animation') == 'fade' ? true : false ),
267                dots            : Boolean( pageSlider.data('dots') ),
268                infinite        : Boolean( pageSlider.data('infinite') ),
269                arrows          : Boolean( pageSlider.data('arrows') ),
270                speed           : parseInt( pageSlider.data('speed') ),
271                autoplay        : Boolean( pageSlider.data('autoplay') ),
272                autoplaySpeed   : parseInt( pageSlider.data('autoplay-speed') ),
273                pauseOnHover    : parseInt( pageSlider.data('pause-on-hover') ),
274                adaptiveHeight  : (window.innerWidth <= 768)
275            }
276
277            /**
278             * The intent ad takes priority over the rotation schedule: if the
279             * first slide is still deciding between the ad and its fallback,
280             * don't let autoplay carry the visitor away from it (or resolve
281             * it to the fallback out of impatience) — hold here and start
282             * autoplay only once that slide has settled, whichever way.
283             */
284            var firstSlide = pageSlides.first();
285            var holdAutoplay = settings.autoplay
286                && firstSlide.hasClass('has-ad-fallback')
287                && ! firstSlide.is('.resolved-ad, .resolved-fallback');
288
289            if ( holdAutoplay ) {
290                settings.autoplay = false;
291            }
292
293            pageSlider.slick( settings );
294
295            if ( holdAutoplay ) {
296                firstSlide.one( 'adslide:resolved', function() {
297                    pageSlider.slick('slickPlay');
298                });
299            }
300
301            var resizeTimer;
302            $(window).on('resize orientationchange', function () {
303                clearTimeout(resizeTimer);
304                resizeTimer = setTimeout(function () {
305                var isMobile = window.innerWidth <= 768;
306                pageSlider.slick('slickSetOption', 'adaptiveHeight', isMobile, true);
307                pageSlider.slick('setPosition');
308                }, 150);
309            });
310        }
311    });
312});

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.