aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSam Potts <me@sampotts.me>2017-11-06 21:19:00 +1100
committerSam Potts <me@sampotts.me>2017-11-06 21:19:00 +1100
commit2497e25b3ce6849986c3501354636fdae11df6d4 (patch)
tree2b780e9d6d2626850a8015b04124af56fc647771 /src
parent9c4b7e70948af3a1e45b63b3d36f3cae86802919 (diff)
downloadplyr-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.js347
-rw-r--r--src/js/plyr.js4
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);