{"mappings":"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","sources":["src/video/video.ima.js"],"sourcesContent":["/**\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * IMA SDK integration plugin for Video.js. For more information see\n * https://www.github.com/googleads/videojs-ima\n */\n\n(function(vjs) {\n 'use strict';\n var extend = function(obj) {\n var arg;\n var index;\n var key;\n for (index = 1; index < arguments.length; index++) {\n arg = arguments[index];\n for (key in arg) {\n if (arg.hasOwnProperty(key)) {\n obj[key] = arg[key];\n }\n }\n }\n return obj;\n },\n\n ima_defaults = {\n debug: false,\n timeout: 5000,\n prerollTimeout: 100\n },\n\n imaPlugin = function(options, readyCallback) {\n var player = this;\n\n /**\n * Creates the ad container passed to the IMA SDK.\n * @private\n */\n player.ima.createAdContainer_ = function() {\n // The adContainerDiv is the DOM of the element that will house\n // the ads and ad controls.\n vjsControls = player.getChild('controlBar');\n adContainerDiv =\n vjsControls.el().parentNode.insertBefore(\n document.createElement('div'),\n vjsControls.el());\n adContainerDiv.id = 'ima-ad-container';\n adContainerDiv.style.width = player.width() + 'px';\n adContainerDiv.style.height = player.height() + 'px';\n adContainerDiv.addEventListener(\n 'mouseover',\n player.ima.showAdControls_,\n false);\n adContainerDiv.addEventListener(\n 'mouseout',\n player.ima.hideAdControls_,\n false);\n player.ima.createControls_();\n adDisplayContainer =\n new google.ima.AdDisplayContainer(adContainerDiv, contentPlayer);\n };\n\n /**\n * Creates the controls for the ad.\n * @private\n */\n player.ima.createControls_ = function() {\n controlsDiv = document.createElement('div');\n controlsDiv.id = 'ima-controls-div';\n controlsDiv.style.width = '100%';\n countdownDiv = document.createElement('div');\n countdownDiv.id = 'ima-countdown-div';\n countdownDiv.innerHTML = 'Advertisement';\n countdownDiv.style.display = showCountdown ? 'block' : 'none';\n seekBarDiv = document.createElement('div');\n seekBarDiv.id = 'ima-seek-bar-div';\n seekBarDiv.style.width = player.width() + 'px';\n progressDiv = document.createElement('div');\n progressDiv.id = 'ima-progress-div';\n playPauseDiv = document.createElement('div');\n playPauseDiv.id = 'ima-play-pause-div';\n playPauseDiv.className = 'ima-playing';\n playPauseDiv.addEventListener(\n 'click',\n player.ima.onAdPlayPauseClick_,\n false);\n muteDiv = document.createElement('div');\n muteDiv.id = 'ima-mute-div';\n muteDiv.className = 'ima-non-muted';\n muteDiv.addEventListener(\n 'click',\n player.ima.onAdMuteClick_,\n false);\n sliderDiv = document.createElement('div');\n sliderDiv.id = 'ima-slider-div';\n sliderDiv.addEventListener(\n 'mousedown',\n player.ima.onAdVolumeSliderMouseDown_,\n false);\n sliderLevelDiv = document.createElement('div');\n sliderLevelDiv.id = 'ima-slider-level-div';\n fullscreenDiv = document.createElement('div');\n fullscreenDiv.id = 'ima-fullscreen-div';\n fullscreenDiv.className = 'ima-non-fullscreen';\n fullscreenDiv.addEventListener(\n 'click',\n player.ima.onAdFullscreenClick_,\n false);\n adContainerDiv.insertBefore(\n controlsDiv,\n adContainerDiv.childNodes[adContainerDiv.childNodes.length]);\n controlsDiv.insertBefore(\n countdownDiv, controlsDiv.childNodes[controlsDiv.childNodes.length]);\n controlsDiv.insertBefore(\n seekBarDiv, controlsDiv.childNodes[controlsDiv.childNodes.length]);\n controlsDiv.insertBefore(\n playPauseDiv, controlsDiv.childNodes[controlsDiv.childNodes.length]);\n controlsDiv.insertBefore(\n muteDiv, controlsDiv.childNodes[controlsDiv.childNodes.length]);\n controlsDiv.insertBefore(\n sliderDiv, controlsDiv.childNodes[controlsDiv.childNodes.length]);\n controlsDiv.insertBefore(\n fullscreenDiv, controlsDiv.childNodes[controlsDiv.childNodes.length]);\n seekBarDiv.insertBefore(\n progressDiv, seekBarDiv.childNodes[controlsDiv.childNodes.length]);\n sliderDiv.insertBefore(\n sliderLevelDiv, sliderDiv.childNodes[sliderDiv.childNodes.length]);\n };\n\n /**\n * Initializes the AdDisplayContainer. On mobile, this must be done as a\n * result of user action.\n */\n player.ima.initializeAdDisplayContainer = function() {\n adDisplayContainerInitialized = true;\n adDisplayContainer.initialize();\n }\n\n /**\n * Creates the AdsRequest and request ads through the AdsLoader.\n */\n player.ima.requestAds = function() {\n if (!adDisplayContainerInitialized) {\n adDisplayContainer.initialize();\n }\n var adsRequest = new google.ima.AdsRequest();\n adsRequest.adTagUrl = settings.adTagUrl;\n\n adsRequest.linearAdSlotWidth = player.width();\n adsRequest.linearAdSlotHeight = player.height();\n adsRequest.nonLinearAdSlotWidth =\n settings.nonLinearWidth || player.width();\n adsRequest.nonLinearAdSlotHeight =\n settings.nonLinearHeight || (player.height() / 3);\n\n adsLoader.requestAds(adsRequest);\n };\n\n /**\n * Listener for the ADS_MANAGER_LOADED event. Creates the AdsManager,\n * sets up event listeners, and triggers the 'adsready' event for\n * videojs-ads-contrib.\n * @private\n */\n player.ima.onAdsManagerLoaded_ = function(adsManagerLoadedEvent) {\n adsManager = adsManagerLoadedEvent.getAdsManager(\n contentPlayheadTracker, adsRenderingSettings);\n\n adsManager.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n player.ima.onAdError_);\n adsManager.addEventListener(\n google.ima.AdEvent.Type.AD_BREAK_READY,\n player.ima.onAdBreakReady_);\n adsManager.addEventListener(\n google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED,\n player.ima.onContentPauseRequested_);\n adsManager.addEventListener(\n google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED,\n player.ima.onContentResumeRequested_);\n adsManager.addEventListener(\n google.ima.AdEvent.Type.ALL_ADS_COMPLETED,\n player.ima.onAllAdsCompleted_);\n\n adsManager.addEventListener(\n google.ima.AdEvent.Type.LOADED,\n player.ima.onAdLoaded_);\n adsManager.addEventListener(\n google.ima.AdEvent.Type.STARTED,\n player.ima.onAdStarted_);\n adsManager.addEventListener(\n google.ima.AdEvent.Type.CLICK,\n player.ima.onAdPlayPauseClick_);\n adsManager.addEventListener(\n google.ima.AdEvent.Type.COMPLETE,\n player.ima.onAdComplete_);\n adsManager.addEventListener(\n google.ima.AdEvent.Type.SKIPPED,\n player.ima.onAdComplete_);\n\n if (!autoPlayAdBreaks) {\n try {\n adsManager.init(\n player.width(),\n player.height(),\n google.ima.ViewMode.NORMAL);\n adsManager.setVolume(player.muted() ? 0 : player.volume());\n } catch (adError) {\n player.ima.onAdError_(adError);\n }\n }\n\n player.trigger('adsready');\n };\n\n /**\n * Start ad playback, or content video playback in the absence of a\n * pre-roll.\n */\n player.ima.start = function() {\n if (autoPlayAdBreaks) {\n try {\n adsManager.init(\n player.width(),\n player.height(),\n google.ima.ViewMode.NORMAL);\n adsManager.setVolume(player.muted() ? 0 : player.volume());\n adsManager.start();\n } catch (adError) {\n player.ima.onAdError_(adError);\n }\n }\n };\n\n /**\n * Listener for errors fired by the AdsLoader.\n * @param {google.ima.AdErrorEvent} event The error event thrown by the\n * AdsLoader. See\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdError.Type\n * @private\n */\n player.ima.onAdsLoaderError_ = function(event) {\n window.console.log('AdsLoader error: ' + event.getError());\n if (adsManager) {\n adsManager.destroy();\n }\n player.trigger('adserror');\n };\n\n /**\n * Listener for errors thrown by the AdsManager.\n * @param {google.ima.AdErrorEvent} adErrorEvent The error event thrown by\n * the AdsManager.\n * @private\n */\n player.ima.onAdError_ = function(adErrorEvent) {\n window.console.log('Ad error: ' + adErrorEvent.getError());\n adsManager.destroy();\n adContainerDiv.style.display = 'none';\n player.trigger('adserror');\n };\n\n /**\n * Listener for AD_BREAK_READY. Passes event on to publisher's listener.\n * @param {google.ima.AdEvent} adEvent AdEvent thrown by the AdsManager.\n * @private\n */\n player.ima.onAdBreakReady_ = function(adEvent) {\n adBreakReadyListener(adEvent);\n };\n\n /**\n * Called by publishers in manual ad break playback mode to start an ad\n * break.\n */\n player.ima.playAdBreak = function() {\n if (!autoPlayAdBreaks) {\n adsManager.start();\n }\n }\n\n /**\n * Pauses the content video and displays the ad container so ads can play.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.\n * @private\n */\n player.ima.onContentPauseRequested_ = function(adEvent) {\n adsActive = true;\n adPlaying = true;\n player.off('ended', localContentEndedListener);\n if (adEvent.getAd().getAdPodInfo().getPodIndex() != -1) {\n // Skip this call for post-roll ads\n player.ads.startLinearAdMode();\n }\n adContainerDiv.style.display = 'block';\n controlsDiv.style.display = 'block';\n vjsControls.hide();\n player.pause();\n };\n\n /**\n * Resumes content video and hides the ad container.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.\n * @private\n */\n player.ima.onContentResumeRequested_ = function(adEvent) {\n adsActive = false;\n adPlaying = false;\n player.on('ended', localContentEndedListener);\n if (currentAd && currentAd.isLinear()) {\n adContainerDiv.style.display = 'none';\n }\n vjsControls.show();\n if (!currentAd) {\n // Something went wrong playing the ad\n player.ads.endLinearAdMode();\n } else if (!contentComplete &&\n // Don't exit linear mode after post-roll or content will auto-replay\n currentAd.getAdPodInfo().getPodIndex() != -1 ) {\n player.ads.endLinearAdMode();\n }\n countdownDiv.innerHTML = '';\n };\n\n /**\n * Records that ads have completed and calls contentAndAdsEndedListeners\n * if content is also complete.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.\n * @private\n */\n player.ima.onAllAdsCompleted_ = function(adEvent) {\n allAdsCompleted = true;\n if (contentComplete == true) {\n for (var index in contentAndAdsEndedListeners) {\n contentAndAdsEndedListeners[index]();\n }\n }\n }\n\n /**\n * Starts the content video when a non-linear ad is loaded.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.\n * @private\n */\n player.ima.onAdLoaded_ = function(adEvent) {\n if (!adEvent.getAd().isLinear()) {\n player.play();\n }\n };\n\n /**\n * Starts the interval timer to check the current ad time when an ad starts\n * playing.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.\n * @private\n */\n player.ima.onAdStarted_ = function(adEvent) {\n currentAd = adEvent.getAd();\n if (currentAd.isLinear()) {\n adTrackingTimer = setInterval(\n player.ima.onAdPlayheadTrackerInterval_, 250);\n // Don't bump container when controls are shown\n adContainerDiv.className = '';\n } else {\n // Bump container when controls are shown\n adContainerDiv.className = 'bumpable-ima-ad-container';\n }\n };\n\n /**\n * Clears the interval timer for current ad time when an ad completes.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.\n * @private\n */\n player.ima.onAdComplete_ = function(adEvent) {\n if (currentAd.isLinear()) {\n clearInterval(adTrackingTimer);\n }\n };\n\n /**\n * Gets the current time and duration of the ad and calls the method to\n * update the ad UI.\n * @private\n */\n player.ima.onAdPlayheadTrackerInterval_ = function() {\n var remainingTime = adsManager.getRemainingTime();\n var duration = currentAd.getDuration();\n var currentTime = duration - remainingTime;\n currentTime = currentTime > 0 ? currentTime : 0;\n var isPod = false;\n var adPosition, totalAds;\n if (currentAd.getAdPodInfo()) {\n isPod = true;\n adPosition = currentAd.getAdPodInfo().getAdPosition();\n totalAds = currentAd.getAdPodInfo().getTotalAds();\n }\n\n // Update countdown timer data\n var remainingMinutes = Math.floor(remainingTime / 60);\n var remainingSeconds = Math.floor(remainingTime % 60);\n if (remainingSeconds.toString().length < 2) {\n remainingSeconds = '0' + remainingSeconds;\n }\n var podCount = ': ';\n if (isPod) {\n podCount = ' (' + adPosition + ' of ' + totalAds + '): ';\n }\n countdownDiv.innerHTML =\n 'Advertisement' + podCount +\n remainingMinutes + ':' + remainingSeconds;\n\n // Update UI\n var playProgressRatio = currentTime / duration;\n var playProgressPercent = playProgressRatio * 100;\n progressDiv.style.width = playProgressPercent + '%';\n };\n\n /**\n * Hides the ad controls on mouseout.\n * @private\n */\n player.ima.hideAdControls_ = function() {\n playPauseDiv.style.display = 'none';\n muteDiv.style.display = 'none';\n fullscreenDiv.style.display = 'none';\n controlsDiv.style.height = '14px';\n };\n\n /**\n * Shows ad controls on mouseover.\n * @private\n */\n player.ima.showAdControls_ = function() {\n controlsDiv.style.height = '37px';\n playPauseDiv.style.display = 'block';\n muteDiv.style.display = 'block';\n sliderDiv.style.display = 'block';\n fullscreenDiv.style.display = 'block';\n };\n\n /**\n * Listener for clicks on the play/pause button during ad playback.\n * @private\n */\n player.ima.onAdPlayPauseClick_ = function() {\n if (adPlaying) {\n playPauseDiv.className = 'ima-paused';\n adsManager.pause();\n adPlaying = false;\n } else {\n playPauseDiv.className = 'ima-playing';\n adsManager.resume();\n adPlaying = true;\n }\n };\n\n /**\n * Listener for clicks on the mute button during ad playback.\n * @private\n */\n player.ima.onAdMuteClick_ = function() {\n if (adMuted) {\n muteDiv.className = 'ima-non-muted';\n adsManager.setVolume(1);\n // Bubble down to content player\n player.muted(false);\n adMuted = false;\n sliderLevelDiv.style.width = player.volume() * 100 + \"%\";\n } else {\n muteDiv.className = 'ima-muted';\n adsManager.setVolume(0);\n // Bubble down to content player\n player.muted(true);\n adMuted = true;\n sliderLevelDiv.style.width = \"0%\";\n }\n };\n\n /* Listener for mouse down events during ad playback. Used for volume.\n * @private\n */\n player.ima.onAdVolumeSliderMouseDown_ = function() {\n document.addEventListener('mouseup', player.ima.onMouseUp_, false);\n document.addEventListener('mousemove', player.ima.onMouseMove_, false);\n }\n\n /* Mouse movement listener used for volume slider.\n * @private\n */\n player.ima.onMouseMove_ = function(event) {\n player.ima.setVolumeSlider_(event);\n }\n\n /* Mouse release listener used for volume slider.\n * @private\n */\n player.ima.onMouseUp_ = function(event) {\n player.ima.setVolumeSlider_(event);\n document.removeEventListener('mousemove', player.ima.onMouseMove_);\n document.removeEventListener('mouseup', player.ima.onMouseUp_);\n }\n\n /* Utility function so set vvolume and associated UI\n * @private\n */\n player.ima.setVolumeSlider_ = function(event) {\n var percent =\n (event.clientX - sliderDiv.getBoundingClientRect().left) /\n sliderDiv.offsetWidth;\n percent *= 100;\n //Bounds value 0-100 if mouse is outside slider region.\n percent = Math.min(Math.max(percent, 0), 100);\n sliderLevelDiv.style.width = percent + \"%\";\n player.volume(percent / 100); //0-1\n adsManager.setVolume(percent / 100);\n if (player.volume() == 0) {\n muteDiv.className = 'ima-muted';\n player.muted(true);\n adMuted = true;\n }\n else\n {\n muteDiv.className = 'ima-non-muted';\n player.muted(false);\n adMuted = false;\n }\n }\n\n /**\n * Listener for clicks on the fullscreen button during ad playback.\n * @private\n */\n player.ima.onAdFullscreenClick_ = function() {\n if (player.isFullscreen()) {\n player.exitFullscreen();\n } else {\n player.requestFullscreen();\n }\n };\n\n /**\n * Listens for the video.js player to change its fullscreen status. This\n * keeps the fullscreen-ness of the AdContainer in sync with the player.\n * @private\n */\n player.ima.onFullscreenChange_ = function() {\n if (player.isFullscreen()) {\n fullscreenDiv.className = 'ima-fullscreen';\n adContainerDiv.style.width = window.screen.width + 'px';\n adContainerDiv.style.height = window.screen.height + 'px';\n adsManager.resize(\n window.screen.width,\n window.screen.height,\n google.ima.ViewMode.FULLSCREEN);\n } else {\n fullscreenDiv.className = 'ima-non-fullscreen';\n adContainerDiv.style.width = player.width() + 'px';\n adContainerDiv.style.height = player.height() + 'px';\n adsManager.resize(\n player.width(),\n player.height(),\n google.ima.ViewMode.NORMAL);\n }\n };\n\n /**\n * Listens for the video.js player to change its volume. This keeps the ad\n * volume in sync with the content volume if the volume of the player is\n * changed while content is playing\n * @private\n */\n player.ima.onVolumeChange_ = function() {\n var newVolume = player.muted() ? 0 : player.volume();\n if (adsManager) {\n adsManager.setVolume(newVolume);\n }\n };\n\n /**\n * Seeks content to 00:00:00. This is used as an event handler for the\n * loadedmetadata event, since seeking is not possible until that event has\n * fired.\n * @private\n */\n player.ima.seekContentToZero_ = function() {\n player.off('loadedmetadata', player.ima.seekContentToZero_);\n player.currentTime(0);\n };\n\n /**\n * Seeks content to 00:00:00 and starts playback. This is used as an event\n * handler for the loadedmetadata event, since seeking is not possible until\n * that event has fired.\n * @private\n */\n player.ima.playContentFromZero_ = function() {\n player.off('loadedmetadata', player.ima.playContentFromZero_);\n player.currentTime(0);\n player.play();\n };\n\n /**\n * Destroys the AdsManager, sets it to null, and calls contentComplete to\n * reset correlators. Once this is done it requests ads again to keep the\n * inventory available.\n * @private\n */\n player.ima.resetIMA_ = function() {\n if (adsManager) {\n adsManager.destroy();\n adsManager = null;\n }\n if (adsLoader && !contentComplete) {\n adsLoader.contentComplete();\n }\n contentComplete = false;\n allAdsCompleted = false;\n };\n\n /**\n * Ads an EventListener to the AdsManager. For a list of available events,\n * see\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to listen.\n * @param {function} callback The method to call when the event is fired.\n */\n player.ima.addEventListener = function(event, callback) {\n if (adsManager) {\n adsManager.addEventListener(event, callback);\n }\n };\n\n /**\n * Returns the instance of the AdsManager.\n * @return {google.ima.AdsManager} The AdsManager being used by the plugin.\n */\n player.ima.getAdsManager = function() {\n return adsManager;\n };\n\n /**\n * Sets the content of the video player. You should use this method instead\n * of setting the content src directly to ensure the proper ad tag is\n * requested when the video content is loaded.\n * @param {?string} contentSrc The URI for the content to be played. Leave\n * blank to use the existing content.\n * @param {?string} adTag The ad tag to be requested when the content loads.\n * Leave blank to use the existing ad tag.\n * @param {?boolean} playOnLoad True to play the content once it has loaded,\n * false to only load the content but not start playback.\n */\n player.ima.setContent =\n function( contentSrc, adTag, playOnLoad) {\n player.ima.resetIMA_();\n settings.adTagUrl = adTag ? adTag : settings.adTagUrl;\n //only try to pause the player when initialised with a source already\n if (!!player.currentSrc()) {\n player.pause();\n }\n if (contentSrc) {\n player.src(contentSrc);\n }\n if (playOnLoad) {\n player.on('loadedmetadata', player.ima.playContentFromZero_);\n } else {\n player.on('loadedmetadata', player.ima.seekContentToZero_);\n }\n };\n\n /**\n * Adds a listener for the 'ended' event of the video player. This should be\n * used instead of setting an 'ended' listener directly to ensure that the\n * ima can do proper cleanup of the SDK before other event listeners\n * are called.\n * @param {function} listener The listener to be called when content completes.\n */\n player.ima.addContentEndedListener = function(listener) {\n contentEndedListeners.push(listener);\n };\n\n /**\n * Adds a listener that will be called when content and all ads have\n * finished playing.\n * @param {function} listener The listener to be called when content and ads complete.\n */\n player.ima.addContentAndAdsEndedListener = function(listener) {\n contentAndAdsEndedListeners.push(listener);\n }\n\n /**\n * Sets the listener to be called to trigger manual ad break playback.\n * @param {function} listener The listener to be called to trigger manual ad break playback.\n */\n player.ima.setAdBreakReadyListener = function(listener) {\n adBreakReadyListener = listener;\n }\n\n /**\n * Pauses the ad.\n */\n player.ima.pauseAd = function() {\n if (adsActive && adPlaying) {\n playPauseDiv.className = 'ima-paused';\n adsManager.pause();\n adPlaying = false;\n }\n };\n\n /**\n * Resumes the ad.\n */\n player.ima.resumeAd = function() {\n if (adsActive && !adPlaying) {\n playPauseDiv.className = 'ima-playing';\n adsManager.resume();\n adPlaying = true;\n }\n };\n\n /**\n * Set up intervals to check for seeking and update current video time.\n * @private\n */\n player.ima.setUpPlayerIntervals_ = function() {\n updateTimeIntervalHandle =\n setInterval(player.ima.updateCurrentTime, seekCheckInterval);\n seekCheckIntervalHandle =\n setInterval(player.ima.checkForSeeking_, seekCheckInterval);\n };\n\n /**\n * Updates the current time of the video\n */\n player.ima.updateCurrentTime = function() {\n if (!contentPlayheadTracker.seeking) {\n contentPlayheadTracker.currentTime = player.currentTime();\n }\n };\n\n /**\n * Detects when the user is seeking through a video.\n * This is used to prevent mid-rolls from playing while a user is seeking.\n *\n * There *is* a seeking property of the HTML5 video element, but it's not\n * properly implemented on all platforms (e.g. mobile safari), so we have to\n * check ourselves to be sure.\n *\n * @private\n */\n player.ima.checkForSeeking_ = function() {\n var tempCurrentTime = player.currentTime();\n var diff = (tempCurrentTime - contentPlayheadTracker.previousTime) * 1000;\n if (Math.abs(diff) > seekCheckInterval + seekThreshold) {\n contentPlayheadTracker.seeking = true;\n } else {\n contentPlayheadTracker.seeking = false;\n }\n contentPlayheadTracker.previousTime = player.currentTime();\n };\n\n /**\n * Changes the flag to show or hide the ad countdown timer.\n *\n * @param {boolean} showCountdownIn Show or hide the countdown timer.\n */\n player.ima.setShowCountdown = function(showCountdownIn) {\n showCountdown = showCountdownIn;\n countdownDiv.style.display = showCountdown ? 'block' : 'none';\n };\n\n /**\n * Current plugin version.\n */\n var VERSION = '0.2.0';\n\n /**\n * Stores user-provided settings.\n */\n var settings;\n\n /**\n * Video element playing content.\n */\n var contentPlayer;\n\n /**\n * Boolean flag to show or hide the ad countdown timer.\n */\n var showCountdown;\n\n /**\n * Boolena flag to enable manual ad break playback.\n */\n var autoPlayAdBreaks;\n\n /**\n * Video.js control bar.\n */\n var vjsControls;\n\n /**\n * Div used as an ad container.\n */\n var adContainerDiv;\n\n /**\n * Div used to display ad controls.\n */\n var controlsDiv;\n\n /**\n * Div used to display ad countdown timer.\n */\n var countdownDiv;\n\n /**\n * Div used to display add seek bar.\n */\n var seekBarDiv;\n\n /**\n * Div used to display ad progress (in seek bar).\n */\n var progressDiv;\n\n /**\n * Div used to display ad play/pause button.\n */\n var playPauseDiv;\n\n /**\n * Div used to display ad mute button.\n */\n var muteDiv;\n\n /**\n * Div used by the volume slider.\n */\n var sliderDiv;\n\n /**\n * Volume slider level visuals\n */\n var sliderLevelDiv;\n\n /**\n * Div used to display ad fullscreen button.\n */\n var fullscreenDiv;\n\n /**\n * IMA SDK AdDisplayContainer.\n */\n var adDisplayContainer;\n\n /**\n * True if the AdDisplayContainer has been initialized. False otherwise.\n */\n var adDisplayContainerInitialized = false;\n\n /**\n * IMA SDK AdsLoader\n */\n var adsLoader;\n\n /**\n * IMA SDK AdsManager\n */\n var adsManager;\n\n /**\n * IMA SDK AdsRenderingSettings.\n */\n var adsRenderingSettings = null;\n\n /**\n * Ad tag URL. Should return VAST, VMAP, or ad rules.\n */\n var adTagUrl;\n\n /**\n * Current IMA SDK Ad.\n */\n var currentAd;\n\n /**\n * Timer used to track content progress.\n */\n var contentTrackingTimer;\n\n /**\n * Timer used to track ad progress.\n */\n var adTrackingTimer;\n\n /**\n * True if ads are currently displayed, false otherwise.\n * True regardless of ad pause state if an ad is currently being displayed.\n */\n var adsActive = false;\n\n /**\n * True if ad is currently playing, false if ad is paused or ads are not\n * currently displayed.\n */\n var adPlaying = false;\n\n /**\n * True if the ad is muted, false otherwise.\n */\n var adMuted = false;\n\n /**\n * True if our content video has completed, false otherwise.\n */\n var contentComplete = false;\n\n /**\n * True if ALL_ADS_COMPLETED has fired, false until then.\n */\n var allAdsCompleted = false;\n\n /**\n * Handle to interval that repeatedly updates current time.\n */\n var updateTimeIntervalHandle;\n\n /**\n * Handle to interval that repeatedly checks for seeking.\n */\n var seekCheckIntervalHandle;\n\n /**\n * Interval (ms) on which to check if the user is seeking through the\n * content.\n */\n var seekCheckInterval = 1000;\n\n /**\n * Threshold by which to judge user seeking. We check every 1000 ms to see\n * if the user is seeking. In order for us to decide that they are *not*\n * seeking, the content video playhead must only change by 900-1100 ms\n * between checks. Any greater change and we assume the user is seeking\n * through the video.\n */\n var seekThreshold = 100;\n\n /**\n * Stores data for the content playhead tracker.\n */\n var contentPlayheadTracker = {\n currentTime: 0,\n previousTime: 0,\n seeking: false,\n duration: 0\n };\n\n /**\n * Stores data for the ad playhead tracker.\n */\n var adPlayheadTracker = {\n currentTime: 0,\n duration: 0,\n isPod: false,\n adPosition: 0,\n totalAds: 0\n };\n\n /**\n * Content ended listeners passed by the publisher to the plugin. Publishers\n * should allow the plugin to handle content ended to ensure proper support\n * of custom ad playback.\n */\n var contentEndedListeners = [];\n\n /**\n * Content and ads ended listeners passed by the publisher to the plugin.\n * These will be called when the plugin detects that content *and all\n * ads* have completed. This differs from the contentEndedListeners in that\n * contentEndedListeners will fire between content ending and a post-roll\n * playing, whereas the contentAndAdsEndedListeners will fire after the\n * post-roll completes.\n */\n var contentAndAdsEndedListeners = [];\n\n /**\n * Listener to be called to trigger manual ad break playback.\n */\n var adBreakReadyListener = undefined;\n\n /**\n * Local content ended listener for contentComplete.\n */\n var localContentEndedListener = function() {\n if (adsLoader && !contentComplete) {\n adsLoader.contentComplete();\n contentComplete = true;\n }\n for (var index in contentEndedListeners) {\n contentEndedListeners[index]();\n }\n if (allAdsCompleted) {\n for (var index in contentAndAdsEndedListeners) {\n contentAndAdsEndedListeners[index]();\n }\n }\n clearInterval(updateTimeIntervalHandle);\n clearInterval(seekCheckIntervalHandle);\n player.one('play', player.ima.setUpPlayerIntervals_);\n };\n\n settings = extend({}, ima_defaults, options || {});\n\n // Currently this isn't used but I can see it being needed in the future, so\n // to avoid implementation problems with later updates I'm requiring it.\n if (!settings['id']) {\n window.console.log('Error: must provide id of video.js div');\n return;\n }\n contentPlayer = document.getElementById(settings['id'] + '_html5_api');\n // Default showing countdown timer to true.\n showCountdown = true;\n if (settings['showCountdown'] == false) {\n showCountdown = false;\n }\n\n autoPlayAdBreaks = true;\n if (settings['autoPlayAdBreaks'] == false) {\n autoPlayAdBreaks = false;\n }\n\n player.one('play', player.ima.setUpPlayerIntervals_);\n\n player.on('ended', localContentEndedListener);\n\n var contrib_ads_defaults = {\n debug: settings.debug,\n timeout: settings.timeout,\n prerollTimeout: settings.prerollTimeout\n };\n\n var ads_plugin_settings =\n extend({}, contrib_ads_defaults, options['contribAdsSettings'] || {});\n\n player.ads(ads_plugin_settings);\n\n adsRenderingSettings = new google.ima.AdsRenderingSettings();\n adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n if (settings['adsRenderingSettings']) {\n for (var setting in settings['adsRenderingSettings']) {\n adsRenderingSettings[setting] =\n settings['adsRenderingSettings'][setting];\n }\n }\n\n if (settings['locale']) {\n google.ima.settings.setLocale(settings['locale']);\n }\n\n player.ima.createAdContainer_();\n\n adsLoader = new google.ima.AdsLoader(adDisplayContainer);\n\n adsLoader.getSettings().setVpaidMode(\n google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n if (settings.vpaidAllowed == false) {\n adsLoader.getSettings().setVpaidMode(\n google.ima.ImaSdkSettings.VpaidMode.DISABLED);\n }\n if (settings.vpaidMode) {\n adsLoader.getSettings().setVpaidMode(settings.vpaidMode);\n }\n\n if (settings.locale) {\n adsLoader.getSettings().setLocale(settings.locale);\n }\n\n adsLoader.getSettings().setPlayerType('videojs-ima');\n adsLoader.getSettings().setPlayerVersion(VERSION);\n adsLoader.getSettings().setAutoPlayAdBreaks(autoPlayAdBreaks);\n\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n player.ima.onAdsManagerLoaded_,\n false);\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n player.ima.onAdsLoaderError_,\n false);\n\n if (!readyCallback) {\n readyCallback = player.ima.start;\n }\n player.on('readyforpreroll', readyCallback);\n player.on('fullscreenchange', player.ima.onFullscreenChange_);\n player.on('volumechange', player.ima.onVolumeChange_);\n };\n\n vjs.plugin('ima', imaPlugin);\n}(window.videojs));"],"names":["vjs","extend","obj","arg","index","key","arguments","length","hasOwnProperty","ima_defaults","debug","timeout","prerollTimeout","plugin","options","readyCallback","player","this","ima","createAdContainer_","vjsControls","getChild","adContainerDiv","el","parentNode","insertBefore","document","createElement","id","style","width","height","addEventListener","showAdControls_","hideAdControls_","createControls_","adDisplayContainer","google","AdDisplayContainer","contentPlayer","controlsDiv","countdownDiv","innerHTML","display","showCountdown","seekBarDiv","progressDiv","playPauseDiv","className","onAdPlayPauseClick_","muteDiv","onAdMuteClick_","sliderDiv","onAdVolumeSliderMouseDown_","sliderLevelDiv","fullscreenDiv","onAdFullscreenClick_","childNodes","initializeAdDisplayContainer","adDisplayContainerInitialized","initialize","requestAds","adsRequest","AdsRequest","adTagUrl","settings","linearAdSlotWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearWidth","nonLinearAdSlotHeight","nonLinearHeight","adsLoader","onAdsManagerLoaded_","adsManagerLoadedEvent","adsManager","getAdsManager","contentPlayheadTracker","adsRenderingSettings","AdErrorEvent","Type","AD_ERROR","onAdError_","AdEvent","AD_BREAK_READY","onAdBreakReady_","CONTENT_PAUSE_REQUESTED","onContentPauseRequested_","CONTENT_RESUME_REQUESTED","onContentResumeRequested_","ALL_ADS_COMPLETED","onAllAdsCompleted_","LOADED","onAdLoaded_","STARTED","onAdStarted_","CLICK","COMPLETE","onAdComplete_","SKIPPED","autoPlayAdBreaks","init","ViewMode","NORMAL","setVolume","muted","volume","adError","trigger","start","onAdsLoaderError_","event","window","console","log","getError","destroy","adErrorEvent","adEvent","adBreakReadyListener","playAdBreak","adsActive","adPlaying","off","localContentEndedListener","getAd","getAdPodInfo","getPodIndex","ads","startLinearAdMode","hide","pause","on","currentAd","isLinear","show","contentComplete","endLinearAdMode","allAdsCompleted","contentAndAdsEndedListeners","play","adTrackingTimer","setInterval","onAdPlayheadTrackerInterval_","clearInterval","remainingTime","getRemainingTime","duration","getDuration","currentTime","adPosition","totalAds","isPod","getAdPosition","getTotalAds","remainingMinutes","Math","floor","remainingSeconds","toString","podCount","playProgressPercent","resume","adMuted","onMouseUp_","onMouseMove_","setVolumeSlider_","removeEventListener","percent","clientX","getBoundingClientRect","left","offsetWidth","min","max","isFullscreen","exitFullscreen","requestFullscreen","onFullscreenChange_","screen","resize","FULLSCREEN","onVolumeChange_","newVolume","seekContentToZero_","playContentFromZero_","resetIMA_","callback","setContent","contentSrc","adTag","playOnLoad","currentSrc","src","addContentEndedListener","listener","contentEndedListeners","push","addContentAndAdsEndedListener","setAdBreakReadyListener","pauseAd","resumeAd","setUpPlayerIntervals_","updateTimeIntervalHandle","updateCurrentTime","seekCheckInterval","seekCheckIntervalHandle","checkForSeeking_","seeking","diff","previousTime","abs","seekThreshold","setShowCountdown","showCountdownIn","undefined","one","getElementById","contrib_ads_defaults","ads_plugin_settings","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","setting","setLocale","AdsLoader","getSettings","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","vpaidAllowed","DISABLED","vpaidMode","locale","setPlayerType","setPlayerVersion","setAutoPlayAdBreaks","AdsManagerLoadedEvent","ADS_MANAGER_LOADED","videojs"],"version":3,"file":"index.905aea52.js.map"}