Capture all events (javascript)

I want to be able to capture all the events that were created and sent, and fire on a callback when that happens.

In addition, I would like to be able to trigger a callback at any time when an event is paired with an event listener.

Problems include: dynamically added elements, events whose propagation or spooling are prevented, and custom events that are generated dynamically. I assume that I will need prototyping dispatchEvent or something else, but I'm not sure. Is it possible?

+6
source share
2 answers

Some basics of events:

  • Events are dispatched on the DOM object (usually an element), which is the purpose of the event.
  • Events can first propagate to children in the capture phase. This phase is rarely used, since until recently it was not supported by some commonly used browsers.
  • Events in the second case can propagate to the parent elements in the bubbling phase. This phase is commonly used.
  • Some events are not propagated, they do not have a capture phase or bubble (for example, focus, blur and send events). Some events that are distributed in some browsers are not distributed in others.
  • DOM elements that respond to events have an event handler. It can be configured to listen to certain events and call the listener function when this event reaches the element, either during capture, or in the form of bubbles, or if the element is the target of the event.
  • Listeners can cancel distribution, for example. the click event on the span inside the link can cancel the distribution, so the link does not receive a click

Given the above, the practical impossibility of "capturing all events" using the event API . This will require setting a listener for each type of event for each element and the inability to capture custom events because you need to know about them in order to set a suitable listener.

I assume that prototyping dispatchEvent or something will be needed

dispatchEvent is an event instance method, it is not specified as a constructor (there is no requirement that it has an internal [[Construct]] ), so it is not practical to use it as such. The browser does not need to implement prototype inheritance for host objects (although most of them do), and the details of the implementation of host objects and methods are largely hidden, so this is not an option.

You can try extending the event API, but you really shouldn't interact with host objects .

You seem to be worried about dynamically added elements. There is a strategy called โ€œevent delegationโ€ where you define the events you want to listen to, and then set your listeners as close to the target objects as possible on an element that does not change (for example, a table element if you dynamically add and delete rows tables or container divs for other elements) for specific types of events that you need to respond to.

You can also have functions that modify custom DOM send events to add listeners or something else.

+2
source

If you really want to do this, you can override addEventListener to track logged and triggered events.

 var myEventManager = (function() { var old = EventTarget.prototype.addEventListener, listeners = [], events = []; EventTarget.prototype.addEventListener = function(type, listener) { function new_listener(listener) { return function(e) { events.push(e); // remember event return listener.call(this, e); // call original listener }; } listeners.push([type, listener]); // remember call return old.call(this, type, new_listener(listener)); // call original }; return { get_events: function() { return events; }, get_listeners: function() {return listeners; } }; }()); 

However, there is no reason not to do this, not least because you quickly run out of memory when recording thousands of events, such as mouse movements. It also will not cause event listeners to be installed in ways like elt.onclick . Of course, they will not catch listeners configured through the old attachEvent IE attachEvent . Most importantly, it will not help you that events that are generated and listened for internal use, such as a mouse click on a checkbox. (A complete solution will also require removeEventListener processing.)

You can also override createEvent and dispatch same way, but again, this will only capture events that are explicitly created or dispatched in JS code.

If you really want to do what you think is desirable, I think you need to unlock Chrome.

+1
source

Source: https://habr.com/ru/post/974908/


All Articles