Listen for all events in JavaScript
I'm trying to figure out how to listen for all events on a JavaScript object.
I know that I can add individual events with something like this
element.addEventListener("click", myFunction);
element.addEventListener("mouseover", myFunction);
...
I'm trying to figure out if there is a catch-all, I'd like to do something like this:
// Begin pseudocode
var myObj = document.getElementById('someID');
myObj.addEventListener(/*catch all*/, myFunction);
function myFunction() {
alert(/*event name*/);
}
// End pseudocode
Solution 1:
A more modern rewrite of @roman-bekkiev's answer:
Object.keys(window).forEach(key => {
if (/^on/.test(key)) {
window.addEventListener(key.slice(2), event => {
console.log(event);
});
}
});
Note that you can further customize what you want to catch, for example:
/^on(key|mouse)/.test(key)
Solution 2:
To pick up standard element's events.
var myObj = document.getElementById('someID');
for(var key in myObj){
if(key.search('on') === 0) {
myObj.addEventListener(key.slice(2), myFunction)
}
}
But as @jeremywoertink mentioned any other events are also possible.
Solution 3:
I hate that this problem persists without a native or elegant solution.
A Better Solution?
This allows you to subscribe to a single CustomEvent
for any EventTarget
using target.addEventListener('*', ...)
.
clear();
/**
* @param : source := EventTarget
* * EventTarget.prototype
* * Node (Element, Attr, etc)
* @usage : [Node].addEventListener('*', ({ detail: e }) => {...}, false);
*/
function proxyEventTargetSource(source) {
var emit = source.dispatchEvent; // obtain reference
function proxy(event) {
var { type } = event, any = new CustomEvent('*', { detail: event }); // use original event as detail
if (!{ '*': true }[ type ]) emit.call(this, any); // only emit "any" if type is not any.type ('*')
return emit.call(this, event);
}
if ({ 'dispatchEvent': true }[ emit.name ]) source.dispatchEvent = proxy; // attempt overwrite only if not already set (avoid rewrapping)
return (source.dispatchEvent === proxy); // indicate if its set after we try to
}
// proxyEventTargetSource(EventTarget.prototype); // all targets
proxyEventTargetSource(document); // single target
var e = new CustomEvent('any!', { detail: true });
document.addEventListener('*', (e) => console.log('type: %s, original: %s, e: %O', e.type, e.detail.type, e), false);
document.dispatchEvent(e);
Granted, a more native or [perhaps] more elegant way would be to use a native Proxy
on apply
for the target's dispatchEvent
method, but that would maybe convey less for the sake of this post.
Gist: https://gist.github.com/cScarlson/875a9fca7ab7084bb608fb66adff0463
Known Issues
Apparently, this only works while driving event-dispatching through EventTargets
's dispatchEvent
method. That is, naturally triggering events through mouse events (for instance) does not work. There would need to be a way to wrap the internal method being called by natural event-triggers.
That being said, if you have a way around this, please show what you have in another answer.