views:

136

answers:

1

I have a page with elements similar to this:

<div id='things'>
    <div class='thing'>
        <div class='activator'>
            <span>Some text</span>
        </div>
    </div>
</div>

The code is similar to this:

$('things').observe(click, function(event) {
    var e = event.element();
    if (e.match('.activator')) {
        doSomeStuffWith(e);
    } else if (e.match('.activator *')) {
        doSomeStuffWith(e.up('.activator');
    }
});

So if I click the .activator or any of its child elements I want to call a function on the .activator, I'm just wondering if there isn't some way of combining the two if-clauses. Something like if (e.match('.class, .class *') { doStuff(e.upOrSelf('activator')); }

I guess I could extend the Element with an upOrSelf method. But I would prefer not to do any non-standard customizations if possible.

A: 

See here for discussions about a more generic way to to event delegation in Prototype. Down the page there is an implementation of Event.delegate() which uses a little trick to achieve what you want. It gathers the target element and its ancestors and applies the event listener to all matching elements using Selector.matchElements.

It's a bit more complicated than this, but here is an abbreviated version (untested):

$('things').observe('click', function(event) {
    var child = event.element();
    var ancestors = [child].concat(child.ancestors());
    Selector.matchElements(ancestors, '.activator').each(function(element) {
       doSomeStuffWith(element);
    });
})
Øystein Riiser Gundersen