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/
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'm stuck working out which one of these I should be using: beforeunload or onbeforeunload They both seem to be doing very similar things, but with different browser compatibility.
Some context:
I have a form. On page load I serialise the form and save it in a variable. If the user leaves the page I serialise the form and compare the two, to see if there's been any changes. However, if the form is submitted then the event should not be fired.
Example 1
I have this working as expected. I just don't understand the differences between the two:
window.onbeforeunload = function(e) {
if(strOnloadForm != strUnloadForm)
return "You have unsaved changes.";
}
With this line to stop it firing when you save the form (bound to .submit())
window.onbeforeunload = null;
Example 2
window.addEventListener("beforeunload", function( event ) {
if(strOnloadForm != strUnloadForm)
event.returnValue = "You have unsaved changes.";
});
With this line to stop it firing when you save the form (bound to .submit())
window.removeEventListener("beforeunload");
What the documentation says
I've read the documentation for onbeforeunload and beforeunload.
Under the onbeforeunload section Notes it states:
You can and should handle this event through window.addEventListener() and the beforeunload event. More documentation is available there.1
Which makes me think I should be using the latter. However the documentation for removeEventHandler says this:
addEventListener() and removeEventListener() are not present in older browsers. You can work around this by inserting the following code at the beginning of your scripts, allowing use of addEventListener() and removeEventListener() in implementations which do not natively support it.2
Could somebody please shed some light on the differences for these please, and the best one to use?
1https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload#Notes
2https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener#Polyfill_to_support_older_browsers
window.onbeforeunload = function () {/**/} will override any existing handlers and replace it with your own.
window.addEventListener("beforeunload", function () {/**/}); will add a new handler.
addEventListener is far preferred. In older browsers (that is: IE6 maybe IE7) you can use attachEvent.
You'll commonly see code like:
function addEvent(object, event_type, event_handler) {
if (object.addEventListener) {
object.addEventListener(event_type, event_handler, false);
} else {
object.attachEvent("on" + event_type, handler);
}
}
I want to add an listener exactly once for beforeunload. This is my pseudocode:
if(window.hasEventListener('beforeunload') === false) {
window.addEventListener('beforeunload', function() { ... }, false);
}
But hasEventListener does not exist obviously. How can I achieve this? Thanks.
In fact there is no need to check if an listener was added to a target:
If multiple identical EventListeners are registered on the same EventTarget with the same parameters, the duplicate instances are discarded. They do not cause the EventListener to be called twice, and since the duplicates are discarded, they do not need to be removed manually with the removeEventListener method.
Source:https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener#Multiple_identical_event_listeners
Using jquery you can do use data("events") on any object (here the window) :
var hasbeforeunload = $(window).data("events") && $(window).data("events").['beforeunload'];
But this works only for jquery added events.
In a more general case, you should simply store the information that you add a listener somewhere :
var addedListeners = {};
function addWindowListenerIfNone(eventType, fun) {
if (addedListeners[eventType]) return;
addedListeners[eventType] = fun;
window.addEventListener(eventType, fun);
}
I think there is no standard way in javascript to get the existing event handlers. At best you could surcharge the addEventListener function of Node to intercept and store the listeners but I don't recommend it...
EDIT :
From jQuery 1.8, event data are available in $._data(element, "events"). The change log has a warning that should be taken into account :
Note that this is not a supported public interface; the actual data
structures may change incompatibly from version to version.
In Chrome Dev tool, you can check all events attached to an element (For debugging)-
// print all events attached to document
var eventObjectAttachedToDocument = getEventListeners(document);
for (var event in eventObjectAttachedToDocument) {
console.log(event);
}
Say I add events to an object using either addEventListener or attachEvent (depending on the browser); is it possible to later invoke those events programmatically?
The events handlers are added/removed using an object like this:
var Event = {
add: function(obj,type,fn) {
if (obj.attachEvent) {
obj.attachEvent('on'+type,fn);
} else {
obj.addEventListener(type,fn,false);
}
},
remove: function(obj,type,fn) {
if (obj.detachEvent) {
obj.detachEvent('on'+type,fn);
} else {
obj.removeEventListener(type,fn,false);
}
}
}
Or do I need to store copies of each handler and just add an Event.invoke(...) function?
Edit: Also, jQuery is not an option :D
As usual, you have to do it one way for Internet Explorer, and the correct way for everything else ;-)
For IE:
document.getElementById("thing_with_mouseover_handler").fireEvent("onmouseover");
See the MSDN library for more info.
For the real browsers:
var event = document.createEvent("MouseEvent");
event.initMouseEvent("mouseover", true, true, window);
document.getElementById("thing_with_mouseover_handler").dispatchEvent(event);
Note that, although the second, standards-based approach seems more long-winded, it is also considerably more flexible: check the documentation, starting with the Mozilla DOM Event Reference at https://developer.mozilla.org/en/DOM/event
Although only tangentially related to what you're trying to do (it's related to custom events, rather than normal ones) Dean Edwards has some example code at http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/ that may be worth a look.
Can you not create functions that do the work required, run those from the events then run those same functions later when required?
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.