Get updates

Scott JavaScript Event Delegation

Coding interactive behavior into “dumb” HTML elements is one of the basic scenarios for JavaScript use. The standard method is usually to hunt through the DOM looking for elements of a certain id or class and attach an event handler function directly to each one.

For most types of events, there’s a better way: Event Delegation. At the basic level it involves attaching an event delegation function to a parent element, then catching events which bubble up and passing them off to specific handlers based on the event’s target.

Before Event Delegation

Previously, I was perfectly happy attaching events to individual elements. Indeed, it still makes sense on a unique basis; if there’s a single “Log out” link that you’re enhancing with JavaScript the click event handler should probably be attached to the link (not inline but within the “onLoad” or similar thread, of course).

Then at work I started building a UI widget with jQuery (sorry Prototype, it was already there when I joined the project; I still have a fondness for Prototype- and Ruby/Rails-style code which I’m sure I’ll pick up again when I have time to return to my own project). I needed this widget to allow inserting and deleting elements on the fly, and inserted elements to have event handlers for additional behavior.

“Hmm, I guess I can add event handlers each time I add elements. Though wouldn’t it be better if they just inherited these behaviors?”

Event Bubbling Makes Possible Event Delegation

Inheritance is one way of looking at it, but I’ll explain event bubbling before getting lost in the metaphor.

Event bubbling is the name given to the way events trigger handlers on the target element and the element’s parent, and its parent’s parent, and so on, hence “bubbling up”. At any level of an element’s ancestry the event can be examined, and by checking out the event.target property (for most browsers, IE has to be different of course) the initial or “target” element can be discerned.

Example time. Say we have some markup that looks like this:
<ul id="toDoList">
 <li><input type="checkbox" /> Watch Dark City again<li>
 <li><input type="checkbox" /> Beat System Shock (the original)<li>
 <li><input type="checkbox" /> Read Dawkins<li>
</ul>

Fast forward to the end of the month when I’ll have finished The God Delusion and click to check off the third item in the list.

What happens is that the input element receives the click event first. After any click handlers attached there are fired, the event bubbles up to the parent element – in this case it’s the li containing the “Read Dawkins” text, and click handlers on that element get fired. Next the event continues moving up the ranks to the ul element (id=”toDoList”) and again any click handlers attached there are fired. Beginning to see how event delegation comes into play?

jQuery and Event Handlers

jQuery is a pretty good library which makes binding event handlers easy, even binding a handler function to multiple elements at once. We might add a handler to each checkbox like this:
function clickHandler(event)
{
  //take action
}
$('#toDoList :checkbox').click(clickHandler);

However, what if we want to add more list items, say in response to the user typing in a text field and pressing enter? We’d have to add event handlers to each new checkbox, and can’t just reuse the line above as that would result in existing checkboxes getting multiple bindings of our clickHandler function.

How about this instead:
function listClickDelegator(event)
{
  if (event.target.tagName.toLowerCase() == 'input' && event.target.getAttribute('type').toLowerCase() == 'checkbox')
  {
    checkboxClickHandler(event);
  }
}
function checkboxClickHandler(event)
{
  //take action
}
$('#toDoList').click(listClickDelegator);

Here we’ve attached a single handler to the root of our unordered list that can catch any click event originating on itself or any of its descendants. When an event is received it checks the target to make sure it is a checkbox, then fires checkboxClickHandler.

Benefits of Event Delegation

I’ll quickly summarize a few of the benefits you can reasonably expect by employing event delegation in your JavaScript:

  • Fewer handlers to attach: No need to identify individual elements and bind handlers to each of them. Saves memory too.
  • Automatically cover new elements: Newly added DOM elements will bubble their events up and be handled the same as existing elements, without any extra effort.
  • Greater flexibility: If we want to operate on clicks to li elements we just need to add an else if into the listClickDelegator, and code our liClickHandler function. The rest of the plumbing is already in place.
  • Easy to maintain: All of our event binding and triggers happen in one place, and likely use less code than the traditional method for anything more than the basic examples I’ve included here.

Event Delegation Pitfalls

A few things to be aware of before you leap to make use of this pattern:

  • Browser compatibility: Not all browsers populate event.target (IE I’m looking at you), without that information it’s difficult to know how to delegate an event. For IE event.srcElement is the way to go. If you’re using a nice library like jQuery this quirk has already been normalized for you, continue using event.target.
  • Not all events bubble: Focus and blur events don’t make it up the tree, so if you want to handle those events you’ll need to bind handlers directly to the desired elements (there are some efforts to ease the pain)

Further Reading on JavaScript Event Delegation

  • Dan Webb takes things one step further with jQuery by showing off a little $.delegate() sugar.
  • Learning jQuery talks about event delegation with examples in Working with Events.
  • If you’re not into jQuery and other JavaScript framework libraries, or you’re “just trying to cut down”, check out the low-fat version of event delegation at Usable Type.
  • Opera’s Seven Rules of Unobtrusive JavaScript picks up event delegation and some more of its benefits at #5.

11 Responses to “JavaScript Event Delegation”

  1. […] Event delegation is a powerful technique that should be used as often as possible and we can achieve it by assigning an outer element an event handler and using the target attribute on the event to determine what should be done: […]

  2. The Simpsons Tapped Out Cheats

    JavaScript Event Delegation – Development – 3DM Design

  3. Fcis.aisdhaka.org

    JavaScript Event Delegation – Development – 3DM Design

  4. dev.meclub.com

    JavaScript Event Delegation – Development – 3DM Design

  5. Support.earls.ca

    JavaScript Event Delegation – Development – 3DM Design

  6. one-time offer

    JavaScript Event Delegation – Development – 3DM Design

  7. Treetops.Vi

    JavaScript Event Delegation – Development – 3DM Design

  8. support.frevvo.Com

    JavaScript Event Delegation – Development – 3DM Design

  9. Support.tellink.com

    JavaScript Event Delegation – Development – 3DM Design

  10. Wanda Strickfaden’s music

    JavaScript Event Delegation – Development – 3DM Design

  11. wodpress training

    JavaScript Event Delegation – Development – 3DM Design

Leave a Reply


Fatal error: Uncaught Error: Call to undefined function show_subscription_checkbox() in /home/dmetro/3dmdesign.com/wp-content/themes/hex_columns/comments.php:90 Stack trace: #0 /home/dmetro/3dmdesign.com/wp-includes/comment-template.php(1471): require() #1 /home/dmetro/3dmdesign.com/wp-content/themes/hex_columns/single.php(65): comments_template() #2 /home/dmetro/3dmdesign.com/wp-includes/template-loader.php(74): include('/home/dmetro/3d...') #3 /home/dmetro/3dmdesign.com/wp-blog-header.php(19): require_once('/home/dmetro/3d...') #4 /home/dmetro/3dmdesign.com/index.php(17): require('/home/dmetro/3d...') #5 {main} thrown in /home/dmetro/3dmdesign.com/wp-content/themes/hex_columns/comments.php on line 90