From bb68bd533acac63d6cb1732ea5791637452afa1f Mon Sep 17 00:00:00 2001 From: Basil Goldman Date: Wed, 21 Sep 2022 10:47:45 +0300 Subject: [PATCH] refactor vpaid load after message event --- TODO.md | 11 + public/js/ads-manager.js | 4 +- public/js/index.js | 559 ++++++++++++++++++++------------------- src/ads-manager.js | 64 ++--- 4 files changed, 329 insertions(+), 309 deletions(-) create mode 100644 TODO.md diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..b429893 --- /dev/null +++ b/TODO.md @@ -0,0 +1,11 @@ +# TODO + +## SIMID Survey Pre-roll +```text +https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/simid&description_url=https%3A%2F%2Fdevelopers.google.com%2Finteractive-media-ads&sz=640x480&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator= +``` + +## OM SDK Sample Pre-roll +```text +https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/omid_ad_samples&env=vp&gdfp_req=1&output=vast&sz=640x480&description_url=http%3A%2F%2Ftest_site.com%2Fhomepage&vpmute=0&vpa=0&vad_format=linear&url=http%3A%2F%2Ftest_site.com&vpos=preroll&unviewed_position_start=1&correlator= +``` diff --git a/public/js/ads-manager.js b/public/js/ads-manager.js index 0ef5d6a..94484af 100644 --- a/public/js/ads-manager.js +++ b/public/js/ads-manager.js @@ -1,6 +1,6 @@ /*! * ads-manager v1.1.5 development - * Updated : 2022-09-19 + * Updated : 2022-09-21 */ /* * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). @@ -42,7 +42,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"AdsManager\": () => (/* binding */ AdsManager)\n/* harmony export */ });\n/* harmony import */ var _dailymotion_vast_client__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @dailymotion/vast-client */ \"./node_modules/@dailymotion/vast-client/dist/vast-client.min.js\");\n/* harmony import */ var _dailymotion_vast_client__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_dailymotion_vast_client__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _ad_error__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ad-error */ \"./src/ad-error.js\");\n\n\n\nconst AdsManager = function(adContainer) {\n\n if(!(adContainer instanceof Element || adContainer instanceof HTMLDocument)) {\n throw new Error('ad container is not defined');\n }\n\n // Ad Container\n this._adContainer = adContainer;\n\n // Slot\n this._slot = null;\n // Video Slot\n this._videoSlot = null;\n\n // Create Slot\n this.createSlot();\n\n // Events\n this.EVENTS = {\n AdsManagerLoaded: 'AdsManagerLoaded', // After success ad request, when vast xml is parsed and ready\n AdStarted: 'AdStarted',\n AdStopped: 'AdStopped',\n AdSkipped: 'AdSkipped',\n AdLoaded: 'AdLoaded',\n AdLinearChange: 'AdLinearChange',\n AdSizeChange: 'AdSizeChange',\n AdExpandedChange: 'AdExpandedChange',\n AdSkippableStateChange: 'AdSkippableStateChange',\n AdDurationChange: 'AdDurationChange',\n AdRemainingTimeChange: 'AdRemainingTimeChange',\n AdVolumeChange: 'AdVolumeChange',\n AdImpression: 'AdImpression',\n AdClickThru: 'AdClickThru',\n AdInteraction: 'AdInteraction',\n AdVideoStart: 'AdVideoStart',\n AdVideoFirstQuartile: 'AdVideoFirstQuartile',\n AdVideoMidpoint: 'AdVideoMidpoint',\n AdVideoThirdQuartile: 'AdVideoThirdQuartile',\n AdVideoComplete: 'AdVideoComplete',\n AdUserAcceptInvitation: 'AdUserAcceptInvitation',\n AdUserMinimize: 'AdUserMinimize',\n AdUserClose: 'AdUserClose',\n AdPaused: 'AdPaused',\n AdPlaying: 'AdPlaying',\n AdError: 'AdError',\n AdLog: 'AdLog',\n AllAdsCompleted: 'AllAdsCompleted' // After all ads completed, vast, vpaid, vmap\n };\n this._eventCallbacks = {};\n this._creativeEventCallbacks = {};\n\n // Attributes\n this._attributes = {\n width: 300,\n height: 154,\n viewMode: 'normal',\n desiredBitrate: -1, // 268,\n duration: 10,\n remainingTime: 10,\n currentTime: 0,\n volume: 0,\n version: '1.1.5'\n };\n\n // Quartile Events\n this._quartileEvents = [\n { event: 'AdImpression', value: 0 },\n { event: 'AdVideoStart', value: 0 },\n { event: 'AdVideoFirstQuartile', value: 25 },\n { event: 'AdVideoMidpoint', value: 50 },\n { event: 'AdVideoThirdQuartile', value: 75 },\n { event: 'AdVideoComplete', value: 100 }\n ];\n this._nextQuartileIndex = 0;\n this._defaultEventCallbacks = {\n 'AdImpression': this.onAdImpression.bind(this),\n 'AdVideoStart': this.onAdVideoStart.bind(this),\n 'AdVideoFirstQuartile': this.onAdVideoFirstQuartile.bind(this),\n 'AdVideoMidpoint': this.onAdVideoMidpoint.bind(this),\n 'AdVideoThirdQuartile': this.onAdVideoThirdQuartile.bind(this),\n 'AdVideoComplete': this.onAdVideoComplete.bind(this)\n };\n\n // Options\n this._options = {\n autoplay: true,\n muted: true,\n vastLoadTimeout: 23000,\n loadVideoTimeout: 8000,\n //creativeLoadTimeout: 5000,\n withCredentials: false,\n wrapperLimit: 10,\n resolveAll: true\n };\n // Error codes\n this.ERROR_CODES = {\n VAST_MALFORMED_RESPONSE:100,\n ADS_REQUEST_NETWORK_ERROR: 1012,\n FAILED_TO_REQUEST_ADS: 1005,\n UNKNOWN_AD_RESPONSE: 1010,\n VAST_ASSET_NOT_FOUND: 1007,\n VAST_EMPTY_RESPONSE: 1009,\n VAST_LINEAR_ASSET_MISMATCH: 403,\n VAST_LOAD_TIMEOUT: 301,\n VAST_MEDIA_LOAD_TIMEOUT: 402,\n VIDEO_PLAY_ERROR: 400,\n VPAID_ERROR: 901,\n };\n // Error messages\n this.ERROR_MESSAGES = {\n VAST_MALFORMED_RESPONSE: 'VAST response was malformed and could not be parsed.', // 100\n ADS_REQUEST_ERROR: 'Unable to request ads from server. Cause: {0}.', // 1005\n ADS_REQUEST_NETWORK_ERROR: 'Unable to request ads from server due to network error.', // 1012\n FAILED_TO_REQUEST_ADS: 'The was a problem requesting ads from the server.', // 1005\n NO_ADS_FOUND: 'The response does not contain any valid ads.', // 1009\n UNKNOWN_AD_RESPONSE: 'The ad response was not understood and cannot be parsed.', // 1010\n VAST_ASSET_NOT_FOUND: 'No assets were found in the VAST ad response.', // 1007\n VAST_EMPTY_RESPONSE: 'The VAST response document is empty.', // 1009\n VAST_LINEAR_ASSET_MISMATCH: 'Linear assets were found in the VAST ad response, but none of them matched the player\\'s capabilities.', // 403\n VAST_LOAD_TIMEOUT: 'Ad request reached a timeout.', // 301\n VAST_MEDIA_LOAD_TIMEOUT: 'VAST media file loading reached a timeout of {0} seconds.', // 402\n VIDEO_PLAY_ERROR: 'There was an error playing the video ad.', // 400\n VPAID_CREATIVE_ERROR: 'An unexpected error occurred within the VPAID creative. Refer to the inner error for more info.' // 901\n };\n // Errors\n this.ERRORS = {\n VAST_MALFORMED_RESPONSE: new _ad_error__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.ERROR_MESSAGES.VAST_MALFORMED_RESPONSE, this.ERROR_CODES.VAST_MALFORMED_RESPONSE),\n VAST_EMPTY_RESPONSE: new _ad_error__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.ERROR_MESSAGES.VAST_EMPTY_RESPONSE, this.ERROR_CODES.VAST_EMPTY_RESPONSE),\n VAST_ASSET_NOT_FOUND: new _ad_error__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.ERROR_MESSAGES.VAST_ASSET_NOT_FOUND, this.ERROR_CODES.VAST_ASSET_NOT_FOUND),\n VAST_LINEAR_ASSET_MISMATCH: new _ad_error__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.ERROR_MESSAGES.VAST_LINEAR_ASSET_MISMATCH, this.ERROR_CODES.VAST_LINEAR_ASSET_MISMATCH),\n VAST_LOAD_TIMEOUT: new _ad_error__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.ERROR_MESSAGES.VAST_LOAD_TIMEOUT, this.ERROR_CODES.VAST_LOAD_TIMEOUT),\n VAST_MEDIA_LOAD_TIMEOUT: new _ad_error__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.ERROR_MESSAGES.VAST_MEDIA_LOAD_TIMEOUT, this.ERROR_CODES.VAST_MEDIA_LOAD_TIMEOUT),\n VIDEO_PLAY_ERROR: new _ad_error__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.ERROR_MESSAGES.VIDEO_PLAY_ERROR, this.ERROR_CODES.VIDEO_PLAY_ERROR)\n };\n\n this._vastClient = null;\n this._vastParser = null;\n this._vastTracker = null;\n\n this._ad = null;\n this._adPod = null;\n this._creative = null;\n this._mediaFiles = null;\n this._mediaFileIndex = 0;\n this._mediaFile = null;\n\n this._isVPAID = false;\n this._vpaidIframe = null;\n this._vpaidCreative = null;\n\n // Timers, Intervals\n this._vastMediaLoadTimer = null;\n this._creativeLoadTimer = null;\n this._vpaidProgressTimer = null;\n\n // Handlers\n this._handleCreativeMessageFn = this._handleCreativeMessage.bind(this);\n\n this.SUPPORTED_CREATIVE_VPAID_VERSION_MIN = 2;\n\n this._hasLoaded = false;\n this._hasError = false;\n this._hasImpression = false;\n this._hasStarted = false;\n\n this._isDestroyed = false;\n}\nAdsManager.prototype.createSlot = function() {\n this._slot = document.createElement('div');\n this._slot.style.position = 'absolute';\n this._slot.style.display = 'none';\n this._adContainer.appendChild(this._slot);\n this.createVideoSlot();\n}\nAdsManager.prototype.removeSlot = function() {\n this._slot.parentNode && this._slot.parentNode.removeChild(this._slot);\n //this.createSlot();\n}\nAdsManager.prototype.showSlot = function() {\n // Check if video slot has src, if no then hide video slot\n if(this._videoSlot.src === '') {\n this.hideVideoSlot();\n }\n // Show slot\n this._slot.style.display = 'block';\n}\nAdsManager.prototype.resizeSlot = function(width, height) {\n this._slot.style.width = width + 'px';\n this._slot.style.height = height + 'px';\n}\nAdsManager.prototype.createVideoSlot = function() {\n this._videoSlot = document.createElement('video');\n this._videoSlot.setAttribute('webkit-playsinline', true);\n this._videoSlot.setAttribute('playsinline', true);\n //this._videoSlot.setAttribute('preload', 'none');\n this._videoSlot.style.width = '100%';\n this._videoSlot.style.height = '100%';\n this._videoSlot.style.backgroundColor = 'rgb(0, 0, 0)';\n //this._adContainer.appendChild(this._videoSlot);\n this._slot.appendChild(this._videoSlot);\n}\nAdsManager.prototype.hideVideoSlot = function() {\n this._videoSlot.style.display = 'none';\n}\nAdsManager.prototype.stopVASTMediaLoadTimeout = function() {\n if(this._vastMediaLoadTimer) {\n clearTimeout(this._vastMediaLoadTimer);\n this._vastMediaLoadTimer = null;\n }\n}\nAdsManager.prototype.startVASTMediaLoadTimeout = function() {\n this.stopVASTMediaLoadTimeout();\n this._vastMediaLoadTimer = setTimeout(() => {\n this.onAdError(this.ERRORS.VAST_MEDIA_LOAD_TIMEOUT.formatMessage(this._options.loadVideoTimeout));\n }, this._options.loadVideoTimeout);\n}\nAdsManager.prototype.updateVPAIDProgress = function() {\n // Check remaining time\n this._attributes.remainingTime = this._isCreativeFunctionInvokable('getAdRemainingTime') ? this._vpaidCreative.getAdRemainingTime() : -1;\n if(!isNaN(this._attributes.remainingTime) && this._attributes.remainingTime !== 1) {\n this._attributes.currentTime = this._attributes.duration - this._attributes.remainingTime;\n // Track progress\n this._vastTracker.setProgress(this._attributes.currentTime);\n }\n}\nAdsManager.prototype.startVPAIDProgress = function() {\n this.stopVPAIDProgress();\n this._vpaidProgressTimer = setInterval(() => {\n if(this._isVPAID && this._vpaidCreative && this._vastTracker) {\n this.updateVPAIDProgress();\n } else {\n this.stopVPAIDProgress();\n }\n }, 1000);\n}\nAdsManager.prototype.stopVPAIDProgress = function() {\n if(this._vpaidProgressTimer) {\n clearInterval(this._vpaidProgressTimer);\n this._vpaidProgressTimer = null;\n }\n}\nAdsManager.prototype.addEventListener = function(eventName, callback, context) {\n const givenCallback = callback.bind(context);\n this._eventCallbacks[eventName] = givenCallback;\n}\nAdsManager.prototype.removeEventListener = function(eventName) {\n this._eventCallbacks[eventName] = null;\n}\nAdsManager.prototype.removeEventListeners = function(eventCallbacks) {\n for (const eventName in eventCallbacks) {\n eventCallbacks.hasOwnProperty(eventName) && this.removeEventListener(eventName);\n }\n}\nAdsManager.prototype.onAdsManagerLoaded = function() {\n if (this.EVENTS.AdsManagerLoaded in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdsManagerLoaded] === 'function') {\n this._eventCallbacks[this.EVENTS.AdsManagerLoaded]();\n }\n }\n}\nAdsManager.prototype.onAdLoaded = function() {\n this.stopVASTMediaLoadTimeout();\n if (this.EVENTS.AdLoaded in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdLoaded] === 'function') {\n this._eventCallbacks[this.EVENTS.AdLoaded](this._creative);\n }\n }\n}\nAdsManager.prototype.onAdDurationChange = function() {\n if(this._isVPAID && this._vpaidCreative && this._vastTracker) {\n this._attributes.duration = this._isCreativeFunctionInvokable('getAdDuration') ? this._vpaidCreative.getAdDuration() : -1;\n if(this._attributes.duration !== -1) {\n this._vastTracker.setDuration(this._attributes.duration);\n }\n }\n if (this.EVENTS.AdDurationChange in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdDurationChange] === 'function') {\n this._eventCallbacks[this.EVENTS.AdDurationChange]();\n }\n }\n}\nAdsManager.prototype.onAdSizeChange = function() {\n if (this.EVENTS.AdSizeChange in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdSizeChange] === 'function') {\n this._eventCallbacks[this.EVENTS.AdSizeChange]();\n }\n }\n}\nAdsManager.prototype.onAdStarted = function() {\n // Show ad slot\n this.showSlot();\n\n if (this.EVENTS.AdStarted in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdStarted] === 'function') {\n this._eventCallbacks[this.EVENTS.AdStarted]();\n }\n }\n}\nAdsManager.prototype.onAdVideoStart = function() {\n if(this._isVPAID && this._vpaidCreative && this._vastTracker) {\n this.updateVPAIDProgress();\n }\n if (this.EVENTS.AdVideoStart in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdVideoStart] === 'function') {\n this._eventCallbacks[this.EVENTS.AdVideoStart]();\n }\n }\n}\nAdsManager.prototype.onAdStopped = function() {\n if (this.EVENTS.AdStopped in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdStopped] === 'function') {\n this._eventCallbacks[this.EVENTS.AdStopped]();\n }\n }\n // abort the ad, unsubscribe and reset to a default state\n this._abort();\n}\nAdsManager.prototype.onAdSkipped = function() {\n if (this.EVENTS.AdSkipped in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdSkipped] === 'function') {\n this._eventCallbacks[this.EVENTS.AdSkipped]();\n }\n }\n // abort the ad, unsubscribe and reset to a default state\n this._abort();\n}\nAdsManager.prototype.onAdVolumeChange = function() {\n if (this.EVENTS.AdVolumeChange in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdVolumeChange] === 'function') {\n this._eventCallbacks[this.EVENTS.AdVolumeChange]();\n }\n }\n}\nAdsManager.prototype.onAdImpression = function() {\n if(this._isVPAID && this._vpaidCreative && this._vastTracker) {\n if (!this._hasImpression) {\n // Check duration\n this._attributes.duration = this._isCreativeFunctionInvokable('getAdDuration') ? this._vpaidCreative.getAdDuration() : -1;\n if(this._attributes.duration !== -1) {\n this._vastTracker.setDuration(this._attributes.duration);\n }\n /*\n // Check remaining time\n this._attributes.remainingTime = this._isCreativeFunctionInvokable(\"getAdRemainingTime\") ? this._vpaidCreative.getAdRemainingTime() : -1;\n console.log('update tracker with new remainingTime', this._attributes.remainingTime);\n console.log('update tracker with new duration', this._attributes.duration);\n */\n // Track impression\n this._vastTracker.trackImpression();\n\n // Start VPAID process\n this.startVPAIDProgress();\n\n this._hasImpression = true;\n }\n }\n if (this.EVENTS.AdImpression in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdImpression] === 'function') {\n this._eventCallbacks[this.EVENTS.AdImpression]();\n }\n }\n}\nAdsManager.prototype.onAdClickThru = function(url, id, playerHandles) {\n if(this._isVPAID && this._vpaidCreative && this._vastTracker) {\n this._vastTracker.click();\n }\n if (this.EVENTS.AdClickThru in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdClickThru] === 'function') {\n this._eventCallbacks[this.EVENTS.AdClickThru](url, id, playerHandles);\n }\n }\n}\nAdsManager.prototype.onAdVideoFirstQuartile = function() {\n if(this._isVPAID && this._vpaidCreative && this._vastTracker) {\n this.updateVPAIDProgress();\n }\n if (this.EVENTS.AdVideoFirstQuartile in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdVideoFirstQuartile] === 'function') {\n this._eventCallbacks[this.EVENTS.AdVideoFirstQuartile]();\n }\n }\n};\nAdsManager.prototype.onAdVideoMidpoint = function() {\n if(this._isVPAID && this._vpaidCreative && this._vastTracker) {\n this.updateVPAIDProgress();\n }\n if (this.EVENTS.AdVideoMidpoint in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdVideoMidpoint] === 'function') {\n this._eventCallbacks[this.EVENTS.AdVideoMidpoint]();\n }\n }\n};\nAdsManager.prototype.onAdVideoThirdQuartile = function() {\n if(this._isVPAID && this._vpaidCreative && this._vastTracker) {\n this.updateVPAIDProgress();\n }\n if (this.EVENTS.AdVideoThirdQuartile in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdVideoThirdQuartile] === 'function') {\n this._eventCallbacks[this.EVENTS.AdVideoThirdQuartile]();\n }\n }\n};\nAdsManager.prototype.onAdPaused = function() {\n if(this._vastTracker) {\n this._vastTracker.setPaused(true);\n }\n if (this.EVENTS.AdPaused in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdPaused] === 'function') {\n this._eventCallbacks[this.EVENTS.AdPaused]();\n }\n }\n};\nAdsManager.prototype.onAdPlaying = function() {\n if(this._vastTracker) {\n this._vastTracker.setPaused(false);\n }\n if (this.EVENTS.AdPlaying in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdPlaying] === 'function') {\n this._eventCallbacks[this.EVENTS.AdPlaying]();\n }\n }\n};\nAdsManager.prototype.onAdVideoComplete = function() {\n if(this._isVPAID && this._vpaidCreative && this._vastTracker) {\n this._vastTracker.complete();\n }\n if (this.EVENTS.AdVideoComplete in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdVideoComplete] === 'function') {\n this._eventCallbacks[this.EVENTS.AdVideoComplete]();\n }\n }\n}\nAdsManager.prototype.onAllAdsCompleted = function() {\n if (this.EVENTS.AllAdsCompleted in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AllAdsCompleted] === 'function') {\n this._eventCallbacks[this.EVENTS.AllAdsCompleted]();\n }\n }\n}\nAdsManager.prototype.onAdError = function(message) {\n\n this._hasError = true;\n /*\n // Stop and clear timeouts, intervals\n this.stopVASTMediaLoadTimeout();\n this.stopVPAIDProgress();\n */\n this.abort();\n\n if (this.EVENTS.AdError in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdError] === 'function') {\n this._eventCallbacks[this.EVENTS.AdError](typeof message !== 'object' ? new _ad_error__WEBPACK_IMPORTED_MODULE_1__[\"default\"](message) : message);\n }\n }\n\n}\nAdsManager.prototype.onAdLog = function(message) {\n if (this.EVENTS.AdLog in this._eventCallbacks) {\n if(typeof this._eventCallbacks[this.EVENTS.AdLog] === 'function') {\n this._eventCallbacks[this.EVENTS.AdLog](message);\n }\n }\n}\nAdsManager.prototype.processVASTResponse = function(res) {\n\n const ads = res.ads;\n if(ads.length != 0) {\n\n if(ads.length > 1) {\n // Ad pod\n // Filter by sequence\n this._adPod = ads.sort(function(a, b) {\n let aSequence = a.sequence;\n let bSequence = b.sequence;\n if (aSequence === bSequence) {\n return 0;\n } else if (aSequence === null) {\n return 1;\n } else if (bSequence === null) {\n return -1;\n }\n return (aSequence < bSequence) ? -1 : (aSequence > bSequence) ? 1 : 0;\n });\n\n this._ad = ads[0];\n } else {\n // Ad\n this._ad = ads[0];\n }\n\n if(this._ad) {\n\n // Filter linear creatives, get first\n this._creative = ads[0].creatives.filter(creative => creative.type === 'linear')[0];\n // Check if creative has media files\n if(this._creative) {\n\n if(this._creative.mediaFiles.length != 0) {\n // Filter and check media files for mime type canPlay and if VPAID or not\n this._mediaFiles = this._creative.mediaFiles.filter(mediaFile => {\n // mime types -> mp4, webm, ogg, 3gp\n if(this.canPlayVideoType(mediaFile.mimeType)) {\n return mediaFile;\n } else if(mediaFile.mimeType === 'application/javascript') {\n // apiFramework -> mime type -> application/javascript\n return mediaFile;\n }\n });//[0]; // take the first one\n\n // Sort media files by size\n this._mediaFiles.sort(function(a, b) {\n let aHeight = a.height;\n let bHeight = b.height;\n return (aHeight < bHeight) ? -1 : (aHeight > bHeight) ? 1 : 0;\n });\n\n if(this._mediaFiles && this._mediaFiles.length != 0) {\n // TODO: move after adLoaded\n // Init VAST Tracker for tracking events\n this._vastTracker = new _dailymotion_vast_client__WEBPACK_IMPORTED_MODULE_0__.VASTTracker(null, this._ad, this._creative);\n this._vastTracker.load();\n\n // If not VPAID dispatch AdsManagerLoaded event -> ad is ready for init\n this.onAdsManagerLoaded();\n } else {\n // Linear assets were found in the VASt ad response, but none of them match the video player's capabilities.\n this.onAdError(this.ERRORS.VAST_LINEAR_ASSET_MISMATCH);\n }\n\n } else {\n // No assets were found in the VAST ad response.\n this.onAdError(this.ERRORS.VAST_ASSET_NOT_FOUND);\n }\n } else {\n // TODO:\n // Non Linear\n console.log('non linear');\n }\n\n }\n\n } else {\n // The VAST response document is empty.\n this.onAdError(this.ERRORS.VAST_EMPTY_RESPONSE);\n }\n}\nAdsManager.prototype.requestAds = function(vastUrl, options = {}) {\n\n if(this._isDestroyed) {\n return;\n }\n\n // Assign options\n Object.assign(this._options, options);\n\n // VAST options\n // timeout: Number - A custom timeout for the requests (default 120000 ms)\n // withCredentials: Boolean - A boolean to enable the withCredentials options for the XHR URLHandler (default false)\n // wrapperLimit: Number - A number of Wrapper responses that can be received with no InLine response (default 10)\n // resolveAll: Boolean - Allows you to parse all the ads contained in the VAST or to parse them ad by ad or adPod by adPod (default true)\n // allowMultipleAds: Boolean - A Boolean value that identifies whether multiple ads are allowed in the requested VAST response. This will override any value of allowMultipleAds attribute set in the VAST\n // followAdditionalWrappers: Boolean - a Boolean value that identifies whether subsequent Wrappers after a requested VAST response is allowed. This will override any value of followAdditionalWrappers attribute set in the VAST\n const vastOptions = {\n timeout: this._options.vastLoadTimeout,\n withCredentials: this._options.withCredentials,\n wrapperLimit: this._options.wrapperLimit,\n resolveAll: this._options.resolveAll\n };\n\n // Abort\n this.abort();\n\n // Check if vastUrl exists\n if(vastUrl && typeof vastUrl === 'string') {\n\n let isURL = false;\n try {\n new URL(vastUrl);\n isURL = true;\n } catch (e) {\n }\n\n if (isURL) {\n // use VAST URL\n this._vastClient = new _dailymotion_vast_client__WEBPACK_IMPORTED_MODULE_0__.VASTClient();\n this._vastClient\n .get(vastUrl, vastOptions)\n .then(res => {\n this.processVASTResponse(res);\n })\n .catch(err => {\n this.onAdError(err.message);\n });\n } else {\n // use VAST XML\n const vastXml = (new window.DOMParser()).parseFromString(vastUrl, 'text/xml');\n this._vastParser = new _dailymotion_vast_client__WEBPACK_IMPORTED_MODULE_0__.VASTParser();\n this._vastParser\n .parseVAST(vastXml, vastOptions)\n .then(res => {\n this.processVASTResponse(res);\n })\n .catch(err => {\n this.onAdError(err.message);\n });\n }\n } else {\n this.onAdError('VAST URL/XML is empty');\n }\n}\nAdsManager.prototype.canPlayVideoType = function(mimeType) {\n if(mimeType === 'video/3gpp' && this.supportsThreeGPVideo()) {\n return true;\n } else if(mimeType === 'video/webm' && this.supportsWebmVideo()) {\n return true;\n } else if(mimeType === 'video/ogg' && this.supportsOggTheoraVideo()) {\n return true;\n } else if(mimeType === 'video/mp4' && this.supportsH264BaselineVideo()) {\n return true;\n }\n return false;\n}\nAdsManager.prototype.supportsVideo = function() {\n return !!document.createElement('video').canPlayType;\n}\nAdsManager.prototype.supportsH264BaselineVideo = function() {\n if(!this.supportsVideo()) return false;\n return document.createElement('video').canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"');\n}\nAdsManager.prototype.supportsOggTheoraVideo = function() {\n if(!this.supportsVideo()) return false;\n return document.createElement('video').canPlayType('video/ogg; codecs=\"theora, vorbis\"');\n}\nAdsManager.prototype.supportsWebmVideo = function() {\n if(!this.supportsVideo()) return false;\n return document.createElement('video').canPlayType('video/webm; codecs=\"vp8, vorbis\"');\n}\nAdsManager.prototype.supportsThreeGPVideo = function() {\n if(!this.supportsVideo()) return false;\n return document.createElement('video').canPlayType('video/3gpp; codecs=\"mp4v.20.8, samr\"');\n}\nAdsManager.prototype.handshakeVersion = function(version) {\n return this._vpaidCreative.handshakeVersion(version);\n}\nAdsManager.prototype._isCreativeFunctionInvokable = function(a) {\n return this._vpaidCreative ? (a = this._vpaidCreative[a]) && typeof a === 'function' : false;\n}\nAdsManager.prototype.checkVPAIDInterface = function(a) {\n const b = { passed: true, missingInterfaces: ''};\n for (let d = a.length - 1; 0 <= d; d--)\n this._isCreativeFunctionInvokable(a[d]) || (b.passed = false, b.missingInterfaces += a[d] + ' ');\n return b;\n}\nAdsManager.prototype.setCallbacksForCreative = function(eventCallbacks, context) {\n for (const event in eventCallbacks) eventCallbacks.hasOwnProperty(event) && this._vpaidCreative.subscribe(eventCallbacks[event], event, context)\n}\nAdsManager.prototype.removeCallbacksForCreative = function(eventCallbacks) {\n if(this._vpaidCreative !== null) {\n for (const event in eventCallbacks) {\n eventCallbacks.hasOwnProperty(event) && this._vpaidCreative.unsubscribe(event); // && this._vpaidCreative.unsubscribe(eventCallbacks[event], event);\n }\n }\n}\nAdsManager.prototype.creativeAssetLoaded = function() {\n const checkVPAIDMinVersion = () => {\n const c = this.handshakeVersion(this.SUPPORTED_CREATIVE_VPAID_VERSION_MIN.toFixed(1));\n return c ? parseFloat(c) < this.SUPPORTED_CREATIVE_VPAID_VERSION_MIN ? (this.onAdError('Only support creatives with VPAID version >= ' + this.SUPPORTED_CREATIVE_VPAID_VERSION_MIN.toFixed(1)), !1) : !0 : (this.onAdError('Cannot get VPAID version from the creative'), !1)\n };\n if (function(that) {\n const c = that.checkVPAIDInterface('handshakeVersion initAd startAd stopAd subscribe unsubscribe getAdLinear'.split(' '));\n c.passed || that.onAdError('Missing interfaces in the VPAID creative: ' + c.missingInterfaces);\n return c.passed\n }(this) && checkVPAIDMinVersion()) {\n\n // VPAID events\n this._creativeEventCallbacks = {\n AdStarted: this.onAdStarted,\n AdStopped: this.onAdStopped,\n AdSkipped: this.onAdSkipped,\n AdLoaded: this.onAdLoaded,\n //AdLinearChange: this.onAdLinearChange,\n AdSizeChange: this.onAdSizeChange,\n //AdExpandedChange: this.onAdExpandedChange,\n AdDurationChange: this.onAdDurationChange,\n AdVolumeChange: this.onAdVolumeChange,\n AdImpression: this.onAdImpression,\n AdClickThru: this.onAdClickThru,\n //AdInteraction: this.onAdInteraction,\n AdVideoStart: this.onAdVideoStart,\n AdVideoFirstQuartile: this.onAdVideoFirstQuartile,\n AdVideoMidpoint: this.onAdVideoMidpoint,\n AdVideoThirdQuartile: this.onAdVideoThirdQuartile,\n AdVideoComplete: this.onAdVideoComplete,\n //AdUserAcceptInvitation: this.onAdUserAcceptInvitation,\n //AdUserMinimize: this.onAdUserMinimize,\n //AdUserClose: this.onAdUserClose,\n AdPaused: this.onAdPaused,\n AdPlaying: this.onAdPlaying, // onAdResumed\n AdError: this.onAdError,\n AdLog: this.onAdLog\n }\n\n // Subscribe for VPAID events\n this.setCallbacksForCreative(this._creativeEventCallbacks, this);\n\n // Prepare for iniAd\n const width = this._attributes.width;\n const height = this._attributes.height;\n const creativeData = {\n AdParameters: this._creative.adParameters\n };\n const environmentVars = {\n slot: this._slot,\n videoSlot: this._videoSlot,\n videoSlotCanAutoPlay: true\n };\n // iniAd(width, height, viewMode, desiredBitrate, creativeData, environmentVars)\n // Start loadVideoTimeout\n this.startVASTMediaLoadTimeout();\n this._vpaidCreative.initAd(width, height, this._attributes.viewMode, this._attributes.desiredBitrate, creativeData, environmentVars);\n\n }\n}\nAdsManager.prototype._handleCreativeMessage = function(msg) {\n if(msg && msg.data) {\n const match = String(msg.data).match(new RegExp('adm://(.*)'));\n if(match) {\n const value = JSON.parse(match[1]);\n if(value == 'error') {\n clearInterval(this._creativeLoadTimer);\n this.onAdError('Error load VPAID');\n }\n }\n }\n}\nAdsManager.prototype.loadCreativeAsset = function(fileURL) {\n this._vpaidIframe = document.createElement('iframe');\n this._adContainer.appendChild(this._vpaidIframe);\n\n this._vpaidIframe.style.display = 'none';\n this._vpaidIframe.style.width = '0px';\n this._vpaidIframe.style.height = '0px';\n\n window.addEventListener('message', this._handleCreativeMessageFn);\n\n this._vpaidIframe.contentWindow.document.open();\n this._vpaidIframe.contentWindow.document.write(`\n