PageSourceSearch

https://sol.vin/js/widgets/youtube_widget.js

js sol.vin collected 2026-10-09 21:58:36 UTC 3,933 bytes, 107 lines download raw bytes

1window.YoutubeWidget = (function() {
2  'use strict';
3
4  var ytApiLoading = false;
5  var pendingCallbacks = [];
6
7  function loadYtApi(callback) {
8    if (window.YT && window.YT.Player) {
9      callback();
10      return;
11    }
12    pendingCallbacks.push(callback);
13    if (!ytApiLoading) {
14      ytApiLoading = true;
15      var tag = document.createElement('script');
16      tag.src = 'https://www.youtube.com/iframe_api';
17      var firstScript = document.getElementsByTagName('script')[0];
18      if (firstScript && firstScript.parentNode) {
19        firstScript.parentNode.insertBefore(tag, firstScript);
20      } else {
21        (document.head || document.documentElement).appendChild(tag);
22      }
23      var prevReady = window.onYouTubeIframeAPIReady;
24      window.onYouTubeIframeAPIReady = function() {
25        if (typeof prevReady === 'function') {
26          prevReady();
27        }
28        while (pendingCallbacks.length > 0) {
29          var cb = pendingCallbacks.shift();
30          try { cb(); } catch (e) {}
31        }
32      };
33    }
34  }
35
36  function bindPlayerState(iframeEl, container) {
37    loadYtApi(function() {
38      try {
39        new window.YT.Player(iframeEl, {
40          events: {
41            'onStateChange': function(event) {
42              if (event && event.data === window.YT.PlayerState.PLAYING) {
43                container.classList.add('is-playing');
44              } else if (event && (event.data === window.YT.PlayerState.PAUSED || event.data === window.YT.PlayerState.ENDED)) {
45                container.classList.remove('is-playing');
46              }
47            }
48          }
49        });
50      } catch (e) {
51        // Fallback: hover and focus CSS filters remain active
52      }
53    });
54  }
55
56  function render(element, videoId, playlistId, embedType) {
57    if (!element) return;
58    var container = element.querySelector('.youtube-player-container');
59    if (!container) {
60      container = document.createElement('div');
61      container.className = 'youtube-player-container video-container';
62      element.appendChild(container);
63    }
64
65    var iframeSrc = '';
66    if (embedType === 'playlist' && playlistId) {
67      if (videoId) {
68        iframeSrc = 'https://www.youtube-nocookie.com/embed/' + videoId + '?list=' + playlistId;
69      } else {
70        iframeSrc = 'https://www.youtube-nocookie.com/embed/videoseries?list=' + playlistId;
71      }
72    } else if (videoId) {
73      iframeSrc = 'https://www.youtube-nocookie.com/embed/' + videoId;
74      if (playlistId) {
75        iframeSrc += '?list=' + playlistId;
76      }
77    } else if (playlistId) {
78      iframeSrc = 'https://www.youtube-nocookie.com/embed/videoseries?list=' + playlistId;
79    }
80
81    if (iframeSrc) {
82      var delimiter = iframeSrc.indexOf('?') >= 0 ? '&' : '?';
83      iframeSrc += delimiter + 'enablejsapi=1';
84      var playerUniqueId = 'yt-player-' + Math.random().toString(36).substring(2, 9);
85      container.innerHTML = '<iframe id="' + playerUniqueId + '" src="' + iframeSrc + '" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen credentialless></iframe>';
86      var iframeEl = container.querySelector('iframe');
87      if (iframeEl) {
88        bindPlayerState(iframeEl, container);
89      }
90    }
91  }
92
93  function init() {
94    var elements = document.querySelectorAll('[data-youtube-id], [data-youtube-playlist-id]');
95    elements.forEach(function(el) {
96      if (el.classList.contains('fav-collection-item-chip') || (el.closest && el.closest('.fav-collection-item-chip'))) return;
97      var videoId = el.getAttribute('data-youtube-id');
98      var playlistId = el.getAttribute('data-youtube-playlist-id');
99      var embedType = el.getAttribute('data-youtube-embed-type');
100      if (videoId || playlistId) {
101        render(el, videoId, playlistId, embedType);
102      }
103    });
104  }
105
106  return { init: init, render: render };
107})();

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.