February 02, 2011

prototype-delegation: An event delegation framework for Prototype

Update: As Tobie mentioned in the comments there actually already exists an event delegation functionality in Prototype since version 1.7 RC 1. Have a look here for the documentation about it: http://api.prototypejs.org/dom/Element/prototype/on/

While jQuery implemented event delegation with release 1.4.2 Prototype is still lacks this feature. There are numerous workarounds for this around the web. But none of those really satisfied my needs. For a project I am currently working on we are using Prototype and were in need of event delegation for our frontend. That's why I took some time to write my own event delegation framework.

The result is prototype-delegation. Since it is a very young project I highly appreciate any feedback there.
You can find it on github.

Usage

Usage is very similar if not identical to jQuery's delegation functions.

The framework extends the Element prototype by two new methods:
delegate(selector, eventName, handler)
undelegate(selector, eventName)
delegate creates a new delegate whereas undelegate removes already installed delegations.

The expected parameters are:
  • selector is a Prototype CSS selector that identifies the element to delegate the events to
  • eventName is the name of the event you want to aggregate and delegate
  • handler is a function that gets called when the event gets delegated


Example

Now let's have a look at a short example how such an event delegation will look like with prototype-delegation:
$('myTable').delegate('tr', 'click', function () {
    alert('You clicked on: ' + this.identify());
    $('myTable').undelegate('tr', 'click');
});
In this example a table with the id 'myTable' is used as the event aggregator. It will delegate all events that match the selector "tr" - that will be every row in the table. Now everytime the user clicks into the table and that click landed on a table row element, the given callback function will get called in the context of the row element.

Inside this function we can reference the table row with the this keyword. In the example we call identify() on it which will give us the id of the row the user clicked on.

After the alert() we undelegate the click event on the tr element again which causes that we can trigger this event only once here.

That's all this framework does. There is nothing more to explain. But it still is a very powerful feature that can reduce the number of events you bind in your frontend drastically.

Links

4 comments:

  1. Am I missing something here? What's wrong with:

    var handler = $('myTable').on('click', 'tr', function (event, element) {
    alert('You clicked on: ' + element.identify());
    handler.stop():
    });


    See http://api.prototypejs.org/dom/Element/prototype/on/ for more details.

    ReplyDelete
  2. @Tobie:
    Wow! That's some hard stuff now. Destroyed my work in one comment ;-)
    On one hand it's cool to have this feature in Prototype. But on the other hand I think it is very little known about it.
    Googling for Prototype and Event delegation yields some strange snippets and hacks of people who tried to implement it or even some board or stackoverflow of people asking how it is possible.
    Even the Prototype API doc only mentions Event delegation slightly hidden in the text.

    So I think you guys should do some promotion on it. A lot of people do not know that it is possible in Prototype ;-)

    ReplyDelete
  3. @ben, Thanks a bunch. Helpful to those with Prototype JS < 1.7.

    By the way, I didn't even know 1.7 had the function until I found this blog.

    ReplyDelete
  4. @ben : Thanks a hell man, you saved me.. My Architect don't want to use 'on' [ Don't ask me why ]. I am copying this. :)

    ReplyDelete