diff --git a/docs/vast-vpaid.html b/docs/vast-vpaid.html index 943651b0..1bbf26fa 100644 --- a/docs/vast-vpaid.html +++ b/docs/vast-vpaid.html @@ -30,7 +30,7 @@ var adTagUrl = "https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpreonly&cmsid=496&vid=short_onecue&correlator="; - player = cloudinary.videoPlayer('player', { + player1 = cloudinary.videoPlayer('player', { cloud_name: 'demo', ads: { adTagUrl: adTagUrl, @@ -38,12 +38,22 @@ } }); - player.playlistByTag('video_race', { + player1.source('elephants'); + + player2 = cloudinary.videoPlayer('player-playlist', { + cloud_name: 'demo', + ads: { + adTagUrl: adTagUrl, + debug: true + } + }); + + player2.playlistByTag('video_race', { autoAdvance: true, repeat: true, }).then(function() { var divElem = document.querySelector("#playlist-data"); - var list = player.playlist().list().map(function(source) { + var list = player2.playlist().list().map(function(source) { return source.publicId() }).join(', '); @@ -62,17 +72,33 @@
Ads and monetization documentation @@ -84,6 +110,16 @@
- // Initialize player
- var player = cloudinary.videoPlayer('player', {
- cloud_name: 'demo' ,
- plugins: {
- vastClient: {
- adTagUrl: "https://rtr.innovid.com/r1.5554946ab01d97.36996823;cb={random_number}",
- adCancelTimeout: 5000,
- adsEnabled: true,
- playAdAlways: true
- }
+ player1 = cloudinary.videoPlayer('player', {
+ cloud_name: 'demo',
+ ads: {
+ adTagUrl: AD_TAG_URL,
+ debug: true
+ }
+ });
+
+ player1.source('elephants');
+
+ player2 = cloudinary.videoPlayer('player-playlist', {
+ cloud_name: 'demo',
+ ads: {
+ adTagUrl: AD_TAG_URL,
+ debug: true
}
});
- // Pass a sorter to sort list in alphabetical order by publicId
- var sorter = function(a, b) {
- if (a.publicId < b.publicId) return 1;
- if (a.publicId > b.publicId) return -1;
- return 0;
- };
-
- // Fetch playlist by tag. Since this operation involves an API call
- // the function returns a Promise when the operation completes.
- // The return value is 'player'.
- player.playlistByTag('demo', {
- sorter: sorter,
- autoAdvance: 0,
- repeat: true
+ player2.playlistByTag('video_race', {
+ autoAdvance: true,
+ repeat: true,
}).then(function() {
var divElem = document.querySelector("#playlist-data");
- var list = player.playlist().list().map(function(source) {
+ var list = player2.playlist().list().map(function(source) {
return source.publicId()
}).join(', ');
diff --git a/package-lock.json b/package-lock.json
index 0f07f47d..390a5278 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,7 +16,7 @@
"uuid": "^9.0.0",
"video.js": "8.5.2",
"videojs-contrib-ads": "^7.3.2",
- "videojs-ima": "^2.1.0",
+ "videojs-ima": "^2.3.0",
"videojs-per-source-behaviors": "^3.0.0",
"webfontloader": "^1.6.28"
},
@@ -23621,14 +23621,14 @@
"integrity": "sha512-X1LuPfLZPisPLrANIAKCknZbZu5obVM/ylfd1CN+SsCmPZQ3UMDPcvLTpPBJxcBuTpHQq2MO1QCFt7p8spnZ/w=="
},
"node_modules/videojs-ima": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/videojs-ima/-/videojs-ima-2.2.0.tgz",
- "integrity": "sha512-VKg7mZsaiW89ko2Sjfz/sDcCbCTjj2OAkg8CakvCs9ZiVg20g6QYVtEWj249V/HTm0/1X01GEPk9hnIrRzgd+A==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/videojs-ima/-/videojs-ima-2.3.0.tgz",
+ "integrity": "sha512-8r0BZGT+WCTO6PePyKZHikV79Ojqh4yLMx4+DmPyXeRcKUVsQ7Va0R7Ok8GRcA8Zy3l1PM6jzLrD/W1rwKhZ8g==",
"dependencies": {
"@hapi/cryptiles": "^5.1.0",
"can-autoplay": "^3.0.2",
"extend": ">=3.0.2",
- "videojs-contrib-ads": "^6.9.0 || ^7"
+ "videojs-contrib-ads": "^6.9.0"
},
"engines": {
"node": ">=0.8.0"
@@ -23637,6 +23637,151 @@
"video.js": "^5.19.2 || ^6 || ^7 || ^8"
}
},
+ "node_modules/videojs-ima/node_modules/@videojs/http-streaming": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.16.2.tgz",
+ "integrity": "sha512-etPTUdCFu7gUWc+1XcbiPr+lrhOcBu3rV5OL1M+3PDW89zskScAkkcdqYzP4pFodBPye/ydamQoTDScOnElw5A==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/vhs-utils": "3.0.5",
+ "aes-decrypter": "3.1.3",
+ "global": "^4.4.0",
+ "m3u8-parser": "4.8.0",
+ "mpd-parser": "^0.22.1",
+ "mux.js": "6.0.1",
+ "video.js": "^6 || ^7"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=5"
+ },
+ "peerDependencies": {
+ "video.js": "^6 || ^7"
+ }
+ },
+ "node_modules/videojs-ima/node_modules/@videojs/http-streaming/node_modules/video.js": {
+ "version": "7.21.5",
+ "resolved": "https://registry.npmjs.org/video.js/-/video.js-7.21.5.tgz",
+ "integrity": "sha512-WRq86tXZKrThA9mK+IR+v4tIQVVvnb5LhvL71fD2AX7TxVOPdaeK1X/wyuUruBqWaOG3w2sZXoMY6HF2Jlo9qA==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/http-streaming": "2.16.2",
+ "@videojs/vhs-utils": "^3.0.4",
+ "@videojs/xhr": "2.6.0",
+ "aes-decrypter": "3.1.3",
+ "global": "^4.4.0",
+ "keycode": "^2.2.0",
+ "m3u8-parser": "4.8.0",
+ "mpd-parser": "0.22.1",
+ "mux.js": "6.0.1",
+ "safe-json-parse": "4.0.0",
+ "videojs-font": "3.2.0",
+ "videojs-vtt.js": "^0.15.5"
+ }
+ },
+ "node_modules/videojs-ima/node_modules/@videojs/vhs-utils": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz",
+ "integrity": "sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "global": "^4.4.0",
+ "url-toolkit": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=5"
+ }
+ },
+ "node_modules/videojs-ima/node_modules/aes-decrypter": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.1.3.tgz",
+ "integrity": "sha512-VkG9g4BbhMBy+N5/XodDeV6F02chEk9IpgRTq/0bS80y4dzy79VH2Gtms02VXomf3HmyRe3yyJYkJ990ns+d6A==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/vhs-utils": "^3.0.5",
+ "global": "^4.4.0",
+ "pkcs7": "^1.0.4"
+ }
+ },
+ "node_modules/videojs-ima/node_modules/m3u8-parser": {
+ "version": "4.8.0",
+ "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.8.0.tgz",
+ "integrity": "sha512-UqA2a/Pw3liR6Df3gwxrqghCP17OpPlQj6RBPLYygf/ZSQ4MoSgvdvhvt35qV+3NaaA0FSZx93Ix+2brT1U7cA==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/vhs-utils": "^3.0.5",
+ "global": "^4.4.0"
+ }
+ },
+ "node_modules/videojs-ima/node_modules/mpd-parser": {
+ "version": "0.22.1",
+ "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.22.1.tgz",
+ "integrity": "sha512-fwBebvpyPUU8bOzvhX0VQZgSohncbgYwUyJJoTSNpmy7ccD2ryiCvM7oRkn/xQH5cv73/xU7rJSNCLjdGFor0Q==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/vhs-utils": "^3.0.5",
+ "@xmldom/xmldom": "^0.8.3",
+ "global": "^4.4.0"
+ },
+ "bin": {
+ "mpd-to-m3u8-json": "bin/parse.js"
+ }
+ },
+ "node_modules/videojs-ima/node_modules/mux.js": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-6.0.1.tgz",
+ "integrity": "sha512-22CHb59rH8pWGcPGW5Og7JngJ9s+z4XuSlYvnxhLuc58cA1WqGDQPzuG8I+sPm1/p0CdgpzVTaKW408k5DNn8w==",
+ "dependencies": {
+ "@babel/runtime": "^7.11.2",
+ "global": "^4.4.0"
+ },
+ "bin": {
+ "muxjs-transmux": "bin/transmux.js"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=5"
+ }
+ },
+ "node_modules/videojs-ima/node_modules/videojs-contrib-ads": {
+ "version": "6.9.0",
+ "resolved": "https://registry.npmjs.org/videojs-contrib-ads/-/videojs-contrib-ads-6.9.0.tgz",
+ "integrity": "sha512-nzKz+jhCGMTYffSNVYrmp9p70s05v6jUMOY3Z7DpVk3iFrWK4Zi/BIkokDWrMoHpKjdmCdKzfJVBT+CrUj6Spw==",
+ "dependencies": {
+ "global": "^4.3.2",
+ "video.js": "^6 || ^7"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=5"
+ }
+ },
+ "node_modules/videojs-ima/node_modules/videojs-contrib-ads/node_modules/video.js": {
+ "version": "7.21.5",
+ "resolved": "https://registry.npmjs.org/video.js/-/video.js-7.21.5.tgz",
+ "integrity": "sha512-WRq86tXZKrThA9mK+IR+v4tIQVVvnb5LhvL71fD2AX7TxVOPdaeK1X/wyuUruBqWaOG3w2sZXoMY6HF2Jlo9qA==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@videojs/http-streaming": "2.16.2",
+ "@videojs/vhs-utils": "^3.0.4",
+ "@videojs/xhr": "2.6.0",
+ "aes-decrypter": "3.1.3",
+ "global": "^4.4.0",
+ "keycode": "^2.2.0",
+ "m3u8-parser": "4.8.0",
+ "mpd-parser": "0.22.1",
+ "mux.js": "6.0.1",
+ "safe-json-parse": "4.0.0",
+ "videojs-font": "3.2.0",
+ "videojs-vtt.js": "^0.15.5"
+ }
+ },
+ "node_modules/videojs-ima/node_modules/videojs-font": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-3.2.0.tgz",
+ "integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA=="
+ },
"node_modules/videojs-per-source-behaviors": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/videojs-per-source-behaviors/-/videojs-per-source-behaviors-3.0.0.tgz",
diff --git a/package.json b/package.json
index 0269a1ae..73d554ed 100644
--- a/package.json
+++ b/package.json
@@ -76,7 +76,7 @@
"uuid": "^9.0.0",
"video.js": "8.5.2",
"videojs-contrib-ads": "^7.3.2",
- "videojs-ima": "^2.1.0",
+ "videojs-ima": "^2.3.0",
"videojs-per-source-behaviors": "^3.0.0",
"webfontloader": "^1.6.28"
},
diff --git a/src/index.all.js b/src/index.all.js
index 88e8515d..969779ff 100644
--- a/src/index.all.js
+++ b/src/index.all.js
@@ -10,6 +10,7 @@ import cloudinary from './index.js';
export * from './index.js';
export * from './plugins/dash/videojs-dash.js';
+export * from './plugins/ima/ima.js';
export * from './plugins/playlist/playlist.js';
export * from './plugins/styled-text-tracks/styled-text-tracks.js';
export * from './plugins/interaction-areas/interaction-areas.service.js';
diff --git a/src/plugins/ima/ima.js b/src/plugins/ima/ima.js
index a6a4286d..1b8b0f6a 100644
--- a/src/plugins/ima/ima.js
+++ b/src/plugins/ima/ima.js
@@ -1,1775 +1,3 @@
-/* eslint-disable */
-/**
- * Copyright 2014 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * IMA SDK integration plugin for Video.js. For more information see
- * https://www.github.com/googleads/videojs-ima
- */
-
-(function(factory) {
- if (typeof define === 'function' && define['amd']) {
- define(['video.js', 'videojs-contrib-ads'], function(videojs){ factory(window, document, (videojs.default || videojs)) });
- } else if (typeof exports === 'object' && typeof module === 'object') {
- var vjs = require('video.js');
- require('videojs-contrib-ads');
- factory(window, document, vjs);
- } else {
- factory(window, document, videojs);
- }
-})(function(window, document, videojs) {
- "use strict";
-
- var extend = function(obj) {
- var arg;
- var index;
- var key;
- for (index = 1; index < arguments.length; index++) {
- arg = arguments[index];
- for (key in arg) {
- if (arg.hasOwnProperty(key)) {
- obj[key] = arg[key];
- }
- }
- }
- return obj;
- };
-
- var ima_defaults = {
- debug: false,
- timeout: 5000,
- prerollTimeout: 100,
- adLabel: 'Advertisement',
- showControlsForAds: true,
- showControlsForJSAds: true,
- adsRenderingSettings: {
- uiElements: [],
- },
- };
-
- var eventTypes = (videojs.browser.IS_ANDROID || videojs.browser.IS_IOS) ? {
- click: 'touchend',
- mousedown: 'touchstart',
- mouseup: 'touchend',
- mousemove: 'touchmove'
- } : {
- click: 'click',
- mousedown: 'mousedown',
- mouseup: 'mouseup',
- mousemove: 'mousemove'
- };
-
- var init = function(options, readyCallback) {
- this.ima = new ImaPlugin(this, options, readyCallback);
- };
-
- var ImaPlugin = function(player, options, readyCallback) {
- this.player = player;
-
- /**
- * Assigns the unique id and class names to the given element as well as the style class
- * @param element
- * @param controlName
- * @private
- */
- var assignControlAttributes_ = function(element, controlName) {
- element.id = this.controlPrefix + controlName;
- element.className = this.controlPrefix + controlName + ' ' + controlName;
- }.bind(this);
-
- /**
- * Returns a regular expression to test a string for the given className
- * @param className
- * @returns {RegExp}
- * @private
- */
- var getClassRegexp_ = function(className){
- // Matches on
- // (beginning of string OR NOT word char)
- // classname
- // (negative lookahead word char OR end of string)
- return new RegExp('(^|[^A-Za-z-])' + className + '((?![A-Za-z-])|$)', 'gi');
- };
-
- /**
- * Adds a class to the given element if it doesn't already have the class
- * @param element
- * @param classToAdd
- * @private
- */
- var addClass_ = function(element, classToAdd){
- if(getClassRegexp_(classToAdd).test(element.className)){
- return element;
- }
-
- return element.className = element.className.trim() + ' ' + classToAdd;
- };
-
- /**
- * Removes a class from the given element if it has the given class
- * @param element
- * @param classToRemove
- * @private
- */
- var removeClass_ = function(element, classToRemove){
- var classRegexp = getClassRegexp_(classToRemove);
-
- if(!classRegexp.test(element.className)){
- return element;
- }
-
- return element.className = element.className.trim().replace(classRegexp, '');
- };
-
- /**
- * Creates the ad container passed to the IMA SDK.
- * @private
- */
- var createAdContainer_ = function() {
- // The adContainerDiv is the DOM of the element that will house
- // the ads and ad controls.
- this.vjsControls = this.player.getChild('controlBar');
- this.adContainerDiv =
- this.vjsControls.el().parentNode.appendChild(
- document.createElement('div'));
- assignControlAttributes_(this.adContainerDiv, 'ima-ad-container');
- this.adContainerDiv.style.position = "absolute";
- this.adContainerDiv.addEventListener(
- 'mouseenter',
- showAdControls_,
- false);
- this.adContainerDiv.addEventListener(
- 'mouseleave',
- hideAdControls_,
- false);
- createControls_();
- this.adDisplayContainer =
- new google.ima.AdDisplayContainer(this.adContainerDiv, this.contentPlayer);
- this.showAdContainer(!this.settings.manual);
- }.bind(this);
-
- /**
- * Creates the controls for the ad.
- * @private
- */
- var createControls_ = function() {
- this.controlsDiv = document.createElement('div');
- assignControlAttributes_(this.controlsDiv, 'ima-controls-div');
- this.controlsDiv.style.width = '100%';
- this.countdownDiv = document.createElement('div');
- assignControlAttributes_(this.countdownDiv, 'ima-countdown-div');
- this.countdownDiv.innerHTML = this.settings.adLabel;
- this.countdownDiv.style.display = this.showCountdown ? '' : 'none';
- this.seekBarDiv = document.createElement('div');
- assignControlAttributes_(this.seekBarDiv, 'ima-seek-bar-div');
- this.seekBarDiv.style.width = '100%';
- this.progressDiv = document.createElement('div');
- assignControlAttributes_(this.progressDiv, 'ima-progress-div');
- this.playPauseDiv = document.createElement('div');
- assignControlAttributes_(this.playPauseDiv, 'ima-play-pause-div');
- addClass_(this.playPauseDiv, 'ima-playing');
- this.playPauseDiv.addEventListener(
- eventTypes.click,
- onAdPlayPauseClick_,
- false);
- this.muteDiv = document.createElement('div');
- assignControlAttributes_(this.muteDiv, 'ima-mute-div');
- addClass_(this.muteDiv, 'ima-non-muted');
- this.muteDiv.addEventListener(
- eventTypes.click,
- onAdMuteClick_,
- false);
- this.sliderDiv = document.createElement('div');
- assignControlAttributes_(this.sliderDiv, 'ima-slider-div');
- this.sliderDiv.addEventListener(
- eventTypes.mousedown,
- onAdVolumeSliderMouseDown_,
- false);
- this.sliderLevelDiv = document.createElement('div');
- assignControlAttributes_(this.sliderLevelDiv, 'ima-slider-level-div');
- this.fullscreenDiv = document.createElement('div');
- assignControlAttributes_(this.fullscreenDiv, 'ima-fullscreen-div');
- addClass_(this.fullscreenDiv, 'ima-non-fullscreen');
- this.fullscreenDiv.addEventListener(
- eventTypes.click,
- onAdFullscreenClick_,
- false);
- this.adContainerDiv.appendChild(this.controlsDiv);
- this.controlsDiv.appendChild(this.seekBarDiv);
- this.controlsDiv.appendChild(this.playPauseDiv);
- this.controlsDiv.appendChild(this.muteDiv);
- this.controlsDiv.appendChild(this.sliderDiv);
- this.controlsDiv.appendChild(this.fullscreenDiv);
- this.seekBarDiv.appendChild(this.progressDiv);
- this.sliderDiv.appendChild(this.sliderLevelDiv);
- if (this.settings.vjsControls) {
- this.initVjsControls();
- this.controlsDiv.style.display = 'none';
- this.vjsControls.el().appendChild(this.countdownDiv);
- } else {
- this.controlsDiv.appendChild(this.countdownDiv);
- }
- }.bind(this);
-
- this.showAdContainer = function(show) {
- this.adContainerDiv.style.display = show ? 'block' : 'none';
- this.player.toggleClass('vjs-ima-ad', show);
- }.bind(this);
-
- /**
- * Initializes the AdDisplayContainer. On mobile, this must be done as a
- * result of user action.
- */
- this.initializeAdDisplayContainer = function() {
- this.adDisplayContainerInitialized = true;
- this.adDisplayContainer.initialize();
- }.bind(this);
-
- /**
- * Creates the AdsRequest and request ads through the AdsLoader.
- */
- this.requestAds = function() {
- if (!this.adDisplayContainerInitialized) {
- this.adDisplayContainer.initialize();
- }
- var adsRequest = new google.ima.AdsRequest();
- if (this.settings.adTagUrl) {
- adsRequest.adTagUrl = this.settings.adTagUrl;
- } else {
- adsRequest.adsResponse = this.settings.adsResponse;
- }
- if (this.settings.forceNonLinearFullSlot) {
- adsRequest.forceNonLinearFullSlot = true;
- }
-
- adsRequest.linearAdSlotWidth = this.getPlayerWidth();
- adsRequest.linearAdSlotHeight = this.getPlayerHeight();
- adsRequest.nonLinearAdSlotWidth =
- this.settings.nonLinearWidth || this.getPlayerWidth();
- adsRequest.nonLinearAdSlotHeight =
- this.settings.nonLinearHeight || (this.getPlayerHeight() / 3);
- adsRequest.vastLoadTimeout = Math.max(this.settings.prerollTimeout,
- this.settings.postrollTimeout);
-
- this.adsLoader.requestAds(adsRequest);
- }.bind(this);
-
- /**
- * Listener for the ADS_MANAGER_LOADED event. Creates the AdsManager,
- * sets up event listeners, and triggers the 'adsready' event for
- * videojs-ads-contrib.
- * @private
- */
- var onAdsManagerLoaded_ = function(adsManagerLoadedEvent) {
- this.adsManager = adsManagerLoadedEvent.getAdsManager(
- this.contentPlayheadTracker, this.adsRenderingSettings);
-
- this.adsManager.addEventListener(
- google.ima.AdErrorEvent.Type.AD_ERROR,
- onAdError_);
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.AD_BREAK_READY,
- onAdBreakReady_);
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED,
- this.onContentPauseRequested_);
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED,
- this.onContentResumeRequested_);
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.ALL_ADS_COMPLETED,
- onAllAdsCompleted_);
-
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.LOADED,
- onAdLoaded_);
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.STARTED,
- onAdStarted_);
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.CLICK,
- onAdPlayPauseClick_);
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.COMPLETE,
- this.onAdComplete_);
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.SKIPPED,
- this.onAdComplete_);
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.PAUSED,
- this.onAdPaused_);
- this.adsManager.addEventListener(
- google.ima.AdEvent.Type.RESUMED,
- this.onAdResumed_);
-
- var eventsMap = {
- 'load': google.ima.AdEvent.Type.LOADED,
- 'ad-started': google.ima.AdEvent.Type.STARTED,
- 'click': google.ima.AdEvent.Type.CLICK,
- 'ad-ended': google.ima.AdEvent.Type.COMPLETE,
- 'ad-skipped': google.ima.AdEvent.Type.SKIPPED,
- 'first-quartile': google.ima.AdEvent.Type.FIRST_QUARTILE,
- 'midpoint': google.ima.AdEvent.Type.MIDPOINT,
- 'third-quartile': google.ima.AdEvent.Type.THIRD_QUARTILE,
- 'impression': google.ima.AdEvent.Type.IMPRESSION,
- 'pause': google.ima.AdEvent.Type.PAUSED,
- 'play': google.ima.AdEvent.Type.RESUMED,
- 'mute': google.ima.AdEvent.Type.VOLUME_MUTED,
- 'allpods-completed': google.ima.AdEvent.Type.ALL_ADS_COMPLETED
- };
-
- Object.keys(eventsMap).forEach(function(event){
- this.adsManager.addEventListener(eventsMap[event], function(){
- this.player.trigger('ads-'+event);
- }.bind(this));
-
- }.bind(this));
-
- setAdMuted(this.player.muted());
-
- if (!this.autoPlayAdBreaks) {
- try {
- var initWidth = this.getPlayerWidth();
- var initHeight = this.getPlayerHeight();
- this.adsManagerDimensions.width = initWidth;
- this.adsManagerDimensions.height = initHeight;
- this.adsManager.init(
- initWidth,
- initHeight,
- google.ima.ViewMode.NORMAL);
- this.adsManager.setVolume(this.player.muted() ? 0 : this.player.volume());
- } catch (adError) {
- onAdError_(adError);
- }
- }
-
- var cuepoints = this.adsManager.getCuePoints();
- var foundpreroll = !cuepoints.length; // no playlist, just preroll
- var foundpostroll = false;;
- cuepoints.forEach(function(offset){
- if (!offset)
- foundpreroll = true;
- else if (offset==-1)
- foundpostroll = true;
- });
- if (!foundpreroll)
- this.player.trigger('nopreroll');
- if (!foundpostroll)
- this.player.trigger('nopostroll');
- if (cuepoints.length)
- this.player.trigger('ads-cuepoints', cuepoints);
-
- this.player.trigger('adsready');
- }.bind(this);
-
- /**
- * DEPRECATED: Use startFromReadyCallback
- * Start ad playback, or content video playback in the absence of a
- * pre-roll.
- */
- this.start = function() {
- window.console.log(
- 'WARNING: player.ima.start is deprecated. Use ' +
- 'player.ima.startFromReadyCallback instead.');
- };
-
- /**
- * Start ad playback, or content video playback in the absence of a
- * pre-roll. **NOTE**: This method only needs to be called if you provide
- * your own readyCallback as the second parameter to player.ima(). If you
- * only provide options and do not provide your own readyCallback,
- * **DO NOT** call this method. If you do provide your own readyCallback,
- * you should call this method in the last line of that callback. For more
- * info, see this method's usage in our advanced and playlist examples.
- */
- this.startFromReadyCallback = function() {
- if (this.autoPlayAdBreaks && this.adsManager) {
- try {
- this.adsManager.init(
- this.getPlayerWidth(),
- this.getPlayerHeight(),
- google.ima.ViewMode.NORMAL);
- this.adsManager.setVolume(this.player.muted() ? 0 : this.player.volume());
- this.adsManager.start();
- } catch (adError) {
- onAdError_(adError);
- }
- }
- }.bind(this);
-
- /**
- * Listener for errors fired by the AdsLoader.
- * @param {google.ima.AdErrorEvent} event The error event thrown by the
- * AdsLoader. See
- * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdError.Type
- * @private
- */
- var onAdsLoaderError_ = function(event) {
- console.log('AdsLoader error: ' + event.getError());
- this.showAdContainer(false);
- if (this.adsManager) {
- this.adsManager.destroy();
- }
- this.player.trigger({type: 'adserror', data: { AdError: event.getError(), AdErrorEvent: event }});
- }.bind(this);
-
- /**
- * Listener for errors thrown by the AdsManager.
- * @param {google.ima.AdErrorEvent} adErrorEvent The error event thrown by
- * the AdsManager.
- * @private
- */
- var onAdError_ = function(adErrorEvent) {
- var errorMessage = adErrorEvent.getError !== undefined ? adErrorEvent.getError() : adErrorEvent.stack;
- console.log('Ad error: ' + errorMessage);
- this.adsActive = false;
- this.adPlaying = false;
- this.restoreLoop();
- this.vjsControls.show();
- this.adsManager.destroy();
- this.showAdContainer(false);
- this.updateVjsControls();
- this.player.trigger({ type: 'adserror', data: { AdError: errorMessage, AdErrorEvent: adErrorEvent }});
- }.bind(this);
-
- /**
- * Listener for AD_BREAK_READY. Passes event on to publisher's listener.
- * @param {google.ima.AdEvent} adEvent AdEvent thrown by the AdsManager.
- * @private
- */
- var onAdBreakReady_ = function(adEvent) {
- this.adBreakReadyListener(adEvent);
- }.bind(this);
-
- /**
- * Called by publishers in manual ad break playback mode to start an ad
- * break.
- */
- this.playAdBreak = function() {
- if (!this.autoPlayAdBreaks) {
- this.adsManager.start();
- }
- }.bind(this);
-
- this.resetLoop = function() {
- this.contentLoop = this.contentPlayer && this.contentPlayer.loop;
- if (this.contentLoop) {
- this.contentPlayer.loop = false;
- }
- }.bind(this);
-
- this.restoreLoop = function() {
- if (this.contentLoop) {
- this.contentPlayer.loop = true;
- this.contentLoop = false;
- }
- }.bind(this);
-
- /**
- * Pauses the content video and displays the ad container so ads can play.
- * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
- * @private
- */
- this.onContentPauseRequested_ = function(adEvent) {
- this.contentSource = this.player.currentSrc();
- this.resetLoop();
- this.player.off('contentended', this.localContentEndedListener);
- this.player.ads.startLinearAdMode();
- this.showAdContainer(true);
-
- var contentType = adEvent.getAd().getContentType();
- if (!this.settings.vjsControls || !this.settings.showControlsForAds){
- if (!this.settings.showControlsForAds
- || ((contentType === 'application/javascript') && !this.settings.showControlsForJSAds)) {
- this.controlsDiv.style.display = 'none';
- } else {
- this.controlsDiv.style.display = 'block';
- }
- this.vjsControls.hide();
- }
- showPlayButton();
- this.player.pause();
- this.adsActive = true;
- this.adPlaying = true;
- this.updateVjsControls();
- }.bind(this);
-
- /**
- * Resumes content video and hides the ad container.
- * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
- * @private
- */
- this.onContentResumeRequested_ = function(adEvent) {
- this.contentResumeTimer = clearTimeout(this.contentResumeTimer);
- this.restoreLoop();
- this.adsActive = false;
- this.adPlaying = false;
- this.player.on('contentended', this.localContentEndedListener);
- if (this.currentAd == null || // hide for post-roll only playlist
- this.currentAd.isLinear()) { // don't hide for non-linear ads
- this.showAdContainer(false);
- }
- this.vjsControls.show();
- this.player.ads.endLinearAdMode();
- this.countdownDiv.innerHTML = '';
- this.updateVjsControls();
- }.bind(this);
-
- /**
- * Records that ads have completed and calls contentAndAdsEndedListeners
- * if content is also complete.
- * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
- * @private
- */
- var onAllAdsCompleted_ = function(adEvent) {
- this.allAdsCompleted = true;
- this.showAdContainer(false);
- if (this.contentComplete == true) {
- if (this.contentPlayer.src && !/^blob:/.test(this.contentPlayer.src) &&
- this.contentSource && this.contentPlayer.src != this.contentSource) {
- this.player.src(this.contentSource);
- }
- this.player.trigger('')
- for (var index in this.contentAndAdsEndedListeners) {
- this.contentAndAdsEndedListeners[index]();
- }
- }
- }.bind(this);
-
- /**
- * Starts the content video when a non-linear ad is loaded.
- * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
- * @private
- */
- var onAdLoaded_ = function(adEvent) {
- if (!adEvent.getAd().isLinear() && !this.player.ended()) {
- this.player.ads.endLinearAdMode();
- this.player.play();
- }
- }.bind(this);
-
- /**
- * Starts the interval timer to check the current ad time when an ad starts
- * playing.
- * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
- * @private
- */
- var onAdStarted_ = function(adEvent) {
- this.currentAd = adEvent.getAd();
- if (this.currentAd.isLinear()) {
- this.adTrackingTimer = setInterval(
- onAdPlayheadTrackerInterval_, 250);
- // Don't bump container when controls are shown
- removeClass_(this.adContainerDiv, 'bumpable-ima-ad-container');
- } else {
- // Bump container when controls are shown
- addClass_(this.adContainerDiv, 'bumpable-ima-ad-container');
- this.player.addClass('vjs-ima-non-linear');
- this.showAdContainer(true);
- }
- }.bind(this);
-
- /**
- * Clears the interval timer for current ad time when an ad completes.
- * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
- * @private
- */
- this.onAdComplete_ = function(adEvent) {
- if (this.currentAd.isLinear()) {
- clearInterval(this.adTrackingTimer);
- var pod = this.currentAd.getAdPodInfo();
- if (pod && pod.getAdPosition() < pod.getTotalAds()) {
- this.player.trigger('ads-pod-ended')
- return;
- }
-
- // this is the final ad so we excpect ima sdk to trigger
- // CONTENT_RESUME_REQUESTED, but for some reason it isn't triggered
- // reliably on iOS, so we fake it
-
- this.contentResumeTimer = setTimeout(function(){
- this.onContentResumeRequested_(null);
- }.bind(this), 1000);
- } else {
- this.player.removeClass('vjs-ima-non-linear');
- }
- }.bind(this);
-
- this.onAdPaused_ = function(adEvent) {
- showPauseButton();
- this.adPlaying = false;
- }.bind(this);
-
- this.onAdResumed_ = function(adEvent) {
- showPlayButton();
- this.adPlaying = true;
- }.bind(this);
-
- var formatTime = function(time) {
- var m = Math.floor(time / 60);
- var s = Math.floor(time % 60);
- if (s.toString().length < 2) {
- s = '0' + s;
- }
- return m + ':' + s;
- };
-
- /**
- * Gets the current time and duration of the ad and calls the method to
- * update the ad UI.
- * @private
- */
- var onAdPlayheadTrackerInterval_ = function() {
- var remainingTime = this.adsManager.getRemainingTime();
- var duration = this.currentAd.getDuration();
- var currentTime = duration - remainingTime;
- currentTime = currentTime > 0 ? currentTime : 0;
- var isPod = false;
- var totalAds = 0;
- var adPosition;
- if (this.currentAd.getAdPodInfo()) {
- isPod = true;
- adPosition = this.currentAd.getAdPodInfo().getAdPosition();
- totalAds = this.currentAd.getAdPodInfo().getTotalAds();
- }
-
- // Update countdown timer data
- var podCount = ': ';
- if (isPod && (totalAds > 1)) {
- podCount = ' (' + adPosition + ' of ' + totalAds + '): ';
- }
- this.countdownDiv.innerHTML =
- this.settings.adLabel + podCount + formatTime(remainingTime);
-
- // Update UI
- var playProgressRatio = currentTime / duration;
- var playProgressPercent = playProgressRatio * 100;
- this.progressDiv.style.width = playProgressPercent + '%';
- this.updateVjsControls();
- }.bind(this);
-
- this.getPlayerWidth = function() {
- var retVal = parseInt(getComputedStyle(this.player.el()).width, 10) ||
- this.player.width();
- return retVal;
- }.bind(this);
-
- this.getPlayerHeight = function() {
- var retVal = parseInt(getComputedStyle(this.player.el()).height, 10) ||
- this.player.height();
- return retVal;
- }.bind(this);
-
- /**
- * Hides the ad controls on mouseout.
- * @private
- */
- var hideAdControls_ = function() {
- this.controlsDiv.style.height = '14px';
- this.playPauseDiv.style.display = 'none';
- this.muteDiv.style.display = 'none';
- this.sliderDiv.style.display = 'none';
- this.fullscreenDiv.style.display = 'none';
- }.bind(this);
-
- /**
- * Shows ad controls on mouseover.
- * @private
- */
- var showAdControls_ = function() {
- this.controlsDiv.style.height = '37px';
- this.playPauseDiv.style.display = 'block';
- this.muteDiv.style.display = 'block';
- this.sliderDiv.style.display = 'block';
- this.fullscreenDiv.style.display = 'block';
- }.bind(this);
-
- /**
- * Show pause and hide play button
- */
- var showPauseButton = function() {
- addClass_(this.playPauseDiv, 'ima-paused');
- removeClass_(this.playPauseDiv, 'ima-playing');
- }.bind(this);
-
- /**
- * Show play and hide pause button
- */
- var showPlayButton = function() {
- addClass_(this.playPauseDiv, 'ima-playing');
- removeClass_(this.playPauseDiv, 'ima-paused');
- }.bind(this);
-
- /**
- * Listener for clicks on the play/pause button during ad playback.
- * @private
- */
- var onAdPlayPauseClick_ = function() {
- if (this.adPlaying) {
- showPauseButton();
- this.adsManager.pause();
- this.adPlaying = false;
- } else {
- showPlayButton();
- this.adsManager.resume();
- this.adPlaying = true;
- }
- }.bind(this);
-
- /**
- * Listener for clicks on the mute button during ad playback.
- * @private
- */
- var onAdMuteClick_ = function() {
- setAdMuted(!this.adMuted);
- }.bind(this);
-
- /* Listener for mouse down events during ad playback. Used for volume.
- * @private
- */
- var onAdVolumeSliderMouseDown_ = function() {
- document.addEventListener(eventTypes.mouseup, onMouseUp_, false);
- document.addEventListener(eventTypes.mousemove, onMouseMove_, false);
- };
-
- /* Mouse movement listener used for volume slider.
- * @private
- */
- var onMouseMove_ = function(event) {
- setVolumeSlider_(event);
- };
-
- /* Mouse release listener used for volume slider.
- * @private
- */
- var onMouseUp_ = function(event) {
- setVolumeSlider_(event);
- document.removeEventListener(eventTypes.mousemove, onMouseMove_);
- document.removeEventListener(eventTypes.mouseup, onMouseUp_);
- };
-
- /* Utility function to set volume and associated UI
- * @private
- */
- var setVolumeSlider_ = function(event) {
- var clientX = event.changedTouches ? event.changedTouches[0].clientX :
- event.clientX;
- var percent = (clientX - this.sliderDiv.getBoundingClientRect().left) /
- this.sliderDiv.offsetWidth;
- percent *= 100;
- //Bounds value 0-100 if mouse is outside slider region.
- percent = Math.min(Math.max(percent, 0), 100);
- this.sliderLevelDiv.style.width = percent + "%";
- this.player.volume(percent / 100); //0-1
- this.adsManager.setVolume(percent / 100);
- if (this.player.volume() == 0) {
- addClass_(this.muteDiv, 'ima-muted');
- removeClass_(this.muteDiv, 'ima-non-muted');
- this.player.muted(true);
- this.adMuted = true;
- }
- else
- {
- addClass_(this.muteDiv, 'ima-non-muted');
- removeClass_(this.muteDiv, 'ima-muted');
- this.player.muted(false);
- this.adMuted = false;
- }
- }.bind(this);
-
- /**
- * Listener for clicks on the fullscreen button during ad playback.
- * @private
- */
- var onAdFullscreenClick_ = function() {
- if (this.player.isFullscreen()) {
- this.player.exitFullscreen();
- } else {
- this.player.requestFullscreen();
- }
- }.bind(this);
-
- /**
- * Listens for the video.js player to change its fullscreen status. This
- * keeps the fullscreen-ness of the AdContainer in sync with the player.
- * @private
- */
- var onFullscreenChange_ = function() {
- if (this.player.isFullscreen()) {
- addClass_(this.fullscreenDiv, 'ima-fullscreen');
- removeClass_(this.fullscreenDiv, 'ima-non-fullscreen');
- if (this.adsManager) {
- this.adsManager.resize(
- window.screen.width,
- window.screen.height,
- google.ima.ViewMode.FULLSCREEN);
- }
- } else {
- addClass_(this.fullscreenDiv, 'ima-non-fullscreen');
- removeClass_(this.fullscreenDiv, 'ima-fullscreen');
- if (this.adsManager) {
- this.adsManager.resize(
- this.getPlayerWidth(),
- this.getPlayerHeight(),
- google.ima.ViewMode.NORMAL);
- }
- }
- }.bind(this);
-
- /**
- * Listens for the video.js player to change its volume. This keeps the ad
- * volume in sync with the content volume if the volume of the player is
- * changed while content is playing
- * @private
- */
- var onVolumeChange_ = function() {
- var newVolume = this.player.muted() ? 0 : this.player.volume();
- if (this.adsManager) {
- this.adsManager.setVolume(newVolume);
- }
- // Update UI
- if (newVolume == 0) {
- this.adMuted = true;
- addClass_(this.muteDiv, 'ima-muted');
- removeClass_(this.muteDiv, 'ima-non-muted');
- this.sliderLevelDiv.style.width = '0%';
- } else {
- this.adMuted = false;
- addClass_(this.muteDiv, 'ima-non-muted');
- removeClass_(this.muteDiv, 'ima-muted');
- this.sliderLevelDiv.style.width = newVolume * 100 + '%';
- }
- }.bind(this);
-
- /**
- * Seeks content to 00:00:00. This is used as an event handler for the
- * loadedmetadata event, since seeking is not possible until that event has
- * fired.
- * @private
- */
- var seekContentToZero_ = function() {
- this.player.off('loadedmetadata', seekContentToZero_);
- this.player.currentTime(0);
- }.bind(this);
-
- /**
- * Seeks content to 00:00:00 and starts playback. This is used as an event
- * handler for the loadedmetadata event, since seeking is not possible until
- * that event has fired.
- * @private
- */
- var playContentFromZero_ = function() {
- this.player.off('loadedmetadata', playContentFromZero_);
- this.player.currentTime(0);
- this.player.play();
- }.bind(this);
-
- /**
- * Destroys the AdsManager, sets it to null, and calls contentComplete to
- * reset correlators. Once this is done it requests ads again to keep the
- * inventory available.
- * @private
- */
- var resetIMA_ = function() {
- this.adsActive = false;
- this.adPlaying = false;
- this.restoreLoop();
- this.player.on('contentended', this.localContentEndedListener);
- if (this.currentAd && this.currentAd.isLinear()) {
- this.showAdContainer(false);
- }
- this.vjsControls.show();
- this.player.ads.endLinearAdMode();
- this.contentPlayheadTracker.currentTime = 0;
- this.countdownDiv.innerHTML = '';
- this.updateVjsControls();
- if (this.adTrackingTimer) {
- // If this is called while an ad is playing, stop trying to get that
- // ad's current time.
- clearInterval(this.adTrackingTimer);
- }
- if (this.adsManager) {
- this.adsManager.destroy();
- this.adsManager = null;
- }
- if (this.adsLoader && !this.contentComplete) {
- this.adsLoader.contentComplete();
- }
- this.contentComplete = false;
- this.allAdsCompleted = false;
- }.bind(this);
-
- /**
- * Ads an EventListener to the AdsManager. For a list of available events,
- * see
- * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type
- * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to listen.
- * @param {function} callback The method to call when the event is fired.
- */
- this.addEventListener = function(event, callback) {
- if (this.adsManager) {
- this.adsManager.addEventListener(event, callback);
- }
- }.bind(this);
-
- /**
- * Returns the instance of the AdsManager.
- * @return {google.ima.AdsManager} The AdsManager being used by the plugin.
- */
- this.getAdsManager = function() {
- return this.adsManager;
- }.bind(this);
-
- /**
- * DEPRECATED: Use setContentWithAdTag.
- * Sets the content of the video player. You should use this method instead
- * of setting the content src directly to ensure the proper ad tag is
- * requested when the video content is loaded.
- * @param {?string} contentSrc The URI for the content to be played. Leave
- * blank to use the existing content.
- * @param {?string} adTag The ad tag to be requested when the content loads.
- * Leave blank to use the existing ad tag.
- * @param {?boolean} playOnLoad True to play the content once it has loaded,
- * false to only load the content but not start playback.
- */
- this.setContent = function(contentSrc, adTag, playOnLoad) {
- window.console.log(
- 'WARNING: player.ima.setContent is deprecated. Use ' +
- 'player.ima.setContentWithAdTag instead.');
- this.setContentWithAdTag(contentSrc, adTag, playOnLoad);
- }.bind(this);
-
- /**
- * Sets the content of the video player. You should use this method instead
- * of setting the content src directly to ensure the proper ad tag is
- * requested when the video content is loaded.
- * @param {?string} contentSrc The URI for the content to be played. Leave
- * blank to use the existing content.
- * @param {?string} adTag The ad tag to be requested when the content loads.
- * Leave blank to use the existing ad tag.
- * @param {?boolean} playOnLoad True to play the content once it has loaded,
- * false to only load the content but not start playback.
- */
- this.setContentWithAdTag = function(contentSrc, adTag, playOnLoad) {
- resetIMA_();
- this.settings.adTagUrl = adTag ? adTag : this.settings.adTagUrl;
- changeSource_(contentSrc, playOnLoad);
- }.bind(this);
-
- /**
- * Sets the content of the video player. You should use this method instead
- * of setting the content src directly to ensure the proper ads response is
- * used when the video content is loaded.
- * @param {?string} contentSrc The URI for the content to be played. Leave
- * blank to use the existing content.
- * @param {?string} adsResponse The ads response to be requested when the
- * content loads. Leave blank to use the existing ads response.
- * @param {?boolean} playOnLoad True to play the content once it has loaded,
- * false to only load the content but not start playback.
- */
- this.setContentWithAdsResponse = function(contentSrc, adsResponse, playOnLoad) {
- resetIMA_();
- this.settings.adsResponse = adsResponse ? adsResponse : this.settings.adsResponse;
- changeSource_(contentSrc, playOnLoad);
- }.bind(this);
-
- /**
- * Plays an ad immediately
- * @param {?string} adTag The ad tag to be requested.
- * Leave blank to use the existing ad tag.
- */
- this.playAd = function(adTag) {
- resetIMA_();
- this.settings.adTagUrl = adTag ? adTag : this.settings.adTagUrl;
- // this.showAdContainer(true);
- // this.vjsControls.hide();
- this.requestAds();
- }.bind(this);
-
- /**
- * Changes the player source.
- * @param {?string} contentSrc The URI for the content to be played. Leave
- * blank to use the existing content.
- * @param {?boolean} playOnLoad True to play the content once it has loaded,
- * false to only load the content but not start playback.
- * @private
- */
- var changeSource_ = function(contentSrc, playOnLoad) {
- // Only try to pause the player when initialised with a source already
- if (!!this.player.currentSrc()) {
- this.player.currentTime(0);
- this.player.pause();
- }
- if (contentSrc) {
- this.player.src(contentSrc);
- }
- if (playOnLoad) {
- this.player.on('loadedmetadata', playContentFromZero_);
- } else {
- this.player.on('loadedmetadata', seekContentToZero_);
- }
- }.bind(this);
-
- var setAdMuted = function(mute) {
- if (mute) {
- addClass_(this.muteDiv, 'ima-muted');
- removeClass_(this.muteDiv, 'ima-non-muted');
- this.adsManager.setVolume(0);
- // Bubble down to content player
- this.player.muted(true);
- this.adMuted = true;
- this.sliderLevelDiv.style.width = "0%";
- } else {
- addClass_(this.muteDiv, 'ima-non-muted');
- removeClass_(this.muteDiv, 'ima-muted');
- this.adsManager.setVolume(this.player.volume());
- // Bubble down to content player
- this.player.muted(false);
- this.adMuted = false;
- this.sliderLevelDiv.style.width = this.player.volume() * 100 + "%";
- }
- }.bind(this);
- /**
- * Adds a listener for the 'contentended' event of the video player. This should be
- * used instead of setting an 'contentended' listener directly to ensure that the
- * ima can do proper cleanup of the SDK before other event listeners
- * are called.
- * @param {function} listener The listener to be called when content completes.
- */
- this.addContentEndedListener = function(listener) {
- this.contentEndedListeners.push(listener);
- }.bind(this);
-
- /**
- * Adds a listener that will be called when content and all ads have
- * finished playing.
- * @param {function} listener The listener to be called when content and ads complete.
- */
- this.addContentAndAdsEndedListener = function(listener) {
- this.contentAndAdsEndedListeners.push(listener);
- }.bind(this);
-
- /**
- * Sets the listener to be called to trigger manual ad break playback.
- * @param {function} listener The listener to be called to trigger manual ad break playback.
- */
- this.setAdBreakReadyListener = function(listener) {
- this.adBreakReadyListener = listener;
- }.bind(this);
-
- /**
- * Pauses the ad.
- */
- this.pauseAd = function() {
- if (this.adsActive && this.adPlaying) {
- showPauseButton();
- this.adsManager.pause();
- this.adPlaying = false;
- }
- }.bind(this);
-
- /**
- * Resumes the ad.
- */
- this.resumeAd = function() {
- if (this.adsActive && !this.adPlaying) {
- showPlayButton();
- this.adsManager.resume();
- this.adPlaying = true;
- }
- }.bind(this);
-
- /**
- * Set up intervals to check for seeking and update current video time.
- * @private
- */
- var setUpPlayerIntervals_ = function() {
- this.updateTimeIntervalHandle =
- setInterval(updateCurrentTime_, this.seekCheckInterval);
- this.seekCheckIntervalHandle =
- setInterval(checkForSeeking_, this.seekCheckInterval);
- this.resizeCheckIntervalHandle =
- setInterval(checkForResize_, this.resizeCheckInterval);
- }.bind(this);
-
- /**
- * Updates the start time of the video
- * @private
- */
- var updateStartTime_ = function(){
- var cur = this.player.currentTime();
- if (!cur || this.player.ads.state!='content-playback')
- return;
- // first time that isn't zero is our start time, but only if it's
- // more than the 1sec
- if (cur<1)
- cur = 0;
- this.contentPlayheadTracker.startTime = cur;
- this.player.off('timeupdate', updateStartTime_);
- }.bind(this);
-
- /**
- * Updates the current time of the video
- * @private
- */
- var updateCurrentTime_ = function() {
- if (this.player.ads.state=='content-playback' &&
- !this.contentPlayheadTracker.seeking &&
- this.contentPlayheadTracker.startTime>=0) {
- this.contentPlayheadTracker.currentTime = this.player.currentTime() -
- this.contentPlayheadTracker.startTime;
- }
- }.bind(this);
-
- /**
- * Detects when the user is seeking through a video.
- * This is used to prevent mid-rolls from playing while a user is seeking.
- *
- * There *is* a seeking property of the HTML5 video element, but it's not
- * properly implemented on all platforms (e.g. mobile safari), so we have to
- * check ourselves to be sure.
- *
- * @private
- */
- var checkForSeeking_ = function() {
- if (this.player.ads.state!='content-playback')
- return;
- var tempCurrentTime = this.player.currentTime();
- var diff = (tempCurrentTime - this.contentPlayheadTracker.previousTime) * 1000;
- if (Math.abs(diff) > this.seekCheckInterval + this.seekThreshold) {
- this.contentPlayheadTracker.seeking = true;
- } else {
- this.contentPlayheadTracker.seeking = false;
- }
- this.contentPlayheadTracker.previousTime = this.player.currentTime();
- }.bind(this);
-
- /**
- * Detects when the player is resized (for fluid support) and resizes the
- * ads manager to match.
- *
- * @private
- */
- var checkForResize_ = function() {
- var currentWidth = this.getPlayerWidth();
- var currentHeight = this.getPlayerHeight();
-
- if (this.adsManager && (currentWidth != this.adsManagerDimensions.width ||
- currentHeight != this.adsManagerDimensions.height)) {
- this.adsManagerDimensions.width = currentWidth;
- this.adsManagerDimensions.height = currentHeight;
- this.adsManager.resize(currentWidth, currentHeight, google.ima.ViewMode.NORMAL);
- }
- }.bind(this);
-
- /**
- * Changes the flag to show or hide the ad countdown timer.
- *
- * @param {boolean} showCountdownIn Show or hide the countdown timer.
- */
- this.setShowCountdown = function(showCountdownIn) {
- this.showCountdown = showCountdownIn;
- this.countdownDiv.style.display = this.showCountdown ? '' : 'none';
- }.bind(this);
-
- /**
- * Current plugin version.
- */
- this.VERSION = '0.2.0';
-
- /**
- * Stores user-provided settings.
- */
- this.settings;
-
- /**
- * Used to prefix videojs ima
- */
- this.controlPrefix;
-
- /**
- * Video element playing content.
- */
- this.contentPlayer;
-
- /**
- * Boolean flag to show or hide the ad countdown timer.
- */
- this.showCountdown;
-
- /**
- * Boolena flag to enable manual ad break playback.
- */
- this.autoPlayAdBreaks;
-
- /**
- * Video.js control bar.
- */
- this.vjsControls;
-
- /**
- * Div used as an ad container.
- */
- this.adContainerDiv;
-
- /**
- * Div used to display ad controls.
- */
- this.controlsDiv;
-
- /**
- * Div used to display ad countdown timer.
- */
- this.countdownDiv;
-
- /**
- * Div used to display add seek bar.
- */
- this.seekBarDiv;
-
- /**
- * Div used to display ad progress (in seek bar).
- */
- this.progressDiv;
-
- /**
- * Div used to display ad play/pause button.
- */
- this.playPauseDiv;
-
- /**
- * Div used to display ad mute button.
- */
- this.muteDiv;
-
- /**
- * Div used by the volume slider.
- */
- this.sliderDiv;
-
- /**
- * Volume slider level visuals
- */
- this.sliderLevelDiv;
-
- /**
- * Div used to display ad fullscreen button.
- */
- this.fullscreenDiv;
-
- /**
- * IMA SDK AdDisplayContainer.
- */
- this.adDisplayContainer;
-
- /**
- * True if the AdDisplayContainer has been initialized. False otherwise.
- */
- this.adDisplayContainerInitialized = false;
-
- /**
- * IMA SDK AdsLoader
- */
- this.adsLoader;
-
- /**
- * IMA SDK AdsManager
- */
- this.adsManager;
-
- /**
- * IMA SDK AdsRenderingSettings.
- */
- this.adsRenderingSettings = null;
-
- /**
- * Ad tag URL. Should return VAST, VMAP, or ad rules.
- */
- this.adTagUrl;
-
- /**
- * VAST, VMAP, or ad rules response. Used in lieu of fetching a response
- * from an ad tag URL.
- */
- this.adsResponse;
-
- /**
- * Current IMA SDK Ad.
- */
- this.currentAd;
-
- /**
- * Timer used to track content progress.
- */
- this.contentTrackingTimer;
-
- /**
- * Timer used to track ad progress.
- */
- this.adTrackingTimer;
-
- /**
- * True if ads are currently displayed, false otherwise.
- * True regardless of ad pause state if an ad is currently being displayed.
- */
- this.adsActive = false;
-
- /**
- * True if ad is currently playing, false if ad is paused or ads are not
- * currently displayed.
- */
- this.adPlaying = false;
-
- /**
- * True if the ad is muted, false otherwise.
- */
- this.adMuted = false;
-
- /**
- * True if our content video has completed, false otherwise.
- */
- this.contentComplete = false;
-
- /**
- * True if ALL_ADS_COMPLETED has fired, false until then.
- */
- this.allAdsCompleted = false;
-
- /**
- * Handle to interval that repeatedly updates current time.
- */
- this.updateTimeIntervalHandle;
-
- /**
- * Handle to interval that repeatedly checks for seeking.
- */
- this.seekCheckIntervalHandle;
-
- /**
- * Interval (ms) on which to check if the user is seeking through the
- * content.
- */
- this.seekCheckInterval = 1000;
-
- /**
- * Handle to interval that repeatedly checks for player resize.
- */
- this.resizeCheckIntervalHandle;
-
- /**
- * Interval (ms) to check for player resize for fluid support.
- */
- this.resizeCheckInterval = 250;
-
- /**
- * Threshold by which to judge user seeking. We check every 1000 ms to see
- * if the user is seeking. In order for us to decide that they are *not*
- * seeking, the content video playhead must only change by 900-1100 ms
- * between checks. Any greater change and we assume the user is seeking
- * through the video.
- */
- this.seekThreshold = 100;
-
- /**
- * Stores data for the content playhead tracker.
- */
- this.contentPlayheadTracker = {
- currentTime: 0,
- previousTime: 0,
- seeking: false,
- duration: 0,
- startTime: -1
- };
-
- /**
- * Stores data for the ad playhead tracker.
- */
- this.adPlayheadTracker = {
- currentTime: 0,
- duration: 0,
- isPod: false,
- adPosition: 0,
- totalAds: 0
- };
-
- /**
- * Stores the dimensions for the ads manager.
- */
- this.adsManagerDimensions = {
- width: 0,
- height: 0
- };
-
- /**
- * Content ended listeners passed by the publisher to the plugin. Publishers
- * should allow the plugin to handle content ended to ensure proper support
- * of custom ad playback.
- */
- this.contentEndedListeners = [];
-
- /**
- * Content and ads ended listeners passed by the publisher to the plugin.
- * These will be called when the plugin detects that content *and all
- * ads* have completed. This differs from the contentEndedListeners in that
- * contentEndedListeners will fire between content ending and a post-roll
- * playing, whereas the contentAndAdsEndedListeners will fire after the
- * post-roll completes.
- */
- this.contentAndAdsEndedListeners = [];
-
- /**
- * Listener to be called to trigger manual ad break playback.
- */
- this.adBreakReadyListener = function() {
- console.log('Please set adBreakReadyListener');
- };
-
- /**
- * Stores the content source so we can re-populate it manually after a
- * post-roll on iOS.
- */
- this.contentSource = '';
-
- /**
- * Local content ended listener for contentComplete.
- */
- this.localContentEndedListener = function() {
- if (this.adsLoader && !this.contentComplete) {
- this.adsLoader.contentComplete();
- this.contentComplete = true;
- }
- for (var index in this.contentEndedListeners) {
- this.contentEndedListeners[index]();
- }
- if (this.allAdsCompleted) {
- for (var index in this.contentAndAdsEndedListeners) {
- this.contentAndAdsEndedListeners[index]();
- }
- }
- clearInterval(this.updateTimeIntervalHandle);
- clearInterval(this.seekCheckIntervalHandle);
- clearInterval(this.resizeCheckIntervalHandle);
- if(this.player.el()) {
- this.player.one('play', setUpPlayerIntervals_);
- }
- }.bind(this);
-
- this.playerDisposedListener = function(){
- this.contentEndedListeners, this.contentAndAdsEndedListeners = [], [];
- this.contentComplete = true;
- this.player.off('contentended', this.localContentEndedListener);
- this.player.off('timeupdate', updateStartTime_);
-
- // Bug fix: https://github.com/googleads/videojs-ima/issues/306
- if (this.player.ads.adTimeoutTimeout) {
- clearTimeout(this.player.ads.adTimeoutTimeout);
- }
-
- var intervalsToClear = [this.updateTimeIntervalHandle, this.seekCheckIntervalHandle,
- this.adTrackingTimer, this.resizeCheckIntervalHandle];
- for (var index in intervalsToClear) {
- var interval = intervalsToClear[index];
- if (interval) {
- clearInterval(interval);
- }
- }
- if (this.adsManager) {
- this.adsManager.destroy();
- this.adsManager = null;
- }
- }.bind(this);
-
- this.initVjsControls = function() {
- var _this = this;
- var override = function(cls, obj, method, fn, always) {
- var orig = cls.prototype[method];
- return obj[method] = function() {
- return _this.adsActive || always ? fn && fn.apply(this, arguments) :
- orig && orig.apply(this, arguments);
- };
- };
- var overrideHandler = function(cls, obj, target, event, method, fn, always) {
- var orig = cls.prototype[method];
- var handler = override(cls, obj, method, fn);
- if (target) {
- obj.off(target, event, orig);
- obj.on(target, event, handler);
- } else {
- obj.off(event, orig);
- obj.on(event, handler);
- }
- };
- var PlayToggle = videojs.getComponent('PlayToggle');
- var playToggle = this.vjsControls.playToggle;
- overrideHandler(PlayToggle, playToggle, null, ['tap', 'click'],
- 'handleClick', function() {
- onAdPlayPauseClick_();
- if (_this.adPlaying) {
- this.handlePlay();
- } else {
- this.handlePause();
- }
- });
- override(PlayToggle, playToggle, 'update', function() {
- var paused = _this.adsActive ? !_this.adPlaying : player.paused();
- this.toggleClass('vjs-play-control-ad', _this.adsActive);
- this.toggleClass('vjs-paused', paused);
- this.toggleClass('vjs-playing', !paused);
- var text = paused ? 'Play' : 'Pause';
- if (text != this.controlText())
- this.controlText(text);
- }, true);
- overrideHandler(PlayToggle, playToggle, player, 'play',
- 'handlePlay', function() { this.update(); }, true);
- overrideHandler(PlayToggle, playToggle, player, 'pause',
- 'handlePause', function() { this.update(); }, true);
-
- var SeekBar = videojs.getComponent('SeekBar');
- var DvrSeekBar = videojs.getComponent('DvrSeekBar');
- var seekBar = this.vjsControls.progressControl.seekBar;
- var getPercent = function() {
- var duration = _this.currentAd && _this.currentAd.getDuration();
- if (!duration || duration<0) {
- return 0;
- }
- var remainingTime = _this.adsManager.getRemainingTime();
- var currentTime = Math.max(duration - remainingTime, 0);
- return currentTime / duration;
- };
- override(SeekBar, seekBar, 'getPercent', getPercent);
- if (DvrSeekBar) {
- override(DvrSeekBar, seekBar, 'getPercent', getPercent);
- }
- overrideHandler(SeekBar, seekBar, null, ['mousedown', 'touchstart'],
- 'handleMouseDown', null);
- overrideHandler(SeekBar, seekBar, null, 'focus', 'handleFocus', null);
-
- var DurationDisplay = videojs.getComponent('DurationDisplay');
- var durationDisplay = this.vjsControls.durationDisplay;
- overrideHandler(DurationDisplay, durationDisplay, player,
- ['timeupdate', 'loadedmetadata'], 'updateContent', function() {
- var duration = _this.currentAd && _this.currentAd.getDuration();
- if (duration && duration != this.duration_) {
- this.duration_ = duration;
- this.contentEl_.innerHTML = ''+
- this.localize('Duration Time')+' '+formatTime(duration);
- }
- });
-
- var CurrentTimeDisplay = videojs.getComponent('CurrentTimeDisplay');
- var currentTimeDisplay = this.vjsControls.currentTimeDisplay;
- overrideHandler(CurrentTimeDisplay, currentTimeDisplay, player,
- ['timeupdate', 'loadedmetadata'], 'updateContent', function() {
- var duration = _this.currentAd && _this.currentAd.getDuration();
- if (!duration) {
- return;
- }
- var time = duration - _this.adsManager.getRemainingTime();
- var formattedTime = formatTime(time);
- if (formattedTime !== this.formattedTime_) {
- this.formattedTime_ = formattedTime;
- this.contentEl_.innerHTML = ''+
- this.localize('Current Time')+' '+formattedTime;
- }
- });
- }.bind(this);
-
- this.updateVjsControls = function() {
- if (!this.settings.vjsControls) {
- return;
- }
- this.player.toggleClass('vjs-ad-paused',
- this.adsActive && !this.adPlaying);
- var controls = this.vjsControls;
- controls.playToggle.update();
- controls.progressControl.seekBar.update();
- controls.durationDisplay.updateContent();
- controls.currentTimeDisplay.updateContent();
- var duration = this.currentAd && this.currentAd.getDuration();
- var display = !this.adsActive || duration && duration>=0 ? '' : 'none';
- controls.durationDisplay.el().style.display = display;
- controls.currentTimeDisplay.el().style.display = display;
- controls.timeDivider.el().style.display = display;
- }.bind(this);
-
- var getPosition = function(el) {
- var box = el.getBoundingClientRect();
- var docEl = document.documentElement;
- var body = document.body;
- var clientLeft = docEl.clientLeft || body.clientLeft || 0;
- var scrollLeft = window.pageXOffset || body.scrollLeft;
- var left = box.left + scrollLeft - clientLeft;
- var clientTop = docEl.clientTop || body.clientTop || 0;
- var scrollTop = window.pageYOffset || body.scrollTop;
- var top = box.top + scrollTop - clientTop;
- return {
- left: left,
- top: top,
- width: box.width,
- height: box.height,
- };
- };
-
- // proxy click events to the video element when non-linear ad is active
- this.proxyClickEvents = function() {
- var events = (videojs && videojs.browser && videojs.browser.IS_ANDROID || videojs.browser.IS_IOS) ?
- ['touchstart', 'touchend'] :
- ['click', 'dblclick', 'mousedown', 'mouseup'];
- var player = this.player, el = player.el(), _this = this;
- events.forEach(function(eventName) {
- el.addEventListener(eventName, function(e) {
- var ad = _this.currentAd, t = e.target;
- if (!ad || ad.isLinear() || t.nodeName!='IFRAME' || e.isTrusted) {
- return;
- }
- // ignore clicks on ad ui elements
- var adWidth = ad.getWidth() || ad.getVastMediaWidth();
- var adHeight = ad.getHeight() || ad.getVastMediaHeight();
- var pos = getPosition(t);
- var touch = e.touches && e.touches[0];
- var x = touch ? touch.pageX : e.clientX;
- var y = touch ? touch.pageY : e.clientY;
- var adRight = pos.left+pos.width-(pos.width-adWidth)/2;
- var adTop = pos.top+pos.height-adHeight-4;
- // click on close button
- if (x(adRight-40) && y>adTop && y<(adTop+30)) {
- return;
- }
- // click on recall button
- if (x>(pos.left+pos.width/2-15) && x<(pos.left+pos.width/2+15) &&
- y>(pos.top+pos.height-15)) {
- return;
- }
- var newEvent;
- var opt = {};
- for (var key in e) {
- opt[key] = e[key];
- }
- opt.bubbles = false;
- try {
- newEvent = new e.constructor(e.type, opt);
- } catch (err) {
- // special case for IE11
- newEvent = document.createEvent('MouseEvent');
- newEvent.initMouseEvent(e.type, opt.bubbles, opt.cancelable,
- opt.view, opt.detail, opt.screenX, opt.screenY, opt.clientX,
- opt.clientY, opt.ctrlKey, opt.altKey, opt.shiftKey, opt.metaKey,
- opt.button, null);
- }
- newEvent.stopPropagation();
- player.tech_.trigger(newEvent);
- });
- });
- }.bind(this);
-
- this.settings = extend({}, ima_defaults, options || {});
- this.settings.adLabel = this.player.localize(this.settings.adLabel);
-
- // Currently this isn't used but I can see it being needed in the future, so
- // to avoid implementation problems with later updates I'm requiring it.
- if (!this.settings['id']) {
- window.console.log('Error: must provide id of video.js div');
- return;
- }
-
- this.controlPrefix = (this.settings.id + '_') || '';
-
- this.contentPlayer = this.player.$('.vjs-tech');
- // Default showing countdown timer to true.
- this.showCountdown = true;
- if (this.settings['showCountdown'] === false) {
- this.showCountdown = false;
- }
-
- this.autoPlayAdBreaks = true;
- if (this.settings['autoPlayAdBreaks'] === false) {
- this.autoPlayAdBreaks = false;
- }
-
- var contrib_ads_defaults = {
- debug: this.settings.debug,
- timeout: this.settings.timeout,
- prerollTimeout: this.settings.prerollTimeout,
- postrollTimeout: this.settings.postrollTimeout
- };
-
- var ads_plugin_settings =
- extend({}, contrib_ads_defaults, options['contribAdsSettings'] || {});
-
- player.ads(ads_plugin_settings);
-
- player.one('play', setUpPlayerIntervals_);
- player.on('contentended', this.localContentEndedListener);
- player.on('dispose', this.playerDisposedListener);
- player.on('timeupdate', updateStartTime_);
- this.adsRenderingSettings = new google.ima.AdsRenderingSettings();
- this.adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
- if (this.settings['adsRenderingSettings']) {
- for (var setting in this.settings['adsRenderingSettings']) {
- this.adsRenderingSettings[setting] =
- this.settings['adsRenderingSettings'][setting];
- }
- }
-
- if (this.settings['locale']) {
- google.ima.settings.setLocale(this.settings['locale']);
- }
-
- createAdContainer_();
- this.adsLoader = new google.ima.AdsLoader(this.adDisplayContainer);
-
- this.adsLoader.getSettings().setVpaidMode(
- google.ima.ImaSdkSettings.VpaidMode.ENABLED);
- if (this.settings.vpaidAllowed == false) {
- this.adsLoader.getSettings().setVpaidMode(
- google.ima.ImaSdkSettings.VpaidMode.DISABLED);
- }
- if (this.settings.vpaidMode) {
- this.adsLoader.getSettings().setVpaidMode(this.settings.vpaidMode);
- }
-
- if (this.settings.locale) {
- this.adsLoader.getSettings().setLocale(this.settings.locale);
- }
-
- if (this.settings.numRedirects) {
- this.adsLoader.getSettings().setNumRedirects(this.settings.numRedirects);
- }
-
- this.adsLoader.getSettings().setPlayerType('videojs-ima');
- this.adsLoader.getSettings().setPlayerVersion(this.VERSION);
- this.adsLoader.getSettings().setAutoPlayAdBreaks(this.autoPlayAdBreaks);
-
- this.adsLoader.addEventListener(
- google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
- onAdsManagerLoaded_,
- false);
- this.adsLoader.addEventListener(
- google.ima.AdErrorEvent.Type.AD_ERROR,
- onAdsLoaderError_,
- false);
-
- if (!readyCallback) {
- readyCallback = this.startFromReadyCallback;
- }
- player.on('readyforpreroll', readyCallback);
- player.ready(function() {
- player.on('fullscreenchange', onFullscreenChange_);
- player.on('volumechange', onVolumeChange_);
- });
- this.proxyClickEvents();
- };
-
- videojs.registerPlugin('ima', init);
-});
+import 'videojs-contrib-ads';
+import 'videojs-ima';
+import 'videojs-ima/dist/videojs.ima.scss';
diff --git a/src/plugins/ima/index.js b/src/plugins/ima/index.js
index 43873798..70867f71 100644
--- a/src/plugins/ima/index.js
+++ b/src/plugins/ima/index.js
@@ -1,11 +1,9 @@
/* global google */
import { isFunction } from 'utils/type-inference';
import { PLAYER_EVENT } from 'utils/consts';
-import 'videojs-contrib-ads';
-import './ima';
-import './videojs-ima.scss';
-export default function imaPlugin(player, playerOptions) {
+export default async function imaPlugin(player, playerOptions) {
+ await import(/* webpackChunkName: "ima" */ './ima');
const loaded = {
contribAdsLoaded: isFunction(player.ads),
@@ -38,11 +36,11 @@ export default function imaPlugin(player, playerOptions) {
if (Object.keys(playerOptions.ads).length > 0 && typeof player.ima === 'object') {
if (playerOptions.ads.adsInPlaylist === 'first-video') {
player.one(PLAYER_EVENT.SOURCE_CHANGED, () => {
- player.ima.playAd();
+ player.ima.playAdBreak();
});
} else {
player.on(PLAYER_EVENT.SOURCE_CHANGED, () => {
- player.ima.playAd();
+ player.ima.playAdBreak();
});
}
}
diff --git a/src/plugins/ima/videojs-ima.scss b/src/plugins/ima/videojs-ima.scss
deleted file mode 100644
index 8d796355..00000000
--- a/src/plugins/ima/videojs-ima.scss
+++ /dev/null
@@ -1,252 +0,0 @@
-.cld-video-player {
- .ima-fullscreen-div, .ima-mute-div, .ima-play-pause-div, .ima-slider-div {
- line-height: 1.7;
- }
-
- &.vjs-ad-loading {
- > video,
- > .vjs-poster {
- opacity: 0;
- }
- }
-}
-
-.ima-ad-container {
- top: 0;
- left: 0;
- position: absolute;
- display: block;
- width: 100%;
- height: 100%;
- video {
- left: 0;
- }
-}
-
-/* Move overlay if user fast-clicks play button. */
-.video-js.vjs-playing .bumpable-ima-ad-container {
- margin-top: -50px;
-}
-
-/* Move overlay when controls are active. */
-.video-js.vjs-user-inactive.vjs-playing .bumpable-ima-ad-container {
- margin-top: 0px;
-}
-
-.video-js.vjs-paused .bumpable-ima-ad-container,
-.video-js.vjs-playing:hover .bumpable-ima-ad-container,
-.video-js.vjs-user-active.vjs-playing .bumpable-ima-ad-container {
- margin-top: -50px;
-}
-
-.vjs-ima-non-linear .vjs-big-play-button,
-.vjs-ima-non-linear .vjs-menu.vjs-settings-menu,
-.vjs-ima-non-linear .vjs-info-overlay,
-.vjs-ima-non-linear .vjs-modal-overlay,
-.vjs-ima-non-linear .vjs-control-bar {
- z-index: 1112;
-}
-
-.ima-controls-div {
- bottom:0px;
- height: 37px;
- position: absolute;
- overflow: hidden;
- display: none;
- opacity: 1;
- background-color: rgba(7, 20, 30, .7);
- background: -moz-linear-gradient(
- bottom,
- rgba(7, 20, 30, .7) 0%,
- rgba(7, 20, 30, 0) 100%); /* FF3.6+ */
- background: -webkit-gradient(
- linear,
- left bottom,
- left top,
- color-stop(0%,rgba(7, 20, 30, .7)),
- color-stop(100%,rgba(7, 20, 30, 0))); /* Chrome,Safari4+ */
- background: -webkit-linear-gradient(
- bottom,
- rgba(7, 20, 30, .7) 0%,
- rgba(7, 20, 30, 0) 100%); /* Chrome10+,Safari5.1+ */
- background: -o-linear-gradient(bottom,
- rgba(7, 20, 30, .7) 0%,
- rgba(7, 20, 30, 0) 100%); /* Opera 11.10+ */
- background: -ms-linear-gradient(bottom,
- rgba(7, 20, 30, .7) 0%,
- rgba(7, 20, 30, 0) 100%); /* IE10+ */
- background: linear-gradient(to top,
- rgba(7, 20, 30, .7) 0%,
- rgba(7, 20, 30, 0) 100%); /* W3C */
- filter: progid:DXImageTransform.Microsoft.gradient(
- startColorstr='#0007141E',
- endColorstr='#07141E',GradientType=0 ); /* IE6-9 */
-}
-
-.ima-countdown-div {
- height: 10px;
- color: #FFFFFF;
- text-shadow: 0 0 0.2em #000;
- cursor: default;
-}
-
-.ima-seek-bar-div {
- top: 12px;
- height: 3px;
- position: absolute;
- background: rgba(255, 255, 255, .4);
-}
-
-.ima-progress-div {
- width: 0px;
- height: 3px;
- background-color: #ECC546;
-}
-
-.ima-play-pause-div, .ima-mute-div, .ima-slider-div, .ima-fullscreen-div {
- width: 35px;
- height: 20px;
- top: 11px;
- left: 0px;
- position: absolute;
- color: #CCCCCC;
- font-size: 1.5em;
- line-height: 2;
- text-align: center;
- font-family: VideoJS;
- cursor: pointer;
-}
-
-.ima-mute-div {
- left: auto;
- right: 85px;
-}
-
-.ima-slider-div {
- left: auto;
- right: 35px;
- width: 50px;
- height: 10px;
- top: 20px;
- background-color: #555555;
-}
-
-.ima-slider-level-div {
- width: 100%;
- height: 10px;
- background-color: #ECC546;
-}
-
-.ima-fullscreen-div {
- left: auto;
- right: 0px;
-}
-
-.ima-playing:before {
- content: "\00f103";
-}
-
-.ima-paused:before {
- content: "\00f101";
-}
-
-.ima-playing:hover:before, .ima-paused:hover:before {
- text-shadow: 0 0 1em #fff;
-}
-
-.ima-non-muted:before {
- content: "\00f107";
-}
-
-.ima-muted:before {
- content: "\00f104";
-}
-
-.ima-non-muted:hover:before, .ima-muted:hover:before {
- text-shadow: 0 0 1em #fff;
-}
-
-.ima-non-fullscreen:before {
- content: "\00f108";
-}
-
-.ima-fullscreen:before {
- content: "\00f109";
-}
-
-.ima-non-fullscreen:hover:before, .ima-fullscreen:hover:before {
- text-shadow: 0 0 1em #fff;
-}
-
-.video-js.vjs-ad-playing .vjs-control-bar {
- z-index: 1112;
-}
-
-.video-js.vjs-ad-playing .vjs-control-bar .vjs-progress-control {
- pointer-events: none;
-}
-
-.video-js.vjs-ad-playing .vjs-control-bar>:not(.vjs-play-control):not(.vjs-volume-menu-button):not(.vjs-time-control):not(.vjs-progress-control):not(.vjs-spacer):not(.vjs-fullscreen-control):not(.vjs-gradient):not(.ima-countdown-div),
-.video-js.vjs-ad-playing .vjs-control-bar .vjs-mouse-display-tooltip,
-.video-js.vjs-ad-playing .vjs-control-bar .vjs-progress-control:before,
-.video-js.vjs-ad-playing .vjs-control-bar .vjs-play-progress:before,
-.video-js.vjs-ad-playing .vjs-control-bar .vjs-progress-control .vjs-load-progress,
-.video-js.vjs-ad-playing .vjs-control-bar .vjs-progress-control .vjs-mouse-display {
- display: none;
-}
-
-.video-js.vjs-ad-playing .vjs-control-bar {
- transition: height 0.1s ease;
-}
-
-.video-js.vjs-ad-playing.vjs-user-inactive:not(.vjs-ad-paused) .vjs-control-bar {
- opacity: 1;
- height: 0;
-}
-
-.video-js.vjs-ad-playing.vjs-user-inactive:not(.vjs-ad-paused) .vjs-control-bar .vjs-progress-holder {
- margin: 0;
-}
-
-.video-js.vjs-ad-playing .vjs-control-bar>:not(.vjs-progress-control):not(.ima-countdown-div) {
- transition: opacity 0.1s ease, visibility 0.1s ease;
-}
-
-.video-js.vjs-ad-playing .vjs-control-bar>:not(.vjs-progress-control):not(.ima-countdown-div) div{
- transition: line-height 0.1s ease;
-}
-
-.video-js.vjs-ad-playing.vjs-user-inactive:not(.vjs-ad-paused) .vjs-control-bar>:not(.vjs-progress-control):not(.ima-countdown-div) {
- opacity: 0;
- visibility: hidden;
- overflow: hidden;
-}
-
-.video-js.vjs-ad-playing.vjs-user-inactive:not(.vjs-ad-paused) .vjs-control-bar>:not(.vjs-progress-control):not(.ima-countdown-div) div{
- line-height: 0.01em;
-}
-
-.video-js.vjs-ad-playing .vjs-control-bar .vjs-progress-control .vjs-thumbnail-holder,
-.video-js.vjs-ad-playing .vjs-control-bar .vjs-progress-control .vjs-thumbnail {
- display: none !important;
-}
-
-.video-js.vjs-ad-playing .vjs-control-bar .vjs-progress-control .vjs-progress-holder {
- cursor: auto;
- box-shadow: none;
- font-size: 100%;
- margin: 0 1em;
-}
-
-.video-js .vjs-control-bar .ima-countdown-div {
- display: none;
- z-index: 1;
-}
-
-.video-js.vjs-ad-playing .vjs-control-bar .ima-countdown-div {
- display: block;
- position: absolute;
- margin-top: -2em;
- left: 2em;
- font-size: 1.2em;
-}
diff --git a/src/plugins/index.js b/src/plugins/index.js
index cc406014..935fe2b4 100644
--- a/src/plugins/index.js
+++ b/src/plugins/index.js
@@ -1,8 +1,6 @@
import 'videojs-per-source-behaviors';
// #if (!process.env.WEBPACK_BUILD_LIGHT)
-import dashPlugin from './dash';
-import imaPlugin from './ima';
import './videojs-http-source-selector/plugin';
// #endif
@@ -19,17 +17,14 @@ import pacedTranscript from './paced-transcript';
import vttThumbnails from './vtt-thumbnails';
// Lazy loaded plugins
+import dashPlugin from './dash';
+import imaPlugin from './ima';
import playlist from './playlist';
import shoppable from './shoppable-plugin';
import styledTextTracks from './styled-text-tracks';
import interactionAreas from './interaction-areas';
const plugins = {
- // #if (!process.env.WEBPACK_BUILD_LIGHT)
- dashPlugin,
- imaPlugin,
- // #endif
-
aiHighlightsGraph,
analytics,
autoplayOnScroll,
@@ -43,6 +38,8 @@ const plugins = {
vttThumbnails,
// Lazy loaded plugins
+ dashPlugin,
+ imaPlugin,
playlist,
shoppable,
styledTextTracks,