index.html 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Alt. youtube player</title>
  5. <style>
  6. /*
  7. Adapt to your needs,
  8. but it shouldn't be necessary to add much of css
  9. as the js-script will handle sizing.
  10. */
  11. * {padding: 0;margin: 0;} /* Not necessary when using frameworks */
  12. .player {
  13. position: relative;
  14. z-index: 2;
  15. width: 70vw;
  16. margin: 0 auto;
  17. }
  18. /*
  19. Note that the > restricts the img to be on the root level of .player
  20. */
  21. .player > img.thumb {
  22. position: absolute;
  23. z-index: 1;
  24. width: 100%;
  25. }
  26. .player > iframe {
  27. position: absolute;
  28. z-index: -1;
  29. width: 100%;
  30. height: 100%;
  31. }
  32. .player.play {
  33. cursor: pointer;
  34. }
  35. .player.stop {
  36. cursor: not-allowed;
  37. }
  38. .player.loading {
  39. cursor: wait;
  40. }
  41. </style>
  42. <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  43. </head>
  44. <body>
  45. <!--
  46. A player MUST:
  47. - Have a class «player»
  48. - Have a child element of img
  49. - with the class «thumb»
  50. - Have a child of the iframe
  51. - that has the query-param «enablejsapi=1»
  52. -->
  53. <div class="player">
  54. <img class="thumb" src="./thumb.png" alt="Thumbnail" />
  55. <div class="something wf realated classed and shit">
  56. <iframe src="https://www.youtube-nocookie.com/embed/dcsvMySGmS8?enablejsapi=1&rel=0" frameborder="0" allow="autoplay; encrypted-media; gyroscope" allowfullscreen></iframe>
  57. </div>
  58. </div>
  59. <!-- additional players -->
  60. <div class="player">
  61. <img class="thumb" src="./thumb.png" alt="Thumbnail" />
  62. <iframe src="https://www.youtube-nocookie.com/embed/pouODQkJQG0?enablejsapi=1" frameborder="0" allow="autoplay; encrypted-media; gyroscope" allowfullscreen></iframe>
  63. </div>
  64. <div class="player">
  65. <img class="thumb" src="./thumb.png" alt="Thumbnail" />
  66. <iframe src="https://www.youtube-nocookie.com/embed/Y-JQ-RCyPpQ?enablejsapi=1" frameborder="0" allow="autoplay; encrypted-media; gyroscope" allowfullscreen></iframe>
  67. </div>
  68. <div class="player">
  69. <img class="thumb" src="./thumb.png" alt="Thumbnail" />
  70. <iframe src="https://www.youtube-nocookie.com/embed/4-079YIasck?enablejsapi=1" frameborder="0" allow="autoplay; encrypted-media; gyroscope" allowfullscreen></iframe>
  71. </div>
  72. <!-- You need this before the </body>-tag (closing) -->
  73. <script>
  74. // Hack to load Youtube iframe_api
  75. jQuery.getScript("https://www.youtube.com/iframe_api")
  76. var ytd = $.Deferred();
  77. window.onYouTubeIframeAPIReady = function () {
  78. ytd.resolve(window.YT);
  79. };
  80. $(document).ready(function () {
  81. // Store all instances of «Youtube Players»
  82. var ytp = [];
  83. // Change effect on IN and OUT here.
  84. // Will affect on both «playerOpen» and «playerClose»
  85. $.fn.outEffect = $.fn.fadeOut;
  86. $.fn.inEffect = $.fn.fadeIn;
  87. // When a player opens
  88. var playerOpen = function (i, player) {
  89. if (!ytp[i])
  90. return;
  91. // Remove thumb and show iframe
  92. player.find('.thumb').outEffect();
  93. player.find('iframe').inEffect({
  94. complete: function () {
  95. // When fully opened, plat video and change cursor
  96. if (ytp[i].getPlayerState() != YT.PlayerState.PLAYING)
  97. ytp[i].playVideo()
  98. player.removeClass('play loading').addClass('stop');
  99. }
  100. });
  101. // Close all the players that might be open.
  102. $('.player').each(function (idx) {
  103. if (i == idx) return;
  104. playerClose(idx, $(this));
  105. })
  106. }
  107. // When a player is closing
  108. var playerClose = function (i, player) {
  109. if (!ytp[i])
  110. return;
  111. // Hide iframe and show thumg
  112. player.find('iframe').outEffect()
  113. player.find('.thumb').inEffect(function() {
  114. // Stop the video; if playing
  115. if (ytp[i].getPlayerState() == YT.PlayerState.PLAYING)
  116. ytp[i].pauseVideo();
  117. player.removeClass('stop loading').addClass('play');
  118. });
  119. }
  120. // Make sure Iframe has the same size as the thumb-img
  121. var adoptThumbSizeToIframe = function (player) {
  122. var ytvid = player.find('iframe');
  123. var thumb = player.find('.thumb');
  124. var hidden = thumb.is(':hidden');
  125. // Hack to read size
  126. if (hidden)
  127. thumb.show();
  128. player.css({
  129. height: thumb.height(),
  130. width: thumb.width(),
  131. });
  132. // Adopt the size of the thumbnail to the iframe
  133. ytvid.css({
  134. height: thumb.height(),
  135. width: thumb.width(),
  136. });
  137. if (hidden)
  138. thumb.hide();
  139. }
  140. // On scroll, check that we are withing bounding. Close if not.
  141. window.addEventListener('scroll', function (e) {
  142. var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  143. var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
  144. var d = $(document).scrollTop();
  145. $('.player').each(function (i) {
  146. if ($(this).find('iframe:visible').length == 0)
  147. return; // player not open (already showing thumb)
  148. var x = $(this).offset()['top'];
  149. var xoff = $(this).height() / 15;
  150. if ((x + $(this).height() - xoff) < d || (x + xoff) > (d + h))
  151. playerClose(i, $(this));
  152. /*
  153. No horizontal test... but...
  154. var y = $(this).offset()['left'];
  155. var yoff = ($(this).width() / 15);
  156. */
  157. })
  158. })
  159. window.addEventListener('resize', function () {
  160. $('.player').each(function() {
  161. console.log("Resize");
  162. adoptThumbSizeToIframe($(this));
  163. })
  164. })
  165. // Youtube API is reacy
  166. ytd.done(function (YT) {
  167. /*
  168. Initialize player on all of them.
  169. Could be optimized and wait with init until the player should start,
  170. and destroy it when it's closed.
  171. */
  172. $(".player").each(function (i) {
  173. var player = $(this).addClass('loading');
  174. var ytvid = player.find('iframe').hide();
  175. adoptThumbSizeToIframe(player);
  176. // Generate and add id to the iframe
  177. ytvid.attr('id', 'player-' + (i+1));
  178. ytp.push(new YT.Player(ytvid.attr('id'), {
  179. events: {
  180. 'onReady': function (e) {
  181. player.removeClass('loading').addClass('play');
  182. player.bind('click', function () {
  183. playerOpen(i, player);
  184. })
  185. },
  186. 'onStateChange': function (e) {
  187. // Add event specific data here
  188. switch (e.data) {
  189. case YT.PlayerState.ENDED:
  190. playerClose(i, player)
  191. break;
  192. case YT.PlayerState.PLAYING:
  193. // console.log("PLAYING");
  194. break;
  195. case YT.PlayerState.PAUSED:
  196. player.removeClass('stop loading').addClass('play');
  197. break;
  198. case YT.PlayerState.BUFFERING:
  199. player.removeClass('stop play').addClass('loading');
  200. break;
  201. case YT.PlayerState.CUED:
  202. //console.log("CUED");
  203. break;
  204. }
  205. },
  206. }
  207. }));
  208. })
  209. })
  210. });
  211. </script>
  212. </body>
  213. </html>