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>
Related
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
})
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/
I have added an event listener to my custom element for my <iron-ajax> call.
Question
How to I reference the last-response property of the <iron-ajax> element from an imperatively defined event listener?
See comments in below code.
custom-element.html
<template>
...
<iron-ajax id="ajax" last-response="{{ajax}}"></iron-ajax>
...
<template>
<script>
...
var t = this.$.ajax;
t.addEventListener('response', function(e) {
console.log(this.ajax); // undefined
console.log(e); // Successfully logs response event object to console
});
...
</script>
Use Javascript bind() to change the context of this in the function:
var t = this.$.ajax;
t.addEventListener('response', function(e) {
console.log(this); // this now = t
console.log(e); // Successfully logs response event object to console
}).bind(t);
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
I have found two ways around this issue.
THe first (which I use when I have an iron-ajax-form is to attach the event listener to the custom element, and let it bubble up from the elements inside
so
this.addEventListener('iron-form-response',function(e) {
//this is correct here
});
The other method, used when I am using an iron ajax itself (ie call this.$.ajax.generateRequest();
is to set a function on my element to take the response - so
<iron-ajax
id="validateuser"
url="/api/validate_user"
handle-as="json"
method = "POST"
body = "[[user]]"
content-type="application/json"
on-response="_validate"></iron-ajax>
and then inside _validate this still refers to my custom element. In this case I don't need last_response, because the response is found like this
_validate: function(e) {
var response = e.detail.response;
this.$.spinner.cancel();
if (response.status) {
//this user validated, so we are logged on
Include the this object in the scope of the event listener.
Introduce a new variable called that and apply the necessary scope as follows.
custom-element.html
var that = this, // Adds scope
t = this.$.ajax;
t.addEventListener('response', function(e) {
console.log(that.ajax); // Successful reference
});
I have an <input> which has an onkeydown inline event handler. In this handler, I'd like to call a function and pass a special parameter to it - the event data.
When I want to handle events (e.g. onmousemove) for the whole document, I use the following code:
document.onmousemove=function(e) {
// here I can make a good use of the 'e' variable,
// for example extract the mouse coordinates from it
}
And it works (although I don't know where the e variable - event data - comes from).
But this time I want to use the function only for the <input> mentioned above.
I need to pass the event data to the function so it can get the pressed key's code. And I want to do it in that inline event handler. I've created a function:
function myfunc (e) {
var evt=window.event?event:e;
var code=evt.keyCode;
alert (code);
}
and tried all of these methods:
<input onkeydown="myfunc(this)">
<input onkeydown="myfunc(this.onkeydown)">
<input onkeydown="myfunc(onkeydown)">
But none of them worked, the alert window kept displaying "undefined".
I looked for a solution to my problem in Google, but didn't find anything that could help me solve it.
<input onkeydown="myfunc(event)">
function myfunc (e) {
e = e || window.event;
var code = e.keyCode;
alert (code);
}
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.