aboutsummaryrefslogtreecommitdiffstats
path: root/src/js/plyr.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/plyr.js')
-rw-r--r--src/js/plyr.js156
1 files changed, 80 insertions, 76 deletions
diff --git a/src/js/plyr.js b/src/js/plyr.js
index 0786334d..1031efb2 100644
--- a/src/js/plyr.js
+++ b/src/js/plyr.js
@@ -6,9 +6,10 @@
// ==========================================================================
import captions from './captions';
+import defaults from './config/defaults';
+import { getProviderByUrl, providers, types } from './config/types';
import Console from './console';
import controls from './controls';
-import defaults from './defaults';
import Fullscreen from './fullscreen';
import Listeners from './listeners';
import media from './media';
@@ -16,9 +17,14 @@ import Ads from './plugins/ads';
import source from './source';
import Storage from './storage';
import support from './support';
-import { providers, types } from './types';
import ui from './ui';
-import utils from './utils';
+import { closest } from './utils/arrays';
+import { createElement, hasClass, removeElement, replaceElement, toggleClass, toggleState, wrap } from './utils/elements';
+import { off, on, trigger } from './utils/events';
+import is from './utils/is';
+import loadSprite from './utils/loadScript';
+import { cloneDeep, extend } from './utils/objects';
+import { parseUrl } from './utils/urls';
// Private properties
// TODO: Use a WeakMap for private globals
@@ -41,18 +47,18 @@ class Plyr {
this.media = target;
// String selector passed
- if (utils.is.string(this.media)) {
+ if (is.string(this.media)) {
this.media = document.querySelectorAll(this.media);
}
// jQuery, NodeList or Array passed, use first element
- if ((window.jQuery && this.media instanceof jQuery) || utils.is.nodeList(this.media) || utils.is.array(this.media)) {
+ if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) {
// eslint-disable-next-line
this.media = this.media[0];
}
// Set config
- this.config = utils.extend(
+ this.config = extend(
{},
defaults,
Plyr.defaults,
@@ -108,7 +114,7 @@ class Plyr {
this.debug.log('Support', support);
// We need an element to setup
- if (utils.is.nullOrUndefined(this.media) || !utils.is.element(this.media)) {
+ if (is.nullOrUndefined(this.media) || !is.element(this.media)) {
this.debug.error('Setup failed: no suitable element passed');
return;
}
@@ -144,7 +150,6 @@ class Plyr {
// Embed properties
let iframe = null;
let url = null;
- let params = null;
// Different setup based on type
switch (type) {
@@ -153,10 +158,10 @@ class Plyr {
iframe = this.media.querySelector('iframe');
// <iframe> type
- if (utils.is.element(iframe)) {
+ if (is.element(iframe)) {
// Detect provider
- url = iframe.getAttribute('src');
- this.provider = utils.getProviderByUrl(url);
+ url = parseUrl(iframe.getAttribute('src'));
+ this.provider = getProviderByUrl(url.toString());
// Rework elements
this.elements.container = this.media;
@@ -166,24 +171,23 @@ class Plyr {
this.elements.container.className = '';
// Get attributes from URL and set config
- params = utils.getUrlParams(url);
- if (!utils.is.empty(params)) {
+ if (!url.searchParams) {
const truthy = [
'1',
'true',
];
- if (truthy.includes(params.autoplay)) {
+ if (truthy.includes(url.searchParams.get('autoplay'))) {
this.config.autoplay = true;
}
- if (truthy.includes(params.loop)) {
+ if (truthy.includes(url.searchParams.get('loop'))) {
this.config.loop.active = true;
}
// TODO: replace fullscreen.iosNative with this playsinline config option
// YouTube requires the playsinline in the URL
if (this.isYouTube) {
- this.config.playsinline = truthy.includes(params.playsinline);
+ this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));
} else {
this.config.playsinline = true;
}
@@ -197,7 +201,7 @@ class Plyr {
}
// Unsupported or missing provider
- if (utils.is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {
+ if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {
this.debug.error('Setup failed: Invalid provider');
return;
}
@@ -255,9 +259,9 @@ class Plyr {
this.media.plyr = this;
// Wrap media
- if (!utils.is.element(this.elements.container)) {
- this.elements.container = utils.createElement('div');
- utils.wrap(this.media, this.elements.container);
+ if (!is.element(this.elements.container)) {
+ this.elements.container = createElement('div');
+ wrap(this.media, this.elements.container);
}
// Allow focus to be captured
@@ -271,7 +275,7 @@ class Plyr {
// Listen for events if debugging
if (this.config.debug) {
- utils.on(this.elements.container, this.config.events.join(' '), event => {
+ on(this.elements.container, this.config.events.join(' '), event => {
this.debug.log(`event: ${event.type}`);
});
}
@@ -330,7 +334,7 @@ class Plyr {
* Play the media, or play the advertisement (if they are not blocked)
*/
play() {
- if (!utils.is.function(this.media.play)) {
+ if (!is.function(this.media.play)) {
return null;
}
@@ -342,7 +346,7 @@ class Plyr {
* Pause the media
*/
pause() {
- if (!this.playing || !utils.is.function(this.media.pause)) {
+ if (!this.playing || !is.function(this.media.pause)) {
return;
}
@@ -383,7 +387,7 @@ class Plyr {
*/
togglePlay(input) {
// Toggle based on current state if nothing passed
- const toggle = utils.is.boolean(input) ? input : !this.playing;
+ const toggle = is.boolean(input) ? input : !this.playing;
if (toggle) {
this.play();
@@ -399,7 +403,7 @@ class Plyr {
if (this.isHTML5) {
this.pause();
this.restart();
- } else if (utils.is.function(this.media.stop)) {
+ } else if (is.function(this.media.stop)) {
this.media.stop();
}
}
@@ -416,7 +420,7 @@ class Plyr {
* @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime
*/
rewind(seekTime) {
- this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime);
+ this.currentTime = this.currentTime - (is.number(seekTime) ? seekTime : this.config.seekTime);
}
/**
@@ -424,7 +428,7 @@ class Plyr {
* @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime
*/
forward(seekTime) {
- this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime);
+ this.currentTime = this.currentTime + (is.number(seekTime) ? seekTime : this.config.seekTime);
}
/**
@@ -438,7 +442,7 @@ class Plyr {
}
// Validate input
- const inputIsValid = utils.is.number(input) && input > 0;
+ const inputIsValid = is.number(input) && input > 0;
// Set
this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0;
@@ -461,7 +465,7 @@ class Plyr {
const { buffered } = this.media;
// YouTube / Vimeo return a float between 0-1
- if (utils.is.number(buffered)) {
+ if (is.number(buffered)) {
return buffered;
}
@@ -505,17 +509,17 @@ class Plyr {
const max = 1;
const min = 0;
- if (utils.is.string(volume)) {
+ if (is.string(volume)) {
volume = Number(volume);
}
// Load volume from storage if no value specified
- if (!utils.is.number(volume)) {
+ if (!is.number(volume)) {
volume = this.storage.get('volume');
}
// Use config if all else fails
- if (!utils.is.number(volume)) {
+ if (!is.number(volume)) {
({ volume } = this.config);
}
@@ -535,7 +539,7 @@ class Plyr {
this.media.volume = volume;
// If muted, and we're increasing volume manually, reset muted state
- if (!utils.is.empty(value) && this.muted && volume > 0) {
+ if (!is.empty(value) && this.muted && volume > 0) {
this.muted = false;
}
}
@@ -553,7 +557,7 @@ class Plyr {
*/
increaseVolume(step) {
const volume = this.media.muted ? 0 : this.volume;
- this.volume = volume + (utils.is.number(step) ? step : 1);
+ this.volume = volume + (is.number(step) ? step : 1);
}
/**
@@ -562,7 +566,7 @@ class Plyr {
*/
decreaseVolume(step) {
const volume = this.media.muted ? 0 : this.volume;
- this.volume = volume - (utils.is.number(step) ? step : 1);
+ this.volume = volume - (is.number(step) ? step : 1);
}
/**
@@ -573,12 +577,12 @@ class Plyr {
let toggle = mute;
// Load muted state from storage
- if (!utils.is.boolean(toggle)) {
+ if (!is.boolean(toggle)) {
toggle = this.storage.get('muted');
}
// Use config if all else fails
- if (!utils.is.boolean(toggle)) {
+ if (!is.boolean(toggle)) {
toggle = this.config.muted;
}
@@ -624,15 +628,15 @@ class Plyr {
set speed(input) {
let speed = null;
- if (utils.is.number(input)) {
+ if (is.number(input)) {
speed = input;
}
- if (!utils.is.number(speed)) {
+ if (!is.number(speed)) {
speed = this.storage.get('speed');
}
- if (!utils.is.number(speed)) {
+ if (!is.number(speed)) {
speed = this.config.speed.selected;
}
@@ -671,19 +675,19 @@ class Plyr {
set quality(input) {
let quality = null;
- if (!utils.is.empty(input)) {
+ if (!is.empty(input)) {
quality = Number(input);
}
- if (!utils.is.number(quality)) {
+ if (!is.number(quality)) {
quality = this.storage.get('quality');
}
- if (!utils.is.number(quality)) {
+ if (!is.number(quality)) {
quality = this.config.quality.selected;
}
- if (!utils.is.number(quality)) {
+ if (!is.number(quality)) {
quality = this.config.quality.default;
}
@@ -692,9 +696,9 @@ class Plyr {
}
if (!this.options.quality.includes(quality)) {
- const closest = utils.closest(this.options.quality, quality);
- this.debug.warn(`Unsupported quality option: ${quality}, using ${closest} instead`);
- quality = closest;
+ const value = closest(this.options.quality, quality);
+ this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);
+ quality = value;
}
// Update config
@@ -717,7 +721,7 @@ class Plyr {
* @param {boolean} input - Whether to loop or not
*/
set loop(input) {
- const toggle = utils.is.boolean(input) ? input : this.config.loop.active;
+ const toggle = is.boolean(input) ? input : this.config.loop.active;
this.config.loop.active = toggle;
this.media.loop = toggle;
@@ -816,7 +820,7 @@ class Plyr {
* @param {boolean} input - Whether to autoplay or not
*/
set autoplay(input) {
- const toggle = utils.is.boolean(input) ? input : this.config.autoplay;
+ const toggle = is.boolean(input) ? input : this.config.autoplay;
this.config.autoplay = toggle;
}
@@ -838,18 +842,18 @@ class Plyr {
}
// If the method is called without parameter, toggle based on current value
- const active = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active);
+ const active = is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active);
// Toggle state
- utils.toggleState(this.elements.buttons.captions, active);
+ toggleState(this.elements.buttons.captions, active);
// Add class hook
- utils.toggleClass(this.elements.container, this.config.classNames.captions.active, active);
+ toggleClass(this.elements.container, this.config.classNames.captions.active, active);
// Update state and trigger event
if (active !== this.captions.active) {
this.captions.active = active;
- utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled');
+ trigger.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled');
}
}
@@ -902,7 +906,7 @@ class Plyr {
}
// Toggle based on current state if not passed
- const toggle = utils.is.boolean(input) ? input : this.pip === states.inline;
+ const toggle = is.boolean(input) ? input : this.pip === states.inline;
// Toggle based on current state
this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);
@@ -938,22 +942,22 @@ class Plyr {
// Don't toggle if missing UI support or if it's audio
if (this.supported.ui && !this.isAudio) {
// Get state before change
- const isHidden = utils.hasClass(this.elements.container, this.config.classNames.hideControls);
+ const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls);
// Negate the argument if not undefined since adding the class to hides the controls
const force = typeof toggle === 'undefined' ? undefined : !toggle;
// Apply and get updated state
- const hiding = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, force);
+ const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);
// Close menu
- if (hiding && this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {
+ if (hiding && this.config.controls.includes('settings') && !is.empty(this.config.settings)) {
controls.toggleMenu.call(this, false);
}
// Trigger event on change
if (hiding !== isHidden) {
const eventName = hiding ? 'controlshidden' : 'controlsshown';
- utils.dispatchEvent.call(this, this.media, eventName);
+ trigger.call(this, this.media, eventName);
}
return !hiding;
}
@@ -966,7 +970,7 @@ class Plyr {
* @param {function} callback - Callback for when event occurs
*/
on(event, callback) {
- utils.on(this.elements.container, event, callback);
+ on(this.elements.container, event, callback);
}
/**
@@ -975,7 +979,7 @@ class Plyr {
* @param {function} callback - Callback for when event occurs
*/
off(event, callback) {
- utils.off(this.elements.container, event, callback);
+ off(this.elements.container, event, callback);
}
/**
@@ -1001,10 +1005,10 @@ class Plyr {
if (soft) {
if (Object.keys(this.elements).length) {
// Remove elements
- utils.removeElement(this.elements.buttons.play);
- utils.removeElement(this.elements.captions);
- utils.removeElement(this.elements.controls);
- utils.removeElement(this.elements.wrapper);
+ removeElement(this.elements.buttons.play);
+ removeElement(this.elements.captions);
+ removeElement(this.elements.controls);
+ removeElement(this.elements.wrapper);
// Clear for GC
this.elements.buttons.play = null;
@@ -1014,7 +1018,7 @@ class Plyr {
}
// Callback
- if (utils.is.function(callback)) {
+ if (is.function(callback)) {
callback();
}
} else {
@@ -1022,13 +1026,13 @@ class Plyr {
this.listeners.clear();
// Replace the container with the original element provided
- utils.replaceElement(this.elements.original, this.elements.container);
+ replaceElement(this.elements.original, this.elements.container);
// Event
- utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true);
+ trigger.call(this, this.elements.original, 'destroyed', true);
// Callback
- if (utils.is.function(callback)) {
+ if (is.function(callback)) {
callback.call(this.elements.original);
}
@@ -1067,7 +1071,7 @@ class Plyr {
clearInterval(this.timers.playing);
// Destroy YouTube API
- if (this.embed !== null && utils.is.function(this.embed.destroy)) {
+ if (this.embed !== null && is.function(this.embed.destroy)) {
this.embed.destroy();
}
@@ -1117,7 +1121,7 @@ class Plyr {
* @param {string} [id] - Unique ID
*/
static loadSprite(url, id) {
- return utils.loadSprite(url, id);
+ return loadSprite(url, id);
}
/**
@@ -1128,15 +1132,15 @@ class Plyr {
static setup(selector, options = {}) {
let targets = null;
- if (utils.is.string(selector)) {
+ if (is.string(selector)) {
targets = Array.from(document.querySelectorAll(selector));
- } else if (utils.is.nodeList(selector)) {
+ } else if (is.nodeList(selector)) {
targets = Array.from(selector);
- } else if (utils.is.array(selector)) {
- targets = selector.filter(utils.is.element);
+ } else if (is.array(selector)) {
+ targets = selector.filter(is.element);
}
- if (utils.is.empty(targets)) {
+ if (is.empty(targets)) {
return null;
}
@@ -1144,6 +1148,6 @@ class Plyr {
}
}
-Plyr.defaults = utils.cloneDeep(defaults);
+Plyr.defaults = cloneDeep(defaults);
export default Plyr;