diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/js/captions.js | 2 | ||||
-rw-r--r-- | src/js/controls.js | 182 | ||||
-rw-r--r-- | src/js/defaults.js | 2 | ||||
-rw-r--r-- | src/js/fullscreen.js | 2 | ||||
-rw-r--r-- | src/js/listeners.js | 11 | ||||
-rw-r--r-- | src/js/plyr.js | 5 | ||||
-rw-r--r-- | src/js/plyr.polyfilled.js | 2 | ||||
-rw-r--r-- | src/js/support.js | 1 | ||||
-rw-r--r-- | src/js/ui.js | 140 | ||||
-rw-r--r-- | src/js/utils.js | 31 | ||||
-rw-r--r-- | src/sass/components/poster.scss | 3 |
11 files changed, 196 insertions, 185 deletions
diff --git a/src/js/captions.js b/src/js/captions.js index e0692dcf..df717351 100644 --- a/src/js/captions.js +++ b/src/js/captions.js @@ -236,7 +236,7 @@ const captions = { // Set the span content if (utils.is.string(caption)) { - content.textContent = caption.trim(); + content.innerText = caption.trim(); } else { content.appendChild(caption); } diff --git a/src/js/controls.js b/src/js/controls.js index ec64977e..8a160864 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -6,34 +6,13 @@ import captions from './captions'; import html5 from './html5'; import i18n from './i18n'; import support from './support'; -import ui from './ui'; import utils from './utils'; // Sniff out the browser const browser = utils.getBrowser(); const controls = { - // Webkit polyfill for lower fill range - updateRangeFill(target) { - // Get range from event if event passed - const range = utils.is.event(target) ? target.target : target; - - // Needs to be a valid <input type='range'> - if (!utils.is.element(range) || range.getAttribute('type') !== 'range') { - return; - } - - // Set aria value for https://github.com/sampotts/plyr/issues/905 - range.setAttribute('aria-valuenow', range.value); - - // WebKit only - if (!browser.isWebkit) { - return; - } - // Set CSS custom property - range.style.setProperty('--value', `${range.value / range.max * 100}%`); - }, // Get icon URL getIconUrl() { @@ -373,7 +352,7 @@ const controls = { break; } - progress.textContent = `% ${suffix.toLowerCase()}`; + progress.innerText = `% ${suffix.toLowerCase()}`; } this.elements.display[type] = progress; @@ -429,6 +408,123 @@ const controls = { list.appendChild(item); }, + // Update the displayed time + updateTimeDisplay(target = null, time = 0, inverted = false) { + // Bail if there's no element to display or the value isn't a number + if (!utils.is.element(target) || !utils.is.number(time)) { + return; + } + + // Always display hours if duration is over an hour + const forceHours = utils.getHours(this.duration) > 0; + + // eslint-disable-next-line no-param-reassign + target.innerText = utils.formatTime(time, forceHours, inverted); + }, + + // Update volume UI and storage + updateVolume() { + if (!this.supported.ui) { + return; + } + + // Update range + if (utils.is.element(this.elements.inputs.volume)) { + controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); + } + + // Update mute state + if (utils.is.element(this.elements.buttons.mute)) { + utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0); + } + }, + + // Update seek value and lower fill + setRange(target, value = 0) { + if (!utils.is.element(target)) { + return; + } + + // eslint-disable-next-line + target.value = value; + + // Webkit range fill + controls.updateRangeFill.call(this, target); + }, + + // Update <progress> elements + updateProgress(event) { + if (!this.supported.ui || !utils.is.event(event)) { + return; + } + + let value = 0; + + const setProgress = (target, input) => { + const value = utils.is.number(input) ? input : 0; + const progress = utils.is.element(target) ? target : this.elements.display.buffer; + + // Update value and label + if (utils.is.element(progress)) { + progress.value = value; + + // Update text label inside + const label = progress.getElementsByTagName('span')[0]; + if (utils.is.element(label)) { + label.childNodes[0].nodeValue = value; + } + } + }; + + if (event) { + switch (event.type) { + // Video playing + case 'timeupdate': + case 'seeking': + value = utils.getPercentage(this.currentTime, this.duration); + + // Set seek range value only if it's a 'natural' time event + if (event.type === 'timeupdate') { + controls.setRange.call(this, this.elements.inputs.seek, value); + } + + break; + + // Check buffer status + case 'playing': + case 'progress': + setProgress(this.elements.display.buffer, this.buffered * 100); + + break; + + default: + break; + } + } + }, + + // Webkit polyfill for lower fill range + updateRangeFill(target) { + // Get range from event if event passed + const range = utils.is.event(target) ? target.target : target; + + // Needs to be a valid <input type='range'> + if (!utils.is.element(range) || range.getAttribute('type') !== 'range') { + return; + } + + // Set aria value for https://github.com/sampotts/plyr/issues/905 + range.setAttribute('aria-valuenow', range.value); + + // WebKit only + if (!browser.isWebkit) { + return; + } + + // Set CSS custom property + range.style.setProperty('--value', `${range.value / range.max * 100}%`); + }, + // Update hover tooltip for seeking updateSeekTooltip(event) { // Bail if setting not true @@ -473,7 +569,7 @@ const controls = { } // Display the time a click would seek to - ui.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); + controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); // Set position this.elements.display.seekTooltip.style.left = `${percent}%`; @@ -488,6 +584,46 @@ const controls = { } }, + // Handle time change event + timeUpdate(event) { + // Only invert if only one time element is displayed and used for both duration and currentTime + const invert = !utils.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); + + // Ignore updates while seeking + if (event && event.type === 'timeupdate' && this.media.seeking) { + return; + } + + // Playing progress + controls.updateProgress.call(this, event); + }, + + // Show the duration on metadataloaded + durationUpdate() { + if (!this.supported.ui) { + return; + } + + // If there's a spot to display duration + const hasDuration = utils.is.element(this.elements.display.duration); + + // If there's only one time display, display duration there + if (!hasDuration && this.config.displayDuration && this.paused) { + controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); + } + + // If there's a duration element, update content + if (hasDuration) { + controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); + } + + // Update the tooltip (if visible) + controls.updateSeekTooltip.call(this); + }, + // Hide/show a tab toggleTab(setting, toggle) { utils.toggleHidden(this.elements.settings.tabs[setting], !toggle); diff --git a/src/js/defaults.js b/src/js/defaults.js index a28f56ee..f160b1aa 100644 --- a/src/js/defaults.js +++ b/src/js/defaults.js @@ -56,7 +56,7 @@ const defaults = { // Sprite (for icons) loadSprite: true, iconPrefix: 'plyr', - iconUrl: 'https://cdn.plyr.io/3.3.6/plyr.svg', + iconUrl: 'https://cdn.plyr.io/3.3.7/plyr.svg', // Blank video (used to prevent errors on source change) blankVideo: 'https://cdn.plyr.io/static/blank.mp4', diff --git a/src/js/fullscreen.js b/src/js/fullscreen.js index cd2d8ac6..000ba706 100644 --- a/src/js/fullscreen.js +++ b/src/js/fullscreen.js @@ -19,7 +19,7 @@ function onChange() { } // Trigger an event - utils.dispatchEvent(this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); + utils.dispatchEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); // Trap focus in container if (!browser.isIos) { diff --git a/src/js/listeners.js b/src/js/listeners.js index f4e9ade3..167bee3c 100644 --- a/src/js/listeners.js +++ b/src/js/listeners.js @@ -250,10 +250,10 @@ class Listeners { // Listen for media events media() { // Time change on media - utils.on(this.player.media, 'timeupdate seeking', event => ui.timeUpdate.call(this.player, event)); + utils.on(this.player.media, 'timeupdate seeking', event => controls.timeUpdate.call(this.player, event)); // Display duration - utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', event => ui.durationUpdate.call(this.player, event)); + utils.on(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 @@ -272,10 +272,10 @@ class Listeners { }); // Check for buffer progress - utils.on(this.player.media, 'progress playing', event => ui.updateProgress.call(this.player, event)); + utils.on(this.player.media, 'progress playing', event => controls.updateProgress.call(this.player, event)); // Handle volume changes - utils.on(this.player.media, 'volumechange', event => ui.updateVolume.call(this.player, event)); + utils.on(this.player.media, 'volumechange', event => controls.updateVolume.call(this.player, event)); // Handle play/pause utils.on(this.player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(this.player, event)); @@ -549,7 +549,8 @@ class Listeners { } this.player.config.invertTime = !this.player.config.invertTime; - ui.timeUpdate.call(this.player); + + controls.timeUpdate.call(this.player); }); } diff --git a/src/js/plyr.js b/src/js/plyr.js index c2a1d6e3..bed09827 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -1,6 +1,6 @@ // ========================================================================== // Plyr -// plyr.js v3.3.6 +// plyr.js v3.3.7 // https://github.com/sampotts/plyr // License: The MIT License (MIT) // ========================================================================== @@ -55,6 +55,7 @@ class Plyr { this.config = utils.extend( {}, defaults, + Plyr.defaults, options || {}, (() => { try { @@ -1269,4 +1270,6 @@ class Plyr { } } +Plyr.defaults = utils.cloneDeep(defaults); + export default Plyr; diff --git a/src/js/plyr.polyfilled.js b/src/js/plyr.polyfilled.js index 0cc3c526..635dee63 100644 --- a/src/js/plyr.polyfilled.js +++ b/src/js/plyr.polyfilled.js @@ -1,6 +1,6 @@ // ========================================================================== // Plyr Polyfilled Build -// plyr.js v3.3.6 +// plyr.js v3.3.7 // https://github.com/sampotts/plyr // License: The MIT License (MIT) // ========================================================================== diff --git a/src/js/support.js b/src/js/support.js index 5528e898..38212d9f 100644 --- a/src/js/support.js +++ b/src/js/support.js @@ -133,6 +133,7 @@ const support = { }, }); window.addEventListener('test', null, options); + window.removeEventListener('test', null, options); } catch (e) { // Do nothing } diff --git a/src/js/ui.js b/src/js/ui.js index 2347b5c8..8f3f6a77 100644 --- a/src/js/ui.js +++ b/src/js/ui.js @@ -74,10 +74,10 @@ const ui = { this.quality = null; // Reset volume display - ui.updateVolume.call(this); + controls.updateVolume.call(this); // Reset time display - ui.timeUpdate.call(this); + controls.timeUpdate.call(this); // Update the UI ui.checkPlaying.call(this); @@ -218,142 +218,6 @@ const ui = { this.toggleControls(this.loading); }, this.loading ? 250 : 0); }, - - // Update volume UI and storage - updateVolume() { - if (!this.supported.ui) { - return; - } - - // Update range - if (utils.is.element(this.elements.inputs.volume)) { - ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume); - } - - // Update mute state - if (utils.is.element(this.elements.buttons.mute)) { - utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0); - } - }, - - // Update seek value and lower fill - setRange(target, value = 0) { - if (!utils.is.element(target)) { - return; - } - - // eslint-disable-next-line - target.value = value; - - // Webkit range fill - controls.updateRangeFill.call(this, target); - }, - - // Set <progress> value - setProgress(target, input) { - const value = utils.is.number(input) ? input : 0; - const progress = utils.is.element(target) ? target : this.elements.display.buffer; - - // Update value and label - if (utils.is.element(progress)) { - progress.value = value; - - // Update text label inside - const label = progress.getElementsByTagName('span')[0]; - if (utils.is.element(label)) { - label.childNodes[0].nodeValue = value; - } - } - }, - - // Update <progress> elements - updateProgress(event) { - if (!this.supported.ui || !utils.is.event(event)) { - return; - } - - let value = 0; - - if (event) { - switch (event.type) { - // Video playing - case 'timeupdate': - case 'seeking': - value = utils.getPercentage(this.currentTime, this.duration); - - // Set seek range value only if it's a 'natural' time event - if (event.type === 'timeupdate') { - ui.setRange.call(this, this.elements.inputs.seek, value); - } - - break; - - // Check buffer status - case 'playing': - case 'progress': - ui.setProgress.call(this, this.elements.display.buffer, this.buffered * 100); - - break; - - default: - break; - } - } - }, - - // Update the displayed time - updateTimeDisplay(target = null, time = 0, inverted = false) { - // Bail if there's no element to display or the value isn't a number - if (!utils.is.element(target) || !utils.is.number(time)) { - return; - } - - // Always display hours if duration is over an hour - const forceHours = utils.getHours(this.duration) > 0; - - // eslint-disable-next-line no-param-reassign - target.textContent = utils.formatTime(time, forceHours, inverted); - }, - - // Handle time change event - timeUpdate(event) { - // Only invert if only one time element is displayed and used for both duration and currentTime - const invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime; - - // Duration - ui.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) { - return; - } - - // Playing progress - ui.updateProgress.call(this, event); - }, - - // Show the duration on metadataloaded - durationUpdate() { - if (!this.supported.ui) { - return; - } - - // If there's a spot to display duration - const hasDuration = utils.is.element(this.elements.display.duration); - - // If there's only one time display, display duration there - if (!hasDuration && this.config.displayDuration && this.paused) { - ui.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration); - } - - // If there's a duration element, update content - if (hasDuration) { - ui.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); - } - - // Update the tooltip (if visible) - controls.updateSeekTooltip.call(this); - }, }; export default ui; diff --git a/src/js/utils.js b/src/js/utils.js index d46a7601..a58d8555 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -3,15 +3,13 @@ // ========================================================================== import loadjs from 'loadjs'; +import Storage from './storage'; import support from './support'; import { providers } from './types'; const utils = { // Check variable types is: { - plyr(input) { - return this.instanceof(input, window.Plyr); - }, object(input) { return this.getConstructor(input) === Object; }, @@ -31,22 +29,22 @@ const utils = { return !this.nullOrUndefined(input) && Array.isArray(input); }, weakMap(input) { - return this.instanceof(input, window.WeakMap); + return this.instanceof(input, WeakMap); }, nodeList(input) { - return this.instanceof(input, window.NodeList); + return this.instanceof(input, NodeList); }, element(input) { - return this.instanceof(input, window.Element); + return this.instanceof(input, Element); }, textNode(input) { return this.getConstructor(input) === Text; }, event(input) { - return this.instanceof(input, window.Event); + return this.instanceof(input, Event); }, cue(input) { - return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue); + return this.instanceof(input, TextTrackCue) || this.instanceof(input, VTTCue); }, track(input) { return this.instanceof(input, TextTrack) || (!this.nullOrUndefined(input) && this.string(input.kind)); @@ -159,6 +157,8 @@ const utils = { // Only load once if ID set if (!hasId || !exists()) { + const useStorage = Storage.supported; + // Create container const container = document.createElement('div'); utils.toggleHidden(container, true); @@ -168,7 +168,7 @@ const utils = { } // Check in cache - if (support.storage) { + if (useStorage) { const cached = window.localStorage.getItem(prefix + id); isCached = cached !== null; @@ -187,7 +187,7 @@ const utils = { return; } - if (support.storage) { + if (useStorage) { window.localStorage.setItem( prefix + id, JSON.stringify({ @@ -250,7 +250,7 @@ const utils = { // Add text node if (utils.is.string(text)) { - element.textContent = text; + element.innerText = text; } // Return built element @@ -547,7 +547,7 @@ const utils = { const event = new CustomEvent(type, { bubbles, detail: Object.assign({}, detail, { - plyr: utils.is.plyr(this) ? this : null, + plyr: this, }), }); @@ -583,7 +583,7 @@ const utils = { return input; } - return input.toString().replace(/{(\d+)}/g, (match, i) => utils.is.string(args[i]) ? args[i] : ''); + return input.toString().replace(/{(\d+)}/g, (match, i) => (utils.is.string(args[i]) ? args[i] : '')); }, // Get percentage @@ -706,6 +706,11 @@ const utils = { return array.filter((item, index) => array.indexOf(item) === index); }, + // Clone nested objects + cloneDeep(object) { + return JSON.parse(JSON.stringify(object)); + }, + // Get the closest value in an array closest(array, value) { if (!utils.is.array(array) || !array.length) { diff --git a/src/sass/components/poster.scss b/src/sass/components/poster.scss index b2518a78..92ab0fce 100644 --- a/src/sass/components/poster.scss +++ b/src/sass/components/poster.scss @@ -6,7 +6,7 @@ background-color: #000; background-position: 50% 50%; background-repeat: no-repeat; - background-size: 100% 100%; + background-size: contain; height: 100%; left: 0; opacity: 0; @@ -15,6 +15,7 @@ transition: opacity 0.3s ease; width: 100%; z-index: 1; + pointer-events: none; } .plyr--stopped .plyr__poster { |