Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugins #1840

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
57 changes: 29 additions & 28 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
{
"parser": "babel-eslint",
"extends": ["airbnb-base", "prettier"],
"plugins": ["simple-import-sort", "import"],
"env": {
"browser": true,
"es6": true
},
"globals": {
"Plyr": false,
"jQuery": false
},
"rules": {
"import/no-cycle": "warn",
"padding-line-between-statements": [
"error",
{
"blankLine": "never",
"prev": ["singleline-const", "singleline-let", "singleline-var"],
"next": ["singleline-const", "singleline-let", "singleline-var"]
}
],
"sort-imports": "off",
"import/order": "off",
"simple-import-sort/sort": "error"
},
"parserOptions": {
"sourceType": "module"
}
"parser": "babel-eslint",
"extends": ["airbnb-base", "prettier"],
"plugins": ["simple-import-sort", "import"],
"env": {
"browser": true,
"es6": true
},
"globals": {
"Plyr": false,
"jQuery": false
},
"rules": {
"import/no-cycle": "warn",
"no-param-reassign": ["error", { "props": false }],
"padding-line-between-statements": [
"error",
{
"blankLine": "never",
"prev": ["singleline-const", "singleline-let", "singleline-var"],
"next": ["singleline-const", "singleline-let", "singleline-var"]
}
],
"sort-imports": "off",
"import/order": "off",
"simple-import-sort/sort": "error"
},
"parserOptions": {
"sourceType": "module"
}
}
2 changes: 1 addition & 1 deletion src/js/captions.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const captions = {
}

// Only Vimeo and HTML5 video supported at this point
if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {
if (!this.isVideo || !this.provider.supportCaptions || (this.isHTML5 && !support.textTracks)) {
// Clear menu and hide
if (
is.array(this.config.controls) &&
Expand Down
35 changes: 0 additions & 35 deletions src/js/config/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,15 +197,6 @@ const defaults = {
// URLs
urls: {
download: null,
vimeo: {
sdk: 'https://player.vimeo.com/api/player.js',
iframe: 'https://player.vimeo.com/video/{0}?{1}',
api: 'https://vimeo.com/api/v2/video/{0}.json',
},
youtube: {
sdk: 'https://www.youtube.com/iframe_api',
api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}',
},
googleIMA: {
sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',
},
Expand Down Expand Up @@ -268,9 +259,6 @@ const defaults = {
'controlsshown',
'ready',

// YouTube
'statechange',

// Quality
'qualitychange',

Expand Down Expand Up @@ -414,29 +402,6 @@ const defaults = {
enabled: false,
src: '',
},

// Vimeo plugin
vimeo: {
byline: false,
portrait: false,
title: false,
speed: true,
transparent: false,
// Whether the owner of the video has a Pro or Business account
// (which allows us to properly hide controls without CSS hacks, etc)
premium: false,
// Custom settings from Plyr
referrerPolicy: null, // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
},

// YouTube plugin
youtube: {
noCookie: true, // Whether to use an alternative version of YouTube without cookies
rel: 0, // No related vids
showinfo: 0, // Hide info
iv_load_policy: 3, // Hide annotations
modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)
},
};

export default defaults;
26 changes: 1 addition & 25 deletions src/js/config/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,9 @@
// Plyr supported types and providers
// ==========================================================================

export const providers = {
html5: 'html5',
youtube: 'youtube',
vimeo: 'vimeo',
};

export const types = {
audio: 'audio',
video: 'video',
};

/**
* Get provider by URL
* @param {String} url
*/
export function getProviderByUrl(url) {
// YouTube
if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(url)) {
return providers.youtube;
}

// Vimeo
if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) {
return providers.vimeo;
}

return null;
}

export default { providers, types };
export default { types };
8 changes: 4 additions & 4 deletions src/js/controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import RangeTouch from 'rangetouch';

import captions from './captions';
import html5 from './html5';
import support from './support';
import { repaint, transitionEndEvent } from './utils/animation';
import { dedupe } from './utils/arrays';
Expand Down Expand Up @@ -1275,7 +1274,7 @@ const controls = {
const defaultAttributes = { class: 'plyr__controls__item' };

// Loop through controls in order
dedupe(is.array(this.config.controls) ? this.config.controls: []).forEach(control => {
dedupe(is.array(this.config.controls) ? this.config.controls : []).forEach(control => {
// Restart button
if (control === 'restart') {
container.appendChild(createButton.call(this, 'restart', defaultAttributes));
Expand Down Expand Up @@ -1596,9 +1595,10 @@ const controls = {
}
});

const qualityOptions = this.provider.getQualityOptions(this);
// Set available quality levels
if (this.isHTML5) {
setQualityMenu.call(this, html5.getQualityOptions.call(this));
if (qualityOptions.length > 0) {
setQualityMenu.call(this, qualityOptions);
}

setSpeedMenu.call(this);
Expand Down
86 changes: 53 additions & 33 deletions src/js/html5.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,39 @@
// Plyr HTML5 helpers
// ==========================================================================

import { types } from './config/types';
import PlyrProvider from './plugins/providers';
import support from './support';
import ui from './ui';
import { removeElement } from './utils/elements';
import { triggerEvent } from './utils/events';
import is from './utils/is';
import { silencePromise } from './utils/promise';
import { setAspectRatio } from './utils/style';

const html5 = {
getSources() {
if (!this.isHTML5) {
class HTML5Provider extends PlyrProvider {
static get name() {
return 'html5';
}

static type(player) {
return player.media.tagName.toLowerCase() === 'video' ? types.video : types.audio;
}

static get availableSpeed() {
return [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4];
}

static get supportCaptions() {
return true;
}

static getSources(player) {
if (!player.isHTML5) {
return [];
}

const sources = Array.from(this.media.querySelectorAll('source'));
const sources = Array.from(player.media.querySelectorAll('source'));

// Filter out unsupported sources (if type is specified)
return sources.filter(source => {
Expand All @@ -25,44 +44,38 @@ const html5 = {
return true;
}

return support.mime.call(this, type);
return support.mime.call(player, type);
});
},
}

// Get quality levels
getQualityOptions() {
static getQualityOptions(player) {
// Whether we're forcing all options (e.g. for streaming)
if (this.config.quality.forced) {
return this.config.quality.options;
if (player.config.quality.forced) {
return player.config.quality.options;
}

// Get sizes from <source> elements
return html5.getSources
.call(this)
return HTML5Provider.getSources(player)
.map(source => Number(source.getAttribute('size')))
.filter(Boolean);
},
}

setup() {
if (!this.isHTML5) {
static setup(player) {
if (!player.isHTML5) {
return;
}

const player = this;

// Set speed options from config
player.options.speed = player.config.speed.options;

// Set aspect ratio if fixed
if (!is.empty(this.config.ratio)) {
if (!is.empty(player.config.ratio)) {
setAspectRatio.call(player);
}

// Quality
Object.defineProperty(player.media, 'quality', {
get() {
// Get sources
const sources = html5.getSources.call(player);
const sources = HTML5Provider.getSources(player);
const source = sources.find(s => s.getAttribute('src') === player.source);

// Return size, if match is found
Expand All @@ -78,7 +91,7 @@ const html5 = {
player.config.quality.onChange(input);
} else {
// Get sources
const sources = html5.getSources.call(player);
const sources = HTML5Provider.getSources(player);
// Get first match for requested size
const source = sources.find(s => Number(s.getAttribute('size')) === input);

Expand All @@ -91,13 +104,15 @@ const html5 = {
const { currentTime, paused, preload, readyState, playbackRate } = player.media;

// Set new source
player.media.src = source.getAttribute('src');
player.media.setAttribute('src', source.getAttribute('src'));

// Prevent loading if preload="none" and the current source isn't loaded (#1044)
if (preload !== 'none' || readyState) {
// Restore time
player.once('loadedmetadata', () => {
// eslint-disable-next-line no-param-reassign
player.speed = playbackRate;
// eslint-disable-next-line no-param-reassign
player.currentTime = currentTime;

// Resume playing
Expand All @@ -117,31 +132,36 @@ const html5 = {
});
},
});
},
}

// Cancel current network requests
// See https://github.com/sampotts/plyr/issues/174
cancelRequests() {
if (!this.isHTML5) {
static cancelRequests(player) {
if (!player.isHTML5) {
return;
}

// Remove child sources
removeElement(html5.getSources.call(this));
removeElement(HTML5Provider.getSources(player));

// Set blank video src attribute
// This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error
// Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection
this.media.setAttribute('src', this.config.blankVideo);
player.media.setAttribute('src', player.config.blankVideo);

// Load the new empty source
// This will cancel existing requests
// See https://github.com/sampotts/plyr/issues/174
this.media.load();
player.media.load();

// Debugging
this.debug.log('Cancelled network requests');
},
};
player.debug.log('Cancelled network requests');
}

static async destroy(player) {
// Restore native video controls
ui.toggleNativeControls.call(player, true);
}
}

export default html5;
export default HTML5Provider;
Loading