Added support for passive event listeners

This commit is contained in:
Sam Potts 2017-05-08 23:07:19 +10:00
parent 279fee3595
commit 408cfe5b97
2 changed files with 71 additions and 25 deletions

4
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

View File

@ -671,52 +671,79 @@
}, },
// Bind along with custom handler // Bind along with custom handler
proxy: function(element, eventName, customListener, defaultListener, useCapture) { proxy: function(element, eventName, customListener, defaultListener, passive, capture) {
utils.on(element, eventName, function(event) { utils.on(element, eventName, function(event) {
if (customListener) { if (customListener) {
customListener.apply(element, [event]); customListener.apply(element, [event]);
} }
defaultListener.apply(element, [event]); defaultListener.apply(element, [event]);
}, useCapture); }, passive, capture);
}, },
// Toggle event listener // Toggle event listener
toggleListener: function(elements, events, callback, toggle, useCapture) { toggleListener: function(elements, events, callback, toggle, passive, capture) {
var eventList = events.split(' '); events = events.split(' ');
// Whether the listener is a capturing listener or not // Whether the listener is a capturing listener or not
// Default to false // Default to false
if (!is.boolean(useCapture)) { if (!is.boolean(capture)) {
useCapture = false; capture = false;
}
// Whether the listener can be passive (i.e. default never prevented)
// Default to true
if (!is.boolean(passive)) {
passive = true;
} }
// If a nodelist is passed, call itself on each node // If a nodelist is passed, call itself on each node
if (elements instanceof NodeList) { if (elements instanceof NodeList) {
for (var x = 0; x < elements.length; x++) { // Convert arguments to Array
if (elements[x] instanceof Node) { // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/arguments
utils.toggleListener(elements[x], arguments[1], arguments[2], arguments[3]); var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments);
// Remove the first argument (elements) as we replace it
args.shift();
// Create listener for each node
[].forEach.call(elements, function(element) {
if (element instanceof Node) {
utils.toggleListener.apply(null, [element].concat(args));
} }
} });
return; return;
} }
// If a single node is passed, bind the event listener // Build options
for (var i = 0; i < eventList.length; i++) { // Default to just capture boolean
elements[toggle ? 'addEventListener' : 'removeEventListener'](eventList[i], callback, useCapture); var options = capture;
// If passive events listeners are supported
if (support.passiveListeners) {
options = {
passive: passive,
capture: capture
};
} }
// If a single node is passed, bind the event listener
events.forEach(function(event) {
elements[toggle ? 'addEventListener' : 'removeEventListener'](event, callback, options);
});
}, },
// Bind event handler // Bind event handler
on: function(element, events, callback, useCapture) { on: function(element, events, callback, passive, capture) {
if (!is.undefined(element)) { if (!is.undefined(element)) {
utils.toggleListener(element, events, callback, true, useCapture); utils.toggleListener(element, events, callback, true, passive, capture);
} }
}, },
// Unbind event handler // Unbind event handler
off: function(element, events, callback, useCapture) { off: function(element, events, callback, passive, capture) {
if (!is.undefined(element)) { if (!is.undefined(element)) {
utils.toggleListener(element, events, callback, false, useCapture); utils.toggleListener(element, events, callback, false, passive, capture);
} }
}, },
@ -989,6 +1016,24 @@
// Check for textTracks support // Check for textTracks support
textTracks: (function() { textTracks: (function() {
return 'textTracks' in document.createElement('video'); return 'textTracks' in document.createElement('video');
})(),
// Check for passive event listener support
// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
// https://www.youtube.com/watch?v=NPM6172J22g
passiveListeners: (function() {
// Test via a getter in the options object to see if the passive property is accessed
var supported = false;
try {
var options = Object.defineProperty({}, 'passive', {
get: function() {
supported = true;
}
});
window.addEventListener("test", null, options);
} catch (e) {}
return supported;
})() })()
}; };
@ -1090,7 +1135,7 @@
} }
// Bind the handler // Bind the handler
utils.on(player.elements.container, 'keydown', checkFocus); utils.on(player.elements.container, 'keydown', checkFocus, false);
} }
// Add elements to HTML5 media (source, tracks, etc) // Add elements to HTML5 media (source, tracks, etc)
@ -3869,11 +3914,11 @@
if (count === 1 && utils.inArray(allowed, code) && (!is.htmlElement(focused) || !utils.matches(focused, config.selectors.editable))) { if (count === 1 && utils.inArray(allowed, code) && (!is.htmlElement(focused) || !utils.matches(focused, config.selectors.editable))) {
handleKey(event); handleKey(event);
} }
}); }, false);
} }
// Handle presses on focused // Handle presses on focused
utils.on(player.elements.container, 'keydown keyup', handleKey); utils.on(player.elements.container, 'keydown keyup', handleKey, false);
} }
function handleKey(event) { function handleKey(event) {
@ -4157,7 +4202,8 @@
}); });
// Focus in/out on controls // Focus in/out on controls
utils.on(player.elements.controls, 'focus blur', toggleControls, true); // TODO: Check we need capture here
utils.on(player.elements.controls, 'focus blur', toggleControls, true, true);
} }
// Mouse wheel for volume // Mouse wheel for volume
@ -4195,7 +4241,7 @@
(direction === -1 && player.elements.media.volume > 0)) { (direction === -1 && player.elements.media.volume > 0)) {
event.preventDefault(); event.preventDefault();
} }
}); }, false);
// Handle user exiting fullscreen by escaping etc // Handle user exiting fullscreen by escaping etc
if (support.fullscreen) { if (support.fullscreen) {
@ -4275,7 +4321,7 @@
if (config.disableContextMenu) { if (config.disableContextMenu) {
utils.on(player.elements.media, 'contextmenu', function(event) { utils.on(player.elements.media, 'contextmenu', function(event) {
event.preventDefault(); event.preventDefault();
}); }, false);
} }
// Proxy events to container // Proxy events to container