diff options
author | Sam Potts <me@sampotts.me> | 2017-11-06 21:19:00 +1100 |
---|---|---|
committer | Sam Potts <me@sampotts.me> | 2017-11-06 21:19:00 +1100 |
commit | 2497e25b3ce6849986c3501354636fdae11df6d4 (patch) | |
tree | 2b780e9d6d2626850a8015b04124af56fc647771 /src | |
parent | 9c4b7e70948af3a1e45b63b3d36f3cae86802919 (diff) | |
download | plyr-2497e25b3ce6849986c3501354636fdae11df6d4.tar.lz plyr-2497e25b3ce6849986c3501354636fdae11df6d4.tar.xz plyr-2497e25b3ce6849986c3501354636fdae11df6d4.zip |
Global listeners to prevent repeat binding
Diffstat (limited to 'src')
-rw-r--r-- | src/js/listeners.js | 347 | ||||
-rw-r--r-- | src/js/plyr.js | 4 |
2 files changed, 182 insertions, 169 deletions
diff --git a/src/js/listeners.js b/src/js/listeners.js index 9483c6a9..3c83038b 100644 --- a/src/js/listeners.js +++ b/src/js/listeners.js @@ -13,161 +13,10 @@ import ui from './ui'; const browser = utils.getBrowser(); const listeners = { - // Listen for media events - media() { - // Time change on media - utils.on(this.media, 'timeupdate seeking', event => ui.timeUpdate.call(this, event)); - - // Display duration - utils.on(this.media, 'durationchange loadedmetadata', event => ui.displayDuration.call(this, event)); - - // Handle the media finishing - utils.on(this.media, 'ended', () => { - // Show poster on end - if (this.type === 'video' && this.config.showPosterOnEnd) { - // Restart - this.restart(); - - // Re-load media - this.media.load(); - } - }); - - // Check for buffer progress - utils.on(this.media, 'progress playing', event => ui.updateProgress.call(this, event)); - - // Handle native mute - utils.on(this.media, 'volumechange', event => ui.updateVolume.call(this, event)); - - // Handle native play/pause - utils.on(this.media, 'play pause ended', event => ui.checkPlaying.call(this, event)); - - // Loading - utils.on(this.media, 'waiting canplay seeked', event => ui.checkLoading.call(this, event)); - - // Click video - if (this.supported.ui && this.config.clickToPlay && this.type !== 'audio') { - // Re-fetch the wrapper - const wrapper = utils.getElement.call(this, `.${this.config.classNames.video}`); - - // Bail if there's no wrapper (this should never happen) - if (!wrapper) { - return; - } - - // Set cursor - wrapper.style.cursor = 'pointer'; - - // On click play, pause ore restart - utils.on(wrapper, 'click', () => { - // Touch devices will just show controls (if we're hiding controls) - if (this.config.hideControls && support.touch && !this.media.paused) { - return; - } - - if (this.media.paused) { - this.play(); - } else if (this.media.ended) { - this.restart(); - this.play(); - } else { - this.pause(); - } - }); - } - - // Disable right click - if (this.config.disableContextMenu) { - utils.on( - this.media, - 'contextmenu', - event => { - event.preventDefault(); - }, - false - ); - } - - // Speed change - utils.on(this.media, 'ratechange', () => { - // Update UI - controls.updateSetting.call(this, 'speed'); - - // Save speed to localStorage - storage.set.call(this, { speed: this.speed }); - }); - - // Quality change - utils.on(this.media, 'qualitychange', () => { - // Update UI - controls.updateSetting.call(this, 'quality'); - - // Save speed to localStorage - storage.set.call(this, { quality: this.quality }); - }); - - // Caption language change - utils.on(this.media, 'captionchange', () => { - // Save speed to localStorage - storage.set.call(this, { language: this.language }); - }); - - // Volume change - utils.on(this.media, 'volumechange', () => { - // Save speed to localStorage - storage.set.call(this, { volume: this.volume }); - }); - - // Captions toggle - utils.on(this.media, 'captionsenabled captionsdisabled', () => { - // Update UI - controls.updateSetting.call(this, 'captions'); - - // Save speed to localStorage - storage.set.call(this, { captions: this.captions.enabled }); - }); - - // Proxy events to container - // Bubble up key events for Edge - utils.on(this.media, this.config.events.concat(['keyup', 'keydown']).join(' '), event => { - utils.dispatchEvent.call(this, this.elements.container, event.type, true); - }); - }, - - // Listen for control events - controls() { - // IE doesn't support input event, so we fallback to change - const inputEvent = browser.isIE ? 'change' : 'input'; + // Global listeners + global() { let last = null; - // Trigger custom and default handlers - const proxy = (event, handlerKey, defaultHandler) => { - const customHandler = this.config.listeners[handlerKey]; - - // Execute custom handler - if (utils.is.function(customHandler)) { - customHandler.call(this, event); - } - - // Only call default handler if not prevented in custom handler - if (!event.defaultPrevented && utils.is.function(defaultHandler)) { - defaultHandler.call(this, event); - } - }; - - // Click play/pause helper - const togglePlay = () => { - const play = this.togglePlay(); - - // Determine which buttons - const target = this.elements.buttons[play ? 'pause' : 'play']; - - // Transfer focus - if (utils.is.htmlElement(target)) { - target.focus(); - } - }; - // Get the key code for an event const getKeyCode = event => (event.keyCode ? event.keyCode : event.which); @@ -252,6 +101,7 @@ const listeners = { case 75: // Space and K key if (!held) { + this.warn('togglePlay', event.type); this.togglePlay(); } break; @@ -326,6 +176,7 @@ const listeners = { // Keyboard shortcuts if (this.config.keyboard.global) { + this.warn('bound'); utils.on(window, 'keydown keyup', handleKey, false); } else if (this.config.keyboard.focused) { utils.on(this.elements.container, 'keydown keyup', handleKey, false); @@ -350,6 +201,180 @@ const listeners = { }, 0); }); + // Toggle controls visibility based on mouse movement + if (this.config.hideControls) { + // Toggle controls on mouse events and entering fullscreen + utils.on( + this.elements.container, + 'mouseenter mouseleave mousemove touchstart touchend touchcancel touchmove enterfullscreen', + event => { + this.toggleControls(event); + } + ); + } + + // Handle user exiting fullscreen by escaping etc + if (fullscreen.enabled) { + utils.on(document, fullscreen.eventType, event => { + this.toggleFullscreen(event); + }); + } + }, + + // Listen for media events + media() { + // Time change on media + utils.on(this.media, 'timeupdate seeking', event => ui.timeUpdate.call(this, event)); + + // Display duration + utils.on(this.media, 'durationchange loadedmetadata', event => ui.displayDuration.call(this, event)); + + // Handle the media finishing + utils.on(this.media, 'ended', () => { + // Show poster on end + if (this.type === 'video' && this.config.showPosterOnEnd) { + // Restart + this.restart(); + + // Re-load media + this.media.load(); + } + }); + + // Check for buffer progress + utils.on(this.media, 'progress playing', event => ui.updateProgress.call(this, event)); + + // Handle native mute + utils.on(this.media, 'volumechange', event => ui.updateVolume.call(this, event)); + + // Handle native play/pause + utils.on(this.media, 'play pause ended', event => ui.checkPlaying.call(this, event)); + + // Loading + utils.on(this.media, 'waiting canplay seeked', event => ui.checkLoading.call(this, event)); + + // Click video + if (this.supported.ui && this.config.clickToPlay && this.type !== 'audio') { + // Re-fetch the wrapper + const wrapper = utils.getElement.call(this, `.${this.config.classNames.video}`); + + // Bail if there's no wrapper (this should never happen) + if (!wrapper) { + return; + } + + // Set cursor + wrapper.style.cursor = 'pointer'; + + // On click play, pause ore restart + utils.on(wrapper, 'click', () => { + // Touch devices will just show controls (if we're hiding controls) + if (this.config.hideControls && support.touch && !this.media.paused) { + return; + } + + if (this.media.paused) { + this.play(); + } else if (this.media.ended) { + this.restart(); + this.play(); + } else { + this.pause(); + } + }); + } + + // Disable right click + if (this.config.disableContextMenu) { + utils.on( + this.media, + 'contextmenu', + event => { + event.preventDefault(); + }, + false + ); + } + + // Speed change + utils.on(this.media, 'ratechange', () => { + // Update UI + controls.updateSetting.call(this, 'speed'); + + // Save speed to localStorage + storage.set.call(this, { speed: this.speed }); + }); + + // Quality change + utils.on(this.media, 'qualitychange', () => { + // Update UI + controls.updateSetting.call(this, 'quality'); + + // Save speed to localStorage + storage.set.call(this, { quality: this.quality }); + }); + + // Caption language change + utils.on(this.media, 'captionchange', () => { + // Save speed to localStorage + storage.set.call(this, { language: this.language }); + }); + + // Volume change + utils.on(this.media, 'volumechange', () => { + // Save speed to localStorage + storage.set.call(this, { volume: this.volume }); + }); + + // Captions toggle + utils.on(this.media, 'captionsenabled captionsdisabled', () => { + // Update UI + controls.updateSetting.call(this, 'captions'); + + // Save speed to localStorage + storage.set.call(this, { captions: this.captions.enabled }); + }); + + // Proxy events to container + // Bubble up key events for Edge + utils.on(this.media, this.config.events.concat(['keyup', 'keydown']).join(' '), event => { + utils.dispatchEvent.call(this, this.elements.container, event.type, true); + }); + }, + + // Listen for control events + controls() { + // IE doesn't support input event, so we fallback to change + const inputEvent = browser.isIE ? 'change' : 'input'; + + // Trigger custom and default handlers + const proxy = (event, handlerKey, defaultHandler) => { + const customHandler = this.config.listeners[handlerKey]; + + // Execute custom handler + if (utils.is.function(customHandler)) { + customHandler.call(this, event); + } + + // Only call default handler if not prevented in custom handler + if (!event.defaultPrevented && utils.is.function(defaultHandler)) { + defaultHandler.call(this, event); + } + }; + + // Click play/pause helper + const togglePlay = () => { + const play = this.togglePlay(); + + // Determine which buttons + const target = this.elements.buttons[play ? 'pause' : 'play']; + + // Transfer focus + if (utils.is.htmlElement(target)) { + target.focus(); + } + }; + // Play utils.on(this.elements.buttons.play, 'click', event => proxy(event, 'play', togglePlay)); @@ -484,15 +509,6 @@ const listeners = { // Toggle controls visibility based on mouse movement if (this.config.hideControls) { - // Toggle controls on mouse events and entering fullscreen - utils.on( - this.elements.container, - 'mouseenter mouseleave mousemove touchstart touchend touchcancel touchmove enterfullscreen', - event => { - this.toggleControls(event); - } - ); - // Watch for cursor over controls so they don't hide when trying to interact utils.on(this.elements.controls, 'mouseenter mouseleave', event => { this.elements.controls.hover = event.type === 'mouseenter'; @@ -556,13 +572,6 @@ const listeners = { }), false ); - - // Handle user exiting fullscreen by escaping etc - if (fullscreen.enabled) { - utils.on(document, fullscreen.eventType, event => { - this.toggleFullscreen(event); - }); - } }, }; diff --git a/src/js/plyr.js b/src/js/plyr.js index 08711172..675ddb0c 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -13,6 +13,7 @@ import utils from './utils'; import captions from './captions'; import controls from './controls'; import fullscreen from './fullscreen'; +import listeners from './listeners'; import media from './media'; import storage from './storage'; import source from './source'; @@ -214,6 +215,9 @@ class Plyr { // Allow focus to be captured this.elements.container.setAttribute('tabindex', 0); + // Global listeners + listeners.global.call(this); + // Add style hook ui.addStyleHook.call(this); |