Getting back the event handler returns undefined - javascript

The following codes don't work:
function dnd(){
}
var ele = document.getElementById("relative");
ele.addEventListener("click",dnd,false);
document.write(ele.onclick);
the output is undefined. I guess the output should be function onclick(event){dnd();}
What should I do to solve this problem?
Any suggestion is appreciated.

There are 3 common ways to attach events to DOM nodes.
The addEventListener() method is the way to register an event listener as specified in W3C DOM. It has many benefits, but doesn't work in Internet Explorer. For Internet Explorer you'd have to use the attachEvent() method, which offers similar functionality.
On the other hand, the onclick property is an older, but more supported way to attach event handlers. However it has certain disadvantages, such as allowing just one event handler for each event.
As for how to get back the event handlers that are attached to a particular node, it depends on the method you use to attach the events. The problem with your example is that you're using the addEventListener() method to attach the event, and then trying to read it using the onclick property.
You may want to check out the following Stack Overflow post for further reading into this topic, especially the post by #Crescent Fresh:
How to find event listeners on a DOM node?

The onclick property is only going to show you an event handler if it is registered inline via the markup (e.g, <div id="relative" onclick="alert('foo');"></div>).
Why do you need to read the event handler? This is a relatively strange thing to do...

There are different ways of establishing event handlers, and they use different mechanisms inside the DOM. In particular — and as you've discovered empirically — adding an event listener via "addEventListener" does not affect the "onclick" attribute of the element. The mechanisms are simply separate.

This is one of the current limitation of W3C event registration model. if you register using JS methods then there is no standard way to get the handlers.
Latest DOM LEVEL 3 Events W3C adds eventListenerList spec. i guess we are lacking of some close support for this API across browsers.
Of-course if you add your method using tradition way
then your example would work.
Some StackOverFlow Links
link text

Related

How does JQuery create it's Custom Events and can I recreate in Javascript?

I am looking to create events in Javascript using the same methodology as JQuery- Does anyone know how JQuery does it?
My reasoning is that using raw Javascript such this:
var myEvent = new CustomEvent("userLogin", eventProperties);
...does not actually work on Android native browser, as it does not support DOM Level 3 like Chrome and other browsers do.
However, JQuery does work on Android's stock browser, and simply uses:
$.event.trigger('MyEvent');
My question is, what is the code behind this? I tried to find it by going through JQuery's source code, but cannot get my head around it!
The fundamental thing here is this: When you hook an event handler up with jQuery, jQuery doesn't directly add that handler to the DOM element. Instead, jQuery hooks up a handler of its own on the DOM element (if it doesn't already have one on it). When the event occurs, jQuery looks at the list of jQuery-registered handlers for the event and fires them in order. (There are several reasons for this; initially it was primarily around IE memory leaks and the fact that IE fired handlers in one order, and everyone else in a different order; so jQuery took over and ensured the order.)
(You might be able to see where I'm going with this...)
So when you use trigger, jQuery sends the synthetic event to the DOM element, but it doesn't rely on that synthetic event to work; it calls the handlers you've registered through jQuery directly. In fact, it sets a flag so that it knows that it's done that, so if the browser does send the event to jQuery's handler for it, jQuery knows to ignore it (since it's already done its work).
You can see this in all its glory starting with line 4,464 of the current uncompressed jQuery file.
So basically jQuery's build its own pub/sub system, and only uses the browser event system as an input to it. So custom events don't usually have to talk to the browser at all.

Setting event handlers to DOM objects

I was looking for the most proper way to attach DOM events avoiding browser compatibility issues and found that the Mozilla developers site states:
The old way is to just assign it like this:
document.getElementById('cupcakeButton').onclick = getACupcake;
As above, the event object is either a global or an argument. This
method may have problems and is not the preferred method, but it still
works and a lot of people still use it.
What type of problems does this refer to?
The most obvious one is already mentioned, it would replace a previously assigned handler.
document.getElementById('id') should work in all browsers except in really old ones (Netscape 4-, IE 4-), there you should use document.layers['id'] and document.all[id] respectively.
IE 5 up to IE 7 have one more issue, which is that they will also return elements where name='id' instead of only the elements where id='id'. That could really stuff you up.
Have a look at jQuery for a way to attach DOM event handlers avoiding browser compatibility issues.
The biggest problem I can think of is that it won't allow assigning multiple click handlers, by doing another .onclick = fn; you basically unbind the previous handler if it was there.
Even if that magically worked, you would have no way to unregister a specific handler; it's all or nothing.

Where to get the list of event types?

The official documentation only says:
The event's type, such as "click", "blur" or "keypress".
For iOS devices the touchstart is another event which is working. Where can I get the full list of all possible events? I like for example actually to get the event for the <select> event hasChanged(). Is this based on another library?
Meteor doesn't define the events it supports — it simply creates a cross-browser event listener wrapper. If you wanted to create custom events and trigger them, Meteor would pick them up.
The native input events supported depends on the browser: the Mozilla Developer Network reference is a good place to start.
Th docs also says that all the DOM events are also possible in addition to click, focus, blur, etc.
Other DOM events are available as well, but for the events above,
Meteor has taken some care to ensure that they work uniformly in all
browsers.
You can see the list of available Javascript events here and here.

jQuery/Javascript temporarily disable events attached by addEventListener/attachEvent

Is there a way to temporarily disable an event listener?
In my case, I have a third party library (not jQuery centric) that creates mouseover/mouseout events on an element using addEventListener/attachEvent.
Under certain circumstances another event fires on a different element and I need to disable those event listeners. My solution thus far has been to simply unbind the mouseover/mouseout. This usually works fine because that event generally causes the page to refresh.
However, every now and again an error can occur (think validation error) that results in the page not refreshing, and I need to re-attach the mouseover/mouseout event listeners.
Helpful information
It's probably worth mentioning that because the mouseover/mouseout event listeners are created and attached within a third party library I cannot simply assign the event to a variable and bind/unbind it in that manner (which AFIK is the best way to do this).
Update
I had originally asked
Is there a way in jQuery to get the event listeners already assigned to an object?
I have since found out it is impossible to access events assigned by addEventListener/attachEvent: Access events added with attachEvent() / addEventListener() in JavaScript
jQuery uses data to store events internally, so you can use it to get all of the event handlers for an object:
$("#foo").data("events")
You can then remove a specific handler by using unbind:
$("#foo").unbind('click', $("#foo").data("events").click[42]);
Unfortunately, you can't access them. At best, you can remove event listeners using W3C's removeEventListener (docs) and/or Microsofts detachEvent (docs). Once the listener is removed, however, it's gone for good.
There's one caveat with removeEventListener, in that if the event was registered twice, once indicating to capture, and once indicating not to capture, you must remove it twice; once for each case.
To learn more about capturing and not capturing, see the W3C spec.
If you want to temporarily disable an event handler being run, why not just add escape code to the function?
like so:
$('#button').click(function(){
var clicked_element = $(this);
if(elem.hasClass('event-click-disabled'))
{
// logging code so we know exactly what events are being skipped
console.info(
'The click event on following element was skipped',
clicked_element
);
return;
}
alert('Button clicked');
});
Then if you want to disable an event on a specific element, just call
element.addClass('event-click-disabled');
The event handler is still run, but it will return immediately.

which HTML element lost focus?

in javascript, when I receive a focus event, how can I work out which element has lost focus? I'm trying to avoid having to put an onblur event handler on all elements within my web page.
#pbrodka: the target/srcElement property would refer to the element with focus for onfocus events
offhand I can't see a way to get this short of onblur, or if the set of objects you care about all have focus methods you could store a reference to that object instead. It's also possible event bubbling could get you out of jail
this all feels like a bit of a code smell though - perhaps you need to describe the problem in more detail
Difficult this. You cannot use event delegation to find out which control last produced a blur as focus/blur do not bubble up. There have been some attempts to 'fix' this but they are buggy and not resiliant cross browser.
Could I ask you why do you need this information as maybe there is an alternative solution.
Unfortunately, the onblur event doesn't bubble, otherwise you could have handled it at the window level to always know when an element lost focus.
As things are, I do believe it will be hard to do without, as you say, adding an onblur event handler to all elements (a truly nasty solution ;-).
It is possible to delegate the focus and blur events, if you follow PPK's advice, here:
http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
The most simple solution is to write a function that walks all forms and then all elements within the form and installs an onblur handler for each (which will probably call some global function). This handler will get an event and this event will contain the info you seek.
This way, you just have to call this method once in body.onload and it will work no matter how complex your document is.
The only drawback is that you will need to call it if you dynamically add forms to your current document. In this case, you must make sure not to install the handler again (or you will get spurious duplicate events).

Categories