Event Delegation With Mootools--Quit Selecting All Those Elements!

By Ryan Florence, published 2010-01-16

Part of the issue Migrated Articles From Original Site Structure..

Event delegation rules the school. Instead of adding events to 300 elements you just add an event to the parent element and it’ll delegate the event down to it’s children, like every good parent would. The benefits? 1) Efficiency, 2) “Set it and forget it”, 3) Makes attaching and detaching events in a class easier, 4) Makes you look cool, and that after all, is the point of being a web developer instead of a surfing instructor.

Say you’ve got this list:

<ul id="my_list">
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
  <li>Event Delegation Rules</li>
</ul>

Sorry about that just making a point here. To add an event to every element you might do:

var fn = function(){
  console.log(this.get('text'));
};

$$('#my_list > li').each(function(item, index){
  item.addEvent('click', fn.bind(item));
});

Problems

  1. That’s a lot of work for the browser to keep track of.
  2. If we wanted to remove that event from all the items we’d have to iterate over the whole list again.
  3. If we dynamically add/remove elements to/from the list via xhr or javascript we have to add the events on the fly to those elements. Or, what I usually see in people’s code, just re-attach the events to every element in the list again (without detaching it first so the originals have the event twice!)
  4. Binding the right stuff in a class gets tricky when working with multiple elements.

I’m sure you could do a search of the mootools mailing list to see people trying to goof around with evalscripts: true in their xhr Requests in an attempt to add events to the requested elements and find several threads.

What a pain …

Element.Delegation to the rescue

With event delegation we could instead do this:

var fn = function(event, target){
  console.log(target); // li
};

$('my_list').addEvent('click:relay(li)', fn);

The syntax is pretty clear. When my_list is clicked, it’ll relay the event to the matching selector–in this case li. “Oh no you dinnut click me, you clicked him!” You can see from the snippet that the function’s signature gives you access to the event as the first argument and the element that was clicked as the second (well, the element that the event was relayed to anyway.)

Benefits of Event Delegation

  1. If you dynamically add/remove elements from the parent element with xhr or javascript, it requires nothing on your part for them to behave like their siblings (“Why can’t you be more like your sister?!”)
  2. If we need to remove the event we only have to remove it from one element.
  3. It’s not very much work to keep track of one event

Attach and Detach methods in a class

A unique benefit that deserves it’s own header is that Element.Delegate makes writing the attach and detach methods in a class much easier when you’ve got multiple elements. It seems I frequently write classes that have this.elements and I run into problems trying to bind a method, and then add it as the function for an event to this.elements, and then being able to remove the event from all of the elements. It gets a bit screwey. But with event delegation I simply add the event to the parent element and my binding becomes quite simple.

I should probably go into more detail about the problem I just whimsically described, but what’s the point of being exhuastive on an obsolete issue when the solution is so …

… Beautiful.

Shell Source

var DelegatesDemo = new Class({

    Implements: Options,
   
        options: {
            typeSelector: 'click:relay(li)',
            delegator: 'parent',
            log: 'log'
        },

    initialize: function(options){
        this.setOptions(options);
        this.delegator = document.id(this.options.delegator);
        this.log = document.id(this.options.log);
        this.bound = this.logDelegateeText.bind(this);
        this.attach();       
    },

    attach: function(){
        this.delegator.addEvent(this.options.typeSelector, this.bound);
        return this;
    },

    detach: function(){
        this.delegator.removeEvent(this.options.typeSelector, this.bound);
    },

    logDelegateeText: function(event, element){
        var text = element.get('text');
        this.log.set('text', text);
    }

});

Special thanks

A couple other developers gave me a few tips about all this:

MooTools in this article

Hi, I'm Ryan!

Location:
South Jordan, UT
Github:
rpflorence
Twitter:
ryanflorence
Freenode:
rpflo

About Me

I'm a front-end web developer from Salt Lake City, Utah and have been creating websites since the early 90's. I like making awesome user experiences and leaving behind maintainable code. I'm active in the JavaScript community writing plugins, contributing to popular JavaScript libraries, speaking at conferences & meet-ups, and writing about it on the web. I work as the JavaScript guy at Instructure.