aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSam Potts <sam@potts.es>2019-04-12 18:39:14 +1000
committerGitHub <noreply@github.com>2019-04-12 18:39:14 +1000
commit5fefabe3bddf705f3c3956152882b5ceab44c8dc (patch)
tree43c1b11c4361e02189ae643f525efb155d8a99d0 /src
parent0f3098040d8650a762067d1f1aa5ab520cb9b90c (diff)
parente281078441ad50c4b0b997b615b48fc0c254f173 (diff)
downloadplyr-5fefabe3bddf705f3c3956152882b5ceab44c8dc.tar.lz
plyr-5fefabe3bddf705f3c3956152882b5ceab44c8dc.tar.xz
plyr-5fefabe3bddf705f3c3956152882b5ceab44c8dc.zip
Merge pull request #1410 from sampotts/develop
v3.5.3
Diffstat (limited to 'src')
-rw-r--r--src/js/config/defaults.js6
-rw-r--r--src/js/html5.js4
-rw-r--r--src/js/listeners.js8
-rw-r--r--src/js/plugins/previewThumbnails.js11
-rw-r--r--src/js/plugins/vimeo.js2
-rw-r--r--src/js/plugins/youtube.js9
-rw-r--r--src/js/plyr.js41
-rw-r--r--src/js/utils/style.js67
-rw-r--r--src/sass/components/embed.scss36
-rw-r--r--src/sass/components/video.scss33
-rw-r--r--src/sass/plyr.scss1
11 files changed, 149 insertions, 69 deletions
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/previewThumbnails.js b/src/js/plugins/previewThumbnails.js
index bd7a6bbd..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]}`);
@@ -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);
}
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/plugins/youtube.js b/src/js/plugins/youtube.js
index 9c447f7d..d862e4dd 100644
--- a/src/js/plugins/youtube.js
+++ b/src/js/plugins/youtube.js
@@ -39,7 +39,12 @@ function getHost(config) {
return 'https://www.youtube-nocookie.com';
}
- return `${window.location.protocol}//www.youtube.com`;
+ if (window.location.protocol === 'http:') {
+ return 'http://www.youtube.com';
+ }
+
+ // Use YouTube's default
+ return undefined;
}
const youtube = {
@@ -394,7 +399,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);
diff --git a/src/js/plyr.js b/src/js/plyr.js
index 0d3d1674..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
@@ -301,8 +302,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
@@ -847,6 +848,34 @@ class Plyr {
}
/**
+ * 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
*/
@@ -1088,11 +1117,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);
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 };
diff --git a/src/sass/components/embed.scss b/src/sass/components/embed.scss
deleted file mode 100644
index 25431caf..00000000
--- a/src/sass/components/embed.scss
+++ /dev/null
@@ -1,36 +0,0 @@
-// --------------------------------------------------------------
-// Embedded players
-// YouTube, Vimeo, etc
-// --------------------------------------------------------------
-
-// Default to 16:9 ratio but this is set by JavaScript based on config
-$embed-padding: ((100 / 16) * 9);
-
-.plyr__video-embed {
- height: 0;
- padding-bottom: to-percentage($embed-padding);
- position: relative;
-
- iframe {
- border: 0;
- height: 100%;
- left: 0;
- position: absolute;
- top: 0;
- user-select: none;
- width: 100%;
- }
-}
-
-// If the full custom UI is supported
-.plyr--full-ui .plyr__video-embed {
- $height: 240;
- $offset: to-percentage(($height - $embed-padding) / ($height / 50));
-
- // Only used for Vimeo
- > .plyr__video-embed__container {
- padding-bottom: to-percentage($height);
- position: relative;
- transform: translateY(-$offset);
- }
-}
diff --git a/src/sass/components/video.scss b/src/sass/components/video.scss
index c3dc4152..fdcf4f2d 100644
--- a/src/sass/components/video.scss
+++ b/src/sass/components/video.scss
@@ -20,3 +20,36 @@
// Require z-index to force border-radius
z-index: 0;
}
+
+// Default to 16:9 ratio but this is set by JavaScript based on config
+$embed-padding: ((100 / 16) * 9);
+
+.plyr__video-embed,
+.plyr__video-wrapper--fixed-ratio {
+ height: 0;
+ padding-bottom: to-percentage($embed-padding);
+}
+
+.plyr__video-embed iframe,
+.plyr__video-wrapper--fixed-ratio video {
+ border: 0;
+ height: 100%;
+ left: 0;
+ position: absolute;
+ top: 0;
+ user-select: none;
+ width: 100%;
+}
+
+// If the full custom UI is supported
+.plyr--full-ui .plyr__video-embed {
+ $height: 240;
+ $offset: to-percentage(($height - $embed-padding) / ($height / 50));
+
+ // Only used for Vimeo
+ > .plyr__video-embed__container {
+ padding-bottom: to-percentage($height);
+ position: relative;
+ transform: translateY(-$offset);
+ }
+}
diff --git a/src/sass/plyr.scss b/src/sass/plyr.scss
index 468c534c..2b6cfa20 100644
--- a/src/sass/plyr.scss
+++ b/src/sass/plyr.scss
@@ -29,7 +29,6 @@
@import 'components/captions';
@import 'components/control';
@import 'components/controls';
-@import 'components/embed';
@import 'components/menus';
@import 'components/sliders';
@import 'components/poster';