/dist/jquery.mb.YTPlayer.js

https://github.com/pupunzi/jquery.mb.YTPlayer · JavaScript · 2928 lines · 1765 code · 467 blank · 696 comment · 349 complexity · 872da36eadd624b2a88e4ec311af3824 MD5 · raw file

Large files are truncated click here to view the full file

  1. /**********************************************
  2. * @File Name: jquery.mb.YTPlayer.src.js
  3. * @Author: Matteo Bicocchi
  4. * @Date: 2020-03-16
  5. * @Email: matbicoc@gmail.com
  6. *
  7. * @Last Modified by: Matteo Bicocchi
  8. * @Last Modified time: 2020-03-18
  9. * @Copyright: 2020. Matteo Bicocchi
  10. *
  11. * Open Lab s.r.l., Florence - Italy
  12. * @blog: http://pupunzi.open-lab.com
  13. * @site: http://pupunzi.com
  14. ****************************************************/
  15. var ytp = ytp || {};
  16. let YTPRndSuffix = new Date().getTime();
  17. let YTPTimerLabels = {
  18. init : "YTPlayerInit_" + YTPRndSuffix,
  19. startPlaying: "YTPlayerStartPlay_" + YTPRndSuffix
  20. };
  21. function onYouTubeIframeAPIReady() {
  22. if (ytp.YTAPIReady)
  23. return;
  24. ytp.YTAPIReady = true;
  25. jQuery(document).trigger('YTAPIReady')
  26. }
  27. let getYTPVideoID = function (url) {
  28. let videoID, playlistID;
  29. if (url.indexOf('youtu.be') > 0 || url.indexOf('youtube.com/embed') > 0) {
  30. videoID = url.substr(url.lastIndexOf('/') + 1, url.length);
  31. playlistID = videoID.indexOf('?list=') > 0 ? videoID.substr(videoID.lastIndexOf('='), videoID.length) : null;
  32. videoID = playlistID ? videoID.substr(0, videoID.lastIndexOf('?')) : videoID
  33. } else if (url.indexOf('http') > -1) {
  34. //videoID = url.match( /([\/&]v\/([^&#]*))|([\\?&]v=([^&#]*))/ )[ 1 ];
  35. videoID = url.match(/[\\?&]v=([^&#]*)/)[1];
  36. playlistID = url.indexOf('list=') > 0 ? url.match(/[\\?&]list=([^&#]*)/)[1] : null
  37. } else {
  38. videoID = url.length > 15 ? null : url;
  39. playlistID = videoID ? null : url
  40. }
  41. return {
  42. videoID : videoID,
  43. playlistID: playlistID
  44. }
  45. };
  46. (function (jQuery, ytp) {
  47. jQuery.mbYTPlayer = {
  48. name : 'jquery.mb.YTPlayer',
  49. version: '3.3.9',
  50. build : '7581',
  51. author : 'Matteo Bicocchi (pupunzi)',
  52. apiKey : '',
  53. /*
  54. * Default options for the player
  55. */
  56. defaults : {
  57. /**
  58. videoURL (string)
  59. the complete Youtube video URL or the short url or the videoID
  60. */
  61. videoURL: null,
  62. /**
  63. containment (string)
  64. default containment for the player
  65. */
  66. containment: 'body',
  67. /**
  68. ratio (string or number)
  69. "auto", "16/9", "4/3" or number: 4/3, 16/9
  70. */
  71. ratio: 'auto',
  72. /**
  73. fadeOnStartTime (int)
  74. fade in timing at video start
  75. */
  76. fadeOnStartTime: 1000,
  77. /**
  78. startAt (int)
  79. start second
  80. */
  81. startAt: 0,
  82. /**
  83. stopAt (int)
  84. stop second
  85. */
  86. stopAt: 0,
  87. /**
  88. autoPlay (bool)
  89. on page load video should start or pause
  90. */
  91. autoPlay: true,
  92. /**
  93. delayAtStart (bool)
  94. If the YT API don't fire the event the player will try to start anyway after...
  95. */
  96. delayAtStart: 1000,
  97. /**
  98. coverImage (string)
  99. The path to the image to be used as cover if the autoPlay option is set to false
  100. */
  101. coverImage: false,
  102. /**
  103. loop (bool or int)
  104. video should loop or not; if number it will loop for the specified times
  105. */
  106. loop: true,
  107. /**
  108. addRaster (bool)
  109. shows a raster image over the video (added via CSS)
  110. You can change the raster image via CSS:
  111. .YTPOverlay.raster { background: url(images/raster.png)}
  112. */
  113. addRaster: false,
  114. /**
  115. mask (bool or object) the key is the second and the value is the path to the image
  116. Ex: mask:{ 0:'assets/mask-1.png', 5:'assets/mask-2.png', 30: false, 50:'assets/mask-3.png'}
  117. */
  118. mask: false,
  119. /**
  120. opacity (int)
  121. 0 to 1
  122. */
  123. opacity: 1,
  124. /**
  125. quality (string)
  126. @deprecated
  127. setPlaybackQuality has been deprecated on the YT API and doesn't work anymore
  128. “small”, “medium”, “large”, “hd720”, “hd1080”, “highres”, "default"
  129. */
  130. quality: 'default',
  131. /**
  132. vol (int)
  133. 0 to 100
  134. */
  135. vol: 50,
  136. /**
  137. mute (bool)
  138. mute the video at start
  139. */
  140. mute: false,
  141. /**
  142. showControls (bool)
  143. shows the control bar at the bottom of the containment
  144. */
  145. showControls: true,
  146. /**
  147. anchor (string)
  148. center,top,bottom,left,right combined in pair
  149. */
  150. anchor: 'center,center',
  151. /**
  152. showAnnotations (bool)
  153. display the annotations on video
  154. */
  155. showAnnotations: false,
  156. /**
  157. cc_load_policy (bool)
  158. display the subtitles
  159. */
  160. cc_load_policy: false,
  161. /**
  162. showYTLogo (bool)
  163. display the Youtube logotype inside the button bar
  164. */
  165. showYTLogo: true,
  166. /**
  167. useOnMobile (bool)
  168. activate the player also on mobile
  169. */
  170. useOnMobile: true,
  171. /**
  172. playOnlyIfVisible (bool)
  173. play the video only if the containment is on screen
  174. */
  175. playOnlyIfVisible: false,
  176. /**
  177. onScreenPercentage (bool)
  178. percentage of the player height the video should stop or start when visible
  179. */
  180. onScreenPercentage: 30,
  181. /**
  182. * goFullScreenOnPlay (bool)
  183. * if the player containment is set to "self" this allow the video to go fullscreen when played
  184. */
  185. goFullScreenOnPlay: false,
  186. /**
  187. stopMovieOnBlur (bool)
  188. stop the video if the window loose the focus
  189. */
  190. stopMovieOnBlur: true,
  191. /**
  192. realfullscreen (bool)
  193. the video when in full screen covers all the display
  194. */
  195. realFullscreen: true,
  196. /**
  197. optimizeDisplay (bool)
  198. The video always fit the containment without displaying the black strips
  199. */
  200. optimizeDisplay: true,
  201. /**
  202. abundance (bool)
  203. the abudance of the video size
  204. */
  205. abundance: 0.3,
  206. /**
  207. gaTrack (bool)
  208. track the video plays on GA
  209. */
  210. gaTrack: true,
  211. /**
  212. remember_last_time (bool)
  213. when the page is reloaded the video will start from the last position
  214. */
  215. remember_last_time: false,
  216. /**
  217. addFilters (bool or string)
  218. add one or more CSS filters as object to the video
  219. Ex: {sepia: 50, hue_rotate : 220}
  220. */
  221. addFilters: false,
  222. /**
  223. useNoCookie (bool)
  224. use https://www.youtube-nocookie.com host to serve the video
  225. */
  226. useNoCookie: true,
  227. /**
  228. onReady (function)
  229. a callback function fired once the player is ready
  230. */
  231. onReady: function (player) {
  232. },
  233. /**
  234. onReady (function)
  235. a callback function fired if there's an error
  236. */
  237. onError: function (player, err) {
  238. },
  239. /**
  240. onEnd (function)
  241. a callback function fired when the video ends
  242. */
  243. onEnd: function () {
  244. }
  245. },
  246. /**
  247. * @fontface icons
  248. * */
  249. controls : {
  250. play : 'P',
  251. pause : 'p',
  252. mute : 'M',
  253. unmute : 'A',
  254. onlyYT : 'O',
  255. showSite: 'R',
  256. ytLogo : 'Y'
  257. },
  258. controlBar : null,
  259. locationProtocol: 'https:',
  260. /**
  261. * Applicable filters
  262. */
  263. defaultFilters: {
  264. grayscale : {value: 0, unit: '%'},
  265. hue_rotate: {value: 0, unit: 'deg'},
  266. invert : {value: 0, unit: '%'},
  267. opacity : {value: 0, unit: '%'},
  268. saturate : {value: 0, unit: '%'},
  269. sepia : {value: 0, unit: '%'},
  270. brightness: {value: 0, unit: '%'},
  271. contrast : {value: 0, unit: '%'},
  272. blur : {value: 0, unit: 'px'}
  273. },
  274. /**
  275. * build the player
  276. * @param options
  277. * @returns [players]
  278. */
  279. buildPlayer: function (options) {
  280. if (!ytp.YTAPIReady && typeof window.YT === 'undefined') {
  281. jQuery('#YTAPI').remove();
  282. let tag = jQuery('<script>').attr({
  283. 'src': 'https://www.youtube.com/iframe_api?v=' + jQuery.mbYTPlayer.version,
  284. 'id' : 'YTAPI'
  285. });
  286. jQuery('head').prepend(tag)
  287. } else {
  288. setTimeout(function () {
  289. jQuery(document).trigger('YTAPIReady');
  290. ytp.YTAPIReady = true
  291. }, 100)
  292. }
  293. function isIframe() {
  294. let isIfr = false;
  295. try {
  296. if (self.location.href !== top.location.href) isIfr = true
  297. } catch (e) {
  298. isIfr = true
  299. }
  300. return isIfr
  301. }
  302. return this.each(function () {
  303. let YTPlayer = this;
  304. let $YTPlayer = jQuery(YTPlayer);
  305. $YTPlayer.hide();
  306. YTPlayer.loop = 0;
  307. YTPlayer.state = 0;
  308. YTPlayer.filters = jQuery.extend(true, {}, jQuery.mbYTPlayer.defaultFilters);
  309. YTPlayer.filtersEnabled = true;
  310. YTPlayer.id = YTPlayer.id || 'YTP_' + new Date().getTime();
  311. $YTPlayer.addClass('mb_YTPlayer');
  312. /**
  313. Set properties
  314. */
  315. let property = $YTPlayer.data('property') && typeof $YTPlayer.data('property') == 'string' ?
  316. eval('(' + $YTPlayer.data('property') + ')') :
  317. $YTPlayer.data('property');
  318. if (typeof property !== 'object')
  319. property = {};
  320. YTPlayer.opt = jQuery.extend(true, {}, jQuery.mbYTPlayer.defaults, YTPlayer.opt, options, property);
  321. YTPRndSuffix = getYTPVideoID(YTPlayer.opt.videoURL).videoID;
  322. YTPTimerLabels = {
  323. init : "YTPlayerInit_" + YTPRndSuffix,
  324. startPlaying: "YTPlayerStartPlay_" + YTPRndSuffix
  325. };
  326. console.time(YTPTimerLabels.init);
  327. console.time(YTPTimerLabels.startPlaying);
  328. YTPlayer.opt.elementId = YTPlayer.id;
  329. if (YTPlayer.opt.vol === 0) {
  330. YTPlayer.opt.vol = 1;
  331. YTPlayer.opt.mute = true
  332. }
  333. if (YTPlayer.opt.loop && typeof YTPlayer.opt.loop === 'boolean') {
  334. YTPlayer.opt.loop = 9999
  335. }
  336. /**
  337. Disable fullScreen if is in an iframe or full-screen API is not available
  338. */
  339. let fullScreenAvailable = document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled;
  340. YTPlayer.opt.realFullscreen = isIframe() || !fullScreenAvailable ? false : YTPlayer.opt.realFullscreen;
  341. /**
  342. Manage annotations
  343. */
  344. YTPlayer.opt.showAnnotations = YTPlayer.opt.showAnnotations ? '1' : '3';
  345. /**
  346. Manage show subtitle and caption
  347. */
  348. YTPlayer.opt.cc_load_policy = YTPlayer.opt.cc_load_policy ? '1' : '0';
  349. /**
  350. Manage cover image
  351. */
  352. YTPlayer.opt.coverImage = YTPlayer.opt.coverImage || YTPlayer.opt.backgroundImage;
  353. /**
  354. Manage Quality
  355. the setPlaybackQuality has been deprecated by YT
  356. */
  357. YTPlayer.opt.quality = 'hd1080';
  358. YTPlayer.opt.containment = YTPlayer.opt.containment === 'self' ? $YTPlayer : jQuery(YTPlayer.opt.containment);
  359. YTPlayer.isRetina = (window.retina || window.devicePixelRatio > 1);
  360. YTPlayer.opt.ratio = YTPlayer.opt.ratio === 'auto' ? 16 / 9 : YTPlayer.opt.ratio;
  361. YTPlayer.opt.ratio = eval(YTPlayer.opt.ratio);
  362. let origContainmentBackground = YTPlayer.opt.containment.css('background-image');
  363. origContainmentBackground = (origContainmentBackground === 'none') ? null : origContainmentBackground;
  364. YTPlayer.orig_containment_background = origContainmentBackground;
  365. if (!$YTPlayer.attr('id'))
  366. $YTPlayer.attr('id', 'ytp_' + new Date().getTime());
  367. YTPlayer.playerID = 'iframe_' + YTPlayer.id;
  368. YTPlayer.isAlone = false;
  369. YTPlayer.hasFocus = true;
  370. YTPlayer.videoID = YTPlayer.opt.videoURL ?
  371. getYTPVideoID(YTPlayer.opt.videoURL).videoID : $YTPlayer.attr('href') ?
  372. getYTPVideoID($YTPlayer.attr('href')).videoID :
  373. false;
  374. /**
  375. Check if it is a video list
  376. */
  377. YTPlayer.playlistID = YTPlayer.opt.videoURL ?
  378. getYTPVideoID(YTPlayer.opt.videoURL).playlistID : $YTPlayer.attr('href') ?
  379. getYTPVideoID($YTPlayer.attr('href')).playlistID :
  380. false;
  381. let start_from_last = 0;
  382. if (jQuery.mbCookie.get('YTPlayer_start_from' + YTPlayer.videoID))
  383. start_from_last = parseFloat(jQuery.mbCookie.get('YTPlayer_start_from' + YTPlayer.videoID));
  384. if (YTPlayer.opt.remember_last_time && start_from_last) {
  385. YTPlayer.start_from_last = start_from_last;
  386. jQuery.mbCookie.remove('YTPlayer_start_from' + YTPlayer.videoID)
  387. }
  388. YTPlayer.isPlayer = $YTPlayer.is(YTPlayer.opt.containment);
  389. YTPlayer.isBackground = YTPlayer.opt.containment.is('body');
  390. if (YTPlayer.isBackground && ytp.backgroundIsInited)
  391. return;
  392. /**
  393. Hide the placeholder if it's not the target of the player
  394. */
  395. if (YTPlayer.isPlayer)
  396. $YTPlayer.show();
  397. /**
  398. create the overlay
  399. */
  400. YTPlayer.overlay = jQuery('<div/>').css({
  401. position: 'absolute',
  402. top : 0,
  403. left : 0,
  404. width : '100%',
  405. height : '100%'
  406. }).addClass('YTPOverlay');
  407. $YTPlayer.changeCoverImage();
  408. /**
  409. create the wrapper
  410. */
  411. YTPlayer.wrapper = jQuery('<div/>').attr('id', 'wrapper_' + YTPlayer.id).css({
  412. position : 'absolute',
  413. zIndex : 0,
  414. minWidth : '100%',
  415. minHeight: '100%',
  416. left : 0,
  417. top : 0,
  418. overflow : 'hidden',
  419. opacity : 0
  420. }).addClass('mbYTP_wrapper');
  421. /**
  422. If is an inline player toggle play if the overlay is clicked
  423. */
  424. if (YTPlayer.isPlayer) {
  425. let inlinePlayButtonCss = jQuery.mbBrowser.mobile ? "inlinePlayButtonMobile" : "inlinePlayButton";
  426. YTPlayer.inlinePlayButton = jQuery('<div/>').addClass(inlinePlayButtonCss).html(jQuery.mbYTPlayer.controls.play);
  427. $YTPlayer.append(YTPlayer.inlinePlayButton);
  428. YTPlayer.inlinePlayButton.on('click', function (e) {
  429. $YTPlayer.YTPPlay();
  430. /**
  431. * Hide the PLAY button on play
  432. */
  433. YTPlayer.inlinePlayButton.hide();
  434. /**
  435. * set the fullscreen on play
  436. */
  437. if (YTPlayer.opt.goFullScreenOnPlay) {
  438. $YTPlayer.YTPFullscreen();
  439. }
  440. e.stopPropagation()
  441. });
  442. if (YTPlayer.opt.autoPlay)
  443. YTPlayer.inlinePlayButton.hide();
  444. YTPlayer.overlay.on('click', function () {
  445. $YTPlayer.YTPTogglePlay();
  446. if (YTPlayer.opt.goFullScreenOnPlay) {
  447. $YTPlayer.YTPFullscreen();
  448. }
  449. }).css({cursor: 'pointer'})
  450. }
  451. /**
  452. create the playerBox where the YT iframe will be placed
  453. */
  454. let playerBox = jQuery('<div/>').attr('id', YTPlayer.playerID).addClass('playerBox');
  455. playerBox.css({
  456. position: 'absolute',
  457. zIndex : 0,
  458. width : '100%',
  459. height : '100%',
  460. top : 0,
  461. left : 0,
  462. overflow: 'hidden',
  463. opacity : 1
  464. });
  465. YTPlayer.wrapper.append(playerBox);
  466. playerBox.after(YTPlayer.overlay);
  467. if (YTPlayer.isPlayer) {
  468. YTPlayer.inlineWrapper = jQuery('<div/>').addClass('inline-YTPlayer');
  469. YTPlayer.inlineWrapper.css({
  470. position: 'relative',
  471. maxWidth: YTPlayer.opt.containment.css('width')
  472. });
  473. YTPlayer.opt.containment.css({
  474. position : 'relative',
  475. paddingBottom: '56.25%',
  476. overflow : 'hidden',
  477. height : 0
  478. });
  479. YTPlayer.opt.containment.wrap(YTPlayer.inlineWrapper)
  480. }
  481. /**
  482. Loop all the elements inside the container and check if their position is not "static"
  483. */
  484. YTPlayer.opt.containment.children().not('script, style').each(function () {
  485. if (jQuery(this).css('position') === 'static')
  486. jQuery(this).css('position', 'relative')
  487. });
  488. if (YTPlayer.isBackground) {
  489. jQuery('body').css({
  490. boxSizing: 'border-box'
  491. });
  492. YTPlayer.wrapper.css({
  493. position: 'fixed',
  494. top : 0,
  495. left : 0,
  496. zIndex : 0
  497. })
  498. } else if (YTPlayer.opt.containment.css('position') === 'static') {
  499. YTPlayer.opt.containment.css({
  500. position: 'relative'
  501. });
  502. $YTPlayer.show()
  503. }
  504. YTPlayer.opt.containment.prepend(YTPlayer.wrapper);
  505. if (!YTPlayer.isBackground) {
  506. YTPlayer.overlay.on('mouseenter', function () {
  507. if (YTPlayer.controlBar && YTPlayer.controlBar.length)
  508. YTPlayer.controlBar.addClass('visible')
  509. }).on('mouseleave', function () {
  510. if (YTPlayer.controlBar && YTPlayer.controlBar.length)
  511. YTPlayer.controlBar.removeClass('visible')
  512. })
  513. }
  514. if (jQuery.mbBrowser.mobile && !YTPlayer.opt.useOnMobile) {
  515. if (YTPlayer.opt.coverImage) {
  516. YTPlayer.wrapper.css({
  517. backgroundImage : 'url(' + YTPlayer.opt.coverImage + ')',
  518. backgroundPosition: 'center center',
  519. backgroundSize : 'cover',
  520. backgroundRepeat : 'no-repeat',
  521. opacity : 1
  522. });
  523. YTPlayer.wrapper.css({opacity: 1})
  524. }
  525. return $YTPlayer
  526. }
  527. /**
  528. If is on device start playing on first touch
  529. */
  530. if (jQuery.mbBrowser.mobile && YTPlayer.opt.autoPlay && YTPlayer.opt.useOnMobile)
  531. jQuery('body').one('touchstart', function () {
  532. YTPlayer.player.playVideo()
  533. });
  534. jQuery(document).one('YTAPIReady', function () {
  535. $YTPlayer.trigger('YTAPIReady_' + YTPlayer.id);
  536. ytp.YTAPIReady = true
  537. });
  538. YTPlayer.isOnScreen = jQuery.mbYTPlayer.isOnScreen(YTPlayer, YTPlayer.opt.onScreenPercentage);
  539. $YTPlayer.one('YTAPIReady_' + YTPlayer.id, function () {
  540. let YTPlayer = this;
  541. let $YTPlayer = jQuery(YTPlayer);
  542. if ((YTPlayer.isBackground && ytp.backgroundIsInited) || YTPlayer.isInit)
  543. return;
  544. if (YTPlayer.isBackground)
  545. ytp.backgroundIsInited = true;
  546. YTPlayer.opt.autoPlay = typeof YTPlayer.opt.autoPlay == 'undefined' ? (!!YTPlayer.isBackground) : YTPlayer.opt.autoPlay;
  547. YTPlayer.opt.vol = YTPlayer.opt.vol ? YTPlayer.opt.vol : 100;
  548. jQuery.mbYTPlayer.getDataFromAPI(YTPlayer);
  549. jQuery(YTPlayer).on('YTPChanged', function (e) {
  550. if (YTPlayer.isInit)
  551. return;
  552. YTPlayer.isInit = true;
  553. /** Initialize the YT player ------------------------------------
  554. * Youtube player variables
  555. * @type {{modestbranding: number, autoplay: number, controls: number, showinfo: number, rel: number, enablejsapi: number, version: number, playerapiid: string, origin: string, allowfullscreen: boolean, iv_load_policy: (string|*|jQuery.mbYTPlayer.opt.showAnnotations), playsinline: number}}
  556. */
  557. let playerVars = {
  558. 'modestbranding' : 1,
  559. 'autoplay' : 0,
  560. 'controls' : 0,
  561. 'showinfo' : 0,
  562. 'rel' : 0,
  563. 'enablejsapi' : 1,
  564. 'version' : 3,
  565. 'playerapiid' : YTPlayer.playerID,
  566. 'origin' : '*',
  567. 'allowfullscreen': true,
  568. 'wmode' : 'transparent',
  569. 'iv_load_policy' : YTPlayer.opt.showAnnotations,
  570. 'cc_load_policy' : YTPlayer.opt.cc_load_policy,
  571. 'playsinline' : jQuery.mbBrowser.mobile && !YTPlayer.isPlayer ? 1 : 0,
  572. /**
  573. Check if the mbBrowser can play HTML5 videos
  574. */
  575. 'html5': document.createElement('video').canPlayType ? 1 : 0
  576. };
  577. new YT.Player(YTPlayer.playerID, {
  578. //videoId: YTPlayer.videoID.toString(),
  579. host : YTPlayer.opt.useNoCookie ? 'https://www.youtube-nocookie.com' : 'https://www.youtube.com',
  580. playerVars: playerVars,
  581. events : {
  582. 'onReady' : function (event) {
  583. YTPlayer.player = event.target;
  584. YTPlayer.player.loadVideoById({
  585. videoId : YTPlayer.videoID.toString(),
  586. suggestedQuality: YTPlayer.opt.quality
  587. });
  588. $YTPlayer.trigger('YTPlayerIsReady_' + YTPlayer.id)
  589. },
  590. /**
  591. * on State Change
  592. * @param event
  593. *
  594. * -1 (unstarted)
  595. * 0 (ended)
  596. * 1 (playing)
  597. * 2 (paused)
  598. * 3 (buffering)
  599. * 5 (video cued)
  600. */
  601. 'onStateChange': function (event) {
  602. if (typeof event.target.getPlayerState != 'function')
  603. return;
  604. let state = event.target.getPlayerState();
  605. if (YTPlayer.preventTrigger || YTPlayer.isStarting) {
  606. YTPlayer.preventTrigger = false;
  607. return
  608. }
  609. YTPlayer.state = state;
  610. // console.debug(YTPlayer.state);
  611. if (event.data === YT.PlayerState.PLAYING) {
  612. event.target.setPlaybackQuality(YTPlayer.opt.quality)
  613. }
  614. let eventType;
  615. switch (state) {
  616. /** unstarted */
  617. case -1:
  618. eventType = 'YTPUnstarted';
  619. break;
  620. /** unstarted */
  621. case 0:
  622. eventType = 'YTPRealEnd';
  623. break;
  624. /** play */
  625. case 1:
  626. eventType = 'YTPPlay';
  627. if (YTPlayer.controlBar.length)
  628. YTPlayer.controlBar.find('.mb_YTPPlayPause').html(jQuery.mbYTPlayer.controls.pause);
  629. if (YTPlayer.isPlayer)
  630. YTPlayer.inlinePlayButton.hide();
  631. jQuery(document).off('mousedown.YTPstart');
  632. break;
  633. /** pause */
  634. case 2:
  635. eventType = 'YTPPause';
  636. if (YTPlayer.controlBar.length)
  637. YTPlayer.controlBar.find('.mb_YTPPlayPause').html(jQuery.mbYTPlayer.controls.play);
  638. if (YTPlayer.isPlayer)
  639. YTPlayer.inlinePlayButton.show();
  640. break;
  641. /** buffer */
  642. case 3:
  643. // YTPlayer.player.setPlaybackQuality('default');
  644. YTPlayer.player.setPlaybackQuality(YTPlayer.opt.quality);
  645. eventType = 'YTPBuffering';
  646. if (YTPlayer.controlBar.length)
  647. YTPlayer.controlBar.find('.mb_YTPPlayPause').html(jQuery.mbYTPlayer.controls.play);
  648. break;
  649. /** cued */
  650. case 5:
  651. eventType = 'YTPCued';
  652. break;
  653. default:
  654. break
  655. }
  656. /**
  657. Trigger state events
  658. */
  659. let YTPEvent = jQuery.Event(eventType);
  660. YTPEvent.time = YTPlayer.currentTime;
  661. jQuery(YTPlayer).trigger(YTPEvent)
  662. },
  663. /**
  664. * onPlaybackQualityChange
  665. * @param e
  666. */
  667. 'onPlaybackQualityChange': function (e) {
  668. let quality = e.target.getPlaybackQuality();
  669. let YTPQualityChange = jQuery.Event('YTPQualityChange');
  670. YTPQualityChange.quality = quality;
  671. jQuery(YTPlayer).trigger(YTPQualityChange)
  672. },
  673. /**
  674. * onError
  675. * @param err
  676. *
  677. 2 – The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.
  678. 5 – The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.
  679. 100 – The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.
  680. 101 – The owner of the requested video does not allow it to be played in embedded players.
  681. 150 – This error is the same as 101. It's just a 101 error in disguise!
  682. */
  683. 'onError': function (err) {
  684. if (typeof YTPlayer.opt.onError == 'function')
  685. YTPlayer.opt.onError($YTPlayer, err);
  686. console.debug("error:", err);
  687. switch (err.data) {
  688. case 2:
  689. console.error('video ID:: ' + YTPlayer.videoID + ': The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.');
  690. break;
  691. case 5:
  692. console.error('video ID:: ' + YTPlayer.videoID + ': The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.');
  693. break;
  694. case 100:
  695. console.error('video ID:: ' + YTPlayer.videoID + ': The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.');
  696. break;
  697. case 101:
  698. case 150:
  699. console.error('video ID:: ' + YTPlayer.videoID + ': The video doesn\'t exist or The owner does not allow it to be played in embedded players.');
  700. break
  701. }
  702. if (YTPlayer.isList)
  703. jQuery(YTPlayer).YTPPlayNext()
  704. }
  705. }
  706. });
  707. $YTPlayer.on('YTPlayerIsReady_' + YTPlayer.id, function () {
  708. if (YTPlayer.isReady)
  709. return this;
  710. YTPlayer.playerEl = YTPlayer.player.getIframe();
  711. jQuery(YTPlayer.playerEl).unselectable();
  712. $YTPlayer.optimizeDisplay();
  713. /**
  714. * Optimize display on resize
  715. */
  716. jQuery(window).off('resize.YTP_' + YTPlayer.id).on('resize.YTP_' + YTPlayer.id, function () {
  717. $YTPlayer.optimizeDisplay()
  718. });
  719. /**
  720. * Optimize display on orientation change
  721. */
  722. jQuery(window).off('orientationchange.YTP_' + YTPlayer.id).on('orientationchange.YTP_' + YTPlayer.id, function () {
  723. $YTPlayer.optimizeDisplay()
  724. });
  725. /**
  726. * Set the time of the last visit progress
  727. */
  728. if (YTPlayer.opt.remember_last_time) {
  729. jQuery(window).on('unload.YTP_' + YTPlayer.id, function () {
  730. let current_time = YTPlayer.player.getCurrentTime();
  731. jQuery.mbCookie.set('YTPlayer_start_from' + YTPlayer.videoID, current_time, 0)
  732. })
  733. }
  734. $YTPlayer.YTPCheckForState()
  735. })
  736. })
  737. });
  738. $YTPlayer.off('YTPTime.mask');
  739. jQuery.mbYTPlayer.applyMask(YTPlayer);
  740. console.timeEnd(YTPTimerLabels.init);
  741. setTimeout(function () {
  742. if (!ytp.YTAPIReady && typeof window.YT == "object") {
  743. jQuery(document).trigger('YTAPIReady');
  744. ytp.YTAPIReady = true;
  745. console.error("YTPlayer: More then a call to the YT API has been detected")
  746. }
  747. }, YTPlayer.opt.delayAtStart)
  748. })
  749. },
  750. /**
  751. *
  752. * @param YTPlayer
  753. * @param perc
  754. * @returns {boolean}
  755. */
  756. isOnScreen: function (YTPlayer, perc) {
  757. perc = perc || 10;
  758. let playerBox = YTPlayer.wrapper;
  759. let winTop = jQuery(window).scrollTop();
  760. let winBottom = winTop + jQuery(window).height();
  761. let margin = (playerBox.height() * perc) / 100;
  762. let elTop = playerBox.offset().top + margin;
  763. let elBottom = playerBox.offset().top + (playerBox.height() - margin);
  764. return ((elBottom <= winBottom) && (elTop >= winTop))
  765. },
  766. /**
  767. * getDataFromAPI
  768. * @param YTPlayer
  769. */
  770. getDataFromAPI: function (YTPlayer) {
  771. YTPlayer.videoData = jQuery.mbStorage.get('YTPlayer_data_' + YTPlayer.videoID);
  772. if (YTPlayer.videoData) {
  773. setTimeout(function () {
  774. YTPlayer.dataReceived = true;
  775. let YTPChanged = jQuery.Event('YTPChanged');
  776. YTPChanged.time = YTPlayer.currentTime;
  777. YTPChanged.videoId = YTPlayer.videoID;
  778. YTPChanged.opt = YTPlayer.opt;
  779. //console.debug("videoData:",YTPlayer.videoData)
  780. jQuery(YTPlayer).trigger(YTPChanged);
  781. let YTPData = jQuery.Event('YTPData');
  782. YTPData.prop = {};
  783. for (let x in YTPlayer.videoData)
  784. if (YTPlayer.videoData.hasOwnProperty(x))
  785. YTPData.prop[x] = YTPlayer.videoData[x];
  786. jQuery(YTPlayer).trigger(YTPData)
  787. }, YTPlayer.opt.fadeOnStartTime);
  788. YTPlayer.hasData = true
  789. } else if (jQuery.mbYTPlayer.apiKey) {
  790. /**
  791. * Get video info from API3 (needs api key)
  792. * snippet,player,contentDetails,statistics,status
  793. */
  794. jQuery.getJSON('https://www.googleapis.com/youtube/v3/videos?id=' + YTPlayer.videoID + '&key=' + jQuery.mbYTPlayer.apiKey + '&part=snippet', function (data) {
  795. YTPlayer.dataReceived = true;
  796. let YTPChanged = jQuery.Event('YTPChanged');
  797. YTPChanged.time = YTPlayer.currentTime;
  798. YTPChanged.videoId = YTPlayer.videoID;
  799. jQuery(YTPlayer).trigger(YTPChanged);
  800. function parseYTPlayer_data(data) {
  801. YTPlayer.videoData = {};
  802. YTPlayer.videoData.id = YTPlayer.videoID;
  803. YTPlayer.videoData.channelTitle = data.channelTitle;
  804. YTPlayer.videoData.title = data.title;
  805. YTPlayer.videoData.description = data.description.length < 400 ? data.description : data.description.substring(0, 400) + ' ...';
  806. YTPlayer.videoData.thumb_max = data.thumbnails.maxres ? data.thumbnails.maxres.url : null;
  807. YTPlayer.videoData.thumb_high = data.thumbnails.high ? data.thumbnails.high.url : null;
  808. YTPlayer.videoData.thumb_medium = data.thumbnails.medium ? data.thumbnails.medium.url : null;
  809. jQuery.mbStorage.set('YTPlayer_data_' + YTPlayer.videoID, YTPlayer.videoData)
  810. }
  811. if (!data.items[0]) {
  812. YTPlayer.videoData = {};
  813. YTPlayer.hasData = false
  814. } else {
  815. parseYTPlayer_data(data.items[0].snippet);
  816. YTPlayer.hasData = true
  817. }
  818. let YTPData = jQuery.Event('YTPData');
  819. YTPData.prop = {};
  820. for (let x in YTPlayer.videoData)
  821. YTPData.prop[x] = YTPlayer.videoData[x];
  822. jQuery(YTPlayer).trigger(YTPData)
  823. })
  824. .fail(function (jqxhr) {
  825. console.error("YT data error:: ", jqxhr);
  826. YTPlayer.hasData = false;
  827. let YTPChanged = jQuery.Event('YTPChanged');
  828. YTPChanged.time = YTPlayer.currentTime;
  829. YTPChanged.videoId = YTPlayer.videoID;
  830. jQuery(YTPlayer).trigger(YTPChanged)
  831. })
  832. } else {
  833. setTimeout(function () {
  834. let YTPChanged = jQuery.Event('YTPChanged');
  835. YTPChanged.time = YTPlayer.currentTime;
  836. YTPChanged.videoId = YTPlayer.videoID;
  837. jQuery(YTPlayer).trigger(YTPChanged)
  838. }, 10);
  839. YTPlayer.videoData = null
  840. }
  841. YTPlayer.opt.ratio = YTPlayer.opt.ratio == 'auto' ? 16 / 9 : YTPlayer.opt.ratio;
  842. if (YTPlayer.isPlayer && !YTPlayer.opt.autoPlay) { //&& ( !jQuery.mbBrowser.mobile && !jQuery.isTablet )
  843. YTPlayer.loading = jQuery('<div/>').addClass('loading').html('Loading').hide();
  844. jQuery(YTPlayer).append(YTPlayer.loading);
  845. YTPlayer.loading.fadeIn()
  846. }
  847. },
  848. /**
  849. * removeStoredData
  850. */
  851. removeStoredData: function () {
  852. jQuery.mbStorage.remove()
  853. },
  854. /**
  855. * getVideoData
  856. * @returns {*|YTPlayer.videoData}
  857. */
  858. getVideoData: function () {
  859. let YTPlayer = this.get(0);
  860. return YTPlayer.videoData
  861. },
  862. /**
  863. * getVideoID
  864. * @returns {*|YTPlayer.videoID|boolean}
  865. */
  866. getVideoID: function () {
  867. let YTPlayer = this.get(0);
  868. return YTPlayer.videoID || false
  869. },
  870. /**
  871. * getPlaylistID
  872. * @returns {*|YTPlayer.videoID|boolean}
  873. */
  874. getPlaylistID : function () {
  875. let YTPlayer = this.get(0);
  876. return YTPlayer.playlistID || false
  877. },
  878. /**
  879. * setVideoQuality
  880. * @deprecated
  881. *
  882. * @param quality
  883. * @returns {jQuery.mbYTPlayer}
  884. */
  885. setVideoQuality: function (quality) {
  886. let YTPlayer = this.get(0);
  887. let time = YTPlayer.player.getCurrentTime();
  888. jQuery(YTPlayer).YTPPause();
  889. YTPlayer.opt.quality = quality;
  890. YTPlayer.player.setPlaybackQuality(quality);
  891. YTPlayer.player.seekTo(time); // or set to CurrentTime using player.getCurrentTime()
  892. jQuery(YTPlayer).YTPPlay();
  893. return this;
  894. },
  895. /**
  896. * getVideoQuality
  897. * @returns {jQuery.mbYTPlayer}
  898. */
  899. getVideoQuality: function () {
  900. let YTPlayer = this.get(0);
  901. let quality = YTPlayer.player.getPlaybackQuality();
  902. return quality
  903. },
  904. /**
  905. * playlist
  906. * @param videos -> Array or String (videoList ID)
  907. * @param shuffle
  908. * @param callback
  909. * @returns {jQuery.mbYTPlayer}
  910. *
  911. * To retrieve a Youtube playlist the Youtube API key is required:
  912. * https://console.developers.google.com/
  913. * jQuery.mbYTPlayer.apiKey
  914. */
  915. playlist: function (videos, shuffle, callback) {
  916. let $YTPlayer = this;
  917. let YTPlayer = $YTPlayer.get(0);
  918. YTPlayer.isList = true;
  919. if (shuffle)
  920. videos = jQuery.shuffle(videos);
  921. if (!YTPlayer.videoID) {
  922. YTPlayer.videos = videos;
  923. YTPlayer.videoCounter = 1;
  924. YTPlayer.videoLength = videos.length;
  925. jQuery(YTPlayer).data('property', videos[0]);
  926. jQuery(YTPlayer).YTPlayer()
  927. }
  928. if (typeof callback == 'function')
  929. jQuery(YTPlayer).on('YTPChanged', function () {
  930. callback(YTPlayer)
  931. });
  932. jQuery(YTPlayer).on('YTPEnd', function () {
  933. jQuery(YTPlayer).YTPPlayNext()
  934. });
  935. return this
  936. },
  937. /**
  938. * playNext
  939. * @returns {jQuery.mbYTPlayer}
  940. */
  941. playNext: function () {
  942. let YTPlayer = this.get(0);
  943. YTPlayer.videoCounter++;
  944. if (YTPlayer.videoCounter > YTPlayer.videoLength)
  945. YTPlayer.videoCounter = 1;
  946. jQuery(YTPlayer).YTPPlayIndex(YTPlayer.videoCounter);
  947. return this
  948. },
  949. /**
  950. * playPrev
  951. * @returns {jQuery.mbYTPlayer}
  952. */
  953. playPrev: function () {
  954. let YTPlayer = this.get(0);
  955. YTPlayer.videoCounter--;
  956. if (YTPlayer.videoCounter <= 0)
  957. YTPlayer.videoCounter = YTPlayer.videoLength;
  958. jQuery(YTPlayer).YTPPlayIndex(YTPlayer.videoCounter);
  959. return this
  960. },
  961. /**
  962. * playIndex
  963. * @param idx
  964. * @returns {jQuery.mbYTPlayer}
  965. */
  966. playIndex: function (idx) {
  967. let YTPlayer = this.get(0);
  968. if (YTPlayer.checkForStartAt) {
  969. clearInterval(YTPlayer.checkForStartAt);
  970. clearInterval(YTPlayer.getState)
  971. }
  972. YTPlayer.videoCounter = idx;
  973. if (YTPlayer.videoCounter >= YTPlayer.videoLength)
  974. YTPlayer.videoCounter = YTPlayer.videoLength;
  975. let video = YTPlayer.videos[YTPlayer.videoCounter - 1];
  976. jQuery(YTPlayer).YTPChangeVideo(video);
  977. return this
  978. },
  979. /**
  980. * changeVideo
  981. * @param opt
  982. * @returns {jQuery.mbYTPlayer}
  983. */
  984. changeVideo: function (opt) {
  985. let $YTPlayer = this;
  986. let YTPlayer = $YTPlayer.get(0);
  987. YTPlayer.opt.startAt = 0;
  988. YTPlayer.opt.stopAt = 0;
  989. YTPlayer.opt.mask = false;
  990. YTPlayer.opt.mute = true;
  991. YTPlayer.opt.autoPlay = true;
  992. YTPlayer.opt.addFilters = false;
  993. YTPlayer.opt.coverImage = false;
  994. YTPlayer.hasData = false;
  995. YTPlayer.hasChanged = true;
  996. YTPlayer.player.loopTime = undefined;
  997. if (opt)
  998. jQuery.extend(YTPlayer.opt, opt);
  999. YTPlayer.videoID = getYTPVideoID(YTPlayer.opt.videoURL).videoID;
  1000. if (YTPlayer.opt.loop && typeof YTPlayer.opt.loop == 'boolean')
  1001. YTPlayer.opt.loop = 9999;
  1002. YTPlayer.wrapper.css({
  1003. background: 'none'
  1004. });
  1005. jQuery(YTPlayer.playerEl).CSSAnimate({
  1006. opacity: 0
  1007. }, YTPlayer.opt.fadeOnStartTime, function () {
  1008. jQuery.mbYTPlayer.getDataFromAPI(YTPlayer);
  1009. $YTPlayer.YTPGetPlayer().loadVideoById({
  1010. videoId : YTPlayer.videoID,
  1011. suggestedQuality: YTPlayer.opt.quality
  1012. });
  1013. $YTPlayer.YTPPause();
  1014. $YTPlayer.optimizeDisplay();
  1015. if (YTPlayer.checkForStartAt) {
  1016. clearInterval(YTPlayer.checkForStartAt);
  1017. clearInterval(YTPlayer.getState)
  1018. }
  1019. $YTPlayer.YTPCheckForState()
  1020. });
  1021. let YTPChangeVideo = jQuery.Event('YTPChangeVideo');
  1022. YTPChangeVideo.time = YTPlayer.currentTime;
  1023. jQuery(YTPlayer).trigger(YTPChangeVideo);
  1024. jQuery.mbYTPlayer.applyMask(YTPlayer);
  1025. return this
  1026. },
  1027. /**
  1028. * getPlayer
  1029. * @returns {player}
  1030. */
  1031. getPlayer: function () {
  1032. let YTPlayer = this.get(0);
  1033. return !YTPlayer.isReady ? null : YTPlayer.player
  1034. },
  1035. /**
  1036. * playerDestroy
  1037. * @returns {jQuery.mbYTPlayer}
  1038. */
  1039. playerDestroy: function () {
  1040. let YTPlayer = this.get(0);
  1041. if (!YTPlayer.isReady)
  1042. return this;
  1043. ytp.YTAPIReady = true;
  1044. ytp.backgroundIsInited = false;
  1045. YTPlayer.isInit = false;
  1046. YTPlayer.videoID = null;
  1047. YTPlayer.isReady = false;
  1048. YTPlayer.wrapper.remove();
  1049. jQuery('#controlBar_' + YTPlayer.id).remove();
  1050. clearInterval(YTPlayer.checkForStartAt);
  1051. clearInterval(YTPlayer.getState);
  1052. return this
  1053. },
  1054. /**
  1055. * fullscreen
  1056. * @param real
  1057. * @returns {jQuery.mbYTPlayer}
  1058. */
  1059. fullscreen: function (real) {
  1060. let YTPlayer = this.get(0);
  1061. if (typeof real == 'undefined')
  1062. real = eval(YTPlayer.opt.realFullscreen);
  1063. let controls = jQuery('#controlBar_' + YTPlayer.id);
  1064. let fullScreenBtn = controls.find('.mb_OnlyYT');
  1065. let videoWrapper = YTPlayer.isPlayer ? YTPlayer.opt.containment : YTPlayer.wrapper;
  1066. if (real) {
  1067. let fullscreenchange = jQuery.mbBrowser.mozilla ? 'mozfullscreenchange' : jQuery.mbBrowser.webkit ? 'webkitfullscreenchange' : 'fullscreenchange';
  1068. jQuery(document).off(fullscreenchange).on(fullscreenchange, function () {
  1069. let isFullScreen = RunPrefixMethod(document, 'IsFullScreen') || RunPrefixMethod(document, 'FullScreen');
  1070. if (!isFullScreen) {
  1071. YTPlayer.isAlone = false;
  1072. fullScreenBtn.html(jQuery.mbYTPlayer.controls.onlyYT);
  1073. jQuery(YTPlayer).YTPSetVideoQuality(YTPlayer.opt.quality);
  1074. videoWrapper.removeClass('YTPFullscreen');
  1075. videoWrapper.CSSAnimate({
  1076. opacity: YTPlayer.opt.opacity
  1077. }, YTPlayer.opt.fadeOnStartTime);
  1078. videoWrapper.css({
  1079. zIndex: 0
  1080. });
  1081. if (YTPlayer.isBackground) {
  1082. jQuery('body').after(controls)
  1083. } else {
  1084. YTPlayer.wrapper.before(controls)
  1085. }
  1086. jQuery(window).resize();
  1087. jQuery(YTPlayer).trigger('YTPFullScreenEnd')
  1088. } else {
  1089. jQuery(YTPlayer).trigger('YTPFullScreenStart')
  1090. }
  1091. })
  1092. }
  1093. if (!YTPlayer.isAlone) {
  1094. function hideMouse() {
  1095. YTPlayer.overlay.css({
  1096. cursor: 'none'
  1097. })
  1098. }
  1099. jQuery(document).on('mousemove.YTPlayer', function (e) {
  1100. YTPlayer.overlay.css({
  1101. cursor: 'auto'
  1102. });
  1103. clearTimeout(YTPlayer.hideCursor);
  1104. if (!jQuery(e.target).parents().is('.mb_YTPBar'))
  1105. YTPlayer.hideCursor = setTimeout(hideMouse, 3000)
  1106. });
  1107. hideMouse();
  1108. if (real) {
  1109. videoWrapper.css({
  1110. opacity: 0
  1111. });
  1112. videoWrapper.addClass('YTPFullscreen');
  1113. launchFullscreen(videoWrapper.get(0));
  1114. setTimeout(function () {
  1115. videoWrapper.CSSAnimate({
  1116. opacity: 1
  1117. }, YTPlayer.opt.fadeOnStartTime * 2);
  1118. videoWrapper.append(controls);
  1119. jQuery(YTPlayer).optimizeDisplay();
  1120. YTPlayer.player.seekTo(YTPlayer.player.getCurrentTime() + .1, true)
  1121. }, YTPlayer.opt.fadeOnStartTime)
  1122. } else
  1123. videoWrapper.css({
  1124. zIndex: 10000
  1125. }).CSSAnimate({
  1126. opacity: 1
  1127. }, YTPlayer.opt.fadeOnStartTime * 2);
  1128. fullScreenBtn.html(jQuery.mbYTPlayer.controls.showSite);
  1129. YTPlayer.isAlone = true
  1130. } else {
  1131. jQuery(document).off('mousemove.YTPlayer');
  1132. clearTimeout(YTPlayer.hideCursor);
  1133. YTPlayer.overlay.css({
  1134. cursor: 'auto'
  1135. });
  1136. if (real) {
  1137. cancelFullscreen()
  1138. } else {
  1139. videoWrapper.CSSAnimate({
  1140. opacity: YTPlayer.opt.opacity
  1141. }, YTPlayer.opt.fadeOnStartTime);
  1142. videoWrapper.css({
  1143. zIndex: 0
  1144. })
  1145. }
  1146. fullScreenBtn.html(jQuery.mbYTPlayer.controls.onlyYT);
  1147. YTPlayer.isAlone = false
  1148. }
  1149. function RunPrefixMethod(obj, method) {
  1150. let pfx = ['webkit', 'moz', 'ms', 'o', ''];
  1151. let p = 0,
  1152. m, t;
  1153. while (p < pfx.length && !obj[m]) {
  1154. m = method;
  1155. if (pfx[p] === '') {
  1156. m = m.substr(0, 1).toLowerCase() + m.substr(1)
  1157. }
  1158. m = pfx[p] + m;
  1159. t = typeof obj[m];
  1160. if (t != 'undefined') {
  1161. pfx = [pfx[p]];
  1162. return (t == 'function' ? obj[m]() : obj[m])
  1163. }
  1164. p++
  1165. }
  1166. }
  1167. function launchFullscreen(element) {
  1168. RunPrefixMethod(element, 'RequestFullScreen')
  1169. }
  1170. function cancelFullscreen() {
  1171. if (RunPrefixMethod(document, 'FullScreen') || RunPrefixMethod(document, 'IsFullScreen')) {
  1172. RunPrefixMethod(document, 'CancelFullScreen')
  1173. }
  1174. }
  1175. return this
  1176. },
  1177. /**
  1178. * toggleLoops
  1179. * @returns {jQuery.mbYTPlayer}
  1180. */
  1181. toggleLoops: function () {
  1182. let YTPlayer = this.get(0);
  1183. let data = YTPlayer.opt;
  1184. if (data.loop == 1) {
  1185. data.loop = 0
  1186. } else {
  1187. if (data.startAt) {
  1188. YTPlayer.player.seekTo(data.startAt)
  1189. } else {
  1190. YTPlayer.player.playVideo()
  1191. }
  1192. data.loop = 1
  1193. }
  1194. return this
  1195. },
  1196. /**
  1197. * play
  1198. * @returns {jQuery.mbYTPlayer}
  1199. */
  1200. play: function () {
  1201. let YTPlayer = this.get(0);
  1202. let $YTPlayer = jQuery(YTPlayer);
  1203. if (!YTPlayer.isReady)
  1204. return this;
  1205. setTimeout(function () {
  1206. $YTPlayer.YTPSetAbundance(YTPlayer.opt.abundance)
  1207. }, 300);
  1208. YTPlayer.player.playVideo();
  1209. jQuery(YTPlayer.playerEl).css({
  1210. opacity: 1
  1211. });
  1212. YTPlayer.wrapper.css({
  1213. backgroundImage: 'none'
  1214. });
  1215. YTPlayer.wrapper.CSSAnimate({
  1216. opacity: YTPlayer.isAlone ? 1 : YTPlayer.opt.opacity
  1217. }, YTPlayer.opt.fadeOnStartTime);
  1218. let controls = jQuery('#controlBar_' + YTPlayer.id);
  1219. let playBtn = controls.find('.mb_YTPPlayPause');
  1220. playBtn.html(jQuery.mbYTPlayer.controls.pause);
  1221. YTPlayer.state = 1;
  1222. return this
  1223. },
  1224. /**
  1225. * togglePlay
  1226. * @param callback
  1227. * @returns {jQuery.mbYTPlayer}
  1228. */
  1229. togglePlay: function (callback) {
  1230. let YTPlayer = this.get(0);
  1231. if (!YTPlayer.isReady)
  1232. return this;
  1233. if (YTPlayer.state === 1)
  1234. this.YTPPause();
  1235. else
  1236. this.YTPPlay();
  1237. if (typeof callback == 'function')
  1238. callback(YTPlayer.state);
  1239. return this
  1240. },
  1241. /**
  1242. * stop
  1243. * @returns {jQuery.mbYTPlayer}
  1244. */
  1245. stop: function () {
  1246. let YTPlayer = this.get(0);
  1247. if (!YTPlayer.isReady)
  1248. return this;
  1249. let controls = jQuery('#controlBar_' + YTPlayer.id);
  1250. let playBtn = controls.find('.mb_YTPPlayPause');
  1251. playBtn.html(jQuery.mbYTPlayer.controls.play);
  1252. YTPlayer.player.stopVideo();
  1253. return this
  1254. },
  1255. /**
  1256. * pause
  1257. * @returns {jQuery.mbYTPlayer}
  1258. */
  1259. pause: function () {
  1260. let YTPlayer = this.get(0);
  1261. if (!YTPlayer.isReady)
  1262. return this;
  1263. if (YTPlayer.opt.abundance < .2)
  1264. this.YTPSetAbundance(.2);
  1265. YTPlayer.player.pauseVideo();
  1266. YTPlayer.state = 2;
  1267. return this
  1268. },
  1269. /**
  1270. * seekTo
  1271. * @param sec
  1272. * @returns {jQuery.mbYTPlayer}
  1273. */
  1274. seekTo: function (sec) {
  1275. let YTPlayer = this.get(0);
  1276. if (!YTPlayer.isReady)
  1277. return this;
  1278. YTPlayer.player.seekTo(sec, true);
  1279. return this
  1280. },
  1281. /**
  1282. *
  1283. * @returns {*}
  1284. */
  1285. getPlaybackRate: function () {
  1286. let YTPlayer = this.get(0);
  1287. if (!YTPlayer.isReady)
  1288. return this;
  1289. return YTPlayer.player.getPlaybackRate()
  1290. },
  1291. /**
  1292. * setPlaybackRate
  1293. * @param val:Number
  1294. * 0.25, 0.5, 1, 1.5, 2
  1295. * @returns {jQuery.mbYTPlayer}
  1296. */
  1297. setPlaybackRate: function (val) {
  1298. let YTPlayer = this.get(0);
  1299. if (!YTPlayer.isReady)
  1300. return this;
  1301. YTPlayer.player.setPlaybackRate(val);
  1302. return this
  1303. },
  1304. /**
  1305. * setVolume
  1306. * @param val
  1307. * @returns {jQuery.mbYTPlayer}
  1308. */
  1309. setVolume: function (val) {
  1310. let YTPlayer = this.get(0);
  1311. if (!YTPlayer.isReady)
  1312. return this;
  1313. YTPlayer.opt.vol = val;
  1314. this.YTPUnmute();
  1315. YTPlayer.player.setVolume(YTPlayer.opt.vol);
  1316. if (YTPlayer.volumeBar && YTPlayer.volumeBar.length)
  1317. YTPlayer.volumeBar.updateSliderVal(val);
  1318. return this
  1319. },
  1320. /**
  1321. * getVolume
  1322. * @returns {*}
  1323. */
  1324. getVolume: function () {
  1325. let YTPlayer = this.get(0);
  1326. if (!YTPlayer.isReady)
  1327. return this;
  1328. return YTPlayer.player.getVolume()
  1329. },
  1330. /**
  1331. * toggleVolume
  1332. * @returns {jQuery.mbYTPlayer}
  1333. */
  1334. toggleVolume: function () {
  1335. let YTPlayer = this.get(0);
  1336. if (!YTPlayer.isReady)
  1337. return this;
  1338. if (YTPlayer.isMute) {
  1339. if (!jQuery.mbBrowser.mobile)
  1340. this.YTPSetVolume(YTPlayer.opt.vol);
  1341. this.YTPUnmute()
  1342. } else {
  1343. this.YTPMute()
  1344. }
  1345. return this
  1346. },
  1347. /**
  1348. * mute
  1349. * @returns {jQuery.mbYTPlayer}
  1350. */
  1351. mute: function () {
  1352. let YTPlayer = this.get(0);
  1353. if (!YTPlayer.isReady)
  1354. return this;
  1355. if (YTPlayer.isMute)
  1356. return this;
  1357. YTPlayer.player.mute();
  1358. YTPlayer.isMute = true;
  1359. YTPlayer.player.setVolume(0);
  1360. if (YTPlayer.volumeBar && YTPlayer.volumeBar.length && YTPlayer.volumeBar.width() > 10) {
  1361. YTPlayer.volumeBar.updateSliderVal(0)
  1362. }
  1363. let controls = jQuery('#controlBar_' + YTPlayer.id);
  1364. let muteBtn = controls.find('.mb_YTPMuteUnmute');
  1365. muteBtn.html(jQuery.mbYTPlayer.controls.unmute);
  1366. jQuery(YTPlayer).addClass('isMuted');
  1367. if (YTPlayer.volumeBar && YTPlayer.volumeBar.length) YTPlayer.volumeBar.addClass('muted');
  1368. let YTPEvent = jQuery.Event('YTPMuted');
  1369. YTPEvent.time = YTPlayer.currentTime;
  1370. if (!YTPlayer.preventTrigger)
  1371. jQuery(YTPlayer).trigger(YTPEvent);
  1372. return this
  1373. },
  1374. /**
  1375. * unmute
  1376. * @returns {jQuery.mbYTPlayer}
  1377. */
  1378. unmute: function () {
  1379. let YTPlayer = this.get(0);
  1380. if (!YTPlayer.isReady)
  1381. return this;
  1382. if (!YTPlayer.isMute)
  1383. return this;
  1384. YTPlayer.player.unMute();
  1385. YTPlayer.isMute = false;
  1386. jQuery(YTPlayer).YTPSetVolume(YTPlayer.opt.vol);
  1387. if (YTPlayer.volumeBar && YTPlayer.volumeBar.length)
  1388. YTPlayer.volumeBar.updateSliderVal(YTPlayer.opt.vol > 10 ? YTPlayer.opt.vol : 10);
  1389. let controls = jQuery('#controlBar_' + YTPlayer.id);
  1390. let muteBtn = controls.find('.mb_YTPMuteUnmute');
  1391. muteBtn.html(jQuery.mbYTPlayer.controls.mute);
  1392. jQuery(YTPlayer).removeClass('isMuted');
  1393. if (YTPlayer.volumeBar && YTPlayer.volumeBar.length)
  1394. YTPlayer.volumeBar.removeClass('muted');
  1395. let YTPEvent = jQuery.Event('YTPUnmuted');
  1396. YTPEvent.time = YTPlayer.currentTime;
  1397. if (!YTPlayer.preventTrigger)
  1398. jQuery(YTPlayer).trigger(YTPEvent);
  1399. return this
  1400. },
  1401. /* FILTERS ---------------------------------------------------------------------------------------------------------*/
  1402. /**
  1403. * applyFilter
  1404. * @param filter
  1405. * @param value
  1406. * @returns {jQuery.mbYTPlayer}
  1407. */
  1408. applyFilter: function (filter, value) {
  1409. let $YTPlayer = this;
  1410. let YTPlayer = $YTPlayer.get(0);
  1411. if (!YTPlayer.isReady)
  1412. return this;
  1413. YTPlayer.filters[filter].value = value;
  1414. if (YTPlayer.filtersEnabled)
  1415. $YTPlayer.YTPEnableFilters()
  1416. },
  1417. /**
  1418. * applyFilters
  1419. * @param filters
  1420. * @returns {jQuery.mbYTPlayer}
  1421. */
  1422. applyFilters: function (filters) {
  1423. let $YTPlayer = this;
  1424. let YTPlayer = $YTPlayer.get(0);
  1425. if (!YTPlayer.isReady) {
  1426. jQuery(YTPlayer).on('YTPReady', function () {
  1427. $YTPlayer.YTPApplyFilters(filters)
  1428. });
  1429. return this
  1430. }
  1431. for (let key in filters) {
  1432. $YTPlayer.YTPApplyFilter(key, filters[key])
  1433. }
  1434. $YTPlayer.trigger('YTPFiltersApplied')
  1435. },
  1436. /**
  1437. * toggleFilter
  1438. * @param filter
  1439. * @param value
  1440. * @returns {jQuery.mbYTPlayer}
  1441. */
  1442. toggleFilter: function (filter, value) {
  1443. let $YTPlayer = this;
  1444. let YTPlayer = $YTPlayer.get(0);
  1445. if (!YTPlayer.isReady)
  1446. return this;
  1447. if (!YTPlayer.filters[filter].value)
  1448. YTPlayer.filters[filter].value = value;
  1449. else
  1450. YTPlayer.filters[filter].value = 0;
  1451. if (YTPlayer.filtersEnabled)
  1452. jQuery(YTPlayer).YTPEnableFilters();
  1453. return this
  1454. },
  1455. /**
  1456. * toggleFilters
  1457. * @param callback
  1458. * @returns {jQuery.mbYTPlayer}
  1459. */
  1460. toggleFilters: function (callback) {
  1461. let $YTPlayer = this;
  1462. let YTPlayer = $YTPlayer.get(0);
  1463. if (!YTPlayer.isReady)
  1464. return this;
  1465. if (YTPlayer.filtersEnabled) {
  1466. jQuery(YTPlayer).trigger('YTPDisableFilters');
  1467. jQuery(YTPlayer).YTPDisableFilters()
  1468. } else {
  1469. jQuery(YTPlayer).YTPEnableFilters();
  1470. jQuery(YTPlayer).trigger('YTPEnableFilters')
  1471. }
  1472. if (typeof callback == 'function')
  1473. callback(YTPlayer.filtersEnabled);
  1474. return this
  1475. },
  1476. /**
  1477. * disableFilters
  1478. * @returns {jQuery.mbYTPlayer}
  1479. */
  1480. disableFilters: function () {
  1481. let $YTPlayer = this;
  1482. let YTPlayer = $YTPlayer.get(0);
  1483. if (!YTPlayer.isReady)
  1484. return this;
  1485. let iframe = jQuery(YTPlayer.playerEl);
  1486. iframe.css('-webkit-filter', '');
  1487. iframe.css('filter', '');
  1488. YTPlayer.filtersEnabled = false;
  1489. return this
  1490. },
  1491. /**
  1492. * enableFilters
  1493. * @returns {jQuery.mbYTPlayer}
  1494. */
  1495. enableFilters: function () {
  1496. let $YTPlayer = this;
  1497. let YTPlayer = $YTPlayer.get(0);
  1498. if (!YTPlayer.isReady)
  1499. return this;
  1500. let iframe = jQuery(YTPlayer.playerEl);
  1501. let filterStyle = '';
  1502. for (let key in YTPlayer.filters) {
  1503. if (YTPlayer.filters[key].value)
  1504. filterStyle += key.replace('_', '-') + '(' + YTPlayer.filters[key].value + YTPlayer.filters[key].unit + ') '
  1505. }
  1506. iframe.css('-webkit-filter', filterStyle);
  1507. iframe.css('filter', filterStyle);
  1508. YTPlayer.filtersEnabled = true;
  1509. return this
  1510. },
  1511. /**
  1512. * removeFilter
  1513. * @param filter
  1514. * @param callback
  1515. * @returns {jQuery.mbYTPlayer}
  1516. */
  1517. removeFilter: function (filter, callback) {
  1518. let $YTPlayer = this;
  1519. let YTPlayer = $YTPlayer.get(0);
  1520. if (!YTPlayer.isReady)
  1521. return this;
  1522. if (typeof filter == 'function') {
  1523. callback = filter;
  1524. filter = null
  1525. }
  1526. if (!filter) {
  1527. for (let key in YTPlayer.filters) {
  1528. if (YTPlayer.filters.hasOwnProperty(key)) {
  1529. $YTPlayer.YTPApplyFilter(key, 0);
  1530. if (typeof callback == 'function')
  1531. callback(key);
  1532. }
  1533. }
  1534. YTPlayer.filters = jQuery.extend(true, {}, jQuery.mbYTPlayer.defaultFilters)
  1535. } else {
  1536. $YTPlayer.YTPApplyFilter(filter, 0);
  1537. if (typeof callback == 'function') callback(filter)
  1538. }
  1539. let YTPEvent = jQuery.Event('YTPFiltersApplied');
  1540. $YTPlayer.trigger(YTPEvent);
  1541. return this
  1542. },
  1543. /**
  1544. * getFilters
  1545. * @returns {filters}
  1546. */
  1547. getFilters: function () {
  1548. let YTPlayer = this.get(0);
  1549. if (!YTPlayer.isReady)
  1550. return this;
  1551. return YTPlayer.filters
  1552. },
  1553. /* MASK ---------------------------------------------------------------------------------------------------------*/
  1554. /**
  1555. * addMask
  1556. * @param mask
  1557. * @returns {jQuery.mbYTPlayer}
  1558. */
  1559. addMask: function (mask) {
  1560. let YTPlayer = this.get(0);
  1561. if (!mask)
  1562. mask = YTPlayer.actualMask;
  1563. let tempImg = jQuery('<img/>').attr('src', mask).on('load', function () {
  1564. YTPlayer.overlay.CSSAnimate({
  1565. opacity: 0
  1566. }, YTPlayer.opt.fadeOnStartTime, function () {
  1567. YTPlayer.hasMask = true;
  1568. tempImg.remove();
  1569. YTPlayer.overlay.css({
  1570. backgroundImage : 'url(' + mask + ')',
  1571. backgroundRepeat : 'no-repeat',
  1572. backgroundPosition: 'center center',
  1573. backgroundSize : 'cover'
  1574. });
  1575. YTPlayer.overlay.CSSAnimate({
  1576. opacity: 1
  1577. }, YTPlayer.opt.fadeOnStartTime)
  1578. })
  1579. });
  1580. return this
  1581. },
  1582. /**
  1583. * removeMask
  1584. * @returns {jQuery.mbYTPlayer}
  1585. */
  1586. removeMask: function () {
  1587. let YTPlayer = this.get(0);
  1588. YTPlayer.overlay.CSSAnimate({
  1589. opacity: 0
  1590. }, YTPlayer.opt.fadeOnStartTime, function () {
  1591. YTPlayer.hasMask = false;
  1592. YTPlayer.overlay.css({
  1593. backgroundImage : '',
  1594. backgroundRepeat : '',
  1595. backgroundPosition: '',
  1596. backgroundSize : ''
  1597. });
  1598. YTPlayer.overlay.CSSAnimate({
  1599. opacity: 1
  1600. }, YTPlayer.opt.fadeOnStartTime)
  1601. });
  1602. return this
  1603. },
  1604. /**
  1605. * Apply mask
  1606. * @param YTPlayer
  1607. */
  1608. applyMask: function (YTPlayer) {
  1609. let $YTPlayer = jQuery(YTPlayer);
  1610. $YTPlayer.off('YTPTime.mask');
  1611. if (YTPlayer.opt.mask) {
  1612. if (typeof YTPlayer.opt.mask == 'string') {
  1613. $YTPlayer.YTPAddMask(YTPlayer.opt.mask);
  1614. YTPlayer.actualMask = YTPlayer.opt.mask
  1615. } else if (typeof YTPlayer.opt.mask == 'object') {
  1616. for (let time in YTPlayer.opt.mask) {
  1617. if (YTPlay