diff options
author | Sam Potts <me@sampotts.me> | 2017-11-04 21:19:02 +1100 |
---|---|---|
committer | Sam Potts <me@sampotts.me> | 2017-11-04 21:19:02 +1100 |
commit | d920de2a25b1f9b3981671bbe9099af61e74410f (patch) | |
tree | be561c96ddf345fcfdbdfe328b9c830d7914efbc /src/js | |
parent | 069c8093aefec9f23f3ff38de6041f8f90edf022 (diff) | |
download | plyr-d920de2a25b1f9b3981671bbe9099af61e74410f.tar.lz plyr-d920de2a25b1f9b3981671bbe9099af61e74410f.tar.xz plyr-d920de2a25b1f9b3981671bbe9099af61e74410f.zip |
Small tweaks
Diffstat (limited to 'src/js')
-rw-r--r-- | src/js/controls.js | 47 | ||||
-rw-r--r-- | src/js/listeners.js | 168 | ||||
-rw-r--r-- | src/js/plugins/vimeo.js | 39 | ||||
-rw-r--r-- | src/js/plugins/youtube.js | 21 | ||||
-rw-r--r-- | src/js/plyr.js | 9 | ||||
-rw-r--r-- | src/js/source.js | 2 | ||||
-rw-r--r-- | src/js/ui.js | 48 | ||||
-rw-r--r-- | src/js/utils.js | 18 |
8 files changed, 201 insertions, 151 deletions
diff --git a/src/js/controls.js b/src/js/controls.js index 1e10f2f2..c95c6197 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -4,6 +4,7 @@ import support from './support'; import utils from './utils'; +import ui from './ui'; const controls = { // Webkit polyfill for lower fill range @@ -300,6 +301,52 @@ const controls = { return container; }, + // Update hover tooltip for seeking + updateSeekTooltip(event) { + // Bail if setting not true + if ( + !this.config.tooltips.seek || + !utils.is.htmlElement(this.elements.inputs.seek) || + !utils.is.htmlElement(this.elements.display.seekTooltip) || + this.duration === 0 + ) { + return; + } + + // Calculate percentage + let percent = 0; + const clientRect = this.elements.inputs.seek.getBoundingClientRect(); + const visible = `${this.config.classNames.tooltip}--visible`; + + // Determine percentage, if already visible + if (utils.is.event(event)) { + percent = 100 / clientRect.width * (event.pageX - clientRect.left); + } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) { + percent = this.elements.display.seekTooltip.style.left.replace('%', ''); + } else { + return; + } + + // Set bounds + if (percent < 0) { + percent = 0; + } else if (percent > 100) { + percent = 100; + } + + // Display the time a click would seek to + ui.updateTimeDisplay.call(this, this.duration / 100 * percent, this.elements.display.seekTooltip); + + // Set position + this.elements.display.seekTooltip.style.left = `${percent}%`; + + // Show/hide the tooltip + // If the event is a moues in/out and percentage is inside bounds + if (utils.is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { + utils.toggleClass(this.elements.display.seekTooltip, visible, event.type === 'mouseenter'); + } + }, + // Hide/show a tab toggleTab(setting, toggle) { const tab = this.elements.settings.tabs[setting]; diff --git a/src/js/listeners.js b/src/js/listeners.js index f3746414..bc1a6094 100644 --- a/src/js/listeners.js +++ b/src/js/listeners.js @@ -360,61 +360,81 @@ const listeners = { }); // Trigger custom and default handlers - const handlerProxy = (event, customHandler, defaultHandler) => { + const proxy = (event, handlerKey, defaultHandler) => { + const customHandler = this.config.listeners[handleKey]; + + // Execute custom handler if (utils.is.function(customHandler)) { customHandler.call(this, event); } - if (utils.is.function(defaultHandler)) { + + // Only call default handler if not prevented in custom handler + if (!event.defaultPrevented && utils.is.function(defaultHandler)) { defaultHandler.call(this, event); } }; // Play - utils.proxy(this.elements.buttons.play, 'click', this.config.listeners.play, togglePlay); - utils.proxy(this.elements.buttons.playLarge, 'click', this.config.listeners.play, togglePlay); + utils.on(this.elements.buttons.play, 'click', event => proxy(event, 'play', togglePlay)); // Pause - utils.proxy(this.elements.buttons.pause, 'click', this.config.listeners.pause, togglePlay); + utils.on(this.elements.buttons.pause, 'click', event => proxy(event, 'pause', togglePlay)); // Pause - utils.proxy(this.elements.buttons.restart, 'click', this.config.listeners.restart, () => { - this.restart(); - }); + utils.on(this.elements.buttons.restart, 'click', event => + proxy(event, 'restart', () => { + this.restart(); + }) + ); // Rewind - utils.proxy(this.elements.buttons.rewind, 'click', this.config.listeners.rewind, () => { - this.rewind(); - }); + utils.on(this.elements.buttons.rewind, 'click', event => + proxy(event, 'rewind', () => { + this.rewind(); + }) + ); // Rewind - utils.proxy(this.elements.buttons.forward, 'click', this.config.listeners.forward, () => { - this.forward(); - }); + utils.on(this.elements.buttons.forward, 'click', event => + proxy(event, 'forward', () => { + this.forward(); + }) + ); // Mute - utils.proxy(this.elements.buttons.mute, 'click', this.config.listeners.mute, () => { - this.toggleMute(); - }); + utils.on(this.elements.buttons.mute, 'click', event => + proxy(event, 'mute', () => { + this.toggleMute(); + }) + ); // Captions - utils.proxy(this.elements.buttons.captions, 'click', this.config.listeners.captions, () => { - this.toggleCaptions(); - }); + utils.on(this.elements.buttons.captions, 'click', event => + proxy(event, 'captions', () => { + this.toggleCaptions(); + }) + ); // Fullscreen - utils.proxy(this.elements.buttons.fullscreen, 'click', this.config.listeners.fullscreen, () => { - this.toggleFullscreen(); - }); + utils.on(this.elements.buttons.fullscreen, 'click', event => + proxy(event, 'fullscreen', () => { + this.toggleFullscreen(); + }) + ); // Picture-in-Picture - utils.proxy(this.elements.buttons.pip, 'click', this.config.listeners.pip, () => { - this.togglePictureInPicture(); - }); + utils.on(this.elements.buttons.pip, 'click', event => + proxy(event, 'pip', () => { + this.togglePictureInPicture(); + }) + ); // Airplay - utils.proxy(this.elements.buttons.airplay, 'click', this.config.listeners.airplay, () => { - this.airPlay(); - }); + utils.on(this.elements.buttons.airplay, 'click', event => + proxy(event, 'airplay', () => { + this.airPlay(); + }) + ); // Settings menu utils.on(this.elements.buttons.settings, 'click', event => { @@ -434,24 +454,24 @@ const listeners = { // Settings menu items - use event delegation as items are added/removed // Settings - Language if (utils.matches(event.target, this.config.selectors.inputs.language)) { - handlerProxy.call(this, event, this.config.listeners.language, () => { + proxy(event, 'language', () => { this.toggleCaptions(true); this.language = event.target.value.toLowerCase(); }); } else if (utils.matches(event.target, this.config.selectors.inputs.quality)) { // Settings - Quality - handlerProxy.call(this, event, this.config.listeners.quality, () => { + proxy(event, 'quality', () => { this.quality = event.target.value; }); } else if (utils.matches(event.target, this.config.selectors.inputs.speed)) { // Settings - Speed - handlerProxy.call(this, event, this.config.listeners.speed, () => { + proxy(event, 'speed', () => { this.speed = parseFloat(event.target.value); }); } else if (utils.matches(event.target, this.config.selectors.buttons.loop)) { // Settings - Looping // TODO: use toggle buttons - handlerProxy.call(this, event, this.config.listeners.loop, () => { + proxy(event, 'loop', () => { // TODO: This should be done in the method itself I think // var value = event.target.getAttribute('data-loop__value') || event.target.getAttribute('data-loop__type'); @@ -461,14 +481,18 @@ const listeners = { }); // Seek - utils.proxy(this.elements.inputs.seek, inputEvent, this.config.listeners.seek, event => { - this.currentTime = event.target.value / event.target.max * this.duration; - }); + utils.on(this.elements.inputs.seek, inputEvent, event => + proxy(event, 'seek', () => { + this.currentTime = event.target.value / event.target.max * this.duration; + }) + ); // Volume - utils.proxy(this.elements.inputs.volume, inputEvent, this.config.listeners.volume, event => { - this.volume = event.target.value; - }); + utils.on(this.elements.inputs.volume, inputEvent, event => + proxy(event, 'volume', () => { + this.volume = event.target.value; + }) + ); // Polyfill for lower fill in <input type="range"> for webkit if (this.browser.isWebkit) { @@ -479,7 +503,7 @@ const listeners = { // Seek tooltip utils.on(this.elements.progress, 'mouseenter mouseleave mousemove', event => - ui.updateSeekTooltip.call(this, event) + controls.updateSeekTooltip.call(this, event) ); // Toggle controls visibility based on mouse movement @@ -516,44 +540,44 @@ const listeners = { } // Mouse wheel for volume - utils.proxy( + utils.on( this.elements.inputs.volume, 'wheel', - this.config.listeners.volume, - event => { - // Detect "natural" scroll - suppored on OS X Safari only - // Other browsers on OS X will be inverted until support improves - const inverted = event.webkitDirectionInvertedFromDevice; - const step = 1 / 50; - let direction = 0; - - // Scroll down (or up on natural) to decrease - if (event.deltaY < 0 || event.deltaX > 0) { - if (inverted) { - this.decreaseVolume(step); - direction = -1; - } else { - this.increaseVolume(step); - direction = 1; + event => + proxy(event, 'volume', () => { + // Detect "natural" scroll - suppored on OS X Safari only + // Other browsers on OS X will be inverted until support improves + const inverted = event.webkitDirectionInvertedFromDevice; + const step = 1 / 50; + let direction = 0; + + // Scroll down (or up on natural) to decrease + if (event.deltaY < 0 || event.deltaX > 0) { + if (inverted) { + this.decreaseVolume(step); + direction = -1; + } else { + this.increaseVolume(step); + direction = 1; + } } - } - // Scroll up (or down on natural) to increase - if (event.deltaY > 0 || event.deltaX < 0) { - if (inverted) { - this.increaseVolume(step); - direction = 1; - } else { - this.decreaseVolume(step); - direction = -1; + // Scroll up (or down on natural) to increase + if (event.deltaY > 0 || event.deltaX < 0) { + if (inverted) { + this.increaseVolume(step); + direction = 1; + } else { + this.decreaseVolume(step); + direction = -1; + } } - } - // Don't break page scrolling at max and min - if ((direction === 1 && this.media.volume < 1) || (direction === -1 && this.media.volume > 0)) { - event.preventDefault(); - } - }, + // Don't break page scrolling at max and min + if ((direction === 1 && this.media.volume < 1) || (direction === -1 && this.media.volume > 0)) { + event.preventDefault(); + } + }), false ); diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js index 12632f64..34e326e7 100644 --- a/src/js/plugins/vimeo.js +++ b/src/js/plugins/vimeo.js @@ -77,6 +77,34 @@ const vimeo = { player.media.paused = true; player.media.currentTime = 0; + let { currentTime } = player.media; + + // Seeking + Object.defineProperty(player.media, 'currentTime', { + get() { + return currentTime; + }, + set(time) { + // Get current paused state + const { paused } = player.media; + + player.warn('called'); + + // Set seeking flag + player.media.seeking = true; + + // Trigger seeking + utils.dispatchEvent.call(player, player.media, 'seeking'); + + // Seek after events + player.embed.setCurrentTime(time); + + // Restore pause state + if (paused) { + this.pause(); + } + }, + }); // Playback speed // Not currently supported in Vimeo @@ -88,10 +116,10 @@ const vimeo = { }); // Rebuild UI - ui.build.call(player); + window.setTimeout(() => ui.build.call(player), 0); player.embed.getCurrentTime().then(value => { - player.media.currentTime = value; + currentTime = value; utils.dispatchEvent.call(this, this.media, 'timeupdate'); }); @@ -103,7 +131,6 @@ const vimeo = { // Get captions player.embed.getTextTracks().then(tracks => { player.captions.tracks = tracks; - captions.setup.call(player); }); @@ -121,10 +148,6 @@ const vimeo = { if (utils.is.htmlElement(player.embed.element) && player.supported.ui) { const frame = player.embed.element; - // Fix Vimeo controls issue - // https://github.com/sampotts/plyr/issues/697 - // frame.src = `${frame.src}&transparent=0`; - // Fix keyboard focus issues // https://github.com/sampotts/plyr/issues/317 frame.setAttribute('tabindex', -1); @@ -144,7 +167,7 @@ const vimeo = { this.embed.on('timeupdate', data => { this.media.seeking = false; - this.media.currentTime = data.seconds; + currentTime = data.seconds; utils.dispatchEvent.call(this, this.media, 'timeupdate'); }); diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 7d5c729c..ce21433e 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -118,6 +118,23 @@ const youtube = { player.media.muted = instance.isMuted(); player.media.currentTime = 0; + // Seeking + Object.defineProperty(player.media, 'currentTime', { + get() { + return Number(instance.getCurrentTime()); + }, + set(time) { + // Set seeking flag + player.media.seeking = true; + + // Trigger seeking + utils.dispatchEvent.call(player, player.media, 'seeking'); + + // Seek after events sent + instance.seekTo(time); + }, + }); + // Playback speed Object.defineProperty(player.media, 'playbackRate', { get() { @@ -142,7 +159,7 @@ const youtube = { } // Rebuild UI - ui.build.call(player); + window.setTimeout(() => ui.build.call(player), 0); utils.dispatchEvent.call(player, player.media, 'timeupdate'); utils.dispatchEvent.call(player, player.media, 'durationchange'); @@ -218,7 +235,7 @@ const youtube = { // Poll to get playback progress player.timers.playing = window.setInterval(() => { - player.media.currentTime = instance.getCurrentTime(); + // player.media.currentTime = instance.getCurrentTime(); utils.dispatchEvent.call(player, player.media, 'timeupdate'); }, 100); diff --git a/src/js/plyr.js b/src/js/plyr.js index f98bef1a..60960d01 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -323,7 +323,7 @@ class Plyr { // Set the current time // TODO: This should be included in the "adapters" // Embeds - if (this.isEmbed) { + /* if (this.isEmbed) { // Get current paused state const { paused } = this.media; @@ -351,8 +351,10 @@ class Plyr { // Trigger seeking utils.dispatchEvent.call(this, this.media, 'seeking'); } else { - this.media.currentTime = targetTime.toFixed(4); - } + + } */ + + this.media.currentTime = targetTime.toFixed(4); // Logging this.log(`Seeking to ${this.currentTime} seconds`); @@ -408,6 +410,7 @@ class Plyr { this.media.volume = volume; // Trigger volumechange for embeds + // TODO: Do in adapters if (this.isEmbed) { // Set media volume switch (this.type) { diff --git a/src/js/source.js b/src/js/source.js index d2d5f61a..d0881675 100644 --- a/src/js/source.js +++ b/src/js/source.js @@ -16,8 +16,6 @@ const source = { src: attributes, }); } else if (utils.is.array(attributes)) { - this.warn(attributes); - attributes.forEach(attribute => { utils.insertElement(type, this.media, attribute); }); diff --git a/src/js/ui.js b/src/js/ui.js index 2d612cdb..1ec58d29 100644 --- a/src/js/ui.js +++ b/src/js/ui.js @@ -114,7 +114,7 @@ const ui = { } // Update the tooltip (if visible) - ui.updateSeekTooltip.call(this); + controls.updateSeekTooltip.call(this); }, // Setup aria attribute for play and iframe title @@ -330,52 +330,6 @@ const ui = { // Playing progress ui.updateProgress.call(this, event); }, - - // Update hover tooltip for seeking - updateSeekTooltip(event) { - // Bail if setting not true - if ( - !this.config.tooltips.seek || - !utils.is.htmlElement(this.elements.inputs.seek) || - !utils.is.htmlElement(this.elements.display.seekTooltip) || - this.duration === 0 - ) { - return; - } - - // Calculate percentage - const clientRect = this.elements.inputs.seek.getBoundingClientRect(); - let percent = 0; - const visible = `${this.config.classNames.tooltip}--visible`; - - // Determine percentage, if already visible - if (utils.is.event(event)) { - percent = 100 / clientRect.width * (event.pageX - clientRect.left); - } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) { - percent = this.elements.display.seekTooltip.style.left.replace('%', ''); - } else { - return; - } - - // Set bounds - if (percent < 0) { - percent = 0; - } else if (percent > 100) { - percent = 100; - } - - // Display the time a click would seek to - ui.updateTimeDisplay.call(this, this.duration / 100 * percent, this.elements.display.seekTooltip); - - // Set position - this.elements.display.seekTooltip.style.left = `${percent}%`; - - // Show/hide the tooltip - // If the event is a moues in/out and percentage is inside bounds - if (utils.is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { - utils.toggleClass(this.elements.display.seekTooltip, visible, event.type === 'mouseenter'); - } - }, }; export default ui; diff --git a/src/js/utils.js b/src/js/utils.js index e81954f4..4296f345 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -391,22 +391,6 @@ const utils = { ); }, - // Bind along with custom handler - proxy(element, eventName, customListener, defaultListener, passive, capture) { - utils.on( - element, - eventName, - event => { - if (customListener) { - customListener.apply(element, [event]); - } - defaultListener.apply(element, [event]); - }, - passive, - capture - ); - }, - // Toggle event listener toggleListener(elements, event, callback, toggle, passive, capture) { // Bail if no elements @@ -415,7 +399,7 @@ const utils = { } // If a nodelist is passed, call itself on each node - if (elements instanceof NodeList) { + if (utils.is.nodeList(elements)) { // Create listener for each node Array.from(elements).forEach(element => { if (element instanceof Node) { |