Element#delgate

Features

(Updated 8/13/2008)
View Source (commented)
Source (compressed)

Demo

<div id="frame">Element#delegate applied here</div>
<div id="content">Content Element</div>

<p class="even">click delegate registered to ".even"</p>

<p class="odd">click delegate registered to "#content .odd"</p>

<p class="even steven">click delegate registered to ".even" and "body #frame div .steven"</p>

// JavaScript on page:
var myrules = {
  '.even': function() { alert('fired ".even" callback') },
  '#content .odd': function() { alert('fired "#frame.odd" callback') },
  'body #frame div .steven': function() { alert('fired "body #frame div .steven" callback') }
};
// delegate clicks within #frame according to rules
$('frame').delegate('click', myrules);

Example Usage

// Element#delegate:
// fire callbacks for all rules that match any #frame child element when clicked
$('frame').delegate('click', myrules);
// fire countWords when any textarea inside #myform is blurred
$('myform').delegate('blur', 'textarea', countWords);
// fire validateDate when a key is pressed from within inputs with class date
document.delegate('keydown', 'input.date', validateDate);

// Element#stopDelegating:
// remove all rules in myrules attached to #frame
$('frame').stopDelegating('click', myrules);
// remove .even rule attached to #frame
$('frame').stopDelegating('click', '.even');
// remove all blur rules attached to myform
$('myform').stopDelegating('blur');
// remove all rules attached to any element
Event.stopDelegating();

How it works

If you don't need the ability to remove delegated observers, delegation looks like the following:

Element.addMethods({
  delegate: function(element, selector, eventName, observer) {
    // observe parent container
    return $(element).observe(eventName, function(event) {
      // check if target element (e.g. element that was clicked or moused over)
      //   matches given selector
      if ($$(selector).indexOf(event.target) > -1) {
        // if it matches, fire the observer (in the scope of the target element)
        return observer.apply(event.target, $A(arguments));
      }
    });
  }
});

$('frame').delegate('#frame p.even', 'click', function() {
 alert('delegated!');
});