The other day, I dicussed jQuery's live() event method and why understanding the mechanics behind it was extremely important; the reason being that the live() event method depends completely on the ability for a given event type to bubble up through the DOM (Document Object Model) tree. That post got me thinking about event bubbling in general and how important it is in the construction of rich user-interface interactions. Then, I started to think about all of the times that I have used click-event-handling at the Document level in order to capture the non-clicking of a given element. This made me very nervous.
As I talked about in my previous post, tracking anything at the document level requires the bubbling chain for the target event to remain in tact; this holds true for both live() and non-live() event handling. The reason that this realization made me nervous was that I often capture click events below the document level and return(false) from my click event handlers. At the click level, this is appropriate as I don't want the item being clicked to exhibit any default behavior and returning false prevents the browser's default behavior. Returning false, however, also prevents the bubbling of the given click event up through the DOM tree. As such, you can easily imagine a situation where you need to track a click event at the document level, but you leave open the opportunity for the end user to click an element that prevents that event from reaching the document.
To see this in action, take a look at the above video.
Now, I'm just one man, so I'm pretty sure I've messed this up a bunch of times. But, the people on the jQuery development team are complete badasses, so I figured they got this right. As such, I wanted to take a look at how they handled this kind of situation. The scenario that seemed to be most in alignment with what I'm talking about here was the jQuery UI Date Picker widget; the jQuery UI Date Picker widget needs to close when the user clicks on anything that is NOT the Date Picker interface.
To see how they wired this up, I installed the jQuery UI library, created a date picker, and then looked at the events bound to the document object:
$( document ).data( "events" )
As it turns out, they don't track click events at the document level at all - they track mouse down events. Ahhh, very clever! That makes perfect sense; since our UI interactions almost always track click events, it's a safe bet that a mousedown event will never be halted in its propagation path. To put this methodology to the test, I set up this small demo page:
As you can see above, the two links in the page capture click events and return(false) to override the browser's default click-event handling. But, since we are tracking mousedown events at the document level, rather than click events, we'll know when someone clicks outside of the pop-up, even if they, by chance, click on one of the links.
Very slick; the jQuery UI team definitely thought this one through quite thoroughly.
Want to use code from this post? Check out the license.