How to modify target property of Event object in JavaScript? - 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);

Related

Call change event of an input programatically [duplicate]

How do I programmatically force an onchange event on an input?
I've tried something like this:
var code = ele.getAttribute('onchange');
eval(code);
But my end goal is to fire any listener functions, and that doesn't seem to work. Neither does just updating the 'value' attribute.
Create an Event object and pass it to the dispatchEvent method of the element:
var element = document.getElementById('just_an_example');
var event = new Event('change');
element.dispatchEvent(event);
This will trigger event listeners regardless of whether they were registered by calling the addEventListener method or by setting the onchange property of the element.
By default, events created and dispatched like this don't propagate (bubble) up the DOM tree like events normally do.
If you want the event to bubble, you need to pass a second argument to the Event constructor:
var event = new Event('change', { bubbles: true });
Information about browser compability:
dispatchEvent()
Event()
In jQuery I mostly use:
$("#element").trigger("change");
ugh don't use eval for anything. Well, there are certain things, but they're extremely rare.
Rather, you would do this:
document.getElementById("test").onchange()
Look here for more options:
http://jehiah.cz/archive/firing-javascript-events-properly
For some reason ele.onchange() is throwing a "method not found" expception for me in IE on my page, so I ended up using this function from the link Kolten provided and calling fireEvent(ele, 'change'), which worked:
function fireEvent(element,event){
if (document.createEventObject){
// dispatch for IE
var evt = document.createEventObject();
return element.fireEvent('on'+event,evt)
}
else{
// dispatch for firefox + others
var evt = document.createEvent("HTMLEvents");
evt.initEvent(event, true, true ); // event type,bubbling,cancelable
return !element.dispatchEvent(evt);
}
}
I did however, create a test page that confirmed calling should onchange() work:
<input id="test1" name="test1" value="Hello" onchange="alert(this.value);"/>
<input type="button" onclick="document.getElementById('test1').onchange();" value="Say Hello"/>
Edit: The reason ele.onchange() didn't work was because I hadn't actually declared anything for the onchange event. But the fireEvent still works.
Taken from the bottom of QUnit
function triggerEvent( elem, type, event ) {
if ( $.browser.mozilla || $.browser.opera ) {
event = document.createEvent("MouseEvents");
event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
elem.dispatchEvent( event );
} else if ( $.browser.msie ) {
elem.fireEvent("on"+type);
}
}
You can, of course, replace the $.browser stuff to your own browser detection methods to make it jQuery independent.
To use this function:
var event;
triggerEvent(ele, "change", event);
This will basically fire the real DOM event as if something had actually changed.
This is the most correct answer for IE and Chrome::
var element = document.getElementById('xxxx');
var evt = document.createEvent('HTMLEvents');
evt.initEvent('change', false, true);
element.dispatchEvent(evt);
If you add all your events with this snippet of code:
//put this somewhere in your JavaScript:
HTMLElement.prototype.addEvent = function(event, callback){
if(!this.events)this.events = {};
if(!this.events[event]){
this.events[event] = [];
var element = this;
this['on'+event] = function(e){
var events = element.events[event];
for(var i=0;i<events.length;i++){
events[i](e||event);
}
}
}
this.events[event].push(callback);
}
//use like this:
element.addEvent('change', function(e){...});
then you can just use element.on<EVENTNAME>() where <EVENTNAME> is the name of your event, and that will call all events with <EVENTNAME>
The change event in an input element is triggered directly only by the user. To trigger the change event programmatically we need to dispatch the change event.
The question is Where and How?
"Where" we want the change event to be triggered exactly at the moment after a bunch of codes is executed, and "How" is in the form of the following syntax:
const myInput = document.getElementById("myInputId");
function myFunc() {
//some codes
myInput.dispatchEvent(new Event("change"));
}
In this way, we created the change event programmatically by using the Event constructor and dispatched it by the dispatchEvent() method. So whenever myFunc() method is invoked, after the //some codes are executed, our synthetic change event is immediately triggered on the desired input element.‍
Important result: Here, the change event is triggered by executing the //some codes in myFunc() instead of changing the input value by the user (default mode).
if you're using jQuery you would have:
$('#elementId').change(function() { alert('Do Stuff'); });
or MS AJAX:
$addHandler($get('elementId'), 'change', function(){ alert('Do Stuff'); });
Or in the raw HTML of the element:
<input type="text" onchange="alert('Do Stuff');" id="myElement" />
After re-reading the question I think I miss-read what was to be done. I've never found a way to update a DOM element in a manner which will force a change event, what you're best doing is having a separate event handler method, like this:
$addHandler($get('elementId'), 'change', elementChanged);
function elementChanged(){
alert('Do Stuff!');
}
function editElement(){
var el = $get('elementId');
el.value = 'something new';
elementChanged();
}
Since you're already writing a JavaScript method which will do the changing it's only 1 additional line to call.
Or, if you are using the Microsoft AJAX framework you can access all the event handlers via:
$get('elementId')._events
It'd allow you to do some reflection-style workings to find the right event handler(s) to fire.
Using JQuery you can do the following:
// for the element which uses ID
$("#id").trigger("change");
// for the element which uses class name
$(".class_name").trigger("change");
For triggering any event in Javascript.
document.getElementById("yourid").addEventListener("change", function({
//your code here
})

Get onmouseover 'event' object when setting function from inside javascript

I used to have an inline onmouseover() defined and used the event object:
<script>
function foo(e, bar) {
var x = e.clientX;
var y = e.clientY;
// do something with the coordinates and bar
}
</script>
<div onmouseover="foo(event, 'barValue')"></div>
Now I'm generating the <div> html via java script, I can't figure out where to get my event object from.
var d = document.createElement("div");
d.onmouseover = function() { foo(event, dynamicBarValue); };
I am not looking for a solution using JQuery.
You are going to receive the evt as a first parameter of your listener (check EventTarget.dispatchEvent()). So you could simply do:
var d = document.createElement("div");
d.onmouseover = function(evt) { foo(evt, dynamicBarValue); };
You are using the On-Event handler Properties syntax for adding the event . However, you are trying to overwrite the event (Property) in JS code by using Syntax
d.onmouseover = function() ....
You have already specified the event in HTML attribute
<div onmouseover="foo(event, 'barValue')"></div> and this code binds the function foo with the mouseover event. When you try to add the d.onmouseover event again in the JS file it will overrwrite the property and create a new handler for your event.
So, You only need to define the attribute in either the HTML code or JS Code.
Moreover, the first argument is the event information.
From MDN,
When the event handler is specified as an HTML attribute, the
specified code is wrapped into a function with the following
parameters:
event - for all event handlers, except onerror.
event, source, lineno,
colno, and error for the onerror event handler. Note that the event
parameter actually contains the error message as string.
So, you can achieve the desired effect be defining only one event handler.
function foo(e, bar) {
var x = e.clientX;
var y = e.clientY;
// do something with the coordinates and bar
console.log(x,y,bar)
}
<div onmouseover="foo(event, 'barValue')">Test</div>

How adding event handler inside a class with a class-method as the callback?

How do I add an event handler inside a class with a class-method as the callback?
<div id="test">move over here</div>
<script>
oClass = new CClass();
function CClass()
{
this.m_s = "hello :-/";
this.OnEvent = OnEvent;
with(this)
{
var r = document.getElementById("test");
r.addEventListener('mouseover', this.OnEvent); // this does NOT work :-/
}
function OnEvent()
{
alert(this); // this will be the HTML div-element
alert(this.m_s); // will be undefined :-()
}
}
</script>
Yes I know some quirks to make it work but what would be the intended way when these event handlers were introduced ??? I again have the bitter feeling, that no-one truly lives OOP :-(
Here for you to play: https://jsfiddle.net/sepfsvyo/1/
The this inside the event listener callback will be the element that fired the event. If you want the this to be the instance of your class, then either:
Bind the function to the class instance:
Using Function.prototype.bind, will create a new function that its this value will always be what you specify it to be (the class instance):
r.addEventListener('mouseover', this.OnEvent.bind(this));
// ^^^^^^^^^^^
Wrap the function inside an anonymous function:
var that = this;
r.addEventListener('mouseover', function(ev) { that.OnEvent(ev); });
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
or use an arrow function (so no need for that):
r.addEventListener('mouseover', ev => this.OnEvent(ev));
// ^^^^^^^^^^^^^^^^^^^^^^
Note: As mentioned in a comment bellow, both of the above methods pass a different function to addEventListener (the one with bind create a new function, and the anounimous function is obviously !== this.OnEvent). If you are going to remove the event listener later, you'll have to store a reference to the function:
var reference;
r.addEventListener('mouseover', reference = this.OnEvent.bind(this));
// ^^^^^^^^^^^^
or:
var reference;
var that = this;
r.addEventListener('mouseover', reference = function(ev) { that.OnEvent(ev); });
// ^^^^^^^^^^^^
then you can remove the event listener like:
r.removeEventListener('mouseover', reference);
You can actually return the object as an EventListener callback, this way JS will search for an handleEvent method in the class and execute accordingly :
var myInstance = new myClass;
myInstance.addEventListener("mousedown",myInstance);
// To remove the event you can follow the same pattern
myInstance.removeEventListener("mousedown",myInstance);
You have to construct your class this way :
class myClass {
constructor(){
// Whatever this is supposed to do.
// You can also add events listener within the class this way :
this.addEventListener("mousedown",this);
}
mouseDownEvent(e)(){
// Some action related to the mouse down event (e)
console.log(e.target);
}
mouseMoveEvent(e)(){
// Some action related to the mouse move event (e)
}
mouseUpEvent(e)(){
// Some action related to the mouse up event (e)
}
handleEvent(e) {
switch(e.type) {
case "mousedown":
this.mouseDownEvent(e);
break;
case "mousemove":
this.mouseMoveEvent(e);
break;
case "mouseup":
this.mouseUpEvent(e);
break;
}
}
}
Sources :
https://medium.com/#WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38
https://www.thecssninja.com/javascript/handleevent
https://metafizzy.co/blog/this-in-event-listeners/
I find this method clearer, also while declaring events inside the class this is pretty explicit.
Hope I helped someone.
The answer from #ibrahimmahrir does the job, but I wanted to consolidate a few points.
As many JavaScript developers struggle to understand, the this keyword is a moving target. In traditional OOP languages, an object method is exclusive to the object, so this is defined as the object to which it is attached.
JavaScript functions are more promiscuous, and can be attached to multiple objects. In JavaScript, this refers to the object which is currently invoking the function, not necessarily the one to which it was originally attached.
For an Event Handler function, the invoking object is the element to which it is attached, not the original object; thus this refers to the element. The usual safe method is to store a reference to the original object in a different variable, often called that:
oClass = new CClass();
function CClass() {
var that = this; // a reference to the original object
this.m_s = "hello :-/";
this.OnEvent = OnEvent;
var r = document.getElementById("test");
r.addEventListener('click', this.OnEvent);
function OnEvent() {
alert(that); // this is now the object
alert(that.m_s); // this works
}
}
The comments above are my updated comments. I have also removed the with statement which wasn’t contributing much and which is seriously discouraged.
Oh, and I have changed the event to click to make it easier to test.
While we’re on the confusion with this, it is not necessarily the element which started things off. Suppose we now include a span:
<div id="test">click <span>over</span> here</div>
Clicking on the span will trigger the event listener, even though the you didn’t actually click on the div to which it is attached. In this case the event is bubbled from the span to the div.
Here this refers only to the div element with the event listener. If you want to reference the span, you will need event.target:
function OnEvent(event) { // include event parameter
alert(this); // the element attached
alert(event.target); // the element clicked
alert(that); // this is now the object
alert(that.m_s); // this works
}
Here is an updated fiddle: https://jsfiddle.net/osk083xv/

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

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.

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