From 11fed8d1b5ec9bfcbeafa0a90ebbc0ac15711807 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 27 Feb 2019 15:43:36 +0100 Subject: Preview seek: fix: allow absolute thumbnail paths --- src/js/plugins/previewThumbnails.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/previewThumbnails.js b/src/js/plugins/previewThumbnails.js index bd7a6bbd..90e6226d 100644 --- a/src/js/plugins/previewThumbnails.js +++ b/src/js/plugins/previewThumbnails.js @@ -148,7 +148,10 @@ 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 (!thumbnail.frames[0].text.startsWith('/')) { + // 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('/') && + !thumbnail.frames[0].text.startsWith('http://') && + !thumbnail.frames[0].text.startsWith('https://')) { thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1); } -- cgit v1.2.3 From ce91945544b51da0a3546367b5a41da3ccbd1eeb Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 27 Feb 2019 15:45:24 +0100 Subject: Preview seek: optional hours and ms in VTT parser --- src/js/plugins/previewThumbnails.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/previewThumbnails.js b/src/js/plugins/previewThumbnails.js index 90e6226d..813bc47e 100644 --- a/src/js/plugins/previewThumbnails.js +++ b/src/js/plugins/previewThumbnails.js @@ -17,17 +17,17 @@ const parseVtt = vttDataString => { if (!is.number(result.startTime)) { // The line with start and end times on it is the first line of interest const matchTimes = line.match( - /([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{2,3})/, + /([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})/, ); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT if (matchTimes) { result.startTime = - Number(matchTimes[1]) * 60 * 60 + + Number(matchTimes[1] || 0) * 60 * 60 + Number(matchTimes[2]) * 60 + Number(matchTimes[3]) + Number(`0.${matchTimes[4]}`); result.endTime = - Number(matchTimes[6]) * 60 * 60 + + Number(matchTimes[6] || 0) * 60 * 60 + Number(matchTimes[7]) * 60 + Number(matchTimes[8]) + Number(`0.${matchTimes[9]}`); -- cgit v1.2.3 From f4b47a9275d597f7f3eb47dbc89603859be166f9 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Thu, 4 Apr 2019 08:51:20 +0300 Subject: fixed setting youtube host for non-https case --- src/js/plugins/youtube.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index d5972c80..cac1a90f 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -34,6 +34,22 @@ function assurePlaybackState(play) { } } +function useHttp() { + return !window.location.href.includes('https://'); +} + +function getYoutubeHost(config) { + let host; + + if (config.noCookie) { + host = 'https://www.youtube-nocookie.com'; + } else { + host = useHttp() ? 'http://www.youtube.com' : undefined; + } + + return host; +} + const youtube = { setup() { // Add embed class for responsive @@ -151,7 +167,7 @@ const youtube = { // https://developers.google.com/youtube/iframe_api_reference player.embed = new window.YT.Player(id, { videoId, - host: config.noCookie ? 'https://www.youtube-nocookie.com' : undefined, + host: getYoutubeHost(config), playerVars: extend( {}, { -- cgit v1.2.3 From c22f5c4b39ba545508392343fc0ffcfa4775dfdb Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Thu, 4 Apr 2019 08:56:46 +0300 Subject: code cleanup --- src/js/plugins/youtube.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index cac1a90f..1f827776 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -34,20 +34,12 @@ function assurePlaybackState(play) { } } -function useHttp() { - return !window.location.href.includes('https://'); -} - function getYoutubeHost(config) { - let host; - if (config.noCookie) { - host = 'https://www.youtube-nocookie.com'; - } else { - host = useHttp() ? 'http://www.youtube.com' : undefined; + return 'https://www.youtube-nocookie.com'; } - return host; + return `${window.location.protocol}//www.youtube.com`; } const youtube = { -- cgit v1.2.3 From 21539be3f2b01a549c920ee683c2121f53929d96 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Thu, 4 Apr 2019 09:32:38 +0300 Subject: code cleanup --- src/js/plugins/youtube.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 1f827776..9c447f7d 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -34,7 +34,7 @@ function assurePlaybackState(play) { } } -function getYoutubeHost(config) { +function getHost(config) { if (config.noCookie) { return 'https://www.youtube-nocookie.com'; } @@ -159,7 +159,7 @@ const youtube = { // https://developers.google.com/youtube/iframe_api_reference player.embed = new window.YT.Player(id, { videoId, - host: getYoutubeHost(config), + host: getHost(config), playerVars: extend( {}, { -- cgit v1.2.3 From 2eccf0dd05f1678749a2c10c84e5c2bff03f1435 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Fri, 12 Apr 2019 12:13:46 +1000 Subject: Fix YouTube autoplay (fixes #1185) --- src/js/plugins/youtube.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index d5972c80..3e73a4d0 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -386,7 +386,7 @@ const youtube = { case 1: // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) - if (player.media.paused && !player.embed.hasPlayed) { + if (!player.config.autoplay && player.media.paused && !player.embed.hasPlayed) { player.media.pause(); } else { assurePlaybackState.call(player, true); -- cgit v1.2.3 From b247093495c3402dbe7c14e3faeff8475f4e277c Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Fri, 12 Apr 2019 12:19:48 +1000 Subject: Aspect ratio improvements (fixes #1042, fixes #1366) --- src/js/plugins/vimeo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js index a7664e73..9d6c1665 100644 --- a/src/js/plugins/vimeo.js +++ b/src/js/plugins/vimeo.js @@ -282,7 +282,7 @@ const vimeo = { Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => { const [width, height] = dimensions; player.embed.ratio = `${width}:${height}`; - setAspectRatio.call(this, player.embed.ratio); + setAspectRatio.call(this); }); // Set autopause -- cgit v1.2.3 From cdacae669786a76d821e828573f996b97ec4df9e Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Fri, 12 Apr 2019 19:00:17 +1000 Subject: Set download URL via setter --- src/js/plugins/vimeo.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js index 9d6c1665..e1e873fa 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); -- cgit v1.2.3 From 243db9eda32d0ceb705b0cb99426995db071b113 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Sat, 13 Apr 2019 12:56:15 +1000 Subject: Fix issue with empty controls and preview thumbs --- src/js/plugins/previewThumbnails.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/js/plugins') 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', { -- cgit v1.2.3 From 7a4a7dece8538b1ff23d9155d882bda01c7940ee Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Thu, 25 Apr 2019 12:02:37 +1000 Subject: Ratio improvements --- src/js/plugins/vimeo.js | 2 +- src/js/plugins/youtube.js | 47 +++++++++++++++++++---------------------------- 2 files changed, 20 insertions(+), 29 deletions(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js index e1e873fa..8d920eea 100644 --- a/src/js/plugins/vimeo.js +++ b/src/js/plugins/vimeo.js @@ -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 -- cgit v1.2.3 From a1b2c0419fa9492f7f992a5f9b376366894259a9 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Thu, 25 Apr 2019 12:03:04 +1000 Subject: Ads improvements for volume and race condition fix --- src/js/plugins/ads.js | 85 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 35 deletions(-) (limited to 'src/js/plugins') 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(); -- cgit v1.2.3 From f100caba81d0f2ecb9305988993072ccb1cdc233 Mon Sep 17 00:00:00 2001 From: Alexander Farkas Date: Fri, 24 May 2019 16:53:58 +0200 Subject: fix youtube embed + handle early destroy --- src/js/plugins/youtube.js | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 7abc05fe..0b812505 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -47,6 +47,8 @@ function getHost(config) { return undefined; } +let onYouTubeReadyCallbacks; + const youtube = { setup() { // Add embed class for responsive @@ -56,26 +58,32 @@ const youtube = { if (is.object(window.YT) && is.function(window.YT.Player)) { youtube.ready.call(this); } else { - // Load the API - loadScript(this.config.urls.youtube.sdk).catch(error => { - this.debug.warn('YouTube API failed to load', error); - }); - // Setup callback for the API - // YouTube has it's own system of course... - window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; + if (!onYouTubeReadyCallbacks) { + const oldYouTubeIframeAPIReady = window.onYouTubeIframeAPIReady; + // Load the API + onYouTubeReadyCallbacks = []; + + // Set callback to process queue + window.onYouTubeIframeAPIReady = () => { + if (oldYouTubeIframeAPIReady && is.function(oldYouTubeIframeAPIReady)) { + oldYouTubeIframeAPIReady(); + } + + window.onYouTubeReadyCallbacks.forEach(callback => { + callback(); + }); + }; + + loadScript(this.config.urls.youtube.sdk).catch(error => { + this.debug.warn('YouTube API failed to load', error); + }); + } // Add to queue window.onYouTubeReadyCallbacks.push(() => { youtube.ready.call(this); }); - - // Set callback to process queue - window.onYouTubeIframeAPIReady = () => { - window.onYouTubeReadyCallbacks.forEach(callback => { - callback(); - }); - }; } }, @@ -109,7 +117,7 @@ const youtube = { const player = this; // Ignore already setup (race condition) - const currentId = player.media.getAttribute('id'); + const currentId = player.media && player.media.getAttribute('id'); if (!is.empty(currentId) && currentId.startsWith('youtube-')) { return; } -- cgit v1.2.3 From 97a6e72e104b6a47abefaa7d6216f0a6c45f0ce9 Mon Sep 17 00:00:00 2001 From: Alexander Farkas Date: Fri, 24 May 2019 16:55:45 +0200 Subject: fix youtube embed + handle early destroy --- src/js/plugins/youtube.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 0b812505..d82dab22 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -81,7 +81,7 @@ const youtube = { } // Add to queue - window.onYouTubeReadyCallbacks.push(() => { + onYouTubeReadyCallbacks.push(() => { youtube.ready.call(this); }); } -- cgit v1.2.3 From c9055f391b3782d96d16fb6efa4337dc90120635 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Sat, 1 Jun 2019 18:45:07 +1000 Subject: Linting changes --- src/js/plugins/ads.js | 6 ++---- src/js/plugins/previewThumbnails.js | 11 ++++++----- src/js/plugins/vimeo.js | 2 -- src/js/plugins/youtube.js | 9 +++------ 4 files changed, 11 insertions(+), 17 deletions(-) (limited to 'src/js/plugins') diff --git a/src/js/plugins/ads.js b/src/js/plugins/ads.js index 2b083285..e6fab967 100644 --- a/src/js/plugins/ads.js +++ b/src/js/plugins/ads.js @@ -267,7 +267,7 @@ class Ads { // Advertisement regular events Object.keys(google.ima.AdEvent.Type).forEach(type => { - this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event)); + this.manager.addEventListener(google.ima.AdEvent.Type[type], e => this.onAdEvent(e)); }); // Resolve our adsManager @@ -303,7 +303,6 @@ class Ads { */ onAdEvent(event) { const { container } = this.player.elements; - // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED) // don't have ad object associated const ad = event.getAd(); @@ -311,8 +310,7 @@ class Ads { // Proxy event const dispatchEvent = type => { - const event = `ads${type.replace(/_/g, '').toLowerCase()}`; - triggerEvent.call(this.player, this.player.media, event); + triggerEvent.call(this.player, this.player.media, `ads${type.replace(/_/g, '').toLowerCase()}`); }; // Bubble the event diff --git a/src/js/plugins/previewThumbnails.js b/src/js/plugins/previewThumbnails.js index 3e4b17a3..f3359a4f 100644 --- a/src/js/plugins/previewThumbnails.js +++ b/src/js/plugins/previewThumbnails.js @@ -2,6 +2,7 @@ import { createElement } from '../utils/elements'; import { once } from '../utils/events'; import fetch from '../utils/fetch'; import is from '../utils/is'; +import { extend } from '../utils/objects'; import { formatTime } from '../utils/time'; // Arg: vttDataString example: "WEBVTT\n\n1\n00:00:05.000 --> 00:00:10.000\n1080p-00001.jpg" @@ -121,7 +122,6 @@ class PreviewThumbnails { // If string, convert into single-element list const urls = is.string(src) ? [src] : src; - // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails const promises = urls.map(u => this.getThumbnail(u)); @@ -426,7 +426,7 @@ class PreviewThumbnails { if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) { // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function - image.dataset.deleting = true; + extend(image, { dataset: { deleting: true } }); // This has to be set before the timeout - to prevent issues switching between hover and scrub const { currentImageContainer } = this; @@ -467,7 +467,6 @@ class PreviewThumbnails { const { urlPrefix } = this.thumbnails[0]; const thumbURL = urlPrefix + newThumbFilename; - const previewImage = new Image(); previewImage.src = thumbURL; previewImage.onload = () => { @@ -601,11 +600,9 @@ class PreviewThumbnails { const seekbarRect = this.player.elements.progress.getBoundingClientRect(); const plyrRect = this.player.elements.container.getBoundingClientRect(); const { container } = this.elements.thumb; - // Find the lowest and highest desired left-position, so we don't slide out the side of the video container const minVal = plyrRect.left - seekbarRect.left + 10; const maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10; - // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth let previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2; @@ -636,9 +633,13 @@ class PreviewThumbnails { // Find difference between height and preview container height const multiplier = this.thumbContainerHeight / frame.h; + // eslint-disable-next-line no-param-reassign previewImage.style.height = `${Math.floor(previewImage.naturalHeight * multiplier)}px`; + // eslint-disable-next-line no-param-reassign previewImage.style.width = `${Math.floor(previewImage.naturalWidth * multiplier)}px`; + // eslint-disable-next-line no-param-reassign previewImage.style.left = `-${frame.x * multiplier}px`; + // eslint-disable-next-line no-param-reassign previewImage.style.top = `-${frame.y * multiplier}px`; } } diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js index 8d920eea..bef48708 100644 --- a/src/js/plugins/vimeo.js +++ b/src/js/plugins/vimeo.js @@ -91,7 +91,6 @@ const vimeo = { } const id = parseId(source); - // Build an iframe const iframe = createElement('iframe'); const src = format(player.config.urls.vimeo.iframe, id, params); @@ -102,7 +101,6 @@ const vimeo = { // Get poster, if already set const { poster } = player; - // Inject the package const wrapper = createElement('div', { poster, class: player.config.classNames.embedContainer }); wrapper.appendChild(iframe); diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 7abc05fe..73448b67 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -107,7 +107,6 @@ const youtube = { // API ready ready() { const player = this; - // Ignore already setup (race condition) const currentId = player.media.getAttribute('id'); if (!is.empty(currentId) && currentId.startsWith('youtube-')) { @@ -125,25 +124,23 @@ const youtube = { // Replace the