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.