Reusable Javascript event object
Asked Answered
I

3

6

I am making mouse click events and I'm trying to dispatch it to some node several times in a row. For that I am using the same MouseEvent object and for some reason this approach does not work. Yet, when I create event manually each time, system works. Does anybody know what is the reason for this behavior? I've tried to change the timeStamp, but problem still occurs. I can solve the problem like I mentioned before, but I am interested in how this MouseEvent and corresponding dispatching and handling subsystems really work. MouseEvent specification that I've found on MDC pages seems to lack a lot of information.

Tnx for the help!

Irisation answered 11/8, 2011 at 21:48 Comment(0)
A
8

Update (2023-08-08): It seems that redispatching events is allowed in current browsers. In fact, according to bug 412567, Firefox allowed this since 2008. This was a change introduced to become compliant with the Acid3 test.

Original answer for reference below.


This is actually a security mechanism, dispatching an event that has been dispatched before isn't allowed. An event always has additional data associated with it, for example whether it comes from a trusted source (user's keyboard rather than JavaScript code). Some attacks (mostly against MSIE because it had mutable event objects) were using this - they caught a trusted event, changed it and dispatched it again elsewhere (changing might not always be required, dispatching it at a different element is enough for some attacks). In the end disallowing redispatching of events turned out to be the best solution. After all, this functionality isn't really required: creating a new event object with identical properties (minus hidden data) isn't exactly hard.

Pretty much all the security issues in this area were related to the file input control. Some time ago Firefox decided to change the file input UI radically and disallow entering the file name directly. I wonder whether this change made redispatching of events a non-issue. I doubt that anybody will be willing to risk opening this can of worms again however.

Abstractionism answered 11/8, 2011 at 22:22 Comment(3)
Maybe this answer needs an Update? In my Firefox 105, the following code perfectly works (logs 10 times 'click'): document.body.addEventListener("click", ev => {console.log("click!")}); const e = new MouseEvent("click"); for(i=0; i<10; i++) document.body.dispatchEvent(e); . For me it also works with other Events. And also if I don't create them myself, but reuse a native one... While I understand that reusing events can be problematic, I'm wondering if there aren't use cases where it is justified (e.g. if something is firing tons of change-Events, reusing might improve performance)Clinandrium
@Sebastian: Yes, I updated the answer. Interestingly, it would appear that Firefox already changed this behavior a while back – we are talking either Firefox 3.5 or 3.6. Both pre-date my original answer.Abstractionism
Thanks for the Update and for the link to the bug report. Nice find!Clinandrium
C
1

I think the reason you can't reuse the same MouseEvent object is because the event system maintains some internal state in the event objects so they can implement things like bubbling and cancelling. You may just have to stick with creating distinct event objects.

Reading Document Object Model Events may give you a better understanding of how the DOM event system works.

Castera answered 11/8, 2011 at 22:2 Comment(0)
C
0

Without knowing what you have now ill just go under assumption.

Make an event function:

function clickEvent(event) {
    //do something
}

Attach it:

obj.onclick = clickHandler;

And you can do this multiple times to multiple objects.

Chiffonier answered 11/8, 2011 at 21:56 Comment(1)
Maybe I wasn't clear. I am trying to dispatch an event, in particularly mouse click event, several times in a row with some small delay in between. For that, I make an MouseEvent and try to dispatch it to the same node via node.dispatchEvent(evt) syntax and I always use the same event object. That does not trigger the corresponding callbacks. When I each time recreate event object, it works. I can do that, but I am interested in how things really work. Tnx!Irisation

© 2022 - 2024 — McMap. All rights reserved.