index.html 9.4 KB

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