PageSourceSearch

https://repjesus.com/build/js/legacy-runtime.js?v=1790297419360

js repjesus.com collected 2026-09-25 11:38:41 UTC 26,595 bytes, 823 lines download raw bytes

1import { router } from '@inertiajs/vue3';
2import { initializeListing } from './listing-runtime.js?v=1790297419360';
3import { hideSiteLoader, hideSiteLoaderWhenReady, scheduleSiteLoader } from './site-loader.js?v=1790297419360';
4import { idlePrefetchLinks, trackAsyncVisitEnd, trackAsyncVisitStart } from './nav-prefetch.js?v=1790297419360';
5
6const initialized = new WeakSet();
7const pageTitleSentinels = new WeakMap();
8let currentPlayerState = {};
9const viewedNotificationsKey = 'repJesusViewedNotifications';
10
11if ('scrollRestoration' in window.history) {
12    window.history.scrollRestoration = 'manual';
13}
14
15// Global SPA navigation helper for the Android WebView bridge.
16// Uses Inertia's router so the media player and app state persist across
17// navigations (no full page reload). Falls back to location.href if
18// Inertia isn't ready yet (e.g. initial load).
19window.repJesusNavigate = (path) => {
20    try {
21        const url = path || '/';
22        // Cancel any in-flight navigation before starting a new one
23        try { router.cancelAll({ async: false }); } catch (_) {}
24        router.visit(url, { preserveScroll: false, preserveState: false });
25    } catch (e) {
26        window.location.href = path || '/';
27    }
28};
29
30const markBackNavigation = () => {
31    const pageKey = `${window.location.pathname.replace(/\/$/, '')}${window.location.search}`;
32    itemContentScrollPending = true;
33    window.repJesusRestoreListingState = true;
34    sessionStorage.setItem('repJesusRestoreListingState', '1');
35    sessionStorage.setItem('repJesusRestoreListingPage', pageKey);
36};
37
38window.repJesusMarkBackNavigation = markBackNavigation;
39window.addEventListener('popstate', markBackNavigation, { capture: true });
40
41document.addEventListener('click', (event) => {
42    const link = event.target.closest('a[data-notification-view]');
43    if (!link) return;
44
45    const notificationId = Number(link.dataset.notificationId || 0);
46    if (notificationId) {
47        try {
48            const viewed = new Set(JSON.parse(sessionStorage.getItem(viewedNotificationsKey) || '[]').map(Number).filter(Boolean));
49            viewed.add(notificationId);
50            sessionStorage.setItem(viewedNotificationsKey, JSON.stringify(Array.from(viewed)));
51        } catch {
52            sessionStorage.setItem(viewedNotificationsKey, JSON.stringify([notificationId]));
53        }
54        window.dispatchEvent(new CustomEvent('repjesus:notification-viewed', {
55            detail: { id: notificationId },
56        }));
57    }
58    link.closest('li.active')?.classList.remove('active');
59}, true);
60
61// Prevent loader for hash-only navigation
62document.addEventListener('click', (event) => {
63    const link = event.target.closest('a[href^="#"]');
64    if (link) {
65        event.preventDefault();
66        const hash = link.getAttribute('href');
67        history.replaceState(null, null, hash);
68        hideSiteLoader();
69
70        // Manually scroll to the hash element
71        const targetId = hash.substring(1);
72        const targetElement = document.getElementById(targetId);
73        if (targetElement) {
74            targetElement.scrollIntoView({ behavior: 'smooth' });
75        }
76    }
77}, true);
78
79document.addEventListener('click', (event) => {
80    const link = event.target.closest('a[href]');
81
82    if (
83        link
84        && link.closest('#postswrapper, #collectionitems')
85        && !link.getAttribute('href')?.startsWith('#')
86        && !link.getAttribute('href')?.startsWith('javascript:')
87        && link.origin === window.location.origin
88        && !link.matches('[data-login-required], [data-add-to-collection], [data-add-genre], [data-profile-follow], [data-like-id]')
89    ) {
90        const targetUrl = new URL(link.href);
91        const targetKey = `${targetUrl.pathname.replace(/\/$/, '')}${targetUrl.search}`;
92
93        if (link.matches('[data-post-link]')) {
94            window.repJesusLoadMoreFreeze?.();
95        } else {
96            sessionStorage.setItem('repJesusSuppressListingRestore', targetKey);
97            sessionStorage.removeItem('repJesusRestoreListingState');
98            sessionStorage.removeItem('repJesusRestoreListingPage');
99            window.repJesusRestoreListingState = false;
100        }
101        return;
102    }
103
104    if (
105        !link
106        || link.classList.contains('back')
107        || link.origin !== window.location.origin
108        || link.getAttribute('href')?.startsWith('#')
109        || link.getAttribute('href')?.startsWith('javascript:')
110        || link.matches('[data-fancybox], [data-login-required], [data-add-to-collection], [data-add-genre], [data-profile-follow], [data-like-id]')
111    ) {
112        return;
113    }
114
115    const targetUrl = new URL(link.href);
116    const targetKey = `${targetUrl.pathname.replace(/\/$/, '')}${targetUrl.search}`;
117    sessionStorage.setItem('repJesusSuppressListingRestore', targetKey);
118    sessionStorage.removeItem('repJesusRestoreListingState');
119    sessionStorage.removeItem('repJesusRestoreListingPage');
120    window.repJesusRestoreListingState = false;
121}, true);
122
123window.addEventListener('repjesus:like-changed', (event) => {
124    const id = Number(event.detail?.id);
125    if (!id) return;
126
127    document.querySelectorAll(`[data-like-id="${id}"] h3`).forEach((icon) => {
128        icon.classList.toggle('like', !event.detail.liked);
129        icon.classList.toggle('unlike', Boolean(event.detail.liked));
130        icon.querySelector('i')?.classList.toggle('far', !event.detail.liked);
131        icon.querySelector('i')?.classList.toggle('fas', Boolean(event.detail.liked));
132    });
133});
134
135window.addEventListener('repjesus:player-loading', (event) => {
136    const id = Number(event.detail?.id || 0);
137    if (!id) return;
138
139    document.querySelectorAll(`[data-play-id="${id}"]`).forEach((button) => {
140        if (event.detail?.loading === false) {
141            if (
142                Number(currentPlayerState.track?.id || 0) === id
143                && currentPlayerState.transitioning
144                && !currentPlayerState.playing
145            ) {
146                return;
147            }
148            button.classList.remove('loading');
149            if (!button.classList.contains('playing')) {
150                const icon = button.dataset.playAlbum ? 'fa-forward' : 'fa-play';
151                button.innerHTML = `<i class="fas ${icon}"></i>`;
152            }
153            return;
154        }
155
156        button.classList.add('loading');
157        button.innerHTML = '<span class="play-loading-dots" aria-hidden="true"><i></i><i></i><i></i></span>';
158    });
159});
160
161const updateLegacyPlayButtons = (state = {}) => {
162    const activeTrackId = Number(state.track?.id || 0);
163    const isPlaying = Boolean(state.active && state.playing && activeTrackId);
164
165    document.querySelectorAll('[data-play-id]').forEach((button) => {
166        const buttonTrackId = Number(button.dataset.playId || 0);
167        const transitioning = Boolean(state.active && state.transitioning && buttonTrackId === activeTrackId);
168        const active = isPlaying && buttonTrackId === activeTrackId;
169        if (transitioning && !active) {
170            button.classList.add('loading');
171            button.classList.remove('playing');
172            button.setAttribute('title', `Loading ${button.dataset.playTitle || ''}`.trim());
173            button.innerHTML = '<span class="play-loading-dots" aria-hidden="true"><i></i><i></i><i></i></span>';
174            return;
175        }
176        button.classList.toggle('playing', active);
177        button.classList.remove('loading');
178        button.setAttribute('title', `${active ? 'Stop' : 'Play'} ${button.dataset.playTitle || ''}`.trim());
179        const playIcon = button.dataset.playAlbum ? 'fa-forward' : 'fa-play';
180        button.innerHTML = `<i class="fas ${active ? 'fa-stop' : playIcon}"></i>`;
181    });
182};
183
184window.addEventListener('repjesus:player-state', (event) => {
185    currentPlayerState = event.detail || {};
186    updateLegacyPlayButtons(event.detail || {});
187});
188
189window.addEventListener('repjesus:track-unavailable', (event) => {
190    const id = Number(event.detail?.id);
191    if (!id) return;
192
193    document.querySelectorAll(`[data-play-id="${id}"]`).forEach((button) => {
194        const item = button.closest('.postitem');
195        if (!item) return;
196
197        item.style.opacity = '0';
198        window.setTimeout(() => {
199            item.remove();
200            window.msnry?.reloadItems?.();
201            window.msnry?.layout?.();
202        }, 250);
203    });
204});
205
206const updatePageTitleStickyState = () => {
207    document.querySelectorAll('.pagetitle').forEach((pageTitle) => {
208        const sentinel = pageTitleSentinels.get(pageTitle);
209
210        if (!sentinel) {
211            return;
212        }
213
214        pageTitle.classList.toggle('sticky', sentinel.getBoundingClientRect().top <= 70);
215    });
216};
217
218const initializePageTitleStickyState = () => {
219    document.querySelectorAll('.pagetitle').forEach((pageTitle) => {
220        if (pageTitleSentinels.has(pageTitle)) {
221            return;
222        }
223
224        const sentinel = document.createElement('span');
225        sentinel.className = 'pagetitle-sticky-sentinel';
226        sentinel.setAttribute('aria-hidden', 'true');
227        sentinel.style.cssText = 'display:block;width:100%;height:0;pointer-events:none;';
228        pageTitle.before(sentinel);
229        pageTitleSentinels.set(pageTitle, sentinel);
230    });
231
232    updatePageTitleStickyState();
233};
234
235const initializeFancybox = () => {
236    const $ = window.jQuery;
237
238    if (!$?.fn?.fancybox) {
239        return;
240    }
241
242    $('[data-fancybox]').each(function initializePopup() {
243        const element = this;
244
245        if (initialized.has(element)) {
246            return;
247        }
248
249        initialized.add(element);
250        $(element).fancybox({
251            infobar: false,
252            buttons: ['close'],
253        });
254    });
255};
256
257const initializeCarousels = () => {
258    const $ = window.jQuery;
259
260    if (!$?.fn?.slick) {
261        return;
262    }
263
264    $('.carousel:not(.item-gallery):not(.slick-initialized)').slick({
265        dots: true,
266        infinite: true,
267        speed: 1000,
268        slidesToShow: 1,
269        autoplay: false,
270        arrows: false,
271        pauseOnHover: true,
272        adaptiveHeight: true,
273    });
274};
275
276const tickerStates = [];
277let tickerFrame = null;
278let tickerTime = 0;
279
280const animateTickers = (time) => {
281    const delta = tickerTime ? (time - tickerTime) / 1000 : 0;
282    tickerTime = time;
283
284    for (let index = tickerStates.length - 1; index >= 0; index -= 1) {
285        const state = tickerStates[index];
286
287        if (!state.row.isConnected) {
288            tickerStates.splice(index, 1);
289            continue;
290        }
291
292        if (!state.width) {
293            state.width = state.track.scrollWidth / 2;
294        }
295
296        if (!state.paused && state.width) {
297            state.position -= state.speed * delta;
298
299            if (Math.abs(state.position) >= state.width) {
300                state.position = 0;
301            }
302
303            state.track.style.transform = `translateX(${state.position}px)`;
304        }
305    }
306
307    tickerFrame = tickerStates.length ? window.requestAnimationFrame(animateTickers) : null;
308};
309
310const initializeTickers = () => {
311    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
312        return;
313    }
314
315    document.querySelectorAll('.ticker-row').forEach((row, index) => {
316        if (tickerStates.some((state) => state.row === row)) {
317            return;
318        }
319
320        const track = row.querySelector('.ticker-track');
321        const items = track?.querySelector('.ticker-items:not([aria-hidden="true"])');
322
323        if (!track || !items) {
324            return;
325        }
326
327        track.querySelectorAll('.ticker-items[aria-hidden="true"]').forEach((clone) => clone.remove());
328        track.style.transform = '';
329
330        const clone = items.cloneNode(true);
331        clone.setAttribute('aria-hidden', 'true');
332        track.appendChild(clone);
333
334        const state = {
335            row,
336            track,
337            position: 0,
338            speed: 80 + index * 25,
339            paused: false,
340            width: 0,
341        };
342
343        row.addEventListener('mouseenter', () => {
344            state.paused = true;
345        });
346        row.addEventListener('mouseleave', () => {
347            state.paused = false;
348        });
349        tickerStates.push(state);
350    });
351
352    if (tickerStates.length && !tickerFrame) {
353        tickerTime = 0;
354        tickerFrame = window.requestAnimationFrame(animateTickers);
355    }
356};
357
358let itemContentScrollPending = true;
359
360const scrollToItemContent = () => {
361    if (!itemContentScrollPending || window.location.hash) {
362        return;
363    }
364
365    itemContentScrollPending = false;
366
367    const item = document.querySelector('.contentWrap .row.item');
368    const target = item?.closest('.contentWrap');
369
370    if (!target) {
371        return;
372    }
373
374    const offset = target.getBoundingClientRect().top + window.scrollY - 300;
375    window.scrollTo({ top: Math.max(offset, 0), behavior: 'smooth' });
376};
377
378let legacyPageInitializationFrame = null;
379
380const initializeLegacyPage = () => {
381    window.cancelAnimationFrame(legacyPageInitializationFrame);
382    legacyPageInitializationFrame = window.requestAnimationFrame(() => {
383        legacyPageInitializationFrame = null;
384        initializeListing();
385        initializeFancybox();
386        initializeCarousels();
387        initializeTickers();
388        initializePageTitleStickyState();
389
390        window.requestAnimationFrame(scrollToItemContent);
391    });
392};
393
394const isTrendingVisit = (event) => {
395    const visitUrl = event?.detail?.visit?.url;
396
397    if (!visitUrl || !window.location.pathname.startsWith('/trending')) {
398        return false;
399    }
400
401    try {
402        return new URL(visitUrl, window.location.origin).pathname.startsWith('/trending');
403    } catch {
404        return false;
405    }
406};
407
408router.on('before', (event) => {
409    if (event.detail.visit.prefetch) {
410        return;
411    }
412
413    if (event.detail.visit.async) {
414        trackAsyncVisitStart();
415    }
416
417    itemContentScrollPending = true;
418
419    if (window.repJesusSkipNextLoader || isTrendingVisit(event)) {
420        hideSiteLoader();
421        return;
422    }
423
424    if (event.detail.visit.only?.length) {
425        hideSiteLoader();
426        return;
427    }
428
429    const currentUrl = window.location.href.split('#')[0];
430    const targetUrl = event.detail.visit.url?.href?.split('#')[0];
431
432    if (currentUrl === targetUrl) {
433        hideSiteLoader();
434        return;
435    }
436
437    window.repJesusLoadMoreSave?.();
438    sessionStorage.setItem('repJesusInertiaNavigation', '1');
439    scheduleSiteLoader();
440});
441
442const hideChat = () => {
443    document.body.classList.add('rj-chat-hidden');
444
445    if (!window.tidioChatApi) {
446        return;
447    }
448
449    window.tidioChatApi.hide();
450};
451
452const initializeChat = () => {
453    hideChat();
454    window.tidioChatApi?.on('close', hideChat);
455};
456
457let previousScroll = window.scrollY;
458
459const handleScroll = () => {
460    const currentScroll = window.scrollY;
461    const scrollingDown = currentScroll > previousScroll && currentScroll > 80;
462
463    document.body.classList.toggle('scroll-down', scrollingDown);
464    document.body.classList.toggle('scroll-up', !scrollingDown);
465    document.querySelectorAll('.rj-player-shell').forEach((el) => {
466        el.classList.toggle('scroll-down', scrollingDown);
467    });
468    updatePageTitleStickyState();
469    previousScroll = Math.max(currentScroll, 0);
470};
471
472document.addEventListener('click', (event) => {
473    const backLink = event.target.closest('a.back');
474
475    if (
476        !backLink
477        || event.button !== 0
478        || event.metaKey
479        || event.ctrlKey
480        || event.shiftKey
481        || event.altKey
482    ) {
483        return;
484    }
485
486    event.preventDefault();
487    event.stopImmediatePropagation();
488    scheduleSiteLoader();
489
490    if (window.history.length > 1) {
491        markBackNavigation();
492        window.history.back();
493    } else {
494        router.visit('/');
495    }
496}, true);
497
498document.addEventListener('click', (event) => {
499    if (event.defaultPrevented) {
500        return;
501    }
502
503    const loginRequired = event.target.closest('[data-login-required]');
504
505    if (loginRequired) {
506        event.preventDefault();
507        hideSiteLoader();
508        window.dispatchEvent(new CustomEvent('repjesus:login-required', {
509            detail: { redirectTo: window.location.pathname + window.location.search },
510        }));
511        return;
512    }
513
514    const notificationDeleteLink = event.target.closest('[data-delete-notification]');
515
516    if (notificationDeleteLink) {
517        event.preventDefault();
518
519        const notification = notificationDeleteLink.dataset.deleteNotification;
520        const token = document.querySelector('meta[name="csrf-token"]')?.content || '';
521
522        fetch(`/notifications/${notification}`, {
523            method: 'DELETE',
524            headers: {
525                Accept: 'application/json',
526                'X-CSRF-TOKEN': token,
527            },
528        }).then((response) => {
529            if (!response.ok) {
530                return;
531            }
532
533            notificationDeleteLink.closest('.postitem')?.remove();
534
535            const list = document.querySelector('#postswrapper');
536            if (list && !list.querySelector('.postitem')) {
537                document.querySelector('.notifications-empty')?.classList.add('active');
538            }
539
540            router.reload({
541                only: ['legacyAuth'],
542                preserveScroll: true,
543            });
544        });
545        return;
546    }
547
548    const profileFollowLink = event.target.closest('[data-profile-follow]');
549
550    if (profileFollowLink) {
551        event.preventDefault();
552
553        if (profileFollowLink.dataset.processing === 'true') return;
554
555        const profile = profileFollowLink.dataset.profileFollow;
556        const token = document.querySelector('meta[name="csrf-token"]')?.content || '';
557        const previous = profileFollowLink.textContent;
558        profileFollowLink.dataset.processing = 'true';
559        profileFollowLink.textContent = 'Processing...';
560
561        fetch(`/profile/${encodeURIComponent(profile)}/follow`, {
562            method: 'POST',
563            headers: {
564                Accept: 'application/json',
565                'Content-Type': 'application/json',
566                'X-CSRF-TOKEN': token,
567            },
568        })
569            .then((response) => response.ok ? response.json() : Promise.reject())
570            .then((data) => {
571                profileFollowLink.textContent = data.following ? 'Unfollow' : 'Follow';
572                profileFollowLink.classList.toggle('follow', Boolean(data.following));
573            })
574            .catch(() => {
575                profileFollowLink.textContent = previous;
576            })
577            .finally(() => {
578                profileFollowLink.dataset.processing = 'false';
579            });
580        return;
581    }
582
583    const loadedPlayButton = event.target.closest('.legacy-loaded-post [data-play-id]');
584
585    if (loadedPlayButton) {
586        event.preventDefault();
587
588        if (loadedPlayButton.classList.contains('playing')) {
589            window.dispatchEvent(new CustomEvent('repjesus:stop-player'));
590            return;
591        }
592
593        // Album play: load artist tracks as a playlist
594        const albumArtistIds = loadedPlayButton.dataset.playAlbum;
595        if (albumArtistIds) {
596            loadedPlayButton.classList.add('loading');
597            loadedPlayButton.innerHTML = '<span class="play-loading-dots" aria-hidden="true"><i></i><i></i><i></i></span>';
598
599            let context = {};
600            try {
601                context = JSON.parse(document.querySelector('#postswrapper')?.dataset.playerContext || '{}');
602            } catch (error) {
603                context = {};
604            }
605
606            window.dispatchEvent(new CustomEvent('repjesus:play-all', {
607                detail: {
608                    url: `/api/album/${albumArtistIds}/tracks`,
609                    context: { ...context, scope: 'album' },
610                    autoplay: true,
611                },
612            }));
613            return;
614        }
615
616        loadedPlayButton.classList.add('loading');
617        loadedPlayButton.innerHTML = '<span class="play-loading-dots" aria-hidden="true"><i></i><i></i><i></i></span>';
618
619        fetch(`/api/player/track/${loadedPlayButton.dataset.playId}`, {
620            headers: { Accept: 'application/json' },
621        })
622            .then((response) => response.json())
623            .then((data) => {
624                if (data.track) {
625                    let context = {};
626                    try {
627                        context = JSON.parse(document.querySelector('#postswrapper')?.dataset.playerContext || '{}');
628                    } catch (error) {
629                        context = {};
630                    }
631                    window.dispatchEvent(new CustomEvent('repjesus:play', {
632                        detail: { track: data.track, context, mode: 'single' },
633                    }));
634                }
635            })
636            .catch(() => {
637                loadedPlayButton.classList.remove('loading');
638                loadedPlayButton.innerHTML = '<i class="fas fa-play"></i>';
639            });
640        return;
641    }
642
643    const loadedLikeLink = event.target.closest('.legacy-loaded-post [data-like-id]');
644
645    if (loadedLikeLink) {
646        event.preventDefault();
647        if (loadedLikeLink.dataset.processing === '1') return;
648        loadedLikeLink.dataset.processing = '1';
649        const icon = loadedLikeLink.querySelector('h3');
650        icon?.classList.add('liking');
651        const token = document.querySelector('meta[name="csrf-token"]')?.content || '';
652
653        fetch(`/posts/${loadedLikeLink.dataset.likeId}/like`, {
654            method: 'POST',
655            headers: {
656                Accept: 'application/json',
657                'Content-Type': 'application/json',
658                'X-CSRF-TOKEN': token,
659            },
660        })
661            .then((response) => response.json())
662            .then((data) => {
663                icon?.classList.toggle('like', !data.liked);
664                icon?.classList.toggle('unlike', data.liked);
665                icon?.querySelector('i')?.classList.toggle('far', !data.liked);
666                icon?.querySelector('i')?.classList.toggle('fas', data.liked);
667                window.dispatchEvent(new CustomEvent('repjesus:like-changed', {
668                    detail: { id: Number(loadedLikeLink.dataset.likeId), ...data },
669                }));
670            })
671            .finally(() => {
672                icon?.classList.remove('liking');
673                loadedLikeLink.dataset.processing = '';
674            });
675        return;
676    }
677
678    const loadedLink = event.target.closest('#postswrapper a[href], #collectionitems a[href]');
679
680    if (
681        loadedLink
682        && loadedLink.origin === window.location.origin
683        && !loadedLink.getAttribute('href')?.startsWith('javascript:')
684        && !loadedLink.matches('[data-login-required], [data-add-to-collection], [data-add-genre], [data-profile-follow], [data-like-id], [data-notification-view]')
685    ) {
686        event.preventDefault();
687        if (loadedLink.matches('[data-notification-view]')) {
688            loadedLink.closest('li.active')?.classList.remove('active');
689        }
690        const targetUrl = new URL(loadedLink.href);
691        const targetKey = `${targetUrl.pathname.replace(/\/$/, '')}${targetUrl.search}`;
692
693        if (loadedLink.matches('[data-post-link]')) {
694            window.repJesusLoadMoreFreeze?.();
695        } else {
696            sessionStorage.setItem('repJesusSuppressListingRestore', targetKey);
697            sessionStorage.removeItem('repJesusRestoreListingState');
698            sessionStorage.removeItem('repJesusRestoreListingPage');
699            window.repJesusRestoreListingState = false;
700        }
701        router.visit(loadedLink.pathname + loadedLink.search + loadedLink.hash);
702        return;
703    }
704
705    const chatLink = event.target.closest('.livechat');
706
707    if (chatLink) {
708        event.preventDefault();
709
710        const openChat = () => {
711            document.body.classList.remove('rj-chat-hidden');
712            window.tidioChatApi?.show();
713            window.tidioChatApi?.open();
714        };
715
716        if (window.tidioChatApi) {
717            openChat();
718        } else {
719            document.addEventListener('tidioChat-ready', openChat, { once: true });
720        }
721
722        return;
723    }
724
725    const backLink = event.target.closest('a.back');
726
727    if (backLink) {
728        event.preventDefault();
729        markBackNavigation();
730        window.history.back();
731        return;
732    }
733
734    const topLink = event.target.closest('.topWrap .top');
735
736    if (topLink) {
737        event.preventDefault();
738        window.scrollTo({ top: 0, behavior: 'smooth' });
739    }
740});
741
742window.addEventListener('scroll', handleScroll, { passive: true });
743window.addEventListener('resize', updatePageTitleStickyState);
744if (window.tidioChatApi) {
745    window.tidioChatApi.on('ready', initializeChat);
746} else {
747    document.addEventListener('tidioChat-ready', initializeChat, { once: true });
748}
749router.on('finish', (event) => {
750    if (event.detail.visit?.prefetch) {
751        return;
752    }
753
754    if (event.detail.visit.async) {
755        trackAsyncVisitEnd();
756    }
757
758    if (window.repJesusSkipNextLoader || isTrendingVisit(event)) {
759        window.repJesusSkipNextLoader = false;
760        hideSiteLoader();
761        initializeLegacyPage();
762        idlePrefetchLinks();
763        return;
764    }
765
766    if (event.detail.visit.only?.length) {
767        hideSiteLoader();
768        return;
769    }
770
771    initializeLegacyPage();
772    hideSiteLoaderWhenReady();
773    idlePrefetchLinks();
774});
775router.on('cancel', (event) => {
776    if (event.detail?.visit?.prefetch) {
777        return;
778    }
779
780    if (event.detail?.visit?.async) {
781        trackAsyncVisitEnd();
782    }
783
784    window.repJesusSkipNextLoader = false;
785    hideSiteLoader();
786});
787router.on('navigate', (event) => {
788    if (event.detail.visit?.prefetch) {
789        return;
790    }
791
792    if (window.repJesusSkipNextLoader || isTrendingVisit(event)) {
793        hideSiteLoader();
794        return;
795    }
796
797    hideSiteLoaderWhenReady();
798});
799window.addEventListener('popstate', () => {
800    markBackNavigation();
801
802    if (window.location.pathname.startsWith('/trending')) {
803        hideSiteLoader();
804        initializeLegacyPage();
805        return;
806    }
807
808    scheduleSiteLoader();
809    initializeLegacyPage();
810    hideSiteLoaderWhenReady();
811});
812window.addEventListener('pageshow', (event) => {
813    if (event.persisted) {
814        initializeLegacyPage();
815        hideSiteLoaderWhenReady();
816    } else {
817        hideSiteLoader();
818    }
819});
820window.addEventListener('repjesus:masonry-ready', hideSiteLoaderWhenReady);
821hideSiteLoader();
822idlePrefetchLinks();
823initializeLegacyPage();

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.