Javascript - Dispatch built-in events [duplicate] - javascript

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

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
})

Firing events on many DOM elements with javascript

I was wondering if it is possible to fire many events (not only one element with one type of event) at the same time in JavaScript on different DOM elements ("li" , "a" , " input", etc..) , I'm using the function fireEvent(element , event) to do the job with only one element and only one kind of event (onchange for example):
function fireEvent(element,event) {
if (document.createEvent) {
// dispatch for firefox + others
var evt = document.createEvent("HTMLEvents");
evt.initEvent(event, true, true ); // event type,bubbling,cancelable
return !element.dispatchEvent(evt);
} else {
// dispatch for IE
var evt = document.createEventObject();
return element.fireEvent('on'+event,evt)
}
}
How can use this function to fire many events on many DOM elements?
This can be done with jQuery.
$("elements").action1().action2()
Having queue:false will trigger all the actions at the same moment.
Dunno if I understood your requirement correctly.
http://jsfiddle.net/t8mr7/1/
All the 4 actions being executed at the same event trigger.

How can I trigger a JavaScript event click

I have a hyperlink in my page. I am trying to automate a number of clicks on the hyperlink for testing purposes. Is there any way you can simulate 50 clicks on the hyperlink using JavaScript?
MSDN
I'm looking for onClick event trigger from the JavaScript.
Performing a single click on an HTML element: Simply do element.click(). Most major browsers support this.
To repeat the click more than once: Add an ID to the element to uniquely select it:
Google Chrome
and call the .click() method in your JavaScript code via a for loop:
var link = document.getElementById('my-link');
for(var i = 0; i < 50; i++)
link.click();
You should just use click. For more advanced event firing, use dispatchEvent.
const body = document.body;
body.addEventListener('click', e => {
console.log('clicked body');
});
console.log('Using click()');
body.click();
console.log('Using dispatchEvent');
body.dispatchEvent(new Event('click'));
Original Answer - Obsolete
Here is what I use for IE9+ http://jsfiddle.net/mendesjuan/rHMCy/4/
/**
* Fire an event handler to the specified node. Event handlers can detect that the event was fired programatically
* by testing for a 'synthetic=true' property on the event object
* #param {HTMLNode} node The node to fire the event handler on.
* #param {String} eventName The name of the event without the "on" (e.g., "focus")
*/
function fireEvent(node, eventName) {
// Make sure we use the ownerDocument from the provided node to avoid cross-window problems
var doc;
if (node.ownerDocument) {
doc = node.ownerDocument;
} else if (node.nodeType == 9){
// the node may be the document itself, nodeType 9 = DOCUMENT_NODE
doc = node;
} else {
throw new Error("Invalid node passed to fireEvent: " + node.id);
}
if (node.dispatchEvent) {
// Gecko-style approach (now the standard) takes more work
var eventClass = "";
// Different events have different event classes.
// If this switch statement can't map an eventName to an eventClass,
// the event firing is going to fail.
switch (eventName) {
case "click": // Dispatching of 'click' appears to not work correctly in Safari. Use 'mousedown' or 'mouseup' instead.
case "mousedown":
case "mouseup":
eventClass = "MouseEvents";
break;
case "focus":
case "change":
case "blur":
case "select":
eventClass = "HTMLEvents";
break;
default:
throw "fireEvent: Couldn't find an event class for event '" + eventName + "'.";
break;
}
var event = doc.createEvent(eventClass);
event.initEvent(eventName, true, true); // All events created as bubbling and cancelable.
event.synthetic = true; // allow detection of synthetic events
// The second parameter says go ahead with the default action
node.dispatchEvent(event, true);
} else if (node.fireEvent) {
// IE-old school style, you can drop this if you don't need to support IE8 and lower
var event = doc.createEventObject();
event.synthetic = true; // allow detection of synthetic events
node.fireEvent("on" + eventName, event);
}
};
Note that calling fireEvent(inputField, 'change'); does not mean it will actually change the input field. The typical use case for firing a change event is when you set a field programmatically and you want event handlers to be called since calling input.value="Something" won't trigger a change event.
What
l.onclick();
does is exactly calling the onclick function of l, that is, if you have set one with l.onclick = myFunction;. If you haven't set l.onclick, it does nothing. In contrast,
l.click();
simulates a click and fires all event handlers, whether added with l.addEventHandler('click', myFunction);, in HTML, or in any other way.
I'm quite ashamed that there are so many incorrect or undisclosed partial applicability.
The easiest way to do this is through Chrome or Opera (my examples will use Chrome) using the Console. Enter the following code into the console (generally in 1 line):
var l = document.getElementById('testLink');
for(var i=0; i<5; i++){
l.click();
}
This will generate the required result
.click() does not work with Android (look at mozilla docs, at mobile section). You can trigger the click event with this method:
function fireClick(node){
if (document.createEvent) {
var evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, false);
node.dispatchEvent(evt);
} else if (document.createEventObject) {
node.fireEvent('onclick') ;
} else if (typeof node.onclick == 'function') {
node.onclick();
}
}
From this post
Use a testing framework
This might be helpful - http://seleniumhq.org/ - Selenium is a web application automated testing system.
You can create tests using the Firefox plugin Selenium IDE
Manual firing of events
To manually fire events the correct way you will need to use different methods for different browsers - either el.dispatchEvent or el.fireEvent where el will be your Anchor element. I believe both of these will require constructing an Event object to pass in.
The alternative, not entirely correct, quick-and-dirty way would be this:
var el = document.getElementById('anchorelementid');
el.onclick(); // Not entirely correct because your event handler will be called
// without an Event object parameter.
IE9+
function triggerEvent(el, type){
var e = document.createEvent('HTMLEvents');
e.initEvent(type, false, true);
el.dispatchEvent(e);
}
Usage example:
var el = document.querySelector('input[type="text"]');
triggerEvent(el, 'mousedown');
Source: https://plainjs.com/javascript/events/trigger-an-event-11/
Please call trigger function any where and button will click.
<a href="#" id="myBtn" title="" >Button click </a>
function trigger(){
document.getElementById("myBtn").click();
}
Fair warning:
element.onclick() does not behave as expected. It only runs the code within onclick="" attribute, but does not trigger default behavior.
I had similar issue with radio button not setting to checked, even though onclick custom function was running fine. Had to add radio.checked = "true"; to set it. Probably the same goes and for other elements (after a.onclick() there should be also window.location.href = "url";)

How to Fire Personal Event in Javascript

I can't fire personal events using Javascript in IE. In Firefox work great.
My code is:
var evento;
if(document.createEventObject)
{
evento = document.createEventObject();
document.fireEvent('eventoPersonal', evento);
}
//FF
else
{
evento = document.createEvent('Events');
evento.initEvent('eventoPersonal',true,false);
document.dispatchEvent(evento);
}
But when try to execute document.fireEvent('eventoPersonal', evento); in IE, it doesn't work. How can I fire NO custom events in IE?
In Internet Explorer I get the error: "Invalid arguments" in the line where execute document.fireEvent('eventoPersonal', evento);
Dean Edward's describes how to fire cutsom events in IE
http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/
Its near the bottom of the article
var currentHandler;
if (document.addEventListener) {
// We've seen this code already
} else if (document.attachEvent) { // MSIE
document.documentElement.fakeEvents = 0; // an expando property
document.documentElement.attachEvent("onpropertychange", function(event) {
if (event.propertyName == "fakeEvents") {
// execute the callback
currentHandler();
}
});
dispatchFakeEvent = function(handler) {
// fire the propertychange event
document.documentElement.fakeEvents++;
};
}
I think the answer is - in IE you can not fire events that are not on this list:
MSDN - DHTML Events
From what I can gather, frameworks store a registry of the "custom" event names and you must use their implementation specific trigger and handle functions for custom events. For example, prototype uses the ondatavailable event to pass through their custom events behind the scenes.
You may want to consider using a library to abstract this. Both prototype an jquery will handle this for you. Jquery is especially good at allowing you to create an event with very simple code.
Jquery's documentation is available here:
http://docs.jquery.com/Events
In IE11 document.dispatchEvent still doesn't work, but now attachEvent is missing too, so the other solution is not going to work either. However, I came up with one even uglier. :) It involves replacing the addEventListener method and goes on like this:
var oldEventListener = document.addEventListener;
document.addEventListener = function (event, func, capture) {
if (event == "MyPreciousCustomEvent") {
document.MyPreciousCustomEvent = func;
}
oldEventListener.call(document, event, func, capture);
};
...
$(function () {
try {
document.MyPreciousCustomEvent("MyPreciousCustomEvent", {});
} catch (e) {}
});
Hope this helps someone.
As I read the relevant MSDN article page on the createEventObject method, it appears as though it isn't used for creating custom event - it is used for creating custom objects that can be passed to already existing events.
Description:
Generates an event object to pass event context information when you use the fireEvent method.
http://msdn.microsoft.com/en-us/library/ms536390%28VS.85%29.aspx
Update: You are getting the "invalid arguments" error because 'eventoPersonal' is not an acceptable event to fire.
Yeah referring to #Don Albrecht, you can use jquery trigger() method more on http://api.jquery.com/trigger/

How do I programmatically force an onchange event on an input?

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
})

Categories