Friday, November 9th, 2007

Pseudo-custom events in Prototype 1.6

Category: Articles, Examples, JavaScript, Prototype

Andrew Dupont has written a tutorial on how to normalize proprietary browser events using Prototype’s new custom events feature.

The piece is interesting as it talks about how the Prototype core team originally went down the wrong path trying to boil the ocean with great features that were a bit too much. And then:

we refocused, trimmed the fat, and added a whole bunch of features to the event system while still excluding thie kitchen sink. We picked some low-hanging fruit; for instance, we normalized the event object so that properties like target exist in all browsers, and we ensured events fire in the scope of the element in IE (so that this refers to the proper thing).

But we also added cross-browser support for custom events. Now developers can fire their own events alongside native browser events and can listen for both types with the same API. Custom events will make Prototype add-ons at least 50% more righteous, allowing for even more control than the standard callback pattern. Imagine TableKit firing an event when a cell gets edited, or PWC firing an event when a dialog is resized.

Since the 1.6 RC1 release, several people have asked whether we have any plans to add native support for mouseenter, mouseleave, or mousewheel. I think we ought not, lest the event codebase become an unholy thicket of special-casing. That’s the sort of environment where bugs thrive.

But, as Sam points out, the addition of custom events makes it easy for third parties to add their own support for proprietary browser events. To demonstrate, today we’ll write 20 lines of code to add sane, cross-browser support for mouse wheel events.

I’m calling these pseudo-custom events because they serve the same purpose as standard browser events: they report on certain occurrences in the UI. Here we’re using custom events to act as uniform façades to inconsistently-implemented events. Together we’ll write some code to generate mouse:wheel events. At the end of this article, you’ll know enough to be able to write code to generate mouse:enter and mouse:leave events document-wide.

This leads you into the example itself which takes you through a number of iterations before ending up with:


  1. (function() {
  2.   function wheel(event) {
  3.     var realDelta;
  5.     // normalize the delta
  6.     if (event.wheelDelta) // IE & Opera
  7.       realDelta = event.wheelDelta / 120;
  8.     else if (event.detail) // W3C
  9.       realDelta = -event.detail / 3;
  11.     if (!realDelta) return;
  13.     var customEvent = event.element().fire("mouse:wheel", {
  14.      delta: realDelta });
  15.     if (customEvent.stopped) event.stop();
  16.   }
  18.  document.observe("mousewheel",     wheel);
  19.  document.observe("DOMMouseScroll", wheel);
  20. })();

Posted by Dion Almaer at 11:35 am

4 rating from 48 votes


Comments feed TrackBack URI

Funny they come up with this…
What they should have done though, is to make sure prototypes fires and catches all dom level 2 events (because the generation of browsers we are currently using do not). This would make the development of ajax applications a lot easier and clearer.

They should also allow developers to add event handlers on nodes that are not yet added to the dom (living in the response of an XHR call for instance).

Comment by Sjoerd Adema — November 11, 2007

How does this compare to MooTools’ custom events?

I’m planning on writing an article exploring MooTools custom events and I will make sure to compare it to Prototype as well.

Incidentally, I just wrote an article on the MooTools ‘mouseenter’ and ‘mouseleave’ events, if anyone is interested:

Comment by jdempcy — May 16, 2008

Leave a comment

You must be logged in to post a comment.