PageSourceSearch

https://siat.ru/wp-content/plugins/external-video-feed-importer/public/js/evf-feed.js?ver=0.4.10

js siat.ru collected 2026-10-02 19:22:16 UTC 4,910 bytes, 121 lines download raw bytes

1(function () {
2    function qs(root, selector) {
3        return root.querySelector(selector);
4    }
5
6    function buildUrl(feed, nextPage) {
7        var url = new URL(EVF_FEED.restUrl, window.location.origin);
8        url.searchParams.set('page', nextPage);
9        url.searchParams.set('per_page', feed.dataset.perPage || '20');
10        url.searchParams.set('category', feed.dataset.category || '');
11        url.searchParams.set('source', feed.dataset.source || '');
12        url.searchParams.set('sort', feed.dataset.sort || 'newest');
13        url.searchParams.set('show_ads', feed.dataset.showAds || '1');
14        return url.toString();
15    }
16
17    function escapeHtml(value) {
18        return String(value || '').replace(/[&<>"']/g, function (char) {
19            return {'&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;'}[char];
20        });
21    }
22
23    function renderVideo(item) {
24        var display = escapeHtml(item.display_type || 'auto');
25        var thumb = item.thumbnail
26            ? '<img src="' + escapeHtml(item.thumbnail) + '" alt="' + escapeHtml(item.title) + '" loading="lazy">'
27            : '<div class="evf-video-thumb__fallback"></div>';
28        var category = item.category ? '<span>' + escapeHtml(item.category) + '</span>' : '';
29        return '<article class="evf-video-card evf-video-card--' + display + '" data-evf-video-card>' +
30            '<div class="evf-video-thumb" data-evf-player data-evf-embed-url="' + escapeHtml(item.embed_url) + '" data-evf-single-url="' + escapeHtml(item.url) + '">' +
31            thumb +
32            '<button class="evf-play-button" type="button" aria-label="Play video"><span></span></button>' +
33            '</div>' +
34            '<div class="evf-video-card__body">' +
35            '<h3 class="evf-video-card__title"><a href="' + escapeHtml(item.url) + '">' + escapeHtml(item.title) + '</a></h3>' +
36            '<div class="evf-video-card__meta">' + category + '</div>' +
37            '</div></article>';
38    }
39
40    function renderItem(item) {
41        if (item.type === 'ad') {
42            return item.html || '';
43        }
44        return renderVideo(item);
45    }
46
47    function loadMore(feed, button) {
48        var nextPage = Number(feed.dataset.page || '1') + 1;
49        button.disabled = true;
50        fetch(buildUrl(feed, nextPage), {credentials: 'same-origin'})
51            .then(function (response) { return response.json(); })
52            .then(function (data) {
53                var grid = qs(feed, '[data-evf-feed-grid]');
54                grid.insertAdjacentHTML('beforeend', (data.items || []).map(renderItem).join(''));
55                initAdCards(grid);
56                feed.dataset.page = String(data.pagination.page);
57                if (!data.pagination.has_more) {
58                    button.remove();
59                } else {
60                    button.disabled = false;
61                }
62            })
63            .catch(function () {
64                button.disabled = false;
65            });
66    }
67
68    document.addEventListener('click', function (event) {
69        var button = event.target.closest('[data-evf-load-more]');
70        if (!button) {
71            return;
72        }
73        var feed = button.closest('[data-evf-feed]');
74        if (feed) {
75            loadMore(feed, button);
76        }
77    });
78
79    function adHasContent(card) {
80        if (!card) {
81            return false;
82        }
83        if (card.querySelector('iframe, img, object, embed')) {
84            return true;
85        }
86        return String(card.textContent || '').trim().length > 0;
87    }
88
89    function initAdCards(root) {
90        (root || document).querySelectorAll('.evf-ad-card').forEach(function (card) {
91            if (card.dataset.evfAdWatch) {
92                return;
93            }
94            card.dataset.evfAdWatch = '1';
95            var update = function () {
96                card.classList.toggle('evf-ad-card--empty', !adHasContent(card));
97            };
98            var observer = new MutationObserver(update);
99            observer.observe(card, { childList: true, subtree: true, characterData: true, attributes: true });
100            window.setTimeout(update, 12000);
101            window.setTimeout(update, 30000);
102        });
103    }
104
105    document.addEventListener('DOMContentLoaded', function () {
106        initAdCards(document);
107    });
108
109    if ('IntersectionObserver' in window) {
110        document.querySelectorAll('[data-evf-feed][data-mode="infinite_scroll"] [data-evf-load-more]').forEach(function (button) {
111            var observer = new IntersectionObserver(function (entries) {
112                entries.forEach(function (entry) {
113                    if (entry.isIntersecting && !button.disabled) {
114                        loadMore(button.closest('[data-evf-feed]'), button);
115                    }
116                });
117            }, {rootMargin: '300px'});
118            observer.observe(button);
119        });
120    }
121})();

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.