diff options
author | Sam Potts <sam@potts.es> | 2018-06-17 01:04:55 +1000 |
---|---|---|
committer | Sam Potts <sam@potts.es> | 2018-06-17 01:04:55 +1000 |
commit | d4abb4b1438cb316aacae480e7b7e9b055a60b24 (patch) | |
tree | c23efc45b68bb159108ddfcbf4f90e26b31e7907 /src | |
parent | 828ce6694232f60d2fb463505757ccc767ae6c3b (diff) | |
download | plyr-d4abb4b1438cb316aacae480e7b7e9b055a60b24.tar.lz plyr-d4abb4b1438cb316aacae480e7b7e9b055a60b24.tar.xz plyr-d4abb4b1438cb316aacae480e7b7e9b055a60b24.zip |
120 line width, package upgrade
Diffstat (limited to 'src')
-rw-r--r-- | src/js/captions.js | 34 | ||||
-rw-r--r-- | src/js/config/defaults.js | 3 | ||||
-rw-r--r-- | src/js/controls.js | 38 | ||||
-rw-r--r-- | src/js/fullscreen.js | 24 | ||||
-rw-r--r-- | src/js/listeners.js | 99 | ||||
-rw-r--r-- | src/js/plugins/ads.js | 6 | ||||
-rw-r--r-- | src/js/plugins/youtube.js | 20 | ||||
-rw-r--r-- | src/js/plyr.js | 7 | ||||
-rw-r--r-- | src/js/source.js | 2 | ||||
-rw-r--r-- | src/js/ui.js | 61 | ||||
-rw-r--r-- | src/js/utils/elements.js | 7 | ||||
-rw-r--r-- | src/js/utils/events.js | 7 | ||||
-rw-r--r-- | src/js/utils/is.js | 5 | ||||
-rw-r--r-- | src/js/utils/strings.js | 5 |
14 files changed, 215 insertions, 103 deletions
diff --git a/src/js/captions.js b/src/js/captions.js index 94500290..28d5cb91 100644 --- a/src/js/captions.js +++ b/src/js/captions.js @@ -6,12 +6,20 @@ import controls from './controls'; import i18n from './i18n'; import support from './support'; +import { dedupe } from './utils/arrays'; import browser from './utils/browser'; -import { createElement, emptyElement, getAttributesFromSelector, insertAfter, removeElement, toggleClass, toggleState } from './utils/elements'; +import { + createElement, + emptyElement, + getAttributesFromSelector, + insertAfter, + removeElement, + toggleClass, + toggleState, +} from './utils/elements'; import { on, triggerEvent } from './utils/events'; import fetch from './utils/fetch'; import is from './utils/is'; -import { dedupe } from './utils/arrays'; import { getHTML } from './utils/strings'; import { parseUrl } from './utils/urls'; @@ -26,7 +34,11 @@ const captions = { // Only Vimeo and HTML5 video supported at this point if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) { // Clear menu and hide - if (is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { + if ( + is.array(this.config.controls) && + this.config.controls.includes('settings') && + this.config.settings.includes('captions') + ) { controls.setCaptionsMenu.call(this); } @@ -49,7 +61,11 @@ const captions = { const src = track.getAttribute('src'); const url = parseUrl(src); - if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) { + if ( + url !== null && + url.hostname !== window.location.href.hostname && + ['http:', 'https:'].includes(url.protocol) + ) { fetch(src, 'blob') .then(blob => { track.setAttribute('src', window.URL.createObjectURL(blob)); @@ -68,8 +84,9 @@ const captions = { // * active: The state preferred by user settings or config // * toggled: The real captions state - const languages = dedupe(Array.from(navigator.languages || navigator.userLanguage) - .map(language => language.split('-')[0])); + const languages = dedupe( + Array.from(navigator.languages || navigator.userLanguage).map(language => language.split('-')[0]), + ); let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase(); @@ -165,10 +182,7 @@ const captions = { // Force language if the call isn't passive and there is no matching language to toggle to if (!this.language && active && !passive) { const tracks = captions.getTracks.call(this); - const track = captions.findTrack.call(this, [ - this.captions.language, - ...this.captions.languages, - ], true); + const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true); // Override user preferences to avoid switching languages if a matching track is added this.captions.language = track.language; diff --git a/src/js/config/defaults.js b/src/js/config/defaults.js index 34fb5519..0e07b75c 100644 --- a/src/js/config/defaults.js +++ b/src/js/config/defaults.js @@ -197,7 +197,8 @@ 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://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet', }, googleIMA: { sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js', diff --git a/src/js/controls.js b/src/js/controls.js index 19c531af..d8d770a5 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -9,8 +9,20 @@ import support from './support'; import { repaint, transitionEndEvent } from './utils/animation'; import { dedupe } from './utils/arrays'; import browser from './utils/browser'; -import { createElement, emptyElement, getAttributesFromSelector, getElement, getElements, hasClass, removeElement, setAttributes, toggleClass, toggleHidden, toggleState } from './utils/elements'; -import { on, off } from './utils/events'; +import { + createElement, + emptyElement, + getAttributesFromSelector, + getElement, + getElements, + hasClass, + removeElement, + setAttributes, + toggleClass, + toggleHidden, + toggleState, +} from './utils/elements'; +import { off, on } from './utils/events'; import is from './utils/is'; import loadSprite from './utils/loadSprite'; import { extend } from './utils/objects'; @@ -68,7 +80,9 @@ const controls = { // Seek tooltip if (is.element(this.elements.progress)) { - this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`); + this.elements.display.seekTooltip = this.elements.progress.querySelector( + `.${this.config.classNames.tooltip}`, + ); } return true; @@ -331,10 +345,10 @@ const controls = { if (type !== 'volume') { progress.appendChild(createElement('span', null, '0')); - const suffixKey = ({ + const suffixKey = { played: 'played', buffer: 'buffered', - })[type]; + }[type]; const suffix = suffixKey ? i18n.get(suffixKey, this.config) : ''; @@ -519,7 +533,12 @@ const controls = { // Update hover tooltip for seeking updateSeekTooltip(event) { // Bail if setting not true - if (!this.config.tooltips.seek || !is.element(this.elements.inputs.seek) || !is.element(this.elements.display.seekTooltip) || this.duration === 0) { + if ( + !this.config.tooltips.seek || + !is.element(this.elements.inputs.seek) || + !is.element(this.elements.display.seekTooltip) || + this.duration === 0 + ) { return; } @@ -573,7 +592,12 @@ const controls = { const invert = !is.element(this.elements.display.duration) && this.config.invertTime; // Duration - controls.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); + controls.updateTimeDisplay.call( + this, + this.elements.display.currentTime, + invert ? this.duration - this.currentTime : this.currentTime, + invert, + ); // Ignore updates while seeking if (event && event.type === 'timeupdate' && this.media.seeking) { diff --git a/src/js/fullscreen.js b/src/js/fullscreen.js index a8d8b7e5..ded581f9 100644 --- a/src/js/fullscreen.js +++ b/src/js/fullscreen.js @@ -63,10 +63,15 @@ class Fullscreen { // Register event listeners // Handle event (incase user presses escape etc) - on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => { - // TODO: Filter for target?? - onChange.call(this); - }); + on.call( + this.player, + document, + this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, + () => { + // TODO: Filter for target?? + onChange.call(this); + }, + ); // Fullscreen toggle on double click on.call(this.player, this.player.elements.container, 'dblclick', event => { @@ -84,7 +89,12 @@ class Fullscreen { // Determine if native supported static get native() { - return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled); + return !!( + document.fullscreenEnabled || + document.webkitFullscreenEnabled || + document.mozFullScreenEnabled || + document.msFullscreenEnabled + ); } // Get the prefix for handlers @@ -142,7 +152,9 @@ class Fullscreen { // Get target element get target() { - return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; + return browser.isIos && this.player.config.fullscreen.iosNative + ? this.player.media + : this.player.elements.container; } // Update UI diff --git a/src/js/listeners.js b/src/js/listeners.js index d962761c..9d987508 100644 --- a/src/js/listeners.js +++ b/src/js/listeners.js @@ -52,9 +52,10 @@ class Listeners { // and if the focused element is not editable (e.g. text input) // and any that accept key input http://webaim.org/techniques/keyboard/ const focused = getFocusElement(); - if (is.element(focused) && ( - focused !== this.player.elements.inputs.seek && - matches(focused, this.player.config.selectors.editable)) + if ( + is.element(focused) && + (focused !== this.player.elements.inputs.seek && + matches(focused, this.player.config.selectors.editable)) ) { return; } @@ -174,7 +175,6 @@ class Listeners { // Add touch class toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true); - } // Global window & document listeners @@ -217,40 +217,49 @@ class Listeners { }); // Toggle controls on mouse events and entering fullscreen - on.call(this.player, this.player.elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', event => { - const { controls } = this.player.elements; + on.call( + this.player, + this.player.elements.container, + 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', + event => { + const { controls } = this.player.elements; - // Remove button states for fullscreen - if (event.type === 'enterfullscreen') { - controls.pressed = false; - controls.hover = false; - } + // Remove button states for fullscreen + if (event.type === 'enterfullscreen') { + controls.pressed = false; + controls.hover = false; + } - // Show, then hide after a timeout unless another control event occurs - const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type); + // Show, then hide after a timeout unless another control event occurs + const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type); - let delay = 0; + let delay = 0; - if (show) { - ui.toggleControls.call(this.player, true); - // Use longer timeout for touch devices - delay = this.player.touch ? 3000 : 2000; - } + if (show) { + ui.toggleControls.call(this.player, true); + // Use longer timeout for touch devices + delay = this.player.touch ? 3000 : 2000; + } - // Clear timer - clearTimeout(this.player.timers.controls); - // Timer to prevent flicker when seeking - this.player.timers.controls = setTimeout(() => ui.toggleControls.call(this.player, false), delay); - }); + // Clear timer + clearTimeout(this.player.timers.controls); + // Timer to prevent flicker when seeking + this.player.timers.controls = setTimeout(() => ui.toggleControls.call(this.player, false), delay); + }, + ); } // Listen for media events media() { // Time change on media - on.call(this.player, this.player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(this.player, event)); + on.call(this.player, this.player.media, 'timeupdate seeking seeked', event => + controls.timeUpdate.call(this.player, event), + ); // Display duration - on.call(this.player, this.player.media, 'durationchange loadeddata loadedmetadata', event => controls.durationUpdate.call(this.player, event)); + on.call(this.player, this.player.media, 'durationchange loadeddata loadedmetadata', event => + controls.durationUpdate.call(this.player, event), + ); // Check for audio tracks on load // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point @@ -269,16 +278,24 @@ class Listeners { }); // Check for buffer progress - on.call(this.player, this.player.media, 'progress playing seeking seeked', event => controls.updateProgress.call(this.player, event)); + on.call(this.player, this.player.media, 'progress playing seeking seeked', event => + controls.updateProgress.call(this.player, event), + ); // Handle volume changes - on.call(this.player, this.player.media, 'volumechange', event => controls.updateVolume.call(this.player, event)); + on.call(this.player, this.player.media, 'volumechange', event => + controls.updateVolume.call(this.player, event), + ); // Handle play/pause - on.call(this.player, this.player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(this.player, event)); + on.call(this.player, this.player.media, 'playing play pause ended emptied timeupdate', event => + ui.checkPlaying.call(this.player, event), + ); // Loading state - on.call(this.player, this.player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(this.player, event)); + on.call(this.player, this.player.media, 'waiting canplay seeked playing', event => + ui.checkLoading.call(this.player, event), + ); // If autoplay, then load advertisement if required // TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows @@ -324,7 +341,8 @@ class Listeners { // Disable right click if (this.player.supported.ui && this.player.config.disableContextMenu) { - on.call(this.player, + on.call( + this.player, this.player.elements.wrapper, 'contextmenu', event => { @@ -365,7 +383,7 @@ class Listeners { // Bubble up key events for Edge const proxyEvents = this.player.config.events.concat(['keyup', 'keydown']).join(' '); on.call(this.player, this.player.media, proxyEvents, event => { - let {detail = {}} = event; + let { detail = {} } = event; // Get error details from media if (event.type === 'error') { @@ -403,7 +421,13 @@ class Listeners { const customHandler = this.player.config.listeners[customHandlerKey]; const hasCustomHandler = is.function(customHandler); - on.call(this.player, element, type, event => proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler); + on.call( + this.player, + element, + type, + event => proxy(event, defaultHandler, customHandlerKey), + passive && !hasCustomHandler, + ); }; // Play/pause toggle @@ -592,7 +616,9 @@ class Listeners { } // Seek tooltip - bind(this.player.elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(this.player, event)); + bind(this.player.elements.progress, 'mouseenter mouseleave mousemove', event => + controls.updateSeekTooltip.call(this.player, event), + ); // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting) bind(this.player.elements.controls, 'mouseenter mouseleave', event => { @@ -665,7 +691,10 @@ class Listeners { } // Don't break page scrolling at max and min - if ((direction === 1 && this.player.media.volume < 1) || (direction === -1 && this.player.media.volume > 0)) { + if ( + (direction === 1 && this.player.media.volume < 1) || + (direction === -1 && this.player.media.volume > 0) + ) { event.preventDefault(); } }, diff --git a/src/js/plugins/ads.js b/src/js/plugins/ads.js index 19df7666..e0d49265 100644 --- a/src/js/plugins/ads.js +++ b/src/js/plugins/ads.js @@ -150,7 +150,11 @@ class Ads { this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events - this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, event => this.onAdsManagerLoaded(event), false); + this.loader.addEventListener( + google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, + event => this.onAdsManagerLoaded(event), + false, + ); this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false); // Request video ads diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 65b6db75..64b6fff7 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -210,13 +210,14 @@ const youtube = { if (!player.media.error) { const code = event.data; // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError - const message = ({ - 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.', - 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.', - 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.', - 101: 'The owner of the requested video does not allow it to be played in embedded players.', - 150: 'The owner of the requested video does not allow it to be played in embedded players.', - }[code]) || 'An unknown error occured'; + const message = + { + 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.', + 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.', + 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.', + 101: 'The owner of the requested video does not allow it to be played in embedded players.', + 150: 'The owner of the requested video does not allow it to be played in embedded players.', + }[code] || 'An unknown error occured'; player.media.error = { code, message }; @@ -453,7 +454,10 @@ const youtube = { } // Get quality - controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels())); + controls.setQualityMenu.call( + player, + mapQualityUnits(instance.getAvailableQualityLevels()), + ); } break; diff --git a/src/js/plyr.js b/src/js/plyr.js index dcbe384b..7ecb810a 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -679,7 +679,12 @@ class Plyr { return; } - let quality = [!is.empty(input) && Number(input), this.storage.get('quality'), config.selected, config.default].find(is.number); + let quality = [ + !is.empty(input) && Number(input), + this.storage.get('quality'), + config.selected, + config.default, + ].find(is.number); if (!options.includes(quality)) { const value = closest(options, quality); diff --git a/src/js/source.js b/src/js/source.js index c62db15a..8c9fdf44 100644 --- a/src/js/source.js +++ b/src/js/source.js @@ -8,8 +8,8 @@ import media from './media'; import support from './support'; import ui from './ui'; import { createElement, insertElement, removeElement } from './utils/elements'; -import { getDeep } from './utils/objects'; import is from './utils/is'; +import { getDeep } from './utils/objects'; const source = { // Add elements to HTML5 media (source, tracks, etc) diff --git a/src/js/ui.js b/src/js/ui.js index 5d7a6ae3..e0d7c6ae 100644 --- a/src/js/ui.js +++ b/src/js/ui.js @@ -86,7 +86,11 @@ const ui = { ui.checkPlaying.call(this); // Check for picture-in-picture support - toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); + toggleClass( + this.elements.container, + this.config.classNames.pip.supported, + support.pip && this.isHTML5 && this.isVideo, + ); // Check for airplay support toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); @@ -174,32 +178,35 @@ const ui = { this.media.setAttribute('poster', poster); // Wait until ui is ready - return ready.call(this) - // Load image - .then(() => loadImage(poster)) - .catch(err => { - // Hide poster on error unless it's been set by another call - if (poster === this.poster) { - ui.togglePoster.call(this, false); - } - // Rethrow - throw err; - }) - .then(() => { - // Prevent race conditions - if (poster !== this.poster) { - throw new Error('setPoster cancelled by later call to setPoster'); - } - }) - .then(() => { - Object.assign(this.elements.poster.style, { - backgroundImage: `url('${poster}')`, - // Reset backgroundSize as well (since it can be set to "cover" for padded thumbnails for youtube) - backgroundSize: '', - }); - ui.togglePoster.call(this, true); - return poster; - }); + return ( + ready + .call(this) + // Load image + .then(() => loadImage(poster)) + .catch(err => { + // Hide poster on error unless it's been set by another call + if (poster === this.poster) { + ui.togglePoster.call(this, false); + } + // Rethrow + throw err; + }) + .then(() => { + // Prevent race conditions + if (poster !== this.poster) { + throw new Error('setPoster cancelled by later call to setPoster'); + } + }) + .then(() => { + Object.assign(this.elements.poster.style, { + backgroundImage: `url('${poster}')`, + // Reset backgroundSize as well (since it can be set to "cover" for padded thumbnails for youtube) + backgroundSize: '', + }); + ui.togglePoster.call(this, true); + return poster; + }) + ); }, // Check playing state diff --git a/src/js/utils/elements.js b/src/js/utils/elements.js index 2d314ed8..19e98f6f 100644 --- a/src/js/utils/elements.js +++ b/src/js/utils/elements.js @@ -218,7 +218,12 @@ export function matches(element, selector) { return Array.from(document.querySelectorAll(selector)).includes(this); } - const matches = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match; + const matches = + prototype.matches || + prototype.webkitMatchesSelector || + prototype.mozMatchesSelector || + prototype.msMatchesSelector || + match; return matches.call(element, selector); } diff --git a/src/js/utils/events.js b/src/js/utils/events.js index 9009d1cc..9f734f04 100644 --- a/src/js/utils/events.js +++ b/src/js/utils/events.js @@ -113,7 +113,8 @@ export function unbindListeners() { } // Run method when / if player is ready -export function ready () { - return new Promise(resolve => this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve)) - .then(() => {}); +export function ready() { + return new Promise( + resolve => (this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve)), + ).then(() => {}); } diff --git a/src/js/utils/is.js b/src/js/utils/is.js index d34d3aed..cb2c07c6 100644 --- a/src/js/utils/is.js +++ b/src/js/utils/is.js @@ -47,7 +47,10 @@ const is = { return instanceOf(input, TextTrack) || (!is.nullOrUndefined(input) && is.string(input.kind)); }, url(input) { - return !is.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input); + return ( + !is.nullOrUndefined(input) && + /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input) + ); }, nullOrUndefined(input) { return input === null || typeof input === 'undefined'; diff --git a/src/js/utils/strings.js b/src/js/utils/strings.js index 8ca14ff8..c872498c 100644 --- a/src/js/utils/strings.js +++ b/src/js/utils/strings.js @@ -29,7 +29,10 @@ export function getPercentage(current, max) { // Replace all occurances of a string in a string export function replaceAll(input = '', find = '', replace = '') { - return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); + return input.replace( + new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), + replace.toString(), + ); } // Convert to title case |