aboutsummaryrefslogtreecommitdiffstats
path: root/src/js/plugins
diff options
context:
space:
mode:
authorSam Potts <sam@potts.es>2019-04-25 12:03:04 +1000
committerSam Potts <sam@potts.es>2019-04-25 12:03:04 +1000
commita1b2c0419fa9492f7f992a5f9b376366894259a9 (patch)
treecb8bf323ca50f686175e84a623f3db8049978ac4 /src/js/plugins
parent9b81e776fbb73195cd4391e4b504e9e1ae7aedad (diff)
downloadplyr-a1b2c0419fa9492f7f992a5f9b376366894259a9.tar.lz
plyr-a1b2c0419fa9492f7f992a5f9b376366894259a9.tar.xz
plyr-a1b2c0419fa9492f7f992a5f9b376366894259a9.zip
Ads improvements for volume and race condition fix
Diffstat (limited to 'src/js/plugins')
-rw-r--r--src/js/plugins/ads.js85
1 files changed, 50 insertions, 35 deletions
diff --git a/src/js/plugins/ads.js b/src/js/plugins/ads.js
index c9256b0e..2b083285 100644
--- a/src/js/plugins/ads.js
+++ b/src/js/plugins/ads.js
@@ -14,6 +14,20 @@ import loadScript from '../utils/loadScript';
import { formatTime } from '../utils/time';
import { buildUrlParams } from '../utils/urls';
+const destroy = instance => {
+ // Destroy our adsManager
+ if (instance.manager) {
+ instance.manager.destroy();
+ }
+
+ // Destroy our adsManager
+ if (instance.elements.displayContainer) {
+ instance.elements.displayContainer.destroy();
+ }
+
+ instance.elements.container.remove();
+};
+
class Ads {
/**
* Ads constructor.
@@ -63,20 +77,22 @@ class Ads {
* Load the IMA SDK
*/
load() {
- if (this.enabled) {
- // Check if the Google IMA3 SDK is loaded or load it ourselves
- if (!is.object(window.google) || !is.object(window.google.ima)) {
- loadScript(this.player.config.urls.googleIMA.sdk)
- .then(() => {
- this.ready();
- })
- .catch(() => {
- // Script failed to load or is blocked
- this.trigger('error', new Error('Google IMA SDK failed to load'));
- });
- } else {
- this.ready();
- }
+ if (!this.enabled) {
+ return;
+ }
+
+ // Check if the Google IMA3 SDK is loaded or load it ourselves
+ if (!is.object(window.google) || !is.object(window.google.ima)) {
+ loadScript(this.player.config.urls.googleIMA.sdk)
+ .then(() => {
+ this.ready();
+ })
+ .catch(() => {
+ // Script failed to load or is blocked
+ this.trigger('error', new Error('Google IMA SDK failed to load'));
+ });
+ } else {
+ this.ready();
}
}
@@ -84,6 +100,11 @@ class Ads {
* Get the ads instance ready
*/
ready() {
+ // Double check we're enabled
+ if (!this.enabled) {
+ destroy(this);
+ }
+
// Start ticking our safety timer. If the whole advertisement
// thing doesn't resolve within our set time; we bail
this.startSafetyTimer(12000, 'ready()');
@@ -240,9 +261,6 @@ class Ads {
// Get the cue points for any mid-rolls by filtering out the pre- and post-roll
this.cuePoints = this.manager.getCuePoints();
- // Set volume to match player
- this.manager.setVolume(this.player.volume);
-
// Add listeners to the required events
// Advertisement error events
this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));
@@ -297,15 +315,15 @@ class Ads {
triggerEvent.call(this.player, this.player.media, event);
};
+ // Bubble the event
+ dispatchEvent(event.type);
+
switch (event.type) {
case google.ima.AdEvent.Type.LOADED:
// This is the first event sent for an ad - it is possible to determine whether the
// ad is a video ad or an overlay
this.trigger('loaded');
- // Bubble event
- dispatchEvent(event.type);
-
// Start countdown
this.pollCountdown(true);
@@ -317,15 +335,19 @@ class Ads {
// console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());
// console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());
+
+ break;
+
+ case google.ima.AdEvent.Type.STARTED:
+ // Set volume to match player
+ this.manager.setVolume(this.player.volume);
+
break;
case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:
// All ads for the current videos are done. We can now request new advertisements
// in case the video is re-played
- // Fire event
- dispatchEvent(event.type);
-
// TODO: Example for what happens when a next video in a playlist would be loaded.
// So here we load a new video when all ads are done.
// Then we load new ads within a new adsManager. When the video
@@ -350,6 +372,7 @@ class Ads {
// playing when the IMA SDK is ready or has failed
this.loadAds();
+
break;
case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:
@@ -357,8 +380,6 @@ class Ads {
// for example display a pause button and remaining time. Fired when content should
// be paused. This usually happens right before an ad is about to cover the content
- dispatchEvent(event.type);
-
this.pauseContent();
break;
@@ -369,26 +390,17 @@ class Ads {
// Fired when content should be resumed. This usually happens when an ad finishes
// or collapses
- dispatchEvent(event.type);
-
this.pollCountdown();
this.resumeContent();
break;
- case google.ima.AdEvent.Type.STARTED:
- case google.ima.AdEvent.Type.MIDPOINT:
- case google.ima.AdEvent.Type.COMPLETE:
- case google.ima.AdEvent.Type.IMPRESSION:
- case google.ima.AdEvent.Type.CLICK:
- dispatchEvent(event.type);
- break;
-
case google.ima.AdEvent.Type.LOG:
if (adData.adError) {
this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);
}
+
break;
default:
@@ -463,6 +475,9 @@ class Ads {
// Play the requested advertisement whenever the adsManager is ready
this.managerPromise
.then(() => {
+ // Set volume to match player
+ this.manager.setVolume(this.player.volume);
+
// Initialize the container. Must be done via a user action on mobile devices
this.elements.displayContainer.initialize();