<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Random notes on Ruby, Rails, the Web et al.
A blog by Łukasz Adamczak.</description><title>Rambling on Rails</title><generator>Tumblr (3.0; @czak)</generator><link>http://blog.czak.pl/</link><item><title>jQuery + custom events = 'polymorphism' for the DOM</title><description>&lt;p&gt;Writing Javascript event handlers for clicking, hovering, focusing etc is basic stuff, and &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; makes it absurdly easy with &lt;a href="http://api.jquery.com/bind/"&gt;.bind()&lt;/a&gt; and &lt;a href="http://api.jquery.com/live/"&gt;.live()&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;click&lt;/code&gt; event handler:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('#collapse_link').click(function() {
    $('form').find('.secondary_field').hide();
    $('form').addClass('collapsed');
    // ...
});
&lt;/code&gt;&lt;/pre&gt;

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

&lt;h3&gt;Custom events as polymorphic behaviors&lt;/h3&gt;

&lt;p&gt;In the spirit of &lt;a href="http://en.wikipedia.org/wiki/Object-oriented_programming"&gt;OOP&lt;/a&gt;, we can have the elements themselves &lt;strong&gt;know&lt;/strong&gt; how to behave in certain situations. This will feel much like defining methods on DOM elements.&lt;/p&gt;

&lt;p&gt;Let’s start with defining the markup to easily identify the elements.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;form id="new_post" class="collapsible"&gt;
    &lt;input type="text" name="content" /&gt;
    &lt;input type="text" name="tags" class="secondary_field" /&gt;
&lt;/form&gt;

&lt;!-- ... --&gt;

&lt;form id="new_post_34_comment" class="new_comment collapsible"&gt;
  &lt;!-- ... --&gt;
&lt;/form&gt;

&lt;!-- ... --&gt;

&lt;form id="new_post_63_comment" class="new_comment collapsible"&gt;
  &lt;!-- ... --&gt;
&lt;/form&gt;
&lt;/code&gt;&lt;/pre&gt;

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

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

&lt;pre&gt;&lt;code&gt;$('#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();
});
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;All we need now is to &lt;a href="http://api.jquery.com/trigger/"&gt;.trigger()&lt;/a&gt; the event. We’ve conveniently classifed all the forms as &lt;code&gt;collapsible&lt;/code&gt;, so the final &lt;code&gt;click&lt;/code&gt; event handler is just pure beauty:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('#collapse_link').click(function() {
  $('.collapsible').trigger('collapse');
});
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;Pure polymorphic win.&lt;/p&gt;</description><link>http://blog.czak.pl/post/405256463</link><guid>http://blog.czak.pl/post/405256463</guid><pubDate>Mon, 22 Feb 2010 22:56:00 +0100</pubDate><category>javascript</category><category>jquery</category></item></channel></rss>

