/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

  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 (YTPlayer.opt.mask[time])
  1618. img = jQuery('<img/>').attr('src', YTPlayer.opt.mask[time])
  1619. }
  1620. if (YTPlayer.opt.mask[0])
  1621. $YTPlayer.YTPAddMask(YTPlayer.opt.mask[0]);
  1622. $YTPlayer.on('YTPTime.mask', function (e) {
  1623. for (let time in YTPlayer.opt.mask) {
  1624. if (e.time === time)
  1625. if (!YTPlayer.opt.mask[time]) {
  1626. $YTPlayer.YTPRemoveMask()
  1627. } else {
  1628. $YTPlayer.YTPAddMask(YTPlayer.opt.mask[time]);
  1629. YTPlayer.actualMask = YTPlayer.opt.mask[time]
  1630. }
  1631. }
  1632. })
  1633. }
  1634. }
  1635. },
  1636. /**
  1637. * toggleMask
  1638. * @returns {jQuery.mbYTPlayer}
  1639. */
  1640. toggleMask: function () {
  1641. let YTPlayer = this.get(0);
  1642. let $YTPlayer = jQuery(YTPlayer);
  1643. if (YTPlayer.hasMask)
  1644. $YTPlayer.YTPRemoveMask();
  1645. else
  1646. $YTPlayer.YTPAddMask();
  1647. return this
  1648. },
  1649. /* CONTROLS --------------------------------------------------------------------------------------------------------*/
  1650. /**
  1651. * manageProgress
  1652. * @returns {{totalTime: number, currentTime: number}}
  1653. */
  1654. manageProgress: function () {
  1655. let YTPlayer = this.get(0);
  1656. let controls = jQuery('#controlBar_' + YTPlayer.id);
  1657. let progressBar = controls.find('.mb_YTPProgress');
  1658. let loadedBar = controls.find('.mb_YTPLoaded');
  1659. let timeBar = controls.find('.mb_YTPseekbar');
  1660. let totW = progressBar.outerWidth();
  1661. let currentTime = Math.floor(YTPlayer.player.getCurrentTime());
  1662. let totalTime = Math.floor(YTPlayer.player.getDuration());
  1663. let timeW = (currentTime * totW) / totalTime;
  1664. let startLeft = 0;
  1665. let loadedW = YTPlayer.player.getVideoLoadedFraction() * 100;
  1666. loadedBar.css({
  1667. left : startLeft,
  1668. width: loadedW + '%'
  1669. });
  1670. timeBar.css({
  1671. left : 0,
  1672. width: timeW
  1673. });
  1674. return {
  1675. totalTime : totalTime,
  1676. currentTime: currentTime
  1677. }
  1678. },
  1679. /**
  1680. * buildControls
  1681. * @param YTPlayer
  1682. */
  1683. buildControls: function (YTPlayer) {
  1684. jQuery('#controlBar_' + YTPlayer.id).remove();
  1685. if (!YTPlayer.opt.showControls) {
  1686. YTPlayer.controlBar = false;
  1687. return
  1688. }
  1689. YTPlayer.opt.showYTLogo = YTPlayer.opt.showYTLogo || YTPlayer.opt.printUrl;
  1690. if (jQuery('#controlBar_' + YTPlayer.id).length)
  1691. return;
  1692. YTPlayer.controlBar = jQuery('<div/>').attr('id', 'controlBar_' + YTPlayer.id).addClass('mb_YTPBar').css({
  1693. whiteSpace: 'noWrap',
  1694. position : YTPlayer.isBackground ? 'fixed' : 'absolute',
  1695. zIndex : YTPlayer.isBackground ? 10000 : 1000
  1696. }).hide().on('click', function (e) {
  1697. e.stopPropagation()
  1698. });
  1699. let buttonBar = jQuery('<div/>').addClass('buttonBar');
  1700. /**
  1701. * play/pause button
  1702. * */
  1703. let playpause = jQuery('<span>' + jQuery.mbYTPlayer.controls.play + '</span>').addClass('mb_YTPPlayPause ytpicon').on('click', function (e) {
  1704. e.stopPropagation();
  1705. jQuery(YTPlayer).YTPTogglePlay()
  1706. });
  1707. /**
  1708. * mute/unmute button
  1709. * */
  1710. let MuteUnmute = jQuery('<span>' + jQuery.mbYTPlayer.controls.mute + '</span>').addClass('mb_YTPMuteUnmute ytpicon').on('click', function (e) {
  1711. e.stopPropagation();
  1712. jQuery(YTPlayer).YTPToggleVolume()
  1713. });
  1714. /**
  1715. * volume bar
  1716. * */
  1717. let volumeBar = jQuery('<div/>').addClass('mb_YTPVolumeBar').css({
  1718. display: 'inline-block'
  1719. });
  1720. YTPlayer.volumeBar = volumeBar;
  1721. /**
  1722. * time elapsed
  1723. * */
  1724. let idx = jQuery('<span/>').addClass('mb_YTPTime');
  1725. let vURL = YTPlayer.opt.videoURL ? YTPlayer.opt.videoURL : '';
  1726. if (vURL.indexOf('http') < 0) vURL = 'https://www.youtube.com/watch?v=' + YTPlayer.opt.videoURL;
  1727. let movieUrl = jQuery('<span/>').html(jQuery.mbYTPlayer.controls.ytLogo).addClass('mb_YTPUrl ytpicon').attr('title', 'view on YouTube').on('click', function () {
  1728. window.open(vURL, 'viewOnYT')
  1729. });
  1730. let onlyVideo = jQuery('<span/>').html(jQuery.mbYTPlayer.controls.onlyYT).addClass('mb_OnlyYT ytpicon').on('click', function (e) {
  1731. e.stopPropagation();
  1732. jQuery(YTPlayer).YTPFullscreen(YTPlayer.opt.realFullscreen)
  1733. });
  1734. let progressBar = jQuery('<div/>').addClass('mb_YTPProgress').css('position', 'absolute').on('click', function (e) {
  1735. e.stopPropagation();
  1736. timeBar.css({
  1737. width: (e.clientX - timeBar.offset().left)
  1738. });
  1739. YTPlayer.timeW = e.clientX - timeBar.offset().left;
  1740. YTPlayer.controlBar.find('.mb_YTPLoaded').css({
  1741. width: 0
  1742. });
  1743. let totalTime = Math.floor(YTPlayer.player.getDuration());
  1744. YTPlayer.goto = (timeBar.outerWidth() * totalTime) / progressBar.outerWidth();
  1745. YTPlayer.player.seekTo(parseFloat(YTPlayer.goto), true);
  1746. YTPlayer.controlBar.find('.mb_YTPLoaded').css({
  1747. width: 0
  1748. })
  1749. });
  1750. let loadedBar = jQuery('<div/>').addClass('mb_YTPLoaded').css('position', 'absolute');
  1751. let timeBar = jQuery('<div/>').addClass('mb_YTPseekbar').css('position', 'absolute');
  1752. progressBar.append(loadedBar).append(timeBar);
  1753. buttonBar.append(playpause).append(MuteUnmute).append(volumeBar).append(idx);
  1754. if (YTPlayer.opt.showYTLogo) {
  1755. buttonBar.append(movieUrl)
  1756. }
  1757. /**
  1758. * Full screen button
  1759. */
  1760. if (YTPlayer.isBackground || (eval(YTPlayer.opt.realFullscreen) && !YTPlayer.isBackground))
  1761. buttonBar.append(onlyVideo);
  1762. YTPlayer.controlBar.append(buttonBar).append(progressBar);
  1763. if (!YTPlayer.isBackground) {
  1764. YTPlayer.controlBar.addClass('inlinePlayer');
  1765. YTPlayer.wrapper.before(YTPlayer.controlBar)
  1766. } else {
  1767. jQuery('body').after(YTPlayer.controlBar)
  1768. }
  1769. /**
  1770. * Volume slider
  1771. */
  1772. volumeBar.simpleSlider({
  1773. initialval : YTPlayer.opt.vol,
  1774. scale : 100,
  1775. orientation: 'h',
  1776. callback : function (el) {
  1777. if (el.value == 0) {
  1778. jQuery(YTPlayer).YTPMute()
  1779. } else {
  1780. jQuery(YTPlayer).YTPUnmute()
  1781. }
  1782. YTPlayer.player.setVolume(el.value);
  1783. if (!YTPlayer.isMute)
  1784. YTPlayer.opt.vol = el.value
  1785. }
  1786. })
  1787. },
  1788. /**
  1789. * changeCoverImage
  1790. *
  1791. * @param imageURL
  1792. * @returns {jQuery.mbYTPlayer}
  1793. */
  1794. changeCoverImage: function (imageURL) {
  1795. let YTPlayer = this.get(0);
  1796. if (YTPlayer.opt.coverImage || YTPlayer.orig_containment_background) {
  1797. let bgndURL = imageURL || (YTPlayer.opt.coverImage ? 'url(' + YTPlayer.opt.coverImage + ') center center' : YTPlayer.orig_containment_background);
  1798. if (bgndURL)
  1799. YTPlayer.opt.containment.css({
  1800. background : bgndURL,
  1801. backgroundSize : 'cover',
  1802. backgroundRepeat : 'no-repeat',
  1803. backgroundAttachment: 'fixed'
  1804. })
  1805. }
  1806. return this;
  1807. },
  1808. /* MANAGE PLAYER STATE ------------------------------------------------------------------------------------------*/
  1809. /**
  1810. * checkForState
  1811. */
  1812. checkForState: function () {
  1813. let YTPlayer = this.get(0);
  1814. let $YTPlayer = jQuery(YTPlayer);
  1815. clearInterval(YTPlayer.getState);
  1816. let interval = 100;
  1817. //Checking if player has been removed from the scene
  1818. if (!jQuery.contains(document, YTPlayer)) {
  1819. $YTPlayer.YTPPlayerDestroy();
  1820. clearInterval(YTPlayer.getState);
  1821. clearInterval(YTPlayer.checkForStartAt);
  1822. return
  1823. }
  1824. jQuery.mbYTPlayer.checkForStart(YTPlayer);
  1825. YTPlayer.getState = setInterval(function () {
  1826. let $YTPlayer = jQuery(YTPlayer);
  1827. if (!YTPlayer.isReady)
  1828. return;
  1829. let prog = jQuery(YTPlayer).YTPManageProgress();
  1830. let stopAt = YTPlayer.opt.stopAt > YTPlayer.opt.startAt ? YTPlayer.opt.stopAt : 0;
  1831. stopAt = stopAt < YTPlayer.player.getDuration() ? stopAt : 0;
  1832. if (YTPlayer.currentTime != prog.currentTime) {
  1833. let YTPEvent = jQuery.Event('YTPTime');
  1834. YTPEvent.time = YTPlayer.currentTime;
  1835. jQuery(YTPlayer).trigger(YTPEvent)
  1836. }
  1837. YTPlayer.currentTime = prog.currentTime;
  1838. YTPlayer.totalTime = YTPlayer.player.getDuration();
  1839. if (YTPlayer.player.getVolume() == 0) $YTPlayer.addClass('isMuted');
  1840. else $YTPlayer.removeClass('isMuted');
  1841. if (YTPlayer.opt.showControls)
  1842. if (prog.totalTime) {
  1843. YTPlayer.controlBar.find('.mb_YTPTime').html(jQuery.mbYTPlayer.formatTime(prog.currentTime) + ' / ' + jQuery.mbYTPlayer.formatTime(prog.totalTime))
  1844. } else {
  1845. YTPlayer.controlBar.find('.mb_YTPTime').html('-- : -- / -- : --')
  1846. }
  1847. /**
  1848. * Manage video pause on window blur
  1849. */
  1850. if (eval(YTPlayer.opt.stopMovieOnBlur)) {
  1851. if (!document.hasFocus()) {
  1852. if (YTPlayer.state == 1) {
  1853. YTPlayer.hasFocus = false;
  1854. YTPlayer.preventTrigger = true;
  1855. $YTPlayer.YTPPause()
  1856. }
  1857. } else if (document.hasFocus() && !YTPlayer.hasFocus && !(YTPlayer.state == -1 || YTPlayer.state == 0)) {
  1858. YTPlayer.hasFocus = true;
  1859. YTPlayer.preventTrigger = true;
  1860. $YTPlayer.YTPPlay()
  1861. }
  1862. }
  1863. /**
  1864. * Manage video pause if not on screen
  1865. */
  1866. if (YTPlayer.opt.playOnlyIfVisible) {
  1867. let isOnScreen = jQuery.mbYTPlayer.isOnScreen(YTPlayer, YTPlayer.opt.onScreenPercentage);
  1868. if (!isOnScreen && YTPlayer.state == 1) {
  1869. YTPlayer.isOnScreen = false;
  1870. $YTPlayer.YTPPause()
  1871. } else if (isOnScreen && !YTPlayer.isOnScreen) {
  1872. YTPlayer.isOnScreen = true;
  1873. YTPlayer.player.playVideo()
  1874. }
  1875. }
  1876. if (YTPlayer.controlBar.length && YTPlayer.controlBar.outerWidth() <= 400 && !YTPlayer.isCompact) {
  1877. YTPlayer.controlBar.addClass('compact');
  1878. YTPlayer.isCompact = true;
  1879. if (!YTPlayer.isMute && YTPlayer.volumeBar) YTPlayer.volumeBar.updateSliderVal(YTPlayer.opt.vol)
  1880. } else if (YTPlayer.controlBar.length && YTPlayer.controlBar.outerWidth() > 400 && YTPlayer.isCompact) {
  1881. YTPlayer.controlBar.removeClass('compact');
  1882. YTPlayer.isCompact = false;
  1883. if (!YTPlayer.isMute && YTPlayer.volumeBar)
  1884. YTPlayer.volumeBar.updateSliderVal(YTPlayer.opt.vol)
  1885. }
  1886. // the video is ended
  1887. if (YTPlayer.player.getPlayerState() > 0 && ((parseFloat(YTPlayer.player.getDuration() - (YTPlayer.opt.fadeOnStartTime / 1000)) < YTPlayer.player.getCurrentTime()) || (stopAt > 0 && parseFloat(YTPlayer.player.getCurrentTime()) >= stopAt))) {
  1888. if (YTPlayer.isEnded)
  1889. return;
  1890. YTPlayer.isEnded = true;
  1891. setTimeout(function () {
  1892. YTPlayer.isEnded = false
  1893. }, 1000);
  1894. if (YTPlayer.isList) {
  1895. if (!YTPlayer.opt.loop || (YTPlayer.opt.loop > 0 && YTPlayer.player.loopTime === YTPlayer.opt.loop - 1)) {
  1896. YTPlayer.player.loopTime = undefined;
  1897. clearInterval(YTPlayer.getState);
  1898. let YTPEnd = jQuery.Event('YTPEnd');
  1899. YTPEnd.time = YTPlayer.currentTime;
  1900. jQuery(YTPlayer).trigger(YTPEnd);
  1901. return
  1902. }
  1903. } else if (!YTPlayer.opt.loop || (YTPlayer.opt.loop > 0 && YTPlayer.player.loopTime === YTPlayer.opt.loop - 1)) {
  1904. YTPlayer.player.loopTime = undefined;
  1905. YTPlayer.state = 2;
  1906. $YTPlayer.changeCoverImage(YTPlayer);
  1907. jQuery(YTPlayer).YTPPause();
  1908. YTPlayer.wrapper.CSSAnimate({
  1909. opacity: 0
  1910. }, YTPlayer.opt.fadeOnStartTime, function () {
  1911. if (YTPlayer.controlBar.length)
  1912. YTPlayer.controlBar.find('.mb_YTPPlayPause').html(jQuery.mbYTPlayer.controls.play);
  1913. $YTPlayer.changeCoverImage();
  1914. let YTPEnd = jQuery.Event('YTPEnd');
  1915. YTPEnd.time = YTPlayer.currentTime;
  1916. jQuery(YTPlayer).trigger(YTPEnd);
  1917. YTPlayer.player.seekTo(YTPlayer.opt.startAt, true);
  1918. });
  1919. return
  1920. }
  1921. YTPlayer.player.loopTime = YTPlayer.player.loopTime ? ++YTPlayer.player.loopTime : 1;
  1922. YTPlayer.opt.startAt = YTPlayer.opt.startAt || 1;
  1923. YTPlayer.preventTrigger = true;
  1924. YTPlayer.state = 2;
  1925. YTPlayer.player.seekTo(YTPlayer.opt.startAt, true)
  1926. }
  1927. }, interval)
  1928. },
  1929. /**
  1930. * checkForStart
  1931. * @param YTPlayer
  1932. */
  1933. checkForStart: function (YTPlayer) {
  1934. let $YTPlayer = jQuery(YTPlayer);
  1935. /* If the player has been removed from scene destroy it */
  1936. if (!jQuery.contains(document, YTPlayer)) {
  1937. $YTPlayer.YTPPlayerDestroy();
  1938. return
  1939. }
  1940. /* CREATE CONTROL BAR */
  1941. jQuery.mbYTPlayer.buildControls(YTPlayer);
  1942. if (YTPlayer.overlay)
  1943. if (YTPlayer.opt.addRaster) {
  1944. let classN = YTPlayer.opt.addRaster == 'dot' ? 'raster-dot' : 'raster';
  1945. YTPlayer.overlay.addClass(YTPlayer.isRetina ? classN + ' retina' : classN)
  1946. } else {
  1947. YTPlayer.overlay.removeClass(function (index, classNames) {
  1948. // change the list into an array
  1949. let current_classes = classNames.split(' '),
  1950. // array of classes which are to be removed
  1951. classes_to_remove = [];
  1952. jQuery.each(current_classes, function (index, class_name) {
  1953. // if the classname begins with bg add it to the classes_to_remove array
  1954. if (/raster.*/.test(class_name)) {
  1955. classes_to_remove.push(class_name)
  1956. }
  1957. });
  1958. classes_to_remove.push('retina');
  1959. // turn the array back into a string
  1960. return classes_to_remove.join(' ')
  1961. })
  1962. }
  1963. YTPlayer.preventTrigger = true;
  1964. YTPlayer.state = 2;
  1965. YTPlayer.preventTrigger = true;
  1966. YTPlayer.player.mute();
  1967. YTPlayer.player.playVideo();
  1968. YTPlayer.isStarting = true;
  1969. let startAt = YTPlayer.start_from_last ? YTPlayer.start_from_last : YTPlayer.opt.startAt ? YTPlayer.opt.startAt : 1;
  1970. YTPlayer.preventTrigger = true;
  1971. YTPlayer.checkForStartAt = setInterval(function () {
  1972. YTPlayer.player.mute();
  1973. YTPlayer.player.seekTo(startAt, true);
  1974. let canPlayVideo = YTPlayer.player.getVideoLoadedFraction() >= startAt / YTPlayer.player.getDuration();
  1975. if (jQuery.mbBrowser.mobile)
  1976. canPlayVideo = true;
  1977. if (YTPlayer.player.getDuration() > 0 && YTPlayer.player.getCurrentTime() >= startAt && canPlayVideo) {
  1978. YTPlayer.start_from_last = null;
  1979. YTPlayer.preventTrigger = true;
  1980. $YTPlayer.YTPPause();
  1981. clearInterval(YTPlayer.checkForStartAt);
  1982. if (typeof YTPlayer.opt.onReady == 'function')
  1983. YTPlayer.opt.onReady(YTPlayer);
  1984. YTPlayer.isReady = true;
  1985. $YTPlayer.YTPRemoveFilter();
  1986. if (YTPlayer.opt.addFilters) {
  1987. $YTPlayer.YTPApplyFilters(YTPlayer.opt.addFilters)
  1988. } else {
  1989. $YTPlayer.YTPApplyFilters()
  1990. }
  1991. $YTPlayer.YTPEnableFilters();
  1992. let YTPready = jQuery.Event('YTPReady');
  1993. YTPready.time = YTPlayer.currentTime;
  1994. $YTPlayer.trigger(YTPready);
  1995. YTPlayer.state = 2;
  1996. if (!YTPlayer.opt.mute) {
  1997. if (YTPlayer.opt.autoPlay) {
  1998. console.debug('We muted the audio to make the video \'auto-play\' according with the latest vendor policy. ' +
  1999. 'The audio will unmute at the first user interaction with the page');
  2000. YTPlayer.player.mute();
  2001. YTPlayer.forcedMuted = true;
  2002. /**
  2003. * If autoPlay is set to true and mute is set to false
  2004. * Browsers will not auto-play
  2005. * Start playing audio after the first click
  2006. */
  2007. jQuery(document).on('mousedown.YTPstartAudio', function () {
  2008. if (YTPlayer.forcedMuted) {
  2009. console.debug("AAAAAAA");
  2010. YTPlayer.player.unMute();
  2011. YTPlayer.forcedMuted = false;
  2012. jQuery(document).off('mousedown.YTPstartAudio')
  2013. }
  2014. });
  2015. jQuery(window).on("scroll", function () {
  2016. console.debug("AAAAA")
  2017. })
  2018. } else {
  2019. YTPlayer.player.unMute()
  2020. }
  2021. } else {
  2022. $YTPlayer.YTPMute()
  2023. }
  2024. if (typeof _gaq != 'undefined' && eval(YTPlayer.opt.gaTrack))
  2025. _gaq.push(['_trackEvent', 'YTPlayer', 'Play', (YTPlayer.hasData ? YTPlayer.videoData.title : YTPlayer.videoID.toString())]);
  2026. else if (typeof ga != 'undefined' && eval(YTPlayer.opt.gaTrack))
  2027. ga('send', 'event', 'YTPlayer', 'play', (YTPlayer.hasData ? YTPlayer.videoData.title : YTPlayer.videoID.toString()));
  2028. if (YTPlayer.opt.autoPlay) {
  2029. let YTPStart = jQuery.Event('YTPStart');
  2030. YTPStart.time = YTPlayer.currentTime;
  2031. jQuery(YTPlayer).trigger(YTPStart);
  2032. YTPlayer.isStarting = false;
  2033. /* Fix for Safari freeze */
  2034. if (jQuery.mbBrowser.os.name === 'mac' && jQuery.mbBrowser.safari) {
  2035. jQuery('body').one('mousedown.YTPstart', function () {
  2036. $YTPlayer.YTPPlay()
  2037. })
  2038. }
  2039. $YTPlayer.YTPPlay();
  2040. console.timeEnd(YTPTimerLabels.startPlaying)
  2041. } else {
  2042. YTPlayer.preventTrigger = true;
  2043. $YTPlayer.YTPPause();
  2044. if (YTPlayer.start_from_last)
  2045. YTPlayer.player.seekTo(startAt, true);
  2046. setTimeout(function () {
  2047. YTPlayer.preventTrigger = true;
  2048. $YTPlayer.YTPPause();
  2049. if (!YTPlayer.isPlayer) {
  2050. if (!YTPlayer.opt.coverImage) {
  2051. jQuery(YTPlayer.playerEl).CSSAnimate({
  2052. opacity: 1
  2053. }, YTPlayer.opt.fadeOnStartTime);
  2054. YTPlayer.wrapper.CSSAnimate({
  2055. opacity: YTPlayer.isAlone ? 1 : YTPlayer.opt.opacity
  2056. }, YTPlayer.opt.fadeOnStartTime)
  2057. } else {
  2058. YTPlayer.wrapper.css({opacity: 0});
  2059. setTimeout(function () {
  2060. $YTPlayer.changeCoverImage()
  2061. }, YTPlayer.opt.fadeOnStartTime)
  2062. }
  2063. }
  2064. YTPlayer.isStarting = false
  2065. }, 500);
  2066. if (YTPlayer.controlBar.length)
  2067. YTPlayer.controlBar.find('.mb_YTPPlayPause').html(jQuery.mbYTPlayer.controls.play)
  2068. }
  2069. if (YTPlayer.isPlayer && !YTPlayer.opt.autoPlay && (YTPlayer.loading && YTPlayer.loading.length)) {
  2070. YTPlayer.loading.html('Ready');
  2071. setTimeout(function () {
  2072. YTPlayer.loading.fadeOut()
  2073. }, 100)
  2074. }
  2075. if (YTPlayer.controlBar && YTPlayer.controlBar.length)
  2076. YTPlayer.controlBar.slideDown(1000)
  2077. }
  2078. if (jQuery.mbBrowser.os.name === 'mac' && jQuery.mbBrowser.safari) {
  2079. YTPlayer.player.playVideo();
  2080. if (startAt >= 0)
  2081. YTPlayer.player.seekTo(startAt, true)
  2082. }
  2083. }, 100);
  2084. return $YTPlayer
  2085. },
  2086. /* TIME METHODS -------------------------------------------------------------------------------------------*/
  2087. /**
  2088. * getTime
  2089. * @returns {string} time
  2090. */
  2091. getTime: function () {
  2092. let YTPlayer = this.get(0);
  2093. return jQuery.mbYTPlayer.formatTime(YTPlayer.currentTime)
  2094. },
  2095. /**
  2096. * getTotalTime
  2097. * @returns {string} total time
  2098. */
  2099. getTotalTime: function () {
  2100. let YTPlayer = this.get(0);
  2101. return jQuery.mbYTPlayer.formatTime(YTPlayer.totalTime)
  2102. },
  2103. /**
  2104. * formatTime
  2105. * @param s
  2106. * @returns {string}
  2107. */
  2108. formatTime: function (s) {
  2109. let min = Math.floor(s / 60);
  2110. let sec = Math.floor(s - (60 * min));
  2111. return (min <= 9 ? '0' + min : min) + ' : ' + (sec <= 9 ? '0' + sec : sec)
  2112. },
  2113. /* PLAYER POSITION AND SIZE OPTIMIZATION-------------------------------------------------------------------------------------------*/
  2114. /**
  2115. * setAnchor
  2116. * @param anchor
  2117. */
  2118. setAnchor: function (anchor) {
  2119. let $YTplayer = this;
  2120. $YTplayer.optimizeDisplay(anchor)
  2121. },
  2122. /**
  2123. * getAnchor
  2124. */
  2125. getAnchor: function () {
  2126. let YTPlayer = this.get(0);
  2127. return YTPlayer.opt.anchor
  2128. },
  2129. /**
  2130. * setAbundance
  2131. * @param val
  2132. * @param updateOptions
  2133. * @returns {jQuery.mbYTPlayer}
  2134. */
  2135. setAbundance: function (val, updateOptions) {
  2136. let YTPlayer = this.get(0);
  2137. let $YTPlayer = this;
  2138. if (updateOptions)
  2139. YTPlayer.opt.abundance = val;
  2140. $YTPlayer.optimizeDisplay(YTPlayer.opt.anchor, val);
  2141. return $YTPlayer
  2142. },
  2143. /**
  2144. * getAbundance
  2145. * @returns {*}
  2146. */
  2147. getAbundance: function () {
  2148. let YTPlayer = this.get(0);
  2149. return YTPlayer.opt.abundance
  2150. },
  2151. /**
  2152. * setOption
  2153. * @param opt
  2154. * @param val
  2155. * @returns {jQuery.mbYTPlayer}
  2156. */
  2157. setOption: function (opt, val) {
  2158. let YTPlayer = this.get(0);
  2159. let $YTPlayer = this;
  2160. YTPlayer.opt[opt] = val;
  2161. return $YTPlayer
  2162. }
  2163. };
  2164. /**
  2165. * optimizeDisplay
  2166. * @param anchor
  2167. * @param abundanceX
  2168. */
  2169. jQuery.fn.optimizeDisplay = function (anchor, abundanceX) {
  2170. let YTPlayer = this.get(0);
  2171. let vid = {};
  2172. let el = YTPlayer.wrapper;
  2173. let iframe = jQuery(YTPlayer.playerEl);
  2174. YTPlayer.opt.anchor = anchor || YTPlayer.opt.anchor;
  2175. // console.debug(YTPlayer.opt.anchor);
  2176. YTPlayer.opt.anchor = typeof YTPlayer.opt.anchor != 'undefined ' ? YTPlayer.opt.anchor : 'center,center';
  2177. let YTPAlign = YTPlayer.opt.anchor.split(',');
  2178. let ab = abundanceX ? abundanceX : YTPlayer.opt.abundance;
  2179. if (YTPlayer.opt.optimizeDisplay) {
  2180. let abundance = el.height() * ab;
  2181. let win = {};
  2182. win.width = el.outerWidth();
  2183. win.height = el.outerHeight() + abundance;
  2184. YTPlayer.opt.ratio = YTPlayer.opt.ratio === 'auto' ? 16 / 9 : YTPlayer.opt.ratio;
  2185. YTPlayer.opt.ratio = eval(YTPlayer.opt.ratio);
  2186. vid.width = win.width + abundance;
  2187. vid.height = Math.ceil(vid.width / YTPlayer.opt.ratio);
  2188. vid.marginTop = Math.ceil(-((vid.height - win.height + abundance) / 2));
  2189. vid.marginLeft = -(abundance / 2);
  2190. let lowest = vid.height < win.height;
  2191. if (lowest) {
  2192. vid.height = win.height + abundance;
  2193. vid.width = Math.ceil(vid.height * YTPlayer.opt.ratio);
  2194. vid.marginTop = -(abundance / 2);
  2195. vid.marginLeft = Math.ceil(-((vid.width - win.width) / 2))
  2196. }
  2197. for (let a in YTPAlign) {
  2198. if (YTPAlign.hasOwnProperty(a)) {
  2199. let al = YTPAlign[a].replace(/ /g, '');
  2200. switch (al) {
  2201. case 'top':
  2202. vid.marginTop = -abundance;
  2203. break;
  2204. case 'bottom':
  2205. vid.marginTop = Math.ceil(-(vid.height - win.height) - (abundance / 2));
  2206. break;
  2207. case 'left':
  2208. vid.marginLeft = -(abundance);
  2209. break;
  2210. case 'right':
  2211. vid.marginLeft = Math.ceil(-(vid.width - win.width) + (abundance / 2));
  2212. break
  2213. }
  2214. }
  2215. }
  2216. } else {
  2217. vid.width = '100%';
  2218. vid.height = '100%';
  2219. vid.marginTop = 0;
  2220. vid.marginLeft = 0
  2221. }
  2222. iframe.css({
  2223. width : vid.width,
  2224. height : vid.height,
  2225. marginTop : vid.marginTop,
  2226. marginLeft: vid.marginLeft,
  2227. maxWidth : 'initial'
  2228. })
  2229. };
  2230. /* UTILITIES -----------------------------------------------------------------------------------------------------------------------*/
  2231. /**
  2232. * shuffle
  2233. * @param arr
  2234. * @returns {Array|string|Blob|*}
  2235. *
  2236. */
  2237. jQuery.shuffle = function (arr) {
  2238. let newArray = arr.slice();
  2239. let len = newArray.length;
  2240. let i = len;
  2241. while (i--) {
  2242. let p = parseInt(Math.random() * len);
  2243. let t = newArray[i];
  2244. newArray[i] = newArray[p];
  2245. newArray[p] = t
  2246. }
  2247. return newArray;
  2248. };
  2249. /**
  2250. * Unselectable
  2251. * @returns {*}
  2252. */
  2253. jQuery.fn.unselectable = function () {
  2254. return this.each(function () {
  2255. jQuery(this).css({
  2256. '-moz-user-select' : 'none',
  2257. '-webkit-user-select': 'none',
  2258. 'user-select' : 'none'
  2259. }).attr('unselectable', 'on')
  2260. })
  2261. };
  2262. /* EXTERNAL METHODS -----------------------------------------------------------------------------------------------------------------------*/
  2263. jQuery.fn.YTPlayer = jQuery.mbYTPlayer.buildPlayer;
  2264. jQuery.fn.mb_YTPlayer = jQuery.mbYTPlayer.buildPlayer;
  2265. jQuery.fn.YTPCheckForState = jQuery.mbYTPlayer.checkForState;
  2266. jQuery.fn.YTPGetPlayer = jQuery.mbYTPlayer.getPlayer;
  2267. jQuery.fn.YTPGetVideoID = jQuery.mbYTPlayer.getVideoID;
  2268. jQuery.fn.YTPGetPlaylistID = jQuery.mbYTPlayer.getPlaylistID;
  2269. jQuery.fn.YTPChangeVideo = jQuery.fn.YTPChangeMovie = jQuery.mbYTPlayer.changeVideo;
  2270. jQuery.fn.YTPPlayerDestroy = jQuery.mbYTPlayer.playerDestroy;
  2271. jQuery.fn.YTPPlay = jQuery.mbYTPlayer.play;
  2272. jQuery.fn.YTPTogglePlay = jQuery.mbYTPlayer.togglePlay;
  2273. jQuery.fn.YTPStop = jQuery.mbYTPlayer.stop;
  2274. jQuery.fn.YTPPause = jQuery.mbYTPlayer.pause;
  2275. jQuery.fn.YTPSeekTo = jQuery.mbYTPlayer.seekTo;
  2276. jQuery.fn.YTPGetPlaybackRate = jQuery.mbYTPlayer.getPlaybackRate;
  2277. jQuery.fn.YTPSetPlaybackRate = jQuery.mbYTPlayer.setPlaybackRate;
  2278. jQuery.fn.changeCoverImage = jQuery.mbYTPlayer.changeCoverImage;
  2279. jQuery.fn.YTPlaylist = jQuery.mbYTPlayer.playlist;
  2280. jQuery.fn.YTPPlayNext = jQuery.mbYTPlayer.playNext;
  2281. jQuery.fn.YTPPlayPrev = jQuery.mbYTPlayer.playPrev;
  2282. jQuery.fn.YTPPlayIndex = jQuery.mbYTPlayer.playIndex;
  2283. jQuery.fn.YTPMute = jQuery.mbYTPlayer.mute;
  2284. jQuery.fn.YTPUnmute = jQuery.mbYTPlayer.unmute;
  2285. jQuery.fn.YTPToggleVolume = jQuery.mbYTPlayer.toggleVolume;
  2286. jQuery.fn.YTPSetVolume = jQuery.mbYTPlayer.setVolume;
  2287. jQuery.fn.YTPGetVolume = jQuery.mbYTPlayer.getVolume;
  2288. jQuery.fn.YTPGetVideoData = jQuery.mbYTPlayer.getVideoData;
  2289. jQuery.fn.YTPFullscreen = jQuery.mbYTPlayer.fullscreen;
  2290. jQuery.fn.YTPToggleLoops = jQuery.mbYTPlayer.toggleLoops;
  2291. jQuery.fn.YTPManageProgress = jQuery.mbYTPlayer.manageProgress;
  2292. jQuery.fn.YTPSetVideoQuality = jQuery.mbYTPlayer.setVideoQuality;
  2293. jQuery.fn.YTPGetVideoQuality = jQuery.mbYTPlayer.getVideoQuality;
  2294. jQuery.fn.YTPApplyFilter = jQuery.mbYTPlayer.applyFilter;
  2295. jQuery.fn.YTPApplyFilters = jQuery.mbYTPlayer.applyFilters;
  2296. jQuery.fn.YTPToggleFilter = jQuery.mbYTPlayer.toggleFilter;
  2297. jQuery.fn.YTPToggleFilters = jQuery.mbYTPlayer.toggleFilters;
  2298. jQuery.fn.YTPRemoveFilter = jQuery.mbYTPlayer.removeFilter;
  2299. jQuery.fn.YTPDisableFilters = jQuery.mbYTPlayer.disableFilters;
  2300. jQuery.fn.YTPEnableFilters = jQuery.mbYTPlayer.enableFilters;
  2301. jQuery.fn.YTPGetFilters = jQuery.mbYTPlayer.getFilters;
  2302. jQuery.fn.YTPGetTime = jQuery.mbYTPlayer.getTime;
  2303. jQuery.fn.YTPGetTotalTime = jQuery.mbYTPlayer.getTotalTime;
  2304. jQuery.fn.YTPAddMask = jQuery.mbYTPlayer.addMask;
  2305. jQuery.fn.YTPRemoveMask = jQuery.mbYTPlayer.removeMask;
  2306. jQuery.fn.YTPToggleMask = jQuery.mbYTPlayer.toggleMask;
  2307. jQuery.fn.YTPGetAbundance = jQuery.mbYTPlayer.getAbundance;
  2308. jQuery.fn.YTPSetAbundance = jQuery.mbYTPlayer.setAbundance;
  2309. jQuery.fn.YTPSetAnchor = jQuery.mbYTPlayer.setAnchor;
  2310. jQuery.fn.YTPGetAnchor = jQuery.mbYTPlayer.getAnchor;
  2311. jQuery.fn.YTPSetOption = jQuery.mbYTPlayer.setOption
  2312. })(jQuery, ytp);
  2313. /*___________________________________________________________________________________________________________________________________________________
  2314. _ jquery.mb.components _
  2315. _ _
  2316. _ file: jquery.mb.mbBrowser.min.js _
  2317. _ last modified: 24/05/17 19.56 _
  2318. _ _
  2319. _ Open Lab s.r.l., Florence - Italy _
  2320. _ _
  2321. _ email: matbicoc@gmail.com _
  2322. _ site: http://pupunzi.com _
  2323. _ http://open-lab.com _
  2324. _ blog: http://pupunzi.open-lab.com _
  2325. _ Q&A: http://jquery.pupunzi.com _
  2326. _ _
  2327. _ Licences: MIT, GPL _
  2328. _ http://www.opensource.org/licenses/mit-license.php _
  2329. _ http://www.gnu.org/licenses/gpl.html _
  2330. _ _
  2331. _ Copyright (c) 2001-2017. Matteo Bicocchi (Pupunzi); _
  2332. ___________________________________________________________________________________________________________________________________________________*/
  2333. var nAgt=navigator.userAgent;jQuery.mbBrowser=jQuery.mbBrowser||{};jQuery.mbBrowser.mozilla=!1;jQuery.mbBrowser.webkit=!1;jQuery.mbBrowser.opera=!1;jQuery.mbBrowser.safari=!1;jQuery.mbBrowser.chrome=!1;jQuery.mbBrowser.androidStock=!1;jQuery.mbBrowser.msie=!1;jQuery.mbBrowser.edge=!1;jQuery.mbBrowser.ua=nAgt;function isTouchSupported(){var a=nAgt.msMaxTouchPoints,e="ontouchstart"in document.createElement("div");return a||e?!0:!1}
  2334. var getOS=function(){var a={version:"Unknown version",name:"Unknown OS"};-1!=navigator.appVersion.indexOf("Win")&&(a.name="Windows");-1!=navigator.appVersion.indexOf("Mac")&&0>navigator.appVersion.indexOf("Mobile")&&(a.name="Mac");-1!=navigator.appVersion.indexOf("Linux")&&(a.name="Linux");/Mac OS X/.test(nAgt)&&!/Mobile/.test(nAgt)&&(a.version=/Mac OS X ([\._\d]+)/.exec(nAgt)[1],a.version=a.version.replace(/_/g,".").substring(0,5));/Windows/.test(nAgt)&&(a.version="Unknown.Unknown");/Windows NT 5.1/.test(nAgt)&&
  2335. (a.version="5.1");/Windows NT 6.0/.test(nAgt)&&(a.version="6.0");/Windows NT 6.1/.test(nAgt)&&(a.version="6.1");/Windows NT 6.2/.test(nAgt)&&(a.version="6.2");/Windows NT 10.0/.test(nAgt)&&(a.version="10.0");/Linux/.test(nAgt)&&/Linux/.test(nAgt)&&(a.version="Unknown.Unknown");a.name=a.name.toLowerCase();a.major_version="Unknown";a.minor_version="Unknown";"Unknown.Unknown"!=a.version&&(a.major_version=parseFloat(a.version.split(".")[0]),a.minor_version=parseFloat(a.version.split(".")[1]));return a};
  2336. jQuery.mbBrowser.os=getOS();jQuery.mbBrowser.hasTouch=isTouchSupported();jQuery.mbBrowser.name=navigator.appName;jQuery.mbBrowser.fullVersion=""+parseFloat(navigator.appVersion);jQuery.mbBrowser.majorVersion=parseInt(navigator.appVersion,10);var nameOffset,verOffset,ix;
  2337. if(-1!=(verOffset=nAgt.indexOf("Opera")))jQuery.mbBrowser.opera=!0,jQuery.mbBrowser.name="Opera",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+6),-1!=(verOffset=nAgt.indexOf("Version"))&&(jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+8));else if(-1!=(verOffset=nAgt.indexOf("OPR")))jQuery.mbBrowser.opera=!0,jQuery.mbBrowser.name="Opera",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+4);else if(-1!=(verOffset=nAgt.indexOf("MSIE")))jQuery.mbBrowser.msie=!0,jQuery.mbBrowser.name="Microsoft Internet Explorer",
  2338. jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+5);else if(-1!=nAgt.indexOf("Trident")){jQuery.mbBrowser.msie=!0;jQuery.mbBrowser.name="Microsoft Internet Explorer";var start=nAgt.indexOf("rv:")+3,end=start+4;jQuery.mbBrowser.fullVersion=nAgt.substring(start,end)}else-1!=(verOffset=nAgt.indexOf("Edge"))?(jQuery.mbBrowser.edge=!0,jQuery.mbBrowser.name="Microsoft Edge",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+5)):-1!=(verOffset=nAgt.indexOf("Chrome"))?(jQuery.mbBrowser.webkit=!0,jQuery.mbBrowser.chrome=
  2339. !0,jQuery.mbBrowser.name="Chrome",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+7)):-1<nAgt.indexOf("mozilla/5.0")&&-1<nAgt.indexOf("android ")&&-1<nAgt.indexOf("applewebkit")&&!(-1<nAgt.indexOf("chrome"))?(verOffset=nAgt.indexOf("Chrome"),jQuery.mbBrowser.webkit=!0,jQuery.mbBrowser.androidStock=!0,jQuery.mbBrowser.name="androidStock",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+7)):-1!=(verOffset=nAgt.indexOf("Safari"))?(jQuery.mbBrowser.webkit=!0,jQuery.mbBrowser.safari=!0,jQuery.mbBrowser.name=
  2340. "Safari",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+7),-1!=(verOffset=nAgt.indexOf("Version"))&&(jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+8))):-1!=(verOffset=nAgt.indexOf("AppleWebkit"))?(jQuery.mbBrowser.webkit=!0,jQuery.mbBrowser.safari=!0,jQuery.mbBrowser.name="Safari",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+7),-1!=(verOffset=nAgt.indexOf("Version"))&&(jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+8))):-1!=(verOffset=nAgt.indexOf("Firefox"))?(jQuery.mbBrowser.mozilla=
  2341. !0,jQuery.mbBrowser.name="Firefox",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+8)):(nameOffset=nAgt.lastIndexOf(" ")+1)<(verOffset=nAgt.lastIndexOf("/"))&&(jQuery.mbBrowser.name=nAgt.substring(nameOffset,verOffset),jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+1),jQuery.mbBrowser.name.toLowerCase()==jQuery.mbBrowser.name.toUpperCase()&&(jQuery.mbBrowser.name=navigator.appName));
  2342. -1!=(ix=jQuery.mbBrowser.fullVersion.indexOf(";"))&&(jQuery.mbBrowser.fullVersion=jQuery.mbBrowser.fullVersion.substring(0,ix));-1!=(ix=jQuery.mbBrowser.fullVersion.indexOf(" "))&&(jQuery.mbBrowser.fullVersion=jQuery.mbBrowser.fullVersion.substring(0,ix));jQuery.mbBrowser.majorVersion=parseInt(""+jQuery.mbBrowser.fullVersion,10);isNaN(jQuery.mbBrowser.majorVersion)&&(jQuery.mbBrowser.fullVersion=""+parseFloat(navigator.appVersion),jQuery.mbBrowser.majorVersion=parseInt(navigator.appVersion,10));
  2343. jQuery.mbBrowser.version=jQuery.mbBrowser.majorVersion;jQuery.mbBrowser.android=/Android/i.test(nAgt);jQuery.mbBrowser.blackberry=/BlackBerry|BB|PlayBook/i.test(nAgt);jQuery.mbBrowser.ios=/iPhone|iPad|iPod|webOS/i.test(nAgt);jQuery.mbBrowser.operaMobile=/Opera Mini/i.test(nAgt);jQuery.mbBrowser.windowsMobile=/IEMobile|Windows Phone/i.test(nAgt);jQuery.mbBrowser.kindle=/Kindle|Silk/i.test(nAgt);
  2344. jQuery.mbBrowser.mobile=jQuery.mbBrowser.android||jQuery.mbBrowser.blackberry||jQuery.mbBrowser.ios||jQuery.mbBrowser.windowsMobile||jQuery.mbBrowser.operaMobile||jQuery.mbBrowser.kindle;jQuery.isMobile=jQuery.mbBrowser.mobile;jQuery.isTablet=jQuery.mbBrowser.mobile&&765<jQuery(window).width();jQuery.isAndroidDefault=jQuery.mbBrowser.android&&!/chrome/i.test(nAgt);jQuery.mbBrowser=jQuery.mbBrowser;
  2345. jQuery.mbBrowser.versionCompare=function(a,e){if("stringstring"!=typeof a+typeof e)return!1;for(var c=a.split("."),d=e.split("."),b=0,f=Math.max(c.length,d.length);b<f;b++){if(c[b]&&!d[b]&&0<parseInt(c[b])||parseInt(c[b])>parseInt(d[b]))return 1;if(d[b]&&!c[b]&&0<parseInt(d[b])||parseInt(c[b])<parseInt(d[b]))return-1}return 0};
  2346. /*
  2347. * ******************************************************************************
  2348. * jquery.mb.components
  2349. * file: jquery.mb.CSSAnimate.min.js
  2350. *
  2351. * Copyright (c) 2001-2014. Matteo Bicocchi (Pupunzi);
  2352. * Open lab srl, Firenze - Italy
  2353. * email: matbicoc@gmail.com
  2354. * site: http://pupunzi.com
  2355. * blog: http://pupunzi.open-lab.com
  2356. * http://open-lab.com
  2357. *
  2358. * Licences: MIT, GPL
  2359. * http://www.opensource.org/licenses/mit-license.php
  2360. * http://www.gnu.org/licenses/gpl.html
  2361. *
  2362. * last modified: 26/03/14 21.40
  2363. * *****************************************************************************
  2364. */
  2365. jQuery.support.CSStransition=function(){var d=(document.body||document.documentElement).style;return void 0!==d.transition||void 0!==d.WebkitTransition||void 0!==d.MozTransition||void 0!==d.MsTransition||void 0!==d.OTransition}();function uncamel(d){return d.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function setUnit(d,a){return"string"!==typeof d||d.match(/^[\-0-9\.]+jQuery/)?""+d+a:d}
  2366. function setFilter(d,a,b){var c=uncamel(a),g=jQuery.mbBrowser.mozilla?"":jQuery.CSS.sfx;d[g+"filter"]=d[g+"filter"]||"";b=setUnit(b>jQuery.CSS.filters[a].max?jQuery.CSS.filters[a].max:b,jQuery.CSS.filters[a].unit);d[g+"filter"]+=c+"("+b+") ";delete d[a]}
  2367. jQuery.CSS={name:"mb.CSSAnimate",author:"Matteo Bicocchi",version:"2.0.0",transitionEnd:"transitionEnd",sfx:"",filters:{blur:{min:0,max:100,unit:"px"},brightness:{min:0,max:400,unit:"%"},contrast:{min:0,max:400,unit:"%"},grayscale:{min:0,max:100,unit:"%"},hueRotate:{min:0,max:360,unit:"deg"},invert:{min:0,max:100,unit:"%"},saturate:{min:0,max:400,unit:"%"},sepia:{min:0,max:100,unit:"%"}},normalizeCss:function(d){var a=jQuery.extend(!0,{},d);jQuery.mbBrowser.webkit||jQuery.mbBrowser.opera?jQuery.CSS.sfx=
  2368. "-webkit-":jQuery.mbBrowser.mozilla?jQuery.CSS.sfx="-moz-":jQuery.mbBrowser.msie&&(jQuery.CSS.sfx="-ms-");jQuery.CSS.sfx="";for(var b in a){"transform"===b&&(a[jQuery.CSS.sfx+"transform"]=a[b],delete a[b]);"transform-origin"===b&&(a[jQuery.CSS.sfx+"transform-origin"]=d[b],delete a[b]);"filter"!==b||jQuery.mbBrowser.mozilla||(a[jQuery.CSS.sfx+"filter"]=d[b],delete a[b]);"blur"===b&&setFilter(a,"blur",d[b]);"brightness"===b&&setFilter(a,"brightness",d[b]);"contrast"===b&&setFilter(a,"contrast",d[b]);"grayscale"===
  2369. b&&setFilter(a,"grayscale",d[b]);"hueRotate"===b&&setFilter(a,"hueRotate",d[b]);"invert"===b&&setFilter(a,"invert",d[b]);"saturate"===b&&setFilter(a,"saturate",d[b]);"sepia"===b&&setFilter(a,"sepia",d[b]);if("x"===b){var c=jQuery.CSS.sfx+"transform";a[c]=a[c]||"";a[c]+=" translateX("+setUnit(d[b],"px")+")";delete a[b]}"y"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" translateY("+setUnit(d[b],"px")+")",delete a[b]);"z"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" translateZ("+
  2370. setUnit(d[b],"px")+")",delete a[b]);"rotate"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" rotate("+setUnit(d[b],"deg")+")",delete a[b]);"rotateX"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" rotateX("+setUnit(d[b],"deg")+")",delete a[b]);"rotateY"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" rotateY("+setUnit(d[b],"deg")+")",delete a[b]);"rotateZ"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" rotateZ("+setUnit(d[b],"deg")+")",delete a[b]);"scale"===b&&
  2371. (c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" scale("+setUnit(d[b],"")+")",delete a[b]);"scaleX"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" scaleX("+setUnit(d[b],"")+")",delete a[b]);"scaleY"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" scaleY("+setUnit(d[b],"")+")",delete a[b]);"scaleZ"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" scaleZ("+setUnit(d[b],"")+")",delete a[b]);"skew"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" skew("+setUnit(d[b],
  2372. "deg")+")",delete a[b]);"skewX"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" skewX("+setUnit(d[b],"deg")+")",delete a[b]);"skewY"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" skewY("+setUnit(d[b],"deg")+")",delete a[b]);"perspective"===b&&(c=jQuery.CSS.sfx+"transform",a[c]=a[c]||"",a[c]+=" perspective("+setUnit(d[b],"px")+")",delete a[b])}return a},getProp:function(d){var a=[],b;for(b in d)0>a.indexOf(b)&&a.push(uncamel(b));return a.join(",")},animate:function(d,a,b,c,g){return this.each(function(){function n(){e.called=
  2373. !0;e.CSSAIsRunning=!1;h.off(jQuery.CSS.transitionEnd+"."+e.id);clearTimeout(e.timeout);h.css(jQuery.CSS.sfx+"transition","");"function"==typeof g&&g.apply(e);"function"==typeof e.CSSqueue&&(e.CSSqueue(),e.CSSqueue=null)}var e=this,h=jQuery(this);e.id=e.id||"CSSA_"+(new Date).getTime();var k=k||{type:"noEvent"};if(e.CSSAIsRunning&&e.eventType==k.type&&!jQuery.mbBrowser.msie&&9>=jQuery.mbBrowser.version)e.CSSqueue=function(){h.CSSAnimate(d,a,b,c,g)};else if(e.CSSqueue=null,e.eventType=k.type,0!==h.length&&
  2374. d){d=jQuery.normalizeCss(d);e.CSSAIsRunning=!0;"function"==typeof a&&(g=a,a=jQuery.fx.speeds._default);"function"==typeof b&&(c=b,b=0);"string"==typeof b&&(g=b,b=0);"function"==typeof c&&(g=c,c="cubic-bezier(0.65,0.03,0.36,0.72)");if("string"==typeof a)for(var l in jQuery.fx.speeds)if(a==l){a=jQuery.fx.speeds[l];break}else a=jQuery.fx.speeds._default;a||(a=jQuery.fx.speeds._default);"string"===typeof g&&(c=g,g=null);if(jQuery.support.CSStransition){var f={"default":"ease","in":"ease-in",out:"ease-out",
  2375. "in-out":"ease-in-out",snap:"cubic-bezier(0,1,.5,1)",easeOutCubic:"cubic-bezier(.215,.61,.355,1)",easeInOutCubic:"cubic-bezier(.645,.045,.355,1)",easeInCirc:"cubic-bezier(.6,.04,.98,.335)",easeOutCirc:"cubic-bezier(.075,.82,.165,1)",easeInOutCirc:"cubic-bezier(.785,.135,.15,.86)",easeInExpo:"cubic-bezier(.95,.05,.795,.035)",easeOutExpo:"cubic-bezier(.19,1,.22,1)",easeInOutExpo:"cubic-bezier(1,0,0,1)",easeInQuad:"cubic-bezier(.55,.085,.68,.53)",easeOutQuad:"cubic-bezier(.25,.46,.45,.94)",easeInOutQuad:"cubic-bezier(.455,.03,.515,.955)",
  2376. easeInQuart:"cubic-bezier(.895,.03,.685,.22)",easeOutQuart:"cubic-bezier(.165,.84,.44,1)",easeInOutQuart:"cubic-bezier(.77,0,.175,1)",easeInQuint:"cubic-bezier(.755,.05,.855,.06)",easeOutQuint:"cubic-bezier(.23,1,.32,1)",easeInOutQuint:"cubic-bezier(.86,0,.07,1)",easeInSine:"cubic-bezier(.47,0,.745,.715)",easeOutSine:"cubic-bezier(.39,.575,.565,1)",easeInOutSine:"cubic-bezier(.445,.05,.55,.95)",easeInBack:"cubic-bezier(.6,-.28,.735,.045)",easeOutBack:"cubic-bezier(.175, .885,.32,1.275)",easeInOutBack:"cubic-bezier(.68,-.55,.265,1.55)"};
  2377. f[c]&&(c=f[c]);h.off(jQuery.CSS.transitionEnd+"."+e.id);f=jQuery.CSS.getProp(d);var m={};jQuery.extend(m,d);m[jQuery.CSS.sfx+"transition-property"]=f;m[jQuery.CSS.sfx+"transition-duration"]=a+"ms";m[jQuery.CSS.sfx+"transition-delay"]=b+"ms";m[jQuery.CSS.sfx+"transition-timing-function"]=c;setTimeout(function(){h.one(jQuery.CSS.transitionEnd+"."+e.id,n);h.css(m)},1);e.timeout=setTimeout(function(){e.called||!g?(e.called=!1,e.CSSAIsRunning=!1):(h.css(jQuery.CSS.sfx+"transition",""),g.apply(e),e.CSSAIsRunning=
  2378. !1,"function"==typeof e.CSSqueue&&(e.CSSqueue(),e.CSSqueue=null))},a+b+10)}else{for(f in d)"transform"===f&&delete d[f],"filter"===f&&delete d[f],"transform-origin"===f&&delete d[f],"auto"===d[f]&&delete d[f],"x"===f&&(k=d[f],l="left",d[l]=k,delete d[f]),"y"===f&&(k=d[f],l="top",d[l]=k,delete d[f]),"-ms-transform"!==f&&"-ms-filter"!==f||delete d[f];h.delay(b).animate(d,a,g)}}})}};jQuery.fn.CSSAnimate=jQuery.CSS.animate;jQuery.normalizeCss=jQuery.CSS.normalizeCss;
  2379. jQuery.fn.css3=function(d){return this.each(function(){var a=jQuery(this),b=jQuery.normalizeCss(d);a.css(b)})};
  2380. /*___________________________________________________________________________________________________________________________________________________
  2381. _ jquery.mb.components _
  2382. _ _
  2383. _ file: jquery.mb.simpleSlider.min.js _
  2384. _ last modified: 09/05/17 19.31 _
  2385. _ _
  2386. _ Open Lab s.r.l., Florence - Italy _
  2387. _ _
  2388. _ email: matteo@open-lab.com _
  2389. _ site: http://pupunzi.com _
  2390. _ http://open-lab.com _
  2391. _ blog: http://pupunzi.open-lab.com _
  2392. _ Q&A: http://jquery.pupunzi.com _
  2393. _ _
  2394. _ Licences: MIT, GPL _
  2395. _ http://www.opensource.org/licenses/mit-license.php _
  2396. _ http://www.gnu.org/licenses/gpl.html _
  2397. _ _
  2398. _ Copyright (c) 2001-2017. Matteo Bicocchi (Pupunzi); _
  2399. ___________________________________________________________________________________________________________________________________________________*/
  2400. (function(b){b.simpleSlider={defaults:{initialval:0,maxval:100,orientation:"h",readonly:!1,callback:!1},events:{start:b.mbBrowser.mobile?"touchstart":"mousedown",end:b.mbBrowser.mobile?"touchend":"mouseup",move:b.mbBrowser.mobile?"touchmove":"mousemove"},init:function(d){return this.each(function(){var a=this,c=b(a);c.addClass("simpleSlider");a.opt={};b.extend(a.opt,b.simpleSlider.defaults,d);b.extend(a.opt,c.data());var f="h"===a.opt.orientation?"horizontal":"vertical";f=b("<div/>").addClass("level").addClass(f);
  2401. c.prepend(f);a.level=f;c.css({cursor:"default"});"auto"==a.opt.maxval&&(a.opt.maxval=b(a).outerWidth());c.updateSliderVal();a.opt.readonly||(c.on(b.simpleSlider.events.start,function(e){b.mbBrowser.mobile&&(e=e.changedTouches[0]);a.canSlide=!0;c.updateSliderVal(e);"h"===a.opt.orientation?c.css({cursor:"col-resize"}):c.css({cursor:"row-resize"});a.lastVal=a.val;b.mbBrowser.mobile||(e.preventDefault(),e.stopPropagation())}),b(document).on(b.simpleSlider.events.move,function(e){b.mbBrowser.mobile&&(e=e.changedTouches[0]);
  2402. a.canSlide&&(b(document).css({cursor:"default"}),c.updateSliderVal(e),b.mbBrowser.mobile||(e.preventDefault(),e.stopPropagation()))}).on(b.simpleSlider.events.end,function(){b(document).css({cursor:"auto"});a.canSlide=!1;c.css({cursor:"auto"})}))})},updateSliderVal:function(d){var a=this.get(0);if(a.opt){a.opt.initialval="number"==typeof a.opt.initialval?a.opt.initialval:a.opt.initialval(a);var c=b(a).outerWidth(),f=b(a).outerHeight();a.x="object"==typeof d?d.clientX+document.body.scrollLeft-this.offset().left:
  2403. "number"==typeof d?d*c/a.opt.maxval:a.opt.initialval*c/a.opt.maxval;a.y="object"==typeof d?d.clientY+document.body.scrollTop-this.offset().top:"number"==typeof d?(a.opt.maxval-a.opt.initialval-d)*f/a.opt.maxval:a.opt.initialval*f/a.opt.maxval;a.y=this.outerHeight()-a.y;a.scaleX=a.x*a.opt.maxval/c;a.scaleY=a.y*a.opt.maxval/f;a.outOfRangeX=a.scaleX>a.opt.maxval?a.scaleX-a.opt.maxval:0>a.scaleX?a.scaleX:0;a.outOfRangeY=a.scaleY>a.opt.maxval?a.scaleY-a.opt.maxval:0>a.scaleY?a.scaleY:0;a.outOfRange="h"===
  2404. a.opt.orientation?a.outOfRangeX:a.outOfRangeY;a.value="undefined"!=typeof d?"h"===a.opt.orientation?a.x>=this.outerWidth()?a.opt.maxval:0>=a.x?0:a.scaleX:a.y>=this.outerHeight()?a.opt.maxval:0>=a.y?0:a.scaleY:"h"===a.opt.orientation?a.scaleX:a.scaleY;"h"===a.opt.orientation?a.level.width(Math.floor(100*a.x/c)+"%"):a.level.height(Math.floor(100*a.y/f));a.lastVal===a.value&&("h"===a.opt.orientation&&(a.x>=this.outerWidth()||0>=a.x)||"h"!==a.opt.orientation&&(a.y>=this.outerHeight()||0>=a.y))||("function"===
  2405. typeof a.opt.callback&&a.opt.callback(a),a.lastVal=a.value)}}};b.fn.simpleSlider=b.simpleSlider.init;b.fn.updateSliderVal=b.simpleSlider.updateSliderVal})(jQuery);
  2406. /*___________________________________________________________________________________________________________________________________________________
  2407. _ jquery.mb.components _
  2408. _ _
  2409. _ file: jquery.mb.storage.min.js _
  2410. _ last modified: 24/05/15 16.08 _
  2411. _ _
  2412. _ Open Lab s.r.l., Florence - Italy _
  2413. _ _
  2414. _ email: matteo@open-lab.com _
  2415. _ site: http://pupunzi.com _
  2416. _ http://open-lab.com _
  2417. _ blog: http://pupunzi.open-lab.com _
  2418. _ Q&A: http://jquery.pupunzi.com _
  2419. _ _
  2420. _ Licences: MIT, GPL _
  2421. _ http://www.opensource.org/licenses/mit-license.php _
  2422. _ http://www.gnu.org/licenses/gpl.html _
  2423. _ _
  2424. _ Copyright (c) 2001-2015. Matteo Bicocchi (Pupunzi); _
  2425. ___________________________________________________________________________________________________________________________________________________*/
  2426. (function(d){d.mbCookie={set:function(a,c,f,b){"object"==typeof c&&(c=JSON.stringify(c));b=b?"; domain="+b:"";var e=new Date,d="";0<f&&(e.setTime(e.getTime()+864E5*f),d="; expires="+e.toGMTString());document.cookie=a+"="+c+d+"; path=/"+b},get:function(a){a+="=";for(var c=document.cookie.split(";"),d=0;d<c.length;d++){for(var b=c[d];" "==b.charAt(0);)b=b.substring(1,b.length);if(0==b.indexOf(a))try{return JSON.parse(b.substring(a.length,b.length))}catch(e){return b.substring(a.length,b.length)}}return null},
  2427. remove:function(a){d.mbCookie.set(a,"",-1)}};d.mbStorage={set:function(a,c){"object"==typeof c&&(c=JSON.stringify(c));localStorage.setItem(a,c)},get:function(a){if(localStorage[a])try{return JSON.parse(localStorage[a])}catch(c){return localStorage[a]}else return null},remove:function(a){a?localStorage.removeItem(a):localStorage.clear()}}})(jQuery);
  2428. /*___________________________________________________________________________________________________________________________________________________
  2429. _ jquery.mb.components _
  2430. _ _
  2431. _ file: jquery.mbBrowser.min.js _
  2432. _ last modified: 1/23/21 4:18 PM _
  2433. _ _
  2434. _ Open Lab s.r.l., Florence - Italy _
  2435. _ _
  2436. _ email: matteo@open-lab.com _
  2437. _ site: http://pupunzi.com _
  2438. _ http://open-lab.com _
  2439. _ blog: http://pupunzi.open-lab.com _
  2440. _ Q&A: http://jquery.pupunzi.com _
  2441. _ _
  2442. _ Licences: MIT, GPL _
  2443. _ http://www.opensource.org/licenses/mit-license.php _
  2444. _ http://www.gnu.org/licenses/gpl.html _
  2445. _ _
  2446. _ Copyright (c) 2001-2021. Matteo Bicocchi (Pupunzi); _
  2447. ___________________________________________________________________________________________________________________________________________________*/
  2448. var nAgt=navigator.userAgent;jQuery.mbBrowser={};jQuery.mbBrowser.mozilla=!1;jQuery.mbBrowser.webkit=!1;jQuery.mbBrowser.opera=!1;jQuery.mbBrowser.safari=!1;jQuery.mbBrowser.chrome=!1;jQuery.mbBrowser.androidStock=!1;jQuery.mbBrowser.msie=!1;jQuery.mbBrowser.edge=!1;jQuery.mbBrowser.ua=nAgt;function isTouchSupported(){var a=nAgt.msMaxTouchPoints,e="ontouchstart"in document.createElement("div");return a||e?!0:!1}
  2449. var getOS=function(){var a={version:"Unknown version",name:"Unknown OS"};-1!=navigator.appVersion.indexOf("Win")&&(a.name="Windows");-1!=navigator.appVersion.indexOf("Mac")&&0>navigator.appVersion.indexOf("Mobile")&&(a.name="Mac");-1!=navigator.appVersion.indexOf("Linux")&&(a.name="Linux");/Mac OS X/.test(nAgt)&&!/Mobile/.test(nAgt)&&(a.version=/Mac OS X ([\._\d]+)/.exec(nAgt)[1],a.version=a.version.replace(/_/g,".").substring(0,5));/Windows/.test(nAgt)&&(a.version="Unknown.Unknown");/Windows NT 5.1/.test(nAgt)&&
  2450. (a.version="5.1");/Windows NT 6.0/.test(nAgt)&&(a.version="6.0");/Windows NT 6.1/.test(nAgt)&&(a.version="6.1");/Windows NT 6.2/.test(nAgt)&&(a.version="6.2");/Windows NT 10.0/.test(nAgt)&&(a.version="10.0");/Linux/.test(nAgt)&&/Linux/.test(nAgt)&&(a.version="Unknown.Unknown");a.name=a.name.toLowerCase();a.major_version="Unknown";a.minor_version="Unknown";"Unknown.Unknown"!=a.version&&(a.major_version=parseFloat(a.version.split(".")[0]),a.minor_version=parseFloat(a.version.split(".")[1]));return a};
  2451. jQuery.mbBrowser.os=getOS();jQuery.mbBrowser.hasTouch=isTouchSupported();jQuery.mbBrowser.name=navigator.appName;jQuery.mbBrowser.fullVersion=""+parseFloat(navigator.appVersion);jQuery.mbBrowser.majorVersion=parseInt(navigator.appVersion,10);var nameOffset,verOffset,ix;
  2452. if(-1!=(verOffset=nAgt.indexOf("Opera")))jQuery.mbBrowser.opera=!0,jQuery.mbBrowser.name="Opera",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+6),-1!=(verOffset=nAgt.indexOf("Version"))&&(jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+8));else if(-1!=(verOffset=nAgt.indexOf("OPR")))jQuery.mbBrowser.opera=!0,jQuery.mbBrowser.name="Opera",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+4);else if(-1!=(verOffset=nAgt.indexOf("MSIE")))jQuery.mbBrowser.msie=!0,jQuery.mbBrowser.name=
  2453. "Microsoft Internet Explorer",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+5);else if(-1!=nAgt.indexOf("Trident")){jQuery.mbBrowser.msie=!0;jQuery.mbBrowser.name="Microsoft Internet Explorer";var start=nAgt.indexOf("rv:")+3,end=start+4;jQuery.mbBrowser.fullVersion=nAgt.substring(start,end)}else-1!=(verOffset=nAgt.indexOf("Edge"))?(jQuery.mbBrowser.edge=!0,jQuery.mbBrowser.name="Microsoft Edge",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+5)):-1!=(verOffset=nAgt.indexOf("Chrome"))?
  2454. (jQuery.mbBrowser.webkit=!0,jQuery.mbBrowser.chrome=!0,jQuery.mbBrowser.name="Chrome",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+7)):-1<nAgt.indexOf("mozilla/5.0")&&-1<nAgt.indexOf("android ")&&-1<nAgt.indexOf("applewebkit")&&!(-1<nAgt.indexOf("chrome"))?(verOffset=nAgt.indexOf("Chrome"),jQuery.mbBrowser.webkit=!0,jQuery.mbBrowser.androidStock=!0,jQuery.mbBrowser.name="androidStock",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+7)):-1!=(verOffset=nAgt.indexOf("Safari"))?(jQuery.mbBrowser.webkit=
  2455. !0,jQuery.mbBrowser.safari=!0,jQuery.mbBrowser.name="Safari",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+7),-1!=(verOffset=nAgt.indexOf("Version"))&&(jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+8))):-1!=(verOffset=nAgt.indexOf("AppleWebkit"))?(jQuery.mbBrowser.webkit=!0,jQuery.mbBrowser.safari=!0,jQuery.mbBrowser.name="Safari",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+7),-1!=(verOffset=nAgt.indexOf("Version"))&&(jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+
  2456. 8))):-1!=(verOffset=nAgt.indexOf("Firefox"))?(jQuery.mbBrowser.mozilla=!0,jQuery.mbBrowser.name="Firefox",jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+8)):(nameOffset=nAgt.lastIndexOf(" ")+1)<(verOffset=nAgt.lastIndexOf("/"))&&(jQuery.mbBrowser.name=nAgt.substring(nameOffset,verOffset),jQuery.mbBrowser.fullVersion=nAgt.substring(verOffset+1),jQuery.mbBrowser.name.toLowerCase()==jQuery.mbBrowser.name.toUpperCase()&&(jQuery.mbBrowser.name=navigator.appName));
  2457. -1!=(ix=jQuery.mbBrowser.fullVersion.indexOf(";"))&&(jQuery.mbBrowser.fullVersion=jQuery.mbBrowser.fullVersion.substring(0,ix));-1!=(ix=jQuery.mbBrowser.fullVersion.indexOf(" "))&&(jQuery.mbBrowser.fullVersion=jQuery.mbBrowser.fullVersion.substring(0,ix));jQuery.mbBrowser.majorVersion=parseInt(""+jQuery.mbBrowser.fullVersion,10);isNaN(jQuery.mbBrowser.majorVersion)&&(jQuery.mbBrowser.fullVersion=""+parseFloat(navigator.appVersion),jQuery.mbBrowser.majorVersion=parseInt(navigator.appVersion,10));
  2458. jQuery.mbBrowser.version=jQuery.mbBrowser.majorVersion;jQuery.mbBrowser.android=/Android/i.test(nAgt);jQuery.mbBrowser.blackberry=/BlackBerry|BB|PlayBook/i.test(nAgt);jQuery.mbBrowser.ios=/iPhone|iPad|iPod|webOS/i.test(nAgt);jQuery.mbBrowser.operaMobile=/Opera Mini/i.test(nAgt);jQuery.mbBrowser.windowsMobile=/IEMobile|Windows Phone/i.test(nAgt);jQuery.mbBrowser.kindle=/Kindle|Silk/i.test(nAgt);
  2459. jQuery.mbBrowser.mobile=jQuery.mbBrowser.android||jQuery.mbBrowser.blackberry||jQuery.mbBrowser.ios||jQuery.mbBrowser.windowsMobile||jQuery.mbBrowser.operaMobile||jQuery.mbBrowser.kindle;jQuery.isMobile=jQuery.mbBrowser.mobile;jQuery.isTablet=jQuery.mbBrowser.mobile&&765<jQuery(window).width();jQuery.isAndroidDefault=jQuery.mbBrowser.android&&!/chrome/i.test(nAgt);jQuery.mbBrowser=jQuery.mbBrowser;
  2460. jQuery.mbBrowser.versionCompare=function(a,e){if("stringstring"!=typeof a+typeof e)return!1;for(var c=a.split("."),d=e.split("."),b=0,f=Math.max(c.length,d.length);b<f;b++){if(c[b]&&!d[b]&&0<parseInt(c[b])||parseInt(c[b])>parseInt(d[b]))return 1;if(d[b]&&!c[b]&&0<parseInt(d[b])||parseInt(c[b])<parseInt(d[b]))return-1}return 0};