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
})
Related
Does anybody know of a method to trigger an event in Prototype, as you can with jQuery's trigger function?
I have bound an event listener using the observe method, but I would also like to be able to fire the event programatically.
event.simulate.js fits your needs.
I've used this several times and it works like a charm. It allows you to manually trigger native events, such as click or hover like so:
$('foo').simulate('click');
The great thing about this is that all attached event handlers will still be executed, just as if you would have clicked the element yourself.
For custom events you can use the standard prototype method Event.fire().
I don't think there is one built in to Prototype, but you can use this (not tested but should at least get you in the right direction):
Element.prototype.triggerEvent = function(eventName)
{
if (document.createEvent)
{
var evt = document.createEvent('HTMLEvents');
evt.initEvent(eventName, true, true);
return this.dispatchEvent(evt);
}
if (this.fireEvent)
return this.fireEvent('on' + eventName);
}
$('foo').triggerEvent('mouseover');
I found this post helpful... http://jehiah.cz/archive/firing-javascript-events-properly
It covers a way to fire events in both Firefox and IE.
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);
}
}
The answers here are true for "Normal" events, that is events which are defined by the User Agent, but for custom events you should use prototype's "fire" method. e.g.
$('something').observe('my:custom', function() { alert('Custom'); });
.
.
$('something').fire('my:custom'); // This will cause the alert to display
I made a google chrome plugin
tasks (on sportingbet.com):
put price for the bet
submit the basket
the problem:
$(".userItems input.amount").val(110); -> works (but need to trigger the keyup)
$(".userItems input.amount").keyup(); -> doesn't work but when I type this in the console, it works.
Whats the difference?
This is mostly interesting, but one angle is to create a simulated key event:
function simulateKeyEvent() {
var event = document.createEvent("KeyboardEvent");
event.initKeyEvent(
"keyup",
true /*let event bubble up*/,
true /*can the event be canceled?*/,
null,
false /*ctrl key held down?*/,
false /*alt?*/,
false /*shift?*/,
false /*meta (cmd)?*/,
9 /*keyCode*/,
0);
var cb = document.getElementById("checkbox");
var canceled = !cb.dispatchEvent(event);
if(canceled) {
// A handler called preventDefault
alert("canceled");
} else {
// None of the handlers called preventDefault
alert("not canceled");
}
}
Now, to actually solve your problem, you might want to run the code outside the extension isolated world, in the page's javascript. To do this, I have a nifty function for you:
function runInPage(code) {
var script = document.createElement('script');
script.innerHTML = code;
document.documentElement.insertBefore(script);
}
Then try runInPage('$(".userItems input.amount").keyup();');
But you'll probably need to load jQuery before this, so do:
var jq = document.createElement('script');
jq.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
document.documentElement.appendChild(jq);
.keyup() without argument will just trigger any callback attach to the keyup event for that input
.val(110) all that is suppose to do is set the value for the input element, which is why not event is triggered.
.val(110).keyup() will do both
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.
The following doesn't work... (at least not in Firefox: document.getElementById('linkid').click() is not a function)
<script type="text/javascript">
function doOnClick() {
document.getElementById('linkid').click();
//Should alert('/testlocation');
}
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>
You need to apply the event handler in the context of that element:
var elem = document.getElementById("linkid");
if (typeof elem.onclick == "function") {
elem.onclick.apply(elem);
}
Otherwise this would reference the context the above code is executed in.
The best way to solve this is to use Vanilla JS, but if you are already using jQuery, there´s a very easy solution:
<script type="text/javascript">
function doOnClick() {
$('#linkid').click();
}
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>
Tested in IE8-10, Chrome, Firefox.
To trigger an event you basically just call the event handler for that
element. Slight change from your code.
var a = document.getElementById("element");
var evnt = a["onclick"];
if (typeof(evnt) == "function") {
evnt.call(a);
}
Granted, OP stated very similarly that this didn't work, but it did for me. Based on the notes in my source, it seems it was implemented around the time, or after, OP's post. Perhaps it's more standard now.
document.getElementsByName('MyElementsName')[0].click();
In my case, my button didn't have an ID. If your element has an id, preferably use the following (untested).
document.getElementById('MyElementsId').click();
I originally tried this method and it didn't work. After Googling I came back and realized my element was by name, and didn't have an ID. Double check you're calling the right attribute.
Source: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click
$("#linkid").trigger("click");
Old thread, but the question is still relevant, so...
(1) The example in your question now DOES work in Firefox. However in addition to calling the event handler (which displays an alert), it ALSO clicks on the link, causing navigation (once the alert is dismissed).
(2) To JUST call the event handler (without triggering navigation) merely replace:
document.getElementById('linkid').click();
with
document.getElementById('linkid').onclick();
Have a look at the handleEvent method
https://developer.mozilla.org/en-US/docs/Web/API/EventListener
"Raw" Javascript:
function MyObj() {
this.abc = "ABC";
}
MyObj.prototype.handleEvent = function(e) {
console.log("caught event: "+e.type);
console.log(this.abc);
}
var myObj = new MyObj();
document.querySelector("#myElement").addEventListener('click', myObj);
Now click on your element (with id "myElement") and it should print the following in the console:
caught event: click
ABC
This allows you to have an object method as event handler, and have access to all the object properties in that method.
You can't just pass a method of an object to addEventListener directly (like that: element.addEventListener('click',myObj.myMethod);) and expect myMethod to act as if I was normally called on the object. I am guessing that any function passed to addEventListener is somehow copied instead of being referenced. For example, if you pass an event listener function reference to addEventListener (in the form of a variable) then unset this reference, the event listener is still executed when events are caught.
Another (less elegant) workaround to pass a method as event listener and stil this and still have access to object properties within the event listener would be something like that:
// see above for definition of MyObj
var myObj = new MyObj();
document.querySelector("#myElement").addEventListener('click', myObj.handleEvent.bind(myObj));
If you're using this purely to reference the function in the onclick attribute, this seems like a very bad idea. Inline events are a bad idea in general.
I would suggest the following:
function addEvent(elm, evType, fn, useCapture) {
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
}
else if (elm.attachEvent) {
var r = elm.attachEvent('on' + evType, fn);
return r;
}
else {
elm['on' + evType] = fn;
}
}
handler = function(){
showHref(el);
}
showHref = function(el) {
alert(el.href);
}
var el = document.getElementById('linkid');
addEvent(el, 'click', handler);
If you want to call the same function from other javascript code, simulating a click to call the function is not the best way. Consider:
function doOnClick() {
showHref(document.getElementById('linkid'));
}
In general I would recommend against calling the event handlers 'manually'.
It's unclear what gets executed because of multiple registered
listeners
Danger to get into a recursive and infinite event-loop (click A
triggering Click B, triggering click A, etc.)
Redundant updates to the DOM
Hard to distinguish actual changes in the view caused by the user from changes made as initialisation code (which should be run only once).
Better is to figure out what exactly you want to have happen, put that in a function and call that manually AND register it as event listener.
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
})