jQuery outside events: Why trigger an event on something, when you can trigger it on everything else?

|

With jQuery outside events you can bind to an event that will be triggered only when a specific “originating” event occurs outside the element in question. For example, you can click outside, double-click outside, mouse-over outside, focus outside (and over ten more default “outside” events). Also, if an outside event hasn’t been provided by default, you can easily define your own.

Note that this was previously known as the “jQuery clickoutside” plugin.. but, hey—it’s pretty amazing what a an awesome idea and few more lines of code can do!

Supported “outside” events

By default, these “outside” events are supported: clickoutside, dblclickoutside, focusoutside, bluroutside, mousemoveoutside, mousedownoutside, mouseupoutside, mouseoveroutside, mouseoutoutside, keydownoutside, keypressoutside, keyupoutside, changeoutside, selectoutside, submitoutside.

Note that each “outside” event is powered by an “originating” event (see the complete list). Only when the originating event is triggered on an element outside the element to which that outside event is bound will the bound event be triggered.

A basic usage example

Let’s say you have a modal dialog. In addition to a standard “close dialog” button, you want the user to be able to click anywhere outside the dialog to close it. Instead of creating a background overlay that the user must click on, you can just use this plugin!

// Hide the modal dialog when someone clicks outside of it.
$("#modal").bind( "clickoutside", function(event){
  $(this).hide();
});

Note that you can also utilize the event.target property, which references the actual element clicked, in your event handler logic. This may be useful if you want to constrain the ‘outside-ness’ of the click to certain elements or containers.

And of course, this same approach works for all “outside” events. See the working examples for more information.

How it works

jQuery outside events are made possible by event delegation. Because events in jQuery bubble up the DOM tree, a catch-all event handler bound on document can be used to see when and where a specific event has been triggered.

When an “outside” event is bound on one or more elements, those elements are added into an internal array and an event handler for the corresponding “originating” event is bound on document. For example, when a “clickoutside” event handler is bound on some divs, the plugin binds a “click” event handler to document.

After that point, whenever an element on the page is clicked, the event will propagate up the DOM tree to document, where the document click event handler will execute. Since that handler can use event.target to know on which element the event was triggered, it can then iterate over all elements in the aforementioned internal array, triggering the custom “outside” event on all elements that aren’t equal to, or a parent of, the triggering element.

Now, whenever an event is triggered on an element, that event’s .target property refers to the element on which the event was triggered. Normally, since events bubble, a bound event handler might not be on the triggering element, but instead might be on one of its ancestor elements, so this makes sense for most events. Of course, in a situation like this, where the custom “outside” event is triggered directly on the element to which it is bound, event.target and this will be the same value inside the event handler.

Now, because the originating event is, by definition, being triggered on an element that is outside the element on which the custom “outside” event is triggered, it seems most useful to set event.target to be the element on which the originating event was triggered, which, if you remember, was available in the document-bound originating event handler.

Fortunately, the special events API in jQuery 1.4.2+ makes this very easy, and it’s just a few lines of code (see here and here) to override any event object properties for a custom event.

While this explanation might have been a little long-winded, this really is a fairly simple example of a jQuery “special event” plugin, so if you want to write one of your own, feel free to take a look at the fully commented source code.

Ok, back to usage

Well, there’s little else to say. Technical explanation on event bubbling aside, this plugin is really quite straightforward. Be sure to check out the click outside, double-click outside, mouse-over outside and focus outside working examples to see it in action, and work from there!

If you have any non-bug-related feedback or suggestions, please let me know below in the comments, and if you have any bug reports, please report them in the issues tracker, thanks!

Special thanks to Jeff Robbins for the original “clickoutside” plugin idea, and David Petersen for the “focusoutside” idea that got me thinking about converting this into a more general “outside events” plugin!

Post A Comment

  • Any of these HTML tags may be used for style: a, b, i, br, p, strong, em, pre, code.
  • Multi-line JavaScript code should be wrapped in <pre class="brush:js"></pre>
    (supported syntax highlighting brushes: js, css, php, plain, bash, ruby, html, xml)
  • Use &lt; instead of < and &gt; instead of > in the examples themselves.