cloudinary-video-player 3.6.3-edge.8 → 3.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/adaptive-streaming.js +50 -50
  2. package/dist/adaptive-streaming.min.js +5 -5
  3. package/dist/chapters.js +10 -10
  4. package/dist/chapters.min.js +3 -3
  5. package/dist/cld-video-player.css +2 -2
  6. package/dist/cld-video-player.js +1861 -1866
  7. package/dist/cld-video-player.light.js +1861 -1866
  8. package/dist/cld-video-player.light.min.js +4 -4
  9. package/dist/cld-video-player.min.css +2 -2
  10. package/dist/cld-video-player.min.js +4 -4
  11. package/dist/colors.js +10 -10
  12. package/dist/colors.min.js +3 -3
  13. package/dist/dash.js +18 -18
  14. package/dist/dash.min.js +4 -4
  15. package/dist/debug.js +38 -38
  16. package/dist/debug.min.js +3 -3
  17. package/dist/ima.js +44 -44
  18. package/dist/ima.min.js +3 -3
  19. package/dist/interaction-areas.js +58 -58
  20. package/dist/interaction-areas.min.js +3 -3
  21. package/dist/node_modules_lodash_throttle_js.js +26 -26
  22. package/dist/playlist.js +182 -182
  23. package/dist/playlist.min.js +3 -3
  24. package/dist/recommendations-overlay.js +34 -34
  25. package/dist/recommendations-overlay.min.js +3 -3
  26. package/dist/share.js +14 -14
  27. package/dist/share.min.js +3 -3
  28. package/dist/shoppable.js +48 -48
  29. package/dist/shoppable.min.js +3 -3
  30. package/dist/visual-search.js +22 -22
  31. package/dist/visual-search.min.js +3 -3
  32. package/lib/adaptive-streaming.js +1 -1
  33. package/lib/all.js +1 -1
  34. package/lib/chapters.js +1 -1
  35. package/lib/cld-video-player.js +1 -1
  36. package/lib/colors.js +1 -1
  37. package/lib/dash.js +1 -1
  38. package/lib/debug.js +1 -1
  39. package/lib/ima.js +1 -1
  40. package/lib/interaction-areas.js +1 -1
  41. package/lib/player.js +1 -1
  42. package/lib/playlist.js +1 -1
  43. package/lib/recommendations-overlay.js +1 -1
  44. package/lib/share.js +1 -1
  45. package/lib/shoppable.js +1 -1
  46. package/lib/videoPlayer.js +1 -1
  47. package/lib/visual-search.js +1 -1
  48. package/package.json +2 -2
package/dist/ima.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * Cloudinary Video Player v3.6.3-edge.8
3
- * Built on 2025-12-18T17:10:29.081Z
2
+ * Cloudinary Video Player v3.6.3
3
+ * Built on 2026-01-04T09:24:08.226Z
4
4
  * https://github.com/cloudinary/cloudinary-video-player
5
5
  */
6
6
  /*
@@ -13,78 +13,78 @@
13
13
  */
14
14
  (self["cloudinaryVideoPlayerChunkLoading"] = self["cloudinaryVideoPlayerChunkLoading"] || []).push([["ima"],{
15
15
 
16
- /***/ "../node_modules/global/document.js"
16
+ /***/ "./plugins/ima/ima.js":
17
+ /*!****************************!*\
18
+ !*** ./plugins/ima/ima.js ***!
19
+ \****************************/
20
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
21
+
22
+ "use strict";
23
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var videojs_contrib_ads__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! videojs-contrib-ads */ \"../node_modules/videojs-contrib-ads/dist/videojs-contrib-ads.es.js\");\n/* harmony import */ var videojs_ima__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! videojs-ima */ \"../node_modules/videojs-ima/dist/videojs.ima.es.js\");\n/* harmony import */ var videojs_ima_dist_videojs_ima_scss__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! videojs-ima/dist/videojs.ima.scss */ \"../node_modules/videojs-ima/dist/videojs.ima.scss\");\n\n\n\n\n//# sourceURL=webpack://cloudinary-video-player/./plugins/ima/ima.js?");
24
+
25
+ /***/ }),
26
+
27
+ /***/ "../node_modules/global/document.js":
17
28
  /*!******************************************!*\
18
29
  !*** ../node_modules/global/document.js ***!
19
30
  \******************************************/
20
- (module, __unused_webpack_exports, __webpack_require__) {
31
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
21
32
 
22
- eval("{var topLevel = typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g :\n typeof window !== 'undefined' ? window : {}\nvar minDoc = __webpack_require__(/*! min-document */ \"?9835\");\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\nmodule.exports = doccy;\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/global/document.js?\n}");
33
+ eval("var topLevel = typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g :\n typeof window !== 'undefined' ? window : {}\nvar minDoc = __webpack_require__(/*! min-document */ \"?9835\");\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\nmodule.exports = doccy;\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/global/document.js?");
23
34
 
24
- /***/ },
35
+ /***/ }),
25
36
 
26
- /***/ "../node_modules/global/window.js"
37
+ /***/ "../node_modules/global/window.js":
27
38
  /*!****************************************!*\
28
39
  !*** ../node_modules/global/window.js ***!
29
40
  \****************************************/
30
- (module, __unused_webpack_exports, __webpack_require__) {
41
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
31
42
 
32
- eval("{var win;\n\nif (typeof window !== \"undefined\") {\n win = window;\n} else if (typeof __webpack_require__.g !== \"undefined\") {\n win = __webpack_require__.g;\n} else if (typeof self !== \"undefined\"){\n win = self;\n} else {\n win = {};\n}\n\nmodule.exports = win;\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/global/window.js?\n}");
43
+ eval("var win;\n\nif (typeof window !== \"undefined\") {\n win = window;\n} else if (typeof __webpack_require__.g !== \"undefined\") {\n win = __webpack_require__.g;\n} else if (typeof self !== \"undefined\"){\n win = self;\n} else {\n win = {};\n}\n\nmodule.exports = win;\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/global/window.js?");
44
+
45
+ /***/ }),
46
+
47
+ /***/ "../node_modules/videojs-ima/dist/videojs.ima.scss":
48
+ /*!*********************************************************!*\
49
+ !*** ../node_modules/videojs-ima/dist/videojs.ima.scss ***!
50
+ \*********************************************************/
51
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
52
+
53
+ "use strict";
54
+ eval("__webpack_require__.r(__webpack_exports__);\n// extracted by mini-css-extract-plugin\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/videojs-ima/dist/videojs.ima.scss?");
33
55
 
34
- /***/ },
56
+ /***/ }),
35
57
 
36
- /***/ "../node_modules/videojs-contrib-ads/dist/videojs-contrib-ads.es.js"
58
+ /***/ "../node_modules/videojs-contrib-ads/dist/videojs-contrib-ads.es.js":
37
59
  /*!**************************************************************************!*\
38
60
  !*** ../node_modules/videojs-contrib-ads/dist/videojs-contrib-ads.es.js ***!
39
61
  \**************************************************************************/
40
- (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
62
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
41
63
 
42
64
  "use strict";
43
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\");\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(video_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var global_window__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! global/window */ \"../node_modules/global/window.js\");\n/* harmony import */ var global_window__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(global_window__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var global_document__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! global/document */ \"../node_modules/global/document.js\");\n/* harmony import */ var global_document__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(global_document__WEBPACK_IMPORTED_MODULE_2__);\n/*! @name videojs-contrib-ads @version 7.5.2 @license Apache-2.0 */\n\n\n\n\nvar version = \"7.5.2\";\n\n/*\n * Implements the public API available in `player.ads` as well as application state.\n */\nfunction getAds(player) {\n return {\n disableNextSnapshotRestore: false,\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 // 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 // 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 // Tracks if loadeddata has happened yet for the current source.\n _hasThereBeenALoadedData: false,\n // Tracks if loadedmetadata has happened yet for the current source.\n _hasThereBeenALoadedMetaData: false,\n // Are we after startLinearAdMode and before endLinearAdMode?\n _inLinearAdMode: false,\n // Should we block calls to play on the content player?\n _shouldBlockPlay: false,\n // Was play blocked by the plugin's playMiddleware feature?\n _playBlocked: false,\n // Tracks whether play has been requested for this source,\n // either by the play method or user interaction\n _playRequested: false,\n // Contains error information when an error occurs in contrib-ads.\n // When set, will contain an object with a type and metadata.\n _error: null,\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 VERSION: version,\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 player.ads._error = null;\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 // Call this when a linear ad pod has finished playing.\n endLinearAdMode: function endLinearAdMode() {\n player.ads._state.endLinearAdMode();\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 // With no arguments, returns a boolean value indicating whether or not\n // contrib-ads is set to treat ads as stitched with content in a single\n // stream. With arguments, treated as a setter, but this behavior is\n // deprecated.\n stitchedAds: function stitchedAds(arg) {\n if (arg !== undefined) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Using player.ads.stitchedAds() as a setter is deprecated, ' + 'it should be set as an option upon initialization of contrib-ads.');\n\n // Keep the private property and the settings in sync. When this\n // setter is removed, we can probably stop using the private property.\n this.settings.stitchedAds = !!arg;\n }\n return this.settings.stitchedAds;\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 if (!this.snapshot) {\n throw new Error('You cannot use videoElementRecycled while there is no snapshot.');\n }\n var srcChanged = player.tech_.src() !== this.snapshot.src;\n var currentSrcChanged = player.currentSrc() !== this.snapshot.currentSrc;\n return srcChanged || currentSrcChanged;\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 (somePlayer === void 0) {\n somePlayer = player;\n }\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 ((video_js__WEBPACK_IMPORTED_MODULE_0___default().browser).IOS_VERSION === '8' && somePlayer.duration() === 0) {\n return true;\n }\n return false;\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 if (somePlayer === void 0) {\n somePlayer = player;\n }\n if (!somePlayer) {\n throw new Error('shouldPlayContentBehindAd requires a player as a param');\n } else if (!somePlayer.ads.settings.liveCuePoints) {\n return false;\n } else {\n return !(video_js__WEBPACK_IMPORTED_MODULE_0___default().browser).IS_IOS && !(video_js__WEBPACK_IMPORTED_MODULE_0___default().browser).IS_ANDROID && somePlayer.duration() === Infinity;\n }\n },\n // Return true if the ads plugin should save and restore snapshots of the\n // player state when moving into and out of ad mode.\n shouldTakeSnapshots: function shouldTakeSnapshots(somePlayer) {\n if (somePlayer === void 0) {\n somePlayer = player;\n }\n return !this.shouldPlayContentBehindAd(somePlayer) && !this.stitchedAds();\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 // 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 // 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 // Deprecated because the name was misleading. Use inAdBreak instead.\n isAdPlaying: function isAdPlaying() {\n return this._state.inAdBreak();\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 * 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 if (tech) {\n tech.removeAttribute('poster');\n }\n },\n debug: function debug() {\n if (this.settings.debug) {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n if (args.length === 1 && typeof args[0] === 'string') {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log('ADS: ' + args[0]);\n } else {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.apply((video_js__WEBPACK_IMPORTED_MODULE_0___default()), ['ADS:'].concat(args));\n }\n }\n },\n /**\n * Set or get the current ads error.\n *\n * @fires Player#vjsadserror\n *\n * @param {import('video.js/dist/types/media-error').ErrorMetadata|null} [err]\n * The error to be set. This can either be a string\n * of the error type, or it can be an object containing the\n * type, along with error metadata.\n * If nothing is passed in, this function will return the current error.\n * @param {string} err.errorType The error type.\n *\n * @return {Object|null|undefined}\n * The current ads error. The function will return undefined if the function\n * is used to set an error. It will return null if there is no error.\n */\n error: function error(err) {\n // If `err` doesn't exist, return the current error.\n if (err === undefined) {\n return this._error || null;\n }\n\n // If `err` is null or not a valid error, reset the ads error.\n if (err === null || !err.errorType) {\n this._error = null;\n return;\n }\n this._error = err;\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.error(\"An error with Ads occured. Type: \" + err.errorType + \".\");\n\n /**\n * @event Player#vjsadserror\n * @type {Event}\n */\n player.trigger({\n type: 'vjsadserror',\n error: this._error\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 if (player.ads.isContentResuming()) {\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 // 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 && !player.ads.stitchedAds()) {\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 // 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 // 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 // Event came from snapshot restore after an ad, use \"content\" prefix\n prefixEvent(this, 'content', event);\n } else {\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 // 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 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 if (src !== player.ads.contentSrc) {\n if (player.ads._seenInitialLoadstart) {\n player.trigger({\n type: 'contentchanged'\n });\n }\n player.trigger({\n type: 'contentupdate',\n oldValue: player.ads.contentSrc,\n newValue: src\n });\n player.ads.contentSrc = src;\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\nfunction _extends() {\n _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n return target;\n };\n return _extends.apply(this, arguments);\n}\nfunction _inheritsLoose(subClass, superClass) {\n subClass.prototype = Object.create(superClass.prototype);\n subClass.prototype.constructor = subClass;\n _setPrototypeOf(subClass, superClass);\n}\nfunction _setPrototypeOf(o, p) {\n _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n return _setPrototypeOf(o, p);\n}\n\n/**\n * Current tcfData returned from CMP\n * Updated on event listener rather than having to make an asyc\n * check within the macro resolver\n */\nvar tcData = {};\n\n/**\n * Sets up a proxy for the TCF API in an iframed player, if a parent frame\n * that has implemented the TCF API is detected\n * https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#is-there-a-sample-iframe-script-call-to-the-cmp-api\n */\nvar proxyTcfApi = function proxyTcfApi(_) {\n if (video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.isInFrame() && typeof (global_window__WEBPACK_IMPORTED_MODULE_1___default().__tcfapi) !== 'function') {\n var frame = (global_window__WEBPACK_IMPORTED_MODULE_1___default());\n var cmpFrame;\n var cmpCallbacks = {};\n while (frame) {\n try {\n if (frame.frames.__tcfapiLocator) {\n cmpFrame = frame;\n break;\n }\n } catch (ignore) {\n // empty\n }\n if (frame === (global_window__WEBPACK_IMPORTED_MODULE_1___default().top)) {\n break;\n }\n frame = frame.parent;\n }\n if (!cmpFrame) {\n return;\n }\n (global_window__WEBPACK_IMPORTED_MODULE_1___default().__tcfapi) = function (cmd, version, callback, arg) {\n var callId = Math.random() + '';\n var msg = {\n __tcfapiCall: {\n command: cmd,\n parameter: arg,\n version: version,\n callId: callId\n }\n };\n cmpCallbacks[callId] = callback;\n cmpFrame.postMessage(msg, '*');\n };\n global_window__WEBPACK_IMPORTED_MODULE_1___default().addEventListener('message', function (event) {\n var json = {};\n try {\n json = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;\n } catch (ignore) {\n // empty\n }\n var payload = json.__tcfapiReturn;\n if (payload) {\n if (typeof cmpCallbacks[payload.callId] === 'function') {\n cmpCallbacks[payload.callId](payload.returnValue, payload.success);\n cmpCallbacks[payload.callId] = null;\n }\n }\n }, false);\n }\n};\n\n/**\n * Sets up event listener for changes to consent data.\n */\nvar listenToTcf = function listenToTcf() {\n proxyTcfApi();\n if (typeof (global_window__WEBPACK_IMPORTED_MODULE_1___default().__tcfapi) === 'function') {\n global_window__WEBPACK_IMPORTED_MODULE_1___default().__tcfapi('addEventListener', 2, function (data, success) {\n if (success) {\n tcData = data;\n }\n });\n }\n};\n\nvar findUspApiLocatorWindow = function findUspApiLocatorWindow(windowObj) {\n var targetWindow = windowObj.parent;\n while (targetWindow !== windowObj.top) {\n try {\n if (targetWindow.frames && targetWindow.frames.__uspapiLocator) {\n return targetWindow;\n }\n } catch (ignore) {\n // do nothing\n }\n targetWindow = targetWindow.parent;\n }\n\n // Check for the __uspapiLocator frame in the top window\n try {\n if (windowObj.top.frames && windowObj.top.frames.__uspapiLocator) {\n return windowObj.top;\n }\n } catch (ignore) {\n // do nothing\n }\n\n // Return null if no __uspapiLocator frame is found in any window\n return null;\n};\nvar uspString = '';\nvar getCurrentUspString = function getCurrentUspString() {\n return uspString;\n};\n\n// Call the USP API to get the US Privacy String, either by invoking it directly or via postMessage() if inside an iframe.\n// In the former case the callback is synchronous, if the latter it is asynchronous, so to be safe it should always be\n// assumed to be asynchronous.\n// The window is passable as an argument for ease of testing\nvar obtainUsPrivacyString = function obtainUsPrivacyString(callback, windowObj) {\n if (windowObj === void 0) {\n windowObj = (global_window__WEBPACK_IMPORTED_MODULE_1___default());\n }\n if (windowObj.__uspapi) {\n windowObj.__uspapi('getUSPData', 1, function (uspData, success) {\n var privacyString = success ? uspData.uspString : null;\n uspString = privacyString;\n callback(privacyString);\n });\n } else {\n var targetWindow = findUspApiLocatorWindow(windowObj);\n\n // If no __uspapiLocator frame is found, execute the callback with a null privacy string\n if (!targetWindow) {\n callback(null);\n return;\n }\n var uniqueId = Math.random().toString(36).substring(2);\n var message = {\n __uspapiCall: {\n command: 'getUSPData',\n version: 1,\n callId: uniqueId\n }\n };\n var handleMessageEvent = function handleMessageEvent(event) {\n if (event && event.data && event.data.__uspapiReturn && event.data.__uspapiReturn.callId === uniqueId) {\n windowObj.removeEventListener('message', handleMessageEvent, false);\n var _event$data$__uspapiR = event.data.__uspapiReturn,\n returnValue = _event$data$__uspapiR.returnValue,\n success = _event$data$__uspapiR.success;\n var privacyString = success ? returnValue.uspString : null;\n uspString = privacyString;\n callback(privacyString);\n }\n };\n windowObj.addEventListener('message', handleMessageEvent, false);\n targetWindow.postMessage(message, '*');\n }\n};\n\nvar Error$1 = {\n AdsBeforePrerollError: 'ads-before-preroll-error',\n AdsPrerollError: 'ads-preroll-error',\n AdsMidrollError: 'ads-midroll-error',\n AdsPostrollError: 'ads-postroll-error',\n AdsMacroReplacementFailed: 'ads-macro-replacement-failed',\n AdsResumeContentFailed: 'ads-resume-content-failed'\n};\n\nvar uriEncodeIfNeeded = function uriEncodeIfNeeded(value, uriEncode) {\n return uriEncode ? encodeURIComponent(value) : 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 for (var i = 0; i < fieldNames.length; i++) {\n var tag = '{mediainfo.' + customFieldsName + '.' + fieldNames[i] + '}';\n macros[tag] = fields[fieldNames[i]];\n }\n }\n};\nvar getMediaInfoMacros = function getMediaInfoMacros(mediainfo, defaults) {\n var macros = {};\n ['description', 'tags', 'reference_id', 'ad_keys'].forEach(function (prop) {\n if (mediainfo && mediainfo[prop]) {\n macros[\"{mediainfo.\" + prop + \"}\"] = mediainfo[prop];\n } else if (defaults[\"{mediainfo.\" + prop + \"}\"]) {\n macros[\"{mediainfo.\" + prop + \"}\"] = defaults[\"{mediainfo.\" + prop + \"}\"];\n } else {\n macros[\"{mediainfo.\" + prop + \"}\"] = '';\n }\n });\n ['custom_fields', 'customFields'].forEach(function (customFieldProp) {\n customFields(mediainfo, macros, customFieldProp);\n });\n return macros;\n};\nvar getDefaultValues = function getDefaultValues(string) {\n var defaults = {};\n var modifiedString = string.replace(/{([^}=]+)=([^}]*)}/g, function (match, name, defaultVal) {\n defaults[\"{\" + name + \"}\"] = defaultVal;\n return \"{\" + name + \"}\";\n });\n return {\n defaults: defaults,\n modifiedString: modifiedString\n };\n};\nvar getStaticMacros = function getStaticMacros(player) {\n return {\n '{player.id}': player.options_['data-player'] || player.id_,\n '{player.height}': player.currentHeight(),\n '{player.width}': player.currentWidth(),\n '{player.heightInt}': Math.round(player.currentHeight()),\n '{player.widthInt}': Math.round(player.currentWidth()),\n '{player.autoplay}': player.autoplay() ? 1 : 0,\n '{player.muted}': player.muted() ? 1 : 0,\n '{player.language}': player.language() || '',\n '{mediainfo.id}': player.mediainfo ? player.mediainfo.id : '',\n '{mediainfo.name}': player.mediainfo ? player.mediainfo.name : '',\n '{mediainfo.duration}': player.mediainfo ? player.mediainfo.duration : '',\n '{player.duration}': player.duration(),\n '{player.durationInt}': Math.round(player.duration()),\n '{player.live}': player.duration() === Infinity ? 1 : 0,\n '{player.pageUrl}': video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.isInFrame() ? (global_document__WEBPACK_IMPORTED_MODULE_2___default().referrer) : (global_window__WEBPACK_IMPORTED_MODULE_1___default().location).href,\n '{playlistinfo.id}': player.playlistinfo ? player.playlistinfo.id : '',\n '{playlistinfo.name}': player.playlistinfo ? player.playlistinfo.name : '',\n '{timestamp}': new Date().getTime(),\n '{document.referrer}': (global_document__WEBPACK_IMPORTED_MODULE_2___default().referrer),\n '{window.location.href}': (global_window__WEBPACK_IMPORTED_MODULE_1___default().location).href,\n '{random}': Math.floor(Math.random() * 1000000000000)\n };\n};\nvar getTcfMacros = function getTcfMacros(tcDataObj) {\n var tcfMacros = {};\n Object.keys(tcDataObj).forEach(function (key) {\n tcfMacros[\"{tcf.\" + key + \"}\"] = tcDataObj[key];\n });\n tcfMacros['{tcf.gdprAppliesInt}'] = tcDataObj.gdprApplies ? 1 : 0;\n return tcfMacros;\n};\nvar getUspMacros = function getUspMacros() {\n return {\n '{usp.uspString}': getCurrentUspString()\n };\n};\n\n// This extracts and evaluates variables from the `window` object for macro replacement. While replaceMacros() handles generic macro name\n// overriding for other macro types, this function also needs to reference the overrides in order to map custom macro names in the string\n// to their corresponding default pageVariable names, so they can be evaluated on the `window` and stored for later replacement in replaceMacros().\nvar getPageVariableMacros = function getPageVariableMacros(string, defaults, macroNameOverrides) {\n var pageVarRegex = new RegExp('{pageVariable\\\\.([^}]+)}', 'g');\n var pageVariablesMacros = {};\n\n // Aggregate any default pageVariable macros found in the string with any pageVariable macros that have custom names specified in\n // macroNameOverrides.\n var pageVariables = (string.match(pageVarRegex) || []).concat(Object.keys(macroNameOverrides).filter(function (macroName) {\n return pageVarRegex.test(macroName) && string.includes(macroNameOverrides[macroName]);\n }));\n if (!pageVariables) {\n return;\n }\n pageVariables.forEach(function (pageVar) {\n var key = pageVar;\n var name = pageVar.slice(14, -1);\n var names = name.split('.');\n var context = (global_window__WEBPACK_IMPORTED_MODULE_1___default());\n var value;\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 if (typeof context === 'undefined') {\n break;\n }\n }\n }\n var type = typeof value;\n\n // Only allow certain types of values. Anything else is probably a mistake.\n if (value === null) {\n pageVariablesMacros[key] = 'null';\n } else if (value === undefined) {\n if (defaults[key]) {\n pageVariablesMacros[key] = defaults[key];\n } else {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn(\"Page variable \\\"\" + name + \"\\\" not found\");\n pageVariablesMacros[key] = '';\n }\n } else if (type !== 'string' && type !== 'number' && type !== 'boolean') {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn(\"Page variable \\\"\" + name + \"\\\" is not a supported type\");\n pageVariablesMacros[key] = '';\n } else {\n pageVariablesMacros[key] = value;\n }\n });\n return pageVariablesMacros;\n};\nvar replaceMacros = function replaceMacros(string, macros, uriEncode, overrides, player) {\n if (overrides === void 0) {\n overrides = {};\n }\n for (var macroName in macros) {\n // The resolvedMacroName is the macro as it is expected to appear in the actual string, or regex if it has been provided.\n var resolvedMacroName = overrides.hasOwnProperty(macroName) ? overrides[macroName] : macroName;\n if (resolvedMacroName.startsWith('r:')) {\n try {\n var regex = new RegExp(resolvedMacroName.slice(2), 'g');\n string = string.replace(regex, uriEncodeIfNeeded(macros[macroName], uriEncode));\n } catch (error) {\n player.ads.error({\n errorType: Error$1.AdsMacroReplacementFailed,\n macro: macroName,\n error: error\n });\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn(\"Unable to replace macro with regex \\\"\" + resolvedMacroName + \"\\\". The provided regex may be invalid.\");\n }\n } else {\n string = string.split(resolvedMacroName).join(uriEncodeIfNeeded(macros[macroName], uriEncode));\n }\n }\n return string;\n};\n\n/**\n *\n * @param {string} string\n * Any string with macros to be replaced\n * @param {boolean} uriEncode\n * A Boolean value indicating whether the macros should be replaced with URI-encoded values\n * @param {object} customMacros\n * An object with custom macros and values to map them to. For example: {'{five}': 5}\n * @param {boolean} customMacros.disableDefaultMacros\n * A boolean indicating whether replacement of default macros should be forgone in favor of only customMacros\n * @param {object} customMacros.macroNameOverrides\n * An object that specifies custom names for default macros, following the following format:\n * // {'{default-macro-name}': '{new-macro-name}'}\n * {'{player.id}': '{{PLAYER_ID}}', ...}\n * @returns {string}\n * The provided string with all macros replaced. For example: adMacroReplacement('{player.id}') returns a string of the player id\n */\nfunction adMacroReplacement(string, uriEncode, customMacros) {\n if (uriEncode === void 0) {\n uriEncode = false;\n }\n if (customMacros === void 0) {\n customMacros = {};\n }\n var disableDefaultMacros = customMacros.disableDefaultMacros || false;\n var macroNameOverrides = customMacros.macroNameOverrides || {};\n\n // Remove special properties from customMacros\n delete customMacros.disableDefaultMacros;\n delete customMacros.macroNameOverrides;\n var macros = customMacros;\n if (disableDefaultMacros) {\n return replaceMacros(string, macros, uriEncode, macroNameOverrides);\n }\n\n // Get macros with defaults e.g. {x=y}, store the values in `defaults` and replace with standard macros in the string\n var _getDefaultValues = getDefaultValues(string),\n defaults = _getDefaultValues.defaults,\n modifiedString = _getDefaultValues.modifiedString;\n string = modifiedString;\n\n // Get all macro values\n _extends(macros, getStaticMacros(this), getMediaInfoMacros(this.mediainfo, defaults), getTcfMacros(tcData), getUspMacros(), getPageVariableMacros(string, defaults, macroNameOverrides));\n\n // Perform macro replacement\n string = replaceMacros(string, macros, uriEncode, macroNameOverrides, this);\n\n // Replace any remaining default values that have not already been replaced. This includes mediainfo custom fields.\n for (var macro in defaults) {\n string = string.replace(macro, defaults[macro]);\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**/\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 video_js__WEBPACK_IMPORTED_MODULE_0___default().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 video_js__WEBPACK_IMPORTED_MODULE_0___default().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 video_js__WEBPACK_IMPORTED_MODULE_0___default().log('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 // this function is in the player's context\n\n if (this.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 (!this.paused()) {\n this.ads.debug('Playback was canceled by cancelContentPlay');\n this.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 this.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 = (video_js__WEBPACK_IMPORTED_MODULE_0___default());\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 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 return false;\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, playPromise) {\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 // Safari issues a pause event when autoplay is blocked but other browsers\n // do not, so we send a pause for consistency in those cases. This keeps the\n // play button in the correct state if play is rejected.\n } else if (playPromise && playPromise.catch) {\n playPromise.catch(function (e) {\n if (e.name === 'NotAllowedError' && !(video_js__WEBPACK_IMPORTED_MODULE_0___default().browser).IS_SAFARI) {\n player.trigger('pause');\n }\n });\n }\n }\n };\n};\nobj.testHook = function (testVjs) {\n videojsReference = testVjs;\n};\n\nvar playMiddleware = obj.playMiddleware,\n isMiddlewareMediatorSupported = obj.isMiddlewareMediatorSupported;\n\n/**\n * Whether or not this copy of Video.js has the ads plugin.\n *\n * @return {boolean}\n * If `true`, has the plugin. `false` otherwise.\n */\nvar hasAdsPlugin = function hasAdsPlugin() {\n // Video.js 6 and 7 have a getPlugin method.\n if ((video_js__WEBPACK_IMPORTED_MODULE_0___default().getPlugin)) {\n return Boolean(video_js__WEBPACK_IMPORTED_MODULE_0___default().getPlugin('ads'));\n }\n\n // Video.js 5 does not have a getPlugin method, so check the player prototype.\n var Player = video_js__WEBPACK_IMPORTED_MODULE_0___default().getComponent('Player');\n return Boolean(Player && Player.prototype.ads);\n};\n\n/**\n * Register contrib-ads with Video.js, but provide protection for duplicate\n * copies of the plugin. This could happen if, for example, a stitched ads\n * plugin and a client-side ads plugin are included simultaneously with their\n * own copies of contrib-ads.\n *\n * If contrib-ads detects a pre-existing duplicate, it will not register\n * itself.\n *\n * Ad plugins using contrib-ads and anticipating that this could come into\n * effect should verify that the contrib-ads they are using is of a compatible\n * version.\n *\n * @param {Function} contribAdsPlugin\n * The plugin function.\n *\n * @return {boolean}\n * When `true`, the plugin was registered. When `false`, the plugin\n * was not registered.\n */\nfunction register(contribAdsPlugin) {\n // If the ads plugin already exists, do not overwrite it.\n if (hasAdsPlugin((video_js__WEBPACK_IMPORTED_MODULE_0___default()))) {\n return false;\n }\n\n // Cross-compatibility with Video.js 6/7 and 5.\n var registerPlugin = (video_js__WEBPACK_IMPORTED_MODULE_0___default().registerPlugin) || (video_js__WEBPACK_IMPORTED_MODULE_0___default().plugin);\n\n // Register this plugin with Video.js.\n registerPlugin('ads', contribAdsPlugin);\n\n // Register the play middleware with Video.js on script execution,\n // to avoid a new playMiddleware factory being added for each player.\n // The `usingContribAdsMiddleware_` flag is used to ensure that we only ever\n // register the middleware once - despite the ability to de-register and\n // re-register the plugin itself.\n if (isMiddlewareMediatorSupported() && !(video_js__WEBPACK_IMPORTED_MODULE_0___default().usingContribAdsMiddleware_)) {\n // Register the play middleware\n video_js__WEBPACK_IMPORTED_MODULE_0___default().use('*', playMiddleware);\n (video_js__WEBPACK_IMPORTED_MODULE_0___default().usingContribAdsMiddleware_) = true;\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.debug('Play middleware has been registered with videojs');\n }\n return true;\n}\n\nvar OUTSTREAM_VIDEO = {\n src: 'data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAAxJtZGF03ABMYXZjNjEuMy4xMDAAQiAIwRg4AAACrgYF//+q3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2NCByMzEwOCAzMWUxOWY5IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAyMyAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTcgbG9va2FoZWFkX3RocmVhZHM9MSBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2NvbXBhdD0wIGNvbnN0cmFpbmVkX2ludHJhPTAgYmZyYW1lcz0zIGJfcHlyYW1pZD0yIGJfYWRhcHQ9MSBiX2JpYXM9MCBkaXJlY3Q9MSB3ZWlnaHRiPTEgb3Blbl9nb3A9MCB3ZWlnaHRwPTIga2V5aW50PTI1MCBrZXlpbnRfbWluPTI1IHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAAn//71sXwKaunqigzoMi7hlyTJrrYi4m0AwABFxzcqWKGahTaoBcQAAMWK4AlcFlIICBeldSEQBGCMHAAABVNtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAIgABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAACQXRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAIgAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAABQAAAAPAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAACIAAAAAAAEAAAAAAbltZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAADwAAAACAFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAFkbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABJHN0YmwAAADAc3RzZAAAAAAAAAABAAAAsGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAABQADwAEgAAABIAAAAAAAAAAEUTGF2YzYxLjMuMTAwIGxpYngyNjQAAAAAAAAAAAAAAAAY//8AAAA2YXZjQwFkAA3/4QAZZ2QADazZQUH7ARAAAAMAEAAAAwPA8UKZYAEABmjr48siwP34+AAAAAAQcGFzcAAAAAEAAAABAAAAFGJ0cnQAAAAAAALAEAACwBAAAAAYc3R0cwAAAAAAAAABAAAAAQAAAgAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAFHN0c3oAAAAAAAAC7wAAAAEAAAAUc3RjbwAAAAAAAAABAAAARQAAAj10cmFrAAAAXHRraGQAAAADAAAAAAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAEBAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAAXAAAEAAABAAAAAAG1bWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAACsRAAACABVxAAAAAAALWhkbHIAAAAAAAAAAHNvdW4AAAAAAAAAAAAAAABTb3VuZEhhbmRsZXIAAAABYG1pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABJHN0YmwAAAB+c3RzZAAAAAAAAAABAAAAbm1wNGEAAAAAAAAAAQAAAAAAAAAAAAIAEAAAAACsRAAAAAAANmVzZHMAAAAAA4CAgCUAAgAEgICAF0AVAAAAAAH0AAAAEisFgICABRIQVuUABoCAgAECAAAAFGJ0cnQAAAAAAAH0AAAAEisAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAAVAAAABgAAABhzdGNvAAAAAAAAAAIAAAAwAAADNAAAABpzZ3BkAQAAAHJvbGwAAAACAAAAAf//AAAAHHNiZ3AAAAAAcm9sbAAAAAEAAAACAAAAAQAAAGF1ZHRhAAAAWW1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAALGlsc3QAAAAkqXRvbwAAABxkYXRhAAAAAQAAAABMYXZmNjEuMS4xMDA=',\n type: 'video/mp4'\n};\n\nvar States = /*#__PURE__*/function () {\n function States() {}\n States.getState = function getState(name) {\n if (!name) {\n return;\n }\n if (States.states_ && States.states_[name]) {\n return States.states_[name];\n }\n };\n States.registerState = function registerState(name, StateToRegister) {\n if (typeof name !== 'string' || !name) {\n throw new Error(\"Illegal state name, \\\"\" + name + \"\\\"; must be a non-empty string.\");\n }\n if (!States.states_) {\n States.states_ = {};\n }\n States.states_[name] = StateToRegister;\n return StateToRegister;\n };\n return States;\n}();\n\nvar State = /*#__PURE__*/function () {\n State._getName = function _getName() {\n return 'Anonymous State';\n };\n function State(player) {\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 var _proto = State.prototype;\n _proto.transitionTo = function transitionTo(NewState) {\n var player = this.player;\n\n // Since State is an abstract class, this will refer to\n // the state that is extending this class\n this.cleanup(player);\n var newState = new NewState(player);\n player.ads._state = newState;\n player.ads.debug(this.constructor._getName() + ' -> ' + newState.constructor._getName());\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\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 _proto.init = function init() {}\n\n /*\n * Implemented by subclasses to provide cleanup logic when transitioning\n * to a new state.\n */;\n _proto.cleanup = function cleanup() {}\n\n /*\n * Default event handlers. Different states can override these to provide behaviors.\n */;\n _proto.onPlay = function onPlay() {};\n _proto.onPlaying = function onPlaying() {};\n _proto.onEnded = function onEnded() {};\n _proto.onAdEnded = function onAdEnded() {};\n _proto.onAdsReady = function onAdsReady() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected adsready event');\n };\n _proto.onAdsError = function onAdsError() {};\n _proto.onAdsCanceled = function onAdsCanceled() {};\n _proto.onAdTimeout = function onAdTimeout() {};\n _proto.onAdStarted = function onAdStarted() {};\n _proto.onAdSkipped = function onAdSkipped() {};\n _proto.onContentChanged = function onContentChanged() {};\n _proto.onContentResumed = function onContentResumed() {};\n _proto.onReadyForPostroll = function onReadyForPostroll() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected readyforpostroll event');\n };\n _proto.onNoPreroll = function onNoPreroll() {};\n _proto.onNoPostroll = function onNoPostroll() {}\n\n /*\n * Method handlers. Different states can override these to provide behaviors.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected startLinearAdMode invocation ' + '(State via ' + this.constructor._getName() + ')');\n };\n _proto.endLinearAdMode = function endLinearAdMode() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected endLinearAdMode invocation ' + '(State via ' + this.constructor._getName() + ')');\n };\n _proto.skipLinearAdMode = function skipLinearAdMode() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().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 _proto.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 _proto.isWaitingForAdBreak = function isWaitingForAdBreak() {\n return false;\n }\n\n /*\n * Overridden by Preroll, Midroll, and Postroll.\n */;\n _proto.isContentResuming = function isContentResuming() {\n return false;\n };\n _proto.inAdBreak = function inAdBreak() {\n return false;\n }\n\n /*\n * Invoke event handler methods when events come in.\n */;\n _proto.handleEvent = function handleEvent(type) {\n var player = this.player;\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 === 'ads-ad-skipped') {\n this.onAdSkipped(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 } else if (type === 'adended') {\n this.onAdEnded(player);\n }\n };\n return State;\n}();\nStates.registerState('State', State);\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 */\nvar AdState = /*#__PURE__*/function (_State) {\n _inheritsLoose(AdState, _State);\n function AdState(player) {\n var _this;\n _this = _State.call(this, player) || this;\n _this.contentResuming = false;\n _this.waitingForAdBreak = false;\n return _this;\n }\n\n /*\n * Overrides State.isAdState\n */\n var _proto = AdState.prototype;\n _proto.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 _proto.onPlaying = function onPlaying() {\n var ContentPlayback = States.getState('ContentPlayback');\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 _proto.onContentResumed = function onContentResumed() {\n var ContentPlayback = States.getState('ContentPlayback');\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 _proto.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 _proto.isContentResuming = function isContentResuming() {\n return this.contentResuming;\n }\n\n /*\n * Allows you to check if an ad break is in progress.\n */;\n _proto.inAdBreak = function inAdBreak() {\n return this.player.ads._inLinearAdMode === true;\n };\n return AdState;\n}(State);\nStates.registerState('AdState', AdState);\n\nvar ContentState = /*#__PURE__*/function (_State) {\n _inheritsLoose(ContentState, _State);\n function ContentState() {\n return _State.apply(this, arguments) || this;\n }\n var _proto = ContentState.prototype;\n /*\n * Overrides State.isAdState\n */\n _proto.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 _proto.onContentChanged = function onContentChanged(player) {\n var BeforePreroll = States.getState('BeforePreroll');\n var Preroll = States.getState('Preroll');\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 return ContentState;\n}(State);\nStates.registerState('ContentState', ContentState);\n\nvar ContentState$1 = States.getState('ContentState');\nvar AdsDone = /*#__PURE__*/function (_ContentState) {\n _inheritsLoose(AdsDone, _ContentState);\n function AdsDone() {\n return _ContentState.apply(this, arguments) || this;\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 var _proto = AdsDone.prototype;\n _proto.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 _proto.startLinearAdMode = function startLinearAdMode() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected startLinearAdMode invocation (AdsDone)');\n };\n return AdsDone;\n}(ContentState$1);\nStates.registerState('AdsDone', AdsDone);\n\n/*\nThe snapshot feature is responsible for saving the player state before an ad, then\nrestoring the player state after an ad.\n*/\nvar tryToResumeTimeout_;\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;\n if ((video_js__WEBPACK_IMPORTED_MODULE_0___default().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 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 sources: player.currentSources(),\n src: player.tech_.src(),\n currentTime: currentTime,\n type: player.currentType()\n };\n if (tech) {\n snapshotObject.style = tech.getAttribute('style');\n }\n for (var i = 0; i < tracks.length; i++) {\n var track = tracks[i];\n suppressedTracks.push({\n track: track,\n mode: track.mode\n });\n track.mode = 'disabled';\n }\n snapshotObject.suppressedTracks = suppressedTracks;\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, callback) {\n var snapshotObject = player.ads.snapshot;\n if (callback === undefined) {\n callback = function callback() {};\n }\n if (player.ads.disableNextSnapshotRestore === true) {\n player.ads.disableNextSnapshotRestore = false;\n delete player.ads.snapshot;\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 var suppressedTracks = snapshotObject.suppressedTracks;\n var trackSnapshot;\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;\n\n // Live video on iOS has special logic to try to seek to the right place after\n // an ad.\n if ((video_js__WEBPACK_IMPORTED_MODULE_0___default().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 // iOS live play after restore if player was paused (would not be paused if\n // ad played muted behind ad)\n if (player.paused()) {\n var playPromise = player.play();\n if (playPromise && playPromise.catch) {\n playPromise.catch(function (error) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Play promise rejected in IOS snapshot resume', error);\n });\n }\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 if (_playPromise && _playPromise.catch) {\n _playPromise.catch(function (error) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().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 // 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 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 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 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 player.ads.error({\n errorType: Error$1.AdsResumeContentFailed,\n error: e\n });\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Failed to resume the content after an advertisement', e);\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', function () {\n delete player.ads.snapshot;\n callback();\n });\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 // This is done directly on the html5 tech because if the integration has set\n // normalizeAutoplay to true, the async play request via autoplay -> manualAutoplay_\n // causes a visible skipback of the content after the ad break\n if ((video_js__WEBPACK_IMPORTED_MODULE_0___default().browser).IS_IOS && !player.autoplay() && typeof player.techCall_ === 'function') {\n player.techCall_('setAutoplay', 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(snapshotObject.sources);\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 if (playPromise && playPromise.catch) {\n playPromise.catch(function (error) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Play promise rejected in snapshot restore', error);\n });\n }\n }\n\n // snapshot restore is complete\n delete player.ads.snapshot;\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 */\nfunction start(player) {\n player.ads.debug('Starting ad break');\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.shouldTakeSnapshots()) {\n player.ads.snapshot = getPlayerSnapshot(player);\n }\n\n // Mute the player behind the ad\n if (player.ads.shouldPlayContentBehindAd(player) && !player.ads.settings.stitchedAds) {\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 // Ensure ads are watched at x1 speed and speed cannot be changed for the duration of the ad\n player.ads.preAdPlaybackRate_ = player.playbackRate();\n player.playbackRate(1);\n if (player.controlBar && player.controlBar.playbackRateMenuButton && player.controlBar.playbackRateMenuButton.playbackRateSupported && !player.controlBar.playbackRateMenuButton.hasClass('vjs-hidden')) {\n player.controlBar.playbackRateMenuButton.hide();\n player.ads.showPlaybackMenuOnAdEnd_ = true;\n } else {\n player.ads.showPlaybackMenuOnAdEnd_ = false;\n }\n}\nfunction end(player, callback) {\n player.ads.debug('Ending ad break');\n if (callback === undefined) {\n callback = function callback() {};\n }\n player.ads.adType = null;\n player.ads._inLinearAdMode = false;\n\n // Signals the end of the ad break to anyone listening.\n player.trigger('adend');\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.shouldTakeSnapshots()) {\n restorePlayerSnapshot(player, callback);\n\n // Reset the volume to pre-ad levels\n } else {\n if (player.ads.preAdVolume_) {\n player.volume(player.ads.preAdVolume_);\n }\n callback();\n }\n\n // Reset playback\n player.playbackRate(player.ads.preAdPlaybackRate_);\n if (player.ads.showPlaybackMenuOnAdEnd_) {\n player.controlBar.playbackRateMenuButton.show();\n }\n}\nvar obj$1 = {\n start: start,\n end: end\n};\n\nvar AdState$1 = States.getState('AdState');\n\n/*\n * This state encapsulates waiting for prerolls, preroll playback, and\n * content restoration after a preroll.\n */\nvar Preroll = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(Preroll, _AdState);\n function Preroll() {\n return _AdState.apply(this, arguments) || this;\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 var _proto = Preroll.prototype;\n _proto.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 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 _proto.onAdsReady = function onAdsReady(player) {\n if (!player.ads.inAdBreak()) {\n player.ads.debug('Received adsready event (Preroll)');\n this.handleAdsReady();\n } else {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected adsready event (Preroll)');\n }\n }\n\n /*\n * Ad plugin is ready. Let's get started on this preroll.\n */;\n _proto.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 _proto.afterLoadStart = function afterLoadStart(callback) {\n var player = this.player;\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 _proto.noPreroll = function noPreroll() {\n var _this = this;\n this.afterLoadStart(function () {\n _this.player.ads.debug('Skipping prerolls due to nopreroll event (Preroll)');\n _this.resumeAfterNoPreroll(_this.player);\n });\n }\n\n /*\n * Fire the readyforpreroll event. If loadstart hasn't happened yet,\n * wait until loadstart first.\n */;\n _proto.readyForPreroll = function readyForPreroll() {\n var player = this.player;\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 _proto.onAdsCanceled = function onAdsCanceled(player) {\n var _this2 = this;\n player.ads.debug('adscanceled (Preroll)');\n this.afterLoadStart(function () {\n _this2.resumeAfterNoPreroll(player);\n });\n }\n\n /*\n * An ad error occured. Play content instead.\n */;\n _proto.onAdsError = function onAdsError(player) {\n var _this3 = this;\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log('adserror (Preroll)');\n player.ads.error({\n errorType: Error$1.AdsPrerollError\n });\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 (this.inAdBreak()) {\n player.ads.endLinearAdMode();\n } else {\n this.afterLoadStart(function () {\n _this3.resumeAfterNoPreroll(player);\n });\n }\n }\n /*\n * Ad plugin invoked startLinearAdMode, the ad break starts now.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n var player = this.player;\n if (this.adsReady && !player.ads.inAdBreak() && !this.isContentResuming()) {\n this.clearTimeout(player);\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 video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected startLinearAdMode invocation (Preroll)');\n }\n }\n\n /*\n * An ad has actually started playing.\n * Remove the loading spinner.\n */;\n _proto.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 _proto.endLinearAdMode = function endLinearAdMode() {\n var player = this.player;\n if (this.inAdBreak()) {\n player.removeClass('vjs-ad-loading');\n player.addClass('vjs-ad-content-resuming');\n this.contentResuming = true;\n obj$1.end(player);\n }\n }\n\n /*\n * Ad skipped by ad plugin. Play content instead.\n */;\n _proto.skipLinearAdMode = function skipLinearAdMode() {\n var _this4 = this;\n var player = this.player;\n if (player.ads.inAdBreak() || this.isContentResuming()) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected skipLinearAdMode invocation');\n } else {\n this.afterLoadStart(function () {\n player.trigger('adskip');\n player.ads.debug('skipLinearAdMode (Preroll)');\n _this4.resumeAfterNoPreroll(player);\n });\n }\n }\n\n /*\n * Prerolls took too long! Play content instead.\n */;\n _proto.onAdTimeout = function onAdTimeout(player) {\n var _this5 = this;\n this.afterLoadStart(function () {\n player.ads.debug('adtimeout (Preroll)');\n _this5.resumeAfterNoPreroll(player);\n });\n }\n\n /*\n * Check if nopreroll event was too late before handling it.\n */;\n _proto.onNoPreroll = function onNoPreroll(player) {\n if (player.ads.inAdBreak() || this.isContentResuming()) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected nopreroll event (Preroll)');\n } else {\n this.noPreroll();\n }\n };\n _proto.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 this.cleanupPartial(player);\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.ads._playRequested || player.ads._pausedOnContentupdate) {\n if (player.paused()) {\n player.ads.debug('resumeAfterNoPreroll: attempting to resume playback (Preroll)');\n var playPromise = player.play();\n if (playPromise && playPromise.then) {\n playPromise.then(null, function (e) {});\n }\n } else {\n player.ads.debug('resumeAfterNoPreroll: already playing (Preroll)');\n player.trigger('play');\n player.trigger('playing');\n }\n }\n }\n\n /*\n * Cleanup timeouts and spinner.\n */;\n _proto.cleanup = function cleanup(player) {\n if (!player.ads._hasThereBeenALoadStartDuringPlayerLife) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Leaving Preroll state before loadstart event can cause issues.');\n }\n this.cleanupPartial(player);\n }\n\n /*\n * Performs cleanup tasks without depending on a state transition. This is\n * used mainly in cases where a preroll failed.\n */;\n _proto.cleanupPartial = function cleanupPartial(player) {\n player.removeClass('vjs-ad-loading');\n player.removeClass('vjs-ad-content-resuming');\n this.clearTimeout(player);\n }\n\n /*\n * Clear the preroll timeout and nulls out the pointer.\n */;\n _proto.clearTimeout = function clearTimeout(player) {\n player.clearTimeout(this._timeout);\n this._timeout = null;\n };\n return Preroll;\n}(AdState$1);\nStates.registerState('Preroll', Preroll);\n\nvar ContentState$2 = States.getState('ContentState');\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 */\nvar BeforePreroll = /*#__PURE__*/function (_ContentState) {\n _inheritsLoose(BeforePreroll, _ContentState);\n function BeforePreroll() {\n return _ContentState.apply(this, arguments) || this;\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 var _proto = BeforePreroll.prototype;\n _proto.init = function init(player) {\n this.adsReady = false;\n this.shouldResumeToContent = false;\n\n // Content playback should be blocked by callPlay() middleware if the allowVjsAutoplay\n // option hasn't been provided and autoplay is not desired.\n player.ads._shouldBlockPlay = player.ads.settings.allowVjsAutoplay ? !player.autoplay() : 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 _proto.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 _proto.onPlay = function onPlay(player) {\n var Preroll = States.getState('Preroll');\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 _proto.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 _proto.onAdsError = function onAdsError() {\n this.player.ads.debug('adserror (BeforePreroll)');\n this.player.ads.error({\n errorType: Error$1.AdsBeforePrerollError\n });\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 _proto.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 _proto.skipLinearAdMode = function skipLinearAdMode() {\n var player = this.player;\n player.trigger('adskip');\n player.ads.debug('skipLinearAdMode (BeforePreroll)');\n this.shouldResumeToContent = true;\n };\n _proto.onContentChanged = function onContentChanged() {\n this.init(this.player);\n };\n return BeforePreroll;\n}(ContentState$2);\nStates.registerState('BeforePreroll', BeforePreroll);\n\nvar AdState$2 = States.getState('AdState');\nvar Midroll = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(Midroll, _AdState);\n function Midroll() {\n return _AdState.apply(this, arguments) || this;\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 var _proto = Midroll.prototype;\n _proto.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 _proto.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n }\n\n /*\n * Midroll break is done.\n */;\n _proto.endLinearAdMode = function endLinearAdMode() {\n var player = this.player;\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 _proto.onAdsError = function onAdsError(player) {\n player.ads.error({\n errorType: Error$1.AdsMidrollError\n });\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 (this.inAdBreak()) {\n player.ads.endLinearAdMode();\n }\n }\n\n /*\n * Cleanup CSS classes.\n */;\n _proto.cleanup = function cleanup(player) {\n player.removeClass('vjs-ad-loading');\n player.removeClass('vjs-ad-content-resuming');\n };\n return Midroll;\n}(AdState$2);\nStates.registerState('Midroll', Midroll);\n\nvar AdState$3 = States.getState('AdState');\nvar Postroll = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(Postroll, _AdState);\n function Postroll() {\n return _AdState.apply(this, arguments) || this;\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 var _proto = Postroll.prototype;\n _proto.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 if (typeof player.ads.settings.postrollTimeout === 'number') {\n timeout = player.ads.settings.postrollTimeout;\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 var AdsDone = States.getState('AdsDone');\n this.transitionTo(AdsDone);\n }\n }\n\n /*\n * Start the postroll if it's not too late.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n var player = this.player;\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 video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected startLinearAdMode invocation (Postroll)');\n }\n }\n\n /*\n * An ad has actually started playing.\n * Remove the loading spinner.\n */;\n _proto.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n }\n\n /*\n * Ending a postroll triggers the ended event.\n */;\n _proto.endLinearAdMode = function endLinearAdMode() {\n var _this = this;\n var player = this.player;\n var AdsDone = States.getState('AdsDone');\n if (this.inAdBreak()) {\n player.removeClass('vjs-ad-loading');\n this.resumeContent(player);\n obj$1.end(player, function () {\n _this.transitionTo(AdsDone);\n });\n }\n }\n\n /*\n * Postroll skipped, time to clean up.\n */;\n _proto.skipLinearAdMode = function skipLinearAdMode() {\n var player = this.player;\n if (player.ads.inAdBreak() || this.isContentResuming()) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().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 _proto.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 _proto.onAdsError = function onAdsError(player) {\n player.ads.debug('Postroll abort (adserror)');\n player.ads.error({\n errorType: Error$1.AdsPostrollError\n });\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 _proto.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 var BeforePreroll = States.getState('BeforePreroll');\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 var Preroll = States.getState('Preroll');\n this.transitionTo(Preroll);\n }\n }\n\n /*\n * Wrap up if there is no postroll.\n */;\n _proto.onNoPostroll = function onNoPostroll(player) {\n if (!this.isContentResuming() && !this.inAdBreak()) {\n this.abort(player);\n } else {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected nopostroll event (Postroll)');\n }\n };\n _proto.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 _proto.abort = function abort(player) {\n var AdsDone = States.getState('AdsDone');\n this.resumeContent(player);\n player.removeClass('vjs-ad-loading');\n this.transitionTo(AdsDone);\n }\n\n /*\n * Cleanup timeouts and state.\n */;\n _proto.cleanup = function cleanup(player) {\n player.removeClass('vjs-ad-content-resuming');\n player.clearTimeout(this._postrollTimeout);\n player.ads._contentEnding = false;\n };\n return Postroll;\n}(AdState$3);\nStates.registerState('Postroll', Postroll);\n\nvar ContentState$3 = States.getState('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 */\nvar ContentPlayback = /*#__PURE__*/function (_ContentState) {\n _inheritsLoose(ContentPlayback, _ContentState);\n function ContentPlayback() {\n return _ContentState.apply(this, arguments) || this;\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 var _proto = ContentPlayback.prototype;\n _proto.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 _proto.onAdsReady = function onAdsReady(player) {\n player.ads.debug('Received adsready event (ContentPlayback)');\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 _proto.onReadyForPostroll = function onReadyForPostroll(player) {\n var Postroll = States.getState('Postroll');\n player.ads.debug('Received readyforpostroll event');\n this.transitionTo(Postroll);\n }\n\n /*\n * This is how midrolls start.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n var Midroll = States.getState('Midroll');\n this.transitionTo(Midroll);\n };\n return ContentPlayback;\n}(ContentState$3);\nStates.registerState('ContentPlayback', ContentPlayback);\n\nvar ContentState$4 = States.getState('ContentState');\n\n/*\n * This state represents content playback when stitched ads are in play.\n */\nvar StitchedContentPlayback = /*#__PURE__*/function (_ContentState) {\n _inheritsLoose(StitchedContentPlayback, _ContentState);\n function StitchedContentPlayback() {\n return _ContentState.apply(this, arguments) || this;\n }\n /*\n * Allows state name to be logged even after minification.\n */\n StitchedContentPlayback._getName = function _getName() {\n return 'StitchedContentPlayback';\n }\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */;\n var _proto = StitchedContentPlayback.prototype;\n _proto.init = function init() {\n // Don't block calls to play in stitched ad players, ever.\n this.player.ads._shouldBlockPlay = false;\n }\n\n /*\n * Source change does not do anything for stitched ad players.\n * contentchanged does not fire during ad breaks, so we don't need to\n * worry about that.\n */;\n _proto.onContentChanged = function onContentChanged() {\n this.player.ads.debug(\"Received contentchanged event (\" + this.constructor._getName() + \")\");\n }\n\n /*\n * This is how stitched ads start.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n var StitchedAdRoll = States.getState('StitchedAdRoll');\n this.transitionTo(StitchedAdRoll);\n };\n return StitchedContentPlayback;\n}(ContentState$4);\nStates.registerState('StitchedContentPlayback', StitchedContentPlayback);\n\nvar AdState$4 = States.getState('AdState');\nvar StitchedAdRoll = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(StitchedAdRoll, _AdState);\n function StitchedAdRoll() {\n return _AdState.apply(this, arguments) || this;\n }\n /*\n * Allows state name to be logged even after minification.\n */\n StitchedAdRoll._getName = function _getName() {\n return 'StitchedAdRoll';\n }\n\n /*\n * StitchedAdRoll breaks happen when the ad plugin calls startLinearAdMode,\n * which can happen at any time during content playback.\n */;\n var _proto = StitchedAdRoll.prototype;\n _proto.init = function init() {\n this.waitingForAdBreak = false;\n this.contentResuming = false;\n this.player.ads.adType = 'stitched';\n obj$1.start(this.player);\n }\n\n /*\n * For stitched ads, there is no \"content resuming\" scenario, so a \"playing\"\n * event is not relevant.\n */;\n _proto.onPlaying = function onPlaying() {}\n\n /*\n * For stitched ads, there is no \"content resuming\" scenario, so a\n * \"contentresumed\" event is not relevant.\n */;\n _proto.onContentResumed = function onContentResumed() {}\n\n /*\n * When we see an \"adended\" event, it means that we are in a postroll that\n * has ended (because the media ended and we are still in an ad state).\n *\n * In these cases, we transition back to content mode and fire ended.\n */;\n _proto.onAdEnded = function onAdEnded() {\n this.endLinearAdMode();\n this.player.trigger('ended');\n }\n\n /*\n * StitchedAdRoll break is done.\n */;\n _proto.endLinearAdMode = function endLinearAdMode() {\n var StitchedContentPlayback = States.getState('StitchedContentPlayback');\n obj$1.end(this.player);\n this.transitionTo(StitchedContentPlayback);\n };\n return StitchedAdRoll;\n}(AdState$4);\nStates.registerState('StitchedAdRoll', StitchedAdRoll);\n\nvar AdState$5 = States.getState('AdState');\n\n/**\n * This is the initial state for a player in outstream mode. Once a 'play' event\n * is seen, we enter the OutstreamPlayback state. If any errors occur, we go\n * straight from OutstreamPlayback to OutstreamDone.\n */\nvar OutstreamPending = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(OutstreamPending, _AdState);\n function OutstreamPending() {\n return _AdState.apply(this, arguments) || this;\n }\n /**\n * Allows state name to be logged after minification\n */\n OutstreamPending._getName = function _getName() {\n return 'OutstreamPending';\n }\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */;\n var _proto = OutstreamPending.prototype;\n _proto.init = function init(player) {\n this.adsReady = false;\n };\n _proto.onPlay = function onPlay(player) {\n var OutstreamPlayback = States.getState('OutstreamPlayback');\n player.ads.debug('Received play event (OutstreamPending)');\n this.transitionTo(OutstreamPlayback, this.adsReady);\n };\n _proto.onAdsReady = function onAdsReady(player) {\n player.ads.debug('Received adsready event (OutstreamPending)');\n this.adsReady = true;\n };\n _proto.onAdsError = function onAdsError() {\n this.player.ads.debug('adserror (OutstreamPending)');\n this.adsReady = false;\n };\n return OutstreamPending;\n}(AdState$5);\nStates.registerState('OutstreamPending', OutstreamPending);\n\nvar AdState$6 = States.getState('AdState');\n\n/**\n * This state is for waiting for ads in an outstream player,\n * playing ads, and transitioning to OutstreamDone after ads have played.\n */\nvar OutstreamPlayback = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(OutstreamPlayback, _AdState);\n function OutstreamPlayback() {\n return _AdState.apply(this, arguments) || this;\n }\n /**\n * Allows state name to be logged after minification\n */\n OutstreamPlayback._getName = function _getName() {\n return 'OutstreamPlayback';\n }\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */;\n var _proto = OutstreamPlayback.prototype;\n _proto.init = function init(player, adsReady) {\n player.addClass('vjs-ad-loading');\n if (adsReady) {\n this.handleAdsReady();\n } else {\n this.abort(player);\n }\n };\n _proto.onAdsReady = function onAdsReady(player) {\n if (!player.ads.inAdBreak()) {\n player.ads.debug('Received adsready event (Preroll)');\n this.handleAdsReady();\n } else {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected adsready event (Preroll)');\n }\n };\n _proto.abort = function abort(player) {\n var OutstreamDone = States.getState('OutstreamDone');\n player.removeClass('vjs-ad-loading');\n this.transitionTo(OutstreamDone);\n }\n\n /*\n * An ad has actually started playing.\n * Remove the loading spinner.\n */;\n _proto.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n };\n _proto.handleAdsReady = function handleAdsReady() {\n this.adsReady = true;\n this.readyForOutstreamPlayback();\n };\n _proto.readyForOutstreamPlayback = function readyForOutstreamPlayback() {\n var player = this.player;\n this.afterLoadStart(function () {\n player.trigger('readyforoutstream');\n });\n };\n _proto.startLinearAdMode = function startLinearAdMode() {\n var player = this.player;\n if (this.adsReady && !player.ads.inAdBreak()) {\n obj$1.start(player);\n }\n }\n\n /*\n * Cleanup timeouts and spinner.\n */;\n _proto.cleanup = function cleanup(player) {\n if (!player.ads._hasThereBeenALoadStartDuringPlayerLife) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Leaving OutstreamPlayback state before loadstart event can cause issues.');\n }\n this.cleanupPartial(player);\n }\n\n /*\n * Performs cleanup tasks without depending on a state transition. This is\n * used mainly in cases where a preroll failed.\n */;\n _proto.cleanupPartial = function cleanupPartial(player) {\n player.removeClass('vjs-ad-loading');\n player.removeClass('vjs-ad-content-resuming');\n this.clearTimeout(player);\n }\n\n /*\n * Clear the outstream ad timeout and nulls out the pointer.\n */;\n _proto.clearTimeout = function clearTimeout(player) {\n player.clearTimeout(this._timeout);\n this._timeout = null;\n };\n _proto.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n }\n\n /*\n * An ad error occured. Transition straight to OutstreamDone\n */;\n _proto.onAdsError = function onAdsError(player) {\n var _this = this;\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log('adserror (OutstreamPlayback)');\n if (this.inAdBreak()) {\n player.ads.endLinearAdMode();\n } else {\n this.afterLoadStart(function () {\n _this.abort(player);\n });\n }\n }\n\n /*\n * Outstream ad took too long! Play content instead.\n */;\n _proto.onAdTimeout = function onAdTimeout(player) {\n var _this2 = this;\n this.afterLoadStart(function () {\n player.ads.debug('adtimeout (OutstreamPlayback)');\n _this2.abort(player);\n });\n };\n _proto.onAdsCanceled = function onAdsCanceled(player) {\n var _this3 = this;\n player.ads.debug('adscanceled (OutstreamPlaybac)');\n this.afterLoadStart(function () {\n _this3.abort(player);\n });\n };\n _proto.endLinearAdMode = function endLinearAdMode() {\n var _this4 = this;\n if (this.inAdBreak()) {\n this.player.removeClass('vjs-ad-loading');\n var OutstreamDone = States.getState('OutstreamDone');\n obj$1.end(this.player, function () {\n _this4.transitionTo(OutstreamDone);\n });\n }\n };\n _proto.afterLoadStart = function afterLoadStart(callback) {\n var player = this.player;\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 * Ad plugin has skipped ad - transition to OutstreamDone\n */;\n _proto.skipLinearAdMode = function skipLinearAdMode() {\n var _this5 = this;\n var player = this.player;\n var OutstreamDone = States.getState('OutstreamDone');\n if (this.inAdBreak()) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected skipLinearAdMode invocation');\n } else {\n this.afterLoadStart(function () {\n player.trigger('adskip');\n player.ads.debug('skipLinearAdMode (OutstreamPlayback)');\n _this5.transitionTo(OutstreamDone);\n });\n }\n };\n return OutstreamPlayback;\n}(AdState$6);\nStates.registerState('OutstreamPlayback', OutstreamPlayback);\n\nvar AdState$7 = States.getState('AdState');\n\n/**\n * This is the final state for a player in outstream mode. There\n * should be no more ads playing once the player has transitioned\n * to this state.\n */\nvar OutstreamDone = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(OutstreamDone, _AdState);\n function OutstreamDone() {\n return _AdState.apply(this, arguments) || this;\n }\n /**\n * Allows state name to be logged after minification\n */\n OutstreamDone._getName = function _getName() {\n return 'OutstreamDone';\n }\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */;\n var _proto = OutstreamDone.prototype;\n _proto.init = function init(player) {\n player.trigger('ended');\n }\n\n /*\n * No more ads should play after this state.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected startLinearAdMode invocation (OutstreamDone)');\n };\n return OutstreamDone;\n}(AdState$7);\nStates.registerState('OutstreamDone', OutstreamDone);\n\n/*\nThis main plugin file is responsible for the public API and enabling the features\nthat live in in separate files.\n*/\nvar isMiddlewareMediatorSupported$1 = obj.isMiddlewareMediatorSupported;\nvar VIDEO_EVENTS = video_js__WEBPACK_IMPORTED_MODULE_0___default().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 // 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 // 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 // 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 // Set this to true when using ads that are part of the content video\n stitchedAds: false,\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 // If set to true, content will play muted behind ads on supported platforms. This is\n // to support ads on video metadata cuepoints during a live stream. It also results in\n // more precise resumes after ads during a live stream.\n liveCuePoints: true,\n // If set to true, callPlay middleware will not terminate the first play request in\n // BeforePreroll if the player intends to autoplay. This allows the manual autoplay\n // attempt made by video.js to resolve/reject naturally and trigger an 'autoplay-success'\n // or 'autoplay-failure' event with which other plugins can interface.\n allowVjsAutoplay: (video_js__WEBPACK_IMPORTED_MODULE_0___default().options).normalizeAutoplay || false\n};\nvar contribAdsPlugin = function contribAdsPlugin(options) {\n var player = this; // eslint-disable-line consistent-this\n\n var settings = video_js__WEBPACK_IMPORTED_MODULE_0___default().obj.merge(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 = [];\n\n // dedupe event names\n VIDEO_EVENTS.concat(['firstplay', 'loadedalldata']).forEach(function (eventName) {\n if (videoEvents.indexOf(eventName) === -1) {\n videoEvents.push(eventName);\n }\n });\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$1()) {\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 video_js__WEBPACK_IMPORTED_MODULE_0___default().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 // We don't need to handle this for stitched ads because\n // linear ads in such cases are stitched into the content.\n if (player.ads.settings.stitchedAds) {\n return;\n }\n // Some techs may retrigger canplay after playback has begun.\n // So we want to procceed only if playback hasn't started.\n if (player.hasStarted()) {\n return;\n }\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 var playPromise = player.play();\n if (playPromise && playPromise.catch) {\n playPromise.catch(function (error) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Play promise rejected when playing ad', error);\n });\n }\n });\n player.on('nopreroll', function () {\n player.ads.debug('Received nopreroll event');\n player.ads.nopreroll_ = true;\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 player.one('loadstart', function () {\n player.ads._hasThereBeenALoadStartDuringPlayerLife = true;\n });\n player.on('loadeddata', function () {\n player.ads._hasThereBeenALoadedData = true;\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 player.ads.settings = settings;\n\n // Set the stitched ads state. This needs to happen before the `_state` is\n // initialized below - BeforePreroll needs to know whether contrib-ads is\n // playing stitched ads or not.\n // The setter is deprecated, so this does not use it.\n // But first, cast to boolean.\n settings.stitchedAds = !!settings.stitchedAds;\n if (settings.playerMode === 'outstream') {\n // Set a 0s mp4 file to enable ads to play\n player.src(OUTSTREAM_VIDEO);\n player.ads._state = new (States.getState('OutstreamPending'))(player);\n } else if (settings.stitchedAds) {\n player.ads._state = new (States.getState('StitchedContentPlayback'))(player);\n } else {\n player.ads._state = new (States.getState('BeforePreroll'))(player);\n }\n player.ads._state.init(player);\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 && (video_js__WEBPACK_IMPORTED_MODULE_0___default().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 if (shouldDisableTracks()) {\n // We must double check all tracks\n for (var i = 0; i < textTrackList.length; i++) {\n var track = textTrackList[i];\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', 'adended', 'ads-ad-started', 'ads-ad-skipped', 'contentchanged', 'dispose', '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.ads.reset();\n player.textTracks().removeEventListener('change', textTrackChangeHandler);\n });\n\n // Listen to TCF changes\n listenToTcf();\n\n // Initialize the US Privacy string\n obtainUsPrivacyString(function () {});\n\n // Can be called for testing, or if the TCF CMP has loaded late\n player.ads.listenToTcf = listenToTcf;\n\n // Expose so the US privacy string can be updated as needed\n player.ads.updateUsPrivacyString = function (callback) {\n return obtainUsPrivacyString(callback);\n };\n};\n\n// contrib-ads specific error const\ncontribAdsPlugin.Error = Error$1;\n\n// Expose the contrib-ads version before it is initialized. Will be replaced\n// after initialization in ads.js\ncontribAdsPlugin.VERSION = version;\n\n// Attempt to register the plugin, if we can.\nregister(contribAdsPlugin);\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (contribAdsPlugin);\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/videojs-contrib-ads/dist/videojs-contrib-ads.es.js?\n}");
65
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\");\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(video_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var global_window__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! global/window */ \"../node_modules/global/window.js\");\n/* harmony import */ var global_window__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(global_window__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var global_document__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! global/document */ \"../node_modules/global/document.js\");\n/* harmony import */ var global_document__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(global_document__WEBPACK_IMPORTED_MODULE_2__);\n/*! @name videojs-contrib-ads @version 7.5.2 @license Apache-2.0 */\n\n\n\n\nvar version = \"7.5.2\";\n\n/*\n * Implements the public API available in `player.ads` as well as application state.\n */\nfunction getAds(player) {\n return {\n disableNextSnapshotRestore: false,\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 // 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 // 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 // Tracks if loadeddata has happened yet for the current source.\n _hasThereBeenALoadedData: false,\n // Tracks if loadedmetadata has happened yet for the current source.\n _hasThereBeenALoadedMetaData: false,\n // Are we after startLinearAdMode and before endLinearAdMode?\n _inLinearAdMode: false,\n // Should we block calls to play on the content player?\n _shouldBlockPlay: false,\n // Was play blocked by the plugin's playMiddleware feature?\n _playBlocked: false,\n // Tracks whether play has been requested for this source,\n // either by the play method or user interaction\n _playRequested: false,\n // Contains error information when an error occurs in contrib-ads.\n // When set, will contain an object with a type and metadata.\n _error: null,\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 VERSION: version,\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 player.ads._error = null;\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 // Call this when a linear ad pod has finished playing.\n endLinearAdMode: function endLinearAdMode() {\n player.ads._state.endLinearAdMode();\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 // With no arguments, returns a boolean value indicating whether or not\n // contrib-ads is set to treat ads as stitched with content in a single\n // stream. With arguments, treated as a setter, but this behavior is\n // deprecated.\n stitchedAds: function stitchedAds(arg) {\n if (arg !== undefined) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Using player.ads.stitchedAds() as a setter is deprecated, ' + 'it should be set as an option upon initialization of contrib-ads.');\n\n // Keep the private property and the settings in sync. When this\n // setter is removed, we can probably stop using the private property.\n this.settings.stitchedAds = !!arg;\n }\n return this.settings.stitchedAds;\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 if (!this.snapshot) {\n throw new Error('You cannot use videoElementRecycled while there is no snapshot.');\n }\n var srcChanged = player.tech_.src() !== this.snapshot.src;\n var currentSrcChanged = player.currentSrc() !== this.snapshot.currentSrc;\n return srcChanged || currentSrcChanged;\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 (somePlayer === void 0) {\n somePlayer = player;\n }\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 ((video_js__WEBPACK_IMPORTED_MODULE_0___default().browser).IOS_VERSION === '8' && somePlayer.duration() === 0) {\n return true;\n }\n return false;\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 if (somePlayer === void 0) {\n somePlayer = player;\n }\n if (!somePlayer) {\n throw new Error('shouldPlayContentBehindAd requires a player as a param');\n } else if (!somePlayer.ads.settings.liveCuePoints) {\n return false;\n } else {\n return !(video_js__WEBPACK_IMPORTED_MODULE_0___default().browser).IS_IOS && !(video_js__WEBPACK_IMPORTED_MODULE_0___default().browser).IS_ANDROID && somePlayer.duration() === Infinity;\n }\n },\n // Return true if the ads plugin should save and restore snapshots of the\n // player state when moving into and out of ad mode.\n shouldTakeSnapshots: function shouldTakeSnapshots(somePlayer) {\n if (somePlayer === void 0) {\n somePlayer = player;\n }\n return !this.shouldPlayContentBehindAd(somePlayer) && !this.stitchedAds();\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 // 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 // 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 // Deprecated because the name was misleading. Use inAdBreak instead.\n isAdPlaying: function isAdPlaying() {\n return this._state.inAdBreak();\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 * 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 if (tech) {\n tech.removeAttribute('poster');\n }\n },\n debug: function debug() {\n if (this.settings.debug) {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n if (args.length === 1 && typeof args[0] === 'string') {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log('ADS: ' + args[0]);\n } else {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.apply((video_js__WEBPACK_IMPORTED_MODULE_0___default()), ['ADS:'].concat(args));\n }\n }\n },\n /**\n * Set or get the current ads error.\n *\n * @fires Player#vjsadserror\n *\n * @param {import('video.js/dist/types/media-error').ErrorMetadata|null} [err]\n * The error to be set. This can either be a string\n * of the error type, or it can be an object containing the\n * type, along with error metadata.\n * If nothing is passed in, this function will return the current error.\n * @param {string} err.errorType The error type.\n *\n * @return {Object|null|undefined}\n * The current ads error. The function will return undefined if the function\n * is used to set an error. It will return null if there is no error.\n */\n error: function error(err) {\n // If `err` doesn't exist, return the current error.\n if (err === undefined) {\n return this._error || null;\n }\n\n // If `err` is null or not a valid error, reset the ads error.\n if (err === null || !err.errorType) {\n this._error = null;\n return;\n }\n this._error = err;\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.error(\"An error with Ads occured. Type: \" + err.errorType + \".\");\n\n /**\n * @event Player#vjsadserror\n * @type {Event}\n */\n player.trigger({\n type: 'vjsadserror',\n error: this._error\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 if (player.ads.isContentResuming()) {\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 // 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 && !player.ads.stitchedAds()) {\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 // 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 // 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 // Event came from snapshot restore after an ad, use \"content\" prefix\n prefixEvent(this, 'content', event);\n } else {\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 // 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 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 if (src !== player.ads.contentSrc) {\n if (player.ads._seenInitialLoadstart) {\n player.trigger({\n type: 'contentchanged'\n });\n }\n player.trigger({\n type: 'contentupdate',\n oldValue: player.ads.contentSrc,\n newValue: src\n });\n player.ads.contentSrc = src;\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\nfunction _extends() {\n _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n return target;\n };\n return _extends.apply(this, arguments);\n}\nfunction _inheritsLoose(subClass, superClass) {\n subClass.prototype = Object.create(superClass.prototype);\n subClass.prototype.constructor = subClass;\n _setPrototypeOf(subClass, superClass);\n}\nfunction _setPrototypeOf(o, p) {\n _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n return _setPrototypeOf(o, p);\n}\n\n/**\n * Current tcfData returned from CMP\n * Updated on event listener rather than having to make an asyc\n * check within the macro resolver\n */\nvar tcData = {};\n\n/**\n * Sets up a proxy for the TCF API in an iframed player, if a parent frame\n * that has implemented the TCF API is detected\n * https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#is-there-a-sample-iframe-script-call-to-the-cmp-api\n */\nvar proxyTcfApi = function proxyTcfApi(_) {\n if (video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.isInFrame() && typeof (global_window__WEBPACK_IMPORTED_MODULE_1___default().__tcfapi) !== 'function') {\n var frame = (global_window__WEBPACK_IMPORTED_MODULE_1___default());\n var cmpFrame;\n var cmpCallbacks = {};\n while (frame) {\n try {\n if (frame.frames.__tcfapiLocator) {\n cmpFrame = frame;\n break;\n }\n } catch (ignore) {\n // empty\n }\n if (frame === (global_window__WEBPACK_IMPORTED_MODULE_1___default().top)) {\n break;\n }\n frame = frame.parent;\n }\n if (!cmpFrame) {\n return;\n }\n (global_window__WEBPACK_IMPORTED_MODULE_1___default().__tcfapi) = function (cmd, version, callback, arg) {\n var callId = Math.random() + '';\n var msg = {\n __tcfapiCall: {\n command: cmd,\n parameter: arg,\n version: version,\n callId: callId\n }\n };\n cmpCallbacks[callId] = callback;\n cmpFrame.postMessage(msg, '*');\n };\n global_window__WEBPACK_IMPORTED_MODULE_1___default().addEventListener('message', function (event) {\n var json = {};\n try {\n json = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;\n } catch (ignore) {\n // empty\n }\n var payload = json.__tcfapiReturn;\n if (payload) {\n if (typeof cmpCallbacks[payload.callId] === 'function') {\n cmpCallbacks[payload.callId](payload.returnValue, payload.success);\n cmpCallbacks[payload.callId] = null;\n }\n }\n }, false);\n }\n};\n\n/**\n * Sets up event listener for changes to consent data.\n */\nvar listenToTcf = function listenToTcf() {\n proxyTcfApi();\n if (typeof (global_window__WEBPACK_IMPORTED_MODULE_1___default().__tcfapi) === 'function') {\n global_window__WEBPACK_IMPORTED_MODULE_1___default().__tcfapi('addEventListener', 2, function (data, success) {\n if (success) {\n tcData = data;\n }\n });\n }\n};\n\nvar findUspApiLocatorWindow = function findUspApiLocatorWindow(windowObj) {\n var targetWindow = windowObj.parent;\n while (targetWindow !== windowObj.top) {\n try {\n if (targetWindow.frames && targetWindow.frames.__uspapiLocator) {\n return targetWindow;\n }\n } catch (ignore) {\n // do nothing\n }\n targetWindow = targetWindow.parent;\n }\n\n // Check for the __uspapiLocator frame in the top window\n try {\n if (windowObj.top.frames && windowObj.top.frames.__uspapiLocator) {\n return windowObj.top;\n }\n } catch (ignore) {\n // do nothing\n }\n\n // Return null if no __uspapiLocator frame is found in any window\n return null;\n};\nvar uspString = '';\nvar getCurrentUspString = function getCurrentUspString() {\n return uspString;\n};\n\n// Call the USP API to get the US Privacy String, either by invoking it directly or via postMessage() if inside an iframe.\n// In the former case the callback is synchronous, if the latter it is asynchronous, so to be safe it should always be\n// assumed to be asynchronous.\n// The window is passable as an argument for ease of testing\nvar obtainUsPrivacyString = function obtainUsPrivacyString(callback, windowObj) {\n if (windowObj === void 0) {\n windowObj = (global_window__WEBPACK_IMPORTED_MODULE_1___default());\n }\n if (windowObj.__uspapi) {\n windowObj.__uspapi('getUSPData', 1, function (uspData, success) {\n var privacyString = success ? uspData.uspString : null;\n uspString = privacyString;\n callback(privacyString);\n });\n } else {\n var targetWindow = findUspApiLocatorWindow(windowObj);\n\n // If no __uspapiLocator frame is found, execute the callback with a null privacy string\n if (!targetWindow) {\n callback(null);\n return;\n }\n var uniqueId = Math.random().toString(36).substring(2);\n var message = {\n __uspapiCall: {\n command: 'getUSPData',\n version: 1,\n callId: uniqueId\n }\n };\n var handleMessageEvent = function handleMessageEvent(event) {\n if (event && event.data && event.data.__uspapiReturn && event.data.__uspapiReturn.callId === uniqueId) {\n windowObj.removeEventListener('message', handleMessageEvent, false);\n var _event$data$__uspapiR = event.data.__uspapiReturn,\n returnValue = _event$data$__uspapiR.returnValue,\n success = _event$data$__uspapiR.success;\n var privacyString = success ? returnValue.uspString : null;\n uspString = privacyString;\n callback(privacyString);\n }\n };\n windowObj.addEventListener('message', handleMessageEvent, false);\n targetWindow.postMessage(message, '*');\n }\n};\n\nvar Error$1 = {\n AdsBeforePrerollError: 'ads-before-preroll-error',\n AdsPrerollError: 'ads-preroll-error',\n AdsMidrollError: 'ads-midroll-error',\n AdsPostrollError: 'ads-postroll-error',\n AdsMacroReplacementFailed: 'ads-macro-replacement-failed',\n AdsResumeContentFailed: 'ads-resume-content-failed'\n};\n\nvar uriEncodeIfNeeded = function uriEncodeIfNeeded(value, uriEncode) {\n return uriEncode ? encodeURIComponent(value) : 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 for (var i = 0; i < fieldNames.length; i++) {\n var tag = '{mediainfo.' + customFieldsName + '.' + fieldNames[i] + '}';\n macros[tag] = fields[fieldNames[i]];\n }\n }\n};\nvar getMediaInfoMacros = function getMediaInfoMacros(mediainfo, defaults) {\n var macros = {};\n ['description', 'tags', 'reference_id', 'ad_keys'].forEach(function (prop) {\n if (mediainfo && mediainfo[prop]) {\n macros[\"{mediainfo.\" + prop + \"}\"] = mediainfo[prop];\n } else if (defaults[\"{mediainfo.\" + prop + \"}\"]) {\n macros[\"{mediainfo.\" + prop + \"}\"] = defaults[\"{mediainfo.\" + prop + \"}\"];\n } else {\n macros[\"{mediainfo.\" + prop + \"}\"] = '';\n }\n });\n ['custom_fields', 'customFields'].forEach(function (customFieldProp) {\n customFields(mediainfo, macros, customFieldProp);\n });\n return macros;\n};\nvar getDefaultValues = function getDefaultValues(string) {\n var defaults = {};\n var modifiedString = string.replace(/{([^}=]+)=([^}]*)}/g, function (match, name, defaultVal) {\n defaults[\"{\" + name + \"}\"] = defaultVal;\n return \"{\" + name + \"}\";\n });\n return {\n defaults: defaults,\n modifiedString: modifiedString\n };\n};\nvar getStaticMacros = function getStaticMacros(player) {\n return {\n '{player.id}': player.options_['data-player'] || player.id_,\n '{player.height}': player.currentHeight(),\n '{player.width}': player.currentWidth(),\n '{player.heightInt}': Math.round(player.currentHeight()),\n '{player.widthInt}': Math.round(player.currentWidth()),\n '{player.autoplay}': player.autoplay() ? 1 : 0,\n '{player.muted}': player.muted() ? 1 : 0,\n '{player.language}': player.language() || '',\n '{mediainfo.id}': player.mediainfo ? player.mediainfo.id : '',\n '{mediainfo.name}': player.mediainfo ? player.mediainfo.name : '',\n '{mediainfo.duration}': player.mediainfo ? player.mediainfo.duration : '',\n '{player.duration}': player.duration(),\n '{player.durationInt}': Math.round(player.duration()),\n '{player.live}': player.duration() === Infinity ? 1 : 0,\n '{player.pageUrl}': video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.isInFrame() ? (global_document__WEBPACK_IMPORTED_MODULE_2___default().referrer) : (global_window__WEBPACK_IMPORTED_MODULE_1___default().location).href,\n '{playlistinfo.id}': player.playlistinfo ? player.playlistinfo.id : '',\n '{playlistinfo.name}': player.playlistinfo ? player.playlistinfo.name : '',\n '{timestamp}': new Date().getTime(),\n '{document.referrer}': (global_document__WEBPACK_IMPORTED_MODULE_2___default().referrer),\n '{window.location.href}': (global_window__WEBPACK_IMPORTED_MODULE_1___default().location).href,\n '{random}': Math.floor(Math.random() * 1000000000000)\n };\n};\nvar getTcfMacros = function getTcfMacros(tcDataObj) {\n var tcfMacros = {};\n Object.keys(tcDataObj).forEach(function (key) {\n tcfMacros[\"{tcf.\" + key + \"}\"] = tcDataObj[key];\n });\n tcfMacros['{tcf.gdprAppliesInt}'] = tcDataObj.gdprApplies ? 1 : 0;\n return tcfMacros;\n};\nvar getUspMacros = function getUspMacros() {\n return {\n '{usp.uspString}': getCurrentUspString()\n };\n};\n\n// This extracts and evaluates variables from the `window` object for macro replacement. While replaceMacros() handles generic macro name\n// overriding for other macro types, this function also needs to reference the overrides in order to map custom macro names in the string\n// to their corresponding default pageVariable names, so they can be evaluated on the `window` and stored for later replacement in replaceMacros().\nvar getPageVariableMacros = function getPageVariableMacros(string, defaults, macroNameOverrides) {\n var pageVarRegex = new RegExp('{pageVariable\\\\.([^}]+)}', 'g');\n var pageVariablesMacros = {};\n\n // Aggregate any default pageVariable macros found in the string with any pageVariable macros that have custom names specified in\n // macroNameOverrides.\n var pageVariables = (string.match(pageVarRegex) || []).concat(Object.keys(macroNameOverrides).filter(function (macroName) {\n return pageVarRegex.test(macroName) && string.includes(macroNameOverrides[macroName]);\n }));\n if (!pageVariables) {\n return;\n }\n pageVariables.forEach(function (pageVar) {\n var key = pageVar;\n var name = pageVar.slice(14, -1);\n var names = name.split('.');\n var context = (global_window__WEBPACK_IMPORTED_MODULE_1___default());\n var value;\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 if (typeof context === 'undefined') {\n break;\n }\n }\n }\n var type = typeof value;\n\n // Only allow certain types of values. Anything else is probably a mistake.\n if (value === null) {\n pageVariablesMacros[key] = 'null';\n } else if (value === undefined) {\n if (defaults[key]) {\n pageVariablesMacros[key] = defaults[key];\n } else {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn(\"Page variable \\\"\" + name + \"\\\" not found\");\n pageVariablesMacros[key] = '';\n }\n } else if (type !== 'string' && type !== 'number' && type !== 'boolean') {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn(\"Page variable \\\"\" + name + \"\\\" is not a supported type\");\n pageVariablesMacros[key] = '';\n } else {\n pageVariablesMacros[key] = value;\n }\n });\n return pageVariablesMacros;\n};\nvar replaceMacros = function replaceMacros(string, macros, uriEncode, overrides, player) {\n if (overrides === void 0) {\n overrides = {};\n }\n for (var macroName in macros) {\n // The resolvedMacroName is the macro as it is expected to appear in the actual string, or regex if it has been provided.\n var resolvedMacroName = overrides.hasOwnProperty(macroName) ? overrides[macroName] : macroName;\n if (resolvedMacroName.startsWith('r:')) {\n try {\n var regex = new RegExp(resolvedMacroName.slice(2), 'g');\n string = string.replace(regex, uriEncodeIfNeeded(macros[macroName], uriEncode));\n } catch (error) {\n player.ads.error({\n errorType: Error$1.AdsMacroReplacementFailed,\n macro: macroName,\n error: error\n });\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn(\"Unable to replace macro with regex \\\"\" + resolvedMacroName + \"\\\". The provided regex may be invalid.\");\n }\n } else {\n string = string.split(resolvedMacroName).join(uriEncodeIfNeeded(macros[macroName], uriEncode));\n }\n }\n return string;\n};\n\n/**\n *\n * @param {string} string\n * Any string with macros to be replaced\n * @param {boolean} uriEncode\n * A Boolean value indicating whether the macros should be replaced with URI-encoded values\n * @param {object} customMacros\n * An object with custom macros and values to map them to. For example: {'{five}': 5}\n * @param {boolean} customMacros.disableDefaultMacros\n * A boolean indicating whether replacement of default macros should be forgone in favor of only customMacros\n * @param {object} customMacros.macroNameOverrides\n * An object that specifies custom names for default macros, following the following format:\n * // {'{default-macro-name}': '{new-macro-name}'}\n * {'{player.id}': '{{PLAYER_ID}}', ...}\n * @returns {string}\n * The provided string with all macros replaced. For example: adMacroReplacement('{player.id}') returns a string of the player id\n */\nfunction adMacroReplacement(string, uriEncode, customMacros) {\n if (uriEncode === void 0) {\n uriEncode = false;\n }\n if (customMacros === void 0) {\n customMacros = {};\n }\n var disableDefaultMacros = customMacros.disableDefaultMacros || false;\n var macroNameOverrides = customMacros.macroNameOverrides || {};\n\n // Remove special properties from customMacros\n delete customMacros.disableDefaultMacros;\n delete customMacros.macroNameOverrides;\n var macros = customMacros;\n if (disableDefaultMacros) {\n return replaceMacros(string, macros, uriEncode, macroNameOverrides);\n }\n\n // Get macros with defaults e.g. {x=y}, store the values in `defaults` and replace with standard macros in the string\n var _getDefaultValues = getDefaultValues(string),\n defaults = _getDefaultValues.defaults,\n modifiedString = _getDefaultValues.modifiedString;\n string = modifiedString;\n\n // Get all macro values\n _extends(macros, getStaticMacros(this), getMediaInfoMacros(this.mediainfo, defaults), getTcfMacros(tcData), getUspMacros(), getPageVariableMacros(string, defaults, macroNameOverrides));\n\n // Perform macro replacement\n string = replaceMacros(string, macros, uriEncode, macroNameOverrides, this);\n\n // Replace any remaining default values that have not already been replaced. This includes mediainfo custom fields.\n for (var macro in defaults) {\n string = string.replace(macro, defaults[macro]);\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**/\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 video_js__WEBPACK_IMPORTED_MODULE_0___default().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 video_js__WEBPACK_IMPORTED_MODULE_0___default().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 video_js__WEBPACK_IMPORTED_MODULE_0___default().log('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 // this function is in the player's context\n\n if (this.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 (!this.paused()) {\n this.ads.debug('Playback was canceled by cancelContentPlay');\n this.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 this.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 = (video_js__WEBPACK_IMPORTED_MODULE_0___default());\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 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 return false;\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, playPromise) {\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 // Safari issues a pause event when autoplay is blocked but other browsers\n // do not, so we send a pause for consistency in those cases. This keeps the\n // play button in the correct state if play is rejected.\n } else if (playPromise && playPromise.catch) {\n playPromise.catch(function (e) {\n if (e.name === 'NotAllowedError' && !(video_js__WEBPACK_IMPORTED_MODULE_0___default().browser).IS_SAFARI) {\n player.trigger('pause');\n }\n });\n }\n }\n };\n};\nobj.testHook = function (testVjs) {\n videojsReference = testVjs;\n};\n\nvar playMiddleware = obj.playMiddleware,\n isMiddlewareMediatorSupported = obj.isMiddlewareMediatorSupported;\n\n/**\n * Whether or not this copy of Video.js has the ads plugin.\n *\n * @return {boolean}\n * If `true`, has the plugin. `false` otherwise.\n */\nvar hasAdsPlugin = function hasAdsPlugin() {\n // Video.js 6 and 7 have a getPlugin method.\n if ((video_js__WEBPACK_IMPORTED_MODULE_0___default().getPlugin)) {\n return Boolean(video_js__WEBPACK_IMPORTED_MODULE_0___default().getPlugin('ads'));\n }\n\n // Video.js 5 does not have a getPlugin method, so check the player prototype.\n var Player = video_js__WEBPACK_IMPORTED_MODULE_0___default().getComponent('Player');\n return Boolean(Player && Player.prototype.ads);\n};\n\n/**\n * Register contrib-ads with Video.js, but provide protection for duplicate\n * copies of the plugin. This could happen if, for example, a stitched ads\n * plugin and a client-side ads plugin are included simultaneously with their\n * own copies of contrib-ads.\n *\n * If contrib-ads detects a pre-existing duplicate, it will not register\n * itself.\n *\n * Ad plugins using contrib-ads and anticipating that this could come into\n * effect should verify that the contrib-ads they are using is of a compatible\n * version.\n *\n * @param {Function} contribAdsPlugin\n * The plugin function.\n *\n * @return {boolean}\n * When `true`, the plugin was registered. When `false`, the plugin\n * was not registered.\n */\nfunction register(contribAdsPlugin) {\n // If the ads plugin already exists, do not overwrite it.\n if (hasAdsPlugin((video_js__WEBPACK_IMPORTED_MODULE_0___default()))) {\n return false;\n }\n\n // Cross-compatibility with Video.js 6/7 and 5.\n var registerPlugin = (video_js__WEBPACK_IMPORTED_MODULE_0___default().registerPlugin) || (video_js__WEBPACK_IMPORTED_MODULE_0___default().plugin);\n\n // Register this plugin with Video.js.\n registerPlugin('ads', contribAdsPlugin);\n\n // Register the play middleware with Video.js on script execution,\n // to avoid a new playMiddleware factory being added for each player.\n // The `usingContribAdsMiddleware_` flag is used to ensure that we only ever\n // register the middleware once - despite the ability to de-register and\n // re-register the plugin itself.\n if (isMiddlewareMediatorSupported() && !(video_js__WEBPACK_IMPORTED_MODULE_0___default().usingContribAdsMiddleware_)) {\n // Register the play middleware\n video_js__WEBPACK_IMPORTED_MODULE_0___default().use('*', playMiddleware);\n (video_js__WEBPACK_IMPORTED_MODULE_0___default().usingContribAdsMiddleware_) = true;\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.debug('Play middleware has been registered with videojs');\n }\n return true;\n}\n\nvar OUTSTREAM_VIDEO = {\n src: 'data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAAxJtZGF03ABMYXZjNjEuMy4xMDAAQiAIwRg4AAACrgYF//+q3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2NCByMzEwOCAzMWUxOWY5IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAyMyAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTcgbG9va2FoZWFkX3RocmVhZHM9MSBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2NvbXBhdD0wIGNvbnN0cmFpbmVkX2ludHJhPTAgYmZyYW1lcz0zIGJfcHlyYW1pZD0yIGJfYWRhcHQ9MSBiX2JpYXM9MCBkaXJlY3Q9MSB3ZWlnaHRiPTEgb3Blbl9nb3A9MCB3ZWlnaHRwPTIga2V5aW50PTI1MCBrZXlpbnRfbWluPTI1IHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAAn//71sXwKaunqigzoMi7hlyTJrrYi4m0AwABFxzcqWKGahTaoBcQAAMWK4AlcFlIICBeldSEQBGCMHAAABVNtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAIgABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAACQXRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAIgAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAABQAAAAPAAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAACIAAAAAAAEAAAAAAbltZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAADwAAAACAFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAFkbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABJHN0YmwAAADAc3RzZAAAAAAAAAABAAAAsGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAABQADwAEgAAABIAAAAAAAAAAEUTGF2YzYxLjMuMTAwIGxpYngyNjQAAAAAAAAAAAAAAAAY//8AAAA2YXZjQwFkAA3/4QAZZ2QADazZQUH7ARAAAAMAEAAAAwPA8UKZYAEABmjr48siwP34+AAAAAAQcGFzcAAAAAEAAAABAAAAFGJ0cnQAAAAAAALAEAACwBAAAAAYc3R0cwAAAAAAAAABAAAAAQAAAgAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAFHN0c3oAAAAAAAAC7wAAAAEAAAAUc3RjbwAAAAAAAAABAAAARQAAAj10cmFrAAAAXHRraGQAAAADAAAAAAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAEBAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAAXAAAEAAABAAAAAAG1bWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAACsRAAACABVxAAAAAAALWhkbHIAAAAAAAAAAHNvdW4AAAAAAAAAAAAAAABTb3VuZEhhbmRsZXIAAAABYG1pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABJHN0YmwAAAB+c3RzZAAAAAAAAAABAAAAbm1wNGEAAAAAAAAAAQAAAAAAAAAAAAIAEAAAAACsRAAAAAAANmVzZHMAAAAAA4CAgCUAAgAEgICAF0AVAAAAAAH0AAAAEisFgICABRIQVuUABoCAgAECAAAAFGJ0cnQAAAAAAAH0AAAAEisAAAAYc3R0cwAAAAAAAAABAAAAAgAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAAVAAAABgAAABhzdGNvAAAAAAAAAAIAAAAwAAADNAAAABpzZ3BkAQAAAHJvbGwAAAACAAAAAf//AAAAHHNiZ3AAAAAAcm9sbAAAAAEAAAACAAAAAQAAAGF1ZHRhAAAAWW1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAALGlsc3QAAAAkqXRvbwAAABxkYXRhAAAAAQAAAABMYXZmNjEuMS4xMDA=',\n type: 'video/mp4'\n};\n\nvar States = /*#__PURE__*/function () {\n function States() {}\n States.getState = function getState(name) {\n if (!name) {\n return;\n }\n if (States.states_ && States.states_[name]) {\n return States.states_[name];\n }\n };\n States.registerState = function registerState(name, StateToRegister) {\n if (typeof name !== 'string' || !name) {\n throw new Error(\"Illegal state name, \\\"\" + name + \"\\\"; must be a non-empty string.\");\n }\n if (!States.states_) {\n States.states_ = {};\n }\n States.states_[name] = StateToRegister;\n return StateToRegister;\n };\n return States;\n}();\n\nvar State = /*#__PURE__*/function () {\n State._getName = function _getName() {\n return 'Anonymous State';\n };\n function State(player) {\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 var _proto = State.prototype;\n _proto.transitionTo = function transitionTo(NewState) {\n var player = this.player;\n\n // Since State is an abstract class, this will refer to\n // the state that is extending this class\n this.cleanup(player);\n var newState = new NewState(player);\n player.ads._state = newState;\n player.ads.debug(this.constructor._getName() + ' -> ' + newState.constructor._getName());\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\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 _proto.init = function init() {}\n\n /*\n * Implemented by subclasses to provide cleanup logic when transitioning\n * to a new state.\n */;\n _proto.cleanup = function cleanup() {}\n\n /*\n * Default event handlers. Different states can override these to provide behaviors.\n */;\n _proto.onPlay = function onPlay() {};\n _proto.onPlaying = function onPlaying() {};\n _proto.onEnded = function onEnded() {};\n _proto.onAdEnded = function onAdEnded() {};\n _proto.onAdsReady = function onAdsReady() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected adsready event');\n };\n _proto.onAdsError = function onAdsError() {};\n _proto.onAdsCanceled = function onAdsCanceled() {};\n _proto.onAdTimeout = function onAdTimeout() {};\n _proto.onAdStarted = function onAdStarted() {};\n _proto.onAdSkipped = function onAdSkipped() {};\n _proto.onContentChanged = function onContentChanged() {};\n _proto.onContentResumed = function onContentResumed() {};\n _proto.onReadyForPostroll = function onReadyForPostroll() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected readyforpostroll event');\n };\n _proto.onNoPreroll = function onNoPreroll() {};\n _proto.onNoPostroll = function onNoPostroll() {}\n\n /*\n * Method handlers. Different states can override these to provide behaviors.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected startLinearAdMode invocation ' + '(State via ' + this.constructor._getName() + ')');\n };\n _proto.endLinearAdMode = function endLinearAdMode() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected endLinearAdMode invocation ' + '(State via ' + this.constructor._getName() + ')');\n };\n _proto.skipLinearAdMode = function skipLinearAdMode() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().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 _proto.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 _proto.isWaitingForAdBreak = function isWaitingForAdBreak() {\n return false;\n }\n\n /*\n * Overridden by Preroll, Midroll, and Postroll.\n */;\n _proto.isContentResuming = function isContentResuming() {\n return false;\n };\n _proto.inAdBreak = function inAdBreak() {\n return false;\n }\n\n /*\n * Invoke event handler methods when events come in.\n */;\n _proto.handleEvent = function handleEvent(type) {\n var player = this.player;\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 === 'ads-ad-skipped') {\n this.onAdSkipped(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 } else if (type === 'adended') {\n this.onAdEnded(player);\n }\n };\n return State;\n}();\nStates.registerState('State', State);\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 */\nvar AdState = /*#__PURE__*/function (_State) {\n _inheritsLoose(AdState, _State);\n function AdState(player) {\n var _this;\n _this = _State.call(this, player) || this;\n _this.contentResuming = false;\n _this.waitingForAdBreak = false;\n return _this;\n }\n\n /*\n * Overrides State.isAdState\n */\n var _proto = AdState.prototype;\n _proto.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 _proto.onPlaying = function onPlaying() {\n var ContentPlayback = States.getState('ContentPlayback');\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 _proto.onContentResumed = function onContentResumed() {\n var ContentPlayback = States.getState('ContentPlayback');\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 _proto.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 _proto.isContentResuming = function isContentResuming() {\n return this.contentResuming;\n }\n\n /*\n * Allows you to check if an ad break is in progress.\n */;\n _proto.inAdBreak = function inAdBreak() {\n return this.player.ads._inLinearAdMode === true;\n };\n return AdState;\n}(State);\nStates.registerState('AdState', AdState);\n\nvar ContentState = /*#__PURE__*/function (_State) {\n _inheritsLoose(ContentState, _State);\n function ContentState() {\n return _State.apply(this, arguments) || this;\n }\n var _proto = ContentState.prototype;\n /*\n * Overrides State.isAdState\n */\n _proto.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 _proto.onContentChanged = function onContentChanged(player) {\n var BeforePreroll = States.getState('BeforePreroll');\n var Preroll = States.getState('Preroll');\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 return ContentState;\n}(State);\nStates.registerState('ContentState', ContentState);\n\nvar ContentState$1 = States.getState('ContentState');\nvar AdsDone = /*#__PURE__*/function (_ContentState) {\n _inheritsLoose(AdsDone, _ContentState);\n function AdsDone() {\n return _ContentState.apply(this, arguments) || this;\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 var _proto = AdsDone.prototype;\n _proto.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 _proto.startLinearAdMode = function startLinearAdMode() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected startLinearAdMode invocation (AdsDone)');\n };\n return AdsDone;\n}(ContentState$1);\nStates.registerState('AdsDone', AdsDone);\n\n/*\nThe snapshot feature is responsible for saving the player state before an ad, then\nrestoring the player state after an ad.\n*/\nvar tryToResumeTimeout_;\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;\n if ((video_js__WEBPACK_IMPORTED_MODULE_0___default().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 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 sources: player.currentSources(),\n src: player.tech_.src(),\n currentTime: currentTime,\n type: player.currentType()\n };\n if (tech) {\n snapshotObject.style = tech.getAttribute('style');\n }\n for (var i = 0; i < tracks.length; i++) {\n var track = tracks[i];\n suppressedTracks.push({\n track: track,\n mode: track.mode\n });\n track.mode = 'disabled';\n }\n snapshotObject.suppressedTracks = suppressedTracks;\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, callback) {\n var snapshotObject = player.ads.snapshot;\n if (callback === undefined) {\n callback = function callback() {};\n }\n if (player.ads.disableNextSnapshotRestore === true) {\n player.ads.disableNextSnapshotRestore = false;\n delete player.ads.snapshot;\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 var suppressedTracks = snapshotObject.suppressedTracks;\n var trackSnapshot;\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;\n\n // Live video on iOS has special logic to try to seek to the right place after\n // an ad.\n if ((video_js__WEBPACK_IMPORTED_MODULE_0___default().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 // iOS live play after restore if player was paused (would not be paused if\n // ad played muted behind ad)\n if (player.paused()) {\n var playPromise = player.play();\n if (playPromise && playPromise.catch) {\n playPromise.catch(function (error) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Play promise rejected in IOS snapshot resume', error);\n });\n }\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 if (_playPromise && _playPromise.catch) {\n _playPromise.catch(function (error) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().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 // 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 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 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 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 player.ads.error({\n errorType: Error$1.AdsResumeContentFailed,\n error: e\n });\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Failed to resume the content after an advertisement', e);\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', function () {\n delete player.ads.snapshot;\n callback();\n });\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 // This is done directly on the html5 tech because if the integration has set\n // normalizeAutoplay to true, the async play request via autoplay -> manualAutoplay_\n // causes a visible skipback of the content after the ad break\n if ((video_js__WEBPACK_IMPORTED_MODULE_0___default().browser).IS_IOS && !player.autoplay() && typeof player.techCall_ === 'function') {\n player.techCall_('setAutoplay', 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(snapshotObject.sources);\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 if (playPromise && playPromise.catch) {\n playPromise.catch(function (error) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Play promise rejected in snapshot restore', error);\n });\n }\n }\n\n // snapshot restore is complete\n delete player.ads.snapshot;\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 */\nfunction start(player) {\n player.ads.debug('Starting ad break');\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.shouldTakeSnapshots()) {\n player.ads.snapshot = getPlayerSnapshot(player);\n }\n\n // Mute the player behind the ad\n if (player.ads.shouldPlayContentBehindAd(player) && !player.ads.settings.stitchedAds) {\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 // Ensure ads are watched at x1 speed and speed cannot be changed for the duration of the ad\n player.ads.preAdPlaybackRate_ = player.playbackRate();\n player.playbackRate(1);\n if (player.controlBar && player.controlBar.playbackRateMenuButton && player.controlBar.playbackRateMenuButton.playbackRateSupported && !player.controlBar.playbackRateMenuButton.hasClass('vjs-hidden')) {\n player.controlBar.playbackRateMenuButton.hide();\n player.ads.showPlaybackMenuOnAdEnd_ = true;\n } else {\n player.ads.showPlaybackMenuOnAdEnd_ = false;\n }\n}\nfunction end(player, callback) {\n player.ads.debug('Ending ad break');\n if (callback === undefined) {\n callback = function callback() {};\n }\n player.ads.adType = null;\n player.ads._inLinearAdMode = false;\n\n // Signals the end of the ad break to anyone listening.\n player.trigger('adend');\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.shouldTakeSnapshots()) {\n restorePlayerSnapshot(player, callback);\n\n // Reset the volume to pre-ad levels\n } else {\n if (player.ads.preAdVolume_) {\n player.volume(player.ads.preAdVolume_);\n }\n callback();\n }\n\n // Reset playback\n player.playbackRate(player.ads.preAdPlaybackRate_);\n if (player.ads.showPlaybackMenuOnAdEnd_) {\n player.controlBar.playbackRateMenuButton.show();\n }\n}\nvar obj$1 = {\n start: start,\n end: end\n};\n\nvar AdState$1 = States.getState('AdState');\n\n/*\n * This state encapsulates waiting for prerolls, preroll playback, and\n * content restoration after a preroll.\n */\nvar Preroll = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(Preroll, _AdState);\n function Preroll() {\n return _AdState.apply(this, arguments) || this;\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 var _proto = Preroll.prototype;\n _proto.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 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 _proto.onAdsReady = function onAdsReady(player) {\n if (!player.ads.inAdBreak()) {\n player.ads.debug('Received adsready event (Preroll)');\n this.handleAdsReady();\n } else {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected adsready event (Preroll)');\n }\n }\n\n /*\n * Ad plugin is ready. Let's get started on this preroll.\n */;\n _proto.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 _proto.afterLoadStart = function afterLoadStart(callback) {\n var player = this.player;\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 _proto.noPreroll = function noPreroll() {\n var _this = this;\n this.afterLoadStart(function () {\n _this.player.ads.debug('Skipping prerolls due to nopreroll event (Preroll)');\n _this.resumeAfterNoPreroll(_this.player);\n });\n }\n\n /*\n * Fire the readyforpreroll event. If loadstart hasn't happened yet,\n * wait until loadstart first.\n */;\n _proto.readyForPreroll = function readyForPreroll() {\n var player = this.player;\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 _proto.onAdsCanceled = function onAdsCanceled(player) {\n var _this2 = this;\n player.ads.debug('adscanceled (Preroll)');\n this.afterLoadStart(function () {\n _this2.resumeAfterNoPreroll(player);\n });\n }\n\n /*\n * An ad error occured. Play content instead.\n */;\n _proto.onAdsError = function onAdsError(player) {\n var _this3 = this;\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log('adserror (Preroll)');\n player.ads.error({\n errorType: Error$1.AdsPrerollError\n });\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 (this.inAdBreak()) {\n player.ads.endLinearAdMode();\n } else {\n this.afterLoadStart(function () {\n _this3.resumeAfterNoPreroll(player);\n });\n }\n }\n /*\n * Ad plugin invoked startLinearAdMode, the ad break starts now.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n var player = this.player;\n if (this.adsReady && !player.ads.inAdBreak() && !this.isContentResuming()) {\n this.clearTimeout(player);\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 video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected startLinearAdMode invocation (Preroll)');\n }\n }\n\n /*\n * An ad has actually started playing.\n * Remove the loading spinner.\n */;\n _proto.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 _proto.endLinearAdMode = function endLinearAdMode() {\n var player = this.player;\n if (this.inAdBreak()) {\n player.removeClass('vjs-ad-loading');\n player.addClass('vjs-ad-content-resuming');\n this.contentResuming = true;\n obj$1.end(player);\n }\n }\n\n /*\n * Ad skipped by ad plugin. Play content instead.\n */;\n _proto.skipLinearAdMode = function skipLinearAdMode() {\n var _this4 = this;\n var player = this.player;\n if (player.ads.inAdBreak() || this.isContentResuming()) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected skipLinearAdMode invocation');\n } else {\n this.afterLoadStart(function () {\n player.trigger('adskip');\n player.ads.debug('skipLinearAdMode (Preroll)');\n _this4.resumeAfterNoPreroll(player);\n });\n }\n }\n\n /*\n * Prerolls took too long! Play content instead.\n */;\n _proto.onAdTimeout = function onAdTimeout(player) {\n var _this5 = this;\n this.afterLoadStart(function () {\n player.ads.debug('adtimeout (Preroll)');\n _this5.resumeAfterNoPreroll(player);\n });\n }\n\n /*\n * Check if nopreroll event was too late before handling it.\n */;\n _proto.onNoPreroll = function onNoPreroll(player) {\n if (player.ads.inAdBreak() || this.isContentResuming()) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected nopreroll event (Preroll)');\n } else {\n this.noPreroll();\n }\n };\n _proto.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 this.cleanupPartial(player);\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.ads._playRequested || player.ads._pausedOnContentupdate) {\n if (player.paused()) {\n player.ads.debug('resumeAfterNoPreroll: attempting to resume playback (Preroll)');\n var playPromise = player.play();\n if (playPromise && playPromise.then) {\n playPromise.then(null, function (e) {});\n }\n } else {\n player.ads.debug('resumeAfterNoPreroll: already playing (Preroll)');\n player.trigger('play');\n player.trigger('playing');\n }\n }\n }\n\n /*\n * Cleanup timeouts and spinner.\n */;\n _proto.cleanup = function cleanup(player) {\n if (!player.ads._hasThereBeenALoadStartDuringPlayerLife) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Leaving Preroll state before loadstart event can cause issues.');\n }\n this.cleanupPartial(player);\n }\n\n /*\n * Performs cleanup tasks without depending on a state transition. This is\n * used mainly in cases where a preroll failed.\n */;\n _proto.cleanupPartial = function cleanupPartial(player) {\n player.removeClass('vjs-ad-loading');\n player.removeClass('vjs-ad-content-resuming');\n this.clearTimeout(player);\n }\n\n /*\n * Clear the preroll timeout and nulls out the pointer.\n */;\n _proto.clearTimeout = function clearTimeout(player) {\n player.clearTimeout(this._timeout);\n this._timeout = null;\n };\n return Preroll;\n}(AdState$1);\nStates.registerState('Preroll', Preroll);\n\nvar ContentState$2 = States.getState('ContentState');\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 */\nvar BeforePreroll = /*#__PURE__*/function (_ContentState) {\n _inheritsLoose(BeforePreroll, _ContentState);\n function BeforePreroll() {\n return _ContentState.apply(this, arguments) || this;\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 var _proto = BeforePreroll.prototype;\n _proto.init = function init(player) {\n this.adsReady = false;\n this.shouldResumeToContent = false;\n\n // Content playback should be blocked by callPlay() middleware if the allowVjsAutoplay\n // option hasn't been provided and autoplay is not desired.\n player.ads._shouldBlockPlay = player.ads.settings.allowVjsAutoplay ? !player.autoplay() : 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 _proto.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 _proto.onPlay = function onPlay(player) {\n var Preroll = States.getState('Preroll');\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 _proto.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 _proto.onAdsError = function onAdsError() {\n this.player.ads.debug('adserror (BeforePreroll)');\n this.player.ads.error({\n errorType: Error$1.AdsBeforePrerollError\n });\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 _proto.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 _proto.skipLinearAdMode = function skipLinearAdMode() {\n var player = this.player;\n player.trigger('adskip');\n player.ads.debug('skipLinearAdMode (BeforePreroll)');\n this.shouldResumeToContent = true;\n };\n _proto.onContentChanged = function onContentChanged() {\n this.init(this.player);\n };\n return BeforePreroll;\n}(ContentState$2);\nStates.registerState('BeforePreroll', BeforePreroll);\n\nvar AdState$2 = States.getState('AdState');\nvar Midroll = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(Midroll, _AdState);\n function Midroll() {\n return _AdState.apply(this, arguments) || this;\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 var _proto = Midroll.prototype;\n _proto.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 _proto.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n }\n\n /*\n * Midroll break is done.\n */;\n _proto.endLinearAdMode = function endLinearAdMode() {\n var player = this.player;\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 _proto.onAdsError = function onAdsError(player) {\n player.ads.error({\n errorType: Error$1.AdsMidrollError\n });\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 (this.inAdBreak()) {\n player.ads.endLinearAdMode();\n }\n }\n\n /*\n * Cleanup CSS classes.\n */;\n _proto.cleanup = function cleanup(player) {\n player.removeClass('vjs-ad-loading');\n player.removeClass('vjs-ad-content-resuming');\n };\n return Midroll;\n}(AdState$2);\nStates.registerState('Midroll', Midroll);\n\nvar AdState$3 = States.getState('AdState');\nvar Postroll = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(Postroll, _AdState);\n function Postroll() {\n return _AdState.apply(this, arguments) || this;\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 var _proto = Postroll.prototype;\n _proto.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 if (typeof player.ads.settings.postrollTimeout === 'number') {\n timeout = player.ads.settings.postrollTimeout;\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 var AdsDone = States.getState('AdsDone');\n this.transitionTo(AdsDone);\n }\n }\n\n /*\n * Start the postroll if it's not too late.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n var player = this.player;\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 video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected startLinearAdMode invocation (Postroll)');\n }\n }\n\n /*\n * An ad has actually started playing.\n * Remove the loading spinner.\n */;\n _proto.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n }\n\n /*\n * Ending a postroll triggers the ended event.\n */;\n _proto.endLinearAdMode = function endLinearAdMode() {\n var _this = this;\n var player = this.player;\n var AdsDone = States.getState('AdsDone');\n if (this.inAdBreak()) {\n player.removeClass('vjs-ad-loading');\n this.resumeContent(player);\n obj$1.end(player, function () {\n _this.transitionTo(AdsDone);\n });\n }\n }\n\n /*\n * Postroll skipped, time to clean up.\n */;\n _proto.skipLinearAdMode = function skipLinearAdMode() {\n var player = this.player;\n if (player.ads.inAdBreak() || this.isContentResuming()) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().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 _proto.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 _proto.onAdsError = function onAdsError(player) {\n player.ads.debug('Postroll abort (adserror)');\n player.ads.error({\n errorType: Error$1.AdsPostrollError\n });\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 _proto.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 var BeforePreroll = States.getState('BeforePreroll');\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 var Preroll = States.getState('Preroll');\n this.transitionTo(Preroll);\n }\n }\n\n /*\n * Wrap up if there is no postroll.\n */;\n _proto.onNoPostroll = function onNoPostroll(player) {\n if (!this.isContentResuming() && !this.inAdBreak()) {\n this.abort(player);\n } else {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected nopostroll event (Postroll)');\n }\n };\n _proto.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 _proto.abort = function abort(player) {\n var AdsDone = States.getState('AdsDone');\n this.resumeContent(player);\n player.removeClass('vjs-ad-loading');\n this.transitionTo(AdsDone);\n }\n\n /*\n * Cleanup timeouts and state.\n */;\n _proto.cleanup = function cleanup(player) {\n player.removeClass('vjs-ad-content-resuming');\n player.clearTimeout(this._postrollTimeout);\n player.ads._contentEnding = false;\n };\n return Postroll;\n}(AdState$3);\nStates.registerState('Postroll', Postroll);\n\nvar ContentState$3 = States.getState('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 */\nvar ContentPlayback = /*#__PURE__*/function (_ContentState) {\n _inheritsLoose(ContentPlayback, _ContentState);\n function ContentPlayback() {\n return _ContentState.apply(this, arguments) || this;\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 var _proto = ContentPlayback.prototype;\n _proto.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 _proto.onAdsReady = function onAdsReady(player) {\n player.ads.debug('Received adsready event (ContentPlayback)');\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 _proto.onReadyForPostroll = function onReadyForPostroll(player) {\n var Postroll = States.getState('Postroll');\n player.ads.debug('Received readyforpostroll event');\n this.transitionTo(Postroll);\n }\n\n /*\n * This is how midrolls start.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n var Midroll = States.getState('Midroll');\n this.transitionTo(Midroll);\n };\n return ContentPlayback;\n}(ContentState$3);\nStates.registerState('ContentPlayback', ContentPlayback);\n\nvar ContentState$4 = States.getState('ContentState');\n\n/*\n * This state represents content playback when stitched ads are in play.\n */\nvar StitchedContentPlayback = /*#__PURE__*/function (_ContentState) {\n _inheritsLoose(StitchedContentPlayback, _ContentState);\n function StitchedContentPlayback() {\n return _ContentState.apply(this, arguments) || this;\n }\n /*\n * Allows state name to be logged even after minification.\n */\n StitchedContentPlayback._getName = function _getName() {\n return 'StitchedContentPlayback';\n }\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */;\n var _proto = StitchedContentPlayback.prototype;\n _proto.init = function init() {\n // Don't block calls to play in stitched ad players, ever.\n this.player.ads._shouldBlockPlay = false;\n }\n\n /*\n * Source change does not do anything for stitched ad players.\n * contentchanged does not fire during ad breaks, so we don't need to\n * worry about that.\n */;\n _proto.onContentChanged = function onContentChanged() {\n this.player.ads.debug(\"Received contentchanged event (\" + this.constructor._getName() + \")\");\n }\n\n /*\n * This is how stitched ads start.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n var StitchedAdRoll = States.getState('StitchedAdRoll');\n this.transitionTo(StitchedAdRoll);\n };\n return StitchedContentPlayback;\n}(ContentState$4);\nStates.registerState('StitchedContentPlayback', StitchedContentPlayback);\n\nvar AdState$4 = States.getState('AdState');\nvar StitchedAdRoll = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(StitchedAdRoll, _AdState);\n function StitchedAdRoll() {\n return _AdState.apply(this, arguments) || this;\n }\n /*\n * Allows state name to be logged even after minification.\n */\n StitchedAdRoll._getName = function _getName() {\n return 'StitchedAdRoll';\n }\n\n /*\n * StitchedAdRoll breaks happen when the ad plugin calls startLinearAdMode,\n * which can happen at any time during content playback.\n */;\n var _proto = StitchedAdRoll.prototype;\n _proto.init = function init() {\n this.waitingForAdBreak = false;\n this.contentResuming = false;\n this.player.ads.adType = 'stitched';\n obj$1.start(this.player);\n }\n\n /*\n * For stitched ads, there is no \"content resuming\" scenario, so a \"playing\"\n * event is not relevant.\n */;\n _proto.onPlaying = function onPlaying() {}\n\n /*\n * For stitched ads, there is no \"content resuming\" scenario, so a\n * \"contentresumed\" event is not relevant.\n */;\n _proto.onContentResumed = function onContentResumed() {}\n\n /*\n * When we see an \"adended\" event, it means that we are in a postroll that\n * has ended (because the media ended and we are still in an ad state).\n *\n * In these cases, we transition back to content mode and fire ended.\n */;\n _proto.onAdEnded = function onAdEnded() {\n this.endLinearAdMode();\n this.player.trigger('ended');\n }\n\n /*\n * StitchedAdRoll break is done.\n */;\n _proto.endLinearAdMode = function endLinearAdMode() {\n var StitchedContentPlayback = States.getState('StitchedContentPlayback');\n obj$1.end(this.player);\n this.transitionTo(StitchedContentPlayback);\n };\n return StitchedAdRoll;\n}(AdState$4);\nStates.registerState('StitchedAdRoll', StitchedAdRoll);\n\nvar AdState$5 = States.getState('AdState');\n\n/**\n * This is the initial state for a player in outstream mode. Once a 'play' event\n * is seen, we enter the OutstreamPlayback state. If any errors occur, we go\n * straight from OutstreamPlayback to OutstreamDone.\n */\nvar OutstreamPending = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(OutstreamPending, _AdState);\n function OutstreamPending() {\n return _AdState.apply(this, arguments) || this;\n }\n /**\n * Allows state name to be logged after minification\n */\n OutstreamPending._getName = function _getName() {\n return 'OutstreamPending';\n }\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */;\n var _proto = OutstreamPending.prototype;\n _proto.init = function init(player) {\n this.adsReady = false;\n };\n _proto.onPlay = function onPlay(player) {\n var OutstreamPlayback = States.getState('OutstreamPlayback');\n player.ads.debug('Received play event (OutstreamPending)');\n this.transitionTo(OutstreamPlayback, this.adsReady);\n };\n _proto.onAdsReady = function onAdsReady(player) {\n player.ads.debug('Received adsready event (OutstreamPending)');\n this.adsReady = true;\n };\n _proto.onAdsError = function onAdsError() {\n this.player.ads.debug('adserror (OutstreamPending)');\n this.adsReady = false;\n };\n return OutstreamPending;\n}(AdState$5);\nStates.registerState('OutstreamPending', OutstreamPending);\n\nvar AdState$6 = States.getState('AdState');\n\n/**\n * This state is for waiting for ads in an outstream player,\n * playing ads, and transitioning to OutstreamDone after ads have played.\n */\nvar OutstreamPlayback = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(OutstreamPlayback, _AdState);\n function OutstreamPlayback() {\n return _AdState.apply(this, arguments) || this;\n }\n /**\n * Allows state name to be logged after minification\n */\n OutstreamPlayback._getName = function _getName() {\n return 'OutstreamPlayback';\n }\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */;\n var _proto = OutstreamPlayback.prototype;\n _proto.init = function init(player, adsReady) {\n player.addClass('vjs-ad-loading');\n if (adsReady) {\n this.handleAdsReady();\n } else {\n this.abort(player);\n }\n };\n _proto.onAdsReady = function onAdsReady(player) {\n if (!player.ads.inAdBreak()) {\n player.ads.debug('Received adsready event (Preroll)');\n this.handleAdsReady();\n } else {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected adsready event (Preroll)');\n }\n };\n _proto.abort = function abort(player) {\n var OutstreamDone = States.getState('OutstreamDone');\n player.removeClass('vjs-ad-loading');\n this.transitionTo(OutstreamDone);\n }\n\n /*\n * An ad has actually started playing.\n * Remove the loading spinner.\n */;\n _proto.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n };\n _proto.handleAdsReady = function handleAdsReady() {\n this.adsReady = true;\n this.readyForOutstreamPlayback();\n };\n _proto.readyForOutstreamPlayback = function readyForOutstreamPlayback() {\n var player = this.player;\n this.afterLoadStart(function () {\n player.trigger('readyforoutstream');\n });\n };\n _proto.startLinearAdMode = function startLinearAdMode() {\n var player = this.player;\n if (this.adsReady && !player.ads.inAdBreak()) {\n obj$1.start(player);\n }\n }\n\n /*\n * Cleanup timeouts and spinner.\n */;\n _proto.cleanup = function cleanup(player) {\n if (!player.ads._hasThereBeenALoadStartDuringPlayerLife) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Leaving OutstreamPlayback state before loadstart event can cause issues.');\n }\n this.cleanupPartial(player);\n }\n\n /*\n * Performs cleanup tasks without depending on a state transition. This is\n * used mainly in cases where a preroll failed.\n */;\n _proto.cleanupPartial = function cleanupPartial(player) {\n player.removeClass('vjs-ad-loading');\n player.removeClass('vjs-ad-content-resuming');\n this.clearTimeout(player);\n }\n\n /*\n * Clear the outstream ad timeout and nulls out the pointer.\n */;\n _proto.clearTimeout = function clearTimeout(player) {\n player.clearTimeout(this._timeout);\n this._timeout = null;\n };\n _proto.onAdStarted = function onAdStarted(player) {\n player.removeClass('vjs-ad-loading');\n }\n\n /*\n * An ad error occured. Transition straight to OutstreamDone\n */;\n _proto.onAdsError = function onAdsError(player) {\n var _this = this;\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log('adserror (OutstreamPlayback)');\n if (this.inAdBreak()) {\n player.ads.endLinearAdMode();\n } else {\n this.afterLoadStart(function () {\n _this.abort(player);\n });\n }\n }\n\n /*\n * Outstream ad took too long! Play content instead.\n */;\n _proto.onAdTimeout = function onAdTimeout(player) {\n var _this2 = this;\n this.afterLoadStart(function () {\n player.ads.debug('adtimeout (OutstreamPlayback)');\n _this2.abort(player);\n });\n };\n _proto.onAdsCanceled = function onAdsCanceled(player) {\n var _this3 = this;\n player.ads.debug('adscanceled (OutstreamPlaybac)');\n this.afterLoadStart(function () {\n _this3.abort(player);\n });\n };\n _proto.endLinearAdMode = function endLinearAdMode() {\n var _this4 = this;\n if (this.inAdBreak()) {\n this.player.removeClass('vjs-ad-loading');\n var OutstreamDone = States.getState('OutstreamDone');\n obj$1.end(this.player, function () {\n _this4.transitionTo(OutstreamDone);\n });\n }\n };\n _proto.afterLoadStart = function afterLoadStart(callback) {\n var player = this.player;\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 * Ad plugin has skipped ad - transition to OutstreamDone\n */;\n _proto.skipLinearAdMode = function skipLinearAdMode() {\n var _this5 = this;\n var player = this.player;\n var OutstreamDone = States.getState('OutstreamDone');\n if (this.inAdBreak()) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected skipLinearAdMode invocation');\n } else {\n this.afterLoadStart(function () {\n player.trigger('adskip');\n player.ads.debug('skipLinearAdMode (OutstreamPlayback)');\n _this5.transitionTo(OutstreamDone);\n });\n }\n };\n return OutstreamPlayback;\n}(AdState$6);\nStates.registerState('OutstreamPlayback', OutstreamPlayback);\n\nvar AdState$7 = States.getState('AdState');\n\n/**\n * This is the final state for a player in outstream mode. There\n * should be no more ads playing once the player has transitioned\n * to this state.\n */\nvar OutstreamDone = /*#__PURE__*/function (_AdState) {\n _inheritsLoose(OutstreamDone, _AdState);\n function OutstreamDone() {\n return _AdState.apply(this, arguments) || this;\n }\n /**\n * Allows state name to be logged after minification\n */\n OutstreamDone._getName = function _getName() {\n return 'OutstreamDone';\n }\n\n /*\n * For state transitions to work correctly, initialization should\n * happen here, not in a constructor.\n */;\n var _proto = OutstreamDone.prototype;\n _proto.init = function init(player) {\n player.trigger('ended');\n }\n\n /*\n * No more ads should play after this state.\n */;\n _proto.startLinearAdMode = function startLinearAdMode() {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Unexpected startLinearAdMode invocation (OutstreamDone)');\n };\n return OutstreamDone;\n}(AdState$7);\nStates.registerState('OutstreamDone', OutstreamDone);\n\n/*\nThis main plugin file is responsible for the public API and enabling the features\nthat live in in separate files.\n*/\nvar isMiddlewareMediatorSupported$1 = obj.isMiddlewareMediatorSupported;\nvar VIDEO_EVENTS = video_js__WEBPACK_IMPORTED_MODULE_0___default().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 // 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 // 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 // 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 // Set this to true when using ads that are part of the content video\n stitchedAds: false,\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 // If set to true, content will play muted behind ads on supported platforms. This is\n // to support ads on video metadata cuepoints during a live stream. It also results in\n // more precise resumes after ads during a live stream.\n liveCuePoints: true,\n // If set to true, callPlay middleware will not terminate the first play request in\n // BeforePreroll if the player intends to autoplay. This allows the manual autoplay\n // attempt made by video.js to resolve/reject naturally and trigger an 'autoplay-success'\n // or 'autoplay-failure' event with which other plugins can interface.\n allowVjsAutoplay: (video_js__WEBPACK_IMPORTED_MODULE_0___default().options).normalizeAutoplay || false\n};\nvar contribAdsPlugin = function contribAdsPlugin(options) {\n var player = this; // eslint-disable-line consistent-this\n\n var settings = video_js__WEBPACK_IMPORTED_MODULE_0___default().obj.merge(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 = [];\n\n // dedupe event names\n VIDEO_EVENTS.concat(['firstplay', 'loadedalldata']).forEach(function (eventName) {\n if (videoEvents.indexOf(eventName) === -1) {\n videoEvents.push(eventName);\n }\n });\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$1()) {\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 video_js__WEBPACK_IMPORTED_MODULE_0___default().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 // We don't need to handle this for stitched ads because\n // linear ads in such cases are stitched into the content.\n if (player.ads.settings.stitchedAds) {\n return;\n }\n // Some techs may retrigger canplay after playback has begun.\n // So we want to procceed only if playback hasn't started.\n if (player.hasStarted()) {\n return;\n }\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 var playPromise = player.play();\n if (playPromise && playPromise.catch) {\n playPromise.catch(function (error) {\n video_js__WEBPACK_IMPORTED_MODULE_0___default().log.warn('Play promise rejected when playing ad', error);\n });\n }\n });\n player.on('nopreroll', function () {\n player.ads.debug('Received nopreroll event');\n player.ads.nopreroll_ = true;\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 player.one('loadstart', function () {\n player.ads._hasThereBeenALoadStartDuringPlayerLife = true;\n });\n player.on('loadeddata', function () {\n player.ads._hasThereBeenALoadedData = true;\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 player.ads.settings = settings;\n\n // Set the stitched ads state. This needs to happen before the `_state` is\n // initialized below - BeforePreroll needs to know whether contrib-ads is\n // playing stitched ads or not.\n // The setter is deprecated, so this does not use it.\n // But first, cast to boolean.\n settings.stitchedAds = !!settings.stitchedAds;\n if (settings.playerMode === 'outstream') {\n // Set a 0s mp4 file to enable ads to play\n player.src(OUTSTREAM_VIDEO);\n player.ads._state = new (States.getState('OutstreamPending'))(player);\n } else if (settings.stitchedAds) {\n player.ads._state = new (States.getState('StitchedContentPlayback'))(player);\n } else {\n player.ads._state = new (States.getState('BeforePreroll'))(player);\n }\n player.ads._state.init(player);\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 && (video_js__WEBPACK_IMPORTED_MODULE_0___default().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 if (shouldDisableTracks()) {\n // We must double check all tracks\n for (var i = 0; i < textTrackList.length; i++) {\n var track = textTrackList[i];\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', 'adended', 'ads-ad-started', 'ads-ad-skipped', 'contentchanged', 'dispose', '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.ads.reset();\n player.textTracks().removeEventListener('change', textTrackChangeHandler);\n });\n\n // Listen to TCF changes\n listenToTcf();\n\n // Initialize the US Privacy string\n obtainUsPrivacyString(function () {});\n\n // Can be called for testing, or if the TCF CMP has loaded late\n player.ads.listenToTcf = listenToTcf;\n\n // Expose so the US privacy string can be updated as needed\n player.ads.updateUsPrivacyString = function (callback) {\n return obtainUsPrivacyString(callback);\n };\n};\n\n// contrib-ads specific error const\ncontribAdsPlugin.Error = Error$1;\n\n// Expose the contrib-ads version before it is initialized. Will be replaced\n// after initialization in ads.js\ncontribAdsPlugin.VERSION = version;\n\n// Attempt to register the plugin, if we can.\nregister(contribAdsPlugin);\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (contribAdsPlugin);\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/videojs-contrib-ads/dist/videojs-contrib-ads.es.js?");
44
66
 
45
- /***/ },
67
+ /***/ }),
46
68
 
47
- /***/ "../node_modules/videojs-ima/dist/videojs.ima.es.js"
69
+ /***/ "../node_modules/videojs-ima/dist/videojs.ima.es.js":
48
70
  /*!**********************************************************!*\
49
71
  !*** ../node_modules/videojs-ima/dist/videojs.ima.es.js ***!
50
72
  \**********************************************************/
51
- (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
52
-
53
- "use strict";
54
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LiveStream: () => (/* binding */ LiveStream),\n/* harmony export */ VodStream: () => (/* binding */ VodStream),\n/* harmony export */ \"default\": () => (/* binding */ ImaPlugin)\n/* harmony export */ });\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\");\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(video_js__WEBPACK_IMPORTED_MODULE_0__);\n\n\nfunction _arrayLikeToArray(r, a) {\n (null == a || a > r.length) && (a = r.length);\n for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];\n return n;\n}\nfunction _classCallCheck(a, n) {\n if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\");\n}\nfunction _createClass(e, r, t) {\n return Object.defineProperty(e, \"prototype\", {\n writable: false\n }), e;\n}\nfunction _createForOfIteratorHelper(r, e) {\n var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"];\n if (!t) {\n if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) {\n t && (r = t);\n var n = 0,\n F = function () {};\n return {\n s: F,\n n: function () {\n return n >= r.length ? {\n done: true\n } : {\n done: false,\n value: r[n++]\n };\n },\n e: function (r) {\n throw r;\n },\n f: F\n };\n }\n throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n }\n var o,\n a = true,\n u = false;\n return {\n s: function () {\n t = t.call(r);\n },\n n: function () {\n var r = t.next();\n return a = r.done, r;\n },\n e: function (r) {\n u = true, o = r;\n },\n f: function () {\n try {\n a || null == t.return || t.return();\n } finally {\n if (u) throw o;\n }\n }\n };\n}\nfunction _typeof(o) {\n \"@babel/helpers - typeof\";\n\n return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) {\n return typeof o;\n } : function (o) {\n return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o;\n }, _typeof(o);\n}\nfunction _unsupportedIterableToArray(r, a) {\n if (r) {\n if (\"string\" == typeof r) return _arrayLikeToArray(r, a);\n var t = {}.toString.call(r).slice(8, -1);\n return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;\n }\n}\n\n/**\n * Copyright 2017 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/**\n * Wraps the video.js player for the plugin.\n *\n * @param {Object} player Video.js player instance.\n * @param {Object} adsPluginSettings Settings for the contrib-ads plugin.\n * @param {Controller} controller Reference to the parent controller.\n */\nvar PlayerWrapper$1 = function PlayerWrapper(player, adsPluginSettings, controller) {\n /**\n * Instance of the video.js player.\n */\n this.vjsPlayer = player;\n\n /**\n * Plugin controller.\n */\n this.controller = controller;\n\n /**\n * Timer used to track content progress.\n */\n this.contentTrackingTimer = null;\n\n /**\n * True if our content video has completed, false otherwise.\n */\n this.contentComplete = false;\n\n /**\n * Handle to interval that repeatedly updates current time.\n */\n this.updateTimeIntervalHandle = null;\n\n /**\n * Interval (ms) to check for player resize for fluid support.\n */\n this.updateTimeInterval = 1000;\n\n /**\n * Handle to interval that repeatedly checks for seeking.\n */\n this.seekCheckIntervalHandle = null;\n\n /**\n * Interval (ms) on which to check if the user is seeking through the\n * content.\n */\n this.seekCheckInterval = 1000;\n\n /**\n * Handle to interval that repeatedly checks for player resize.\n */\n this.resizeCheckIntervalHandle = null;\n\n /**\n * Interval (ms) to check for player resize for fluid support.\n */\n this.resizeCheckInterval = 250;\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 this.seekThreshold = 100;\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 this.contentEndedListeners = [];\n\n /**\n * Stores the content source so we can re-populate it manually after a\n * post-roll on iOS.\n */\n this.contentSource = '';\n\n /**\n * Stores the content source type so we can re-populate it manually after a\n * post-roll.\n */\n this.contentSourceType = '';\n\n /**\n * Stores data for the content playhead tracker.\n */\n this.contentPlayheadTracker = {\n currentTime: 0,\n previousTime: 0,\n seeking: false,\n duration: 0\n };\n\n /**\n * Player dimensions. Used in our resize check.\n */\n this.vjsPlayerDimensions = {\n width: this.getPlayerWidth(),\n height: this.getPlayerHeight()\n };\n\n /**\n * Video.js control bar.\n */\n this.vjsControls = this.vjsPlayer.getChild('controlBar');\n\n /**\n * Vanilla HTML5 video player underneath the video.js player.\n */\n this.h5Player = null;\n this.vjsPlayer.one('play', this.setUpPlayerIntervals.bind(this));\n this.boundContentEndedListener = this.localContentEndedListener.bind(this);\n this.vjsPlayer.on('readyforpostroll', this.boundContentEndedListener);\n this.vjsPlayer.on('dispose', this.playerDisposedListener.bind(this));\n this.vjsPlayer.on('readyforpreroll', this.onReadyForPreroll.bind(this));\n this.vjsPlayer.on('adtimeout', this.onAdTimeout.bind(this));\n this.vjsPlayer.ready(this.onPlayerReady.bind(this));\n if (this.controller.getSettings().requestMode === 'onPlay') {\n this.vjsPlayer.one('play', this.controller.requestAds.bind(this.controller));\n }\n if (!this.vjsPlayer.ads) {\n window.console.warn('You may be using a version of videojs-contrib-ads ' + 'that is not compatible with your version of video.js.');\n }\n this.vjsPlayer.ads(adsPluginSettings);\n};\n\n/**\n * Set up the intervals we use on the player.\n */\nPlayerWrapper$1.prototype.setUpPlayerIntervals = function () {\n /**\n * Clear old interval handers in case the method was called more than once\n */\n if (this.updateTimeIntervalHandle) {\n clearInterval(this.updateTimeIntervalHandle);\n }\n if (this.seekCheckIntervalHandle) {\n clearInterval(this.seekCheckIntervalHandle);\n }\n if (this.resizeCheckIntervalHandle) {\n clearInterval(this.resizeCheckIntervalHandle);\n }\n this.updateTimeIntervalHandle = setInterval(this.updateCurrentTime.bind(this), this.updateTimeInterval);\n this.seekCheckIntervalHandle = setInterval(this.checkForSeeking.bind(this), this.seekCheckInterval);\n this.resizeCheckIntervalHandle = setInterval(this.checkForResize.bind(this), this.resizeCheckInterval);\n};\n\n/**\n * Updates the current time of the video\n */\nPlayerWrapper$1.prototype.updateCurrentTime = function () {\n if (!this.contentPlayheadTracker.seeking) {\n this.contentPlayheadTracker.currentTime = this.vjsPlayer.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 */\nPlayerWrapper$1.prototype.checkForSeeking = function () {\n var tempCurrentTime = this.vjsPlayer.currentTime();\n var diff = (tempCurrentTime - this.contentPlayheadTracker.previousTime) * 1000;\n if (Math.abs(diff) > this.seekCheckInterval + this.seekThreshold) {\n this.contentPlayheadTracker.seeking = true;\n } else {\n this.contentPlayheadTracker.seeking = false;\n }\n this.contentPlayheadTracker.previousTime = this.vjsPlayer.currentTime();\n};\n\n/**\n * Detects when the player is resized (for fluid support) and resizes the\n * ads manager to match.\n */\nPlayerWrapper$1.prototype.checkForResize = function () {\n var currentWidth = this.getPlayerWidth();\n var currentHeight = this.getPlayerHeight();\n if (currentWidth != this.vjsPlayerDimensions.width || currentHeight != this.vjsPlayerDimensions.height) {\n this.vjsPlayerDimensions.width = currentWidth;\n this.vjsPlayerDimensions.height = currentHeight;\n this.controller.onPlayerResize(currentWidth, currentHeight);\n }\n};\n\n/**\n * Local content ended listener for contentComplete.\n */\nPlayerWrapper$1.prototype.localContentEndedListener = function () {\n if (!this.contentComplete) {\n this.contentComplete = true;\n this.controller.onContentComplete();\n }\n for (var index in this.contentEndedListeners) {\n if (typeof this.contentEndedListeners[index] === 'function') {\n this.contentEndedListeners[index]();\n }\n }\n if (this.vjsPlayer.el()) {\n this.vjsPlayer.one('play', this.setUpPlayerIntervals.bind(this));\n }\n};\n\n/**\n * Called when it's time to play a post-roll but we don't have one to play.\n */\nPlayerWrapper$1.prototype.onNoPostroll = function () {\n this.vjsPlayer.trigger('nopostroll');\n};\n\n/**\n * Detects when the video.js player has been disposed.\n */\nPlayerWrapper$1.prototype.playerDisposedListener = function () {\n this.contentEndedListeners = [];\n this.controller.onPlayerDisposed();\n this.contentComplete = true;\n this.vjsPlayer.off('readyforpostroll', this.boundContentEndedListener);\n\n // Bug fix: https://github.com/googleads/videojs-ima/issues/306\n if (this.vjsPlayer.ads.adTimeoutTimeout) {\n clearTimeout(this.vjsPlayer.ads.adTimeoutTimeout);\n }\n var intervalsToClear = [this.updateTimeIntervalHandle, this.seekCheckIntervalHandle, this.resizeCheckIntervalHandle];\n for (var index in intervalsToClear) {\n if (intervalsToClear[index]) {\n clearInterval(intervalsToClear[index]);\n }\n }\n};\n\n/**\n * Start ad playback, or content video playback in the absence of a\n * pre-roll.\n */\nPlayerWrapper$1.prototype.onReadyForPreroll = function () {\n this.controller.onPlayerReadyForPreroll();\n};\n\n/**\n * Detects if the ad has timed out.\n */\nPlayerWrapper$1.prototype.onAdTimeout = function () {\n this.controller.onAdTimeout();\n};\n\n/**\n * Called when the player fires its 'ready' event.\n */\nPlayerWrapper$1.prototype.onPlayerReady = function () {\n this.h5Player = document.getElementById(this.getPlayerId()).getElementsByClassName('vjs-tech')[0];\n\n // Detect inline options\n if (this.h5Player.hasAttribute('autoplay')) {\n this.controller.setSetting('adWillAutoPlay', true);\n }\n\n // Sync ad volume with player volume.\n this.onVolumeChange();\n this.vjsPlayer.on('fullscreenchange', this.onFullscreenChange.bind(this));\n this.vjsPlayer.on('volumechange', this.onVolumeChange.bind(this));\n this.controller.onPlayerReady();\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 */\nPlayerWrapper$1.prototype.onFullscreenChange = function () {\n if (this.vjsPlayer.isFullscreen()) {\n this.controller.onPlayerEnterFullscreen();\n } else {\n this.controller.onPlayerExitFullscreen();\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 */\nPlayerWrapper$1.prototype.onVolumeChange = function () {\n var newVolume = this.vjsPlayer.muted() ? 0 : this.vjsPlayer.volume();\n this.controller.onPlayerVolumeChanged(newVolume);\n};\n\n/**\n * Inject the ad container div into the DOM.\n *\n * @param{HTMLElement} adContainerDiv The ad container div.\n */\nPlayerWrapper$1.prototype.injectAdContainerDiv = function (adContainerDiv) {\n this.vjsControls.el().parentNode.appendChild(adContainerDiv);\n};\n\n/**\n * @return {Object} The content player.\n */\nPlayerWrapper$1.prototype.getContentPlayer = function () {\n return this.h5Player;\n};\n\n/**\n * @return {number} The volume, 0-1.\n */\nPlayerWrapper$1.prototype.getVolume = function () {\n return this.vjsPlayer.muted() ? 0 : this.vjsPlayer.volume();\n};\n\n/**\n * Set the volume of the player. 0-1.\n *\n * @param {number} volume The new volume.\n */\nPlayerWrapper$1.prototype.setVolume = function (volume) {\n this.vjsPlayer.volume(volume);\n if (volume == 0) {\n this.vjsPlayer.muted(true);\n } else {\n this.vjsPlayer.muted(false);\n }\n};\n\n/**\n * Ummute the player.\n */\nPlayerWrapper$1.prototype.unmute = function () {\n this.vjsPlayer.muted(false);\n};\n\n/**\n * Mute the player.\n */\nPlayerWrapper$1.prototype.mute = function () {\n this.vjsPlayer.muted(true);\n};\n\n/**\n * Play the video.\n */\nPlayerWrapper$1.prototype.play = function () {\n this.vjsPlayer.play();\n};\n\n/**\n * Toggles playback of the video.\n */\nPlayerWrapper$1.prototype.togglePlayback = function () {\n if (this.vjsPlayer.paused()) {\n this.vjsPlayer.play();\n } else {\n this.vjsPlayer.pause();\n }\n};\n\n/**\n * Get the player width.\n *\n * @return {number} The player's width.\n */\nPlayerWrapper$1.prototype.getPlayerWidth = function () {\n var width = (getComputedStyle(this.vjsPlayer.el()) || {}).width;\n if (!width || parseFloat(width) === 0) {\n width = (this.vjsPlayer.el().getBoundingClientRect() || {}).width;\n }\n return parseFloat(width) || this.vjsPlayer.width();\n};\n\n/**\n * Get the player height.\n *\n * @return {number} The player's height.\n */\nPlayerWrapper$1.prototype.getPlayerHeight = function () {\n var height = (getComputedStyle(this.vjsPlayer.el()) || {}).height;\n if (!height || parseFloat(height) === 0) {\n height = (this.vjsPlayer.el().getBoundingClientRect() || {}).height;\n }\n return parseFloat(height) || this.vjsPlayer.height();\n};\n\n/**\n * @return {Object} The vjs player's options object.\n */\nPlayerWrapper$1.prototype.getPlayerOptions = function () {\n return this.vjsPlayer.options_;\n};\n\n/**\n * Returns the instance of the player id.\n * @return {string} The player id.\n */\nPlayerWrapper$1.prototype.getPlayerId = function () {\n return this.vjsPlayer.id();\n};\n\n/**\n * Toggle fullscreen state.\n */\nPlayerWrapper$1.prototype.toggleFullscreen = function () {\n if (this.vjsPlayer.isFullscreen()) {\n this.vjsPlayer.exitFullscreen();\n } else {\n this.vjsPlayer.requestFullscreen();\n }\n};\n\n/**\n * Returns the content playhead tracker.\n *\n * @return {Object} The content playhead tracker.\n */\nPlayerWrapper$1.prototype.getContentPlayheadTracker = function () {\n return this.contentPlayheadTracker;\n};\n\n/**\n * Handles ad errors.\n *\n * @param {Object} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nPlayerWrapper$1.prototype.onAdError = function (adErrorEvent) {\n this.vjsControls.show();\n var errorMessage = adErrorEvent.getError !== undefined ? adErrorEvent.getError() : adErrorEvent.stack;\n this.vjsPlayer.trigger({\n type: 'adserror',\n data: {\n AdError: errorMessage,\n AdErrorEvent: adErrorEvent\n }\n });\n};\n\n/**\n * Handles ad log messages.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the IMA SDK.\n */\nPlayerWrapper$1.prototype.onAdLog = function (adEvent) {\n var adData = adEvent.getAdData();\n var errorMessage = adData['adError'] !== undefined ? adData['adError'].getMessage() : undefined;\n this.vjsPlayer.trigger({\n type: 'adslog',\n data: {\n AdError: errorMessage,\n AdEvent: adEvent\n }\n });\n};\n\n/**\n * Handles ad break starting.\n */\nPlayerWrapper$1.prototype.onAdBreakStart = function () {\n this.contentSource = this.vjsPlayer.currentSrc();\n this.contentSourceType = this.vjsPlayer.currentType();\n this.vjsPlayer.off('readyforpostroll', this.boundContentEndedListener);\n this.vjsPlayer.ads.startLinearAdMode();\n this.vjsControls.hide();\n this.vjsPlayer.pause();\n};\n\n/**\n * Handles ad break ending.\n */\nPlayerWrapper$1.prototype.onAdBreakEnd = function () {\n this.vjsPlayer.on('readyforpostroll', this.boundContentEndedListener);\n if (this.vjsPlayer.ads.inAdBreak()) {\n this.vjsPlayer.ads.endLinearAdMode();\n }\n this.vjsControls.show();\n};\n\n/**\n * Handles an individual ad start.\n */\nPlayerWrapper$1.prototype.onAdStart = function () {\n this.vjsPlayer.trigger('ads-ad-started');\n};\n\n/**\n * Handles when all ads have finished playing.\n */\nPlayerWrapper$1.prototype.onAllAdsCompleted = function () {\n if (this.contentComplete == true) {\n // The null check on this.contentSource was added to fix\n // an error when the post-roll was an empty VAST tag.\n if (this.contentSource && this.vjsPlayer.currentSrc() != this.contentSource) {\n this.vjsPlayer.src({\n src: this.contentSource,\n type: this.contentSourceType\n });\n }\n this.controller.onContentAndAdsCompleted();\n }\n};\n\n/**\n * Triggers adsready for contrib-ads.\n */\nPlayerWrapper$1.prototype.onAdsReady = function () {\n this.vjsPlayer.trigger('adsready');\n};\n\n/**\n * Changes the player source.\n * @param {?string} contentSrc The URI for the content to be played. Leave\n * blank to use the existing content.\n */\nPlayerWrapper$1.prototype.changeSource = function (contentSrc) {\n // Only try to pause the player when initialised with a source already\n if (this.vjsPlayer.currentSrc()) {\n this.vjsPlayer.currentTime(0);\n this.vjsPlayer.pause();\n }\n if (contentSrc) {\n this.vjsPlayer.src(contentSrc);\n }\n this.vjsPlayer.one('loadedmetadata', this.seekContentToZero.bind(this));\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 */\nPlayerWrapper$1.prototype.seekContentToZero = function () {\n this.vjsPlayer.currentTime(0);\n};\n\n/**\n * Triggers an event on the VJS player\n * @param {string} name The event name.\n * @param {Object} data The event data.\n */\nPlayerWrapper$1.prototype.triggerPlayerEvent = function (name, data) {\n this.vjsPlayer.trigger(name, data);\n};\n\n/**\n * Listener JSDoc for ESLint. This listener can be passed to\n * addContentEndedListener.\n * @callback listener\n */\n\n/**\n * Adds a listener for the 'readyforpostroll' event of the video player. This\n * should be used instead of setting an 'readyforpostroll' listener directly to\n * ensure that the ima can do proper cleanup of the SDK before other event\n * listeners are called.\n * @param {listener} listener The listener to be called when content\n * completes.\n */\nPlayerWrapper$1.prototype.addContentEndedListener = function (listener) {\n this.contentEndedListeners.push(listener);\n};\n\n/**\n * Reset the player.\n */\nPlayerWrapper$1.prototype.reset = function () {\n // Attempts to remove the contentEndedListener before adding it.\n // This is to prevent an error where an erroring video caused multiple\n // contentEndedListeners to be added.\n this.vjsPlayer.off('readyforpostroll', this.boundContentEndedListener);\n this.vjsPlayer.on('readyforpostroll', this.boundContentEndedListener);\n this.vjsControls.show();\n if (this.vjsPlayer.ads.inAdBreak()) {\n this.vjsPlayer.ads.endLinearAdMode();\n }\n // Reset the content time we give the SDK. Fixes an issue where requesting\n // VMAP followed by VMAP would play the second mid-rolls as pre-rolls if\n // the first playthrough of the video passed the second response's\n // mid-roll time.\n this.contentPlayheadTracker.currentTime = 0;\n this.contentComplete = false;\n};\n\n/**\n * Copyright 2017 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/**\n * Ad UI implementation.\n *\n * @param {Controller} controller Plugin controller.\n * @constructor\n * @struct\n * @final\n */\nvar AdUi = function AdUi(controller) {\n /**\n * Plugin controller.\n */\n this.controller = controller;\n\n /**\n * Div used as an ad container.\n */\n this.adContainerDiv = document.createElement('div');\n\n /**\n * Div used to display ad controls.\n */\n this.controlsDiv = document.createElement('div');\n\n /**\n * Div used to display ad countdown timer.\n */\n this.countdownDiv = document.createElement('div');\n\n /**\n * Div used to display add seek bar.\n */\n this.seekBarDiv = document.createElement('div');\n\n /**\n * Div used to display ad progress (in seek bar).\n */\n this.progressDiv = document.createElement('div');\n\n /**\n * Div used to display ad play/pause button.\n */\n this.playPauseDiv = document.createElement('div');\n\n /**\n * Div used to display ad mute button.\n */\n this.muteDiv = document.createElement('div');\n\n /**\n * Div used by the volume slider.\n */\n this.sliderDiv = document.createElement('div');\n\n /**\n * Volume slider level visuals\n */\n this.sliderLevelDiv = document.createElement('div');\n\n /**\n * Div used to display ad fullscreen button.\n */\n this.fullscreenDiv = document.createElement('div');\n\n /**\n * Bound event handler for onMouseUp.\n */\n this.boundOnMouseUp = this.onMouseUp.bind(this);\n\n /**\n * Bound event handler for onMouseMove.\n */\n this.boundOnMouseMove = this.onMouseMove.bind(this);\n\n /**\n * Stores data for the ad playhead tracker.\n */\n this.adPlayheadTracker = {\n 'currentTime': 0,\n 'duration': 0,\n 'isPod': false,\n 'adPosition': 0,\n 'totalAds': 0\n };\n\n /**\n * Used to prefix videojs ima controls.\n */\n this.controlPrefix = this.controller.getPlayerId() + '_';\n\n /**\n * Boolean flag to show or hide the ad countdown timer.\n */\n this.showCountdown = true;\n if (this.controller.getSettings().showCountdown === false) {\n this.showCountdown = false;\n }\n\n /**\n * Boolean flag if the current ad is nonlinear.\n */\n this.isAdNonlinear = false;\n this.createAdContainer();\n};\n\n/**\n * Creates the ad container.\n */\nAdUi.prototype.createAdContainer = function () {\n this.assignControlAttributes(this.adContainerDiv, 'ima-ad-container');\n // Hide the ad container until an ad starts.\n this.adContainerDiv.classList.add('hide-ad-container');\n this.adContainerDiv.addEventListener('mouseenter', this.showAdControls.bind(this), false);\n this.adContainerDiv.addEventListener('mouseleave', this.hideAdControls.bind(this), false);\n this.adContainerDiv.addEventListener('click', this.onAdContainerClick.bind(this), false);\n this.createControls();\n this.controller.injectAdContainerDiv(this.adContainerDiv);\n};\n\n/**\n * Create the controls.\n */\nAdUi.prototype.createControls = function () {\n this.assignControlAttributes(this.controlsDiv, 'ima-controls-div');\n this.controlsDiv.style.width = '100%';\n if (!this.controller.getIsMobile()) {\n this.assignControlAttributes(this.countdownDiv, 'ima-countdown-div');\n this.countdownDiv.innerHTML = this.controller.getSettings().adLabel;\n this.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';\n } else {\n this.countdownDiv.style.display = 'none';\n }\n this.assignControlAttributes(this.seekBarDiv, 'ima-seek-bar-div');\n this.seekBarDiv.style.width = '100%';\n this.assignControlAttributes(this.progressDiv, 'ima-progress-div');\n this.assignControlAttributes(this.playPauseDiv, 'ima-play-pause-div');\n this.addClass(this.playPauseDiv, 'ima-playing');\n this.playPauseDiv.addEventListener('click', this.onAdPlayPauseClick.bind(this), false);\n this.assignControlAttributes(this.muteDiv, 'ima-mute-div');\n this.addClass(this.muteDiv, 'ima-non-muted');\n this.muteDiv.addEventListener('click', this.onAdMuteClick.bind(this), false);\n this.assignControlAttributes(this.sliderDiv, 'ima-slider-div');\n this.sliderDiv.addEventListener('mousedown', this.onAdVolumeSliderMouseDown.bind(this), false);\n\n // Hide volume slider controls on iOS as they aren't supported.\n if (this.controller.getIsIos()) {\n this.sliderDiv.style.display = 'none';\n }\n this.assignControlAttributes(this.sliderLevelDiv, 'ima-slider-level-div');\n this.assignControlAttributes(this.fullscreenDiv, 'ima-fullscreen-div');\n this.addClass(this.fullscreenDiv, 'ima-non-fullscreen');\n this.fullscreenDiv.addEventListener('click', this.onAdFullscreenClick.bind(this), false);\n this.adContainerDiv.appendChild(this.controlsDiv);\n this.controlsDiv.appendChild(this.countdownDiv);\n this.controlsDiv.appendChild(this.seekBarDiv);\n this.controlsDiv.appendChild(this.playPauseDiv);\n this.controlsDiv.appendChild(this.muteDiv);\n this.controlsDiv.appendChild(this.sliderDiv);\n this.controlsDiv.appendChild(this.fullscreenDiv);\n this.seekBarDiv.appendChild(this.progressDiv);\n this.sliderDiv.appendChild(this.sliderLevelDiv);\n};\n\n/**\n * Listener for clicks on the play/pause button during ad playback.\n */\nAdUi.prototype.onAdPlayPauseClick = function () {\n this.controller.onAdPlayPauseClick();\n};\n\n/**\n * Listener for clicks on the play/pause button during ad playback.\n */\nAdUi.prototype.onAdMuteClick = function () {\n this.controller.onAdMuteClick();\n};\n\n/**\n * Listener for clicks on the fullscreen button during ad playback.\n */\nAdUi.prototype.onAdFullscreenClick = function () {\n this.controller.toggleFullscreen();\n};\n\n/**\n * Show pause and hide play button\n */\nAdUi.prototype.onAdsPaused = function () {\n this.controller.sdkImpl.adPlaying = false;\n this.addClass(this.playPauseDiv, 'ima-paused');\n this.removeClass(this.playPauseDiv, 'ima-playing');\n this.showAdControls();\n};\n\n/**\n * Show pause and hide play button\n */\nAdUi.prototype.onAdsResumed = function () {\n this.onAdsPlaying();\n this.showAdControls();\n};\n\n/**\n * Show play and hide pause button\n */\nAdUi.prototype.onAdsPlaying = function () {\n this.controller.sdkImpl.adPlaying = true;\n this.addClass(this.playPauseDiv, 'ima-playing');\n this.removeClass(this.playPauseDiv, 'ima-paused');\n};\n\n/**\n * Takes data from the controller to update the UI.\n *\n * @param {number} currentTime Current time of the ad.\n * @param {number} remainingTime Remaining time of the ad.\n * @param {number} duration Duration of the ad.\n * @param {number} adPosition Index of the ad in the pod.\n * @param {number} totalAds Total number of ads in the pod.\n */\nAdUi.prototype.updateAdUi = function (currentTime, remainingTime, duration, adPosition, totalAds) {\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 (totalAds > 1) {\n podCount = ' (' + adPosition + ' ' + this.controller.getSettings().adLabelNofN + ' ' + totalAds + '): ';\n }\n this.countdownDiv.innerHTML = this.controller.getSettings().adLabel + podCount + remainingMinutes + ':' + remainingSeconds;\n\n // Update UI\n var playProgressRatio = currentTime / duration;\n var playProgressPercent = playProgressRatio * 100;\n this.progressDiv.style.width = playProgressPercent + '%';\n};\n\n/**\n * Handles UI changes when the ad is unmuted.\n */\nAdUi.prototype.unmute = function () {\n this.addClass(this.muteDiv, 'ima-non-muted');\n this.removeClass(this.muteDiv, 'ima-muted');\n this.sliderLevelDiv.style.width = this.controller.getPlayerVolume() * 100 + '%';\n};\n\n/**\n * Handles UI changes when the ad is muted.\n */\nAdUi.prototype.mute = function () {\n this.addClass(this.muteDiv, 'ima-muted');\n this.removeClass(this.muteDiv, 'ima-non-muted');\n this.sliderLevelDiv.style.width = '0%';\n};\n\n/*\n * Listener for mouse down events during ad playback. Used for volume.\n */\nAdUi.prototype.onAdVolumeSliderMouseDown = function () {\n document.addEventListener('mouseup', this.boundOnMouseUp, false);\n document.addEventListener('mousemove', this.boundOnMouseMove, false);\n};\n\n/*\n * Mouse movement listener used for volume slider.\n */\nAdUi.prototype.onMouseMove = function (event) {\n this.changeVolume(event);\n};\n\n/*\n * Mouse release listener used for volume slider.\n */\nAdUi.prototype.onMouseUp = function (event) {\n this.changeVolume(event);\n document.removeEventListener('mouseup', this.boundOnMouseUp);\n document.removeEventListener('mousemove', this.boundOnMouseMove);\n};\n\n/*\n * Utility function to set volume and associated UI\n */\nAdUi.prototype.changeVolume = function (event) {\n var percent = (event.clientX - this.sliderDiv.getBoundingClientRect().left) / this.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 this.sliderLevelDiv.style.width = percent + '%';\n if (this.percent == 0) {\n this.addClass(this.muteDiv, 'ima-muted');\n this.removeClass(this.muteDiv, 'ima-non-muted');\n } else {\n this.addClass(this.muteDiv, 'ima-non-muted');\n this.removeClass(this.muteDiv, 'ima-muted');\n }\n this.controller.setVolume(percent / 100); // 0-1\n};\n\n/**\n * Show the ad container.\n */\nAdUi.prototype.showAdContainer = function () {\n this.adContainerDiv.classList.remove('hide-ad-container');\n};\n\n/**\n * Hide the ad container.\n */\nAdUi.prototype.hideAdContainer = function () {\n this.adContainerDiv.classList.add('hide-ad-container');\n};\n\n/**\n * Handles clicks on the ad container.\n */\nAdUi.prototype.onAdContainerClick = function () {\n if (this.isAdNonlinear) {\n this.controller.togglePlayback();\n }\n};\n\n/**\n * Resets the state of the ad ui.\n */\nAdUi.prototype.reset = function () {\n this.hideAdContainer();\n};\n\n/**\n * Handles ad errors.\n */\nAdUi.prototype.onAdError = function () {\n this.hideAdContainer();\n};\n\n/**\n * Handles ad break starting.\n *\n * @param {Object} adEvent The event fired by the IMA SDK.\n */\nAdUi.prototype.onAdBreakStart = function (adEvent) {\n this.showAdContainer();\n var contentType = adEvent.getAd().getContentType();\n if (contentType === 'application/javascript' && !this.controller.getSettings().showControlsForJSAds) {\n this.controlsDiv.style.display = 'none';\n } else {\n this.controlsDiv.style.display = 'block';\n }\n this.onAdsPlaying();\n // Start with the ad controls minimized.\n this.hideAdControls();\n};\n\n/**\n * Handles ad break ending.\n */\nAdUi.prototype.onAdBreakEnd = function () {\n var currentAd = this.controller.getCurrentAd();\n if (currentAd == null ||\n // hide for post-roll only playlist\n currentAd.isLinear()) {\n // don't hide for non-linear ads\n this.hideAdContainer();\n }\n this.controlsDiv.style.display = 'none';\n this.countdownDiv.innerHTML = '';\n};\n\n/**\n * Handles when all ads have finished playing.\n */\nAdUi.prototype.onAllAdsCompleted = function () {\n this.hideAdContainer();\n};\n\n/**\n * Handles when a linear ad starts.\n */\nAdUi.prototype.onLinearAdStart = function () {\n // Don't bump container when controls are shown\n this.removeClass(this.adContainerDiv, 'bumpable-ima-ad-container');\n this.isAdNonlinear = false;\n};\n\n/**\n * Handles when a non-linear ad starts.\n */\nAdUi.prototype.onNonLinearAdLoad = function () {\n // Bump container when controls are shown\n this.addClass(this.adContainerDiv, 'bumpable-ima-ad-container');\n this.isAdNonlinear = true;\n};\nAdUi.prototype.onPlayerEnterFullscreen = function () {\n this.addClass(this.fullscreenDiv, 'ima-fullscreen');\n this.removeClass(this.fullscreenDiv, 'ima-non-fullscreen');\n};\nAdUi.prototype.onPlayerExitFullscreen = function () {\n this.addClass(this.fullscreenDiv, 'ima-non-fullscreen');\n this.removeClass(this.fullscreenDiv, 'ima-fullscreen');\n};\n\n/**\n * Called when the player volume changes.\n *\n * @param {number} volume The new player volume.\n */\nAdUi.prototype.onPlayerVolumeChanged = function (volume) {\n if (volume == 0) {\n this.addClass(this.muteDiv, 'ima-muted');\n this.removeClass(this.muteDiv, 'ima-non-muted');\n this.sliderLevelDiv.style.width = '0%';\n } else {\n this.addClass(this.muteDiv, 'ima-non-muted');\n this.removeClass(this.muteDiv, 'ima-muted');\n this.sliderLevelDiv.style.width = volume * 100 + '%';\n }\n};\n\n/**\n * Shows ad controls on mouseover.\n */\nAdUi.prototype.showAdControls = function () {\n var _this$controller$getS = this.controller.getSettings(),\n disableAdControls = _this$controller$getS.disableAdControls;\n if (!disableAdControls) {\n this.addClass(this.controlsDiv, 'ima-controls-div-showing');\n }\n};\n\n/**\n * Hide the ad controls.\n */\nAdUi.prototype.hideAdControls = function () {\n this.removeClass(this.controlsDiv, 'ima-controls-div-showing');\n};\n\n/**\n * Assigns the unique id and class names to the given element as well as the\n * style class.\n * @param {HTMLElement} element Element that needs the controlName assigned.\n * @param {string} controlName Control name to assign.\n */\nAdUi.prototype.assignControlAttributes = function (element, controlName) {\n element.id = this.controlPrefix + controlName;\n element.className = this.controlPrefix + controlName + ' ' + controlName;\n};\n\n/**\n * Returns a regular expression to test a string for the given className.\n *\n * @param {string} className The name of the class.\n * @return {RegExp} The regular expression used to test for that class.\n */\nAdUi.prototype.getClassRegexp = function (className) {\n // Matches on\n // (beginning of string OR NOT word char)\n // classname\n // (negative lookahead word char OR end of string)\n return new RegExp('(^|[^A-Za-z-])' + className + '((?![A-Za-z-])|$)', 'gi');\n};\n\n/**\n * Returns whether or not the provided element has the provied class in its\n * className.\n * @param {HTMLElement} element Element to tes.t\n * @param {string} className Class to look for.\n * @return {boolean} True if element has className in class list. False\n * otherwise.\n */\nAdUi.prototype.elementHasClass = function (element, className) {\n var classRegexp = this.getClassRegexp(className);\n return classRegexp.test(element.className);\n};\n\n/**\n * Adds a class to the given element if it doesn't already have the class\n * @param {HTMLElement} element Element to which the class will be added.\n * @param {string} classToAdd Class to add.\n */\nAdUi.prototype.addClass = function (element, classToAdd) {\n element.className = element.className.trim() + ' ' + classToAdd;\n};\n\n/**\n * Removes a class from the given element if it has the given class\n *\n * @param {HTMLElement} element Element from which the class will be removed.\n * @param {string} classToRemove Class to remove.\n */\nAdUi.prototype.removeClass = function (element, classToRemove) {\n var classRegexp = this.getClassRegexp(classToRemove);\n element.className = element.className.trim().replace(classRegexp, '');\n};\n\n/**\n * @return {HTMLElement} The div for the ad container.\n */\nAdUi.prototype.getAdContainerDiv = function () {\n return this.adContainerDiv;\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 */\nAdUi.prototype.setShowCountdown = function (showCountdownIn) {\n this.showCountdown = showCountdownIn;\n this.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';\n};\n\nvar version = \"2.5.0\";\nvar pkg = {\n\tversion: version};\n\n/**\n * Implementation of the IMA SDK for the plugin.\n *\n * @param {Object} controller Reference to the parent controller.\n *\n * @constructor\n * @struct\n * @final\n */\nvar SdkImpl$1 = function SdkImpl(controller) {\n /**\n * Plugin controller.\n */\n this.controller = controller;\n\n /**\n * IMA SDK AdDisplayContainer.\n */\n this.adDisplayContainer = null;\n\n /**\n * True if the AdDisplayContainer has been initialized. False otherwise.\n */\n this.adDisplayContainerInitialized = false;\n\n /**\n * IMA SDK AdsLoader\n */\n this.adsLoader = null;\n\n /**\n * IMA SDK AdsManager\n */\n this.adsManager = null;\n\n /**\n * IMA SDK AdsRenderingSettings.\n */\n this.adsRenderingSettings = null;\n\n /**\n * VAST, VMAP, or ad rules response. Used in lieu of fetching a response\n * from an ad tag URL.\n */\n this.adsResponse = null;\n\n /**\n * Current IMA SDK Ad.\n */\n this.currentAd = null;\n\n /**\n * Timer used to track ad progress.\n */\n this.adTrackingTimer = null;\n\n /**\n * True if ALL_ADS_COMPLETED has fired, false until then.\n */\n this.allAdsCompleted = false;\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 this.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 this.adPlaying = false;\n\n /**\n * True if the ad is muted, false otherwise.\n */\n this.adMuted = false;\n\n /**\n * Listener to be called to trigger manual ad break playback.\n */\n this.adBreakReadyListener = undefined;\n\n /**\n * Tracks whether or not we have already called adsLoader.contentComplete().\n */\n this.contentCompleteCalled = false;\n\n /**\n * True if the ad has timed out.\n */\n this.isAdTimedOut = false;\n\n /**\n * Stores the dimensions for the ads manager.\n */\n this.adsManagerDimensions = {\n width: 0,\n height: 0\n };\n\n /**\n * Boolean flag to enable manual ad break playback.\n */\n this.autoPlayAdBreaks = true;\n if (this.controller.getSettings().autoPlayAdBreaks === false) {\n this.autoPlayAdBreaks = false;\n }\n\n // Set SDK settings from plugin settings.\n if (this.controller.getSettings().locale) {\n /* eslint no-undef: 'error' */\n /* global google */\n google.ima.settings.setLocale(this.controller.getSettings().locale);\n }\n if (this.controller.getSettings().disableFlashAds) {\n google.ima.settings.setDisableFlashAds(this.controller.getSettings().disableFlashAds);\n }\n if (this.controller.getSettings().disableCustomPlaybackForIOS10Plus) {\n google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.controller.getSettings().disableCustomPlaybackForIOS10Plus);\n }\n if (this.controller.getSettings().ppid) {\n google.ima.settings.setPpid(this.controller.getSettings().ppid);\n }\n if (this.controller.getSettings().featureFlags) {\n google.ima.settings.setFeatureFlags(this.controller.getSettings().featureFlags);\n }\n};\n\n/**\n * Creates and initializes the IMA SDK objects.\n */\nSdkImpl$1.prototype.initAdObjects = function () {\n this.adDisplayContainer = new google.ima.AdDisplayContainer(this.controller.getAdContainerDiv(), this.controller.getContentPlayer());\n this.adsLoader = new google.ima.AdsLoader(this.adDisplayContainer);\n this.adsLoader.getSettings().setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n if (this.controller.getSettings().vpaidAllowed == false) {\n this.adsLoader.getSettings().setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.DISABLED);\n }\n if (this.controller.getSettings().vpaidMode !== undefined) {\n this.adsLoader.getSettings().setVpaidMode(this.controller.getSettings().vpaidMode);\n }\n if (this.controller.getSettings().locale) {\n this.adsLoader.getSettings().setLocale(this.controller.getSettings().locale);\n }\n if (this.controller.getSettings().numRedirects) {\n this.adsLoader.getSettings().setNumRedirects(this.controller.getSettings().numRedirects);\n }\n if (this.controller.getSettings().sessionId) {\n this.adsLoader.getSettings().setSessionId(this.controller.getSettings().sessionId);\n }\n this.adsLoader.getSettings().setPlayerType('videojs-ima');\n this.adsLoader.getSettings().setPlayerVersion(pkg.version);\n this.adsLoader.getSettings().setAutoPlayAdBreaks(this.autoPlayAdBreaks);\n this.adsLoader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, this.onAdsManagerLoaded.bind(this), false);\n this.adsLoader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, this.onAdsLoaderError.bind(this), false);\n this.controller.playerWrapper.vjsPlayer.trigger({\n type: 'ads-loader',\n adsLoader: this.adsLoader\n });\n};\n\n/**\n * Creates the AdsRequest and request ads through the AdsLoader.\n */\nSdkImpl$1.prototype.requestAds = function () {\n var adsRequest = new google.ima.AdsRequest();\n if (this.controller.getSettings().adTagUrl) {\n adsRequest.adTagUrl = this.controller.getSettings().adTagUrl;\n } else {\n adsRequest.adsResponse = this.controller.getSettings().adsResponse;\n }\n if (this.controller.getSettings().forceNonLinearFullSlot) {\n adsRequest.forceNonLinearFullSlot = true;\n }\n if (this.controller.getSettings().vastLoadTimeout) {\n adsRequest.vastLoadTimeout = this.controller.getSettings().vastLoadTimeout;\n }\n if (this.controller.getSettings().omidMode) {\n window.console.warn('The additional setting `omidMode` has been removed. ' + 'Use `omidVendorAccess` instead.');\n }\n if (this.controller.getSettings().omidVendorAccess) {\n adsRequest.omidAccessModeRules = {};\n var omidVendorValues = this.controller.getSettings().omidVendorAccess;\n Object.keys(omidVendorValues).forEach(function (vendorKey) {\n adsRequest.omidAccessModeRules[vendorKey] = omidVendorValues[vendorKey];\n });\n }\n adsRequest.linearAdSlotWidth = this.controller.getPlayerWidth();\n adsRequest.linearAdSlotHeight = this.controller.getPlayerHeight();\n adsRequest.nonLinearAdSlotWidth = this.controller.getSettings().nonLinearWidth || this.controller.getPlayerWidth();\n adsRequest.nonLinearAdSlotHeight = this.controller.getSettings().nonLinearHeight || this.controller.getPlayerHeight();\n adsRequest.setAdWillAutoPlay(this.controller.adsWillAutoplay());\n adsRequest.setAdWillPlayMuted(this.controller.adsWillPlayMuted());\n\n // Populate the adsRequestproperties with those provided in the AdsRequest\n // object in the settings.\n var providedAdsRequest = this.controller.getSettings().adsRequest;\n if (providedAdsRequest && _typeof(providedAdsRequest) === 'object') {\n Object.keys(providedAdsRequest).forEach(function (key) {\n adsRequest[key] = providedAdsRequest[key];\n });\n }\n this.adsLoader.requestAds(adsRequest);\n this.controller.playerWrapper.vjsPlayer.trigger({\n type: 'ads-request',\n AdsRequest: adsRequest\n });\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 *\n * @param {google.ima.AdsManagerLoadedEvent} adsManagerLoadedEvent Fired when\n * the AdsManager loads.\n */\nSdkImpl$1.prototype.onAdsManagerLoaded = function (adsManagerLoadedEvent) {\n this.createAdsRenderingSettings();\n this.adsManager = adsManagerLoadedEvent.getAdsManager(this.controller.getContentPlayheadTracker(), this.adsRenderingSettings);\n this.adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, this.onAdError.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.AD_BREAK_READY, this.onAdBreakReady.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, this.onContentPauseRequested.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, this.onContentResumeRequested.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.ALL_ADS_COMPLETED, this.onAllAdsCompleted.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, this.onAdLoaded.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, this.onAdStarted.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, this.onAdComplete.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.SKIPPED, this.onAdComplete.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.LOG, this.onAdLog.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.PAUSED, this.onAdPaused.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.RESUMED, this.onAdResumed.bind(this));\n this.controller.playerWrapper.vjsPlayer.trigger({\n type: 'ads-manager',\n adsManager: this.adsManager\n });\n if (!this.autoPlayAdBreaks) {\n this.initAdsManager();\n }\n var _this$controller$getS = this.controller.getSettings(),\n preventLateAdStart = _this$controller$getS.preventLateAdStart;\n if (!preventLateAdStart) {\n this.controller.onAdsReady();\n } else if (preventLateAdStart && !this.isAdTimedOut) {\n this.controller.onAdsReady();\n }\n if (this.controller.getSettings().adsManagerLoadedCallback) {\n this.controller.getSettings().adsManagerLoadedCallback();\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/client-side/reference/js/google.ima.AdError#.Type\n */\nSdkImpl$1.prototype.onAdsLoaderError = function (event) {\n window.console.warn('AdsLoader error: ' + event.getError());\n this.controller.onErrorLoadingAds(event);\n if (this.adsManager) {\n this.adsManager.destroy();\n }\n};\n\n/**\n * Initialize the ads manager.\n */\nSdkImpl$1.prototype.initAdsManager = function () {\n try {\n var initWidth = this.controller.getPlayerWidth();\n var initHeight = this.controller.getPlayerHeight();\n this.adsManagerDimensions.width = initWidth;\n this.adsManagerDimensions.height = initHeight;\n this.adsManager.init(initWidth, initHeight);\n this.adsManager.setVolume(this.controller.getPlayerVolume());\n this.initializeAdDisplayContainer();\n } catch (adError) {\n this.onAdError(adError);\n }\n};\n\n/**\n * Create AdsRenderingSettings for the IMA SDK.\n */\nSdkImpl$1.prototype.createAdsRenderingSettings = function () {\n this.adsRenderingSettings = new google.ima.AdsRenderingSettings();\n this.adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n if (this.controller.getSettings().adsRenderingSettings) {\n for (var setting in this.controller.getSettings().adsRenderingSettings) {\n if (setting !== '') {\n this.adsRenderingSettings[setting] = this.controller.getSettings().adsRenderingSettings[setting];\n }\n }\n }\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 */\nSdkImpl$1.prototype.onAdError = function (adErrorEvent) {\n var errorMessage = adErrorEvent.getError !== undefined ? adErrorEvent.getError() : adErrorEvent.stack;\n window.console.warn('Ad error: ' + errorMessage);\n this.adsManager.destroy();\n this.controller.onAdError(adErrorEvent);\n\n // reset these so consumers don't think we are still in an ad break,\n // but reset them after any prior cleanup happens\n this.adsActive = false;\n this.adPlaying = false;\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 */\nSdkImpl$1.prototype.onAdBreakReady = function (adEvent) {\n this.adBreakReadyListener(adEvent);\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 */\nSdkImpl$1.prototype.onContentPauseRequested = function (adEvent) {\n this.adsActive = true;\n this.adPlaying = true;\n this.controller.onAdBreakStart(adEvent);\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 */\nSdkImpl$1.prototype.onContentResumeRequested = function (adEvent) {\n this.adsActive = false;\n this.adPlaying = false;\n this.controller.onAdBreakEnd();\n // Hide controls in case of future non-linear ads. They'll be unhidden in\n // content_pause_requested.\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 */\nSdkImpl$1.prototype.onAllAdsCompleted = function (adEvent) {\n this.allAdsCompleted = true;\n this.controller.onAllAdsCompleted();\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 */\nSdkImpl$1.prototype.onAdLoaded = function (adEvent) {\n if (!adEvent.getAd().isLinear()) {\n this.controller.onNonLinearAdLoad();\n this.controller.playContent();\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 */\nSdkImpl$1.prototype.onAdStarted = function (adEvent) {\n this.currentAd = adEvent.getAd();\n if (this.currentAd.isLinear()) {\n this.adTrackingTimer = setInterval(this.onAdPlayheadTrackerInterval.bind(this), 250);\n this.controller.onLinearAdStart();\n } else {\n this.controller.onNonLinearAdStart();\n }\n};\n\n/**\n * Handles an ad click. Puts the player UI in a paused state.\n */\nSdkImpl$1.prototype.onAdPaused = function () {\n this.controller.onAdsPaused();\n};\n\n/**\n * Syncs controls when an ad resumes.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.\n */\nSdkImpl$1.prototype.onAdResumed = function (adEvent) {\n this.controller.onAdsResumed();\n};\n\n/**\n * Clears the interval timer for current ad time when an ad completes.\n */\nSdkImpl$1.prototype.onAdComplete = function () {\n if (this.currentAd.isLinear()) {\n clearInterval(this.adTrackingTimer);\n }\n};\n\n/**\n * Handles ad log messages.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.\n */\nSdkImpl$1.prototype.onAdLog = function (adEvent) {\n this.controller.onAdLog(adEvent);\n};\n\n/**\n * Gets the current time and duration of the ad and calls the method to\n * update the ad UI.\n */\nSdkImpl$1.prototype.onAdPlayheadTrackerInterval = function () {\n if (this.adsManager === null) return;\n var remainingTime = this.adsManager.getRemainingTime();\n var duration = this.currentAd.getDuration();\n var currentTime = duration - remainingTime;\n currentTime = currentTime > 0 ? currentTime : 0;\n var totalAds = 0;\n var adPosition;\n if (this.currentAd.getAdPodInfo()) {\n adPosition = this.currentAd.getAdPodInfo().getAdPosition();\n totalAds = this.currentAd.getAdPodInfo().getTotalAds();\n }\n this.controller.onAdPlayheadUpdated(currentTime, remainingTime, duration, adPosition, totalAds);\n};\n\n/**\n * Called by the player wrapper when content completes.\n */\nSdkImpl$1.prototype.onContentComplete = function () {\n if (this.adsLoader) {\n this.adsLoader.contentComplete();\n this.contentCompleteCalled = true;\n }\n if (this.adsManager && this.adsManager.getCuePoints() && !this.adsManager.getCuePoints().includes(-1) || !this.adsManager) {\n this.controller.onNoPostroll();\n }\n if (this.allAdsCompleted) {\n this.controller.onContentAndAdsCompleted();\n }\n};\n\n/**\n * Called when the player is disposed.\n */\nSdkImpl$1.prototype.onPlayerDisposed = function () {\n if (this.adTrackingTimer) {\n clearInterval(this.adTrackingTimer);\n }\n if (this.adsManager) {\n this.adsManager.destroy();\n this.adsManager = null;\n }\n};\nSdkImpl$1.prototype.onPlayerReadyForPreroll = function () {\n if (this.autoPlayAdBreaks) {\n this.initAdsManager();\n try {\n this.controller.showAdContainer();\n // Sync ad volume with content volume.\n this.adsManager.setVolume(this.controller.getPlayerVolume());\n this.adsManager.start();\n } catch (adError) {\n this.onAdError(adError);\n }\n }\n};\nSdkImpl$1.prototype.onAdTimeout = function () {\n this.isAdTimedOut = true;\n};\nSdkImpl$1.prototype.onPlayerReady = function () {\n this.initAdObjects();\n if ((this.controller.getSettings().adTagUrl || this.controller.getSettings().adsResponse) && this.controller.getSettings().requestMode === 'onLoad') {\n this.requestAds();\n }\n};\nSdkImpl$1.prototype.onPlayerEnterFullscreen = function () {\n if (this.adsManager) {\n this.adsManager.resize(window.screen.width, window.screen.height);\n }\n};\nSdkImpl$1.prototype.onPlayerExitFullscreen = function () {\n if (this.adsManager) {\n this.adsManager.resize(this.controller.getPlayerWidth(), this.controller.getPlayerHeight());\n }\n};\n\n/**\n * Called when the player volume changes.\n *\n * @param {number} volume The new player volume.\n */\nSdkImpl$1.prototype.onPlayerVolumeChanged = function (volume) {\n if (this.adsManager) {\n this.adsManager.setVolume(volume);\n }\n if (volume == 0) {\n this.adMuted = true;\n } else {\n this.adMuted = false;\n }\n};\n\n/**\n * Called when the player wrapper detects that the player has been resized.\n *\n * @param {number} width The post-resize width of the player.\n * @param {number} height The post-resize height of the player.\n */\nSdkImpl$1.prototype.onPlayerResize = function (width, height) {\n if (this.adsManager) {\n this.adsManagerDimensions.width = width;\n this.adsManagerDimensions.height = height;\n /* eslint no-undef: 'error' */\n this.adsManager.resize(width, height);\n }\n};\n\n/**\n * @return {Object} The current ad.\n */\nSdkImpl$1.prototype.getCurrentAd = function () {\n return this.currentAd;\n};\n\n/**\n * Listener JSDoc for ESLint. This listener can be passed to\n * setAdBreakReadyListener.\n * @callback listener\n */\n\n/**\n * Sets the listener to be called to trigger manual ad break playback.\n * @param {listener} listener The listener to be called to trigger manual ad\n * break playback.\n */\nSdkImpl$1.prototype.setAdBreakReadyListener = function (listener) {\n this.adBreakReadyListener = listener;\n};\n\n/**\n * @return {boolean} True if an ad is currently playing. False otherwise.\n */\nSdkImpl$1.prototype.isAdPlaying = function () {\n return this.adPlaying;\n};\n\n/**\n * @return {boolean} True if an ad is currently playing. False otherwise.\n */\nSdkImpl$1.prototype.isAdMuted = function () {\n return this.adMuted;\n};\n\n/**\n * Pause ads.\n */\nSdkImpl$1.prototype.pauseAds = function () {\n this.adsManager.pause();\n this.adPlaying = false;\n};\n\n/**\n * Resume ads.\n */\nSdkImpl$1.prototype.resumeAds = function () {\n this.adsManager.resume();\n this.adPlaying = true;\n};\n\n/**\n * Unmute ads.\n */\nSdkImpl$1.prototype.unmute = function () {\n this.adsManager.setVolume(1);\n this.adMuted = false;\n};\n\n/**\n * Mute ads.\n */\nSdkImpl$1.prototype.mute = function () {\n this.adsManager.setVolume(0);\n this.adMuted = true;\n};\n\n/**\n * Set the volume of the ads. 0-1.\n *\n * @param {number} volume The new volume.\n */\nSdkImpl$1.prototype.setVolume = function (volume) {\n this.adsManager.setVolume(volume);\n if (volume == 0) {\n this.adMuted = true;\n } else {\n this.adMuted = false;\n }\n};\n\n/**\n * Initializes the AdDisplayContainer. On mobile, this must be done as a\n * result of user action.\n */\nSdkImpl$1.prototype.initializeAdDisplayContainer = function () {\n if (this.adDisplayContainer) {\n if (!this.adDisplayContainerInitialized) {\n this.adDisplayContainer.initialize();\n this.adDisplayContainerInitialized = true;\n }\n }\n};\n\n/**\n * Called by publishers in manual ad break playback mode to start an ad\n * break.\n */\nSdkImpl$1.prototype.playAdBreak = function () {\n if (!this.autoPlayAdBreaks) {\n this.controller.showAdContainer();\n // Sync ad volume with content volume.\n this.adsManager.setVolume(this.controller.getPlayerVolume());\n this.adsManager.start();\n }\n};\n\n/**\n * Callback JSDoc for ESLint. This callback can be passed to addEventListener.\n * @callback callback\n */\n\n/**\n * Adds an EventListener to the AdsManager. For a list of available events,\n * see\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.AdEvent#.Type\n * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to\n * listen.\n * @param {callback} callback The method to call when the event is fired.\n */\nSdkImpl$1.prototype.addEventListener = function (event, callback) {\n if (this.adsManager) {\n this.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 */\nSdkImpl$1.prototype.getAdsManager = function () {\n return this.adsManager;\n};\n\n/**\n * Reset the SDK implementation.\n */\nSdkImpl$1.prototype.reset = function () {\n this.adsActive = false;\n this.adPlaying = false;\n if (this.adTrackingTimer) {\n // If this is called while an ad is playing, stop trying to get that\n // ad's current time.\n clearInterval(this.adTrackingTimer);\n }\n if (this.adsManager) {\n this.adsManager.destroy();\n this.adsManager = null;\n }\n if (this.adsLoader && !this.contentCompleteCalled) {\n this.adsLoader.contentComplete();\n }\n this.contentCompleteCalled = false;\n this.allAdsCompleted = false;\n};\n\n/**\n * Copyright 2017 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/**\n * The grand coordinator of the plugin. Facilitates communication between all\n * other plugin classes.\n *\n * @param {Object} player Instance of the video.js player.\n * @param {Object} options Options provided by the implementation.\n * @constructor\n * @struct\n * @final\n */\nvar Controller = function Controller(player, options) {\n /**\n * Stores user-provided settings.\n * @type {Object}\n */\n this.settings = {};\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 this.contentAndAdsEndedListeners = [];\n\n /**\n * Whether or not we are running on a mobile platform.\n */\n this.isMobile = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/Android/i);\n\n /**\n * Whether or not we are running on an iOS platform.\n */\n this.isIos = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i);\n this.initWithSettings(options);\n\n /**\n * Stores contrib-ads default settings.\n */\n var contribAdsDefaults = {\n debug: this.settings.debug,\n timeout: this.settings.timeout,\n prerollTimeout: this.settings.prerollTimeout\n };\n var adsPluginSettings = Object.assign({}, contribAdsDefaults, options.contribAdsSettings || {});\n this.playerWrapper = new PlayerWrapper$1(player, adsPluginSettings, this);\n this.adUi = new AdUi(this);\n this.sdkImpl = new SdkImpl$1(this);\n};\nController.IMA_DEFAULTS = {\n adLabel: 'Advertisement',\n adLabelNofN: 'of',\n debug: false,\n disableAdControls: false,\n prerollTimeout: 1000,\n preventLateAdStart: false,\n requestMode: 'onLoad',\n showControlsForJSAds: true,\n timeout: 5000\n};\n\n/**\n * Extends the settings to include user-provided settings.\n *\n * @param {Object} options Options to be used in initialization.\n */\nController.prototype.initWithSettings = function (options) {\n this.settings = Object.assign({}, Controller.IMA_DEFAULTS, options || {});\n this.warnAboutDeprecatedSettings();\n\n // Default showing countdown timer to true.\n this.showCountdown = true;\n if (this.settings.showCountdown === false) {\n this.showCountdown = false;\n }\n};\n\n/**\n * Logs console warnings when deprecated settings are used.\n */\nController.prototype.warnAboutDeprecatedSettings = function () {\n var _this = this;\n var deprecatedSettings = ['adWillAutoplay', 'adsWillAutoplay', 'adWillPlayMuted', 'adsWillPlayMuted'];\n deprecatedSettings.forEach(function (setting) {\n if (_this.settings[setting] !== undefined) {\n console.warn('WARNING: videojs.ima setting ' + setting + ' is deprecated');\n }\n });\n};\n\n/**\n * Return the settings object.\n *\n * @return {Object} The settings object.\n */\nController.prototype.getSettings = function () {\n return this.settings;\n};\n\n/**\n * Return whether or not we're in a mobile environment.\n *\n * @return {boolean} True if running on mobile, false otherwise.\n */\nController.prototype.getIsMobile = function () {\n return this.isMobile;\n};\n\n/**\n * Return whether or not we're in an iOS environment.\n *\n * @return {boolean} True if running on iOS, false otherwise.\n */\nController.prototype.getIsIos = function () {\n return this.isIos;\n};\n\n/**\n * Inject the ad container div into the DOM.\n *\n * @param{HTMLElement} adContainerDiv The ad container div.\n */\nController.prototype.injectAdContainerDiv = function (adContainerDiv) {\n this.playerWrapper.injectAdContainerDiv(adContainerDiv);\n};\n\n/**\n * @return {HTMLElement} The div for the ad container.\n */\nController.prototype.getAdContainerDiv = function () {\n return this.adUi.getAdContainerDiv();\n};\n\n/**\n * @return {Object} The content player.\n */\nController.prototype.getContentPlayer = function () {\n return this.playerWrapper.getContentPlayer();\n};\n\n/**\n * Returns the content playhead tracker.\n *\n * @return {Object} The content playhead tracker.\n */\nController.prototype.getContentPlayheadTracker = function () {\n return this.playerWrapper.getContentPlayheadTracker();\n};\n\n/**\n * Requests ads.\n */\nController.prototype.requestAds = function () {\n this.sdkImpl.requestAds();\n};\n\n/**\n * Add or modify a setting.\n *\n * @param {string} key Key to modify\n * @param {Object} value Value to set at key.\n */\nController.prototype.setSetting = function (key, value) {\n this.settings[key] = value;\n};\n\n/**\n * Called when there is an error loading ads.\n *\n * @param {Object} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nController.prototype.onErrorLoadingAds = function (adErrorEvent) {\n this.adUi.onAdError();\n this.playerWrapper.onAdError(adErrorEvent);\n};\n\n/**\n * Called by the ad UI when the play/pause button is clicked.\n */\nController.prototype.onAdPlayPauseClick = function () {\n if (this.sdkImpl.isAdPlaying()) {\n this.adUi.onAdsPaused();\n this.sdkImpl.pauseAds();\n } else {\n this.adUi.onAdsPlaying();\n this.sdkImpl.resumeAds();\n }\n};\n\n/**\n * Called by the ad UI when the mute button is clicked.\n *\n */\nController.prototype.onAdMuteClick = function () {\n if (this.sdkImpl.isAdMuted()) {\n this.playerWrapper.unmute();\n this.adUi.unmute();\n this.sdkImpl.unmute();\n } else {\n this.playerWrapper.mute();\n this.adUi.mute();\n this.sdkImpl.mute();\n }\n};\n\n/**\n * Set the volume of the player and ads. 0-1.\n *\n * @param {number} volume The new volume.\n */\nController.prototype.setVolume = function (volume) {\n this.playerWrapper.setVolume(volume);\n this.sdkImpl.setVolume(volume);\n};\n\n/**\n * @return {number} The volume of the content player.\n */\nController.prototype.getPlayerVolume = function () {\n return this.playerWrapper.getVolume();\n};\n\n/**\n * Toggle fullscreen state.\n */\nController.prototype.toggleFullscreen = function () {\n this.playerWrapper.toggleFullscreen();\n};\n\n/**\n * Relays ad errors to the player wrapper.\n *\n * @param {Object} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nController.prototype.onAdError = function (adErrorEvent) {\n this.adUi.onAdError();\n this.playerWrapper.onAdError(adErrorEvent);\n};\n\n/**\n * Handles ad break starting.\n *\n * @param {Object} adEvent The event fired by the IMA SDK.\n */\nController.prototype.onAdBreakStart = function (adEvent) {\n this.playerWrapper.onAdBreakStart();\n this.adUi.onAdBreakStart(adEvent);\n};\n\n/**\n * Show the ad container.\n */\nController.prototype.showAdContainer = function () {\n this.adUi.showAdContainer();\n};\n\n/**\n * Handles ad break ending.\n */\nController.prototype.onAdBreakEnd = function () {\n this.playerWrapper.onAdBreakEnd();\n this.adUi.onAdBreakEnd();\n};\n\n/**\n * Handles when all ads have finished playing.\n */\nController.prototype.onAllAdsCompleted = function () {\n this.adUi.onAllAdsCompleted();\n this.playerWrapper.onAllAdsCompleted();\n};\n\n/**\n * Handles the SDK firing an ad paused event.\n */\nController.prototype.onAdsPaused = function () {\n this.adUi.onAdsPaused();\n};\n\n/**\n * Handles the SDK firing an ad resumed event.\n */\nController.prototype.onAdsResumed = function () {\n this.adUi.onAdsResumed();\n};\n\n/**\n * Takes data from the sdk impl and passes it to the ad UI to update the UI.\n *\n * @param {number} currentTime Current time of the ad.\n * @param {number} remainingTime Remaining time of the ad.\n * @param {number} duration Duration of the ad.\n * @param {number} adPosition Index of the ad in the pod.\n * @param {number} totalAds Total number of ads in the pod.\n */\nController.prototype.onAdPlayheadUpdated = function (currentTime, remainingTime, duration, adPosition, totalAds) {\n this.adUi.updateAdUi(currentTime, remainingTime, duration, adPosition, totalAds);\n};\n\n/**\n * Handles ad log messages.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the IMA SDK.\n */\nController.prototype.onAdLog = function (adEvent) {\n this.playerWrapper.onAdLog(adEvent);\n};\n\n/**\n * @return {Object} The current ad.\n */\nController.prototype.getCurrentAd = function () {\n return this.sdkImpl.getCurrentAd();\n};\n\n/**\n * Play content.\n */\nController.prototype.playContent = function () {\n this.playerWrapper.play();\n};\n\n/**\n * Handles when a linear ad starts.\n */\nController.prototype.onLinearAdStart = function () {\n this.adUi.onLinearAdStart();\n this.playerWrapper.onAdStart();\n};\n\n/**\n * Handles when a non-linear ad loads.\n */\nController.prototype.onNonLinearAdLoad = function () {\n this.adUi.onNonLinearAdLoad();\n};\n\n/**\n * Handles when a non-linear ad starts.\n */\nController.prototype.onNonLinearAdStart = function () {\n this.adUi.onNonLinearAdLoad();\n this.playerWrapper.onAdStart();\n};\n\n/**\n * Get the player width.\n *\n * @return {number} The width of the player.\n */\nController.prototype.getPlayerWidth = function () {\n return this.playerWrapper.getPlayerWidth();\n};\n\n/**\n * Get the player height.\n *\n * @return {number} The height of the player.\n */\nController.prototype.getPlayerHeight = function () {\n return this.playerWrapper.getPlayerHeight();\n};\n\n/**\n * Tells the player wrapper that ads are ready.\n */\nController.prototype.onAdsReady = function () {\n this.playerWrapper.onAdsReady();\n};\n\n/**\n * Called when the player wrapper detects that the player has been resized.\n *\n * @param {number} width The post-resize width of the player.\n * @param {number} height The post-resize height of the player.\n */\nController.prototype.onPlayerResize = function (width, height) {\n this.sdkImpl.onPlayerResize(width, height);\n};\n\n/**\n * Called by the player wrapper when content completes.\n */\nController.prototype.onContentComplete = function () {\n this.sdkImpl.onContentComplete();\n};\n\n/**\n * Called by the player wrapper when it's time to play a post-roll but we don't\n * have one to play.\n */\nController.prototype.onNoPostroll = function () {\n this.playerWrapper.onNoPostroll();\n};\n\n/**\n * Called when content and all ads have completed.\n */\nController.prototype.onContentAndAdsCompleted = function () {\n for (var index in this.contentAndAdsEndedListeners) {\n if (typeof this.contentAndAdsEndedListeners[index] === 'function') {\n this.contentAndAdsEndedListeners[index]();\n }\n }\n};\n\n/**\n * Called when the player is disposed.\n */\nController.prototype.onPlayerDisposed = function () {\n this.contentAndAdsEndedListeners = [];\n this.sdkImpl.onPlayerDisposed();\n};\n\n/**\n * Called when the player is ready to play a pre-roll.\n */\nController.prototype.onPlayerReadyForPreroll = function () {\n this.sdkImpl.onPlayerReadyForPreroll();\n};\n\n/**\n * Called if the ad times out.\n */\nController.prototype.onAdTimeout = function () {\n this.sdkImpl.onAdTimeout();\n};\n\n/**\n * Called when the player is ready.\n */\nController.prototype.onPlayerReady = function () {\n this.sdkImpl.onPlayerReady();\n};\n\n/**\n * Called when the player enters fullscreen.\n */\nController.prototype.onPlayerEnterFullscreen = function () {\n this.adUi.onPlayerEnterFullscreen();\n this.sdkImpl.onPlayerEnterFullscreen();\n};\n\n/**\n * Called when the player exits fullscreen.\n */\nController.prototype.onPlayerExitFullscreen = function () {\n this.adUi.onPlayerExitFullscreen();\n this.sdkImpl.onPlayerExitFullscreen();\n};\n\n/**\n * Called when the player volume changes.\n *\n * @param {number} volume The new player volume.\n */\nController.prototype.onPlayerVolumeChanged = function (volume) {\n this.adUi.onPlayerVolumeChanged(volume);\n this.sdkImpl.onPlayerVolumeChanged(volume);\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 */\nController.prototype.setContentWithAdTag = function (contentSrc, adTag) {\n this.reset();\n this.settings.adTagUrl = adTag ? adTag : this.settings.adTagUrl;\n this.playerWrapper.changeSource(contentSrc);\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 ads response is\n * used 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} adsResponse The ads response to be requested when the\n * content loads. Leave blank to use the existing ads response.\n */\nController.prototype.setContentWithAdsResponse = function (contentSrc, adsResponse) {\n this.reset();\n this.settings.adsResponse = adsResponse ? adsResponse : this.settings.adsResponse;\n this.playerWrapper.changeSource(contentSrc);\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 ads request is\n * used 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 {?Object} adsRequest The ads request to be requested when the\n * content loads. Leave blank to use the existing ads request.\n */\nController.prototype.setContentWithAdsRequest = function (contentSrc, adsRequest) {\n this.reset();\n this.settings.adsRequest = adsRequest ? adsRequest : this.settings.adsRequest;\n this.playerWrapper.changeSource(contentSrc);\n};\n\n/**\n * Resets the state of the plugin.\n */\nController.prototype.reset = function () {\n this.sdkImpl.reset();\n this.playerWrapper.reset();\n this.adUi.reset();\n};\n\n/**\n * Listener JSDoc for ESLint. This listener can be passed to\n * (add|remove)ContentEndedListener.\n * @callback listener\n */\n\n/**\n * Adds a listener for the 'readyforpostroll' event of the video player. This\n * should be used instead of setting an 'readyforpostroll' listener directly to\n * ensure that the ima can do proper cleanup of the SDK before other event\n * listeners are called.\n * @param {listener} listener The listener to be called when content\n * completes.\n */\nController.prototype.addContentEndedListener = function (listener) {\n this.playerWrapper.addContentEndedListener(listener);\n};\n\n/**\n * Adds a listener that will be called when content and all ads have\n * finished playing.\n * @param {listener} listener The listener to be called when content and ads\n * complete.\n */\nController.prototype.addContentAndAdsEndedListener = function (listener) {\n this.contentAndAdsEndedListeners.push(listener);\n};\n\n/**\n * Sets the listener to be called to trigger manual ad break playback.\n * @param {listener} listener The listener to be called to trigger manual ad\n * break playback.\n */\nController.prototype.setAdBreakReadyListener = function (listener) {\n this.sdkImpl.setAdBreakReadyListener(listener);\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 */\nController.prototype.setShowCountdown = function (showCountdownIn) {\n this.adUi.setShowCountdown(showCountdownIn);\n this.showCountdown = showCountdownIn;\n this.adUi.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';\n};\n\n/**\n * Initializes the AdDisplayContainer. On mobile, this must be done as a\n * result of user action.\n */\nController.prototype.initializeAdDisplayContainer = function () {\n this.sdkImpl.initializeAdDisplayContainer();\n};\n\n/**\n * Called by publishers in manual ad break playback mode to start an ad\n * break.\n */\nController.prototype.playAdBreak = function () {\n this.sdkImpl.playAdBreak();\n};\n\n/**\n * Callback JSDoc for ESLint. This callback can be passed to addEventListener.\n * @callback callback\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/client-side/reference/js/google.ima.AdEvent#.Type\n * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to\n * listen.\n * @param {callback} callback The method to call when the event is fired.\n */\nController.prototype.addEventListener = function (event, callback) {\n this.sdkImpl.addEventListener(event, callback);\n};\n\n/**\n * Returns the instance of the AdsManager.\n * @return {google.ima.AdsManager} The AdsManager being used by the plugin.\n */\nController.prototype.getAdsManager = function () {\n return this.sdkImpl.getAdsManager();\n};\n\n/**\n * Returns the instance of the player id.\n * @return {string} The player id.\n */\nController.prototype.getPlayerId = function () {\n return this.playerWrapper.getPlayerId();\n};\n\n/**\n * Changes the ad tag. You will need to call requestAds after this method\n * for the new ads to be requested.\n * @param {?string} adTag The ad tag to be requested the next time\n * requestAds is called.\n */\nController.prototype.changeAdTag = function (adTag) {\n this.reset();\n this.settings.adTagUrl = adTag;\n};\n\n/**\n * Pauses the ad.\n */\nController.prototype.pauseAd = function () {\n this.adUi.onAdsPaused();\n this.sdkImpl.pauseAds();\n};\n\n/**\n * Resumes the ad.\n */\nController.prototype.resumeAd = function () {\n this.adUi.onAdsPlaying();\n this.sdkImpl.resumeAds();\n};\n\n/**\n * Toggles video/ad playback.\n */\nController.prototype.togglePlayback = function () {\n this.playerWrapper.togglePlayback();\n};\n\n/**\n * @return {boolean} true if we expect that ads will autoplay. false otherwise.\n */\nController.prototype.adsWillAutoplay = function () {\n if (this.settings.adsWillAutoplay !== undefined) {\n return this.settings.adsWillAutoplay;\n } else if (this.settings.adWillAutoplay !== undefined) {\n return this.settings.adWillAutoplay;\n } else {\n return !!this.playerWrapper.getPlayerOptions().autoplay;\n }\n};\n\n/**\n * @return {boolean} true if we expect that ads will autoplay. false otherwise.\n */\nController.prototype.adsWillPlayMuted = function () {\n if (this.settings.adsWillPlayMuted !== undefined) {\n return this.settings.adsWillPlayMuted;\n } else if (this.settings.adWillPlayMuted !== undefined) {\n return this.settings.adWillPlayMuted;\n } else if (this.playerWrapper.getPlayerOptions().muted !== undefined) {\n return this.playerWrapper.getPlayerOptions().muted;\n } else {\n return this.playerWrapper.getVolume() == 0;\n }\n};\n\n/**\n * Triggers an event on the VJS player\n * @param {string} name The event name.\n * @param {Object} data The event data.\n */\nController.prototype.triggerPlayerEvent = function (name, data) {\n this.playerWrapper.triggerPlayerEvent(name, data);\n};\n\n/**\n * Copyright 2021 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/**\n * Wraps the video.js stream player for the plugin.\n *\n * @param {!Object} player Video.js player instance.\n * @param {!Object} adsPluginSettings Settings for the contrib-ads plugin.\n * @param {!DaiController} daiController Reference to the parent controller.\n */\nvar PlayerWrapper = function PlayerWrapper(player, adsPluginSettings, daiController) {\n /**\n * Instance of the video.js player.\n */\n this.vjsPlayer = player;\n\n /**\n * Plugin DAI controller.\n */\n this.daiController = daiController;\n\n /**\n * Video.js control bar.\n */\n this.vjsControls = this.vjsPlayer.getChild('controlBar');\n\n /**\n * Vanilla HTML5 video player underneath the video.js player.\n */\n this.h5Player = null;\n this.vjsPlayer.on('dispose', this.playerDisposedListener.bind(this));\n this.vjsPlayer.on('pause', this.onPause.bind(this));\n this.vjsPlayer.on('play', this.onPlay.bind(this));\n this.vjsPlayer.on('seeked', this.onSeekEnd.bind(this));\n this.vjsPlayer.ready(this.onPlayerReady.bind(this));\n if (!this.vjsPlayer.ads) {\n window.console.warn('You may be using a version of videojs-contrib-ads ' + 'that is not compatible with your version of video.js.');\n }\n this.vjsPlayer.ads(adsPluginSettings);\n};\n\n/**\n * Called in response to the video.js player's 'disposed' event.\n */\nPlayerWrapper.prototype.playerDisposedListener = function () {\n this.contentEndedListeners = [];\n this.daiController.onPlayerDisposed();\n};\n\n/**\n * Called on the player 'pause' event. Handles displaying controls during\n * paused ad breaks.\n */\nPlayerWrapper.prototype.onPause = function () {\n // This code will run if the stream is paused during an ad break. Since\n // controls are usually hidden during ads, they will now show to allow\n // users to resume ad playback.\n if (this.daiController.isInAdBreak()) {\n this.vjsControls.show();\n }\n};\n\n/**\n * Called on the player 'play' event. Handles hiding controls during\n * ad breaks while playing.\n */\nPlayerWrapper.prototype.onPlay = function () {\n if (this.daiController.isInAdBreak()) {\n this.vjsControls.hide();\n }\n};\n\n/**\n * Called on the player's 'seeked' event. Sets up handling for ad break\n * snapback for VOD streams.\n */\nPlayerWrapper.prototype.onSeekEnd = function () {\n this.daiController.onSeekEnd(this.vjsPlayer.currentTime());\n};\n\n/**\n * Called on the player's 'ready' event to begin initiating IMA.\n */\nPlayerWrapper.prototype.onPlayerReady = function () {\n this.h5Player = document.getElementById(this.getPlayerId()).getElementsByClassName('vjs-tech')[0];\n this.daiController.onPlayerReady();\n};\n\n/**\n * @return {!Object} The stream player.\n */\nPlayerWrapper.prototype.getStreamPlayer = function () {\n return this.h5Player;\n};\n\n/**\n * @return {!Object} The video.js player.\n */\nPlayerWrapper.prototype.getVjsPlayer = function () {\n return this.vjsPlayer;\n};\n\n/**\n * @return {!Object} The vjs player's options object.\n */\nPlayerWrapper.prototype.getPlayerOptions = function () {\n return this.vjsPlayer.options_;\n};\n\n/**\n * Returns the instance of the player id.\n * @return {string} The player id.\n */\nPlayerWrapper.prototype.getPlayerId = function () {\n return this.vjsPlayer.id();\n};\n\n/**\n * Handles ad errors.\n *\n * @param {!Object} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nPlayerWrapper.prototype.onAdError = function (adErrorEvent) {\n this.vjsControls.show();\n var errorMessage = adErrorEvent.getError !== undefined ? adErrorEvent.getError() : adErrorEvent.stack;\n this.vjsPlayer.trigger({\n type: 'adserror',\n data: {\n AdError: errorMessage,\n AdErrorEvent: adErrorEvent\n }\n });\n};\n\n/**\n * Handles ad break starting.\n */\nPlayerWrapper.prototype.onAdBreakStart = function () {\n this.vjsControls.hide();\n};\n\n/**\n * Handles ad break ending.\n */\nPlayerWrapper.prototype.onAdBreakEnd = function () {\n this.vjsControls.show();\n};\n\n/**\n * Reset the player.\n */\nPlayerWrapper.prototype.reset = function () {\n this.vjsControls.show();\n};\n\n/**\n * Copyright 2021 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/**\n * Implementation of the IMA DAI SDK for the plugin.\n *\n * @param {DaiController!} daiController Reference to the parent DAI\n * controller.\n *\n * @constructor\n * @struct\n * @final\n */\nvar SdkImpl = function SdkImpl(daiController) {\n /**\n * Plugin DAI controller.\n */\n this.daiController = daiController;\n\n /**\n * The html5 stream player.\n */\n this.streamPlayer = null;\n\n /**\n * The videoJS stream player.\n */\n this.vjsPlayer = null;\n\n /**\n * IMA SDK StreamManager\n */\n this.streamManager = null;\n\n /**\n * IMA stream UI settings.\n */\n /* eslint no-undef: 'error' */\n /* global google */\n this.uiSettings = new google.ima.dai.api.UiSettings();\n\n /**\n * If the stream is currently in an ad break.\n */\n this.isAdBreak = false;\n\n /**\n * If the stream is currently seeking from a snapback.\n */\n this.isSnapback = false;\n\n /**\n * Originally seeked to time, to return stream to after ads.\n */\n this.snapForwardTime = 0;\n\n /**\n * Timed metadata for the stream.\n */\n this.timedMetadata;\n\n /**\n * Timed metadata record.\n */\n this.metadataLoaded = {};\n this.SOURCE_TYPES = {\n hls: 'application/x-mpegURL',\n dash: 'application/dash+xml'\n };\n};\n\n/**\n * Creates and initializes the IMA DAI SDK objects.\n */\nSdkImpl.prototype.initImaDai = function () {\n var _this = this;\n this.streamPlayer = this.daiController.getStreamPlayer();\n this.vjsPlayer = this.daiController.getVjsPlayer();\n this.createAdUiDiv();\n if (this.daiController.getSettings().locale) {\n this.uiSettings.setLocale(this.daiController.getSettings().locale);\n }\n this.streamManager = new google.ima.dai.api.StreamManager(this.streamPlayer, this.adUiDiv, this.uiSettings);\n this.streamPlayer.addEventListener('pause', this.onStreamPause);\n this.streamPlayer.addEventListener('play', this.onStreamPlay);\n var imaEvents = [google.ima.dai.api.StreamEvent.Type.LOADED, google.ima.dai.api.StreamEvent.Type.ERROR, google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED, google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED];\n imaEvents.forEach(function (event) {\n _this.streamManager.addEventListener(event, _this.onStreamEvent.bind(_this));\n });\n this.vjsPlayer.textTracks().onaddtrack = this.onAddTrack.bind(this);\n this.vjsPlayer.trigger({\n type: 'stream-manager',\n StreamManager: this.streamManager\n });\n this.requestStream();\n};\n\n/**\n * Called when the video player has metadata to process.\n * @param {Event!} event The event that triggered this call.\n */\nSdkImpl.prototype.onAddTrack = function (event) {\n var _this2 = this;\n var track = event.track;\n if (track.kind === 'metadata') {\n track.mode = 'hidden';\n track.addEventListener('cuechange', function (e) {\n var _iterator = _createForOfIteratorHelper(track.activeCues),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var cue = _step.value;\n var metadata = {};\n metadata[cue.value.key] = cue.value.data;\n _this2.streamManager.onTimedMetadata(metadata);\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n });\n }\n};\n\n/**\n * Creates the ad UI container.\n */\nSdkImpl.prototype.createAdUiDiv = function () {\n var uiDiv = document.createElement('div');\n uiDiv.id = 'ad-ui';\n // 3em is the height of the control bar.\n uiDiv.style.height = 'calc(100% - 3em)';\n this.streamPlayer.parentNode.appendChild(uiDiv);\n this.adUiDiv = uiDiv;\n};\n\n/**\n * Called on pause to update the ad UI.\n */\nSdkImpl.prototype.onStreamPause = function () {\n if (this.isAdBreak) {\n this.adUiDiv.style.display = 'none';\n }\n};\n\n/**\n * Called on play to update the ad UI.\n */\nSdkImpl.prototype.onStreamPlay = function () {\n if (this.isAdBreak) {\n this.adUiDiv.style.display = 'block';\n }\n};\n\n/**\n * Called on play to update the ad UI.\n * @param {number} currentTime the current time of the stream.\n */\nSdkImpl.prototype.onSeekEnd = function (currentTime) {\n var streamType = this.daiController.getSettings().streamType;\n if (streamType === 'live') {\n return;\n }\n if (this.isSnapback) {\n this.isSnapback = false;\n return;\n }\n var previousCuePoint = this.streamManager.previousCuePointForStreamTime(currentTime);\n if (previousCuePoint && !previousCuePoint.played) {\n this.isSnapback = true;\n this.snapForwardTime = currentTime;\n this.vjsPlayer.currentTime(previousCuePoint.start);\n }\n};\n\n/**\n * Handles IMA events.\n * @param {google.ima.StreamEvent!} event the IMA event\n */\nSdkImpl.prototype.onStreamEvent = function (event) {\n switch (event.type) {\n case google.ima.dai.api.StreamEvent.Type.LOADED:\n this.loadUrl(event.getStreamData().url);\n break;\n case google.ima.dai.api.StreamEvent.Type.ERROR:\n window.console.warn('Error loading stream, attempting to play backup ' + 'stream. ' + event.getStreamData().errorMessage);\n this.daiController.onErrorLoadingAds(event);\n if (this.daiController.getSettings().fallbackStreamUrl) {\n this.loadUrl(this.daiController.getSettings().fallbackStreamUrl);\n }\n break;\n case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:\n this.isAdBreak = true;\n this.adUiDiv.style.display = 'block';\n this.daiController.onAdBreakStart();\n break;\n case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:\n this.isAdBreak = false;\n this.adUiDiv.style.display = 'none';\n this.daiController.onAdBreakEnd();\n if (this.snapForwardTime && this.snapForwardTime > this.vjsPlayer.currentTime()) {\n this.vjsPlayer.currentTime(this.snapForwardTime);\n this.snapForwardTime = 0;\n }\n break;\n }\n};\n\n/**\n * Loads the stream URL .\n * @param {string} streamUrl the URL for the stream being loaded.\n */\nSdkImpl.prototype.loadUrl = function (streamUrl) {\n this.vjsPlayer.ready(function () {\n var streamFormat = this.daiController.getSettings().streamFormat;\n this.vjsPlayer.src({\n src: streamUrl,\n type: this.SOURCE_TYPES[streamFormat]\n });\n var bookmarkTime = this.daiController.getSettings().bookmarkTime;\n if (bookmarkTime) {\n var startTime = this.streamManager.streamTimeForContentTime(bookmarkTime);\n // Seeking on load triggers the onSeekEnd event, so treat this seek as\n // if it's snapback. Without this, resuming at a bookmark kicks you\n // back to the ad before the bookmark.\n this.isSnapback = true;\n this.vjsPlayer.currentTime(startTime);\n }\n }.bind(this));\n};\n\n/**\n * Creates the AdsRequest and request ads through the AdsLoader.\n */\nSdkImpl.prototype.requestStream = function () {\n var streamRequest;\n var streamType = this.daiController.getSettings().streamType;\n if (streamType === 'vod') {\n streamRequest = new google.ima.dai.api.VODStreamRequest();\n streamRequest.contentSourceId = this.daiController.getSettings().cmsId;\n streamRequest.videoId = this.daiController.getSettings().videoId;\n } else if (streamType === 'live') {\n streamRequest = new google.ima.dai.api.LiveStreamRequest();\n streamRequest.assetKey = this.daiController.getSettings().assetKey;\n } else {\n window.console.warn('No valid stream type selected');\n }\n streamRequest.format = this.daiController.getSettings().streamFormat;\n if (this.daiController.getSettings().apiKey) {\n streamRequest.apiKey = this.daiController.getSettings().apiKey;\n }\n if (this.daiController.getSettings().authToken) {\n streamRequest.authToken = this.daiController.getSettings().authToken;\n }\n if (this.daiController.getSettings().adTagParameters) {\n streamRequest.adTagParameters = this.daiController.getSettings().adTagParameters;\n }\n if (this.daiController.getSettings().streamActivityMonitorId) {\n streamRequest.streamActivityMonitorId = this.daiController.getSettings().streamActivityMonitorId;\n }\n if (this.daiController.getSettings().omidMode) {\n streamRequest.omidAccessModeRules = {};\n var omidValues = this.daiController.getSettings().omidMode;\n if (omidValues.FULL) {\n streamRequest.omidAccessModeRules[google.ima.OmidAccessMode.FULL] = omidValues.FULL;\n }\n if (omidValues.DOMAIN) {\n streamRequest.omidAccessModeRules[google.ima.OmidAccessMode.DOMAIN] = omidValues.DOMAIN;\n }\n if (omidValues.LIMITED) {\n streamRequest.omidAccessModeRules[google.ima.OmidAccessMode.LIMITED] = omidValues.LIMITED;\n }\n }\n this.streamManager.requestStream(streamRequest);\n this.vjsPlayer.trigger({\n type: 'stream-request',\n StreamRequest: streamRequest\n });\n};\n\n/**\n * Initiates IMA when the player is ready.\n */\nSdkImpl.prototype.onPlayerReady = function () {\n this.initImaDai();\n};\n\n/**\n * Reset the StreamManager when the player is disposed.\n */\nSdkImpl.prototype.onPlayerDisposed = function () {\n if (this.streamManager) {\n this.streamManager.reset();\n }\n};\n\n/**\n * Adds an EventListener to the StreamManager. For a list of available events,\n * see\n * https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/html5/reference/js/StreamEvent#.Type\n * @param {google.ima.dai.api.StreamEvent.Type} event The StreamEvent.Type for\n * which to listen.\n * @param {callback} callback The method to call when the event is fired.\n */\nSdkImpl.prototype.addEventListener = function (event, callback) {\n if (this.streamManager) {\n this.streamManager.addEventListener(event, callback);\n }\n};\n\n/**\n * Returns the instance of the StreamManager.\n * @return {google.ima.StreamManager!} The StreamManager being used by the\n * plugin.\n */\nSdkImpl.prototype.getStreamManager = function () {\n return this.streamManager;\n};\n\n/**\n * Reset the SDK implementation.\n */\nSdkImpl.prototype.reset = function () {\n if (this.streamManager) {\n this.streamManager.reset();\n }\n};\n\n/**\n * Copyright 2021 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/**\n * The coordinator for the DAI portion of the plugin. Facilitates\n * communication between all other plugin classes.\n *\n * @param {Object!} player Instance of the video.js player.\n * @param {Object!} options Options provided by the implementation.\n * @constructor\n * @struct\n * @final\n */\nvar DaiController = function DaiController(player, options) {\n /**\n * If the stream is currently in an ad break.\n * @type {boolean}\n */\n this.inAdBreak = false;\n\n /**\n * Stores user-provided settings.\n * @type {Object!}\n */\n this.settings = {};\n\n /**\n * Whether or not we are running on a mobile platform.\n */\n this.isMobile = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/Android/i);\n\n /**\n * Whether or not we are running on an iOS platform.\n */\n this.isIos = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i);\n this.initWithSettings(options);\n\n /**\n * Stores contrib-ads default settings.\n */\n var contribAdsDefaults = {\n debug: this.settings.debug,\n timeout: this.settings.timeout,\n prerollTimeout: this.settings.prerollTimeout\n };\n var adsPluginSettings = Object.assign({}, contribAdsDefaults, options.contribAdsSettings || {});\n this.playerWrapper = new PlayerWrapper(player, adsPluginSettings, this);\n this.sdkImpl = new SdkImpl(this);\n};\nDaiController.IMA_DEFAULTS = {\n adLabel: 'Advertisement',\n adLabelNofN: 'of',\n debug: false,\n disableAdControls: false,\n showControlsForJSAds: true\n};\n\n/**\n * Extends the settings to include user-provided settings.\n *\n * @param {Object!} options Options to be used in initialization.\n */\nDaiController.prototype.initWithSettings = function (options) {\n this.settings = Object.assign({}, DaiController.IMA_DEFAULTS, options || {});\n this.warnAboutDeprecatedSettings();\n\n // Default showing countdown timer to true.\n this.showCountdown = true;\n if (this.settings.showCountdown === false) {\n this.showCountdown = false;\n }\n};\n\n/**\n * Logs console warnings when deprecated settings are used.\n */\nDaiController.prototype.warnAboutDeprecatedSettings = function () {\n var _this = this;\n var deprecatedSettings = [\n // Currently no DAI plugin settings are deprecated.\n ];\n deprecatedSettings.forEach(function (setting) {\n if (_this.settings[setting] !== undefined) {\n console.warn('WARNING: videojs.imaDai setting ' + setting + ' is deprecated');\n }\n });\n};\n\n/**\n * Return the settings object.\n *\n * @return {Object!} The settings object.\n */\nDaiController.prototype.getSettings = function () {\n return this.settings;\n};\n\n/**\n * Return whether or not we're in a mobile environment.\n *\n * @return {boolean} True if running on mobile, false otherwise.\n */\nDaiController.prototype.getIsMobile = function () {\n return this.isMobile;\n};\n\n/**\n * Return whether or not we're in an iOS environment.\n *\n * @return {boolean} True if running on iOS, false otherwise.\n */\nDaiController.prototype.getIsIos = function () {\n return this.isIos;\n};\n\n/**\n * @return {Object!} The html5 player.\n */\nDaiController.prototype.getStreamPlayer = function () {\n return this.playerWrapper.getStreamPlayer();\n};\n\n/**\n * @return {Object!} The video.js player.\n */\nDaiController.prototype.getVjsPlayer = function () {\n return this.playerWrapper.getVjsPlayer();\n};\n\n/**\n * Requests the stream.\n */\nDaiController.prototype.requestStream = function () {\n this.sdkImpl.requestStream();\n};\n\n/**\n * Add or modify a setting.\n *\n * @param {string} key Key to modify\n * @param {Object!} value Value to set at key.\n*/\nDaiController.prototype.setSetting = function (key, value) {\n this.settings[key] = value;\n};\n\n/**\n * Called when there is an error loading ads.\n *\n * @param {Object!} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nDaiController.prototype.onErrorLoadingAds = function (adErrorEvent) {\n this.playerWrapper.onAdError(adErrorEvent);\n};\n\n/**\n * Relays ad errors to the player wrapper.\n *\n * @param {Object!} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nDaiController.prototype.onAdError = function (adErrorEvent) {\n this.playerWrapper.onAdError(adErrorEvent);\n};\n\n/**\n * Signals player that an ad break has started.\n */\nDaiController.prototype.onAdBreakStart = function () {\n this.inAdBreak = true;\n this.playerWrapper.onAdBreakStart();\n};\n\n/**\n * Signals player that an ad break has ended.\n */\nDaiController.prototype.onAdBreakEnd = function () {\n this.inAdBreak = false;\n this.playerWrapper.onAdBreakEnd();\n};\n\n/**\n * Called when the player is disposed.\n */\nDaiController.prototype.onPlayerDisposed = function () {\n this.contentAndAdsEndedListeners = [];\n this.sdkImpl.onPlayerDisposed();\n};\n\n/**\n * Returns if the stream is currently in an ad break.\n * @return {boolean} If the stream is currently in an ad break.\n */\nDaiController.prototype.isInAdBreak = function () {\n return this.inAdBreak;\n};\n\n/**\n * Called on seek end to check for ad snapback.\n * @param {number} currentTime the current time of the stream.\n */\nDaiController.prototype.onSeekEnd = function (currentTime) {\n this.sdkImpl.onSeekEnd(currentTime);\n};\n\n/**\n * Called when the player is ready.\n */\nDaiController.prototype.onPlayerReady = function () {\n this.sdkImpl.onPlayerReady();\n};\n\n/**\n * Resets the state of the plugin.\n */\nDaiController.prototype.reset = function () {\n this.sdkImpl.reset();\n this.playerWrapper.reset();\n};\n\n/**\n * Adds an EventListener to the StreamManager. For a list of available events,\n * see\n * https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/html5/reference/js/StreamEvent\n * @param {google.ima.StreamEvent.Type!} event The AdEvent.Type for which to\n * listen.\n * @param {callback!} callback The method to call when the event is fired.\n */\nDaiController.prototype.addEventListener = function (event, callback) {\n this.sdkImpl.addEventListener(event, callback);\n};\n\n/**\n * Returns the instance of the StreamManager.\n * @return {google.ima.StreamManager!} The StreamManager being used by the\n * plugin.\n */\nDaiController.prototype.getStreamManager = function () {\n return this.sdkImpl.getStreamManager();\n};\n\n/**\n * Returns the instance of the player id.\n * @return {string} The player id.\n */\nDaiController.prototype.getPlayerId = function () {\n return this.playerWrapper.getPlayerId();\n};\n\n/**\n * @return {boolean} true if we expect that the stream will autoplay. false\n * otherwise.\n */\nDaiController.prototype.streamWillAutoplay = function () {\n if (this.settings.streamWillAutoplay !== undefined) {\n return this.settings.streamWillAutoplay;\n } else {\n return !!this.playerWrapper.getPlayerOptions().autoplay;\n }\n};\n\n/**\n * Triggers an event on the VJS player\n * @param {string} name The event name.\n * @param {Object!} data The event data.\n */\nDaiController.prototype.triggerPlayerEvent = function (name, data) {\n this.playerWrapper.triggerPlayerEvent(name, data);\n};\n\n/**\n * Exposes the ImaPlugin to a publisher implementation.\n *\n * @param {Object} player Instance of the video.js player to which this plugin\n * will be added.\n * @param {Object} options Options provided by the implementation.\n * @constructor\n * @struct\n * @final\n */\nvar ImaPlugin = function ImaPlugin(player, options) {\n this.controller = new Controller(player, options);\n\n /**\n * Listener JSDoc for ESLint. This listener can be passed to\n * addContent(AndAds)EndedListener.\n * @callback listener\n */\n\n /**\n * Adds a listener that will be called when content and all ads have\n * finished playing.\n * @param {listener} listener The listener to be called when content and ads\n * complete.\n */\n this.addContentAndAdsEndedListener = function (listener) {\n this.controller.addContentAndAdsEndedListener(listener);\n }.bind(this);\n\n /**\n * Adds a listener for the 'readyforpostroll' event of the video player. This\n * should be used instead of setting an 'readyforpostroll' listener directly\n * to ensure that the ima can do proper cleanup of the SDK before other event\n * listeners are called.\n * @param {listener} listener The listener to be called when content\n * completes.\n */\n this.addContentEndedListener = function (listener) {\n this.controller.addContentEndedListener(listener);\n }.bind(this);\n\n /**\n * Callback JSDoc for ESLint. This callback can be passed to addEventListener.\n * @callback callback\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/client-side/reference/js/google.ima.AdEvent#.Type\n * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to\n * listen.\n * @param {callback} callback The method to call when the event is fired.\n */\n this.addEventListener = function (event, callback) {\n this.controller.addEventListener(event, callback);\n }.bind(this);\n\n /**\n * Changes the ad tag. You will need to call requestAds after this method\n * for the new ads to be requested.\n * @param {?string} adTag The ad tag to be requested the next time requestAds\n * is called.\n */\n this.changeAdTag = function (adTag) {\n this.controller.changeAdTag(adTag);\n }.bind(this);\n\n /**\n * Returns the instance of the AdsManager.\n * @return {google.ima.AdsManager} The AdsManager being used by the plugin.\n */\n this.getAdsManager = function () {\n return this.controller.getAdsManager();\n }.bind(this);\n\n /**\n * Initializes the AdDisplayContainer. On mobile, this must be done as a\n * result of user action.\n */\n this.initializeAdDisplayContainer = function () {\n this.controller.initializeAdDisplayContainer();\n }.bind(this);\n\n /**\n * Pauses the ad.\n */\n this.pauseAd = function () {\n this.controller.pauseAd();\n }.bind(this);\n\n /**\n * Called by publishers in manual ad break playback mode to start an ad\n * break.\n */\n this.playAdBreak = function () {\n this.controller.playAdBreak();\n }.bind(this);\n\n /**\n * Creates the AdsRequest and request ads through the AdsLoader.\n */\n this.requestAds = function () {\n this.controller.requestAds();\n }.bind(this);\n\n /**\n * Resumes the ad.\n */\n this.resumeAd = function () {\n this.controller.resumeAd();\n }.bind(this);\n\n /**\n * Sets the listener to be called to trigger manual ad break playback.\n * @param {listener} listener The listener to be called to trigger manual ad\n * break playback.\n */\n this.setAdBreakReadyListener = function (listener) {\n this.controller.setAdBreakReadyListener(listener);\n }.bind(this);\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 */\n this.setContentWithAdTag = function (contentSrc, adTag) {\n this.controller.setContentWithAdTag(contentSrc, adTag);\n }.bind(this);\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 ads response is\n * used 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} adsResponse The ads response to be requested when the\n * content loads. Leave blank to use the existing ads response.\n */\n this.setContentWithAdsResponse = function (contentSrc, adsResponse) {\n this.controller.setContentWithAdsResponse(contentSrc, adsResponse);\n }.bind(this);\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 ads request is\n * used 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 {?Object} adsRequest The ads request to be requested when the\n * content loads. Leave blank to use the existing ads request.\n */\n this.setContentWithAdsRequest = function (contentSrc, adsRequest) {\n this.controller.setContentWithAdsRequest(contentSrc, adsRequest);\n }.bind(this);\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 this.setShowCountdown = function (showCountdownIn) {\n this.controller.setShowCountdown(showCountdownIn);\n }.bind(this);\n};\n\n/**\n * Exposes the ImaDaiPlugin to a publisher implementation.\n *\n * @param {Object} player Instance of the video.js player to which this plugin\n * will be added.\n * @param {Object} options Options provided by the implementation.\n * @constructor\n * @struct\n * @final\n */\nvar ImaDaiPlugin = function ImaDaiPlugin(player, options) {\n this.controller = new DaiController(player, options);\n\n /**\n * Adds a listener that will be called when content and all ads in the\n * stream have finished playing. VOD stream only.\n * @param {listener} listener The listener to be called when content and ads\n * complete.\n */\n this.streamEndedListener = function (listener) {\n this.controller.addStreamEndedListener(listener);\n }.bind(this);\n\n /**\n * Adds an EventListener to the StreamManager.\n * @param {google.ima.StreamEvent.Type} event The StreamEvent.Type for which\n * to listen.\n * @param {callback} callback The method to call when the event is fired.\n */\n this.addEventListener = function (event, callback) {\n this.controller.addEventListener(event, callback);\n }.bind(this);\n\n /**\n * Returns the instance of the StreamManager.\n * @return {google.ima.StreamManager} The StreamManager being used by the\n * plugin.\n */\n this.getStreamManager = function () {\n return this.controller.getStreamManager();\n }.bind(this);\n};\n\n/**\n * Initializes the plugin for client-side ads.\n * @param {Object} options Plugin option set on initiation.\n */\nvar init = function init(options) {\n /* eslint no-invalid-this: 'off' */\n this.ima = new ImaPlugin(this, options);\n};\n\n/**\n * LiveStream class used for DAI live streams.\n */\nvar LiveStream = /*#__PURE__*/_createClass(\n/**\n * LiveStream class constructor used for DAI live streams.\n * @param {string} streamFormat stream format, plugin currently supports only\n * 'hls' streams.\n * @param {string} assetKey live stream's asset key.\n */\nfunction LiveStream(streamFormat, assetKey) {\n _classCallCheck(this, LiveStream);\n streamFormat = streamFormat.toLowerCase();\n if (streamFormat !== 'hls' && streamFormat !== 'dash') {\n window.console.error('VodStream error: incorrect streamFormat.');\n return;\n } else if (streamFormat === 'dash') {\n window.console.error('streamFormat error: DASH streams are not' + 'currently supported by this plugin.');\n return;\n } else if (typeof assetKey !== 'string') {\n window.console.error('assetKey error: value must be string.');\n return;\n }\n this.streamFormat = streamFormat;\n this.assetKey = assetKey;\n});\n/**\n * VodStream class used for DAI VOD streams.\n */\nvar VodStream = /*#__PURE__*/_createClass(\n/**\n * VodStream class constructor used for DAI VOD streams.\n * @param {string} streamFormat stream format, plugin currently supports only\n * 'hls' streams.\n * @param {string} cmsId VOD stream's CMS ID.\n * @param {string} videoId VOD stream's video ID.\n */\nfunction VodStream(streamFormat, cmsId, videoId) {\n _classCallCheck(this, VodStream);\n streamFormat = streamFormat.toLowerCase();\n if (streamFormat !== 'hls' && streamFormat !== 'dash') {\n window.console.error('VodStream error: incorrect streamFormat.');\n return;\n } else if (streamFormat === 'dash') {\n window.console.error('streamFormat error: DASH streams are not' + 'currently supported by this plugin.');\n return;\n } else if (typeof cmsId !== 'string') {\n window.console.error('cmsId error: value must be string.');\n return;\n } else if (typeof videoId !== 'string') {\n window.console.error('videoId error: value must be string.');\n return;\n }\n this.streamFormat = streamFormat;\n this.cmsId = cmsId;\n this.videoId = videoId;\n});\n/**\n * Initializes the plugin for DAI ads.\n * @param {Object} stream Accepts either an instance of the LiveStream or\n * VodStream classes.\n * @param {Object} options Plugin option set on initiation.\n */\nvar initDai = function initDai(stream, options) {\n if (stream instanceof LiveStream) {\n options.streamType = 'live';\n options.assetKey = stream.assetKey;\n } else if (stream instanceof VodStream) {\n options.streamType = 'vod';\n options.cmsId = stream.cmsId;\n options.videoId = stream.videoId;\n } else {\n window.console.error('initDai() first parameter must be an instance of LiveStream or ' + 'VodStream.');\n return;\n }\n options.streamFormat = stream.streamFormat;\n /* eslint no-invalid-this: 'off' */\n this.imaDai = new ImaDaiPlugin(this, options);\n};\nvar registerPlugin = (video_js__WEBPACK_IMPORTED_MODULE_0___default().registerPlugin) || (video_js__WEBPACK_IMPORTED_MODULE_0___default().plugin);\nregisterPlugin('ima', init);\nregisterPlugin('imaDai', initDai);\n\n\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/videojs-ima/dist/videojs.ima.es.js?\n}");
55
-
56
- /***/ },
57
-
58
- /***/ "../node_modules/videojs-ima/dist/videojs.ima.scss"
59
- /*!*********************************************************!*\
60
- !*** ../node_modules/videojs-ima/dist/videojs.ima.scss ***!
61
- \*********************************************************/
62
- (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
63
-
64
- "use strict";
65
- eval("{__webpack_require__.r(__webpack_exports__);\n// extracted by mini-css-extract-plugin\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/videojs-ima/dist/videojs.ima.scss?\n}");
66
-
67
- /***/ },
68
-
69
- /***/ "./plugins/ima/ima.js"
70
- /*!****************************!*\
71
- !*** ./plugins/ima/ima.js ***!
72
- \****************************/
73
- (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
73
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
74
74
 
75
75
  "use strict";
76
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var videojs_contrib_ads__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! videojs-contrib-ads */ \"../node_modules/videojs-contrib-ads/dist/videojs-contrib-ads.es.js\");\n/* harmony import */ var videojs_ima__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! videojs-ima */ \"../node_modules/videojs-ima/dist/videojs.ima.es.js\");\n/* harmony import */ var videojs_ima_dist_videojs_ima_scss__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! videojs-ima/dist/videojs.ima.scss */ \"../node_modules/videojs-ima/dist/videojs.ima.scss\");\n\n\n\n\n//# sourceURL=webpack://cloudinary-video-player/./plugins/ima/ima.js?\n}");
76
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LiveStream: () => (/* binding */ LiveStream),\n/* harmony export */ VodStream: () => (/* binding */ VodStream),\n/* harmony export */ \"default\": () => (/* binding */ ImaPlugin)\n/* harmony export */ });\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\");\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(video_js__WEBPACK_IMPORTED_MODULE_0__);\n\n\nfunction _arrayLikeToArray(r, a) {\n (null == a || a > r.length) && (a = r.length);\n for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];\n return n;\n}\nfunction _classCallCheck(a, n) {\n if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\");\n}\nfunction _createClass(e, r, t) {\n return Object.defineProperty(e, \"prototype\", {\n writable: false\n }), e;\n}\nfunction _createForOfIteratorHelper(r, e) {\n var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"];\n if (!t) {\n if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) {\n t && (r = t);\n var n = 0,\n F = function () {};\n return {\n s: F,\n n: function () {\n return n >= r.length ? {\n done: true\n } : {\n done: false,\n value: r[n++]\n };\n },\n e: function (r) {\n throw r;\n },\n f: F\n };\n }\n throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n }\n var o,\n a = true,\n u = false;\n return {\n s: function () {\n t = t.call(r);\n },\n n: function () {\n var r = t.next();\n return a = r.done, r;\n },\n e: function (r) {\n u = true, o = r;\n },\n f: function () {\n try {\n a || null == t.return || t.return();\n } finally {\n if (u) throw o;\n }\n }\n };\n}\nfunction _typeof(o) {\n \"@babel/helpers - typeof\";\n\n return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) {\n return typeof o;\n } : function (o) {\n return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o;\n }, _typeof(o);\n}\nfunction _unsupportedIterableToArray(r, a) {\n if (r) {\n if (\"string\" == typeof r) return _arrayLikeToArray(r, a);\n var t = {}.toString.call(r).slice(8, -1);\n return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;\n }\n}\n\n/**\n * Copyright 2017 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/**\n * Wraps the video.js player for the plugin.\n *\n * @param {Object} player Video.js player instance.\n * @param {Object} adsPluginSettings Settings for the contrib-ads plugin.\n * @param {Controller} controller Reference to the parent controller.\n */\nvar PlayerWrapper$1 = function PlayerWrapper(player, adsPluginSettings, controller) {\n /**\n * Instance of the video.js player.\n */\n this.vjsPlayer = player;\n\n /**\n * Plugin controller.\n */\n this.controller = controller;\n\n /**\n * Timer used to track content progress.\n */\n this.contentTrackingTimer = null;\n\n /**\n * True if our content video has completed, false otherwise.\n */\n this.contentComplete = false;\n\n /**\n * Handle to interval that repeatedly updates current time.\n */\n this.updateTimeIntervalHandle = null;\n\n /**\n * Interval (ms) to check for player resize for fluid support.\n */\n this.updateTimeInterval = 1000;\n\n /**\n * Handle to interval that repeatedly checks for seeking.\n */\n this.seekCheckIntervalHandle = null;\n\n /**\n * Interval (ms) on which to check if the user is seeking through the\n * content.\n */\n this.seekCheckInterval = 1000;\n\n /**\n * Handle to interval that repeatedly checks for player resize.\n */\n this.resizeCheckIntervalHandle = null;\n\n /**\n * Interval (ms) to check for player resize for fluid support.\n */\n this.resizeCheckInterval = 250;\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 this.seekThreshold = 100;\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 this.contentEndedListeners = [];\n\n /**\n * Stores the content source so we can re-populate it manually after a\n * post-roll on iOS.\n */\n this.contentSource = '';\n\n /**\n * Stores the content source type so we can re-populate it manually after a\n * post-roll.\n */\n this.contentSourceType = '';\n\n /**\n * Stores data for the content playhead tracker.\n */\n this.contentPlayheadTracker = {\n currentTime: 0,\n previousTime: 0,\n seeking: false,\n duration: 0\n };\n\n /**\n * Player dimensions. Used in our resize check.\n */\n this.vjsPlayerDimensions = {\n width: this.getPlayerWidth(),\n height: this.getPlayerHeight()\n };\n\n /**\n * Video.js control bar.\n */\n this.vjsControls = this.vjsPlayer.getChild('controlBar');\n\n /**\n * Vanilla HTML5 video player underneath the video.js player.\n */\n this.h5Player = null;\n this.vjsPlayer.one('play', this.setUpPlayerIntervals.bind(this));\n this.boundContentEndedListener = this.localContentEndedListener.bind(this);\n this.vjsPlayer.on('readyforpostroll', this.boundContentEndedListener);\n this.vjsPlayer.on('dispose', this.playerDisposedListener.bind(this));\n this.vjsPlayer.on('readyforpreroll', this.onReadyForPreroll.bind(this));\n this.vjsPlayer.on('adtimeout', this.onAdTimeout.bind(this));\n this.vjsPlayer.ready(this.onPlayerReady.bind(this));\n if (this.controller.getSettings().requestMode === 'onPlay') {\n this.vjsPlayer.one('play', this.controller.requestAds.bind(this.controller));\n }\n if (!this.vjsPlayer.ads) {\n window.console.warn('You may be using a version of videojs-contrib-ads ' + 'that is not compatible with your version of video.js.');\n }\n this.vjsPlayer.ads(adsPluginSettings);\n};\n\n/**\n * Set up the intervals we use on the player.\n */\nPlayerWrapper$1.prototype.setUpPlayerIntervals = function () {\n /**\n * Clear old interval handers in case the method was called more than once\n */\n if (this.updateTimeIntervalHandle) {\n clearInterval(this.updateTimeIntervalHandle);\n }\n if (this.seekCheckIntervalHandle) {\n clearInterval(this.seekCheckIntervalHandle);\n }\n if (this.resizeCheckIntervalHandle) {\n clearInterval(this.resizeCheckIntervalHandle);\n }\n this.updateTimeIntervalHandle = setInterval(this.updateCurrentTime.bind(this), this.updateTimeInterval);\n this.seekCheckIntervalHandle = setInterval(this.checkForSeeking.bind(this), this.seekCheckInterval);\n this.resizeCheckIntervalHandle = setInterval(this.checkForResize.bind(this), this.resizeCheckInterval);\n};\n\n/**\n * Updates the current time of the video\n */\nPlayerWrapper$1.prototype.updateCurrentTime = function () {\n if (!this.contentPlayheadTracker.seeking) {\n this.contentPlayheadTracker.currentTime = this.vjsPlayer.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 */\nPlayerWrapper$1.prototype.checkForSeeking = function () {\n var tempCurrentTime = this.vjsPlayer.currentTime();\n var diff = (tempCurrentTime - this.contentPlayheadTracker.previousTime) * 1000;\n if (Math.abs(diff) > this.seekCheckInterval + this.seekThreshold) {\n this.contentPlayheadTracker.seeking = true;\n } else {\n this.contentPlayheadTracker.seeking = false;\n }\n this.contentPlayheadTracker.previousTime = this.vjsPlayer.currentTime();\n};\n\n/**\n * Detects when the player is resized (for fluid support) and resizes the\n * ads manager to match.\n */\nPlayerWrapper$1.prototype.checkForResize = function () {\n var currentWidth = this.getPlayerWidth();\n var currentHeight = this.getPlayerHeight();\n if (currentWidth != this.vjsPlayerDimensions.width || currentHeight != this.vjsPlayerDimensions.height) {\n this.vjsPlayerDimensions.width = currentWidth;\n this.vjsPlayerDimensions.height = currentHeight;\n this.controller.onPlayerResize(currentWidth, currentHeight);\n }\n};\n\n/**\n * Local content ended listener for contentComplete.\n */\nPlayerWrapper$1.prototype.localContentEndedListener = function () {\n if (!this.contentComplete) {\n this.contentComplete = true;\n this.controller.onContentComplete();\n }\n for (var index in this.contentEndedListeners) {\n if (typeof this.contentEndedListeners[index] === 'function') {\n this.contentEndedListeners[index]();\n }\n }\n if (this.vjsPlayer.el()) {\n this.vjsPlayer.one('play', this.setUpPlayerIntervals.bind(this));\n }\n};\n\n/**\n * Called when it's time to play a post-roll but we don't have one to play.\n */\nPlayerWrapper$1.prototype.onNoPostroll = function () {\n this.vjsPlayer.trigger('nopostroll');\n};\n\n/**\n * Detects when the video.js player has been disposed.\n */\nPlayerWrapper$1.prototype.playerDisposedListener = function () {\n this.contentEndedListeners = [];\n this.controller.onPlayerDisposed();\n this.contentComplete = true;\n this.vjsPlayer.off('readyforpostroll', this.boundContentEndedListener);\n\n // Bug fix: https://github.com/googleads/videojs-ima/issues/306\n if (this.vjsPlayer.ads.adTimeoutTimeout) {\n clearTimeout(this.vjsPlayer.ads.adTimeoutTimeout);\n }\n var intervalsToClear = [this.updateTimeIntervalHandle, this.seekCheckIntervalHandle, this.resizeCheckIntervalHandle];\n for (var index in intervalsToClear) {\n if (intervalsToClear[index]) {\n clearInterval(intervalsToClear[index]);\n }\n }\n};\n\n/**\n * Start ad playback, or content video playback in the absence of a\n * pre-roll.\n */\nPlayerWrapper$1.prototype.onReadyForPreroll = function () {\n this.controller.onPlayerReadyForPreroll();\n};\n\n/**\n * Detects if the ad has timed out.\n */\nPlayerWrapper$1.prototype.onAdTimeout = function () {\n this.controller.onAdTimeout();\n};\n\n/**\n * Called when the player fires its 'ready' event.\n */\nPlayerWrapper$1.prototype.onPlayerReady = function () {\n this.h5Player = document.getElementById(this.getPlayerId()).getElementsByClassName('vjs-tech')[0];\n\n // Detect inline options\n if (this.h5Player.hasAttribute('autoplay')) {\n this.controller.setSetting('adWillAutoPlay', true);\n }\n\n // Sync ad volume with player volume.\n this.onVolumeChange();\n this.vjsPlayer.on('fullscreenchange', this.onFullscreenChange.bind(this));\n this.vjsPlayer.on('volumechange', this.onVolumeChange.bind(this));\n this.controller.onPlayerReady();\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 */\nPlayerWrapper$1.prototype.onFullscreenChange = function () {\n if (this.vjsPlayer.isFullscreen()) {\n this.controller.onPlayerEnterFullscreen();\n } else {\n this.controller.onPlayerExitFullscreen();\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 */\nPlayerWrapper$1.prototype.onVolumeChange = function () {\n var newVolume = this.vjsPlayer.muted() ? 0 : this.vjsPlayer.volume();\n this.controller.onPlayerVolumeChanged(newVolume);\n};\n\n/**\n * Inject the ad container div into the DOM.\n *\n * @param{HTMLElement} adContainerDiv The ad container div.\n */\nPlayerWrapper$1.prototype.injectAdContainerDiv = function (adContainerDiv) {\n this.vjsControls.el().parentNode.appendChild(adContainerDiv);\n};\n\n/**\n * @return {Object} The content player.\n */\nPlayerWrapper$1.prototype.getContentPlayer = function () {\n return this.h5Player;\n};\n\n/**\n * @return {number} The volume, 0-1.\n */\nPlayerWrapper$1.prototype.getVolume = function () {\n return this.vjsPlayer.muted() ? 0 : this.vjsPlayer.volume();\n};\n\n/**\n * Set the volume of the player. 0-1.\n *\n * @param {number} volume The new volume.\n */\nPlayerWrapper$1.prototype.setVolume = function (volume) {\n this.vjsPlayer.volume(volume);\n if (volume == 0) {\n this.vjsPlayer.muted(true);\n } else {\n this.vjsPlayer.muted(false);\n }\n};\n\n/**\n * Ummute the player.\n */\nPlayerWrapper$1.prototype.unmute = function () {\n this.vjsPlayer.muted(false);\n};\n\n/**\n * Mute the player.\n */\nPlayerWrapper$1.prototype.mute = function () {\n this.vjsPlayer.muted(true);\n};\n\n/**\n * Play the video.\n */\nPlayerWrapper$1.prototype.play = function () {\n this.vjsPlayer.play();\n};\n\n/**\n * Toggles playback of the video.\n */\nPlayerWrapper$1.prototype.togglePlayback = function () {\n if (this.vjsPlayer.paused()) {\n this.vjsPlayer.play();\n } else {\n this.vjsPlayer.pause();\n }\n};\n\n/**\n * Get the player width.\n *\n * @return {number} The player's width.\n */\nPlayerWrapper$1.prototype.getPlayerWidth = function () {\n var width = (getComputedStyle(this.vjsPlayer.el()) || {}).width;\n if (!width || parseFloat(width) === 0) {\n width = (this.vjsPlayer.el().getBoundingClientRect() || {}).width;\n }\n return parseFloat(width) || this.vjsPlayer.width();\n};\n\n/**\n * Get the player height.\n *\n * @return {number} The player's height.\n */\nPlayerWrapper$1.prototype.getPlayerHeight = function () {\n var height = (getComputedStyle(this.vjsPlayer.el()) || {}).height;\n if (!height || parseFloat(height) === 0) {\n height = (this.vjsPlayer.el().getBoundingClientRect() || {}).height;\n }\n return parseFloat(height) || this.vjsPlayer.height();\n};\n\n/**\n * @return {Object} The vjs player's options object.\n */\nPlayerWrapper$1.prototype.getPlayerOptions = function () {\n return this.vjsPlayer.options_;\n};\n\n/**\n * Returns the instance of the player id.\n * @return {string} The player id.\n */\nPlayerWrapper$1.prototype.getPlayerId = function () {\n return this.vjsPlayer.id();\n};\n\n/**\n * Toggle fullscreen state.\n */\nPlayerWrapper$1.prototype.toggleFullscreen = function () {\n if (this.vjsPlayer.isFullscreen()) {\n this.vjsPlayer.exitFullscreen();\n } else {\n this.vjsPlayer.requestFullscreen();\n }\n};\n\n/**\n * Returns the content playhead tracker.\n *\n * @return {Object} The content playhead tracker.\n */\nPlayerWrapper$1.prototype.getContentPlayheadTracker = function () {\n return this.contentPlayheadTracker;\n};\n\n/**\n * Handles ad errors.\n *\n * @param {Object} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nPlayerWrapper$1.prototype.onAdError = function (adErrorEvent) {\n this.vjsControls.show();\n var errorMessage = adErrorEvent.getError !== undefined ? adErrorEvent.getError() : adErrorEvent.stack;\n this.vjsPlayer.trigger({\n type: 'adserror',\n data: {\n AdError: errorMessage,\n AdErrorEvent: adErrorEvent\n }\n });\n};\n\n/**\n * Handles ad log messages.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the IMA SDK.\n */\nPlayerWrapper$1.prototype.onAdLog = function (adEvent) {\n var adData = adEvent.getAdData();\n var errorMessage = adData['adError'] !== undefined ? adData['adError'].getMessage() : undefined;\n this.vjsPlayer.trigger({\n type: 'adslog',\n data: {\n AdError: errorMessage,\n AdEvent: adEvent\n }\n });\n};\n\n/**\n * Handles ad break starting.\n */\nPlayerWrapper$1.prototype.onAdBreakStart = function () {\n this.contentSource = this.vjsPlayer.currentSrc();\n this.contentSourceType = this.vjsPlayer.currentType();\n this.vjsPlayer.off('readyforpostroll', this.boundContentEndedListener);\n this.vjsPlayer.ads.startLinearAdMode();\n this.vjsControls.hide();\n this.vjsPlayer.pause();\n};\n\n/**\n * Handles ad break ending.\n */\nPlayerWrapper$1.prototype.onAdBreakEnd = function () {\n this.vjsPlayer.on('readyforpostroll', this.boundContentEndedListener);\n if (this.vjsPlayer.ads.inAdBreak()) {\n this.vjsPlayer.ads.endLinearAdMode();\n }\n this.vjsControls.show();\n};\n\n/**\n * Handles an individual ad start.\n */\nPlayerWrapper$1.prototype.onAdStart = function () {\n this.vjsPlayer.trigger('ads-ad-started');\n};\n\n/**\n * Handles when all ads have finished playing.\n */\nPlayerWrapper$1.prototype.onAllAdsCompleted = function () {\n if (this.contentComplete == true) {\n // The null check on this.contentSource was added to fix\n // an error when the post-roll was an empty VAST tag.\n if (this.contentSource && this.vjsPlayer.currentSrc() != this.contentSource) {\n this.vjsPlayer.src({\n src: this.contentSource,\n type: this.contentSourceType\n });\n }\n this.controller.onContentAndAdsCompleted();\n }\n};\n\n/**\n * Triggers adsready for contrib-ads.\n */\nPlayerWrapper$1.prototype.onAdsReady = function () {\n this.vjsPlayer.trigger('adsready');\n};\n\n/**\n * Changes the player source.\n * @param {?string} contentSrc The URI for the content to be played. Leave\n * blank to use the existing content.\n */\nPlayerWrapper$1.prototype.changeSource = function (contentSrc) {\n // Only try to pause the player when initialised with a source already\n if (this.vjsPlayer.currentSrc()) {\n this.vjsPlayer.currentTime(0);\n this.vjsPlayer.pause();\n }\n if (contentSrc) {\n this.vjsPlayer.src(contentSrc);\n }\n this.vjsPlayer.one('loadedmetadata', this.seekContentToZero.bind(this));\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 */\nPlayerWrapper$1.prototype.seekContentToZero = function () {\n this.vjsPlayer.currentTime(0);\n};\n\n/**\n * Triggers an event on the VJS player\n * @param {string} name The event name.\n * @param {Object} data The event data.\n */\nPlayerWrapper$1.prototype.triggerPlayerEvent = function (name, data) {\n this.vjsPlayer.trigger(name, data);\n};\n\n/**\n * Listener JSDoc for ESLint. This listener can be passed to\n * addContentEndedListener.\n * @callback listener\n */\n\n/**\n * Adds a listener for the 'readyforpostroll' event of the video player. This\n * should be used instead of setting an 'readyforpostroll' listener directly to\n * ensure that the ima can do proper cleanup of the SDK before other event\n * listeners are called.\n * @param {listener} listener The listener to be called when content\n * completes.\n */\nPlayerWrapper$1.prototype.addContentEndedListener = function (listener) {\n this.contentEndedListeners.push(listener);\n};\n\n/**\n * Reset the player.\n */\nPlayerWrapper$1.prototype.reset = function () {\n // Attempts to remove the contentEndedListener before adding it.\n // This is to prevent an error where an erroring video caused multiple\n // contentEndedListeners to be added.\n this.vjsPlayer.off('readyforpostroll', this.boundContentEndedListener);\n this.vjsPlayer.on('readyforpostroll', this.boundContentEndedListener);\n this.vjsControls.show();\n if (this.vjsPlayer.ads.inAdBreak()) {\n this.vjsPlayer.ads.endLinearAdMode();\n }\n // Reset the content time we give the SDK. Fixes an issue where requesting\n // VMAP followed by VMAP would play the second mid-rolls as pre-rolls if\n // the first playthrough of the video passed the second response's\n // mid-roll time.\n this.contentPlayheadTracker.currentTime = 0;\n this.contentComplete = false;\n};\n\n/**\n * Copyright 2017 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/**\n * Ad UI implementation.\n *\n * @param {Controller} controller Plugin controller.\n * @constructor\n * @struct\n * @final\n */\nvar AdUi = function AdUi(controller) {\n /**\n * Plugin controller.\n */\n this.controller = controller;\n\n /**\n * Div used as an ad container.\n */\n this.adContainerDiv = document.createElement('div');\n\n /**\n * Div used to display ad controls.\n */\n this.controlsDiv = document.createElement('div');\n\n /**\n * Div used to display ad countdown timer.\n */\n this.countdownDiv = document.createElement('div');\n\n /**\n * Div used to display add seek bar.\n */\n this.seekBarDiv = document.createElement('div');\n\n /**\n * Div used to display ad progress (in seek bar).\n */\n this.progressDiv = document.createElement('div');\n\n /**\n * Div used to display ad play/pause button.\n */\n this.playPauseDiv = document.createElement('div');\n\n /**\n * Div used to display ad mute button.\n */\n this.muteDiv = document.createElement('div');\n\n /**\n * Div used by the volume slider.\n */\n this.sliderDiv = document.createElement('div');\n\n /**\n * Volume slider level visuals\n */\n this.sliderLevelDiv = document.createElement('div');\n\n /**\n * Div used to display ad fullscreen button.\n */\n this.fullscreenDiv = document.createElement('div');\n\n /**\n * Bound event handler for onMouseUp.\n */\n this.boundOnMouseUp = this.onMouseUp.bind(this);\n\n /**\n * Bound event handler for onMouseMove.\n */\n this.boundOnMouseMove = this.onMouseMove.bind(this);\n\n /**\n * Stores data for the ad playhead tracker.\n */\n this.adPlayheadTracker = {\n 'currentTime': 0,\n 'duration': 0,\n 'isPod': false,\n 'adPosition': 0,\n 'totalAds': 0\n };\n\n /**\n * Used to prefix videojs ima controls.\n */\n this.controlPrefix = this.controller.getPlayerId() + '_';\n\n /**\n * Boolean flag to show or hide the ad countdown timer.\n */\n this.showCountdown = true;\n if (this.controller.getSettings().showCountdown === false) {\n this.showCountdown = false;\n }\n\n /**\n * Boolean flag if the current ad is nonlinear.\n */\n this.isAdNonlinear = false;\n this.createAdContainer();\n};\n\n/**\n * Creates the ad container.\n */\nAdUi.prototype.createAdContainer = function () {\n this.assignControlAttributes(this.adContainerDiv, 'ima-ad-container');\n // Hide the ad container until an ad starts.\n this.adContainerDiv.classList.add('hide-ad-container');\n this.adContainerDiv.addEventListener('mouseenter', this.showAdControls.bind(this), false);\n this.adContainerDiv.addEventListener('mouseleave', this.hideAdControls.bind(this), false);\n this.adContainerDiv.addEventListener('click', this.onAdContainerClick.bind(this), false);\n this.createControls();\n this.controller.injectAdContainerDiv(this.adContainerDiv);\n};\n\n/**\n * Create the controls.\n */\nAdUi.prototype.createControls = function () {\n this.assignControlAttributes(this.controlsDiv, 'ima-controls-div');\n this.controlsDiv.style.width = '100%';\n if (!this.controller.getIsMobile()) {\n this.assignControlAttributes(this.countdownDiv, 'ima-countdown-div');\n this.countdownDiv.innerHTML = this.controller.getSettings().adLabel;\n this.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';\n } else {\n this.countdownDiv.style.display = 'none';\n }\n this.assignControlAttributes(this.seekBarDiv, 'ima-seek-bar-div');\n this.seekBarDiv.style.width = '100%';\n this.assignControlAttributes(this.progressDiv, 'ima-progress-div');\n this.assignControlAttributes(this.playPauseDiv, 'ima-play-pause-div');\n this.addClass(this.playPauseDiv, 'ima-playing');\n this.playPauseDiv.addEventListener('click', this.onAdPlayPauseClick.bind(this), false);\n this.assignControlAttributes(this.muteDiv, 'ima-mute-div');\n this.addClass(this.muteDiv, 'ima-non-muted');\n this.muteDiv.addEventListener('click', this.onAdMuteClick.bind(this), false);\n this.assignControlAttributes(this.sliderDiv, 'ima-slider-div');\n this.sliderDiv.addEventListener('mousedown', this.onAdVolumeSliderMouseDown.bind(this), false);\n\n // Hide volume slider controls on iOS as they aren't supported.\n if (this.controller.getIsIos()) {\n this.sliderDiv.style.display = 'none';\n }\n this.assignControlAttributes(this.sliderLevelDiv, 'ima-slider-level-div');\n this.assignControlAttributes(this.fullscreenDiv, 'ima-fullscreen-div');\n this.addClass(this.fullscreenDiv, 'ima-non-fullscreen');\n this.fullscreenDiv.addEventListener('click', this.onAdFullscreenClick.bind(this), false);\n this.adContainerDiv.appendChild(this.controlsDiv);\n this.controlsDiv.appendChild(this.countdownDiv);\n this.controlsDiv.appendChild(this.seekBarDiv);\n this.controlsDiv.appendChild(this.playPauseDiv);\n this.controlsDiv.appendChild(this.muteDiv);\n this.controlsDiv.appendChild(this.sliderDiv);\n this.controlsDiv.appendChild(this.fullscreenDiv);\n this.seekBarDiv.appendChild(this.progressDiv);\n this.sliderDiv.appendChild(this.sliderLevelDiv);\n};\n\n/**\n * Listener for clicks on the play/pause button during ad playback.\n */\nAdUi.prototype.onAdPlayPauseClick = function () {\n this.controller.onAdPlayPauseClick();\n};\n\n/**\n * Listener for clicks on the play/pause button during ad playback.\n */\nAdUi.prototype.onAdMuteClick = function () {\n this.controller.onAdMuteClick();\n};\n\n/**\n * Listener for clicks on the fullscreen button during ad playback.\n */\nAdUi.prototype.onAdFullscreenClick = function () {\n this.controller.toggleFullscreen();\n};\n\n/**\n * Show pause and hide play button\n */\nAdUi.prototype.onAdsPaused = function () {\n this.controller.sdkImpl.adPlaying = false;\n this.addClass(this.playPauseDiv, 'ima-paused');\n this.removeClass(this.playPauseDiv, 'ima-playing');\n this.showAdControls();\n};\n\n/**\n * Show pause and hide play button\n */\nAdUi.prototype.onAdsResumed = function () {\n this.onAdsPlaying();\n this.showAdControls();\n};\n\n/**\n * Show play and hide pause button\n */\nAdUi.prototype.onAdsPlaying = function () {\n this.controller.sdkImpl.adPlaying = true;\n this.addClass(this.playPauseDiv, 'ima-playing');\n this.removeClass(this.playPauseDiv, 'ima-paused');\n};\n\n/**\n * Takes data from the controller to update the UI.\n *\n * @param {number} currentTime Current time of the ad.\n * @param {number} remainingTime Remaining time of the ad.\n * @param {number} duration Duration of the ad.\n * @param {number} adPosition Index of the ad in the pod.\n * @param {number} totalAds Total number of ads in the pod.\n */\nAdUi.prototype.updateAdUi = function (currentTime, remainingTime, duration, adPosition, totalAds) {\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 (totalAds > 1) {\n podCount = ' (' + adPosition + ' ' + this.controller.getSettings().adLabelNofN + ' ' + totalAds + '): ';\n }\n this.countdownDiv.innerHTML = this.controller.getSettings().adLabel + podCount + remainingMinutes + ':' + remainingSeconds;\n\n // Update UI\n var playProgressRatio = currentTime / duration;\n var playProgressPercent = playProgressRatio * 100;\n this.progressDiv.style.width = playProgressPercent + '%';\n};\n\n/**\n * Handles UI changes when the ad is unmuted.\n */\nAdUi.prototype.unmute = function () {\n this.addClass(this.muteDiv, 'ima-non-muted');\n this.removeClass(this.muteDiv, 'ima-muted');\n this.sliderLevelDiv.style.width = this.controller.getPlayerVolume() * 100 + '%';\n};\n\n/**\n * Handles UI changes when the ad is muted.\n */\nAdUi.prototype.mute = function () {\n this.addClass(this.muteDiv, 'ima-muted');\n this.removeClass(this.muteDiv, 'ima-non-muted');\n this.sliderLevelDiv.style.width = '0%';\n};\n\n/*\n * Listener for mouse down events during ad playback. Used for volume.\n */\nAdUi.prototype.onAdVolumeSliderMouseDown = function () {\n document.addEventListener('mouseup', this.boundOnMouseUp, false);\n document.addEventListener('mousemove', this.boundOnMouseMove, false);\n};\n\n/*\n * Mouse movement listener used for volume slider.\n */\nAdUi.prototype.onMouseMove = function (event) {\n this.changeVolume(event);\n};\n\n/*\n * Mouse release listener used for volume slider.\n */\nAdUi.prototype.onMouseUp = function (event) {\n this.changeVolume(event);\n document.removeEventListener('mouseup', this.boundOnMouseUp);\n document.removeEventListener('mousemove', this.boundOnMouseMove);\n};\n\n/*\n * Utility function to set volume and associated UI\n */\nAdUi.prototype.changeVolume = function (event) {\n var percent = (event.clientX - this.sliderDiv.getBoundingClientRect().left) / this.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 this.sliderLevelDiv.style.width = percent + '%';\n if (this.percent == 0) {\n this.addClass(this.muteDiv, 'ima-muted');\n this.removeClass(this.muteDiv, 'ima-non-muted');\n } else {\n this.addClass(this.muteDiv, 'ima-non-muted');\n this.removeClass(this.muteDiv, 'ima-muted');\n }\n this.controller.setVolume(percent / 100); // 0-1\n};\n\n/**\n * Show the ad container.\n */\nAdUi.prototype.showAdContainer = function () {\n this.adContainerDiv.classList.remove('hide-ad-container');\n};\n\n/**\n * Hide the ad container.\n */\nAdUi.prototype.hideAdContainer = function () {\n this.adContainerDiv.classList.add('hide-ad-container');\n};\n\n/**\n * Handles clicks on the ad container.\n */\nAdUi.prototype.onAdContainerClick = function () {\n if (this.isAdNonlinear) {\n this.controller.togglePlayback();\n }\n};\n\n/**\n * Resets the state of the ad ui.\n */\nAdUi.prototype.reset = function () {\n this.hideAdContainer();\n};\n\n/**\n * Handles ad errors.\n */\nAdUi.prototype.onAdError = function () {\n this.hideAdContainer();\n};\n\n/**\n * Handles ad break starting.\n *\n * @param {Object} adEvent The event fired by the IMA SDK.\n */\nAdUi.prototype.onAdBreakStart = function (adEvent) {\n this.showAdContainer();\n var contentType = adEvent.getAd().getContentType();\n if (contentType === 'application/javascript' && !this.controller.getSettings().showControlsForJSAds) {\n this.controlsDiv.style.display = 'none';\n } else {\n this.controlsDiv.style.display = 'block';\n }\n this.onAdsPlaying();\n // Start with the ad controls minimized.\n this.hideAdControls();\n};\n\n/**\n * Handles ad break ending.\n */\nAdUi.prototype.onAdBreakEnd = function () {\n var currentAd = this.controller.getCurrentAd();\n if (currentAd == null ||\n // hide for post-roll only playlist\n currentAd.isLinear()) {\n // don't hide for non-linear ads\n this.hideAdContainer();\n }\n this.controlsDiv.style.display = 'none';\n this.countdownDiv.innerHTML = '';\n};\n\n/**\n * Handles when all ads have finished playing.\n */\nAdUi.prototype.onAllAdsCompleted = function () {\n this.hideAdContainer();\n};\n\n/**\n * Handles when a linear ad starts.\n */\nAdUi.prototype.onLinearAdStart = function () {\n // Don't bump container when controls are shown\n this.removeClass(this.adContainerDiv, 'bumpable-ima-ad-container');\n this.isAdNonlinear = false;\n};\n\n/**\n * Handles when a non-linear ad starts.\n */\nAdUi.prototype.onNonLinearAdLoad = function () {\n // Bump container when controls are shown\n this.addClass(this.adContainerDiv, 'bumpable-ima-ad-container');\n this.isAdNonlinear = true;\n};\nAdUi.prototype.onPlayerEnterFullscreen = function () {\n this.addClass(this.fullscreenDiv, 'ima-fullscreen');\n this.removeClass(this.fullscreenDiv, 'ima-non-fullscreen');\n};\nAdUi.prototype.onPlayerExitFullscreen = function () {\n this.addClass(this.fullscreenDiv, 'ima-non-fullscreen');\n this.removeClass(this.fullscreenDiv, 'ima-fullscreen');\n};\n\n/**\n * Called when the player volume changes.\n *\n * @param {number} volume The new player volume.\n */\nAdUi.prototype.onPlayerVolumeChanged = function (volume) {\n if (volume == 0) {\n this.addClass(this.muteDiv, 'ima-muted');\n this.removeClass(this.muteDiv, 'ima-non-muted');\n this.sliderLevelDiv.style.width = '0%';\n } else {\n this.addClass(this.muteDiv, 'ima-non-muted');\n this.removeClass(this.muteDiv, 'ima-muted');\n this.sliderLevelDiv.style.width = volume * 100 + '%';\n }\n};\n\n/**\n * Shows ad controls on mouseover.\n */\nAdUi.prototype.showAdControls = function () {\n var _this$controller$getS = this.controller.getSettings(),\n disableAdControls = _this$controller$getS.disableAdControls;\n if (!disableAdControls) {\n this.addClass(this.controlsDiv, 'ima-controls-div-showing');\n }\n};\n\n/**\n * Hide the ad controls.\n */\nAdUi.prototype.hideAdControls = function () {\n this.removeClass(this.controlsDiv, 'ima-controls-div-showing');\n};\n\n/**\n * Assigns the unique id and class names to the given element as well as the\n * style class.\n * @param {HTMLElement} element Element that needs the controlName assigned.\n * @param {string} controlName Control name to assign.\n */\nAdUi.prototype.assignControlAttributes = function (element, controlName) {\n element.id = this.controlPrefix + controlName;\n element.className = this.controlPrefix + controlName + ' ' + controlName;\n};\n\n/**\n * Returns a regular expression to test a string for the given className.\n *\n * @param {string} className The name of the class.\n * @return {RegExp} The regular expression used to test for that class.\n */\nAdUi.prototype.getClassRegexp = function (className) {\n // Matches on\n // (beginning of string OR NOT word char)\n // classname\n // (negative lookahead word char OR end of string)\n return new RegExp('(^|[^A-Za-z-])' + className + '((?![A-Za-z-])|$)', 'gi');\n};\n\n/**\n * Returns whether or not the provided element has the provied class in its\n * className.\n * @param {HTMLElement} element Element to tes.t\n * @param {string} className Class to look for.\n * @return {boolean} True if element has className in class list. False\n * otherwise.\n */\nAdUi.prototype.elementHasClass = function (element, className) {\n var classRegexp = this.getClassRegexp(className);\n return classRegexp.test(element.className);\n};\n\n/**\n * Adds a class to the given element if it doesn't already have the class\n * @param {HTMLElement} element Element to which the class will be added.\n * @param {string} classToAdd Class to add.\n */\nAdUi.prototype.addClass = function (element, classToAdd) {\n element.className = element.className.trim() + ' ' + classToAdd;\n};\n\n/**\n * Removes a class from the given element if it has the given class\n *\n * @param {HTMLElement} element Element from which the class will be removed.\n * @param {string} classToRemove Class to remove.\n */\nAdUi.prototype.removeClass = function (element, classToRemove) {\n var classRegexp = this.getClassRegexp(classToRemove);\n element.className = element.className.trim().replace(classRegexp, '');\n};\n\n/**\n * @return {HTMLElement} The div for the ad container.\n */\nAdUi.prototype.getAdContainerDiv = function () {\n return this.adContainerDiv;\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 */\nAdUi.prototype.setShowCountdown = function (showCountdownIn) {\n this.showCountdown = showCountdownIn;\n this.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';\n};\n\nvar version = \"2.5.0\";\nvar pkg = {\n\tversion: version};\n\n/**\n * Implementation of the IMA SDK for the plugin.\n *\n * @param {Object} controller Reference to the parent controller.\n *\n * @constructor\n * @struct\n * @final\n */\nvar SdkImpl$1 = function SdkImpl(controller) {\n /**\n * Plugin controller.\n */\n this.controller = controller;\n\n /**\n * IMA SDK AdDisplayContainer.\n */\n this.adDisplayContainer = null;\n\n /**\n * True if the AdDisplayContainer has been initialized. False otherwise.\n */\n this.adDisplayContainerInitialized = false;\n\n /**\n * IMA SDK AdsLoader\n */\n this.adsLoader = null;\n\n /**\n * IMA SDK AdsManager\n */\n this.adsManager = null;\n\n /**\n * IMA SDK AdsRenderingSettings.\n */\n this.adsRenderingSettings = null;\n\n /**\n * VAST, VMAP, or ad rules response. Used in lieu of fetching a response\n * from an ad tag URL.\n */\n this.adsResponse = null;\n\n /**\n * Current IMA SDK Ad.\n */\n this.currentAd = null;\n\n /**\n * Timer used to track ad progress.\n */\n this.adTrackingTimer = null;\n\n /**\n * True if ALL_ADS_COMPLETED has fired, false until then.\n */\n this.allAdsCompleted = false;\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 this.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 this.adPlaying = false;\n\n /**\n * True if the ad is muted, false otherwise.\n */\n this.adMuted = false;\n\n /**\n * Listener to be called to trigger manual ad break playback.\n */\n this.adBreakReadyListener = undefined;\n\n /**\n * Tracks whether or not we have already called adsLoader.contentComplete().\n */\n this.contentCompleteCalled = false;\n\n /**\n * True if the ad has timed out.\n */\n this.isAdTimedOut = false;\n\n /**\n * Stores the dimensions for the ads manager.\n */\n this.adsManagerDimensions = {\n width: 0,\n height: 0\n };\n\n /**\n * Boolean flag to enable manual ad break playback.\n */\n this.autoPlayAdBreaks = true;\n if (this.controller.getSettings().autoPlayAdBreaks === false) {\n this.autoPlayAdBreaks = false;\n }\n\n // Set SDK settings from plugin settings.\n if (this.controller.getSettings().locale) {\n /* eslint no-undef: 'error' */\n /* global google */\n google.ima.settings.setLocale(this.controller.getSettings().locale);\n }\n if (this.controller.getSettings().disableFlashAds) {\n google.ima.settings.setDisableFlashAds(this.controller.getSettings().disableFlashAds);\n }\n if (this.controller.getSettings().disableCustomPlaybackForIOS10Plus) {\n google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.controller.getSettings().disableCustomPlaybackForIOS10Plus);\n }\n if (this.controller.getSettings().ppid) {\n google.ima.settings.setPpid(this.controller.getSettings().ppid);\n }\n if (this.controller.getSettings().featureFlags) {\n google.ima.settings.setFeatureFlags(this.controller.getSettings().featureFlags);\n }\n};\n\n/**\n * Creates and initializes the IMA SDK objects.\n */\nSdkImpl$1.prototype.initAdObjects = function () {\n this.adDisplayContainer = new google.ima.AdDisplayContainer(this.controller.getAdContainerDiv(), this.controller.getContentPlayer());\n this.adsLoader = new google.ima.AdsLoader(this.adDisplayContainer);\n this.adsLoader.getSettings().setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n if (this.controller.getSettings().vpaidAllowed == false) {\n this.adsLoader.getSettings().setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.DISABLED);\n }\n if (this.controller.getSettings().vpaidMode !== undefined) {\n this.adsLoader.getSettings().setVpaidMode(this.controller.getSettings().vpaidMode);\n }\n if (this.controller.getSettings().locale) {\n this.adsLoader.getSettings().setLocale(this.controller.getSettings().locale);\n }\n if (this.controller.getSettings().numRedirects) {\n this.adsLoader.getSettings().setNumRedirects(this.controller.getSettings().numRedirects);\n }\n if (this.controller.getSettings().sessionId) {\n this.adsLoader.getSettings().setSessionId(this.controller.getSettings().sessionId);\n }\n this.adsLoader.getSettings().setPlayerType('videojs-ima');\n this.adsLoader.getSettings().setPlayerVersion(pkg.version);\n this.adsLoader.getSettings().setAutoPlayAdBreaks(this.autoPlayAdBreaks);\n this.adsLoader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, this.onAdsManagerLoaded.bind(this), false);\n this.adsLoader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, this.onAdsLoaderError.bind(this), false);\n this.controller.playerWrapper.vjsPlayer.trigger({\n type: 'ads-loader',\n adsLoader: this.adsLoader\n });\n};\n\n/**\n * Creates the AdsRequest and request ads through the AdsLoader.\n */\nSdkImpl$1.prototype.requestAds = function () {\n var adsRequest = new google.ima.AdsRequest();\n if (this.controller.getSettings().adTagUrl) {\n adsRequest.adTagUrl = this.controller.getSettings().adTagUrl;\n } else {\n adsRequest.adsResponse = this.controller.getSettings().adsResponse;\n }\n if (this.controller.getSettings().forceNonLinearFullSlot) {\n adsRequest.forceNonLinearFullSlot = true;\n }\n if (this.controller.getSettings().vastLoadTimeout) {\n adsRequest.vastLoadTimeout = this.controller.getSettings().vastLoadTimeout;\n }\n if (this.controller.getSettings().omidMode) {\n window.console.warn('The additional setting `omidMode` has been removed. ' + 'Use `omidVendorAccess` instead.');\n }\n if (this.controller.getSettings().omidVendorAccess) {\n adsRequest.omidAccessModeRules = {};\n var omidVendorValues = this.controller.getSettings().omidVendorAccess;\n Object.keys(omidVendorValues).forEach(function (vendorKey) {\n adsRequest.omidAccessModeRules[vendorKey] = omidVendorValues[vendorKey];\n });\n }\n adsRequest.linearAdSlotWidth = this.controller.getPlayerWidth();\n adsRequest.linearAdSlotHeight = this.controller.getPlayerHeight();\n adsRequest.nonLinearAdSlotWidth = this.controller.getSettings().nonLinearWidth || this.controller.getPlayerWidth();\n adsRequest.nonLinearAdSlotHeight = this.controller.getSettings().nonLinearHeight || this.controller.getPlayerHeight();\n adsRequest.setAdWillAutoPlay(this.controller.adsWillAutoplay());\n adsRequest.setAdWillPlayMuted(this.controller.adsWillPlayMuted());\n\n // Populate the adsRequestproperties with those provided in the AdsRequest\n // object in the settings.\n var providedAdsRequest = this.controller.getSettings().adsRequest;\n if (providedAdsRequest && _typeof(providedAdsRequest) === 'object') {\n Object.keys(providedAdsRequest).forEach(function (key) {\n adsRequest[key] = providedAdsRequest[key];\n });\n }\n this.adsLoader.requestAds(adsRequest);\n this.controller.playerWrapper.vjsPlayer.trigger({\n type: 'ads-request',\n AdsRequest: adsRequest\n });\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 *\n * @param {google.ima.AdsManagerLoadedEvent} adsManagerLoadedEvent Fired when\n * the AdsManager loads.\n */\nSdkImpl$1.prototype.onAdsManagerLoaded = function (adsManagerLoadedEvent) {\n this.createAdsRenderingSettings();\n this.adsManager = adsManagerLoadedEvent.getAdsManager(this.controller.getContentPlayheadTracker(), this.adsRenderingSettings);\n this.adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, this.onAdError.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.AD_BREAK_READY, this.onAdBreakReady.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, this.onContentPauseRequested.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, this.onContentResumeRequested.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.ALL_ADS_COMPLETED, this.onAllAdsCompleted.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, this.onAdLoaded.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, this.onAdStarted.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, this.onAdComplete.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.SKIPPED, this.onAdComplete.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.LOG, this.onAdLog.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.PAUSED, this.onAdPaused.bind(this));\n this.adsManager.addEventListener(google.ima.AdEvent.Type.RESUMED, this.onAdResumed.bind(this));\n this.controller.playerWrapper.vjsPlayer.trigger({\n type: 'ads-manager',\n adsManager: this.adsManager\n });\n if (!this.autoPlayAdBreaks) {\n this.initAdsManager();\n }\n var _this$controller$getS = this.controller.getSettings(),\n preventLateAdStart = _this$controller$getS.preventLateAdStart;\n if (!preventLateAdStart) {\n this.controller.onAdsReady();\n } else if (preventLateAdStart && !this.isAdTimedOut) {\n this.controller.onAdsReady();\n }\n if (this.controller.getSettings().adsManagerLoadedCallback) {\n this.controller.getSettings().adsManagerLoadedCallback();\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/client-side/reference/js/google.ima.AdError#.Type\n */\nSdkImpl$1.prototype.onAdsLoaderError = function (event) {\n window.console.warn('AdsLoader error: ' + event.getError());\n this.controller.onErrorLoadingAds(event);\n if (this.adsManager) {\n this.adsManager.destroy();\n }\n};\n\n/**\n * Initialize the ads manager.\n */\nSdkImpl$1.prototype.initAdsManager = function () {\n try {\n var initWidth = this.controller.getPlayerWidth();\n var initHeight = this.controller.getPlayerHeight();\n this.adsManagerDimensions.width = initWidth;\n this.adsManagerDimensions.height = initHeight;\n this.adsManager.init(initWidth, initHeight);\n this.adsManager.setVolume(this.controller.getPlayerVolume());\n this.initializeAdDisplayContainer();\n } catch (adError) {\n this.onAdError(adError);\n }\n};\n\n/**\n * Create AdsRenderingSettings for the IMA SDK.\n */\nSdkImpl$1.prototype.createAdsRenderingSettings = function () {\n this.adsRenderingSettings = new google.ima.AdsRenderingSettings();\n this.adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n if (this.controller.getSettings().adsRenderingSettings) {\n for (var setting in this.controller.getSettings().adsRenderingSettings) {\n if (setting !== '') {\n this.adsRenderingSettings[setting] = this.controller.getSettings().adsRenderingSettings[setting];\n }\n }\n }\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 */\nSdkImpl$1.prototype.onAdError = function (adErrorEvent) {\n var errorMessage = adErrorEvent.getError !== undefined ? adErrorEvent.getError() : adErrorEvent.stack;\n window.console.warn('Ad error: ' + errorMessage);\n this.adsManager.destroy();\n this.controller.onAdError(adErrorEvent);\n\n // reset these so consumers don't think we are still in an ad break,\n // but reset them after any prior cleanup happens\n this.adsActive = false;\n this.adPlaying = false;\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 */\nSdkImpl$1.prototype.onAdBreakReady = function (adEvent) {\n this.adBreakReadyListener(adEvent);\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 */\nSdkImpl$1.prototype.onContentPauseRequested = function (adEvent) {\n this.adsActive = true;\n this.adPlaying = true;\n this.controller.onAdBreakStart(adEvent);\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 */\nSdkImpl$1.prototype.onContentResumeRequested = function (adEvent) {\n this.adsActive = false;\n this.adPlaying = false;\n this.controller.onAdBreakEnd();\n // Hide controls in case of future non-linear ads. They'll be unhidden in\n // content_pause_requested.\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 */\nSdkImpl$1.prototype.onAllAdsCompleted = function (adEvent) {\n this.allAdsCompleted = true;\n this.controller.onAllAdsCompleted();\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 */\nSdkImpl$1.prototype.onAdLoaded = function (adEvent) {\n if (!adEvent.getAd().isLinear()) {\n this.controller.onNonLinearAdLoad();\n this.controller.playContent();\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 */\nSdkImpl$1.prototype.onAdStarted = function (adEvent) {\n this.currentAd = adEvent.getAd();\n if (this.currentAd.isLinear()) {\n this.adTrackingTimer = setInterval(this.onAdPlayheadTrackerInterval.bind(this), 250);\n this.controller.onLinearAdStart();\n } else {\n this.controller.onNonLinearAdStart();\n }\n};\n\n/**\n * Handles an ad click. Puts the player UI in a paused state.\n */\nSdkImpl$1.prototype.onAdPaused = function () {\n this.controller.onAdsPaused();\n};\n\n/**\n * Syncs controls when an ad resumes.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.\n */\nSdkImpl$1.prototype.onAdResumed = function (adEvent) {\n this.controller.onAdsResumed();\n};\n\n/**\n * Clears the interval timer for current ad time when an ad completes.\n */\nSdkImpl$1.prototype.onAdComplete = function () {\n if (this.currentAd.isLinear()) {\n clearInterval(this.adTrackingTimer);\n }\n};\n\n/**\n * Handles ad log messages.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.\n */\nSdkImpl$1.prototype.onAdLog = function (adEvent) {\n this.controller.onAdLog(adEvent);\n};\n\n/**\n * Gets the current time and duration of the ad and calls the method to\n * update the ad UI.\n */\nSdkImpl$1.prototype.onAdPlayheadTrackerInterval = function () {\n if (this.adsManager === null) return;\n var remainingTime = this.adsManager.getRemainingTime();\n var duration = this.currentAd.getDuration();\n var currentTime = duration - remainingTime;\n currentTime = currentTime > 0 ? currentTime : 0;\n var totalAds = 0;\n var adPosition;\n if (this.currentAd.getAdPodInfo()) {\n adPosition = this.currentAd.getAdPodInfo().getAdPosition();\n totalAds = this.currentAd.getAdPodInfo().getTotalAds();\n }\n this.controller.onAdPlayheadUpdated(currentTime, remainingTime, duration, adPosition, totalAds);\n};\n\n/**\n * Called by the player wrapper when content completes.\n */\nSdkImpl$1.prototype.onContentComplete = function () {\n if (this.adsLoader) {\n this.adsLoader.contentComplete();\n this.contentCompleteCalled = true;\n }\n if (this.adsManager && this.adsManager.getCuePoints() && !this.adsManager.getCuePoints().includes(-1) || !this.adsManager) {\n this.controller.onNoPostroll();\n }\n if (this.allAdsCompleted) {\n this.controller.onContentAndAdsCompleted();\n }\n};\n\n/**\n * Called when the player is disposed.\n */\nSdkImpl$1.prototype.onPlayerDisposed = function () {\n if (this.adTrackingTimer) {\n clearInterval(this.adTrackingTimer);\n }\n if (this.adsManager) {\n this.adsManager.destroy();\n this.adsManager = null;\n }\n};\nSdkImpl$1.prototype.onPlayerReadyForPreroll = function () {\n if (this.autoPlayAdBreaks) {\n this.initAdsManager();\n try {\n this.controller.showAdContainer();\n // Sync ad volume with content volume.\n this.adsManager.setVolume(this.controller.getPlayerVolume());\n this.adsManager.start();\n } catch (adError) {\n this.onAdError(adError);\n }\n }\n};\nSdkImpl$1.prototype.onAdTimeout = function () {\n this.isAdTimedOut = true;\n};\nSdkImpl$1.prototype.onPlayerReady = function () {\n this.initAdObjects();\n if ((this.controller.getSettings().adTagUrl || this.controller.getSettings().adsResponse) && this.controller.getSettings().requestMode === 'onLoad') {\n this.requestAds();\n }\n};\nSdkImpl$1.prototype.onPlayerEnterFullscreen = function () {\n if (this.adsManager) {\n this.adsManager.resize(window.screen.width, window.screen.height);\n }\n};\nSdkImpl$1.prototype.onPlayerExitFullscreen = function () {\n if (this.adsManager) {\n this.adsManager.resize(this.controller.getPlayerWidth(), this.controller.getPlayerHeight());\n }\n};\n\n/**\n * Called when the player volume changes.\n *\n * @param {number} volume The new player volume.\n */\nSdkImpl$1.prototype.onPlayerVolumeChanged = function (volume) {\n if (this.adsManager) {\n this.adsManager.setVolume(volume);\n }\n if (volume == 0) {\n this.adMuted = true;\n } else {\n this.adMuted = false;\n }\n};\n\n/**\n * Called when the player wrapper detects that the player has been resized.\n *\n * @param {number} width The post-resize width of the player.\n * @param {number} height The post-resize height of the player.\n */\nSdkImpl$1.prototype.onPlayerResize = function (width, height) {\n if (this.adsManager) {\n this.adsManagerDimensions.width = width;\n this.adsManagerDimensions.height = height;\n /* eslint no-undef: 'error' */\n this.adsManager.resize(width, height);\n }\n};\n\n/**\n * @return {Object} The current ad.\n */\nSdkImpl$1.prototype.getCurrentAd = function () {\n return this.currentAd;\n};\n\n/**\n * Listener JSDoc for ESLint. This listener can be passed to\n * setAdBreakReadyListener.\n * @callback listener\n */\n\n/**\n * Sets the listener to be called to trigger manual ad break playback.\n * @param {listener} listener The listener to be called to trigger manual ad\n * break playback.\n */\nSdkImpl$1.prototype.setAdBreakReadyListener = function (listener) {\n this.adBreakReadyListener = listener;\n};\n\n/**\n * @return {boolean} True if an ad is currently playing. False otherwise.\n */\nSdkImpl$1.prototype.isAdPlaying = function () {\n return this.adPlaying;\n};\n\n/**\n * @return {boolean} True if an ad is currently playing. False otherwise.\n */\nSdkImpl$1.prototype.isAdMuted = function () {\n return this.adMuted;\n};\n\n/**\n * Pause ads.\n */\nSdkImpl$1.prototype.pauseAds = function () {\n this.adsManager.pause();\n this.adPlaying = false;\n};\n\n/**\n * Resume ads.\n */\nSdkImpl$1.prototype.resumeAds = function () {\n this.adsManager.resume();\n this.adPlaying = true;\n};\n\n/**\n * Unmute ads.\n */\nSdkImpl$1.prototype.unmute = function () {\n this.adsManager.setVolume(1);\n this.adMuted = false;\n};\n\n/**\n * Mute ads.\n */\nSdkImpl$1.prototype.mute = function () {\n this.adsManager.setVolume(0);\n this.adMuted = true;\n};\n\n/**\n * Set the volume of the ads. 0-1.\n *\n * @param {number} volume The new volume.\n */\nSdkImpl$1.prototype.setVolume = function (volume) {\n this.adsManager.setVolume(volume);\n if (volume == 0) {\n this.adMuted = true;\n } else {\n this.adMuted = false;\n }\n};\n\n/**\n * Initializes the AdDisplayContainer. On mobile, this must be done as a\n * result of user action.\n */\nSdkImpl$1.prototype.initializeAdDisplayContainer = function () {\n if (this.adDisplayContainer) {\n if (!this.adDisplayContainerInitialized) {\n this.adDisplayContainer.initialize();\n this.adDisplayContainerInitialized = true;\n }\n }\n};\n\n/**\n * Called by publishers in manual ad break playback mode to start an ad\n * break.\n */\nSdkImpl$1.prototype.playAdBreak = function () {\n if (!this.autoPlayAdBreaks) {\n this.controller.showAdContainer();\n // Sync ad volume with content volume.\n this.adsManager.setVolume(this.controller.getPlayerVolume());\n this.adsManager.start();\n }\n};\n\n/**\n * Callback JSDoc for ESLint. This callback can be passed to addEventListener.\n * @callback callback\n */\n\n/**\n * Adds an EventListener to the AdsManager. For a list of available events,\n * see\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.AdEvent#.Type\n * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to\n * listen.\n * @param {callback} callback The method to call when the event is fired.\n */\nSdkImpl$1.prototype.addEventListener = function (event, callback) {\n if (this.adsManager) {\n this.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 */\nSdkImpl$1.prototype.getAdsManager = function () {\n return this.adsManager;\n};\n\n/**\n * Reset the SDK implementation.\n */\nSdkImpl$1.prototype.reset = function () {\n this.adsActive = false;\n this.adPlaying = false;\n if (this.adTrackingTimer) {\n // If this is called while an ad is playing, stop trying to get that\n // ad's current time.\n clearInterval(this.adTrackingTimer);\n }\n if (this.adsManager) {\n this.adsManager.destroy();\n this.adsManager = null;\n }\n if (this.adsLoader && !this.contentCompleteCalled) {\n this.adsLoader.contentComplete();\n }\n this.contentCompleteCalled = false;\n this.allAdsCompleted = false;\n};\n\n/**\n * Copyright 2017 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/**\n * The grand coordinator of the plugin. Facilitates communication between all\n * other plugin classes.\n *\n * @param {Object} player Instance of the video.js player.\n * @param {Object} options Options provided by the implementation.\n * @constructor\n * @struct\n * @final\n */\nvar Controller = function Controller(player, options) {\n /**\n * Stores user-provided settings.\n * @type {Object}\n */\n this.settings = {};\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 this.contentAndAdsEndedListeners = [];\n\n /**\n * Whether or not we are running on a mobile platform.\n */\n this.isMobile = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/Android/i);\n\n /**\n * Whether or not we are running on an iOS platform.\n */\n this.isIos = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i);\n this.initWithSettings(options);\n\n /**\n * Stores contrib-ads default settings.\n */\n var contribAdsDefaults = {\n debug: this.settings.debug,\n timeout: this.settings.timeout,\n prerollTimeout: this.settings.prerollTimeout\n };\n var adsPluginSettings = Object.assign({}, contribAdsDefaults, options.contribAdsSettings || {});\n this.playerWrapper = new PlayerWrapper$1(player, adsPluginSettings, this);\n this.adUi = new AdUi(this);\n this.sdkImpl = new SdkImpl$1(this);\n};\nController.IMA_DEFAULTS = {\n adLabel: 'Advertisement',\n adLabelNofN: 'of',\n debug: false,\n disableAdControls: false,\n prerollTimeout: 1000,\n preventLateAdStart: false,\n requestMode: 'onLoad',\n showControlsForJSAds: true,\n timeout: 5000\n};\n\n/**\n * Extends the settings to include user-provided settings.\n *\n * @param {Object} options Options to be used in initialization.\n */\nController.prototype.initWithSettings = function (options) {\n this.settings = Object.assign({}, Controller.IMA_DEFAULTS, options || {});\n this.warnAboutDeprecatedSettings();\n\n // Default showing countdown timer to true.\n this.showCountdown = true;\n if (this.settings.showCountdown === false) {\n this.showCountdown = false;\n }\n};\n\n/**\n * Logs console warnings when deprecated settings are used.\n */\nController.prototype.warnAboutDeprecatedSettings = function () {\n var _this = this;\n var deprecatedSettings = ['adWillAutoplay', 'adsWillAutoplay', 'adWillPlayMuted', 'adsWillPlayMuted'];\n deprecatedSettings.forEach(function (setting) {\n if (_this.settings[setting] !== undefined) {\n console.warn('WARNING: videojs.ima setting ' + setting + ' is deprecated');\n }\n });\n};\n\n/**\n * Return the settings object.\n *\n * @return {Object} The settings object.\n */\nController.prototype.getSettings = function () {\n return this.settings;\n};\n\n/**\n * Return whether or not we're in a mobile environment.\n *\n * @return {boolean} True if running on mobile, false otherwise.\n */\nController.prototype.getIsMobile = function () {\n return this.isMobile;\n};\n\n/**\n * Return whether or not we're in an iOS environment.\n *\n * @return {boolean} True if running on iOS, false otherwise.\n */\nController.prototype.getIsIos = function () {\n return this.isIos;\n};\n\n/**\n * Inject the ad container div into the DOM.\n *\n * @param{HTMLElement} adContainerDiv The ad container div.\n */\nController.prototype.injectAdContainerDiv = function (adContainerDiv) {\n this.playerWrapper.injectAdContainerDiv(adContainerDiv);\n};\n\n/**\n * @return {HTMLElement} The div for the ad container.\n */\nController.prototype.getAdContainerDiv = function () {\n return this.adUi.getAdContainerDiv();\n};\n\n/**\n * @return {Object} The content player.\n */\nController.prototype.getContentPlayer = function () {\n return this.playerWrapper.getContentPlayer();\n};\n\n/**\n * Returns the content playhead tracker.\n *\n * @return {Object} The content playhead tracker.\n */\nController.prototype.getContentPlayheadTracker = function () {\n return this.playerWrapper.getContentPlayheadTracker();\n};\n\n/**\n * Requests ads.\n */\nController.prototype.requestAds = function () {\n this.sdkImpl.requestAds();\n};\n\n/**\n * Add or modify a setting.\n *\n * @param {string} key Key to modify\n * @param {Object} value Value to set at key.\n */\nController.prototype.setSetting = function (key, value) {\n this.settings[key] = value;\n};\n\n/**\n * Called when there is an error loading ads.\n *\n * @param {Object} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nController.prototype.onErrorLoadingAds = function (adErrorEvent) {\n this.adUi.onAdError();\n this.playerWrapper.onAdError(adErrorEvent);\n};\n\n/**\n * Called by the ad UI when the play/pause button is clicked.\n */\nController.prototype.onAdPlayPauseClick = function () {\n if (this.sdkImpl.isAdPlaying()) {\n this.adUi.onAdsPaused();\n this.sdkImpl.pauseAds();\n } else {\n this.adUi.onAdsPlaying();\n this.sdkImpl.resumeAds();\n }\n};\n\n/**\n * Called by the ad UI when the mute button is clicked.\n *\n */\nController.prototype.onAdMuteClick = function () {\n if (this.sdkImpl.isAdMuted()) {\n this.playerWrapper.unmute();\n this.adUi.unmute();\n this.sdkImpl.unmute();\n } else {\n this.playerWrapper.mute();\n this.adUi.mute();\n this.sdkImpl.mute();\n }\n};\n\n/**\n * Set the volume of the player and ads. 0-1.\n *\n * @param {number} volume The new volume.\n */\nController.prototype.setVolume = function (volume) {\n this.playerWrapper.setVolume(volume);\n this.sdkImpl.setVolume(volume);\n};\n\n/**\n * @return {number} The volume of the content player.\n */\nController.prototype.getPlayerVolume = function () {\n return this.playerWrapper.getVolume();\n};\n\n/**\n * Toggle fullscreen state.\n */\nController.prototype.toggleFullscreen = function () {\n this.playerWrapper.toggleFullscreen();\n};\n\n/**\n * Relays ad errors to the player wrapper.\n *\n * @param {Object} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nController.prototype.onAdError = function (adErrorEvent) {\n this.adUi.onAdError();\n this.playerWrapper.onAdError(adErrorEvent);\n};\n\n/**\n * Handles ad break starting.\n *\n * @param {Object} adEvent The event fired by the IMA SDK.\n */\nController.prototype.onAdBreakStart = function (adEvent) {\n this.playerWrapper.onAdBreakStart();\n this.adUi.onAdBreakStart(adEvent);\n};\n\n/**\n * Show the ad container.\n */\nController.prototype.showAdContainer = function () {\n this.adUi.showAdContainer();\n};\n\n/**\n * Handles ad break ending.\n */\nController.prototype.onAdBreakEnd = function () {\n this.playerWrapper.onAdBreakEnd();\n this.adUi.onAdBreakEnd();\n};\n\n/**\n * Handles when all ads have finished playing.\n */\nController.prototype.onAllAdsCompleted = function () {\n this.adUi.onAllAdsCompleted();\n this.playerWrapper.onAllAdsCompleted();\n};\n\n/**\n * Handles the SDK firing an ad paused event.\n */\nController.prototype.onAdsPaused = function () {\n this.adUi.onAdsPaused();\n};\n\n/**\n * Handles the SDK firing an ad resumed event.\n */\nController.prototype.onAdsResumed = function () {\n this.adUi.onAdsResumed();\n};\n\n/**\n * Takes data from the sdk impl and passes it to the ad UI to update the UI.\n *\n * @param {number} currentTime Current time of the ad.\n * @param {number} remainingTime Remaining time of the ad.\n * @param {number} duration Duration of the ad.\n * @param {number} adPosition Index of the ad in the pod.\n * @param {number} totalAds Total number of ads in the pod.\n */\nController.prototype.onAdPlayheadUpdated = function (currentTime, remainingTime, duration, adPosition, totalAds) {\n this.adUi.updateAdUi(currentTime, remainingTime, duration, adPosition, totalAds);\n};\n\n/**\n * Handles ad log messages.\n * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the IMA SDK.\n */\nController.prototype.onAdLog = function (adEvent) {\n this.playerWrapper.onAdLog(adEvent);\n};\n\n/**\n * @return {Object} The current ad.\n */\nController.prototype.getCurrentAd = function () {\n return this.sdkImpl.getCurrentAd();\n};\n\n/**\n * Play content.\n */\nController.prototype.playContent = function () {\n this.playerWrapper.play();\n};\n\n/**\n * Handles when a linear ad starts.\n */\nController.prototype.onLinearAdStart = function () {\n this.adUi.onLinearAdStart();\n this.playerWrapper.onAdStart();\n};\n\n/**\n * Handles when a non-linear ad loads.\n */\nController.prototype.onNonLinearAdLoad = function () {\n this.adUi.onNonLinearAdLoad();\n};\n\n/**\n * Handles when a non-linear ad starts.\n */\nController.prototype.onNonLinearAdStart = function () {\n this.adUi.onNonLinearAdLoad();\n this.playerWrapper.onAdStart();\n};\n\n/**\n * Get the player width.\n *\n * @return {number} The width of the player.\n */\nController.prototype.getPlayerWidth = function () {\n return this.playerWrapper.getPlayerWidth();\n};\n\n/**\n * Get the player height.\n *\n * @return {number} The height of the player.\n */\nController.prototype.getPlayerHeight = function () {\n return this.playerWrapper.getPlayerHeight();\n};\n\n/**\n * Tells the player wrapper that ads are ready.\n */\nController.prototype.onAdsReady = function () {\n this.playerWrapper.onAdsReady();\n};\n\n/**\n * Called when the player wrapper detects that the player has been resized.\n *\n * @param {number} width The post-resize width of the player.\n * @param {number} height The post-resize height of the player.\n */\nController.prototype.onPlayerResize = function (width, height) {\n this.sdkImpl.onPlayerResize(width, height);\n};\n\n/**\n * Called by the player wrapper when content completes.\n */\nController.prototype.onContentComplete = function () {\n this.sdkImpl.onContentComplete();\n};\n\n/**\n * Called by the player wrapper when it's time to play a post-roll but we don't\n * have one to play.\n */\nController.prototype.onNoPostroll = function () {\n this.playerWrapper.onNoPostroll();\n};\n\n/**\n * Called when content and all ads have completed.\n */\nController.prototype.onContentAndAdsCompleted = function () {\n for (var index in this.contentAndAdsEndedListeners) {\n if (typeof this.contentAndAdsEndedListeners[index] === 'function') {\n this.contentAndAdsEndedListeners[index]();\n }\n }\n};\n\n/**\n * Called when the player is disposed.\n */\nController.prototype.onPlayerDisposed = function () {\n this.contentAndAdsEndedListeners = [];\n this.sdkImpl.onPlayerDisposed();\n};\n\n/**\n * Called when the player is ready to play a pre-roll.\n */\nController.prototype.onPlayerReadyForPreroll = function () {\n this.sdkImpl.onPlayerReadyForPreroll();\n};\n\n/**\n * Called if the ad times out.\n */\nController.prototype.onAdTimeout = function () {\n this.sdkImpl.onAdTimeout();\n};\n\n/**\n * Called when the player is ready.\n */\nController.prototype.onPlayerReady = function () {\n this.sdkImpl.onPlayerReady();\n};\n\n/**\n * Called when the player enters fullscreen.\n */\nController.prototype.onPlayerEnterFullscreen = function () {\n this.adUi.onPlayerEnterFullscreen();\n this.sdkImpl.onPlayerEnterFullscreen();\n};\n\n/**\n * Called when the player exits fullscreen.\n */\nController.prototype.onPlayerExitFullscreen = function () {\n this.adUi.onPlayerExitFullscreen();\n this.sdkImpl.onPlayerExitFullscreen();\n};\n\n/**\n * Called when the player volume changes.\n *\n * @param {number} volume The new player volume.\n */\nController.prototype.onPlayerVolumeChanged = function (volume) {\n this.adUi.onPlayerVolumeChanged(volume);\n this.sdkImpl.onPlayerVolumeChanged(volume);\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 */\nController.prototype.setContentWithAdTag = function (contentSrc, adTag) {\n this.reset();\n this.settings.adTagUrl = adTag ? adTag : this.settings.adTagUrl;\n this.playerWrapper.changeSource(contentSrc);\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 ads response is\n * used 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} adsResponse The ads response to be requested when the\n * content loads. Leave blank to use the existing ads response.\n */\nController.prototype.setContentWithAdsResponse = function (contentSrc, adsResponse) {\n this.reset();\n this.settings.adsResponse = adsResponse ? adsResponse : this.settings.adsResponse;\n this.playerWrapper.changeSource(contentSrc);\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 ads request is\n * used 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 {?Object} adsRequest The ads request to be requested when the\n * content loads. Leave blank to use the existing ads request.\n */\nController.prototype.setContentWithAdsRequest = function (contentSrc, adsRequest) {\n this.reset();\n this.settings.adsRequest = adsRequest ? adsRequest : this.settings.adsRequest;\n this.playerWrapper.changeSource(contentSrc);\n};\n\n/**\n * Resets the state of the plugin.\n */\nController.prototype.reset = function () {\n this.sdkImpl.reset();\n this.playerWrapper.reset();\n this.adUi.reset();\n};\n\n/**\n * Listener JSDoc for ESLint. This listener can be passed to\n * (add|remove)ContentEndedListener.\n * @callback listener\n */\n\n/**\n * Adds a listener for the 'readyforpostroll' event of the video player. This\n * should be used instead of setting an 'readyforpostroll' listener directly to\n * ensure that the ima can do proper cleanup of the SDK before other event\n * listeners are called.\n * @param {listener} listener The listener to be called when content\n * completes.\n */\nController.prototype.addContentEndedListener = function (listener) {\n this.playerWrapper.addContentEndedListener(listener);\n};\n\n/**\n * Adds a listener that will be called when content and all ads have\n * finished playing.\n * @param {listener} listener The listener to be called when content and ads\n * complete.\n */\nController.prototype.addContentAndAdsEndedListener = function (listener) {\n this.contentAndAdsEndedListeners.push(listener);\n};\n\n/**\n * Sets the listener to be called to trigger manual ad break playback.\n * @param {listener} listener The listener to be called to trigger manual ad\n * break playback.\n */\nController.prototype.setAdBreakReadyListener = function (listener) {\n this.sdkImpl.setAdBreakReadyListener(listener);\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 */\nController.prototype.setShowCountdown = function (showCountdownIn) {\n this.adUi.setShowCountdown(showCountdownIn);\n this.showCountdown = showCountdownIn;\n this.adUi.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';\n};\n\n/**\n * Initializes the AdDisplayContainer. On mobile, this must be done as a\n * result of user action.\n */\nController.prototype.initializeAdDisplayContainer = function () {\n this.sdkImpl.initializeAdDisplayContainer();\n};\n\n/**\n * Called by publishers in manual ad break playback mode to start an ad\n * break.\n */\nController.prototype.playAdBreak = function () {\n this.sdkImpl.playAdBreak();\n};\n\n/**\n * Callback JSDoc for ESLint. This callback can be passed to addEventListener.\n * @callback callback\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/client-side/reference/js/google.ima.AdEvent#.Type\n * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to\n * listen.\n * @param {callback} callback The method to call when the event is fired.\n */\nController.prototype.addEventListener = function (event, callback) {\n this.sdkImpl.addEventListener(event, callback);\n};\n\n/**\n * Returns the instance of the AdsManager.\n * @return {google.ima.AdsManager} The AdsManager being used by the plugin.\n */\nController.prototype.getAdsManager = function () {\n return this.sdkImpl.getAdsManager();\n};\n\n/**\n * Returns the instance of the player id.\n * @return {string} The player id.\n */\nController.prototype.getPlayerId = function () {\n return this.playerWrapper.getPlayerId();\n};\n\n/**\n * Changes the ad tag. You will need to call requestAds after this method\n * for the new ads to be requested.\n * @param {?string} adTag The ad tag to be requested the next time\n * requestAds is called.\n */\nController.prototype.changeAdTag = function (adTag) {\n this.reset();\n this.settings.adTagUrl = adTag;\n};\n\n/**\n * Pauses the ad.\n */\nController.prototype.pauseAd = function () {\n this.adUi.onAdsPaused();\n this.sdkImpl.pauseAds();\n};\n\n/**\n * Resumes the ad.\n */\nController.prototype.resumeAd = function () {\n this.adUi.onAdsPlaying();\n this.sdkImpl.resumeAds();\n};\n\n/**\n * Toggles video/ad playback.\n */\nController.prototype.togglePlayback = function () {\n this.playerWrapper.togglePlayback();\n};\n\n/**\n * @return {boolean} true if we expect that ads will autoplay. false otherwise.\n */\nController.prototype.adsWillAutoplay = function () {\n if (this.settings.adsWillAutoplay !== undefined) {\n return this.settings.adsWillAutoplay;\n } else if (this.settings.adWillAutoplay !== undefined) {\n return this.settings.adWillAutoplay;\n } else {\n return !!this.playerWrapper.getPlayerOptions().autoplay;\n }\n};\n\n/**\n * @return {boolean} true if we expect that ads will autoplay. false otherwise.\n */\nController.prototype.adsWillPlayMuted = function () {\n if (this.settings.adsWillPlayMuted !== undefined) {\n return this.settings.adsWillPlayMuted;\n } else if (this.settings.adWillPlayMuted !== undefined) {\n return this.settings.adWillPlayMuted;\n } else if (this.playerWrapper.getPlayerOptions().muted !== undefined) {\n return this.playerWrapper.getPlayerOptions().muted;\n } else {\n return this.playerWrapper.getVolume() == 0;\n }\n};\n\n/**\n * Triggers an event on the VJS player\n * @param {string} name The event name.\n * @param {Object} data The event data.\n */\nController.prototype.triggerPlayerEvent = function (name, data) {\n this.playerWrapper.triggerPlayerEvent(name, data);\n};\n\n/**\n * Copyright 2021 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/**\n * Wraps the video.js stream player for the plugin.\n *\n * @param {!Object} player Video.js player instance.\n * @param {!Object} adsPluginSettings Settings for the contrib-ads plugin.\n * @param {!DaiController} daiController Reference to the parent controller.\n */\nvar PlayerWrapper = function PlayerWrapper(player, adsPluginSettings, daiController) {\n /**\n * Instance of the video.js player.\n */\n this.vjsPlayer = player;\n\n /**\n * Plugin DAI controller.\n */\n this.daiController = daiController;\n\n /**\n * Video.js control bar.\n */\n this.vjsControls = this.vjsPlayer.getChild('controlBar');\n\n /**\n * Vanilla HTML5 video player underneath the video.js player.\n */\n this.h5Player = null;\n this.vjsPlayer.on('dispose', this.playerDisposedListener.bind(this));\n this.vjsPlayer.on('pause', this.onPause.bind(this));\n this.vjsPlayer.on('play', this.onPlay.bind(this));\n this.vjsPlayer.on('seeked', this.onSeekEnd.bind(this));\n this.vjsPlayer.ready(this.onPlayerReady.bind(this));\n if (!this.vjsPlayer.ads) {\n window.console.warn('You may be using a version of videojs-contrib-ads ' + 'that is not compatible with your version of video.js.');\n }\n this.vjsPlayer.ads(adsPluginSettings);\n};\n\n/**\n * Called in response to the video.js player's 'disposed' event.\n */\nPlayerWrapper.prototype.playerDisposedListener = function () {\n this.contentEndedListeners = [];\n this.daiController.onPlayerDisposed();\n};\n\n/**\n * Called on the player 'pause' event. Handles displaying controls during\n * paused ad breaks.\n */\nPlayerWrapper.prototype.onPause = function () {\n // This code will run if the stream is paused during an ad break. Since\n // controls are usually hidden during ads, they will now show to allow\n // users to resume ad playback.\n if (this.daiController.isInAdBreak()) {\n this.vjsControls.show();\n }\n};\n\n/**\n * Called on the player 'play' event. Handles hiding controls during\n * ad breaks while playing.\n */\nPlayerWrapper.prototype.onPlay = function () {\n if (this.daiController.isInAdBreak()) {\n this.vjsControls.hide();\n }\n};\n\n/**\n * Called on the player's 'seeked' event. Sets up handling for ad break\n * snapback for VOD streams.\n */\nPlayerWrapper.prototype.onSeekEnd = function () {\n this.daiController.onSeekEnd(this.vjsPlayer.currentTime());\n};\n\n/**\n * Called on the player's 'ready' event to begin initiating IMA.\n */\nPlayerWrapper.prototype.onPlayerReady = function () {\n this.h5Player = document.getElementById(this.getPlayerId()).getElementsByClassName('vjs-tech')[0];\n this.daiController.onPlayerReady();\n};\n\n/**\n * @return {!Object} The stream player.\n */\nPlayerWrapper.prototype.getStreamPlayer = function () {\n return this.h5Player;\n};\n\n/**\n * @return {!Object} The video.js player.\n */\nPlayerWrapper.prototype.getVjsPlayer = function () {\n return this.vjsPlayer;\n};\n\n/**\n * @return {!Object} The vjs player's options object.\n */\nPlayerWrapper.prototype.getPlayerOptions = function () {\n return this.vjsPlayer.options_;\n};\n\n/**\n * Returns the instance of the player id.\n * @return {string} The player id.\n */\nPlayerWrapper.prototype.getPlayerId = function () {\n return this.vjsPlayer.id();\n};\n\n/**\n * Handles ad errors.\n *\n * @param {!Object} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nPlayerWrapper.prototype.onAdError = function (adErrorEvent) {\n this.vjsControls.show();\n var errorMessage = adErrorEvent.getError !== undefined ? adErrorEvent.getError() : adErrorEvent.stack;\n this.vjsPlayer.trigger({\n type: 'adserror',\n data: {\n AdError: errorMessage,\n AdErrorEvent: adErrorEvent\n }\n });\n};\n\n/**\n * Handles ad break starting.\n */\nPlayerWrapper.prototype.onAdBreakStart = function () {\n this.vjsControls.hide();\n};\n\n/**\n * Handles ad break ending.\n */\nPlayerWrapper.prototype.onAdBreakEnd = function () {\n this.vjsControls.show();\n};\n\n/**\n * Reset the player.\n */\nPlayerWrapper.prototype.reset = function () {\n this.vjsControls.show();\n};\n\n/**\n * Copyright 2021 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/**\n * Implementation of the IMA DAI SDK for the plugin.\n *\n * @param {DaiController!} daiController Reference to the parent DAI\n * controller.\n *\n * @constructor\n * @struct\n * @final\n */\nvar SdkImpl = function SdkImpl(daiController) {\n /**\n * Plugin DAI controller.\n */\n this.daiController = daiController;\n\n /**\n * The html5 stream player.\n */\n this.streamPlayer = null;\n\n /**\n * The videoJS stream player.\n */\n this.vjsPlayer = null;\n\n /**\n * IMA SDK StreamManager\n */\n this.streamManager = null;\n\n /**\n * IMA stream UI settings.\n */\n /* eslint no-undef: 'error' */\n /* global google */\n this.uiSettings = new google.ima.dai.api.UiSettings();\n\n /**\n * If the stream is currently in an ad break.\n */\n this.isAdBreak = false;\n\n /**\n * If the stream is currently seeking from a snapback.\n */\n this.isSnapback = false;\n\n /**\n * Originally seeked to time, to return stream to after ads.\n */\n this.snapForwardTime = 0;\n\n /**\n * Timed metadata for the stream.\n */\n this.timedMetadata;\n\n /**\n * Timed metadata record.\n */\n this.metadataLoaded = {};\n this.SOURCE_TYPES = {\n hls: 'application/x-mpegURL',\n dash: 'application/dash+xml'\n };\n};\n\n/**\n * Creates and initializes the IMA DAI SDK objects.\n */\nSdkImpl.prototype.initImaDai = function () {\n var _this = this;\n this.streamPlayer = this.daiController.getStreamPlayer();\n this.vjsPlayer = this.daiController.getVjsPlayer();\n this.createAdUiDiv();\n if (this.daiController.getSettings().locale) {\n this.uiSettings.setLocale(this.daiController.getSettings().locale);\n }\n this.streamManager = new google.ima.dai.api.StreamManager(this.streamPlayer, this.adUiDiv, this.uiSettings);\n this.streamPlayer.addEventListener('pause', this.onStreamPause);\n this.streamPlayer.addEventListener('play', this.onStreamPlay);\n var imaEvents = [google.ima.dai.api.StreamEvent.Type.LOADED, google.ima.dai.api.StreamEvent.Type.ERROR, google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED, google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED];\n imaEvents.forEach(function (event) {\n _this.streamManager.addEventListener(event, _this.onStreamEvent.bind(_this));\n });\n this.vjsPlayer.textTracks().onaddtrack = this.onAddTrack.bind(this);\n this.vjsPlayer.trigger({\n type: 'stream-manager',\n StreamManager: this.streamManager\n });\n this.requestStream();\n};\n\n/**\n * Called when the video player has metadata to process.\n * @param {Event!} event The event that triggered this call.\n */\nSdkImpl.prototype.onAddTrack = function (event) {\n var _this2 = this;\n var track = event.track;\n if (track.kind === 'metadata') {\n track.mode = 'hidden';\n track.addEventListener('cuechange', function (e) {\n var _iterator = _createForOfIteratorHelper(track.activeCues),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var cue = _step.value;\n var metadata = {};\n metadata[cue.value.key] = cue.value.data;\n _this2.streamManager.onTimedMetadata(metadata);\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n });\n }\n};\n\n/**\n * Creates the ad UI container.\n */\nSdkImpl.prototype.createAdUiDiv = function () {\n var uiDiv = document.createElement('div');\n uiDiv.id = 'ad-ui';\n // 3em is the height of the control bar.\n uiDiv.style.height = 'calc(100% - 3em)';\n this.streamPlayer.parentNode.appendChild(uiDiv);\n this.adUiDiv = uiDiv;\n};\n\n/**\n * Called on pause to update the ad UI.\n */\nSdkImpl.prototype.onStreamPause = function () {\n if (this.isAdBreak) {\n this.adUiDiv.style.display = 'none';\n }\n};\n\n/**\n * Called on play to update the ad UI.\n */\nSdkImpl.prototype.onStreamPlay = function () {\n if (this.isAdBreak) {\n this.adUiDiv.style.display = 'block';\n }\n};\n\n/**\n * Called on play to update the ad UI.\n * @param {number} currentTime the current time of the stream.\n */\nSdkImpl.prototype.onSeekEnd = function (currentTime) {\n var streamType = this.daiController.getSettings().streamType;\n if (streamType === 'live') {\n return;\n }\n if (this.isSnapback) {\n this.isSnapback = false;\n return;\n }\n var previousCuePoint = this.streamManager.previousCuePointForStreamTime(currentTime);\n if (previousCuePoint && !previousCuePoint.played) {\n this.isSnapback = true;\n this.snapForwardTime = currentTime;\n this.vjsPlayer.currentTime(previousCuePoint.start);\n }\n};\n\n/**\n * Handles IMA events.\n * @param {google.ima.StreamEvent!} event the IMA event\n */\nSdkImpl.prototype.onStreamEvent = function (event) {\n switch (event.type) {\n case google.ima.dai.api.StreamEvent.Type.LOADED:\n this.loadUrl(event.getStreamData().url);\n break;\n case google.ima.dai.api.StreamEvent.Type.ERROR:\n window.console.warn('Error loading stream, attempting to play backup ' + 'stream. ' + event.getStreamData().errorMessage);\n this.daiController.onErrorLoadingAds(event);\n if (this.daiController.getSettings().fallbackStreamUrl) {\n this.loadUrl(this.daiController.getSettings().fallbackStreamUrl);\n }\n break;\n case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:\n this.isAdBreak = true;\n this.adUiDiv.style.display = 'block';\n this.daiController.onAdBreakStart();\n break;\n case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:\n this.isAdBreak = false;\n this.adUiDiv.style.display = 'none';\n this.daiController.onAdBreakEnd();\n if (this.snapForwardTime && this.snapForwardTime > this.vjsPlayer.currentTime()) {\n this.vjsPlayer.currentTime(this.snapForwardTime);\n this.snapForwardTime = 0;\n }\n break;\n }\n};\n\n/**\n * Loads the stream URL .\n * @param {string} streamUrl the URL for the stream being loaded.\n */\nSdkImpl.prototype.loadUrl = function (streamUrl) {\n this.vjsPlayer.ready(function () {\n var streamFormat = this.daiController.getSettings().streamFormat;\n this.vjsPlayer.src({\n src: streamUrl,\n type: this.SOURCE_TYPES[streamFormat]\n });\n var bookmarkTime = this.daiController.getSettings().bookmarkTime;\n if (bookmarkTime) {\n var startTime = this.streamManager.streamTimeForContentTime(bookmarkTime);\n // Seeking on load triggers the onSeekEnd event, so treat this seek as\n // if it's snapback. Without this, resuming at a bookmark kicks you\n // back to the ad before the bookmark.\n this.isSnapback = true;\n this.vjsPlayer.currentTime(startTime);\n }\n }.bind(this));\n};\n\n/**\n * Creates the AdsRequest and request ads through the AdsLoader.\n */\nSdkImpl.prototype.requestStream = function () {\n var streamRequest;\n var streamType = this.daiController.getSettings().streamType;\n if (streamType === 'vod') {\n streamRequest = new google.ima.dai.api.VODStreamRequest();\n streamRequest.contentSourceId = this.daiController.getSettings().cmsId;\n streamRequest.videoId = this.daiController.getSettings().videoId;\n } else if (streamType === 'live') {\n streamRequest = new google.ima.dai.api.LiveStreamRequest();\n streamRequest.assetKey = this.daiController.getSettings().assetKey;\n } else {\n window.console.warn('No valid stream type selected');\n }\n streamRequest.format = this.daiController.getSettings().streamFormat;\n if (this.daiController.getSettings().apiKey) {\n streamRequest.apiKey = this.daiController.getSettings().apiKey;\n }\n if (this.daiController.getSettings().authToken) {\n streamRequest.authToken = this.daiController.getSettings().authToken;\n }\n if (this.daiController.getSettings().adTagParameters) {\n streamRequest.adTagParameters = this.daiController.getSettings().adTagParameters;\n }\n if (this.daiController.getSettings().streamActivityMonitorId) {\n streamRequest.streamActivityMonitorId = this.daiController.getSettings().streamActivityMonitorId;\n }\n if (this.daiController.getSettings().omidMode) {\n streamRequest.omidAccessModeRules = {};\n var omidValues = this.daiController.getSettings().omidMode;\n if (omidValues.FULL) {\n streamRequest.omidAccessModeRules[google.ima.OmidAccessMode.FULL] = omidValues.FULL;\n }\n if (omidValues.DOMAIN) {\n streamRequest.omidAccessModeRules[google.ima.OmidAccessMode.DOMAIN] = omidValues.DOMAIN;\n }\n if (omidValues.LIMITED) {\n streamRequest.omidAccessModeRules[google.ima.OmidAccessMode.LIMITED] = omidValues.LIMITED;\n }\n }\n this.streamManager.requestStream(streamRequest);\n this.vjsPlayer.trigger({\n type: 'stream-request',\n StreamRequest: streamRequest\n });\n};\n\n/**\n * Initiates IMA when the player is ready.\n */\nSdkImpl.prototype.onPlayerReady = function () {\n this.initImaDai();\n};\n\n/**\n * Reset the StreamManager when the player is disposed.\n */\nSdkImpl.prototype.onPlayerDisposed = function () {\n if (this.streamManager) {\n this.streamManager.reset();\n }\n};\n\n/**\n * Adds an EventListener to the StreamManager. For a list of available events,\n * see\n * https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/html5/reference/js/StreamEvent#.Type\n * @param {google.ima.dai.api.StreamEvent.Type} event The StreamEvent.Type for\n * which to listen.\n * @param {callback} callback The method to call when the event is fired.\n */\nSdkImpl.prototype.addEventListener = function (event, callback) {\n if (this.streamManager) {\n this.streamManager.addEventListener(event, callback);\n }\n};\n\n/**\n * Returns the instance of the StreamManager.\n * @return {google.ima.StreamManager!} The StreamManager being used by the\n * plugin.\n */\nSdkImpl.prototype.getStreamManager = function () {\n return this.streamManager;\n};\n\n/**\n * Reset the SDK implementation.\n */\nSdkImpl.prototype.reset = function () {\n if (this.streamManager) {\n this.streamManager.reset();\n }\n};\n\n/**\n * Copyright 2021 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/**\n * The coordinator for the DAI portion of the plugin. Facilitates\n * communication between all other plugin classes.\n *\n * @param {Object!} player Instance of the video.js player.\n * @param {Object!} options Options provided by the implementation.\n * @constructor\n * @struct\n * @final\n */\nvar DaiController = function DaiController(player, options) {\n /**\n * If the stream is currently in an ad break.\n * @type {boolean}\n */\n this.inAdBreak = false;\n\n /**\n * Stores user-provided settings.\n * @type {Object!}\n */\n this.settings = {};\n\n /**\n * Whether or not we are running on a mobile platform.\n */\n this.isMobile = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/Android/i);\n\n /**\n * Whether or not we are running on an iOS platform.\n */\n this.isIos = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i);\n this.initWithSettings(options);\n\n /**\n * Stores contrib-ads default settings.\n */\n var contribAdsDefaults = {\n debug: this.settings.debug,\n timeout: this.settings.timeout,\n prerollTimeout: this.settings.prerollTimeout\n };\n var adsPluginSettings = Object.assign({}, contribAdsDefaults, options.contribAdsSettings || {});\n this.playerWrapper = new PlayerWrapper(player, adsPluginSettings, this);\n this.sdkImpl = new SdkImpl(this);\n};\nDaiController.IMA_DEFAULTS = {\n adLabel: 'Advertisement',\n adLabelNofN: 'of',\n debug: false,\n disableAdControls: false,\n showControlsForJSAds: true\n};\n\n/**\n * Extends the settings to include user-provided settings.\n *\n * @param {Object!} options Options to be used in initialization.\n */\nDaiController.prototype.initWithSettings = function (options) {\n this.settings = Object.assign({}, DaiController.IMA_DEFAULTS, options || {});\n this.warnAboutDeprecatedSettings();\n\n // Default showing countdown timer to true.\n this.showCountdown = true;\n if (this.settings.showCountdown === false) {\n this.showCountdown = false;\n }\n};\n\n/**\n * Logs console warnings when deprecated settings are used.\n */\nDaiController.prototype.warnAboutDeprecatedSettings = function () {\n var _this = this;\n var deprecatedSettings = [\n // Currently no DAI plugin settings are deprecated.\n ];\n deprecatedSettings.forEach(function (setting) {\n if (_this.settings[setting] !== undefined) {\n console.warn('WARNING: videojs.imaDai setting ' + setting + ' is deprecated');\n }\n });\n};\n\n/**\n * Return the settings object.\n *\n * @return {Object!} The settings object.\n */\nDaiController.prototype.getSettings = function () {\n return this.settings;\n};\n\n/**\n * Return whether or not we're in a mobile environment.\n *\n * @return {boolean} True if running on mobile, false otherwise.\n */\nDaiController.prototype.getIsMobile = function () {\n return this.isMobile;\n};\n\n/**\n * Return whether or not we're in an iOS environment.\n *\n * @return {boolean} True if running on iOS, false otherwise.\n */\nDaiController.prototype.getIsIos = function () {\n return this.isIos;\n};\n\n/**\n * @return {Object!} The html5 player.\n */\nDaiController.prototype.getStreamPlayer = function () {\n return this.playerWrapper.getStreamPlayer();\n};\n\n/**\n * @return {Object!} The video.js player.\n */\nDaiController.prototype.getVjsPlayer = function () {\n return this.playerWrapper.getVjsPlayer();\n};\n\n/**\n * Requests the stream.\n */\nDaiController.prototype.requestStream = function () {\n this.sdkImpl.requestStream();\n};\n\n/**\n * Add or modify a setting.\n *\n * @param {string} key Key to modify\n * @param {Object!} value Value to set at key.\n*/\nDaiController.prototype.setSetting = function (key, value) {\n this.settings[key] = value;\n};\n\n/**\n * Called when there is an error loading ads.\n *\n * @param {Object!} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nDaiController.prototype.onErrorLoadingAds = function (adErrorEvent) {\n this.playerWrapper.onAdError(adErrorEvent);\n};\n\n/**\n * Relays ad errors to the player wrapper.\n *\n * @param {Object!} adErrorEvent The ad error event thrown by the IMA SDK.\n */\nDaiController.prototype.onAdError = function (adErrorEvent) {\n this.playerWrapper.onAdError(adErrorEvent);\n};\n\n/**\n * Signals player that an ad break has started.\n */\nDaiController.prototype.onAdBreakStart = function () {\n this.inAdBreak = true;\n this.playerWrapper.onAdBreakStart();\n};\n\n/**\n * Signals player that an ad break has ended.\n */\nDaiController.prototype.onAdBreakEnd = function () {\n this.inAdBreak = false;\n this.playerWrapper.onAdBreakEnd();\n};\n\n/**\n * Called when the player is disposed.\n */\nDaiController.prototype.onPlayerDisposed = function () {\n this.contentAndAdsEndedListeners = [];\n this.sdkImpl.onPlayerDisposed();\n};\n\n/**\n * Returns if the stream is currently in an ad break.\n * @return {boolean} If the stream is currently in an ad break.\n */\nDaiController.prototype.isInAdBreak = function () {\n return this.inAdBreak;\n};\n\n/**\n * Called on seek end to check for ad snapback.\n * @param {number} currentTime the current time of the stream.\n */\nDaiController.prototype.onSeekEnd = function (currentTime) {\n this.sdkImpl.onSeekEnd(currentTime);\n};\n\n/**\n * Called when the player is ready.\n */\nDaiController.prototype.onPlayerReady = function () {\n this.sdkImpl.onPlayerReady();\n};\n\n/**\n * Resets the state of the plugin.\n */\nDaiController.prototype.reset = function () {\n this.sdkImpl.reset();\n this.playerWrapper.reset();\n};\n\n/**\n * Adds an EventListener to the StreamManager. For a list of available events,\n * see\n * https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/html5/reference/js/StreamEvent\n * @param {google.ima.StreamEvent.Type!} event The AdEvent.Type for which to\n * listen.\n * @param {callback!} callback The method to call when the event is fired.\n */\nDaiController.prototype.addEventListener = function (event, callback) {\n this.sdkImpl.addEventListener(event, callback);\n};\n\n/**\n * Returns the instance of the StreamManager.\n * @return {google.ima.StreamManager!} The StreamManager being used by the\n * plugin.\n */\nDaiController.prototype.getStreamManager = function () {\n return this.sdkImpl.getStreamManager();\n};\n\n/**\n * Returns the instance of the player id.\n * @return {string} The player id.\n */\nDaiController.prototype.getPlayerId = function () {\n return this.playerWrapper.getPlayerId();\n};\n\n/**\n * @return {boolean} true if we expect that the stream will autoplay. false\n * otherwise.\n */\nDaiController.prototype.streamWillAutoplay = function () {\n if (this.settings.streamWillAutoplay !== undefined) {\n return this.settings.streamWillAutoplay;\n } else {\n return !!this.playerWrapper.getPlayerOptions().autoplay;\n }\n};\n\n/**\n * Triggers an event on the VJS player\n * @param {string} name The event name.\n * @param {Object!} data The event data.\n */\nDaiController.prototype.triggerPlayerEvent = function (name, data) {\n this.playerWrapper.triggerPlayerEvent(name, data);\n};\n\n/**\n * Exposes the ImaPlugin to a publisher implementation.\n *\n * @param {Object} player Instance of the video.js player to which this plugin\n * will be added.\n * @param {Object} options Options provided by the implementation.\n * @constructor\n * @struct\n * @final\n */\nvar ImaPlugin = function ImaPlugin(player, options) {\n this.controller = new Controller(player, options);\n\n /**\n * Listener JSDoc for ESLint. This listener can be passed to\n * addContent(AndAds)EndedListener.\n * @callback listener\n */\n\n /**\n * Adds a listener that will be called when content and all ads have\n * finished playing.\n * @param {listener} listener The listener to be called when content and ads\n * complete.\n */\n this.addContentAndAdsEndedListener = function (listener) {\n this.controller.addContentAndAdsEndedListener(listener);\n }.bind(this);\n\n /**\n * Adds a listener for the 'readyforpostroll' event of the video player. This\n * should be used instead of setting an 'readyforpostroll' listener directly\n * to ensure that the ima can do proper cleanup of the SDK before other event\n * listeners are called.\n * @param {listener} listener The listener to be called when content\n * completes.\n */\n this.addContentEndedListener = function (listener) {\n this.controller.addContentEndedListener(listener);\n }.bind(this);\n\n /**\n * Callback JSDoc for ESLint. This callback can be passed to addEventListener.\n * @callback callback\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/client-side/reference/js/google.ima.AdEvent#.Type\n * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to\n * listen.\n * @param {callback} callback The method to call when the event is fired.\n */\n this.addEventListener = function (event, callback) {\n this.controller.addEventListener(event, callback);\n }.bind(this);\n\n /**\n * Changes the ad tag. You will need to call requestAds after this method\n * for the new ads to be requested.\n * @param {?string} adTag The ad tag to be requested the next time requestAds\n * is called.\n */\n this.changeAdTag = function (adTag) {\n this.controller.changeAdTag(adTag);\n }.bind(this);\n\n /**\n * Returns the instance of the AdsManager.\n * @return {google.ima.AdsManager} The AdsManager being used by the plugin.\n */\n this.getAdsManager = function () {\n return this.controller.getAdsManager();\n }.bind(this);\n\n /**\n * Initializes the AdDisplayContainer. On mobile, this must be done as a\n * result of user action.\n */\n this.initializeAdDisplayContainer = function () {\n this.controller.initializeAdDisplayContainer();\n }.bind(this);\n\n /**\n * Pauses the ad.\n */\n this.pauseAd = function () {\n this.controller.pauseAd();\n }.bind(this);\n\n /**\n * Called by publishers in manual ad break playback mode to start an ad\n * break.\n */\n this.playAdBreak = function () {\n this.controller.playAdBreak();\n }.bind(this);\n\n /**\n * Creates the AdsRequest and request ads through the AdsLoader.\n */\n this.requestAds = function () {\n this.controller.requestAds();\n }.bind(this);\n\n /**\n * Resumes the ad.\n */\n this.resumeAd = function () {\n this.controller.resumeAd();\n }.bind(this);\n\n /**\n * Sets the listener to be called to trigger manual ad break playback.\n * @param {listener} listener The listener to be called to trigger manual ad\n * break playback.\n */\n this.setAdBreakReadyListener = function (listener) {\n this.controller.setAdBreakReadyListener(listener);\n }.bind(this);\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 */\n this.setContentWithAdTag = function (contentSrc, adTag) {\n this.controller.setContentWithAdTag(contentSrc, adTag);\n }.bind(this);\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 ads response is\n * used 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} adsResponse The ads response to be requested when the\n * content loads. Leave blank to use the existing ads response.\n */\n this.setContentWithAdsResponse = function (contentSrc, adsResponse) {\n this.controller.setContentWithAdsResponse(contentSrc, adsResponse);\n }.bind(this);\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 ads request is\n * used 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 {?Object} adsRequest The ads request to be requested when the\n * content loads. Leave blank to use the existing ads request.\n */\n this.setContentWithAdsRequest = function (contentSrc, adsRequest) {\n this.controller.setContentWithAdsRequest(contentSrc, adsRequest);\n }.bind(this);\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 this.setShowCountdown = function (showCountdownIn) {\n this.controller.setShowCountdown(showCountdownIn);\n }.bind(this);\n};\n\n/**\n * Exposes the ImaDaiPlugin to a publisher implementation.\n *\n * @param {Object} player Instance of the video.js player to which this plugin\n * will be added.\n * @param {Object} options Options provided by the implementation.\n * @constructor\n * @struct\n * @final\n */\nvar ImaDaiPlugin = function ImaDaiPlugin(player, options) {\n this.controller = new DaiController(player, options);\n\n /**\n * Adds a listener that will be called when content and all ads in the\n * stream have finished playing. VOD stream only.\n * @param {listener} listener The listener to be called when content and ads\n * complete.\n */\n this.streamEndedListener = function (listener) {\n this.controller.addStreamEndedListener(listener);\n }.bind(this);\n\n /**\n * Adds an EventListener to the StreamManager.\n * @param {google.ima.StreamEvent.Type} event The StreamEvent.Type for which\n * to listen.\n * @param {callback} callback The method to call when the event is fired.\n */\n this.addEventListener = function (event, callback) {\n this.controller.addEventListener(event, callback);\n }.bind(this);\n\n /**\n * Returns the instance of the StreamManager.\n * @return {google.ima.StreamManager} The StreamManager being used by the\n * plugin.\n */\n this.getStreamManager = function () {\n return this.controller.getStreamManager();\n }.bind(this);\n};\n\n/**\n * Initializes the plugin for client-side ads.\n * @param {Object} options Plugin option set on initiation.\n */\nvar init = function init(options) {\n /* eslint no-invalid-this: 'off' */\n this.ima = new ImaPlugin(this, options);\n};\n\n/**\n * LiveStream class used for DAI live streams.\n */\nvar LiveStream = /*#__PURE__*/_createClass(\n/**\n * LiveStream class constructor used for DAI live streams.\n * @param {string} streamFormat stream format, plugin currently supports only\n * 'hls' streams.\n * @param {string} assetKey live stream's asset key.\n */\nfunction LiveStream(streamFormat, assetKey) {\n _classCallCheck(this, LiveStream);\n streamFormat = streamFormat.toLowerCase();\n if (streamFormat !== 'hls' && streamFormat !== 'dash') {\n window.console.error('VodStream error: incorrect streamFormat.');\n return;\n } else if (streamFormat === 'dash') {\n window.console.error('streamFormat error: DASH streams are not' + 'currently supported by this plugin.');\n return;\n } else if (typeof assetKey !== 'string') {\n window.console.error('assetKey error: value must be string.');\n return;\n }\n this.streamFormat = streamFormat;\n this.assetKey = assetKey;\n});\n/**\n * VodStream class used for DAI VOD streams.\n */\nvar VodStream = /*#__PURE__*/_createClass(\n/**\n * VodStream class constructor used for DAI VOD streams.\n * @param {string} streamFormat stream format, plugin currently supports only\n * 'hls' streams.\n * @param {string} cmsId VOD stream's CMS ID.\n * @param {string} videoId VOD stream's video ID.\n */\nfunction VodStream(streamFormat, cmsId, videoId) {\n _classCallCheck(this, VodStream);\n streamFormat = streamFormat.toLowerCase();\n if (streamFormat !== 'hls' && streamFormat !== 'dash') {\n window.console.error('VodStream error: incorrect streamFormat.');\n return;\n } else if (streamFormat === 'dash') {\n window.console.error('streamFormat error: DASH streams are not' + 'currently supported by this plugin.');\n return;\n } else if (typeof cmsId !== 'string') {\n window.console.error('cmsId error: value must be string.');\n return;\n } else if (typeof videoId !== 'string') {\n window.console.error('videoId error: value must be string.');\n return;\n }\n this.streamFormat = streamFormat;\n this.cmsId = cmsId;\n this.videoId = videoId;\n});\n/**\n * Initializes the plugin for DAI ads.\n * @param {Object} stream Accepts either an instance of the LiveStream or\n * VodStream classes.\n * @param {Object} options Plugin option set on initiation.\n */\nvar initDai = function initDai(stream, options) {\n if (stream instanceof LiveStream) {\n options.streamType = 'live';\n options.assetKey = stream.assetKey;\n } else if (stream instanceof VodStream) {\n options.streamType = 'vod';\n options.cmsId = stream.cmsId;\n options.videoId = stream.videoId;\n } else {\n window.console.error('initDai() first parameter must be an instance of LiveStream or ' + 'VodStream.');\n return;\n }\n options.streamFormat = stream.streamFormat;\n /* eslint no-invalid-this: 'off' */\n this.imaDai = new ImaDaiPlugin(this, options);\n};\nvar registerPlugin = (video_js__WEBPACK_IMPORTED_MODULE_0___default().registerPlugin) || (video_js__WEBPACK_IMPORTED_MODULE_0___default().plugin);\nregisterPlugin('ima', init);\nregisterPlugin('imaDai', initDai);\n\n\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/videojs-ima/dist/videojs.ima.es.js?");
77
77
 
78
- /***/ },
78
+ /***/ }),
79
79
 
80
- /***/ "?9835"
80
+ /***/ "?9835":
81
81
  /*!******************************!*\
82
82
  !*** min-document (ignored) ***!
83
83
  \******************************/
84
- () {
84
+ /***/ (() => {
85
85
 
86
- eval("{/* (ignored) */\n\n//# sourceURL=webpack://cloudinary-video-player/min-document_(ignored)?\n}");
86
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://cloudinary-video-player/min-document_(ignored)?");
87
87
 
88
- /***/ }
88
+ /***/ })
89
89
 
90
90
  }]);