PageSourceSearch

https://predanie.ru/js/president-vlog.js?v=v5.3.139

js predanie.ru collected 2026-09-24 08:54:12 UTC 7,020 bytes, 209 lines download raw bytes

1/**
2 * Открывает выпуск влога с главной и страницы всех выпусков
3 * в нативном HTML5-видеоплеере.
4 */
5(function () {
6  'use strict';
7
8  function copyTextFallback(text) {
9    var textarea = document.createElement('textarea');
10    textarea.value = text;
11    textarea.setAttribute('readonly', '');
12    textarea.style.position = 'fixed';
13    textarea.style.opacity = '0';
14    textarea.style.pointerEvents = 'none';
15    document.body.appendChild(textarea);
16    textarea.select();
17    textarea.setSelectionRange(0, textarea.value.length);
18
19    var copied = false;
20    try {
21      copied = document.execCommand('copy');
22    } catch (_) {
23      copied = false;
24    }
25
26    textarea.remove();
27    return copied;
28  }
29
30  function copyText(text) {
31    if (
32      navigator.clipboard &&
33      typeof navigator.clipboard.writeText === 'function'
34    ) {
35      return navigator.clipboard.writeText(text).catch(function () {
36        if (copyTextFallback(text)) return;
37        throw new Error('Не удалось скопировать ссылку');
38      });
39    }
40
41    if (copyTextFallback(text)) return Promise.resolve();
42    return Promise.reject(new Error('Не удалось скопировать ссылку'));
43  }
44
45  function initRssCopyLinks() {
46    var links = document.querySelectorAll('[data-rss-copy-link]');
47
48    links.forEach(function (link) {
49      if (link.getAttribute('data-rss-copy-ready') === 'true') return;
50      link.setAttribute('data-rss-copy-ready', 'true');
51
52      var label = link.querySelector('[data-rss-copy-label]');
53      var icon = link.querySelector('[data-rss-copy-icon]');
54      var originalLabel = label ? label.textContent : '';
55      var originalIconClass = icon ? icon.className : '';
56      var originalTitle = link.getAttribute('title');
57      var originalAriaLabel = link.getAttribute('aria-label');
58      var resetTimer = null;
59
60      function restoreLink() {
61        if (label) label.textContent = originalLabel;
62        if (icon) icon.className = originalIconClass;
63        if (originalTitle) link.setAttribute('title', originalTitle);
64        else link.removeAttribute('title');
65        if (originalAriaLabel)
66          link.setAttribute('aria-label', originalAriaLabel);
67        else link.removeAttribute('aria-label');
68      }
69
70      function showResult(message, iconClass, ariaLabel) {
71        if (label) label.textContent = message;
72        if (icon) icon.className = iconClass;
73        link.setAttribute('title', message);
74        link.setAttribute('aria-label', ariaLabel);
75        if (resetTimer) window.clearTimeout(resetTimer);
76        resetTimer = window.setTimeout(restoreLink, 2800);
77      }
78
79      link.addEventListener('click', function (event) {
80        event.preventDefault();
81
82        var rssUrl = new URL(link.getAttribute('href'), window.location.href)
83          .href;
84        copyText(rssUrl).then(
85          function () {
86            showResult(
87              'Ссылка скопирована',
88              'fas fa-check',
89              'Ссылка RSS-ленты скопирована',
90            );
91          },
92          function () {
93            showResult(
94              'Не удалось скопировать',
95              'fas fa-exclamation-circle',
96              'Не удалось скопировать ссылку RSS-ленты',
97            );
98          },
99        );
100      });
101    });
102  }
103
104  function initPresidentVlog() {
105    initRssCopyLinks();
106
107    var dialog = document.getElementById('presidentVlogDialog');
108    var player = document.getElementById('presidentVlogPlayer');
109    var closeButton = document.getElementById('presidentVlogDialogClose');
110    var title = document.getElementById('presidentVlogDialogTitle');
111    var date = document.getElementById('presidentVlogDialogDate');
112    var cards = document.querySelectorAll('[data-vlog-video]');
113
114    if (!dialog || !player || !cards.length) return;
115
116    function stopVideo() {
117      player.pause();
118      player.removeAttribute('autoplay');
119      player.replaceChildren();
120      player.load();
121      document.body.classList.remove('president-vlog-open');
122    }
123
124    function closeDialog() {
125      if (typeof dialog.close === 'function' && dialog.open) {
126        dialog.close();
127      } else {
128        dialog.removeAttribute('open');
129        stopVideo();
130      }
131    }
132
133    function openVideo(card) {
134      var sources = [];
135      try {
136        sources = JSON.parse(card.getAttribute('data-video-sources') || '[]');
137      } catch (_) {
138        return;
139      }
140      if (!Array.isArray(sources) || !sources.length) return;
141
142      player.replaceChildren();
143      sources.forEach(function (item) {
144        if (!item || !item.url) return;
145        var source = document.createElement('source');
146        source.src = item.url;
147        if (item.type) source.type = item.type;
148        player.appendChild(source);
149      });
150
151      if (title) {
152        title.textContent =
153          card.getAttribute('data-video-title') || 'Выпуск влога';
154      }
155      if (date) {
156        date.textContent = card.getAttribute('data-video-date') || '';
157      }
158
159      player.setAttribute('autoplay', '');
160      player.load();
161      document.body.classList.add('president-vlog-open');
162
163      if (typeof dialog.showModal === 'function') {
164        dialog.showModal();
165      } else {
166        dialog.setAttribute('open', '');
167      }
168
169      var playPromise = player.play();
170      if (playPromise && typeof playPromise.catch === 'function') {
171        playPromise.catch(function () {
172          // Если браузер запретил автозапуск, пользователь запускает видео
173          // обычной кнопкой нативного плеера.
174        });
175      }
176    }
177
178    // TODO: при добавлении бесконечной подгрузки перевести подписку на
179    // делегированное событие контейнера, чтобы новые карточки открывались
180    // без повторной инициализации обработчиков.
181    cards.forEach(function (card) {
182      card.addEventListener('click', function () {
183        openVideo(card);
184      });
185    });
186
187    if (closeButton) closeButton.addEventListener('click', closeDialog);
188    dialog.addEventListener('close', stopVideo);
189    dialog.addEventListener('cancel', function () {
190      stopVideo();
191    });
192    dialog.addEventListener('click', function (event) {
193      if (event.target !== dialog) return;
194      var rect = dialog.getBoundingClientRect();
195      var inside =
196        event.clientX >= rect.left &&
197        event.clientX <= rect.right &&
198        event.clientY >= rect.top &&
199        event.clientY <= rect.bottom;
200      if (!inside) closeDialog();
201    });
202  }
203
204  if (document.readyState === 'loading') {
205    document.addEventListener('DOMContentLoaded', initPresidentVlog);
206  } else {
207    initPresidentVlog();
208  }
209})();

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.