Dev Logging

printf("does this work\n");
in

Custom Events in jQuery

A reader comment on my last post brought it to my attention that support for custom events actually already exists in jQuery! I decided to take a look at their solution. You can find an example here (click on “Examples” and scroll to the bottom). It’s pretty cool, but there are a couple things I don’t like about it.

Here’s the code from their sample:

$("p").bind("myCustomEvent", function(e, myName, myValue) {
    $(this).text(myName + ", hi there!");
    $("span").stop().css("opacity", 1)
               .text("myName = " + myName)
               .fadeIn(30).fadeOut(1000);
});
$("button").click(function() {
    $("p").trigger("myCustomEvent", ["John"]);
});

You might not be totally familiar with jQuery, but the interface is pretty fluent, so I think this will be somewhat straightforward. The most important concept in jQuery is the wrapped set. You can basically pass in a string formatted like a CSS selector to grab a bunch of elements from the DOM. The first statement starts off by grabbing all the “p” elements and binding a custom element with a callback. The event is then raised on the button click in the next line. You can mostly ignore the contents of the callback function.

DISCLAIMER: The following complaints are based strictly on a quick look at this sample and a little nosing around in the jQuery source code.

Here’s what I don’t like. First, the custom event is bound directly to a set of DOM elements, and I can’t really think of any time I’d want to do this. If you’re working with custom events, they’re most likely going to be “application” events. “profileUpdated” or “commentSaved” or “itemDeleted”: those sorts of things. It doesn’t make any sense to me to tie something like this to a set of elements. One has nothing to do with the other. Why not just have a generic callback that selects all the “p” elements itself? For that matter, it seems like the usage they have here is pretty inconsistent; the event is bound directly to the “p” elements, but the callback then selects all the “span” elements. Doesn’t that mean those same operations will be carried out on every span as many times as we have p elements? If the callbacks aren’t tied to sets of elements, this problem goes away. Maybe there’s some other use case I’m not thinking of, but the whole thing seems semantically flawed. I think they probably did this to keep the API consistent with the standard DOM events, but I think they would have been better served doing something else.

My second complaint is a little bit of a guess, but the code in the sample seems to back it up. Look at how the event is raised. We’re allowed to pass in event arguments, but we have to pack them in an array ourselves. This is more of a minor complaint, but I do think it makes the API a little less nice to work with. This is kind of a shock. I think jQuery’s intuitive interface is its biggest strength; everything works pretty much exactly the way you’d expect it to. The main thing that allows this is that most functions have a lot of intuitive overloads, which is probably why they had to make this compromise. If you’re accepting an arbitrary number of arbitrary arguments, there’s really no way to tell what’s what. I can understand the compromise, but I don’t really like it.

To disclaim again, I really like jQuery, though I am a little unfamiliar with this part of the API. Just some uninformed thoughts on the subject.

Comments

Dev Logging said:

Regular readers will notice that I’m quite taken with JavaScript recently . I’ve been looking at using

# August 21, 2009 4:33 PM