(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{237:function(e,n){e.exports=function(e){function n(e){"undefined"!=typeof console&&(console.error||console.log)("[Script Loader]",e)}try{"undefined"!=typeof execScript&&"undefined"!=typeof attachEvent&&"undefined"==typeof addEventListener?execScript(e):"undefined"!=typeof eval?eval.call(null,e):n("EvalError: No eval function available")}catch(e){n(e)}}},242:function(e,n){e.exports="/*\n * videojs-contrib-ads\n * @version 6.4.1\n * @copyright 2018 Brightcove, Inc.\n * @license Apache-2.0\n */\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :\n\ttypeof define === 'function' && define.amd ? define(['video.js'], factory) :\n\t(global.videojsContribAds = factory(global.videojs));\n}(this, (function (videojs) { 'use strict';\n\nvideojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs;\n\nvar version = \"6.4.1\";\n\n/*\n * Implements the public API available in `player.ads` as well as application state.\n */\n\nfunction getAds(player) {\n return {\n\n disableNextSnapshotRestore: false,\n\n // This is true if we have finished actual content playback but haven't\n // dealt with postrolls and officially ended yet\n _contentEnding: false,\n\n // This is set to true if the content has officially ended at least once.\n // After that, the user can seek backwards and replay content, but _contentHasEnded\n // remains true.\n _contentHasEnded: false,\n\n // Tracks if loadstart has happened yet for the initial source. It is not reset\n // on source changes because loadstart is the event that signals to the ad plugin\n // that the source has changed. Therefore, no special signaling is needed to know\n // that there has been one for subsequent sources.\n _hasThereBeenALoadStartDuringPlayerLife: false,\n\n // Tracks if loadeddata has happened yet for the current source.\n _hasThereBeenALoadedData: false,\n\n // Tracks if loadedmetadata has happened yet for the current source.\n _hasThereBeenALoadedMetaData: false,\n\n // Are we after startLinearAdMode and before endLinearAdMode?\n _inLinearAdMode: false,\n\n // Should we block calls to play on the content player?\n _shouldBlockPlay: false,\n\n // Was play blocked by the plugin's playMiddleware feature?\n _playBlocked: false,\n\n // Tracks whether play has been requested for this source,\n // either by the play method or user interaction\n _playRequested: false,\n\n // This is an estimation of the current ad type being played\n // This is experimental currently. Do not rely on its presence or behavior!\n adType: null,\n\n VERSION: version,\n\n reset: function reset() {\n player.ads.disableNextSnapshotRestore = false;\n player.ads._contentEnding = false;\n player.ads._contentHasEnded = false;\n player.ads.snapshot = null;\n player.ads.adType = null;\n player.ads._hasThereBeenALoadedData = false;\n player.ads._hasThereBeenALoadedMetaData = false;\n player.ads._cancelledPlay = false;\n player.ads._shouldBlockPlay = false;\n player.ads._playBlocked = false;\n player.ads.nopreroll_ = false;\n player.ads.nopostroll_ = false;\n player.ads._playRequested = false;\n },\n\n\n // Call this when an ad response has been received and there are\n // linear ads ready to be played.\n startLinearAdMode: function startLinearAdMode() {\n player.ads._state.startLinearAdMode();\n },\n\n\n // Call this when a linear ad pod has finished playing.\n endLinearAdMode: function endLinearAdMode() {\n player.ads._state.endLinearAdMode();\n },\n\n\n // Call this when an ad response has been received but there are no\n // linear ads to be played (i.e. no ads available, or overlays).\n // This has no effect if we are already in an ad break. Always\n // use endLinearAdMode() to exit from linear ad-playback state.\n skipLinearAdMode: function skipLinearAdMode() {\n player.ads._state.skipLinearAdMode();\n },\n stitchedAds: function stitchedAds(arg) {\n if (arg !== undefined) {\n this._stitchedAds = !!arg;\n }\n return this._stitchedAds;\n },\n\n\n // Returns whether the video element has been modified since the\n // snapshot was taken.\n // We test both src and currentSrc because changing the src attribute to a URL that\n // AdBlocker is intercepting doesn't update currentSrc.\n videoElementRecycled: function videoElementRecycled() {\n if (player.ads.shouldPlayContentBehindAd(player)) {\n return false;\n }\n\n if (!this.snapshot) {\n throw new Error('You cannot use videoElementRecycled while there is no snapshot.');\n }\n\n var srcChanged = player.tech_.src() !== this.snapshot.src;\n var currentSrcChanged = player.currentSrc() !== this.snapshot.currentSrc;\n\n return srcChanged || currentSrcChanged;\n },\n\n\n // Returns a boolean indicating if given player is in live mode.\n // One reason for this: https://github.com/videojs/video.js/issues/3262\n // Also, some live content can have a duration.\n isLive: function isLive(somePlayer) {\n if (typeof somePlayer.ads.settings.contentIsLive === 'boolean') {\n return somePlayer.ads.settings.contentIsLive;\n } else if (somePlayer.duration() === Infinity) {\n return true;\n } else if (videojs.browser.IOS_VERSION === '8' && somePlayer.duration() === 0) {\n return true;\n }\n return false;\n },\n\n\n // Return true if content playback should mute and continue during ad breaks.\n // This is only done during live streams on platforms where it's supported.\n // This improves speed and accuracy when returning from an ad break.\n shouldPlayContentBehindAd: function shouldPlayContentBehindAd(somePlayer) {\n return !videojs.browser.IS_IOS && !videojs.browser.IS_ANDROID && somePlayer.duration() === Infinity;\n },\n\n\n // Returns true if player is in ad mode.\n //\n // Ad mode definition:\n // If content playback is blocked by the ad plugin.\n //\n // Examples of ad mode:\n //\n // * Waiting to find out if an ad is going to play while content would normally be\n // playing.\n // * Waiting for an ad to start playing while content would normally be playing.\n // * An ad is playing (even if content is also playing)\n // * An ad has completed and content is about to resume, but content has not resumed\n // yet.\n //\n // Examples of not ad mode:\n //\n // * Content playback has not been requested\n // * Content playback is paused\n // * An asynchronous ad request is ongoing while content is playing\n // * A non-linear ad is active\n isInAdMode: function isInAdMode() {\n return this._state.isAdState();\n },\n\n\n // Returns true if in ad mode but an ad break hasn't started yet.\n isWaitingForAdBreak: function isWaitingForAdBreak() {\n return this._state.isWaitingForAdBreak();\n },\n\n\n // Returns true if content is resuming after an ad. This is part of ad mode.\n isContentResuming: function isContentResuming() {\n return this._state.isContentResuming();\n },\n\n\n // Deprecated because the name was misleading. Use inAdBreak instead.\n isAdPlaying: function isAdPlaying() {\n return this._state.inAdBreak();\n },\n\n\n // Returns true if an ad break is ongoing. This is part of ad mode.\n // An ad break is the time between startLinearAdMode and endLinearAdMode.\n inAdBreak: function inAdBreak() {\n return this._state.inAdBreak();\n },\n\n\n /*\n * Remove the poster attribute from the video element tech, if present. When\n * reusing a video element for multiple videos, the poster image will briefly\n * reappear while the new source loads. Removing the attribute ahead of time\n * prevents the poster from showing up between videos.\n *\n * @param {Object} player The videojs player object\n */\n removeNativePoster: function removeNativePoster() {\n var tech = player.$('.vjs-tech');\n\n if (tech) {\n tech.removeAttribute('poster');\n }\n },\n debug: function debug() {\n if (this.settings.debug) {\n for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n if (args.length === 1 && typeof args[0] === 'string') {\n videojs.log('ADS: ' + args[0]);\n } else {\n videojs.log.apply(videojs, ['ADS:'].concat(args));\n }\n }\n }\n };\n}\n\n/*\nThe goal of this feature is to make player events work as an integrator would\nexpect despite the presense of ads. For example, an integrator would expect\nan `ended` event to happen once the content is ended. If an `ended` event is sent\nas a result of a preroll ending, that is a bug. The `redispatch` method should recognize\nsuch `ended` events and prefix them so they are sent as `adended`, and so on with\nall other player events.\n*/\n\n// Cancel an event.\n// Video.js wraps native events. This technique stops propagation for the Video.js event\n// (AKA player event or wrapper event) while native events continue propagating.\nvar cancelEvent = function cancelEvent(player, event) {\n event.isImmediatePropagationStopped = function () {\n return true;\n };\n event.cancelBubble = true;\n event.isPropagationStopped = function () {\n return true;\n };\n};\n\n// Redispatch an event with a prefix.\n// Cancels the event, then sends a new event with the type of the original\n// event with the given prefix added.\n// The inclusion of the \"state\" property should be removed in a future\n// major version update with instructions to migrate any code that relies on it.\n// It is an implementation detail and relying on it creates fragility.\nvar prefixEvent = function prefixEvent(player, prefix, event) {\n cancelEvent(player, event);\n player.trigger({\n type: prefix + event.type,\n originalEvent: event\n });\n};\n\n// Playing event\n// Requirements:\n// * Normal playing event when there is no preroll\n// * No playing event before preroll\n// * At least one playing event after preroll\nvar handlePlaying = function handlePlaying(player, event) {\n if (player.ads.isInAdMode()) {\n\n if (player.ads.isContentResuming()) {\n\n // Prefix playing event when switching back to content after postroll.\n if (player.ads._contentEnding) {\n prefixEvent(player, 'content', event);\n }\n\n // Prefix all other playing events during ads.\n } else {\n prefixEvent(player, 'ad', event);\n }\n }\n};\n\n// Ended event\n// Requirements:\n// * A single ended event when there is no postroll\n// * No ended event before postroll\n// * A single ended event after postroll\nvar handleEnded = function handleEnded(player, event) {\n if (player.ads.isInAdMode()) {\n\n // Cancel ended events during content resuming. Normally we would\n // prefix them, but `contentended` has a special meaning. In the\n // future we'd like to rename the existing `contentended` to\n // `readyforpostroll`, then we could remove the special `resumeended`\n // and do a conventional content prefix here.\n if (player.ads.isContentResuming()) {\n cancelEvent(player, event);\n\n // Important: do not use this event outside of videojs-contrib-ads.\n // It will be removed and your code will break.\n // Ideally this would simply be `contentended`, but until\n // `contentended` no longer has a special meaning it cannot be\n // changed.\n player.trigger('resumeended');\n\n // Ad prefix in ad mode\n } else {\n prefixEvent(player, 'ad', event);\n }\n\n // Prefix ended due to content ending before postroll check\n } else if (!player.ads._contentHasEnded) {\n\n // This will change to cancelEvent after the contentended deprecation\n // period (contrib-ads 7)\n prefixEvent(player, 'content', event);\n\n // Content ended for the first time, time to check for postrolls\n player.trigger('readyforpostroll');\n }\n};\n\n// handleLoadEvent is used for loadstart, loadeddata, and loadedmetadata\n// Requirements:\n// * Initial event is not prefixed\n// * Event due to ad loading is prefixed\n// * Event due to content source change is not prefixed\n// * Event due to content resuming is prefixed\nvar handleLoadEvent = function handleLoadEvent(player, event) {\n\n // Initial event\n if (event.type === 'loadstart' && !player.ads._hasThereBeenALoadStartDuringPlayerLife || event.type === 'loadeddata' && !player.ads._hasThereBeenALoadedData || event.type === 'loadedmetadata' && !player.ads._hasThereBeenALoadedMetaData) {\n return;\n\n // Ad playing\n } else if (player.ads.inAdBreak()) {\n prefixEvent(player, 'ad', event);\n\n // Source change\n } else if (player.currentSrc() !== player.ads.contentSrc) {\n return;\n\n // Content resuming\n } else {\n prefixEvent(player, 'content', event);\n }\n};\n\n// Play event\n// Requirements:\n// * Play events have the \"ad\" prefix when an ad is playing\n// * Play events have the \"content\" prefix when content is resuming\n// Play requests are unique because they represent user intention to play. They happen\n// because the user clicked play, or someone called player.play(), etc. It could happen\n// multiple times during ad loading, regardless of where we are in the process. With our\n// current architecture, this could cause the content to start playing.\n// Therefore, contrib-ads must always either:\n// - cancelContentPlay if there is any possible chance the play caused the\n// content to start playing, even if we are technically in ad mode. In order for\n// that to happen, play events need to be unprefixed until the last possible moment.\n// - use playMiddleware to stop the play from reaching the Tech so there is no risk\n// of the content starting to play.\n// Currently, playMiddleware is only supported on desktop browsers with\n// video.js after version 6.7.1.\nvar handlePlay = function handlePlay(player, event) {\n if (player.ads.inAdBreak()) {\n prefixEvent(player, 'ad', event);\n\n // Content resuming\n } else if (player.ads.isContentResuming()) {\n prefixEvent(player, 'content', event);\n }\n};\n\n// Handle a player event, either by redispatching it with a prefix, or by\n// letting it go on its way without any meddling.\nfunction redispatch(event) {\n\n // Events with special treatment\n if (event.type === 'playing') {\n handlePlaying(this, event);\n } else if (event.type === 'ended') {\n handleEnded(this, event);\n } else if (event.type === 'loadstart' || event.type === 'loadeddata' || event.type === 'loadedmetadata') {\n handleLoadEvent(this, event);\n } else if (event.type === 'play') {\n handlePlay(this, event);\n\n // Standard handling for all other events\n } else if (this.ads.isInAdMode()) {\n if (this.ads.isContentResuming()) {\n\n // Event came from snapshot restore after an ad, use \"content\" prefix\n prefixEvent(this, 'content', event);\n } else {\n\n // Event came from ad playback, use \"ad\" prefix\n prefixEvent(this, 'ad', event);\n }\n }\n}\n\n/*\nThis feature sends a `contentupdate` event when the player source changes.\n*/\n\n// Start sending contentupdate events\nfunction initializeContentupdate(player) {\n\n // Keep track of the current content source\n // If you want to change the src of the video without triggering\n // the ad workflow to restart, you can update this variable before\n // modifying the player's source\n player.ads.contentSrc = player.currentSrc();\n\n player.ads._seenInitialLoadstart = false;\n\n // Check if a new src has been set, if so, trigger contentupdate\n var checkSrc = function checkSrc() {\n if (!player.ads.inAdBreak()) {\n var src = player.currentSrc();\n\n if (src !== player.ads.contentSrc) {\n\n if (player.ads._seenInitialLoadstart) {\n player.trigger({\n type: 'contentchanged'\n });\n }\n\n player.trigger({\n type: 'contentupdate',\n oldValue: player.ads.contentSrc,\n newValue: src\n });\n player.ads.contentSrc = src;\n }\n\n player.ads._seenInitialLoadstart = true;\n }\n };\n\n // loadstart reliably indicates a new src has been set\n player.on('loadstart', checkSrc);\n}\n\nvar commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n\nvar win;\n\nif (typeof window !== \"undefined\") {\n win = window;\n} else if (typeof commonjsGlobal !== \"undefined\") {\n win = commonjsGlobal;\n} else if (typeof self !== \"undefined\"){\n win = self;\n} else {\n win = {};\n}\n\nvar window_1 = win;\n\nvar empty = {};\n\n\nvar empty$1 = (Object.freeze || Object)({\n\t'default': empty\n});\n\nvar minDoc = ( empty$1 && empty ) || empty$1;\n\nvar topLevel = typeof commonjsGlobal !== 'undefined' ? commonjsGlobal :\n typeof window !== 'undefined' ? window : {};\n\n\nvar doccy;\n\nif (typeof document !== 'undefined') {\n doccy = document;\n} else {\n doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];\n\n if (!doccy) {\n doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;\n }\n}\n\nvar document_1 = doccy;\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) {\n return typeof obj;\n} : function (obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n};\n\n\n\n\n\nvar asyncGenerator = function () {\n function AwaitValue(value) {\n this.value = value;\n }\n\n function AsyncGenerator(gen) {\n var front, back;\n\n function send(key, arg) {\n return new Promise(function (resolve, reject) {\n var request = {\n key: key,\n arg: arg,\n resolve: resolve,\n reject: reject,\n next: null\n };\n\n if (back) {\n back = back.next = request;\n } else {\n front = back = request;\n resume(key, arg);\n }\n });\n }\n\n function resume(key, arg) {\n try {\n var result = gen[key](arg);\n var value = result.value;\n\n if (value instanceof AwaitValue) {\n Promise.resolve(value.value).then(function (arg) {\n resume(\"next\", arg);\n }, function (arg) {\n resume(\"throw\", arg);\n });\n } else {\n settle(result.done ? \"return\" : \"normal\", result.value);\n }\n } catch (err) {\n settle(\"throw\", err);\n }\n }\n\n function settle(type, value) {\n switch (type) {\n case \"return\":\n front.resolve({\n value: value,\n done: true\n });\n break;\n\n case \"throw\":\n front.reject(value);\n break;\n\n default:\n front.resolve({\n value: value,\n done: false\n });\n break;\n }\n\n front = front.next;\n\n if (front) {\n resume(front.key, front.arg);\n } else {\n back = null;\n }\n }\n\n this._invoke = send;\n\n if (typeof gen.return !== \"function\") {\n this.return = undefined;\n }\n }\n\n if (typeof Symbol === \"function\" && Symbol.asyncIterator) {\n AsyncGenerator.prototype[Symbol.asyncIterator] = function () {\n return this;\n };\n }\n\n AsyncGenerator.prototype.next = function (arg) {\n return this._invoke(\"next\", arg);\n };\n\n AsyncGenerator.prototype.throw = function (arg) {\n return this._invoke(\"throw\", arg);\n };\n\n AsyncGenerator.prototype.return = function (arg) {\n return this._invoke(\"return\", arg);\n };\n\n return {\n wrap: function (fn) {\n return function () {\n return new AsyncGenerator(fn.apply(this, arguments));\n };\n },\n await: function (value) {\n return new AwaitValue(value);\n }\n };\n}();\n\n\n\n\n\nvar classCallCheck = function (instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n};\n\n\n\n\n\n\n\n\n\n\n\nvar inherits = function (subClass, superClass) {\n if (typeof superClass !== \"function\" && superClass !== null) {\n throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass);\n }\n\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n value: subClass,\n enumerable: false,\n writable: true,\n configurable: true\n }\n });\n if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;\n};\n\n\n\n\n\n\n\n\n\n\n\nvar possibleConstructorReturn = function (self, call) {\n if (!self) {\n throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n }\n\n return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self;\n};\n\n/*\nThis feature provides an optional method for ad plugins to insert run-time values\ninto an ad server URL or configuration.\n*/\n\n// Return URI encoded version of value if uriEncode is true\nvar uriEncodeIfNeeded = function uriEncodeIfNeeded(value, uriEncode) {\n if (uriEncode) {\n return encodeURIComponent(value);\n }\n return value;\n};\n\n// Add custom field macros to macros object\n// based on given name for custom fields property of mediainfo object.\nvar customFields = function customFields(mediainfo, macros, customFieldsName) {\n if (mediainfo && mediainfo[customFieldsName]) {\n var fields = mediainfo[customFieldsName];\n var fieldNames = Object.keys(fields);\n\n for (var i = 0; i < fieldNames.length; i++) {\n var tag = '{mediainfo.' + customFieldsName + '.' + fieldNames[i] + '}';\n\n macros[tag] = fields[fieldNames[i]];\n }\n }\n};\n\n// Public method that ad plugins use for ad macros.\n// \"string\" is any string with macros to be replaced\n// \"uriEncode\" if true will uri encode macro values when replaced\n// \"customMacros\" is a object with custom macros and values to map them to\n// - For example: {'{five}': 5}\n// Return value is is \"string\" with macros replaced\n// - For example: adMacroReplacement('{player.id}') returns a string of the player id\nfunction adMacroReplacement(string, uriEncode, customMacros) {\n var _this = this;\n\n var defaults = {};\n\n // Get macros with defaults e.g. {x=y}, store values and replace with standard macros\n string = string.replace(/{([^}=]+)=([^}]+)}/g, function (match, name, defaultVal) {\n defaults['{' + name + '}'] = defaultVal;\n\n return '{' + name + '}';\n });\n\n if (uriEncode === undefined) {\n uriEncode = false;\n }\n\n var macros = {};\n\n if (customMacros !== undefined) {\n macros = customMacros;\n }\n\n // Static macros\n macros['{player.id}'] = this.options_['data-player'];\n macros['{mediainfo.id}'] = this.mediainfo ? this.mediainfo.id : '';\n macros['{mediainfo.name}'] = this.mediainfo ? this.mediainfo.name : '';\n macros['{mediainfo.duration}'] = this.mediainfo ? this.mediainfo.duration : '';\n macros['{player.duration}'] = this.duration();\n macros['{timestamp}'] = new Date().getTime();\n macros['{document.referrer}'] = document_1.referrer;\n macros['{window.location.href}'] = window_1.location.href;\n macros['{random}'] = Math.floor(Math.random() * 1000000000000);\n\n ['description', 'tags', 'reference_id', 'ad_keys'].forEach(function (prop) {\n if (_this.mediainfo && _this.mediainfo[prop]) {\n macros['{mediainfo.' + prop + '}'] = _this.mediainfo[prop];\n } else if (defaults['{mediainfo.' + prop + '}']) {\n macros['{mediainfo.' + prop + '}'] = defaults['{mediainfo.' + prop + '}'];\n } else {\n macros['{mediainfo.' + prop + '}'] = '';\n }\n });\n\n // Custom fields in mediainfo\n customFields(this.mediainfo, macros, 'custom_fields');\n customFields(this.mediainfo, macros, 'customFields');\n\n // Go through all the replacement macros and apply them to the string.\n // This will replace all occurrences of the replacement macros.\n for (var i in macros) {\n string = string.split(i).join(uriEncodeIfNeeded(macros[i], uriEncode));\n }\n\n // Page variables\n string = string.replace(/{pageVariable\\.([^}]+)}/g, function (match, name) {\n var value = void 0;\n var context = window_1;\n var names = name.split('.');\n\n // Iterate down multiple levels of selector without using eval\n // This makes things like pageVariable.foo.bar work\n for (var _i = 0; _i < names.length; _i++) {\n if (_i === names.length - 1) {\n value = context[names[_i]];\n } else {\n context = context[names[_i]];\n }\n }\n\n var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);\n\n // Only allow certain types of values. Anything else is probably a mistake.\n if (value === null) {\n return 'null';\n } else if (value === undefined) {\n if (defaults['{pageVariable.' + name + '}']) {\n return defaults['{pageVariable.' + name + '}'];\n }\n videojs.log.warn('Page variable \"' + name + '\" not found');\n return '';\n } else if (type !== 'string' && type !== 'number' && type !== 'boolean') {\n videojs.log.warn('Page variable \"' + name + '\" is not a supported type');\n return '';\n }\n\n return uriEncodeIfNeeded(String(value), uriEncode);\n });\n\n // Replace defaults\n for (var defaultVal in defaults) {\n string = string.replace(defaultVal, defaults[defaultVal]);\n }\n\n return string;\n}\n\n/*\n* This feature allows metadata text tracks to be manipulated once available\n* @see processMetadataTracks.\n* It also allows ad implementations to leverage ad cues coming through\n* text tracks, @see processAdTrack\n**/\n\nvar cueTextTracks = {};\n\n/*\n* This feature allows metadata text tracks to be manipulated once they are available,\n* usually after the 'loadstart' event is observed on the player\n* @param player A reference to a player\n* @param processMetadataTrack A callback that performs some operations on a\n* metadata text track\n**/\ncueTextTracks.processMetadataTracks = function (player, processMetadataTrack) {\n var tracks = player.textTracks();\n var setModeAndProcess = function setModeAndProcess(track) {\n if (track.kind === 'metadata') {\n player.ads.cueTextTracks.setMetadataTrackMode(track);\n processMetadataTrack(player, track);\n }\n };\n\n // Text tracks are available\n for (var i = 0; i < tracks.length; i++) {\n setModeAndProcess(tracks[i]);\n }\n\n // Wait until text tracks are added\n tracks.addEventListener('addtrack', function (event) {\n setModeAndProcess(event.track);\n });\n};\n\n/*\n* Sets the track mode to one of 'disabled', 'hidden' or 'showing'\n* @see https://github.com/videojs/video.js/blob/master/docs/guides/text-tracks.md\n* Default behavior is to do nothing, @override if this is not desired\n* @param track The text track to set the mode on\n*/\ncueTextTracks.setMetadataTrackMode = function (track) {\n return;\n};\n\n/*\n* Determines whether cue is an ad cue and returns the cue data.\n* @param player A reference to the player\n* @param cue The full cue object\n* Returns the given cue by default @override if futher processing is required\n* @return {Object} a useable ad cue or null if not supported\n**/\ncueTextTracks.getSupportedAdCue = function (player, cue) {\n return cue;\n};\n\n/*\n* Defines whether a cue is supported or not, potentially\n* based on the player settings\n* @param player A reference to the player\n* @param cue The cue to be checked\n* Default behavior is to return true, @override if this is not desired\n* @return {Boolean}\n*/\ncueTextTracks.isSupportedAdCue = function (player, cue) {\n return true;\n};\n\n/*\n* Gets the id associated with a cue.\n* @param cue The cue to extract an ID from\n* @returns The first occurance of 'id' in the object,\n* @override if this is not the desired cue id\n**/\ncueTextTracks.getCueId = function (player, cue) {\n return cue.id;\n};\n\n/*\n* Checks whether a cue has already been used\n* @param cueId The Id associated with a cue\n**/\nvar cueAlreadySeen = function cueAlreadySeen(player, cueId) {\n return cueId !== undefined && player.ads.includedCues[cueId];\n};\n\n/*\n* Indicates that a cue has been used\n* @param cueId The Id associated with a cue\n**/\nvar setCueAlreadySeen = function setCueAlreadySeen(player, cueId) {\n if (cueId !== undefined && cueId !== '') {\n player.ads.includedCues[cueId] = true;\n }\n};\n\n/*\n* This feature allows ad metadata tracks to be manipulated in ad implementations\n* @param player A reference to the player\n* @param cues The set of cues to work with\n* @param processCue A method that uses a cue to make some\n* ad request in the ad implementation\n* @param [cancelAdsHandler] A method that dynamically cancels ads in the ad implementation\n**/\ncueTextTracks.processAdTrack = function (player, cues, processCue, cancelAdsHandler) {\n player.ads.includedCues = {};\n\n // loop over set of cues\n for (var i = 0; i < cues.length; i++) {\n var cue = cues[i];\n var cueData = this.getSupportedAdCue(player, cue);\n\n // Exit if this is not a supported cue\n if (!this.isSupportedAdCue(player, cue)) {\n videojs.log.warn('Skipping as this is not a supported ad cue.', cue);\n return;\n }\n\n // Continue processing supported cue\n var cueId = this.getCueId(player, cue);\n var startTime = cue.startTime;\n\n // Skip ad if cue was already used\n if (cueAlreadySeen(player, cueId)) {\n videojs.log('Skipping ad already seen with ID ' + cueId);\n return;\n }\n\n // Optional dynamic ad cancellation\n if (cancelAdsHandler) {\n cancelAdsHandler(player, cueData, cueId, startTime);\n }\n\n // Process cue as an ad cue\n processCue(player, cueData, cueId, startTime);\n\n // Indicate that this cue has been used\n setCueAlreadySeen(player, cueId);\n }\n};\n\nfunction initCancelContentPlay(player, debug) {\n if (debug) {\n videojs.log('ADS:', 'Using cancelContentPlay to block content playback');\n }\n\n // Listen to play events to \"cancel\" them afterward\n player.on('play', cancelContentPlay);\n}\n\n/*\nThis feature makes sure the player is paused during ad loading.\n\nIt does this by pausing the player immediately after a \"play\" where ads will be requested,\nthen signalling that we should play after the ad is done.\n*/\n\nfunction cancelContentPlay() {\n var player = this;\n\n if (player.ads._shouldBlockPlay === false) {\n // Only block play if the ad plugin is in a state when content\n // playback should be blocked. This currently means during\n // BeforePrerollState and PrerollState.\n return;\n }\n\n // pause playback so ads can be handled.\n if (!player.paused()) {\n player.ads.debug('Playback was canceled by cancelContentPlay');\n player.pause();\n }\n\n // When the 'content-playback' state is entered, this will let us know to play.\n // This is needed if there is no preroll or if it errors, times out, etc.\n player.ads._cancelledPlay = true;\n}\n\nvar obj = {};\n// This reference allows videojs to be mocked in unit tests\n// while still using the available videojs import in the source code\n// @see obj.testHook\nvar videojsReference = videojs;\n\n/**\n * Checks if middleware mediators are available and\n * can be used on this platform.\n * Currently we can only use mediators on desktop platforms.\n */\nobj.isMiddlewareMediatorSupported = function () {\n\n if (videojsReference.browser.IS_IOS || videojsReference.browser.IS_ANDROID) {\n return false;\n } else if (\n // added when middleware was introduced in video.js\n videojsReference.use &&\n // added when mediators were introduced in video.js\n videojsReference.middleware && videojsReference.middleware.TERMINATOR) {\n return true;\n }\n\n return false;\n};\n\nobj.playMiddleware = function (player) {\n return {\n setSource: function setSource(srcObj, next) {\n next(null, srcObj);\n },\n callPlay: function callPlay() {\n // Block play calls while waiting for an ad, only if this is an\n // ad supported player\n if (player.ads && player.ads._shouldBlockPlay === true) {\n player.ads.debug('Using playMiddleware to block content playback');\n player.ads._playBlocked = true;\n return videojsReference.middleware.TERMINATOR;\n }\n },\n play: function play(terminated, value) {\n if (player.ads && player.ads._playBlocked && terminated) {\n player.ads.debug('Play call to Tech was terminated.');\n // Trigger play event to match the user's intent to play.\n // The call to play on the Tech has been blocked, so triggering\n // the event on the Player will not affect the Tech's playback state.\n player.trigger('play');\n // At this point the player has technically started\n player.addClass('vjs-has-started');\n // Reset playBlocked\n player.ads._playBlocked = false;\n }\n }\n };\n};\n\nobj.testHook = function (testVjs) {\n videojsReference = testVjs;\n};\n\nvar State = function () {\n State._getName = function _getName() {\n return 'Anonymous State';\n };\n\n function State(player) {\n classCallCheck(this, State);\n\n this.player = player;\n }\n\n /*\n * This is the only allowed way to perform state transitions. State transitions usually\n * happen in player event handlers. They can also happen recursively in `init`. They\n * should _not_ happen in `cleanup`.\n */\n\n\n State.prototype.transitionTo = function transitionTo(NewState) {\n var player = this.player;\n var previousState = this;\n\n previousState.cleanup(player);\n var newState = new NewState(player);\n\n player.ads._state = newState;\n player.ads.debug(previousState.constructor._getName() + ' -> ' + newState.constructor._getName());\n\n for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n\n newState.init.apply(newState, [player].concat(args));\n };\n\n /*\n * Implemented by subclasses to provide initialization logic when transitioning\n * to a new state.\n */\n\n\n State.prototype.init = function init() {};\n\n /*\n * Implemented by subclasses to provide cleanup logic when transitioning\n * to a new state.\n */\n\n\n State.prototype.cleanup = function cleanup() {};\n\n /*\n * Default event handlers. Different states can override these to provide behaviors.\n */\n\n\n State.prototype.onPlay = function onPlay() {};\n\n State.prototype.onPlaying = function onPlaying() {};\n\n State.prototype.onEnded = function onEnded() {};\n\n State.prototype.onAdsReady = function onAdsReady() {\n videojs.log.warn('Unexpected adsready event');\n };\n\n State.prototype.onAdsError = function onAdsError() {};\n\n State.prototype.onAdsCanceled = function onAdsCanceled() {};\n\n State.prototype.onAdTimeout = function onAdTimeout() {};\n\n State.prototype.onAdStarted = function onAdStarted() {};\n\n State.prototype.onContentChanged = function onContentChanged() {};\n\n State.prototype.onContentResumed = function onContentResumed() {};\n\n State.prototype.onReadyForPostroll = function onReadyForPostroll() {\n videojs.log.warn('Unexpected readyforpostroll event');\n };\n\n State.prototype.onNoPreroll = function onNoPreroll() {};\n\n State.prototype.onNoPostroll = function onNoPostroll() {};\n\n /*\n * Method handlers. Different states can override these to provide behaviors.\n */\n\n\n State.prototype.startLinearAdMode = function startLinearAdMode() {\n videojs.log.warn('Unexpected startLinearAdMode invocation ' + '(State via ' + this.constructor._getName() + ')');\n };\n\n State.prototype.endLinearAdMode = function endLinearAdMode() {\n videojs.log.warn('Unexpected endLinearAdMode invocation ' + '(State via ' + this.constructor._getName() + ')');\n };\n\n State.prototype.skipLinearAdMode = function skipLinearAdMode() {\n videojs.log.warn('Unexpected skipLinearAdMode invocation ' + '(State via ' + this.constructor._getName() + ')');\n };\n\n /*\n * Overridden by ContentState and AdState. Should not be overriden elsewhere.\n */\n\n\n State.prototype.isAdState = function isAdState() {\n throw new Error('isAdState unimplemented for ' + this.constructor._getName());\n };\n\n /*\n * Overridden by Preroll and Postroll. Midrolls jump right into the ad break\n * so there is no \"waiting\" state for them.\n */\n\n\n State.prototype.isWaitingForAdBreak = function isWaitingForAdBreak() {\n return false;\n };\n\n /*\n * Overridden by Preroll, Midroll, and Postroll.\n */\n\n\n State.prototype.isContentResuming = function isContentResuming() {\n return false;\n };\n\n State.prototype.inAdBreak = function inAdBreak() {\n return false;\n };\n\n /*\n * Invoke event handler methods when events come in.\n */\n\n\n State.prototype.handleEvent = function handleEvent(type) {\n var player = this.player;\n\n if (type === 'play') {\n this.onPlay(player);\n } else if (type === 'adsready') {\n this.onAdsReady(player);\n } else if (type === 'adserror') {\n this.onAdsError(player);\n } else if (type === 'adscanceled') {\n this.onAdsCanceled(player);\n } else if (type === 'adtimeout') {\n this.onAdTimeout(player);\n } else if (type === 'ads-ad-started') {\n this.onAdStarted(player);\n } else if (type === 'contentchanged') {\n this.onContentChanged(player);\n } else if (type === 'contentresumed') {\n this.onContentResumed(player);\n } else if (type === 'readyforpostroll') {\n this.onReadyForPostroll(player);\n } else if (type === 'playing') {\n this.onPlaying(player);\n } else if (type === 'ended') {\n this.onEnded(player);\n } else if (type === 'nopreroll') {\n this.onNoPreroll(player);\n } else if (type === 'nopostroll') {\n this.onNoPostroll(player);\n }\n };\n\n return State;\n}();\n\n/*\n * This class contains logic for all ads, be they prerolls, midrolls, or postrolls.\n * Primarily, this involves handling startLinearAdMode and endLinearAdMode.\n * It also handles content resuming.\n */\n\nvar AdState = function (_State) {\n inherits(AdState, _State);\n\n function AdState(player) {\n classCallCheck(this, AdState);\n\n var _this = possibleConstructorReturn(this, _State.call(this, player));\n\n _this.contentResuming = false;\n _this.waitingForAdBreak = false;\n return _this;\n }\n\n /*\n * Overrides State.isAdState\n */\n\n\n AdState.prototype.isAdState = function isAdState() {\n return true;\n };\n\n /*\n * We end the content-resuming process on the playing event because this is the exact\n * moment that content playback is no longer blocked by ads.\n */\n\n\n AdState.prototype.onPlaying = function onPlaying() {\n if (this.contentResuming) {\n this.transitionTo(ContentPlayback);\n }\n };\n\n /*\n * If the ad plugin does not result in a playing event when resuming content after an\n * ad, they should instead trigger a contentresumed event to signal that content should\n * resume. The main use case for this is when ads are stitched into the content video.\n */\n\n\n AdState.prototype.onContentResumed = function onContentResumed() {\n if (this.contentResuming) {\n this.transitionTo(ContentPlayback);\n }\n };\n\n /*\n * Check if we are in an ad state waiting for the ad plugin to start\n * an ad break.\n */\n\n\n AdState.prototype.isWaitingForAdBreak = function isWaitingForAdBreak() {\n return this.waitingForAdBreak;\n };\n\n /*\n * Allows you to check if content is currently resuming after an ad break.\n */\n\n\n AdState.prototype.isContentResuming = function isContentResuming() {\n return this.contentResuming;\n };\n\n /*\n * Allows you to check if an ad break is in progress.\n */\n\n\n AdState.prototype.inAdBreak = function inAdBreak() {\n return this.player.ads._inLinearAdMode === true;\n };\n\n return AdState;\n}(State);\n\nvar ContentState = function (_State) {\n inherits(ContentState, _State);\n\n function ContentState() {\n classCallCheck(this, ContentState);\n return possibleConstructorReturn(this, _State.apply(this, arguments));\n }\n\n /*\n * Overrides State.isAdState\n */\n ContentState.prototype.isAdState = function isAdState() {\n return false;\n };\n\n /*\n * Source change sends you back to preroll checks. contentchanged does not\n * fire during ad breaks, so we don't need to worry about that.\n */\n\n\n ContentState.prototype.onContentChanged = function onContentChanged(player) {\n player.ads.debug('Received contentchanged event (ContentState)');\n if (player.paused()) {\n this.transitionTo(BeforePreroll);\n } else {\n this.transitionTo(Preroll, false);\n player.pause();\n player.ads._pausedOnContentupdate = true;\n }\n };\n\n return ContentState;\n}(State);\n\n/*\nThe snapshot feature is responsible for saving the player state before an ad, then\nrestoring the player state after an ad.\n*/\n\nvar tryToResumeTimeout_ = void 0;\n\n/*\n * Returns an object that captures the portions of player state relevant to\n * video playback. The result of this function can be passed to\n * restorePlayerSnapshot with a player to return the player to the state it\n * was in when this function was invoked.\n * @param {Object} player The videojs player object\n */\nfunction getPlayerSnapshot(player) {\n var currentTime = void 0;\n\n if (videojs.browser.IS_IOS && player.ads.isLive(player)) {\n // Record how far behind live we are\n if (player.seekable().length > 0) {\n currentTime = player.currentTime() - player.seekable().end(0);\n } else {\n currentTime = player.currentTime();\n }\n } else {\n currentTime = player.currentTime();\n }\n\n var tech = player.$('.vjs-tech');\n var tracks = player.textTracks ? player.textTracks() : [];\n var suppressedTracks = [];\n var snapshotObject = {\n ended: player.ended(),\n currentSrc: player.currentSrc(),\n src: player.tech_.src(),\n currentTime: currentTime,\n type: player.currentType()\n };\n\n if (tech) {\n snapshotObject.style = tech.getAttribute('style');\n }\n\n for (var i = 0; i < tracks.length; i++) {\n var track = tracks[i];\n\n suppressedTracks.push({\n track: track,\n mode: track.mode\n });\n track.mode = 'disabled';\n }\n snapshotObject.suppressedTracks = suppressedTracks;\n\n return snapshotObject;\n}\n\n/*\n * Attempts to modify the specified player so that its state is equivalent to\n * the state of the snapshot.\n * @param {Object} player - the videojs player object\n * @param {Object} snapshotObject - the player state to apply\n */\nfunction restorePlayerSnapshot(player, snapshotObject, callback) {\n if (callback === undefined) {\n callback = function callback() {};\n }\n\n if (player.ads.disableNextSnapshotRestore === true) {\n player.ads.disableNextSnapshotRestore = false;\n callback();\n return;\n }\n\n // The playback tech\n var tech = player.$('.vjs-tech');\n\n // the number of[ remaining attempts to restore the snapshot\n var attempts = 20;\n\n var suppressedTracks = snapshotObject.suppressedTracks;\n\n var trackSnapshot = void 0;\n var restoreTracks = function restoreTracks() {\n for (var i = 0; i < suppressedTracks.length; i++) {\n trackSnapshot = suppressedTracks[i];\n trackSnapshot.track.mode = trackSnapshot.mode;\n }\n };\n\n // Finish restoring the playback state.\n // This only happens if the content video element was reused for ad playback.\n var resume = function resume() {\n var currentTime = void 0;\n\n // Live video on iOS has special logic to try to seek to the right place after\n // an ad.\n if (videojs.browser.IS_IOS && player.ads.isLive(player)) {\n if (snapshotObject.currentTime < 0) {\n // Playback was behind real time, so seek backwards to match\n if (player.seekable().length > 0) {\n currentTime = player.seekable().end(0) + snapshotObject.currentTime;\n } else {\n currentTime = player.currentTime();\n }\n player.currentTime(currentTime);\n }\n\n // Restore the video position after an ad.\n // We check snapshotObject.ended because the content starts at the beginning again\n // after being restored.\n } else if (snapshotObject.ended) {\n // For postrolls, seek to the player's current duration.\n // It could be different from the snapshot's currentTime due to\n // inaccuracy in HLS.\n player.currentTime(player.duration());\n } else {\n // Prerolls and midrolls, just seek to the player time before the ad.\n player.currentTime(snapshotObject.currentTime);\n var playPromise = player.play();\n\n if (playPromise && playPromise['catch']) {\n playPromise['catch'](function (error) {\n videojs.log.warn('Play promise rejected in snapshot resume', error);\n });\n }\n }\n\n // if we added autoplay to force content loading on iOS, remove it now\n // that it has served its purpose\n if (player.ads.shouldRemoveAutoplay_) {\n player.autoplay(false);\n player.ads.shouldRemoveAutoplay_ = false;\n }\n };\n\n // Determine if the video element has loaded enough of the snapshot source\n // to be ready to apply the rest of the state.\n // This only happens if the content video element was reused for ad playback.\n var tryToResume = function tryToResume() {\n\n // tryToResume can either have been called through the `contentcanplay`\n // event or fired through setTimeout.\n // When tryToResume is called, we should make sure to clear out the other\n // way it could've been called by removing the listener and clearing out\n // the timeout.\n player.off('contentcanplay', tryToResume);\n if (tryToResumeTimeout_) {\n player.clearTimeout(tryToResumeTimeout_);\n }\n\n // Tech may have changed depending on the differences in sources of the\n // original video and that of the ad\n tech = player.el().querySelector('.vjs-tech');\n\n if (tech.readyState > 1) {\n // some browsers and media aren't \"seekable\".\n // readyState greater than 1 allows for seeking without exceptions\n return resume();\n }\n\n if (tech.seekable === undefined) {\n // if the tech doesn't expose the seekable time ranges, try to\n // resume playback immediately\n return resume();\n }\n\n if (tech.seekable.length > 0) {\n // if some period of the video is seekable, resume playback\n return resume();\n }\n\n // delay a bit and then check again unless we're out of attempts\n if (attempts--) {\n player.setTimeout(tryToResume, 50);\n } else {\n try {\n resume();\n } catch (e) {\n videojs.log.warn('Failed to resume the content after an advertisement', e);\n }\n }\n };\n\n if ('style' in snapshotObject) {\n // overwrite all css style properties to restore state precisely\n tech.setAttribute('style', snapshotObject.style || '');\n }\n\n // Determine whether the player needs to be restored to its state\n // before ad playback began. With a custom ad display or burned-in\n // ads, the content player state hasn't been modified and so no\n // restoration is required\n\n if (player.ads.videoElementRecycled()) {\n // Snapshot restore is done, so now we're really finished.\n player.one('resumeended', callback);\n\n // on ios7, fiddling with textTracks too early will cause safari to crash\n player.one('contentloadedmetadata', restoreTracks);\n\n // adding autoplay guarantees that Safari will load the content so we can\n // seek back to the correct time after ads\n if (videojs.browser.IS_IOS && !player.autoplay()) {\n player.autoplay(true);\n\n // if we get here, the player was not originally configured to autoplay,\n // so we should remove it after it has served its purpose\n player.ads.shouldRemoveAutoplay_ = true;\n }\n\n // if the src changed for ad playback, reset it\n player.src({ src: snapshotObject.currentSrc, type: snapshotObject.type });\n\n // and then resume from the snapshots time once the original src has loaded\n // in some browsers (firefox) `canplay` may not fire correctly.\n // Reace the `canplay` event with a timeout.\n player.one('contentcanplay', tryToResume);\n tryToResumeTimeout_ = player.setTimeout(tryToResume, 2000);\n } else {\n // if we didn't change the src, just restore the tracks\n restoreTracks();\n\n // we don't need to check snapshotObject.ended here because the content video\n // element wasn't recycled\n if (!player.ended()) {\n // the src didn't change and this wasn't a postroll\n // just resume playback at the current time.\n var playPromise = player.play();\n\n if (playPromise && playPromise['catch']) {\n playPromise['catch'](function (error) {\n videojs.log.warn('Play promise rejected in snapshot restore', error);\n });\n }\n }\n\n // snapshot restore is complete\n callback();\n }\n}\n\n/*\n * Encapsulates logic for starting and ending ad breaks. An ad break\n * is the time between startLinearAdMode and endLinearAdMode. The ad\n * plugin may play 0 or more ads during this time.\n */\n\nfunction start(player) {\n player.ads.debug('Starting ad break');\n\n player.ads._inLinearAdMode = true;\n\n // No longer does anything, used to move us to ad-playback\n player.trigger('adstart');\n\n // Capture current player state snapshot\n if (!player.ads.shouldPlayContentBehindAd(player)) {\n player.ads.snapshot = getPlayerSnapshot(player);\n }\n\n // Mute the player behind the ad\n if (player.ads.shouldPlayContentBehindAd(player)) {\n player.ads.preAdVolume_ = player.volume();\n player.volume(0);\n }\n\n // Add css to the element to indicate and ad is playing.\n player.addClass('vjs-ad-playing');\n\n // We should remove the vjs-live class if it has been added in order to\n // show the adprogress control bar on Android devices for falsely\n // determined LIVE videos due to the duration incorrectly reported as Infinity\n if (player.hasClass('vjs-live')) {\n player.removeClass('vjs-live');\n }\n\n // This removes the native poster so the ads don't show the content\n // poster if content element is reused for ad playback.\n player.ads.removeNativePoster();\n}\n\nfunction end(player, callback) {\n player.ads.debug('Ending ad break');\n\n if (callback === undefined) {\n callback = function callback() {};\n }\n\n player.ads.adType = null;\n\n player.ads._inLinearAdMode = false;\n\n // Signals the end of the ad break to anyone listening.\n player.trigger('adend');\n\n player.removeClass('vjs-ad-playing');\n\n // We should add the vjs-live class back if the video is a LIVE video\n // If we dont do this, then for a LIVE Video, we will get an incorrect\n // styled control, which displays the time for the video\n if (player.ads.isLive(player)) {\n player.addClass('vjs-live');\n }\n\n // Restore snapshot\n if (!player.ads.shouldPlayContentBehindAd(player)) {\n restorePlayerSnapshot(player, player.ads.snapshot, callback);\n\n // Reset the volume to pre-ad levels\n } else {\n player.volume(player.ads.preAdVolume_);\n callback();\n }\n}\n\nvar obj$1 = { start: start, end: end };\n\n/*\n * This state encapsulates waiting for prerolls, preroll playback, and\n * content restoration after a preroll.\n */\n\nvar Preroll = function (_AdState) {\n inherits(Preroll, _AdState);\n\n function Preroll() {\n classCallCheck(this, Preroll);\n return possibleConstructorReturn(this, _AdState.apply(this, arguments));\n }\n\n /*\n * Allows state name to be logged even after minification.\n */\n Preroll._getName = function _getName() {\n return 'Preroll';\n };\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */\n\n\n Preroll.prototype.init = function init(player, adsReady, shouldResumeToContent) {\n this.waitingForAdBreak = true;\n\n // Loading spinner from now until ad start or end of ad break.\n player.addClass('vjs-ad-loading');\n\n // If adserror, adscanceled, nopreroll or skipLinearAdMode already\n // ocurred, resume to content immediately\n if (shouldResumeToContent || player.ads.nopreroll_) {\n return this.resumeAfterNoPreroll(player);\n }\n\n // Determine preroll timeout based on plugin settings\n var timeout = player.ads.settings.timeout;\n\n if (typeof player.ads.settings.prerollTimeout === 'number') {\n timeout = player.ads.settings.prerollTimeout;\n }\n\n // Start the clock ticking for ad timeout\n this._timeout = player.setTimeout(function () {\n player.trigger('adtimeout');\n }, timeout);\n\n // If adsready already happened, lets get started. Otherwise,\n // wait until onAdsReady.\n if (adsReady) {\n this.handleAdsReady();\n } else {\n this.adsReady = false;\n }\n };\n\n /*\n * Adsready event after play event.\n */\n\n\n Preroll.prototype.onAdsReady = function onAdsReady(player) {\n if (!player.ads.inAdBreak()) {\n player.ads.debug('Received adsready event (Preroll)');\n this.handleAdsReady();\n } else {\n videojs.log.warn('Unexpected adsready event (Preroll)');\n }\n };\n\n /*\n * Ad plugin is ready. Let's get started on this preroll.\n */\n\n\n Preroll.prototype.handleAdsReady = function handleAdsReady() {\n this.adsReady = true;\n this.readyForPreroll();\n };\n\n /*\n * Helper to call a callback only after a loadstart event.\n * If we start content or ads before loadstart, loadstart\n * will not be prefixed correctly.\n */\n\n\n Preroll.prototype.afterLoadStart = function afterLoadStart(callback) {\n var player = this.player;\n\n if (player.ads._hasThereBeenALoadStartDuringPlayerLife) {\n callback();\n } else {\n player.ads.debug('Waiting for loadstart...');\n player.one('loadstart', function () {\n player.ads.debug('Received loadstart event');\n callback();\n });\n }\n };\n\n /*\n * If there is no preroll, play content instead.\n */\n\n\n Preroll.prototype.noPreroll = function noPreroll() {\n var _this2 = this;\n\n this.afterLoadStart(function () {\n _this2.player.ads.debug('Skipping prerolls due to nopreroll event (Preroll)');\n _this2.resumeAfterNoPreroll(_this2.player);\n });\n };\n\n /*\n * Fire the readyforpreroll event. If loadstart hasn't happened yet,\n * wait until loadstart first.\n */\n\n\n Preroll.prototype.readyForPreroll = function readyForPreroll() {\n var player = this.player;\n\n this.afterLoadStart(function () {\n player.ads.debug('Triggered readyforpreroll event (Preroll)');\n player.trigger('readyforpreroll');\n });\n };\n\n /*\n * adscanceled cancels all ads for the source. Play content now.\n */\n\n\n Preroll.prototype.onAdsCanceled = function onAdsCanceled(player) {\n var _this3 = this;\n\n player.ads.debug('adscanceled (Preroll)');\n\n this.afterLoadStart(function () {\n _this3.resumeAfterNoPreroll(player);\n });\n };\n\n /*\n * An ad error occured. Play content instead.\n */\n\n\n Preroll.prototype.onAdsError = function onAdsError(player) {\n var _this4 = this;\n\n videojs.log('adserror (Preroll)');\n // In the future, we may not want to do this automatically.\n // Ad plugins should be able to choose to continue the ad break\n // if there was an error.\n if (this.inAdBreak()) {\n player.ads.endLinearAdMode();\n } else {\n this.afterLoadStart(function () {\n _this4.resumeAfterNoPreroll(player);\n });\n }\n };\n\n /*\n * Ad plugin invoked startLinearAdMode, the ad break starts now.\n */\n\n\n Preroll.prototype.startLinearAdMode = function startLinearAdMode() {\n var player = this.player;\n\n if (this.adsReady && !player.ads.inAdBreak() && !this.isContentResuming()) {\n player.clearTimeout(this._timeout);\n player.ads.adType = 'preroll';\n this.waitingForAdBreak = false;\n obj$1.start(player);\n\n // We don't need to block play calls anymore\n player.ads._shouldBlockPlay = false;\n } else {\n videojs.log.warn('Unexpected startLinearAdMode invocation (Preroll)');\n }\n };\n\n /*\n * An ad has actually started playing.\n * Remove the loading spinner.\n */\n\n\n Preroll.prototype.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n };\n\n /*\n * Ad plugin invoked endLinearAdMode, the ad break ends now.\n */\n\n\n Preroll.prototype.endLinearAdMode = function endLinearAdMode() {\n var player = this.player;\n\n if (this.inAdBreak()) {\n player.removeClass('vjs-ad-loading');\n player.addClass('vjs-ad-content-resuming');\n obj$1.end(player);\n this.contentResuming = true;\n }\n };\n\n /*\n * Ad skipped by ad plugin. Play content instead.\n */\n\n\n Preroll.prototype.skipLinearAdMode = function skipLinearAdMode() {\n var _this5 = this;\n\n var player = this.player;\n\n if (player.ads.inAdBreak() || this.isContentResuming()) {\n videojs.log.warn('Unexpected skipLinearAdMode invocation');\n } else {\n this.afterLoadStart(function () {\n player.trigger('adskip');\n player.ads.debug('skipLinearAdMode (Preroll)');\n _this5.resumeAfterNoPreroll(player);\n });\n }\n };\n\n /*\n * Prerolls took too long! Play content instead.\n */\n\n\n Preroll.prototype.onAdTimeout = function onAdTimeout(player) {\n var _this6 = this;\n\n this.afterLoadStart(function () {\n player.ads.debug('adtimeout (Preroll)');\n _this6.resumeAfterNoPreroll(player);\n });\n };\n\n /*\n * Check if nopreroll event was too late before handling it.\n */\n\n\n Preroll.prototype.onNoPreroll = function onNoPreroll(player) {\n if (player.ads.inAdBreak() || this.isContentResuming()) {\n videojs.log.warn('Unexpected nopreroll event (Preroll)');\n } else {\n this.noPreroll();\n }\n };\n\n Preroll.prototype.resumeAfterNoPreroll = function resumeAfterNoPreroll(player) {\n // Resume to content and unblock play as there is no preroll ad\n this.contentResuming = true;\n player.ads._shouldBlockPlay = false;\n\n // Play the content if we had requested play or we paused on 'contentupdate'\n // and we haven't played yet. This happens if there was no preroll or if it\n // errored, timed out, etc. Otherwise snapshot restore would play.\n if (player.paused() && (player.ads._playRequested || player.ads._pausedOnContentupdate)) {\n player.play();\n }\n };\n\n /*\n * Cleanup timeouts and spinner.\n */\n\n\n Preroll.prototype.cleanup = function cleanup(player) {\n if (!player.ads._hasThereBeenALoadStartDuringPlayerLife) {\n videojs.log.warn('Leaving Preroll state before loadstart event can cause issues.');\n }\n\n player.removeClass('vjs-ad-loading');\n player.removeClass('vjs-ad-content-resuming');\n player.clearTimeout(this._timeout);\n };\n\n return Preroll;\n}(AdState);\n\nvar Midroll = function (_AdState) {\n inherits(Midroll, _AdState);\n\n function Midroll() {\n classCallCheck(this, Midroll);\n return possibleConstructorReturn(this, _AdState.apply(this, arguments));\n }\n\n /*\n * Allows state name to be logged even after minification.\n */\n Midroll._getName = function _getName() {\n return 'Midroll';\n };\n\n /*\n * Midroll breaks happen when the ad plugin calls startLinearAdMode,\n * which can happen at any time during content playback.\n */\n\n\n Midroll.prototype.init = function init(player) {\n player.ads.adType = 'midroll';\n obj$1.start(player);\n player.addClass('vjs-ad-loading');\n };\n\n /*\n * An ad has actually started playing.\n * Remove the loading spinner.\n */\n\n\n Midroll.prototype.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n };\n\n /*\n * Midroll break is done.\n */\n\n\n Midroll.prototype.endLinearAdMode = function endLinearAdMode() {\n var player = this.player;\n\n if (this.inAdBreak()) {\n this.contentResuming = true;\n player.addClass('vjs-ad-content-resuming');\n player.removeClass('vjs-ad-loading');\n obj$1.end(player);\n }\n };\n\n /*\n * End midroll break if there is an error.\n */\n\n\n Midroll.prototype.onAdsError = function onAdsError(player) {\n // In the future, we may not want to do this automatically.\n // Ad plugins should be able to choose to continue the ad break\n // if there was an error.\n if (this.inAdBreak()) {\n player.ads.endLinearAdMode();\n }\n };\n\n /*\n * Cleanup CSS classes.\n */\n\n\n Midroll.prototype.cleanup = function cleanup(player) {\n player.removeClass('vjs-ad-loading');\n player.removeClass('vjs-ad-content-resuming');\n };\n\n return Midroll;\n}(AdState);\n\nvar Postroll = function (_AdState) {\n inherits(Postroll, _AdState);\n\n function Postroll() {\n classCallCheck(this, Postroll);\n return possibleConstructorReturn(this, _AdState.apply(this, arguments));\n }\n\n /*\n * Allows state name to be logged even after minification.\n */\n Postroll._getName = function _getName() {\n return 'Postroll';\n };\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */\n\n\n Postroll.prototype.init = function init(player) {\n this.waitingForAdBreak = true;\n\n // Legacy name that now simply means \"handling postrolls\".\n player.ads._contentEnding = true;\n\n // Start postroll process.\n if (!player.ads.nopostroll_) {\n player.addClass('vjs-ad-loading');\n\n // Determine postroll timeout based on plugin settings\n var timeout = player.ads.settings.timeout;\n\n if (typeof player.ads.settings.postrollTimeout === 'number') {\n timeout = player.ads.settings.postrollTimeout;\n }\n\n this._postrollTimeout = player.setTimeout(function () {\n player.trigger('adtimeout');\n }, timeout);\n\n // No postroll, ads are done\n } else {\n this.resumeContent(player);\n this.transitionTo(AdsDone);\n }\n };\n\n /*\n * Start the postroll if it's not too late.\n */\n\n\n Postroll.prototype.startLinearAdMode = function startLinearAdMode() {\n var player = this.player;\n\n if (!player.ads.inAdBreak() && !this.isContentResuming()) {\n player.ads.adType = 'postroll';\n player.clearTimeout(this._postrollTimeout);\n this.waitingForAdBreak = false;\n obj$1.start(player);\n } else {\n videojs.log.warn('Unexpected startLinearAdMode invocation (Postroll)');\n }\n };\n\n /*\n * An ad has actually started playing.\n * Remove the loading spinner.\n */\n\n\n Postroll.prototype.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n };\n\n /*\n * Ending a postroll triggers the ended event.\n */\n\n\n Postroll.prototype.endLinearAdMode = function endLinearAdMode() {\n var _this2 = this;\n\n var player = this.player;\n\n if (this.inAdBreak()) {\n player.removeClass('vjs-ad-loading');\n this.resumeContent(player);\n obj$1.end(player, function () {\n _this2.transitionTo(AdsDone);\n });\n }\n };\n\n /*\n * Postroll skipped, time to clean up.\n */\n\n\n Postroll.prototype.skipLinearAdMode = function skipLinearAdMode() {\n var player = this.player;\n\n if (player.ads.inAdBreak() || this.isContentResuming()) {\n videojs.log.warn('Unexpected skipLinearAdMode invocation');\n } else {\n player.ads.debug('Postroll abort (skipLinearAdMode)');\n player.trigger('adskip');\n this.abort(player);\n }\n };\n\n /*\n * Postroll timed out, time to clean up.\n */\n\n\n Postroll.prototype.onAdTimeout = function onAdTimeout(player) {\n player.ads.debug('Postroll abort (adtimeout)');\n this.abort(player);\n };\n\n /*\n * Postroll errored out, time to clean up.\n */\n\n\n Postroll.prototype.onAdsError = function onAdsError(player) {\n player.ads.debug('Postroll abort (adserror)');\n\n // In the future, we may not want to do this automatically.\n // Ad plugins should be able to choose to continue the ad break\n // if there was an error.\n if (player.ads.inAdBreak()) {\n player.ads.endLinearAdMode();\n } else {\n this.abort(player);\n }\n };\n\n /*\n * Handle content change if we're not in an ad break.\n */\n\n\n Postroll.prototype.onContentChanged = function onContentChanged(player) {\n // Content resuming after Postroll. Content is paused\n // at this point, since it is done playing.\n if (this.isContentResuming()) {\n this.transitionTo(BeforePreroll);\n\n // Waiting for postroll to start. Content is considered playing\n // at this point, since it had to be playing to start the postroll.\n } else if (!this.inAdBreak()) {\n this.transitionTo(Preroll);\n }\n };\n\n /*\n * Wrap up if there is no postroll.\n */\n\n\n Postroll.prototype.onNoPostroll = function onNoPostroll(player) {\n if (!this.isContentResuming() && !this.inAdBreak()) {\n this.abort(player);\n } else {\n videojs.log.warn('Unexpected nopostroll event (Postroll)');\n }\n };\n\n Postroll.prototype.resumeContent = function resumeContent(player) {\n this.contentResuming = true;\n player.addClass('vjs-ad-content-resuming');\n };\n\n /*\n * Helper for ending Postrolls. In the future we may want to\n * refactor this class so that `cleanup` handles all of this.\n */\n\n\n Postroll.prototype.abort = function abort(player) {\n this.resumeContent(player);\n player.removeClass('vjs-ad-loading');\n this.transitionTo(AdsDone);\n };\n\n /*\n * Cleanup timeouts and state.\n */\n\n\n Postroll.prototype.cleanup = function cleanup(player) {\n player.removeClass('vjs-ad-content-resuming');\n player.clearTimeout(this._postrollTimeout);\n player.ads._contentEnding = false;\n };\n\n return Postroll;\n}(AdState);\n\n/*\n * This is the initial state for a player with an ad plugin. Normally, it remains in this\n * state until a \"play\" event is seen. After that, we enter the Preroll state to check for\n * prerolls. This happens regardless of whether or not any prerolls ultimately will play.\n * Errors and other conditions may lead us directly from here to ContentPlayback.\n */\n\nvar BeforePreroll = function (_ContentState) {\n inherits(BeforePreroll, _ContentState);\n\n function BeforePreroll() {\n classCallCheck(this, BeforePreroll);\n return possibleConstructorReturn(this, _ContentState.apply(this, arguments));\n }\n\n /*\n * Allows state name to be logged even after minification.\n */\n BeforePreroll._getName = function _getName() {\n return 'BeforePreroll';\n };\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */\n\n\n BeforePreroll.prototype.init = function init(player) {\n this.adsReady = false;\n this.shouldResumeToContent = false;\n\n // Content playback should be blocked until we are done\n // playing ads or we know there are no ads to play\n player.ads._shouldBlockPlay = true;\n };\n\n /*\n * The ad plugin may trigger adsready before the play request. If so,\n * we record that adsready already happened so the Preroll state will know.\n */\n\n\n BeforePreroll.prototype.onAdsReady = function onAdsReady(player) {\n player.ads.debug('Received adsready event (BeforePreroll)');\n this.adsReady = true;\n };\n\n /*\n * Ad mode officially begins on the play request, because at this point\n * content playback is blocked by the ad plugin.\n */\n\n\n BeforePreroll.prototype.onPlay = function onPlay(player) {\n player.ads.debug('Received play event (BeforePreroll)');\n\n // Check for prerolls\n this.transitionTo(Preroll, this.adsReady, this.shouldResumeToContent);\n };\n\n /*\n * All ads for the entire video are canceled.\n */\n\n\n BeforePreroll.prototype.onAdsCanceled = function onAdsCanceled(player) {\n player.ads.debug('adscanceled (BeforePreroll)');\n this.shouldResumeToContent = true;\n };\n\n /*\n * An ad error occured. Play content instead.\n */\n\n\n BeforePreroll.prototype.onAdsError = function onAdsError() {\n this.player.ads.debug('adserror (BeforePreroll)');\n this.shouldResumeToContent = true;\n };\n\n /*\n * If there is no preroll, don't wait for a play event to move forward.\n */\n\n\n BeforePreroll.prototype.onNoPreroll = function onNoPreroll() {\n this.player.ads.debug('Skipping prerolls due to nopreroll event (BeforePreroll)');\n this.shouldResumeToContent = true;\n };\n\n /*\n * Prerolls skipped by ad plugin. Play content instead.\n */\n\n\n BeforePreroll.prototype.skipLinearAdMode = function skipLinearAdMode() {\n var player = this.player;\n\n player.trigger('adskip');\n player.ads.debug('skipLinearAdMode (BeforePreroll)');\n this.shouldResumeToContent = true;\n };\n\n /*\n * Content source change before preroll is currently not handled. When\n * developed, this is where to start.\n */\n\n\n BeforePreroll.prototype.onContentChanged = function onContentChanged() {};\n\n return BeforePreroll;\n}(ContentState);\n\n/*\n * This state represents content playback the first time through before\n * content ends. After content has ended once, we check for postrolls and\n * move on to the AdsDone state rather than returning here.\n */\n\nvar ContentPlayback = function (_ContentState) {\n inherits(ContentPlayback, _ContentState);\n\n function ContentPlayback() {\n classCallCheck(this, ContentPlayback);\n return possibleConstructorReturn(this, _ContentState.apply(this, arguments));\n }\n\n /*\n * Allows state name to be logged even after minification.\n */\n ContentPlayback._getName = function _getName() {\n return 'ContentPlayback';\n };\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */\n\n\n ContentPlayback.prototype.init = function init(player) {\n // Don't block calls to play in content playback\n player.ads._shouldBlockPlay = false;\n };\n\n /*\n * In the case of a timeout, adsready might come in late. This assumes the behavior\n * that if an ad times out, it could still interrupt the content and start playing.\n * An ad plugin could behave otherwise by ignoring this event.\n */\n\n\n ContentPlayback.prototype.onAdsReady = function onAdsReady(player) {\n player.ads.debug('Received adsready event (ContentPlayback)');\n\n if (!player.ads.nopreroll_) {\n player.ads.debug('Triggered readyforpreroll event (ContentPlayback)');\n player.trigger('readyforpreroll');\n }\n };\n\n /*\n * Content ended before postroll checks.\n */\n\n\n ContentPlayback.prototype.onReadyForPostroll = function onReadyForPostroll(player) {\n player.ads.debug('Received readyforpostroll event');\n this.transitionTo(Postroll);\n };\n\n /*\n * This is how midrolls start.\n */\n\n\n ContentPlayback.prototype.startLinearAdMode = function startLinearAdMode() {\n this.transitionTo(Midroll);\n };\n\n return ContentPlayback;\n}(ContentState);\n\nvar AdsDone = function (_ContentState) {\n inherits(AdsDone, _ContentState);\n\n function AdsDone() {\n classCallCheck(this, AdsDone);\n return possibleConstructorReturn(this, _ContentState.apply(this, arguments));\n }\n\n /*\n * Allows state name to be logged even after minification.\n */\n AdsDone._getName = function _getName() {\n return 'AdsDone';\n };\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */\n\n\n AdsDone.prototype.init = function init(player) {\n // From now on, `ended` events won't be redispatched\n player.ads._contentHasEnded = true;\n player.trigger('ended');\n };\n\n /*\n * Midrolls do not play after ads are done.\n */\n\n\n AdsDone.prototype.startLinearAdMode = function startLinearAdMode() {\n videojs.log.warn('Unexpected startLinearAdMode invocation (AdsDone)');\n };\n\n return AdsDone;\n}(ContentState);\n\n/*\n * This file is necessary to avoid this rollup issue:\n * https://github.com/rollup/rollup/issues/1089\n */\n\n/*\nThis main plugin file is responsible for the public API and enabling the features\nthat live in in separate files.\n*/\n\nvar playMiddleware = obj.playMiddleware;\nvar isMiddlewareMediatorSupported = obj.isMiddlewareMediatorSupported;\n\nvar VIDEO_EVENTS = videojs.getTech('Html5').Events;\n\n// default settings\nvar defaults = {\n // maximum amount of time in ms to wait to receive `adsready` from the ad\n // implementation after play has been requested. Ad implementations are\n // expected to load any dynamic libraries and make any requests to determine\n // ad policies for a video during this time.\n timeout: 5000,\n\n // maximum amount of time in ms to wait for the ad implementation to start\n // linear ad mode after `readyforpreroll` has fired. This is in addition to\n // the standard timeout.\n prerollTimeout: undefined,\n\n // maximum amount of time in ms to wait for the ad implementation to start\n // linear ad mode after `readyforpostroll` has fired.\n postrollTimeout: undefined,\n\n // when truthy, instructs the plugin to output additional information about\n // plugin state to the video.js log. On most devices, the video.js log is\n // the same as the developer console.\n debug: false,\n\n // set this to true when using ads that are part of the content video\n stitchedAds: false,\n\n // force content to be treated as live or not live\n // if not defined, the code will try to infer if content is live,\n // which can have limitations.\n contentIsLive: undefined\n};\n\nvar contribAdsPlugin = function contribAdsPlugin(options) {\n\n var player = this; // eslint-disable-line consistent-this\n\n var settings = videojs.mergeOptions(defaults, options);\n\n // prefix all video element events during ad playback\n // if the video element emits ad-related events directly,\n // plugins that aren't ad-aware will break. prefixing allows\n // plugins that wish to handle ad events to do so while\n // avoiding the complexity for common usage\n var videoEvents = VIDEO_EVENTS.concat(['firstplay', 'loadedalldata', 'playing']);\n\n // Set up redispatching of player events\n player.on(videoEvents, redispatch);\n\n // Set up features to block content playback while waiting for ads.\n // Play middleware is only supported on later versions of video.js\n // and on desktop currently(as the user-gesture requirement on mobile\n // will disallow calling play once play blocking is lifted)\n // The middleware must also be registered outside of the plugin,\n // to avoid a middleware factory being created for each player\n if (isMiddlewareMediatorSupported() && settings.debug) {\n // We log the debug message here as the plugin settings are available here\n videojs.log('ADS:', 'Play middleware has been registered with videojs');\n } else {\n // Register the cancelContentPlay feature on the player\n initCancelContentPlay(player, settings.debug);\n }\n\n // If we haven't seen a loadstart after 5 seconds, the plugin was not initialized\n // correctly.\n player.setTimeout(function () {\n if (!player.ads._hasThereBeenALoadStartDuringPlayerLife && player.src() !== '') {\n videojs.log.error('videojs-contrib-ads has not seen a loadstart event 5 seconds ' + 'after being initialized, but a source is present. This indicates that ' + 'videojs-contrib-ads was initialized too late. It must be initialized ' + 'immediately after video.js in the same tick. As a result, some ads will not ' + 'play and some media events will be incorrect. For more information, see ' + 'http://videojs.github.io/videojs-contrib-ads/integrator/getting-started.html');\n }\n }, 5000);\n\n // \"vjs-has-started\" should be present at the end of a video. This makes sure it's\n // always there.\n player.on('ended', function () {\n if (!player.hasClass('vjs-has-started')) {\n player.addClass('vjs-has-started');\n }\n });\n\n // video.js removes the vjs-waiting class on timeupdate. We want\n // to make sure this still happens during content restoration.\n player.on('contenttimeupdate', function () {\n player.removeClass('vjs-waiting');\n });\n\n // We now auto-play when an ad gets loaded if we're playing ads in the same video\n // element as the content.\n // The problem is that in IE11, we cannot play in addurationchange but in iOS8, we\n // cannot play from adcanplay.\n // This will prevent ad plugins from needing to do this themselves.\n player.on(['addurationchange', 'adcanplay'], function () {\n if (player.ads.snapshot && player.currentSrc() === player.ads.snapshot.currentSrc) {\n return;\n }\n\n // If an ad isn't playing, don't try to play an ad. This could result from prefixed\n // events when the player is blocked by a preroll check, but there is no preroll.\n if (!player.ads.inAdBreak()) {\n return;\n }\n\n var playPromise = player.play();\n\n if (playPromise && playPromise['catch']) {\n playPromise['catch'](function (error) {\n videojs.log.warn('Play promise rejected when playing ad', error);\n });\n }\n });\n\n player.on('nopreroll', function () {\n player.ads.debug('Received nopreroll event');\n player.ads.nopreroll_ = true;\n });\n\n player.on('nopostroll', function () {\n player.ads.debug('Received nopostroll event');\n player.ads.nopostroll_ = true;\n });\n\n // Restart the cancelContentPlay process.\n player.on('playing', function () {\n player.ads._cancelledPlay = false;\n player.ads._pausedOnContentupdate = false;\n });\n\n // Keep track of whether a play event has happened\n player.on('play', function () {\n player.ads._playRequested = true;\n });\n\n player.one('loadstart', function () {\n player.ads._hasThereBeenALoadStartDuringPlayerLife = true;\n });\n\n player.on('loadeddata', function () {\n player.ads._hasThereBeenALoadedData = true;\n });\n\n player.on('loadedmetadata', function () {\n player.ads._hasThereBeenALoadedMetaData = true;\n });\n\n // Replace the plugin constructor with the ad namespace\n player.ads = getAds(player);\n\n player.ads.settings = settings;\n player.ads._state = new BeforePreroll(player);\n player.ads._state.init(player);\n\n player.ads.stitchedAds(settings.stitchedAds);\n\n player.ads.cueTextTracks = cueTextTracks;\n player.ads.adMacroReplacement = adMacroReplacement.bind(player);\n\n // Start sending contentupdate and contentchanged events for this player\n initializeContentupdate(player);\n\n // Global contentchanged handler for resetting plugin state\n player.on('contentchanged', player.ads.reset);\n\n // A utility method for textTrackChangeHandler to define the conditions\n // when text tracks should be disabled.\n // Currently this includes:\n // - on iOS with native text tracks, during an ad playing\n var shouldDisableTracks = function shouldDisableTracks() {\n // If the platform matches iOS with native text tracks\n // and this occurs during ad playback, we should disable tracks again.\n // If shouldPlayContentBehindAd, no special handling is needed.\n return !player.ads.shouldPlayContentBehindAd(player) && player.ads.inAdBreak() && player.tech_.featuresNativeTextTracks && videojs.browser.IS_IOS &&\n // older versions of video.js did not use an emulated textTrackList\n !Array.isArray(player.textTracks());\n };\n\n /*\n * iOS Safari will change caption mode to 'showing' if a user previously\n * turned captions on manually for that video source, so this TextTrackList\n * 'change' event handler will re-disable them in case that occurs during ad playback\n */\n var textTrackChangeHandler = function textTrackChangeHandler() {\n var textTrackList = player.textTracks();\n\n if (shouldDisableTracks()) {\n // We must double check all tracks\n for (var i = 0; i < textTrackList.length; i++) {\n var track = textTrackList[i];\n\n if (track.mode === 'showing') {\n track.mode = 'disabled';\n }\n }\n }\n };\n\n // Add the listener to the text track list\n player.ready(function () {\n player.textTracks().addEventListener('change', textTrackChangeHandler);\n });\n\n // Event handling for the current state.\n player.on(['play', 'playing', 'ended', 'adsready', 'adscanceled', 'adskip', 'adserror', 'adtimeout', 'ads-ad-started', 'contentchanged', 'contentresumed', 'readyforpostroll', 'nopreroll', 'nopostroll'], function (e) {\n player.ads._state.handleEvent(e.type);\n });\n\n // Clear timeouts and handlers when player is disposed\n player.on('dispose', function () {\n player.textTracks().removeEventListener('change', textTrackChangeHandler);\n });\n};\n\nvar registerPlugin = videojs.registerPlugin || videojs.plugin;\n\n// Register this plugin with videojs\nregisterPlugin('ads', contribAdsPlugin);\n\n// Register the Play Middleware with video.js on script execution,\n// to avoid a new playMiddleware factory being created on\n// videojs for each player created.\nif (isMiddlewareMediatorSupported()) {\n // Register the play middleware\n videojs.use('*', playMiddleware);\n}\n\nreturn contribAdsPlugin;\n\n})));\n"},245:function(e,n,t){t(237)(t(242))}}]);