jQuery + custom events = ‘polymorphism’ for the DOM

Writing Javascript event handlers for clicking, hovering, focusing etc is basic stuff, and jQuery makes it absurdly easy with .bind() and .live().

One thing these two also support, which I never paid much attention to, are custom events. I recently needed an elegant solution for quite a complex DOM manipulation. That’s when custom events popped into my mind and - voila - turned out to be awesome stuff.

Say you need multiple DOM elements react to an event. In my case, I need several forms on a page “collapse” when a certain link is clicked. In some simple case, just put everything in the click event handler:

$('#collapse_link').click(function() {
    $('form').find('.secondary_field').hide();
    $('form').addClass('collapsed');
    // ...
});

The mess begins when there are different forms on the page and all need to react differently to this event. Sure, you can keep putting more and more stuff into the click event handler, but at a certain point you just need a cleaner solution.

Custom events as polymorphic behaviors

In the spirit of OOP, we can have the elements themselves know how to behave in certain situations. This will feel much like defining methods on DOM elements.

Let’s start with defining the markup to easily identify the elements.

<form id="new_post" class="collapsible">
    <input type="text" name="content" />
    <input type="text" name="tags" class="secondary_field" />
</form>

<!-- ... -->

<form id="new_post_34_comment" class="new_comment collapsible">
  <!-- ... -->
</form>

<!-- ... -->

<form id="new_post_63_comment" class="new_comment collapsible">
  <!-- ... -->
</form>

We have a single post form, #new_post and multiple comment forms, .new_comment. All forms on the page share the class collapsible. Think of it as the OOP concept of a base class.

Now we know that the post form needs one behavior and the comment forms need another. Let’s name our event collapse and properly bind handlers to our elements:

$('#new_post').bind('collapse', function() {
  // One behavior for the post form
  $(this).find('.secondary_field').hide();
  $(this).addClass('collapsed');
});

$('.new_comment').bind('collapse', function() {
  // Another behavior for comment forms
  $(this).hide();
});

You probably see where we’re going. We have a collection of separate, different elements on a page. All belong to a certain class - collapsible - and all know how to react to a certain event - collapse. Sounds familiar?

All we need now is to .trigger() the event. We’ve conveniently classifed all the forms as collapsible, so the final click event handler is just pure beauty:

$('#collapse_link').click(function() {
  $('.collapsible').trigger('collapse');
});

What happens is exactly what we expect. The collapse event is triggered on all collapsible elements, and all behave in the proper manner - calling the appropriate handler bound earlier.

Pure polymorphic win.

posted 1 year ago and tagged as javascript jquery