PDA

View Full Version : YUI Question : Event Delegation



INeedADip
20 Oct 2006, 4:44 PM
Just ignore this question because I know it doesn't belong in this forum, but I can't get an answer in the YUI forums.

HTML:


<div id="parent">
<div class="child">Test</div>
<div class="child">Test2</div>
</div>

Now I've got a click event handler that looks like:


YAHOO.util.Event.on('parent', 'click', clickDelegate);
function clickDelegate(e){
var origin = YAHOO.util.Event.getTarget(e, false);
if(origin && YAHOO.util.Dom.hasClass(origin, 'child'))
alert(origin.innerHTML + ' was clicked.');
}

That works great...
My question is: How do I do that for the mouseover or mousemove event?
I can't seem to get that to work. here is what I'm doing now (doesn't work):


YAHOO.util.Event.on('parent', 'mouseover', hoverDelegate);
function hoverDelegate(e){
var origin = YAHOO.util.Event.getTarget(e, false);
if(YAHOO.util.Dom.hasClass(origin, 'child'))
alert(origin.innerHTML + ' was hovered.');
}

My variable "origin" is always undefined. Hopefully you guys can see
what I'm trying to do. Any input would be appreciated.

Another YUI question: What is the difference between Event.getTarget() and Event.getRelatedTarget()?
I can't find any documentation on the difference.

INeedADip
20 Oct 2006, 5:17 PM
I got it to work...Dumb coding error. I think I've been staring at the code for too long (Time for a break).

jack.slocum
21 Oct 2006, 5:57 AM
You could make your life much easier using the EventManager.

Take for example this code:


YAHOO.util.Event.on('parent', 'click', clickDelegate);
function clickDelegate(e){
var origin = YAHOO.util.Event.getTarget(e, false);
if(origin && YAHOO.util.Dom.hasClass(origin, 'child'))
alert(origin.innerHTML + ' was clicked.');
}


If you were put say an A or an IMG in that div, the code would fail because the target would be the child element (the a or img) which wouldn't have that class.

Here's the equiv using EventManager:


YAHOO.ext.EventManager.on('parent', 'click', clickDelegate);
function clickDelegate(e){
var origin = e.findTarget('child');
if(origin)
alert(origin.innerHTML + ' was clicked.');
}


The EventManager gives a normalized event object with shorthand access to the YAHOO.util.Event stuff and also provides useful methods (such as findTarget).

The findTarget method will search the target node and it's parent nodes to correct the problem I stated above. It takes a class name, a tagName or both:



// find target with class 'child'
e.findTarget('child');

// find div target
e.findTarget(null, 'div');

// find div target with className 'child'
e.findTarget('child', 'div');


If you are using the Element object, you can subscribe to them use mon() or addManagedListener()



var div = getEl('myDiv');
div.mon('click', ...);


The 'e' variable has other methods defined directly on it such as preventDefault and stopEvent (all the YAHOO.util.Event methods), key code constants, normalized mousewheel data, and also adds a check for when e is null, something that YUI missed.

I can't live without this functionality now that I am used to it.

e comes in as:
http://www.jackslocum.com/docs/YAHOO.ext.EventObject.html

INeedADip
23 Oct 2006, 10:13 AM
Very interesting...I will try this.

Am I wrong in taking this approach on the mousemove functions? There are definately a lot more mouse move events over the container, then there are click events.

Should I loop through and attach the events to each "child" element instead of performing these calculations all the time? Have you had any bad experiences with this?

jack.slocum
23 Oct 2006, 2:08 PM
I would probably attach to mousemove events directly on the child since they could be expensive otherwise. mouseover and mouseout I generally use delegation though.