Poor man's JavaScript Behaviours(edit)

JavaScript behaviours are roughly defined as an event handler that is set once, then handled by elements that are created on the fly later on.

For example, if I have a list of links referencing images which are loaded inline, adding an removing the links from this list would not require me to re-hook the event handler.

There is a jQuery plugin called LiveQuery which can handle this for you, and does so by caching the event handler you set and hooking in to the .append(), .after(), etc, methods to reattach the cached event handler to the newly created elements.

The poor man's behaviours takes a different approach.

The technique is really very simple, and if you've been writing JavaScript you may have already made use of it in some form. It doesn't use a timer, and makes use of event bubbling.

In our example, our HTML would look like this:

<ul id="imageLinks">
  <li><a href="/images/1.jpg">Image 1</a></li>
  <li><a href="/images/2.jpg">Image 2</a></li>
  <li><a href="/images/3.jpg">Image 3</a></li>
</ul>

Clicking on a link would load the image dynamically, but for our example, we'll just log the image url.

The JavaScript event handling is set on the ul element instead of the anchor elements.

// addEvent function for IE + Firefox
var addEvent = (function () {
  return document.body.addEventListener ? function (e, ev, fn) {
    e.addEventListener(ev, fn, false);
  } : function () {
    e.attachEvent("on" + ev, fn);
  };
})();

addEvent(document.getElementById('imageLinks'), 'click', function (event) {
  // only proceed if the user click on an anchor
  var el = event.target;
  if (el.nodeName == 'A') {
    // this is our real event code - which we can read values
    // from the 'el' variable, including .href, .rel, etc. to
    // handle specific like code
    console.log(el.href);
    return false; // cancel click event
  }
});

As you can see the core of the event handling is within the if (el.nodeName == 'A') (note the casing on the nodeName must be capitalised). If you need to match a class name, you can do it here too.

Taking it Further

This can be converted to a jQuery plugin, that supports more complicated selector matches, again without any timeouts.

It's limitation over LiveQuery, is that it's restricted to a subset of elements, i.e. a group of links that match X selector within a UL.

(function ($) {
  $.fn.behaviour = function (selector, fn) {
    return this.click(function (ev) {
      var el = ev.target;
      if ($(el).is(selector)) {
        return fn.call(el);
      }
    });
  };
})(jQuery);

$(function () {
  $('#imageLinks').behaviour('a', function () {
    console.log('Clicked link: ' + this.href);
    return false;
  });
});

Here's a working demonstration of poor man's behaviours

Comments

comments powered by Disqus