frontend.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. ;(function( $ ) {
  2. PPVideo = function( settings ) {
  3. this.id = settings.id;
  4. this.type = settings.type;
  5. this.autoplay = settings.autoplay;
  6. this.lightbox = settings.lightbox;
  7. this.aspectRatio = settings.aspectRatioLightbox;
  8. this.overlay = settings.overlay;
  9. this.triggerSelector = settings.triggerSelector;
  10. this.node = $('.fl-node-' + this.id);
  11. this.settings = settings;
  12. this.api = {};
  13. this._init();
  14. };
  15. PPVideo.prototype = {
  16. _init: function() {
  17. if ( this.lightbox ) {
  18. this._initLightbox();
  19. } else {
  20. this._inlinePlay();
  21. }
  22. this._initApi();
  23. },
  24. _initApi: function() {
  25. var self = this;
  26. this.api.youtube = {};
  27. self.api.youtube.loadApiScript = function() {
  28. $( 'script:first' ).before( $( '<script>', { src: 'https://www.youtube.com/iframe_api' } ) );
  29. self.api.youtube.apiScriptLoaded = true;
  30. };
  31. self.api.youtube.isApiLoaded = function() {
  32. return window.YT && YT.loaded;
  33. };
  34. self.api.youtube.getApiObject = function() {
  35. return YT;
  36. };
  37. self.api.youtube.onApiReady = function(callback) {
  38. if ( ! self.api.youtube.apiScriptLoaded ) {
  39. self.api.youtube.loadApiScript();
  40. }
  41. if ( self.api.youtube.isApiLoaded() ) {
  42. callback( self.api.youtube.getApiObject() );
  43. } else {
  44. setTimeout( function() {
  45. self.api.youtube.onApiReady(callback);
  46. }, 350 );
  47. }
  48. };
  49. self.api.youtube.getVideoId = function(url) {
  50. var videoIDParts = url.match( /^(?:https?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?vi?=|(?:embed|v|vi|user)\/))([^?&"'>]+)/ );
  51. return videoIDParts && videoIDParts[1];
  52. };
  53. // if ( 'youtube' == self.type ) {
  54. // self.api.youtube.onApiReady( function( apiObject ) {
  55. // self._prepareYTVideo( apiObject );
  56. // }.bind( self ) );
  57. // }
  58. },
  59. _inlinePlay: function() {
  60. var self = this;
  61. var videoFrame = this.node.find( '.pp-video-iframe' );
  62. var videoPlayer = this.node.find( '.pp-video-player' );
  63. var hasOverlay = this.node.find('.pp-video-image-overlay').length > 0;
  64. if ( videoPlayer.length > 0 ) {
  65. videoPlayer.attr( 'playsinline', '' );
  66. if ( this.autoplay && ! hasOverlay ) {
  67. if ( this._isIOS() ) {
  68. videoPlayer.attr( 'muted', '' );
  69. }
  70. videoPlayer[0].play();
  71. }
  72. }
  73. if ( videoFrame.length > 0 ) {
  74. videoFrame.show();
  75. var src = videoFrame.data( 'src' ) || videoFrame.data( 'cli-src' ) || videoFrame.data( 'src-cmplz' );
  76. videoFrame.data( 'src', src.replace('&autoplay=1', '') );
  77. videoFrame.data( 'src', src.replace('autoplay=1', '') );
  78. if ( ! this.autoplay && ! hasOverlay ) {
  79. videoFrame.attr( 'src', videoFrame.data( 'src' ) );
  80. }
  81. if ( this.autoplay && ! this.lightbox ) {
  82. var src = videoFrame.data( 'src' ).split('#');
  83. var iframeSrc = src[0] + '&autoplay=1';
  84. if ( 'youtube' == self.type ) {
  85. iframeSrc += '&enablejsapi=1';
  86. }
  87. if ( 'undefined' !== typeof src[1] ) {
  88. iframeSrc += '#' + src[1];
  89. }
  90. videoFrame.attr( 'src', iframeSrc );
  91. this.node.find( '.pp-video-image-overlay' ).fadeOut(100, function() {
  92. this.remove();
  93. if ( 'youtube' == self.type ) {
  94. self.api.youtube.onApiReady( function( apiObject ) {
  95. self._prepareYTVideo( apiObject );
  96. }.bind( self ) );
  97. }
  98. });
  99. }
  100. }
  101. this.node.find('.pp-video-image-overlay').on('click keyup', function(e) {
  102. // Click or keyboard (enter or spacebar) input?
  103. if ( ! this._validClick(e) ) {
  104. return;
  105. }
  106. e.preventDefault();
  107. this.node.find( '.pp-video-image-overlay' ).fadeOut(800, function() {
  108. this.remove();
  109. });
  110. if ( videoPlayer.length > 0 ) {
  111. videoPlayer[0].play();
  112. return;
  113. }
  114. videoFrame.show();
  115. var lazyLoad = videoFrame.data( 'src' );
  116. if ( lazyLoad ) {
  117. videoFrame.attr( 'src', lazyLoad );
  118. }
  119. var iframeSrc = videoFrame[0].src.replace('&autoplay=0', '');
  120. iframeSrc = iframeSrc.replace('autoplay=0', '');
  121. var src = iframeSrc.split('#');
  122. iframeSrc = src[0];
  123. if ( 'facebook' === this.type ) {
  124. iframeSrc += '&autoplay=0';
  125. } else {
  126. iframeSrc += '&autoplay=1';
  127. }
  128. if ( 'undefined' !== typeof src[1] ) {
  129. iframeSrc += '#' + src[1];
  130. }
  131. videoFrame[0].src = iframeSrc;
  132. }.bind( this ) );
  133. },
  134. _initLightbox: function() {
  135. var id = this.id;
  136. var self = this;
  137. var options = {
  138. modal : false,
  139. enableEscapeButton: true,
  140. type : 'inline',
  141. baseClass : 'fancybox-' + id + ' pp-video-lightbox',
  142. buttons : [
  143. 'close'
  144. ],
  145. wheel : false,
  146. touch : false,
  147. afterLoad : function(current, previous) {
  148. $('.fancybox-' + id).find('.fancybox-bg').addClass('fancybox-' + id + '-overlay');
  149. if ( $('.fancybox-' + id).find( '.pp-video-iframe' ).length > 0 ) {
  150. var iframeSrc = $('.fancybox-' + id).find( '.pp-video-iframe' )[0].src.replace('&autoplay=0', '');
  151. iframeSrc = iframeSrc.replace('autoplay=0', '');
  152. var src = iframeSrc.split('#');
  153. iframeSrc = src[0];
  154. if ( 'facebook' === self.type ) {
  155. iframeSrc += '&autoplay=0';
  156. } else {
  157. iframeSrc += '&autoplay=1';
  158. }
  159. if ( 'youtube' == self.type ) {
  160. iframeSrc += '&enablejsapi=1';
  161. }
  162. if ( 'undefined' !== typeof src[1] ) {
  163. iframeSrc += '#' + src[1];
  164. }
  165. $('.fancybox-' + id).find( '.pp-video-iframe' )[0].src = iframeSrc;
  166. if ( 'youtube' == self.type ) {
  167. self.api.youtube.onApiReady( function( apiObject ) {
  168. self._prepareYTVideo( apiObject );
  169. }.bind( self ) );
  170. }
  171. setTimeout(function() {
  172. $('.fancybox-' + id).trigger('focus');
  173. }, 1200);
  174. }
  175. $('.fancybox-' + id).on('click.pp-video', '.fancybox-content', function(e) {
  176. if ( $(this).hasClass( 'fancybox-content' ) ) {
  177. $.fancybox.close();
  178. }
  179. });
  180. $(document).trigger( 'pp_video_lightbox_after_load', [ $('.fancybox-' + id), id ] );
  181. },
  182. afterClose: function() {
  183. $('.fl-node-' + id).find('.pp-video-play-icon').attr( 'tabindex', '0' );
  184. $('.fl-node-' + id).find('.pp-video-play-icon')[0].focus();
  185. },
  186. iframe: {
  187. preload: false
  188. },
  189. keys: {
  190. close: [27],
  191. },
  192. clickSlide: 'close',
  193. clickOutside: 'close'
  194. };
  195. var wrapperClasses = 'pp-aspect-ratio-' + this.aspectRatio;
  196. var selector = '.fl-node-' + this.id + ' .pp-video-image-overlay';
  197. if ( '' !== this.triggerSelector ) {
  198. selector += ', ' + this.triggerSelector;
  199. }
  200. $( 'body' ).on('click keyup', selector, function(e) {
  201. // Click or keyboard (enter or spacebar) input?
  202. if ( ! this._validClick(e) ) {
  203. return;
  204. }
  205. e.preventDefault();
  206. e.stopPropagation();
  207. var lightboxContent = this.node.find('.pp-video-lightbox-content').html();
  208. $.fancybox.open($( '<div class="'+wrapperClasses+'"></div>').html( lightboxContent ), options );
  209. this.node.find('.pp-video-play-icon').attr( 'tabindex', '-1' );
  210. }.bind( this ) );
  211. $(document).on('keyup', function(e) {
  212. if ( e.keyCode === 27 ) {
  213. $.fancybox.close();
  214. }
  215. });
  216. $(window).on( 'hashchange', this._onHashChange.bind( this ) );
  217. this._onHashChange();
  218. },
  219. _onHashChange: function() {
  220. var hash = location.hash,
  221. validHash = '#video-' + this.id;
  222. if ( hash === validHash ) {
  223. $('.fl-node-' + this.id + ' .pp-video-image-overlay').trigger( 'click' );
  224. }
  225. },
  226. _prepareYTVideo: function(YT) {
  227. var $iframe = this._getIframe(),
  228. iframeSrc = $iframe.attr( 'src' ) || $iframe.attr( 'data-src' ),
  229. videoID = this.api.youtube.getVideoId( iframeSrc ),
  230. self = this;
  231. var playerOptions = {
  232. videoId: videoID,
  233. events: {
  234. onReady: function() {
  235. if (self.settings.mute) {
  236. self.youtubePlayer.mute();
  237. }
  238. if (self.settings.autoplay || onOverlayClick) {
  239. self.youtubePlayer.playVideo();
  240. }
  241. },
  242. onStateChange: function( event ) {
  243. if (event.data === YT.PlayerState.ENDED && self.settings.loop) {
  244. self.youtubePlayer.seekTo(self.settings.startTime || 0);
  245. }
  246. }
  247. },
  248. playerVars: {
  249. controls: self.settings.controls ? 1 : 0,
  250. rel: self.settings.rel ? 1 : 0,
  251. playsinline: self.settings.autoplay ? 1 : 0,
  252. modestbranding: self.settings.modestbranding ? 1 : 0,
  253. autoplay: self.settings.autoplay ? 1 : 0,
  254. start: self.settings.startTime,
  255. end: self.settings.endTime
  256. }
  257. }; // To handle CORS issues, when the default host is changed, the origin parameter has to be set.
  258. if (self.settings.yt_privacy) {
  259. playerOptions.host = 'https://www.youtube-nocookie.com';
  260. playerOptions.origin = window.location.hostname;
  261. }
  262. this.youtubePlayer = new YT.Player($iframe[0], playerOptions);
  263. },
  264. _getIframe: function() {
  265. if ( ! this.lightbox ) {
  266. return $( '.fl-node-' + this.id + ' .pp-video-iframe' );
  267. } else {
  268. return $( '.fancybox-' + this.id + ' .pp-video-iframe' );
  269. }
  270. },
  271. _validClick: function(e) {
  272. return (e.which == 1 || e.which == 13 || e.which == 32 || e.which == undefined) ? true : false;
  273. },
  274. _isIOS: function() {
  275. return !window.MSStream && /iPad|iPhone|iPod/.test(navigator.userAgent);
  276. }
  277. };
  278. })(jQuery);