InvalidStateError: Failed to execute 'dispatchEvent' on 'EventTarget' - javascript

I'm trying to spoof a mouse event in Javascript. Here's whats happening:
// Create event object
var event = new CustomEvent('mousedown');
// Initialize
event.initCustomEvent('mousedown', true, false, {});
// Inherit
event = Object.create(event);
event.pageX = 10;
event.pageY = 10;
Now, to dispatch...
targetElement.dispatchEvent(event);
When I do this I get the error:
Error: Failed to execute 'dispatchEvent' on 'EventTarget': The event provided is null.
What am I doing wrong?

An event must have an own property of type, an inherited type property is not enough and will mean type is treated as undefined, hence the error
// Create event object
var event = new CustomEvent('mousedown', {bubbles: true, cancelable: false});
// initCustomEvent deprecated, see below
// Inherit
event = Object.create(event);
event.type = 'mousedown';
event.pageX = 10;
event.pageY = 10;
This error may also be a warning of other unexpected behaviour that will stem from the way you're dispatching an Object which is inheriting from an Event rather than having own properties.
CustomEvent instances are not sealed, so you can always add properties to them directly
var ev = new CustomEvent('mousedown', {bubbles: true, cancelable: false});
ev.pageX = 10;
ev.pageY = 10;
Be aware that the customEvent.initCustomEvent method is deprecated, you should pass this information into the constructor as a dictionary in the second arg,
var cev = new CustomEvent('mousedown', {bubbles: true, cancelable: false});
If you don't need a detail property, consider using Event instead of CustomEvent
var eev = new Event('mousedown', {bubbles: true, cancelable: false});
// cev as above, now consider
'detail' in cev; // true
cev.detail; // null
// vs
'detail' in eev; // false
eev.detail; // undefined
A mousedown event usually has a read-only detail of 0 (which rarely gets checked by code)

The problem is this line
event = Object.create(event);
Apparently, dispatchEvent expects event object to have certain own properties which it fails to find, because it's not checking prototype. Then it assumes that passed object is not well-formed event instance. Hence the error.
I'm not sure why you want to create new object with original event in prototype, without this everything should work.

Related

Custom Event having same name as native event

First of all, I would like to know whether it is right to create custom event with the same name as native event ?
My requirement is, I want to dispatch a custom event "click" with additional data using Javascript dispatchEvent. If I do so, the event is fired twice. My code is given below:
button.addEventListener("click", (event)=>{
if(!event.detail || event.detail && !event.detail.fromComponent){
let eventObject = new CustomEvent("click", {bubbles: true, composed: true, cancelable: true, detail: {myCustomKey: myCustomValue, fromComponent: true });
}
});
To avoid infinite looping, I have added boolean key*fromComponent in the detail object. Is there any way to achieve my requirement?

Event vs CustomEvent

I was wondering, what is the purpose of CustomEvent, because it can be easily emulated by good old Event.
So, what is the difference between:
var e = new Event("reload");
e.detail = {
username: "name"
};
element.dispatchEvent(e);
and
var e = new CustomEvent("reload", {
detail: {
username: "name"
}
});
inner.dispatchEvent(e);
Why does CustomEvent exist if it is easy to attach custom data to ordinary Event object?
It's not the same. You can't set the detail of a real CustomEvent:
var event = new CustomEvent('myevent', {detail:123});
event.detail = 456; // Ignored in sloppy mode, throws in strict mode
console.log(event.detail); // 123
var event = new Event('myevent');
event.detail = 123; // It's not readonly
event.detail = 456;
console.log(event.detail); // 456
Yes, you could use Object.defineProperty. But I guess the point is that the argument of CustomEvent was supposed to set some internal data of the event. Now it only considers detail, which is not used internally. But a future spec could add something new, and then you may not be able to set that internal data by using properties.
A CustomEvent also inherits from CustomElement.prototype. That only adds detail and the deprecated initCustomEvent. But you can add your own methods or properties in there, which won't be inherited by other events. But I don't recommend this, you shouldn't modify objects you don't own.
So basically you can use CustomEvent in order to classify the event differently than other events. See this graphic from an old spec

Adding an object to a fabric.Canvas without dispatching the `object:added` event

Is there a way of adding an object to a fabric.Canvas instance without dispatching the object:added event?
Currently I'm forced to use the following ugly approach:
var dispatchObjectAdded = true;
canvas.on('object:added', function () {
if (!dispatchObjectAdded) {
return;
}
// handle event..
});
// add normally with dispatch
canvas.add(object);
// add without dispatch
dispatchObjectAdded = false;
canvas.add(object);
dispatchObjectAdded = true;
This works because the object:added event is dispatched synchronously, but I'm sure there's a better way – I just can't find what it is.
You can define a custom property on your object, and check in the event handler if the object that triggered the event has that property.
Here is a small fiddle example.

How to modify target property of Event object in JavaScript?

I'm executing async code, so I wanted to trigger an event once I finished. I created Event object, and I want to pass my current "this" object as a target property of the event. However, this property do not change.
var e = new Event("success");
e.target = myTargetObject;
console.log(e.target); // return 'null' for any myTargetObject.
var chngEvt = document.createEvent("MouseEvents");
chngEvt.initMouseEvent('click', true, true);
e.target.dispatchEvent(chngEvt);

Javascript event custom property disappears

I have an iFrame inside my document, which at one point triggers a custom event:
function notifyEnd(gameStatus) {
var fireOnThis = parent.document;
var evObj = document.createEvent('Event');
evObj.gameStatus = gameStatus;
evObj.initEvent('gameEnd', true, true);
fireOnThis.dispatchEvent(evObj);
}
Please note the gameStatus property set on the event.
My document registers an event listener for this event:
document.addEventListener('gameEnd', function(e) {
document.getElementById("gameEndForm:gameStatus").value = e.gameStatus;
document.getElementById("gameEndForm:gameCompleteButton").click();
}, true);
However, when the event is fired, the "gameStatus" property has an "undefined" value. I couldn't find any clue as to what could cause such a behaviour.
Thanks for your help,
Sébastien
Seems to me that you want to use a MessageEvent and use the data parameter of initMessageEvent.
http://help.dottoro.com/ljknkjqd.php
You can use JSON is you want to pass more than just one string.

Categories