Yelotofu

Yelotofu ~ “In building standards compliant sites we are creating a better Web for the future.”

JavaScript: Event Delegation

Recently, I've been hearing much about event delegation. Many new to this concept seem to be baffled by the term. However, it really is a simple idea when you realise what's involved.

Put simply, event delegation is the practice of directing events on parent DOM elements who then listen on their children for events.

To understand event delegation and why it works you should read this ppk article before continuing — JavaScript Event Order.

Back? OK, so now you know about event capturing and bubbling the concept is easier to comprehend.

Event delegation takes advantage of the fact that actions performed on a child element always bubbles up to the top. Traditionally events are handled on the element that fired it, for example (excuse my jQuery) :

$('button').click(function(e) {
  alert('You clicked on me?');
});

Now rather than handling the click event shown above on the element itself we could delegate it to a parent because we know all events eventually bubble to the top, so

$('html').click(function(e) {
  if ( $(e.target).is('button') )
    alert('You clicked on me?');
});

produces the same result as the first code snippet.

Did you notice e.target? This is the essence of event delegation. As the event bubbles it keeps a mental note of its starting position in its pocket; e.target is a reference to the first element the event started bubbling from. In the above code sample that would be button.

That's event delegation in a nutshell!

Now, you might be asking - why should I use this rather than traditional one-to-one event handling?

Here are a few reasons:

  • In event delegation you bind one event handler to handle events on multiple elements. In traditional event handling you have to create a thousand event handlers to handle a thousand events. As you would expect event delegation is less resource expensive and could result in quicker response times
  • If Ajax or DOM manipulation happens, re-binding event handlers usually follow. Event delegation avoids re-binding by listening to a parent you know won't be manipulated, i.e. html, body or the website container.
  • Event delegation makes for cleaner code if you have a large webapp demanding lots of event handling.
  • No need to worry about event order and bubbling issues as we're now taking advantage of this effect

In conclusion. Event delegation is not a replacement for Event handling - both have their uses depending on situation. Event delegation requires more planning and could be harder to debug due to the inherent abstractions. You just can't beat the humble event handler if all you want is a link opening in a new browser window. That said, you'd be mad not to use it if you have a complex app with thousands of event objects doing various operations from submitting a form to loading Ajax content.

Further reading:

jQuery UI Spinner

After contributing jQuery Numeric Stepper to the jQuery UI community. Paul Bakaus kindly asked whether I'd like to merge it with the official jQuery UI Spinner, of which I was more than happy to do out of pure love for jQuery.

The jQuery UI Spinner widget will be available with the soon to be released jQuery UI v1.6.

Here's a demo of the current incarnation.

Also, check out Subversion if you're interested in getting the latest and greatest.

Update: this spin control is currently in re-design phase and will come under intense refactoring to be leaner and meaner. So the UI team have decided to push back its release to v1.next, which means it will not be part of the final 1.6 release. Sorry guys!

Update2: I've posted an update on this here.

jQuery: outerHTML

The outerHTML property (IE only) could sometimes be very handy, especially if you're trying to replace an element entirely. Brandon Aaron has very kindly given us a outerHTML plugin that does half the job as it doesn't support replacements. The following code snippet fills in the blanks:

jQuery.fn.outerHTML = function(s) {
return (s)
? this.before(s).remove()
: jQuery("<p>").append(this.eq(0).clone()).html();
}

To get the outerHTML value of an element do this...

$('#myTag').outerHTML();

To replace #myTag entirely do this...

$('#myTag').outerHTML("<p>My brand new #myTag.</p>");

Hope this helps someone :)

Update: There's now a demo page.

jQuery Numeric Stepper

As an experiement I ported over my Accessible Numeric Stepper into a jQuery widget and added some accessibility enhancements and new features in the process.

This widget utilises ui.core.js - a factory method object for creating widget classes. Widgets in jQuery are essentially plugins at heart but built to follow stricter coding standards in order to unify the underlying quality between developers. It also adds convenient mouse interaction classes and option settings among other things.

The result is jQuery Numeric Stepper an unofficial jQuery UI widget. Features include:

  • min, max, start and step size settings
  • supports decimal values and decimal step sizes
  • supports currency values
  • keyboard and mousewheel interaction - increment/decrement values via cursor keys, +/- keys and mousewheel

Download latest source code here

Bugs? Missing feature? Code improvements? Let me know!

Update: Features seen here are now part of the official jQuery UI Spinner, set for the 1.6 release of jQuery UI. More details.

Loving jQuery

In recent weeks I have come to love jQuery. jQuery is this lightweight, elegant and so-much-fun-to-code-with JavaScript library. You may already have it in your source code if you're using either the latest version of WordPress or Drupal.

jQuery is so easy to get to grips with, the documentation is simple to follow and complete with loads of code samples.

jQuery's elegance comes in the form of its ability to select DOM nodes through CSS-like syntax (i.e., CSS queries) in a compact way—brilliant for those who are already very familiar with CSS!

Most or even all actions start with a CSS query, which in a sense promotes the use of unobtrusive JavaScript as it's simply easier to use the $() syntax than add a function directly into HTML.

jQuery is also very much down to earth in a practical way providing a few neat toggle functions:

  • toggle — show/hide selected elements
  • slideToggle — show/hide selected elements with slide Up/Down effects
  • toggleClass — add/remove a class from selected elements

There are also some handy plugins such as the Flash plugin and the ifixpng plugin, which fixes PNG transparency for img elements and CSS backgrounds in IE.5 and IE6.

If something isn't built-in, extending jQuery is ridiculously easy via custom plugins. Here's one way you could define a custom plugin:

 
jQuery.fn.myPlugin = function() {
    // Your plugin code goes in here
}

To take advantage of jQuery's chainability you need only add a single line returning the current context object—this:

 
jQuery.fn.myPlugin = function() {
    // Your plugin code goes in here
    return this;
}

To demonstrate how easy jQuery is to extend I created a simple one line plugin to toggle fadeIn and fadeOut effects, see below.

jQuery fadeToggle plugin:

jQuery.fn.fadeToggle = function(s, fn){
    return (this.is(":visible"))
        ? this.fadeOut(s, fn)
        : this.fadeIn(s, fn);
};

Example usage:

jQuery(function($){
    $(".toggler").click(function(){
        $(".content").fadeToggle();
    });
});

A demo of jQuery fadeToggle plugin in action

Next Entries »