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') 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') 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 266b70d9d083c99b606bbf63f1a05e0cfe52a18c Mon Sep 17 00:00:00 2001 From: Jimmy Jia Date: Mon, 1 Apr 2019 14:42:51 -0400 Subject: fix: Properly clear all timeouts on destroy --- src/js/plyr.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/js') diff --git a/src/js/plyr.js b/src/js/plyr.js index 0d3d1674..e28c5da3 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -1088,11 +1088,13 @@ class Plyr { // Stop playback this.stop(); + // Clear timeouts + clearTimeout(this.timers.loading); + clearTimeout(this.timers.controls); + clearTimeout(this.timers.resized); + // Provider specific stuff if (this.isHTML5) { - // Clear timeout - clearTimeout(this.timers.loading); - // Restore native video controls ui.toggleNativeControls.call(this, true); -- 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') 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') 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') 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') 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 9ca7b861a925ec0412006f7cc926bfa1859a0daa Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Fri, 12 Apr 2019 12:14:12 +1000 Subject: Autoplay tweak for HTML5 --- src/js/plyr.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/js') diff --git a/src/js/plyr.js b/src/js/plyr.js index e28c5da3..c06df984 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -301,8 +301,8 @@ class Plyr { } // Autoplay if required - if (this.config.autoplay) { - this.play(); + if (this.isHTML5 && this.config.autoplay) { + setTimeout(() => this.play(), 10); } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek -- 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/config/defaults.js | 6 +++-- src/js/html5.js | 4 +++ src/js/listeners.js | 8 +++--- src/js/plugins/vimeo.js | 2 +- src/js/plyr.js | 29 ++++++++++++++++++++ src/js/utils/style.js | 67 +++++++++++++++++++++++++++++++++++++---------- 6 files changed, 95 insertions(+), 21 deletions(-) (limited to 'src/js') diff --git a/src/js/config/defaults.js b/src/js/config/defaults.js index 82809511..c45131bc 100644 --- a/src/js/config/defaults.js +++ b/src/js/config/defaults.js @@ -42,8 +42,9 @@ const defaults = { // Clicking the currentTime inverts it's value to show time left rather than elapsed toggleInvert: true, - // Aspect ratio (for embeds) - ratio: '16:9', + // Force an aspect ratio + // The format must be `'w:h'` (e.g. `'16:9'`) + ratio: null, // Click video container to play/pause clickToPlay: true, @@ -330,6 +331,7 @@ const defaults = { provider: 'plyr--{0}', video: 'plyr__video-wrapper', embed: 'plyr__video-embed', + videoFixedRatio: 'plyr__video-wrapper--fixed-ratio', embedContainer: 'plyr__video-embed__container', poster: 'plyr__poster', posterEnabled: 'plyr__poster-enabled', diff --git a/src/js/html5.js b/src/js/html5.js index 3266a58e..34f0c391 100644 --- a/src/js/html5.js +++ b/src/js/html5.js @@ -6,6 +6,7 @@ import support from './support'; import { removeElement } from './utils/elements'; import { triggerEvent } from './utils/events'; import is from './utils/is'; +import { setAspectRatio } from './utils/style'; const html5 = { getSources() { @@ -43,6 +44,9 @@ const html5 = { const player = this; + // Set aspect ratio if set + setAspectRatio.call(player); + // Quality Object.defineProperty(player.media, 'quality', { get() { diff --git a/src/js/listeners.js b/src/js/listeners.js index 3c65b824..5a593b10 100644 --- a/src/js/listeners.js +++ b/src/js/listeners.js @@ -9,7 +9,7 @@ import browser from './utils/browser'; import { getElement, getElements, matches, toggleClass, toggleHidden } from './utils/elements'; import { off, on, once, toggleListener, triggerEvent } from './utils/events'; import is from './utils/is'; -import { setAspectRatio } from './utils/style'; +import { getAspectRatio, setAspectRatio } from './utils/style'; class Listeners { constructor(player) { @@ -317,10 +317,10 @@ class Listeners { } const target = player.elements.wrapper.firstChild; - const [, height] = ratio.split(':').map(Number); - const [videoWidth, videoHeight] = player.embed.ratio.split(':').map(Number); + const [, y] = ratio; + const [videoX, videoY] = getAspectRatio.call(this); - target.style.maxWidth = toggle ? `${(height / videoHeight) * videoWidth}px` : null; + target.style.maxWidth = toggle ? `${(y / videoY) * videoX}px` : null; target.style.margin = toggle ? '0 auto' : null; }; 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 diff --git a/src/js/plyr.js b/src/js/plyr.js index c06df984..1dd3ecb9 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -26,6 +26,7 @@ import { off, on, once, triggerEvent, unbindListeners } from './utils/events'; import is from './utils/is'; import loadSprite from './utils/loadSprite'; import { cloneDeep, extend } from './utils/objects'; +import { getAspectRatio, reduceAspectRatio, setAspectRatio, validateRatio } from './utils/style'; import { parseUrl } from './utils/urls'; // Private properties @@ -846,6 +847,34 @@ class Plyr { return this.media.getAttribute('poster'); } + /** + * Get the current aspect ratio in use + */ + get ratio() { + const ratio = reduceAspectRatio(getAspectRatio.call(this)); + + return is.array(ratio) ? ratio.join(':') : ratio; + } + + /** + * Set video aspect ratio + */ + set ratio(input) { + if (!this.isVideo) { + this.debug.warn('Aspect ratio can only be set for video'); + return; + } + + if (!is.string(input) || !validateRatio(input)) { + this.debug.error(`Invalid aspect ratio specified (${input})`); + return; + } + + this.config.ratio = input; + + setAspectRatio.call(this); + } + /** * Set the autoplay state * @param {Boolean} input - Whether to autoplay or not diff --git a/src/js/utils/style.js b/src/js/utils/style.js index a8eb393b..191e6461 100644 --- a/src/js/utils/style.js +++ b/src/js/utils/style.js @@ -4,26 +4,63 @@ import is from './is'; -/* function reduceAspectRatio(width, height) { - const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h)); - const ratio = getRatio(width, height); - return `${width / ratio}:${height / ratio}`; -} */ +export function validateRatio(input) { + if (!is.array(input) && (!is.string(input) || !input.includes(':'))) { + return false; + } -// Set aspect ratio for responsive container -export function setAspectRatio(input) { - let ratio = input; + const ratio = is.array(input) ? input : input.split(':'); + + return ratio.map(Number).every(is.number); +} + +export function reduceAspectRatio(ratio) { + if (!is.array(ratio) || !ratio.every(is.number)) { + return null; + } + + const [width, height] = ratio; + const getDivider = (w, h) => (h === 0 ? w : getDivider(h, w % h)); + const divider = getDivider(width, height); + + return [width / divider, height / divider]; +} - if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) { - ({ ratio } = this.embed); +export function getAspectRatio(input) { + const parse = ratio => { + if (!validateRatio(ratio)) { + return null; + } + + return ratio.split(':').map(Number); + }; + + // Provided ratio + let ratio = parse(input); + + // Get from config + if (ratio === null) { + ratio = parse(this.config.ratio); + } + + // Get from embed + if (ratio === null && !is.empty(this.embed) && is.string(this.embed.ratio)) { + ratio = parse(this.embed.ratio); } - if (!is.string(ratio)) { - ({ ratio } = this.config); + return ratio; +} + +// Set aspect ratio for responsive container +export function setAspectRatio(input) { + if (!this.isVideo) { + return {}; } - const [x, y] = ratio.split(':').map(Number); - const padding = (100 / x) * y; + const ratio = getAspectRatio.call(this, input); + + const [w, h] = is.array(ratio) ? ratio : [0, 0]; + const padding = (100 / w) * h; this.elements.wrapper.style.paddingBottom = `${padding}%`; @@ -32,6 +69,8 @@ export function setAspectRatio(input) { const height = 240; const offset = (height - padding) / (height / 50); this.media.style.transform = `translateY(-${offset}%)`; + } else if (this.isHTML5) { + this.elements.wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); } return { padding, ratio }; -- cgit v1.2.3 From 2bd08cdc28bf55b7f7a169b02eb288d7b197b8d6 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Fri, 12 Apr 2019 18:44:05 +1000 Subject: 3.5.3 --- src/js/config/defaults.js | 2 +- src/js/plyr.js | 2 +- src/js/plyr.polyfilled.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/js') diff --git a/src/js/config/defaults.js b/src/js/config/defaults.js index c45131bc..f276a2df 100644 --- a/src/js/config/defaults.js +++ b/src/js/config/defaults.js @@ -61,7 +61,7 @@ const defaults = { // Sprite (for icons) loadSprite: true, iconPrefix: 'plyr', - iconUrl: 'https://cdn.plyr.io/3.5.2/plyr.svg', + iconUrl: 'https://cdn.plyr.io/3.5.3/plyr.svg', // Blank video (used to prevent errors on source change) blankVideo: 'https://cdn.plyr.io/static/blank.mp4', diff --git a/src/js/plyr.js b/src/js/plyr.js index 1dd3ecb9..c252d052 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -1,6 +1,6 @@ // ========================================================================== // Plyr -// plyr.js v3.5.2 +// plyr.js v3.5.3 // https://github.com/sampotts/plyr // License: The MIT License (MIT) // ========================================================================== diff --git a/src/js/plyr.polyfilled.js b/src/js/plyr.polyfilled.js index 8623e41a..ce41151b 100644 --- a/src/js/plyr.polyfilled.js +++ b/src/js/plyr.polyfilled.js @@ -1,6 +1,6 @@ // ========================================================================== // Plyr Polyfilled Build -// plyr.js v3.5.2 +// plyr.js v3.5.3 // https://github.com/sampotts/plyr // License: The MIT License (MIT) // ========================================================================== -- 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/controls.js | 6 +++--- src/js/listeners.js | 2 +- src/js/plugins/vimeo.js | 6 +++--- src/js/plyr.js | 13 +++++++++++++ 4 files changed, 20 insertions(+), 7 deletions(-) (limited to 'src/js') diff --git a/src/js/controls.js b/src/js/controls.js index 73903e16..78d3144f 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -1244,8 +1244,8 @@ const controls = { controls.focusFirstMenuItem.call(this, target, tabFocus); }, - // Set the download link - setDownloadLink() { + // Set the download URL + setDownloadUrl() { const button = this.elements.buttons.download; // Bail if no button @@ -1253,7 +1253,7 @@ const controls = { return; } - // Set download link + // Set attribute button.setAttribute('href', this.download); }, diff --git a/src/js/listeners.js b/src/js/listeners.js index 5a593b10..b463498f 100644 --- a/src/js/listeners.js +++ b/src/js/listeners.js @@ -486,7 +486,7 @@ class Listeners { // Update download link when ready and if quality changes on.call(player, player.media, 'ready qualitychange', () => { - controls.setDownloadLink.call(player); + controls.setDownloadUrl.call(player); }); // Proxy events to container 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); diff --git a/src/js/plyr.js b/src/js/plyr.js index 1dd3ecb9..0a804437 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -823,6 +823,19 @@ class Plyr { return is.url(download) ? download : this.source; } + /** + * Set the download URL + */ + set download(input) { + if (!is.url(input)) { + return; + } + + this.config.urls.download = input; + + controls.setDownloadUrl.call(this); + } + /** * Set the poster image for a video * @param {String} input - the URL for the new poster image -- cgit v1.2.3 From e9367ee85e443b28b003e3ff79ac0e2445879aa4 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Fri, 12 Apr 2019 20:18:17 +1000 Subject: Fix setting initial speed (fixes #1408) --- src/js/plyr.js | 4 +++- src/js/ui.js | 29 +++++++++++++++++------------ 2 files changed, 20 insertions(+), 13 deletions(-) (limited to 'src/js') diff --git a/src/js/plyr.js b/src/js/plyr.js index 3b169321..d67fae83 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -678,7 +678,9 @@ class Plyr { this.config.speed.selected = speed; // Set media speed - this.media.playbackRate = speed; + setTimeout(() => { + this.media.playbackRate = speed; + }, 0); } /** diff --git a/src/js/ui.js b/src/js/ui.js index 8e50bb83..50de7df1 100644 --- a/src/js/ui.js +++ b/src/js/ui.js @@ -67,15 +67,15 @@ const ui = { // Reset mute state this.muted = null; - // Reset speed - this.speed = null; - // Reset loop state this.loop = null; // Reset quality setting this.quality = null; + // Reset speed + this.speed = null; + // Reset volume display controls.updateVolume.call(this); @@ -233,13 +233,16 @@ const ui = { clearTimeout(this.timers.loading); // Timer to prevent flicker when seeking - this.timers.loading = setTimeout(() => { - // Update progress bar loading class state - toggleClass(this.elements.container, this.config.classNames.loading, this.loading); - - // Update controls visibility - ui.toggleControls.call(this); - }, this.loading ? 250 : 0); + this.timers.loading = setTimeout( + () => { + // Update progress bar loading class state + toggleClass(this.elements.container, this.config.classNames.loading, this.loading); + + // Update controls visibility + ui.toggleControls.call(this); + }, + this.loading ? 250 : 0, + ); }, // Toggle controls based on state and `force` argument @@ -248,10 +251,12 @@ const ui = { if (controls && this.config.hideControls) { // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.) - const recentTouchSeek = (this.touch && this.lastSeekTime + 2000 > Date.now()); + const recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide - this.toggleControls(Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek)); + this.toggleControls( + Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek), + ); } }, }; -- cgit v1.2.3 From b675ba1f350207071526453d0e03153225dc4c63 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Sat, 13 Apr 2019 12:55:48 +1000 Subject: Fix issue with setGutter call --- src/js/listeners.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/js') diff --git a/src/js/listeners.js b/src/js/listeners.js index b463498f..eb621207 100644 --- a/src/js/listeners.js +++ b/src/js/listeners.js @@ -356,7 +356,7 @@ class Listeners { const { padding, ratio } = setPlayerSize(isEnter); // Set Vimeo gutter - setGutter(ratio, padding, isEnter); + setGutter.call(player, ratio, padding, isEnter); // If not using native fullscreen, we need to check for resizes of viewport if (!usingNative) { -- 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') 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 2cf44c236d586ca07f03744a3df8ffeff425b8f7 Mon Sep 17 00:00:00 2001 From: Emiel Beinema Date: Mon, 15 Apr 2019 12:16:48 +0200 Subject: Use querySelector on container for showMenuPanel --- src/js/controls.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/js') diff --git a/src/js/controls.js b/src/js/controls.js index 78d3144f..104f5c95 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -1191,7 +1191,7 @@ const controls = { // Show a panel in the menu showMenuPanel(type = '', tabFocus = false) { - const target = document.getElementById(`plyr-settings-${this.id}-${type}`); + const target = this.elements.container.querySelector(`#plyr-settings-${this.id}-${type}`); // Nothing to show, bail if (!is.element(target)) { -- cgit v1.2.3 From a91652287b10237552b6b1ac87c8286aff4f583d Mon Sep 17 00:00:00 2001 From: Emiel Beinema Date: Mon, 15 Apr 2019 12:17:10 +0200 Subject: Don't close menu on click in menu in webcomponent --- src/js/controls.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/js') diff --git a/src/js/controls.js b/src/js/controls.js index 104f5c95..275ffb3f 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -1138,7 +1138,9 @@ const controls = { } else if (is.keyboardEvent(input) && input.which === 27) { show = false; } else if (is.event(input)) { - const isMenuItem = popup.contains(input.target); + // If Plyr is in a shadowDOM, the event target is set to the component, instead of the + // element in the shadowDOM. The path, however, is complete. + const isMenuItem = popup.contains(input.path[0]); // If the click was inside the menu or if the click // wasn't the button or menu item and we're trying to -- cgit v1.2.3 From b2fff4c33f45c8e61bbe1f6549e69ef46ef8b2fa Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Mon, 15 Apr 2019 22:08:09 +1000 Subject: Increase speed limits --- src/js/plyr.js | 52 +++++++++++++++++++++++++++++++++++++------------ src/js/utils/numbers.js | 17 ++++++++++++++++ 2 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 src/js/utils/numbers.js (limited to 'src/js') diff --git a/src/js/plyr.js b/src/js/plyr.js index d67fae83..be1cba4b 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -25,6 +25,7 @@ import { createElement, hasClass, removeElement, replaceElement, toggleClass, wr import { off, on, once, triggerEvent, unbindListeners } from './utils/events'; import is from './utils/is'; import loadSprite from './utils/loadSprite'; +import { clamp } from './utils/numbers'; import { cloneDeep, extend } from './utils/objects'; import { getAspectRatio, reduceAspectRatio, setAspectRatio, validateRatio } from './utils/style'; import { parseUrl } from './utils/urls'; @@ -661,18 +662,9 @@ class Plyr { speed = this.config.speed.selected; } - // Set min/max - if (speed < 0.1) { - speed = 0.1; - } - if (speed > 2.0) { - speed = 2.0; - } - - if (!this.config.speed.options.includes(speed)) { - this.debug.warn(`Unsupported speed (${speed})`); - return; - } + // Clamp to min/max + const { minimumSpeed: min, maximumSpeed: max } = this; + speed = clamp(speed, min, max); // Update config this.config.speed.selected = speed; @@ -690,6 +682,42 @@ class Plyr { return Number(this.media.playbackRate); } + /** + * Get the minimum allowed speed + */ + get minimumSpeed() { + if (this.isYouTube) { + // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate + return Math.min(...this.options.speed); + } + + if (this.isVimeo) { + // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror + return 0.5; + } + + // https://stackoverflow.com/a/32320020/1191319 + return 0.0625; + } + + /** + * Get the maximum allowed speed + */ + get maximumSpeed() { + if (this.isYouTube) { + // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate + return Math.max(...this.options.speed); + } + + if (this.isVimeo) { + // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror + return 2; + } + + // https://stackoverflow.com/a/32320020/1191319 + return 16; + } + /** * Set playback quality * Currently HTML5 & YouTube only diff --git a/src/js/utils/numbers.js b/src/js/utils/numbers.js new file mode 100644 index 00000000..f6eb65c8 --- /dev/null +++ b/src/js/utils/numbers.js @@ -0,0 +1,17 @@ +/** + * Returns a number whose value is limited to the given range. + * + * Example: limit the output of this computation to between 0 and 255 + * (x * 255).clamp(0, 255) + * + * @param {Number} input + * @param {Number} min The lower boundary of the output range + * @param {Number} max The upper boundary of the output range + * @returns A number in the range [min, max] + * @type Number + */ +export function clamp(input = 0, min = 0, max = 255) { + return Math.min(Math.max(input, min), max); +} + +export default { clamp }; -- cgit v1.2.3 From e147f3a754765a8d21899751e8e8cf283929abfd Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Thu, 25 Apr 2019 12:01:00 +1000 Subject: Formatting --- src/js/captions.js | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'src/js') diff --git a/src/js/captions.js b/src/js/captions.js index ae4642aa..b326d85e 100644 --- a/src/js/captions.js +++ b/src/js/captions.js @@ -124,19 +124,21 @@ const captions = { // Handle tracks (add event listener and "pseudo"-default) if (this.isHTML5 && this.isVideo) { - tracks.filter(track => !meta.get(track)).forEach(track => { - this.debug.log('Track added', track); - // Attempt to store if the original dom element was "default" - meta.set(track, { - default: track.mode === 'showing', + tracks + .filter(track => !meta.get(track)) + .forEach(track => { + this.debug.log('Track added', track); + // Attempt to store if the original dom element was "default" + meta.set(track, { + default: track.mode === 'showing', + }); + + // Turn off native caption rendering to avoid double captions + track.mode = 'hidden'; + + // Add event listener for cue changes + on.call(this, track, 'cuechange', () => captions.updateCues.call(this)); }); - - // Turn off native caption rendering to avoid double captions - track.mode = 'hidden'; - - // Add event listener for cue changes - on.call(this, track, 'cuechange', () => captions.updateCues.call(this)); - }); } // Update language first time it matches, or if the previous matching track was removed @@ -300,10 +302,12 @@ const captions = { const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default); const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a)); let track; + languages.every(language => { track = sorted.find(track => track.language === language); return !track; // Break iteration if there is a match }); + // If no match is found but is required, get first return track || (force ? sorted[0] : undefined); }, @@ -360,6 +364,7 @@ const captions = { // Get cues from track if (!cues) { const track = captions.getCurrentTrack.call(this); + cues = Array.from((track || {}).activeCues || []) .map(cue => cue.getCueAsHTML()) .map(getHTML); -- cgit v1.2.3 From ad68d9484f92eca434c1d6feef29af321b4955af Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Thu, 25 Apr 2019 12:01:30 +1000 Subject: Clean up and API change --- src/js/config/defaults.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'src/js') diff --git a/src/js/config/defaults.js b/src/js/config/defaults.js index f276a2df..6ba6d323 100644 --- a/src/js/config/defaults.js +++ b/src/js/config/defaults.js @@ -61,7 +61,7 @@ const defaults = { // Sprite (for icons) loadSprite: true, iconPrefix: 'plyr', - iconUrl: 'https://cdn.plyr.io/3.5.3/plyr.svg', + iconUrl: 'https://cdn.plyr.io/3.5.2/plyr.svg', // Blank video (used to prevent errors on source change) blankVideo: 'https://cdn.plyr.io/static/blank.mp4', @@ -195,8 +195,7 @@ const defaults = { }, youtube: { sdk: 'https://www.youtube.com/iframe_api', - api: - 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet', + api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}', // 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title),fileDetails)&part=snippet', }, googleIMA: { sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js', @@ -320,9 +319,6 @@ const defaults = { progress: '.plyr__progress', captions: '.plyr__captions', caption: '.plyr__caption', - menu: { - quality: '.js-plyr__menu__list--quality', - }, }, // Class hooks added to the player in different states @@ -396,11 +392,6 @@ const defaults = { }, }, - // API keys - keys: { - google: null, - }, - // Advertisements plugin // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio ads: { -- cgit v1.2.3 From f0d3e8c3b95886f64ef5216a665f5644929359b6 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Thu, 25 Apr 2019 12:01:52 +1000 Subject: Fix for className being wiped out --- src/js/controls.js | 534 ++++++++++++++++++++++++++++------------------------- 1 file changed, 284 insertions(+), 250 deletions(-) (limited to 'src/js') diff --git a/src/js/controls.js b/src/js/controls.js index 78d3144f..d836184c 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -172,7 +172,7 @@ const controls = { // Create a