UNPKG

jquery.mb.ytplayer

Version:

This plugin let you play any public YouTube video as background of your page. It can also be used as a customized player in page.

1,941 lines (1,612 loc) 75.9 kB
/********************************************** * @File Name: jquery.mb.YTPlayer.src.js * @Author: Matteo Bicocchi * @Date: 2020-03-16 * @Email: matbicoc@gmail.com * * @Last Modified by: Matteo Bicocchi * @Last Modified time: 2020-03-18 * @Copyright: 2020. Matteo Bicocchi * * Open Lab s.r.l., Florence - Italy * @blog: http://pupunzi.open-lab.com * @site: http://pupunzi.com ****************************************************/ /* src-block */ alert('This is the \'jquery.mb.YTPlayer.src.js\' javascript file and can\'t be included. Use the one you find in the \'dist\' folder!'); /* end-src-block */ var ytp = ytp || {}; let YTPRndSuffix = new Date().getTime(); let YTPTimerLabels = { init : "YTPlayerInit_" + YTPRndSuffix, startPlaying: "YTPlayerStartPlay_" + YTPRndSuffix }; function onYouTubeIframeAPIReady() { if (ytp.YTAPIReady) return; ytp.YTAPIReady = true; jQuery(document).trigger('YTAPIReady') } let getYTPVideoID = function (url) { let videoID, playlistID; if (url.indexOf('youtu.be') > 0 || url.indexOf('youtube.com/embed') > 0) { videoID = url.substr(url.lastIndexOf('/') + 1, url.length); playlistID = videoID.indexOf('?list=') > 0 ? videoID.substr(videoID.lastIndexOf('='), videoID.length) : null; videoID = playlistID ? videoID.substr(0, videoID.lastIndexOf('?')) : videoID } else if (url.indexOf('http') > -1) { //videoID = url.match( /([\/&]v\/([^&#]*))|([\\?&]v=([^&#]*))/ )[ 1 ]; videoID = url.match(/[\\?&]v=([^&#]*)/)[1]; playlistID = url.indexOf('list=') > 0 ? url.match(/[\\?&]list=([^&#]*)/)[1] : null } else { videoID = url.length > 15 ? null : url; playlistID = videoID ? null : url } return { videoID : videoID, playlistID: playlistID } }; function iOSversion() { if (/iP(hone|od|ad)/.test(navigator.platform)) { let v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/); return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)] } } (function (jQuery, ytp) { jQuery.mbYTPlayer = { name : 'jquery.mb.YTPlayer', version: '{{ version }}', build : '{{ buildnum }}', author : 'Matteo Bicocchi (pupunzi)', apiKey : '', /* * Default options for the player */ defaults : { /** videoURL (string) the complete Youtube video URL or the short url or the videoID */ videoURL: null, /** containment (string) default containment for the player */ containment: 'body', /** ratio (string or number) "auto", "16/9", "4/3" or number: 4/3, 16/9 */ ratio: 'auto', /** fadeOnStartTime (int) fade in timing at video start */ fadeOnStartTime: 1000, /** startAt (int) start second */ startAt: 0, /** stopAt (int) stop second */ stopAt: 0, /** autoPlay (bool) on page load video should start or pause */ autoPlay: true, /** delayAtStart (bool) If the YT API don't fire the event the player will try to start anyway after... */ delayAtStart: 1000, /** coverImage (string) The path to the image to be used as cover if the autoPlay option is set to false */ coverImage: false, /** loop (bool or int) video should loop or not; if number it will loop for the specified times */ loop: true, /** addRaster (bool) shows a raster image over the video (added via CSS) You can change the raster image via CSS: .YTPOverlay.raster { background: url(images/raster.png)} */ addRaster: false, /** mask (bool or object) the key is the second and the value is the path to the image Ex: mask:{ 0:'assets/mask-1.png', 5:'assets/mask-2.png', 30: false, 50:'assets/mask-3.png'} */ mask: false, /** opacity (int) 0 to 1 */ opacity: 1, /** quality (string) @deprecated setPlaybackQuality has been deprecated on the YT API and doesn't work anymore “small”, “medium”, “large”, “hd720”, “hd1080”, “highres”, "default" */ quality: 'hd1080', /** vol (int) 0 to 100 */ vol: 50, /** mute (bool) mute the video at start */ mute: false, /** showControls (bool) shows the control bar at the bottom of the containment */ showControls: true, /** anchor (string) center,top,bottom,left,right combined in pair */ anchor: 'center,center', /** showAnnotations (bool) display the annotations on video */ showAnnotations: false, /** cc_load_policy (bool) display the subtitles */ cc_load_policy: false, /** showYTLogo (bool) display the Youtube logotype inside the button bar */ showYTLogo: true, /** useOnMobile (bool) activate the player also on mobile */ useOnMobile: true, /** playOnlyIfVisible (bool) play the video only if the containment is on screen */ playOnlyIfVisible: false, /** onScreenPercentage (bool) percentage of the player height the video should stop or start when visible */ onScreenPercentage: 30, /** * goFullScreenOnPlay (bool) * if the player containment is set to "self" this allow the video to go fullscreen when played */ goFullScreenOnPlay: false, /** stopMovieOnBlur (bool) stop the video if the window loose the focus */ stopMovieOnBlur: true, /** realfullscreen (bool) the video when in full screen covers all the display */ realFullscreen: true, /** optimizeDisplay (bool) The video always fit the containment without displaying the black strips */ optimizeDisplay: true, /** abundance (bool) the abudance of the video size */ abundance: 0.3, /** gaTrack (bool) track the video plays on GA */ gaTrack: true, /** remember_last_time (bool) when the page is reloaded the video will start from the last position */ remember_last_time: false, /** addFilters (bool or string) add one or more CSS filters as object to the video Ex: {sepia: 50, hue_rotate : 220} */ addFilters: false, /** useNoCookie (bool) use https://www.youtube-nocookie.com host to serve the video */ useNoCookie: true, /** onReady (function) a callback function fired once the player is ready */ onReady: function (player) { }, /** onReady (function) a callback function fired if there's an error */ onError: function (player, err) { }, /** onEnd (function) a callback function fired when the video ends */ onEnd: function () { } }, /** * @fontface icons * */ controls : { play : 'P', pause : 'p', mute : 'M', unmute : 'A', onlyYT : 'O', showSite: 'R', ytLogo : 'Y' }, controlBar : null, locationProtocol: 'https:', /** * Applicable filters */ defaultFilters: { grayscale : {value: 0, unit: '%'}, hue_rotate: {value: 0, unit: 'deg'}, invert : {value: 0, unit: '%'}, opacity : {value: 0, unit: '%'}, saturate : {value: 0, unit: '%'}, sepia : {value: 0, unit: '%'}, brightness: {value: 0, unit: '%'}, contrast : {value: 0, unit: '%'}, blur : {value: 0, unit: 'px'} }, /** * build the player * @param options * @returns [players] */ buildPlayer: function (options) { if (!ytp.YTAPIReady && typeof window.YT === 'undefined') { jQuery('#YTAPI').remove(); let tag = jQuery('<script>').attr({ 'src': 'https://www.youtube.com/iframe_api?v=' + jQuery.mbYTPlayer.version, 'id' : 'YTAPI' }); jQuery('head').prepend(tag) } else { setTimeout(function () { jQuery(document).trigger('YTAPIReady'); ytp.YTAPIReady = true }, 100) } function isIframe() { let isIfr = false; try { if (self.location.href !== top.location.href) isIfr = true } catch (e) { isIfr = true } return isIfr } return this.each(function () { let YTPlayer = this; let $YTPlayer = jQuery(YTPlayer); $YTPlayer.hide(); YTPlayer.loop = 0; YTPlayer.state = 0; YTPlayer.filters = jQuery.extend(true, {}, jQuery.mbYTPlayer.defaultFilters); YTPlayer.filtersEnabled = true; YTPlayer.id = YTPlayer.id || 'YTP_' + new Date().getTime(); $YTPlayer.addClass('mb_YTPlayer'); /** Set properties */ let property = $YTPlayer.data('property') && typeof $YTPlayer.data('property') == 'string' ? eval('(' + $YTPlayer.data('property') + ')') : $YTPlayer.data('property'); if (typeof property !== 'object') property = {}; YTPlayer.opt = jQuery.extend(true, {}, jQuery.mbYTPlayer.defaults, YTPlayer.opt, options, property); YTPRndSuffix = getYTPVideoID(YTPlayer.opt.videoURL).videoID; YTPTimerLabels = { init : "YTPlayerInit_" + YTPRndSuffix, startPlaying: "YTPlayerStartPlay_" + YTPRndSuffix }; console.time(YTPTimerLabels.init); console.time(YTPTimerLabels.startPlaying); YTPlayer.opt.elementId = YTPlayer.id; if (YTPlayer.opt.vol === 0) { YTPlayer.opt.vol = 1; YTPlayer.opt.mute = true } if (YTPlayer.opt.loop && typeof YTPlayer.opt.loop === 'boolean') { YTPlayer.opt.loop = 9999 } /** Disable fullScreen if is in an iframe or full-screen API is not available */ let fullScreenAvailable = document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled; YTPlayer.opt.realFullscreen = isIframe() || !fullScreenAvailable ? false : YTPlayer.opt.realFullscreen; /** Manage annotations */ YTPlayer.opt.showAnnotations = YTPlayer.opt.showAnnotations ? '1' : '3'; /** Manage show subtitle and caption */ YTPlayer.opt.cc_load_policy = YTPlayer.opt.cc_load_policy ? '1' : '0'; /** Manage cover image */ YTPlayer.opt.coverImage = YTPlayer.opt.coverImage || YTPlayer.opt.backgroundImage; /** Manage Quality the setPlaybackQuality has been deprecated by YT */ YTPlayer.opt.quality = 'hd1080'; /** * todo: remove Manage Opacity for IE < 10 */ if (jQuery.mbBrowser.msie && jQuery.mbBrowser.version < 9) YTPlayer.opt.opacity = 1; YTPlayer.opt.containment = YTPlayer.opt.containment === 'self' ? $YTPlayer : jQuery(YTPlayer.opt.containment); YTPlayer.isRetina = (window.retina || window.devicePixelRatio > 1); YTPlayer.opt.ratio = YTPlayer.opt.ratio === 'auto' ? 16 / 9 : YTPlayer.opt.ratio; YTPlayer.opt.ratio = eval(YTPlayer.opt.ratio); let origContainmentBackground = YTPlayer.opt.containment.css('background-image'); origContainmentBackground = (origContainmentBackground === 'none') ? null : origContainmentBackground; YTPlayer.orig_containment_background = origContainmentBackground; if (!$YTPlayer.attr('id')) $YTPlayer.attr('id', 'ytp_' + new Date().getTime()); YTPlayer.playerID = 'iframe_' + YTPlayer.id; YTPlayer.isAlone = false; YTPlayer.hasFocus = true; YTPlayer.videoID = YTPlayer.opt.videoURL ? getYTPVideoID(YTPlayer.opt.videoURL).videoID : $YTPlayer.attr('href') ? getYTPVideoID($YTPlayer.attr('href')).videoID : false; /** Check if it is a video list */ YTPlayer.playlistID = YTPlayer.opt.videoURL ? getYTPVideoID(YTPlayer.opt.videoURL).playlistID : $YTPlayer.attr('href') ? getYTPVideoID($YTPlayer.attr('href')).playlistID : false; let start_from_last = 0; if (jQuery.mbCookie.get('YTPlayer_start_from' + YTPlayer.videoID)) start_from_last = parseFloat(jQuery.mbCookie.get('YTPlayer_start_from' + YTPlayer.videoID)); if (YTPlayer.opt.remember_last_time && start_from_last) { YTPlayer.start_from_last = start_from_last; jQuery.mbCookie.remove('YTPlayer_start_from' + YTPlayer.videoID) } YTPlayer.isPlayer = $YTPlayer.is(YTPlayer.opt.containment); YTPlayer.isBackground = YTPlayer.opt.containment.is('body'); if (YTPlayer.isBackground && ytp.backgroundIsInited) return; /** Hide the placeholder if it's not the target of the player */ if (YTPlayer.isPlayer) $YTPlayer.show(); /** create the overlay */ YTPlayer.overlay = jQuery('<div/>').css({ position: 'absolute', top : 0, left : 0, width : '100%', height : '100%' }).addClass('YTPOverlay'); $YTPlayer.changeCoverImage(); /** create the wrapper */ YTPlayer.wrapper = jQuery('<div/>').attr('id', 'wrapper_' + YTPlayer.id).css({ position : 'absolute', zIndex : 0, minWidth : '100%', minHeight: '100%', left : 0, top : 0, overflow : 'hidden', opacity : 0 }).addClass('mbYTP_wrapper'); /** If is an inline player toggle play if the overlay is clicked */ if (YTPlayer.isPlayer) { let inlinePlayButtonCss = jQuery.browser.mobile ? "inlinePlayButtonMobile" : "inlinePlayButton"; YTPlayer.inlinePlayButton = jQuery('<div/>').addClass('inlinePlayButton').html(jQuery.mbYTPlayer.controls.play); $YTPlayer.append(YTPlayer.inlinePlayButton); YTPlayer.inlinePlayButton.on('click', function (e) { $YTPlayer.YTPPlay(); /** * Hide the PLAY button on play */ YTPlayer.inlinePlayButton.hide(); /** * set the fullscreen on play */ if (YTPlayer.opt.goFullScreenOnPlay) { $YTPlayer.YTPFullscreen(); } e.stopPropagation() }); if (YTPlayer.opt.autoPlay) YTPlayer.inlinePlayButton.hide(); YTPlayer.overlay.on('click', function () { $YTPlayer.YTPTogglePlay(); if (YTPlayer.opt.goFullScreenOnPlay) { $YTPlayer.YTPFullscreen(); } }).css({cursor: 'pointer'}) } /** create the playerBox where the YT iframe will be placed */ let playerBox = jQuery('<div/>').attr('id', YTPlayer.playerID).addClass('playerBox'); playerBox.css({ position: 'absolute', zIndex : 0, width : '100%', height : '100%', top : 0, left : 0, overflow: 'hidden', opacity : 1 }); YTPlayer.wrapper.append(playerBox); playerBox.after(YTPlayer.overlay); if (YTPlayer.isPlayer) { YTPlayer.inlineWrapper = jQuery('<div/>').addClass('inline-YTPlayer'); YTPlayer.inlineWrapper.css({ position: 'relative', maxWidth: YTPlayer.opt.containment.css('width') }); YTPlayer.opt.containment.css({ position : 'relative', paddingBottom: '56.25%', overflow : 'hidden', height : 0 }); YTPlayer.opt.containment.wrap(YTPlayer.inlineWrapper) } /** Loop all the elements inside the container and check if their position is not "static" */ YTPlayer.opt.containment.children().not('script, style').each(function () { if (jQuery(this).css('position') === 'static') jQuery(this).css('position', 'relative') }); if (YTPlayer.isBackground) { jQuery('body').css({ boxSizing: 'border-box' }); YTPlayer.wrapper.css({ position: 'fixed', top : 0, left : 0, zIndex : 0 }) } else if (YTPlayer.opt.containment.css('position') === 'static') { YTPlayer.opt.containment.css({ position: 'relative' }); $YTPlayer.show() } YTPlayer.opt.containment.prepend(YTPlayer.wrapper); if (!YTPlayer.isBackground) { YTPlayer.overlay.on('mouseenter', function () { if (YTPlayer.controlBar && YTPlayer.controlBar.length) YTPlayer.controlBar.addClass('visible') }).on('mouseleave', function () { if (YTPlayer.controlBar && YTPlayer.controlBar.length) YTPlayer.controlBar.removeClass('visible') }) } if (jQuery.mbBrowser.mobile && !YTPlayer.opt.useOnMobile) { if (YTPlayer.opt.coverImage) { YTPlayer.wrapper.css({ backgroundImage : 'url(' + YTPlayer.opt.coverImage + ')', backgroundPosition: 'center center', backgroundSize : 'cover', backgroundRepeat : 'no-repeat', opacity : 1 }); YTPlayer.wrapper.css({opacity: 1}) } return $YTPlayer } /** If is on device start playing on first touch */ if (jQuery.mbBrowser.mobile && YTPlayer.opt.autoPlay && YTPlayer.opt.useOnMobile) jQuery('body').one('touchstart', function () { YTPlayer.player.playVideo() }); jQuery(document).one('YTAPIReady', function () { $YTPlayer.trigger('YTAPIReady_' + YTPlayer.id); ytp.YTAPIReady = true }); YTPlayer.isOnScreen = jQuery.mbYTPlayer.isOnScreen(YTPlayer, YTPlayer.opt.onScreenPercentage); $YTPlayer.one('YTAPIReady_' + YTPlayer.id, function () { let YTPlayer = this; let $YTPlayer = jQuery(YTPlayer); if ((YTPlayer.isBackground && ytp.backgroundIsInited) || YTPlayer.isInit) return; if (YTPlayer.isBackground) ytp.backgroundIsInited = true; YTPlayer.opt.autoPlay = typeof YTPlayer.opt.autoPlay == 'undefined' ? (!!YTPlayer.isBackground) : YTPlayer.opt.autoPlay; YTPlayer.opt.vol = YTPlayer.opt.vol ? YTPlayer.opt.vol : 100; jQuery.mbYTPlayer.getDataFromAPI(YTPlayer); jQuery(YTPlayer).on('YTPChanged', function (e) { if (YTPlayer.isInit) return; YTPlayer.isInit = true; /** Initialize the YT player ------------------------------------ * Youtube player variables * @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}} */ let playerVars = { 'modestbranding' : 1, 'autoplay' : 0, 'controls' : 0, 'showinfo' : 0, 'rel' : 0, 'enablejsapi' : 1, 'version' : 3, 'playerapiid' : YTPlayer.playerID, 'origin' : '*', 'allowfullscreen': true, 'wmode' : 'transparent', 'iv_load_policy' : YTPlayer.opt.showAnnotations, 'cc_load_policy' : YTPlayer.opt.cc_load_policy, 'playsinline' : jQuery.mbBrowser.mobile && !YTPlayer.isPlayer ? 1 : 0, /** Check if the browser can play HTML5 videos */ 'html5': document.createElement('video').canPlayType ? 1 : 0 }; new YT.Player(YTPlayer.playerID, { //videoId: YTPlayer.videoID.toString(), host : YTPlayer.opt.useNoCookie? 'https://www.youtube-nocookie.com' : 'https://www.youtube.com', playerVars: playerVars, events : { 'onReady' : function (event) { YTPlayer.player = event.target; YTPlayer.player.loadVideoById({ videoId : YTPlayer.videoID.toString(), suggestedQuality: YTPlayer.opt.quality }); $YTPlayer.trigger('YTPlayerIsReady_' + YTPlayer.id) }, /** * on State Change * @param event * * -1 (unstarted) * 0 (ended) * 1 (playing) * 2 (paused) * 3 (buffering) * 5 (video cued) */ 'onStateChange' : function (event) { if (typeof event.target.getPlayerState != 'function') return; let state = event.target.getPlayerState(); if (YTPlayer.preventTrigger || YTPlayer.isStarting) { YTPlayer.preventTrigger = false; return } YTPlayer.state = state; // console.debug(YTPlayer.state); if (event.data === YT.PlayerState.PLAYING) { event.target.setPlaybackQuality(YTPlayer.opt.quality) } let eventType; switch (state) { /** unstarted */ case -1: eventType = 'YTPUnstarted'; break; /** unstarted */ case 0: eventType = 'YTPRealEnd'; break; /** play */ case 1: eventType = 'YTPPlay'; if (YTPlayer.controlBar.length) YTPlayer.controlBar.find('.mb_YTPPlayPause').html(jQuery.mbYTPlayer.controls.pause); if (YTPlayer.isPlayer) YTPlayer.inlinePlayButton.hide(); jQuery(document).off('mousedown.YTPstart'); break; /** pause */ case 2: eventType = 'YTPPause'; if (YTPlayer.controlBar.length) YTPlayer.controlBar.find('.mb_YTPPlayPause').html(jQuery.mbYTPlayer.controls.play); if (YTPlayer.isPlayer) YTPlayer.inlinePlayButton.show(); break; /** buffer */ case 3: // YTPlayer.player.setPlaybackQuality('default'); YTPlayer.player.setPlaybackQuality(YTPlayer.opt.quality); eventType = 'YTPBuffering'; if (YTPlayer.controlBar.length) YTPlayer.controlBar.find('.mb_YTPPlayPause').html(jQuery.mbYTPlayer.controls.play); break; /** cued */ case 5: eventType = 'YTPCued'; break; default: break } /** Trigger state events */ let YTPEvent = jQuery.Event(eventType); YTPEvent.time = YTPlayer.currentTime; jQuery(YTPlayer).trigger(YTPEvent) }, /** * onPlaybackQualityChange * @param e */ 'onPlaybackQualityChange': function (e) { let quality = e.target.getPlaybackQuality(); let YTPQualityChange = jQuery.Event('YTPQualityChange'); YTPQualityChange.quality = quality; jQuery(YTPlayer).trigger(YTPQualityChange) }, /** * onError * @param err * 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. 5 – The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred. 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. 101 – The owner of the requested video does not allow it to be played in embedded players. 150 – This error is the same as 101. It's just a 101 error in disguise! */ 'onError' : function (err) { if (typeof YTPlayer.opt.onError == 'function') YTPlayer.opt.onError($YTPlayer, err); console.debug("error:", err); switch (err.data) { case 2: 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.'); break; case 5: 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.'); break; case 100: 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.'); break; case 101: case 150: console.error('video ID:: ' + YTPlayer.videoID + ': The video doesn\'t exist or The owner does not allow it to be played in embedded players.'); break } if (YTPlayer.isList) jQuery(YTPlayer).YTPPlayNext() } } }); $YTPlayer.on('YTPlayerIsReady_' + YTPlayer.id, function () { if (YTPlayer.isReady) return this; YTPlayer.playerEl = YTPlayer.player.getIframe(); jQuery(YTPlayer.playerEl).unselectable(); $YTPlayer.optimizeDisplay(); /** * Optimize display on resize */ jQuery(window).off('resize.YTP_' + YTPlayer.id).on('resize.YTP_' + YTPlayer.id, function () { $YTPlayer.optimizeDisplay() }); /** * Optimize display on orientation change */ jQuery(window).off('orientationchange.YTP_' + YTPlayer.id).on('orientationchange.YTP_' + YTPlayer.id, function () { $YTPlayer.optimizeDisplay() }); /** * Set the time of the last visit progress */ if (YTPlayer.opt.remember_last_time) { jQuery(window).on('unload.YTP_' + YTPlayer.id, function () { let current_time = YTPlayer.player.getCurrentTime(); jQuery.mbCookie.set('YTPlayer_start_from' + YTPlayer.videoID, current_time, 0) }) } $YTPlayer.YTPCheckForState() }) }) }); $YTPlayer.off('YTPTime.mask'); jQuery.mbYTPlayer.applyMask(YTPlayer); console.timeEnd(YTPTimerLabels.init); setTimeout(function () { if (!ytp.YTAPIReady && typeof window.YT == "object") { jQuery(document).trigger('YTAPIReady'); ytp.YTAPIReady = true; console.error("YTPlayer: More then a call to the YT API has been detected") } }, YTPlayer.opt.delayAtStart) }) }, /** * * @param YTPlayer * @param perc * @returns {boolean} */ isOnScreen: function (YTPlayer, perc) { perc = perc || 10; let playerBox = YTPlayer.wrapper; let winTop = jQuery(window).scrollTop(); let winBottom = winTop + jQuery(window).height(); let margin = (playerBox.height() * perc) / 100; let elTop = playerBox.offset().top + margin; let elBottom = playerBox.offset().top + (playerBox.height() - margin); return ((elBottom <= winBottom) && (elTop >= winTop)) }, /** * getDataFromAPI * @param YTPlayer */ getDataFromAPI: function (YTPlayer) { YTPlayer.videoData = jQuery.mbStorage.get('YTPlayer_data_' + YTPlayer.videoID); if (YTPlayer.videoData) { setTimeout(function () { YTPlayer.dataReceived = true; let YTPChanged = jQuery.Event('YTPChanged'); YTPChanged.time = YTPlayer.currentTime; YTPChanged.videoId = YTPlayer.videoID; YTPChanged.opt = YTPlayer.opt; //console.debug("videoData:",YTPlayer.videoData) jQuery(YTPlayer).trigger(YTPChanged); let YTPData = jQuery.Event('YTPData'); YTPData.prop = {}; for (let x in YTPlayer.videoData) if (YTPlayer.videoData.hasOwnProperty(x)) YTPData.prop[x] = YTPlayer.videoData[x]; jQuery(YTPlayer).trigger(YTPData) }, YTPlayer.opt.fadeOnStartTime); YTPlayer.hasData = true } else if (jQuery.mbYTPlayer.apiKey) { /** * Get video info from API3 (needs api key) * snippet,player,contentDetails,statistics,status */ jQuery.getJSON('https://www.googleapis.com/youtube/v3/videos?id=' + YTPlayer.videoID + '&key=' + jQuery.mbYTPlayer.apiKey + '&part=snippet', function (data) { YTPlayer.dataReceived = true; let YTPChanged = jQuery.Event('YTPChanged'); YTPChanged.time = YTPlayer.currentTime; YTPChanged.videoId = YTPlayer.videoID; jQuery(YTPlayer).trigger(YTPChanged); function parseYTPlayer_data(data) { YTPlayer.videoData = {}; YTPlayer.videoData.id = YTPlayer.videoID; YTPlayer.videoData.channelTitle = data.channelTitle; YTPlayer.videoData.title = data.title; YTPlayer.videoData.description = data.description.length < 400 ? data.description : data.description.substring(0, 400) + ' ...'; YTPlayer.videoData.thumb_max = data.thumbnails.maxres ? data.thumbnails.maxres.url : null; YTPlayer.videoData.thumb_high = data.thumbnails.high ? data.thumbnails.high.url : null; YTPlayer.videoData.thumb_medium = data.thumbnails.medium ? data.thumbnails.medium.url : null; jQuery.mbStorage.set('YTPlayer_data_' + YTPlayer.videoID, YTPlayer.videoData) } if (!data.items[0]) { YTPlayer.videoData = {}; YTPlayer.hasData = false } else { parseYTPlayer_data(data.items[0].snippet); YTPlayer.hasData = true } let YTPData = jQuery.Event('YTPData'); YTPData.prop = {}; for (let x in YTPlayer.videoData) YTPData.prop[x] = YTPlayer.videoData[x]; jQuery(YTPlayer).trigger(YTPData) }) .fail(function (jqxhr) { console.error("YT data error:: ", jqxhr); YTPlayer.hasData = false; let YTPChanged = jQuery.Event('YTPChanged'); YTPChanged.time = YTPlayer.currentTime; YTPChanged.videoId = YTPlayer.videoID; jQuery(YTPlayer).trigger(YTPChanged) }) } else { setTimeout(function () { let YTPChanged = jQuery.Event('YTPChanged'); YTPChanged.time = YTPlayer.currentTime; YTPChanged.videoId = YTPlayer.videoID; jQuery(YTPlayer).trigger(YTPChanged) }, 10); YTPlayer.videoData = null } YTPlayer.opt.ratio = YTPlayer.opt.ratio == 'auto' ? 16 / 9 : YTPlayer.opt.ratio; if (YTPlayer.isPlayer && !YTPlayer.opt.autoPlay) { //&& ( !jQuery.mbBrowser.mobile && !jQuery.isTablet ) YTPlayer.loading = jQuery('<div/>').addClass('loading').html('Loading').hide(); jQuery(YTPlayer).append(YTPlayer.loading); YTPlayer.loading.fadeIn() } }, /** * removeStoredData */ removeStoredData: function () { jQuery.mbStorage.remove() }, /** * getVideoData * @returns {*|YTPlayer.videoData} */ getVideoData: function () { let YTPlayer = this.get(0); return YTPlayer.videoData }, /** * getVideoID * @returns {*|YTPlayer.videoID|boolean} */ getVideoID: function () { let YTPlayer = this.get(0); return YTPlayer.videoID || false }, /** * getPlaylistID * @returns {*|YTPlayer.videoID|boolean} */ getPlaylistID : function () { let YTPlayer = this.get(0); return YTPlayer.playlistID || false }, /** * setVideoQuality * @deprecated * * @param quality * @returns {jQuery.mbYTPlayer} */ setVideoQuality: function (quality) { let YTPlayer = this.get(0); let time = YTPlayer.player.getCurrentTime(); jQuery(YTPlayer).YTPPause(); YTPlayer.opt.quality = quality; YTPlayer.player.setPlaybackQuality(quality); YTPlayer.player.seekTo(time); // or set to CurrentTime using player.getCurrentTime() jQuery(YTPlayer).YTPPlay(); return this; }, /** * getVideoQuality * @returns {jQuery.mbYTPlayer} */ getVideoQuality: function () { let YTPlayer = this.get(0); let quality = YTPlayer.player.getPlaybackQuality(); return quality }, /** * playlist * @param videos -> Array or String (videoList ID) * @param shuffle * @param callback * @returns {jQuery.mbYTPlayer} * * To retrieve a Youtube playlist the Youtube API key is required: * https://console.developers.google.com/ * jQuery.mbYTPlayer.apiKey */ playlist: function (videos, shuffle, callback) { let $YTPlayer = this; let YTPlayer = $YTPlayer.get(0); YTPlayer.isList = true; if (shuffle) videos = jQuery.shuffle(videos); if (!YTPlayer.videoID) { YTPlayer.videos = videos; YTPlayer.videoCounter = 1; YTPlayer.videoLength = videos.length; jQuery(YTPlayer).data('property', videos[0]); jQuery(YTPlayer).YTPlayer() } if (typeof callback == 'function') jQuery(YTPlayer).on('YTPChanged', function () { callback(YTPlayer) }); jQuery(YTPlayer).on('YTPEnd', function () { jQuery(YTPlayer).YTPPlayNext() }); return this }, /** * playNext * @returns {jQuery.mbYTPlayer} */ playNext: function () { let YTPlayer = this.get(0); YTPlayer.videoCounter++; if (YTPlayer.videoCounter > YTPlayer.videoLength) YTPlayer.videoCounter = 1; jQuery(YTPlayer).YTPPlayIndex(YTPlayer.videoCounter); return this }, /** * playPrev * @returns {jQuery.mbYTPlayer} */ playPrev: function () { let YTPlayer = this.get(0); YTPlayer.videoCounter--; if (YTPlayer.videoCounter <= 0) YTPlayer.videoCounter = YTPlayer.videoLength; jQuery(YTPlayer).YTPPlayIndex(YTPlayer.videoCounter); return this }, /** * playIndex * @param idx * @returns {jQuery.mbYTPlayer} */ playIndex: function (idx) { let YTPlayer = this.get(0); if (YTPlayer.checkForStartAt) { clearInterval(YTPlayer.checkForStartAt); clearInterval(YTPlayer.getState) } YTPlayer.videoCounter = idx; if (YTPlayer.videoCounter >= YTPlayer.videoLength) YTPlayer.videoCounter = YTPlayer.videoLength; let video = YTPlayer.videos[YTPlayer.videoCounter - 1]; jQuery(YTPlayer).YTPChangeVideo(video); return this }, /** * changeVideo * @param opt * @returns {jQuery.mbYTPlayer} */ changeVideo: function (opt) { let $YTPlayer = this; let YTPlayer = $YTPlayer.get(0); YTPlayer.opt.startAt = 0; YTPlayer.opt.stopAt = 0; YTPlayer.opt.mask = false; YTPlayer.opt.mute = true; YTPlayer.opt.autoPlay = true; YTPlayer.opt.addFilters = false; YTPlayer.opt.coverImage = false; YTPlayer.hasData = false; YTPlayer.hasChanged = true; YTPlayer.player.loopTime = undefined; if (opt) jQuery.extend(YTPlayer.opt, opt); YTPlayer.videoID = getYTPVideoID(YTPlayer.opt.videoURL).videoID; if (YTPlayer.opt.loop && typeof YTPlayer.opt.loop == 'boolean') YTPlayer.opt.loop = 9999; YTPlayer.wrapper.css({ background: 'none' }); jQuery(YTPlayer.playerEl).CSSAnimate({ opacity: 0 }, YTPlayer.opt.fadeOnStartTime, function () { jQuery.mbYTPlayer.getDataFromAPI(YTPlayer); $YTPlayer.YTPGetPlayer().loadVideoById({ videoId : YTPlayer.videoID, suggestedQuality: YTPlayer.opt.quality }); $YTPlayer.YTPPause(); $YTPlayer.optimizeDisplay(); if (YTPlayer.checkForStartAt) { clearInterval(YTPlayer.checkForStartAt); clearInterval(YTPlayer.getState) } $YTPlayer.YTPCheckForState() }); let YTPChangeVideo = jQuery.Event('YTPChangeVideo'); YTPChangeVideo.time = YTPlayer.currentTime; jQuery(YTPlayer).trigger(YTPChangeVideo); jQuery.mbYTPlayer.applyMask(YTPlayer); return this }, /** * getPlayer * @returns {player} */ getPlayer: function () { let YTPlayer = this.get(0); return !YTPlayer.isReady ? null : YTPlayer.player }, /** * playerDestroy * @returns {jQuery.mbYTPlayer} */ playerDestroy: function () { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; ytp.YTAPIReady = true; ytp.backgroundIsInited = false; YTPlayer.isInit = false; YTPlayer.videoID = null; YTPlayer.isReady = false; YTPlayer.wrapper.remove(); jQuery('#controlBar_' + YTPlayer.id).remove(); clearInterval(YTPlayer.checkForStartAt); clearInterval(YTPlayer.getState); return this }, /** * fullscreen * @param real * @returns {jQuery.mbYTPlayer} */ fullscreen: function (real) { let YTPlayer = this.get(0); if (typeof real == 'undefined') real = eval(YTPlayer.opt.realFullscreen); let controls = jQuery('#controlBar_' + YTPlayer.id); let fullScreenBtn = controls.find('.mb_OnlyYT'); let videoWrapper = YTPlayer.isPlayer ? YTPlayer.opt.containment : YTPlayer.wrapper; if (real) { let fullscreenchange = jQuery.mbBrowser.mozilla ? 'mozfullscreenchange' : jQuery.mbBrowser.webkit ? 'webkitfullscreenchange' : 'fullscreenchange'; jQuery(document).off(fullscreenchange).on(fullscreenchange, function () { let isFullScreen = RunPrefixMethod(document, 'IsFullScreen') || RunPrefixMethod(document, 'FullScreen'); if (!isFullScreen) { YTPlayer.isAlone = false; fullScreenBtn.html(jQuery.mbYTPlayer.controls.onlyYT); jQuery(YTPlayer).YTPSetVideoQuality(YTPlayer.opt.quality); videoWrapper.removeClass('YTPFullscreen'); videoWrapper.CSSAnimate({ opacity: YTPlayer.opt.opacity }, YTPlayer.opt.fadeOnStartTime); videoWrapper.css({ zIndex: 0 }); if (YTPlayer.isBackground) { jQuery('body').after(controls) } else { YTPlayer.wrapper.before(controls) } jQuery(window).resize(); jQuery(YTPlayer).trigger('YTPFullScreenEnd') } else { jQuery(YTPlayer).trigger('YTPFullScreenStart') } }) } if (!YTPlayer.isAlone) { function hideMouse() { YTPlayer.overlay.css({ cursor: 'none' }) } jQuery(document).on('mousemove.YTPlayer', function (e) { YTPlayer.overlay.css({ cursor: 'auto' }); clearTimeout(YTPlayer.hideCursor); if (!jQuery(e.target).parents().is('.mb_YTPBar')) YTPlayer.hideCursor = setTimeout(hideMouse, 3000) }); hideMouse(); if (real) { videoWrapper.css({ opacity: 0 }); videoWrapper.addClass('YTPFullscreen'); launchFullscreen(videoWrapper.get(0)); setTimeout(function () { videoWrapper.CSSAnimate({ opacity: 1 }, YTPlayer.opt.fadeOnStartTime * 2); videoWrapper.append(controls); jQuery(YTPlayer).optimizeDisplay(); YTPlayer.player.seekTo(YTPlayer.player.getCurrentTime() + .1, true) }, YTPlayer.opt.fadeOnStartTime) } else videoWrapper.css({ zIndex: 10000 }).CSSAnimate({ opacity: 1 }, YTPlayer.opt.fadeOnStartTime * 2); fullScreenBtn.html(jQuery.mbYTPlayer.controls.showSite); YTPlayer.isAlone = true } else { jQuery(document).off('mousemove.YTPlayer'); clearTimeout(YTPlayer.hideCursor); YTPlayer.overlay.css({ cursor: 'auto' }); if (real) { cancelFullscreen() } else { videoWrapper.CSSAnimate({ opacity: YTPlayer.opt.opacity }, YTPlayer.opt.fadeOnStartTime); videoWrapper.css({ zIndex: 0 }) } fullScreenBtn.html(jQuery.mbYTPlayer.controls.onlyYT); YTPlayer.isAlone = false } function RunPrefixMethod(obj, method) { let pfx = ['webkit', 'moz', 'ms', 'o', '']; let p = 0, m, t; while (p < pfx.length && !obj[m]) { m = method; if (pfx[p] == '') { m = m.substr(0, 1).toLowerCase() + m.substr(1) } m = pfx[p] + m; t = typeof obj[m]; if (t != 'undefined') { pfx = [pfx[p]]; return (t == 'function' ? obj[m]() : obj[m]) } p++ } } function launchFullscreen(element) { RunPrefixMethod(element, 'RequestFullScreen') } function cancelFullscreen() { if (RunPrefixMethod(document, 'FullScreen') || RunPrefixMethod(document, 'IsFullScreen')) { RunPrefixMethod(document, 'CancelFullScreen') } } return this }, /** * toggleLoops * @returns {jQuery.mbYTPlayer} */ toggleLoops: function () { let YTPlayer = this.get(0); let data = YTPlayer.opt; if (data.loop == 1) { data.loop = 0 } else { if (data.startAt) { YTPlayer.player.seekTo(data.startAt) } else { YTPlayer.player.playVideo() } data.loop = 1 } return this }, /** * play * @returns {jQuery.mbYTPlayer} */ play: function () { let YTPlayer = this.get(0); let $YTPlayer = jQuery(YTPlayer); if (!YTPlayer.isReady) return this; setTimeout(function () { $YTPlayer.YTPSetAbundance(YTPlayer.opt.abundance) }, 300); YTPlayer.player.playVideo(); jQuery(YTPlayer.playerEl).css({ opacity: 1 }); YTPlayer.wrapper.css({ backgroundImage: 'none' }); YTPlayer.wrapper.CSSAnimate({ opacity: YTPlayer.isAlone ? 1 : YTPlayer.opt.opacity }, YTPlayer.opt.fadeOnStartTime); let controls = jQuery('#controlBar_' + YTPlayer.id); let playBtn = controls.find('.mb_YTPPlayPause'); playBtn.html(jQuery.mbYTPlayer.controls.pause); YTPlayer.state = 1; return this }, /** * togglePlay * @param callback * @returns {jQuery.mbYTPlayer} */ togglePlay: function (callback) { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; if (YTPlayer.state == 1) this.YTPPause(); else this.YTPPlay(); if (typeof callback == 'function') callback(YTPlayer.state); return this }, /** * stop * @returns {jQuery.mbYTPlayer} */ stop: function () { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; let controls = jQuery('#controlBar_' + YTPlayer.id); let playBtn = controls.find('.mb_YTPPlayPause'); playBtn.html(jQuery.mbYTPlayer.controls.play); YTPlayer.player.stopVideo(); return this }, /** * pause * @returns {jQuery.mbYTPlayer} */ pause: function () { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; if (YTPlayer.opt.abundance < .2) this.YTPSetAbundance(.2); YTPlayer.player.pauseVideo(); YTPlayer.state = 2; return this }, /** * seekTo * @param sec * @returns {jQuery.mbYTPlayer} */ seekTo: function (sec) { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; YTPlayer.player.seekTo(sec, true); return this }, /** * * @returns {*} */ getPlaybackRate: function () { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; return YTPlayer.player.getPlaybackRate() }, /** * setPlaybackRate * @param val:Number * 0.25, 0.5, 1, 1.5, 2 * @returns {jQuery.mbYTPlayer} */ setPlaybackRate: function (val) { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; YTPlayer.player.setPlaybackRate(val); return this }, /** * setVolume * @param val * @returns {jQuery.mbYTPlayer} */ setVolume: function (val) { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; YTPlayer.opt.vol = val; this.YTPUnmute(); YTPlayer.player.setVolume(YTPlayer.opt.vol); if (YTPlayer.volumeBar && YTPlayer.volumeBar.length) YTPlayer.volumeBar.updateSliderVal(val); return this }, /** * getVolume * @returns {*} */ getVolume: function () { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; return YTPlayer.player.getVolume() }, /** * toggleVolume * @returns {jQuery.mbYTPlayer} */ toggleVolume: function () { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; if (YTPlayer.isMute) { if (!jQuery.mbBrowser.mobile) this.YTPSetVolume(YTPlayer.opt.vol); this.YTPUnmute() } else { this.YTPMute() } return this }, /** * mute * @returns {jQuery.mbYTPlayer} */ mute: function () { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; if (YTPlayer.isMute) return this; YTPlayer.player.mute(); YTPlayer.isMute = true; YTPlayer.player.setVolume(0); if (YTPlayer.volumeBar && YTPlayer.volumeBar.length && YTPlayer.volumeBar.width() > 10) { YTPlayer.volumeBar.updateSliderVal(0) } let controls = jQuery('#controlBar_' + YTPlayer.id); let muteBtn = controls.find('.mb_YTPMuteUnmute'); muteBtn.html(jQuery.mbYTPlayer.controls.unmute); jQuery(YTPlayer).addClass('isMuted'); if (YTPlayer.volumeBar && YTPlayer.volumeBar.length) YTPlayer.volumeBar.addClass('muted'); let YTPEvent = jQuery.Event('YTPMuted'); YTPEvent.time = YTPlayer.currentTime; if (!YTPlayer.preventTrigger) jQuery(YTPlayer).trigger(YTPEvent); return this }, /** * unmute * @returns {jQuery.mbYTPlayer} */ unmute: function () { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; if (!YTPlayer.isMute) return this; YTPlayer.player.unMute(); YTPlayer.isMute = false; jQuery(YTPlayer).YTPSetVolume(YTPlayer.opt.vol); if (YTPlayer.volumeBar && YTPlayer.volumeBar.length) YTPlayer.volumeBar.updateSliderVal(YTPlayer.opt.vol > 10 ? YTPlayer.opt.vol : 10); let controls = jQuery('#controlBar_' + YTPlayer.id); let muteBtn = controls.find('.mb_YTPMuteUnmute'); muteBtn.html(jQuery.mbYTPlayer.controls.mute); jQuery(YTPlayer).removeClass('isMuted'); if (YTPlayer.volumeBar && YTPlayer.volumeBar.length) YTPlayer.volumeBar.removeClass('muted'); let YTPEvent = jQuery.Event('YTPUnmuted'); YTPEvent.time = YTPlayer.currentTime; if (!YTPlayer.preventTrigger) jQuery(YTPlayer).trigger(YTPEvent); return this }, /* FILTERS ---------------------------------------------------------------------------------------------------------*/ /** * applyFilter * @param filter * @param value * @returns {jQuery.mbYTPlayer} */ applyFilter: function (filter, value) { let $YTPlayer = this; let YTPlayer = $YTPlayer.get(0); if (!YTPlayer.isReady) return this; YTPlayer.filters[filter].value = value; if (YTPlayer.filtersEnabled) $YTPlayer.YTPEnableFilters() }, /** * applyFilters * @param filters * @returns {jQuery.mbYTPlayer} */ applyFilters: function (filters) { let $YTPlayer = this; let YTPlayer = $YTPlayer.get(0); if (!YTPlayer.isReady) { jQuery(YTPlayer).on('YTPReady', function () { $YTPlayer.YTPApplyFilters(filters) }); return this } for (let key in filters) { $YTPlayer.YTPApplyFilter(key, filters[key]) } $YTPlayer.trigger('YTPFiltersApplied') }, /** * toggleFilter * @param filter * @param value * @returns {jQuery.mbYTPlayer} */ toggleFilter: function (filter, value) { let $YTPlayer = this; let YTPlayer = $YTPlayer.get(0); if (!YTPlayer.isReady) return this; if (!YTPlayer.filters[filter].value) YTPlayer.filters[filter].value = value; else YTPlayer.filters[filter].value = 0; if (YTPlayer.filtersEnabled) jQuery(YTPlayer).YTPEnableFilters(); return this }, /** * toggleFilters * @param callback * @returns {jQuery.mbYTPlayer} */ toggleFilters: function (callback) { let $YTPlayer = this; let YTPlayer = $YTPlayer.get(0); if (!YTPlayer.isReady) return this; if (YTPlayer.filtersEnabled) { jQuery(YTPlayer).trigger('YTPDisableFilters'); jQuery(YTPlayer).YTPDisableFilters() } else { jQuery(YTPlayer).YTPEnableFilters(); jQuery(YTPlayer).trigger('YTPEnableFilters') } if (typeof callback == 'function') callback(YTPlayer.filtersEnabled); return this }, /** * disableFilters * @returns {jQuery.mbYTPlayer} */ disableFilters: function () { let $YTPlayer = this; let YTPlayer = $YTPlayer.get(0); if (!YTPlayer.isReady) return this; let iframe = jQuery(YTPlayer.playerEl); iframe.css('-webkit-filter', ''); iframe.css('filter', ''); YTPlayer.filtersEnabled = false; return this }, /** * enableFilters * @returns {jQuery.mbYTPlayer} */ enableFilters: function () { let $YTPlayer = this; let YTPlayer = $YTPlayer.get(0); if (!YTPlayer.isReady) return this; let iframe = jQuery(YTPlayer.playerEl); let filterStyle = ''; for (let key in YTPlayer.filters) { if (YTPlayer.filters[key].value) filterStyle += key.replace('_', '-') + '(' + YTPlayer.filters[key].value + YTPlayer.filters[key].unit + ') ' } iframe.css('-webkit-filter', filterStyle); iframe.css('filter', filterStyle); YTPlayer.filtersEnabled = true; return this }, /** * removeFilter * @param filter * @param callback * @returns {jQuery.mbYTPlayer} */ removeFilter: function (filter, callback) { let $YTPlayer = this; let YTPlayer = $YTPlayer.get(0); if (!YTPlayer.isReady) return this; if (typeof filter == 'function') { callback = filter; filter = null } if (!filter) { for (let key in YTPlayer.filters) { if (YTPlayer.filters.hasOwnProperty(key)) { $YTPlayer.YTPApplyFilter(key, 0); if (typeof callback == 'function') callback(key); } } YTPlayer.filters = jQuery.extend(true, {}, jQuery.mbYTPlayer.defaultFilters) } else { $YTPlayer.YTPApplyFilter(filter, 0); if (typeof callback == 'function') callback(filter) } let YTPEvent = jQuery.Event('YTPFiltersApplied'); $YTPlayer.trigger(YTPEvent); return this }, /** * getFilters * @returns {filters} */ getFilters: function () { let YTPlayer = this.get(0); if (!YTPlayer.isReady) return this; return YTPlayer.filters }, /* MASK ---------------------------------------------------------------------------------------------------------*/ /** * addMask * @param mask * @returns {jQuery.mbYTPlayer} */ addMask: function (mask) { let YTPlayer = this.get(0); if (!mask) mask = YTPlayer.actualMask; let tempImg = jQuery('<img/>').attr('src', mask).on('load', function () { YTPlayer.overlay.CSSAnimate({ opacity: 0 }, YTPlayer.opt.fadeOnStartTime, function () { YTPlayer.hasMask = true; tempImg.remove(); YTPlayer.overlay.css({ backgroundImage : 'url(' + mask + ')', backgroundRepeat : 'no-repeat', backgroundPosition: 'center center', backgroundSize : 'cover' }); YTPlayer.overlay.CSSAnimate({ opacity: 1 }, YTPlayer.opt.fadeOnStartTime) }) }); return this }, /** * removeMask * @returns {jQuery.mbYTPlayer} */ removeMask: function () { let YTPlayer = this.get(0); YTPlayer.overlay.CSSAnimate({ opacity: 0 }, YTPlayer.opt.fadeOnStartTime, function () { YTPlayer.hasMask = false; YTPlayer.overlay.css({ backgroundImage : '', backgroundRepeat : '', backgroundPosition: '', backgroundSize : '' }); YTPlayer.overlay.CSSAnimat