aboutsummaryrefslogtreecommitdiffstats
path: root/src/js/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/plugins')
-rw-r--r--src/js/plugins/ads.js85
-rw-r--r--src/js/plugins/previewThumbnails.js10
-rw-r--r--src/js/plugins/vimeo.js8
-rw-r--r--src/js/plugins/youtube.js47
4 files changed, 80 insertions, 70 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();
diff --git a/src/js/plugins/previewThumbnails.js b/src/js/plugins/previewThumbnails.js
index 813bc47e..3e4b17a3 100644
--- a/src/js/plugins/previewThumbnails.js
+++ b/src/js/plugins/previewThumbnails.js
@@ -149,9 +149,11 @@ class PreviewThumbnails {
// If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file
// If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank
// If the thumbnail URLs start with with none of '/', 'http://' or 'https://', then we need to set their relative path to be the location of the VTT file
- if (!thumbnail.frames[0].text.startsWith('/') &&
+ if (
+ !thumbnail.frames[0].text.startsWith('/') &&
!thumbnail.frames[0].text.startsWith('http://') &&
- !thumbnail.frames[0].text.startsWith('https://')) {
+ !thumbnail.frames[0].text.startsWith('https://')
+ ) {
thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);
}
@@ -297,7 +299,9 @@ class PreviewThumbnails {
this.elements.thumb.container.appendChild(timeContainer);
// Inject the whole thumb
- this.player.elements.progress.appendChild(this.elements.thumb.container);
+ if (is.element(this.player.elements.progress)) {
+ this.player.elements.progress.appendChild(this.elements.thumb.container);
+ }
// Create HTML element: plyr__preview-scrubbing-container
this.elements.scrubbing.container = createElement('div', {
diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js
index 9d6c1665..8d920eea 100644
--- a/src/js/plugins/vimeo.js
+++ b/src/js/plugins/vimeo.js
@@ -48,14 +48,14 @@ const vimeo = {
// Set intial ratio
setAspectRatio.call(this);
- // Load the API if not already
+ // Load the SDK if not already
if (!is.object(window.Vimeo)) {
loadScript(this.config.urls.vimeo.sdk)
.then(() => {
vimeo.ready.call(this);
})
.catch(error => {
- this.debug.warn('Vimeo API failed to load', error);
+ this.debug.warn('Vimeo SDK (player.js) failed to load', error);
});
} else {
vimeo.ready.call(this);
@@ -259,7 +259,7 @@ const vimeo = {
.getVideoUrl()
.then(value => {
currentSrc = value;
- controls.setDownloadLink.call(player);
+ controls.setDownloadUrl.call(player);
})
.catch(error => {
this.debug.warn(error);
@@ -281,7 +281,7 @@ const vimeo = {
// Set aspect ratio based on video size
Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {
const [width, height] = dimensions;
- player.embed.ratio = `${width}:${height}`;
+ player.embed.ratio = [width, height];
setAspectRatio.call(this);
});
diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js
index d862e4dd..7abc05fe 100644
--- a/src/js/plugins/youtube.js
+++ b/src/js/plugins/youtube.js
@@ -52,9 +52,6 @@ const youtube = {
// Add embed class for responsive
toggleClass(this.elements.wrapper, this.config.classNames.embed, true);
- // Set aspect ratio
- setAspectRatio.call(this);
-
// Setup API
if (is.object(window.YT) && is.function(window.YT.Player)) {
youtube.ready.call(this);
@@ -84,33 +81,27 @@ const youtube = {
// Get the media title
getTitle(videoId) {
- // Try via undocumented API method first
- // This method disappears now and then though...
- // https://github.com/sampotts/plyr/issues/709
- if (is.function(this.embed.getVideoData)) {
- const { title } = this.embed.getVideoData();
-
- if (is.empty(title)) {
- this.config.title = title;
- ui.setTitle.call(this);
- return;
- }
- }
+ const url = format(this.config.urls.youtube.api, videoId);
- // Or via Google API
- const key = this.config.keys.google;
- if (is.string(key) && !is.empty(key)) {
- const url = format(this.config.urls.youtube.api, videoId, key);
+ fetch(url)
+ .then(data => {
+ if (is.object(data)) {
+ const { title, height, width } = data;
- fetch(url)
- .then(result => {
- if (is.object(result)) {
- this.config.title = result.items[0].snippet.title;
- ui.setTitle.call(this);
- }
- })
- .catch(() => {});
- }
+ // Set title
+ this.config.title = title;
+ ui.setTitle.call(this);
+
+ // Set aspect ratio
+ this.embed.ratio = [width, height];
+ }
+
+ setAspectRatio.call(this);
+ })
+ .catch(() => {
+ // Set aspect ratio
+ setAspectRatio.call(this);
+ });
},
// API ready