PageSourceSearch

https://117w.top/js/missav-hover-preview.js?v=2026081803

js 117w.top collected 2026-10-09 04:33:54 UTC 6,199 bytes, 132 lines download raw bytes

1(function () {
2    'use strict';
3
4    var invalidPoster = '/images/poster-invalid-55xcc.jpg';
5    var posterSelector = '.poster img,.thumb img,.video-card img,.vodlist_thumb,.vodlist_thumb img,.play_vlist_thumb img,.mgn-picture img,.video-img-box img,.img-box img,a[href*="/video"] img,a[href*="/play"] img,a[href*="vodplay"] img';
6
7    function isPosterImage(image) {
8        return image instanceof HTMLImageElement && image.matches(posterSelector);
9    }
10
11    document.addEventListener('error', function (event) {
12        var image = event.target;
13        if (!isPosterImage(image) || image.dataset.invalidPosterApplied === '1') return;
14        image.dataset.invalidPosterApplied = '1';
15        image.removeAttribute('srcset');
16        image.removeAttribute('sizes');
17        image.src = invalidPoster;
18    }, true);
19
20    var mobileMenuStyle = document.createElement('style');
21    mobileMenuStyle.textContent = '@media(max-width:950px){.main-nav.open,.main-nav.show,.site-header.nav-open .main-nav,.navbar-collapse.show,.mobile-nav.open,.mobile-nav.show,.nav-menu.open,.nav-menu.show,.main-menu.open,.main-menu.show,.offcanvas.show,.category-menu.open,.category-menu.show{padding-bottom:300px!important;scroll-padding-bottom:300px!important}}';
22    document.head.appendChild(mobileMenuStyle);
23
24    // Disable only on touch-only devices. Hybrid notebooks and desktop browsers
25    // do not always report `pointer: fine`, although they still emit mouse hover.
26    if (window.matchMedia('(hover: none) and (pointer: coarse)').matches) return;
27
28    var active = null;
29    var timer = 0;
30    var cardSelector = '[data-missav-preview],a.poster,a.thumb,a.vodlist_thumb,.atlas-card>a,.mgn-picture>a,.video-img>a,.position-relative>a,a[href]';
31
32    function decodeProxyUrl(value) {
33        var decoded = String(value || '');
34        for (var depth = 0; depth < 4; depth += 1) {
35            var match = decoded.match(/\/(?:base|resource)\/([A-Za-z0-9_=-]+)(?:\.cache|\/|$)/);
36            if (!match) break;
37            try {
38                var token = match[1].replace(/-/g, '+').replace(/_/g, '/');
39                while (token.length % 4) token += '=';
40                var next = atob(token);
41                if (!next || next === decoded) break;
42                decoded = next;
43            } catch (_) {
44                break;
45            }
46        }
47        return decoded;
48    }
49
50    function resolvePreview(container) {
51        if (container.dataset.missavPreview) return container.dataset.missavPreview;
52        if (container.dataset.preview && /\.mp4(?:$|\?)/i.test(container.dataset.preview)) {
53            return container.dataset.preview;
54        }
55        var image = container.querySelector('img');
56        if (!image) return '';
57        if (/^https?:\/\//i.test(image.dataset.mediabook || '')) return image.dataset.mediabook;
58        var candidates = [image.currentSrc, image.src, image.dataset.original, image.dataset.wpsrc];
59        for (var index = 0; index < candidates.length; index += 1) {
60            var decoded = decodeProxyUrl(candidates[index]);
61            var match = decoded.match(/https?:\/\/fourhoi\.com\/([^/?#]+)\//i);
62            if (!match) continue;
63            var slug = match[1];
64            try { slug = decodeURIComponent(slug); } catch (_) {}
65            var preview = 'https://mp.dage263.one/?url=https://fourhoi.com/' + encodeURIComponent(slug) + '/preview.mp4';
66            container.dataset.missavPreview = preview;
67            return preview;
68        }
69        return '';
70    }
71
72    function stop(container) {
73        clearTimeout(timer);
74        timer = 0;
75        var video = container && container.querySelector(':scope > .missav-hover-preview');
76        if (video) {
77            video.pause();
78            video.removeAttribute('src');
79            video.load();
80            video.remove();
81        }
82        if (active === container) active = null;
83    }
84
85    function start(container) {
86        var source = resolvePreview(container);
87        if (!source || container.querySelector(':scope > .missav-hover-preview')) return;
88        if (active && active !== container) stop(active);
89        active = container;
90        timer = window.setTimeout(function () {
91            if (active !== container || !container.isConnected) return;
92            var video = document.createElement('video');
93            video.className = 'missav-hover-preview';
94            video.muted = true;
95            video.loop = true;
96            video.playsInline = true;
97            video.preload = 'auto';
98            video.src = source;
99            Object.assign(video.style, {
100                position: 'absolute', inset: '0', width: '100%', height: '100%',
101                objectFit: 'cover', zIndex: '3', pointerEvents: 'none', background: '#000'
102            });
103            var position = getComputedStyle(container).position;
104            if (position === 'static') container.style.position = 'relative';
105            container.style.overflow = 'hidden';
106            container.appendChild(video);
107            video.addEventListener('error', function () { stop(container); }, { once: true });
108            video.play().catch(function () {
109                // Some browsers resolve autoplay only after enough media data is available.
110                video.addEventListener('canplay', function () {
111                    if (active === container) video.play().catch(function () {});
112                }, { once: true });
113            });
114        }, 180);
115    }
116
117    document.addEventListener('mouseover', function (event) {
118        var container = event.target.closest(cardSelector);
119        if (!container || !container.querySelector('img') || (event.relatedTarget && container.contains(event.relatedTarget))) return;
120        start(container);
121    }, true);
122
123    document.addEventListener('mouseout', function (event) {
124        var container = event.target.closest(cardSelector);
125        if (!container || !container.querySelector('img') || (event.relatedTarget && container.contains(event.relatedTarget))) return;
126        stop(container);
127    }, true);
128
129    document.addEventListener('visibilitychange', function () {
130        if (document.hidden && active) stop(active);
131    });
132})();

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.