Grow your CSS skills. Land your dream job.

Event delegation and "sliding door" links?

  • # August 7, 2009 at 7:29 pm

    Hi all,

    Long time reader (of the main site), first time poster! Trying to find a cleaner way around the following issue.

    Suppose I have the following markup:

    Using a JS library like jQuery (I use YUI2/3 mostly but feel free to leave any responses in jQuery/mootools/etc. syntax!), I want to attach a single event listener to #demo and take advantage of event bubbling/delegation.

    The event handler inspects ids to figure out what was clicked on. This means that if you click on an EM element within the link, the event handler will never know that one of the sliding door links was clicked.

    Can anyone recommend a clean solution to this issue that preserves the single event handler/event delegation?

    The half-solution I have come up with in my code is to create a faux-event object using the parentNode when an EM is encountered, which works fine but seems a bit too hacky. Here is an example of that (YUI3 event utility syntax here):

    Code:
    var clickHandler = function(e){
    switch(e.target.get(‘id’)){
    case ‘sd1′:
    alert(‘sd1 clicked.’);
    break;
    case ‘sd2′:
    alert(‘sd2 clicked.’);
    break;
    default:
    switch(e.target.get(‘nodeName’)){
    case ‘EM':
    var oE = {
    target: e.target.get(‘parentNode’),
    };
    that.clickHandler(oE);
    break;
    default:
    return true;
    }
    }
    }; // clickHandler()

    Thanks for any responses!

    # August 17, 2009 at 6:00 pm

    I have an idea using jQuery (I don’t really know any other libraries). In the event handler, try using target.parents(‘#demo a’) to get the correct anchor if a nested element was clicked; this should work for any dom element and with an arbitrarily deep nesting. Take a look at the test page I was using:

    Code:
    < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">





    # August 19, 2009 at 3:26 pm

    Yeah that is more or less what I am doing – checking the parent node if an EM or IMG (which are the only elements that may be within my A elements) is encountered.

    I am looking for a cleaner/more elegant way to do this, but have been unable to find one for weeks (I guess this might actually be the best way).

    # August 20, 2009 at 11:46 am

    Sorry, I thought you were trying to clean up your existing method for the purpose of making it less "hard coded" so you could be more flexible with the code inside the anchor.

    It seems like you ultimately want to stop events past the anchor tags; nothing nested within the anchor would register events so that only the anchor would register the event. It’s an interesting thought, but it’s not currently possible that I know of.

    Why do you need to maintain a single event handler? Why not attach an identical handler to each ‘#demo a’ element? This isn’t hacky at all and really seems to make more sense. I’m sure you have a reason, I’m just curious as to what it is :D

    # August 20, 2009 at 7:42 pm

    The reason to use one event listener instead of several (AKA Event Delegation) is to save the user’s memory. One event listener uses a lot less resources than many, and since this is an AJAX app where content is added/removed a lot, it helps eliminate the risk of memory leaks associated with attaching a bunch of event listeners to A elements that might be removed/reintroduced into the document many times (not to mention a lot less code being written/executed).

    I have come up with a slightly cleaner method. Instead of using a whitelist of elements for whom the parent should be checked, I give any elements whose parent should be checked when they are the event target a special class like "check-parent".

    # August 20, 2009 at 9:22 pm
    Quote:
    The event handler inspects ids to figure out what was clicked on. This means that if you click on an EM element within the link, the event handler will never know that one of the sliding door links was clicked.

    Ok i just focused on the quote above… But i know jquery has a .data() function and it can be used like so

    Code:
    $(‘#demo’).find(‘a’).click(function(){
    var $this = $(this),
    data = $this.data(‘clicked’);

    if(data) $this.data(‘clicked’, false);
    else $this.data(‘clicked’, true);

    console.log($this.data(‘clicked’));
    return false;

    });

    Im not sure on the requirement on using $("#demo") as the selector but that is doing the same thing as (‘#demo a’)

    The html was the same but just cleared out the id’s on the anchors

    Note: only time the <em> being clicked on becomes an issue is if you attach a click handler event on it then you just need to go to "$(this).parent(‘a’).data(……" this being the <em>

Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.

*May or may not contain any actual "CSS" or "Tricks".