Utils broken down into seperate files and exports

This commit is contained in:
Sam Potts
2018-06-13 00:02:55 +10:00
parent 840e31a693
commit 392dfd024c
42 changed files with 5282 additions and 5316 deletions

View File

@ -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;