77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<div class="intro">
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <p>The `event-outside` module adds a <a href="predefined">suite of
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith events</a> based on activity occuring <em>outside</em> the subscribed
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith elements. For example, the "clickoutside" event will fire only if a click
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith occurred on an element <em>other than</em> the Node subscribed or one of
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith its descendants.</p>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <p>The module also adds a `Y.Event.defineOutside(...)` method to <a
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith href="#defineoutside">create additional outside events</a>.</p>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <p>This module was contributed by <a
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith href="https://github.com/brettstimmerman">Brett Stimmerman</a>, inspired
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith by <a href="http://benalman.com/projects/jquery-outside-events-plugin/">Ben
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith Alman's Outside Events jQuery plugin</a>.</p>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith</div>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<h2>Not me. Those other elements</h2>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<p>It's a common UX pattern to close popups or trigger save or cancel actions when users do something in another area of a web page. This family of events makes setting up that behavior easy.</p>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith```
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smithnode.on('clickoutside', function () {
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith this.hide('fadeOut');
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith});
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smithsurvey.on('keyupoutside', heyYoureNotDoneYet);
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith// hide the overlay if the page focus moves somewhere outside the overlay's
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith// content area.
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smithoverlay.get('boundingBox').on('focusoutside', overlay.hide, overlay);
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith```
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<h2>How they work</h2>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<p>When an outside event subscription is made on an element, the actual
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smithsubscription created is a `document` level subscription for the corresponding
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke SmithDOM event. When a triggering event occurs on the page and bubbles up to the
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith`document`, its `e.target` is compared to the outside event subscriber. If the
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smithevent originated from an element outside the subscriber, the outside event
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smithsubscribers are executed.</p>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<p>An originating target is considered outside the subscriber if it is not the subscriber itself or any of the subscriber's descendants.</p>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<h2 id="predefined">`*outside`</h2>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<p>The naming convention for outside events is <code><em>&lt;event&gt;</em>outside</code>.</p>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<p>The module creates the following events by default:</p>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<style>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith#eventlist {
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith list-style: none;
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith margin: 0 0 0 1em;
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith padding: 0;
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith}
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith#eventlist ul {
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith list-style: none;
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith margin-left: 0;
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith margin-right: 2em;
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith padding: 0;
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith}
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith</style>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<ul class="yui3-g" id="eventlist">
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li class="yui3-u">
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <ul>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>mousedown</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>mouseup</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>mouseover</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>mouseout</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>mousemove</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith </ul>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith </li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li class="yui3-u">
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <ul>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>click</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>dblclick</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>keydown</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>keyup</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>keypress</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith </ul>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith </li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li class="yui3-u">
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <ul>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>focus</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>blur</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>change</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>select</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li><code><em>submit</em>outside</code></li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith </ul>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith </li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith</ul>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<h2 id="defineoutside">Create more outside events</h2>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<p>Use the module's `Y.Event.defineOutside( triggeringEvent, [alternateName] )` method to create more outside
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smithevents.</p>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith```
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith// Create a `touchstartoutside` event
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke SmithY.Event.defineOutside('touchstart');
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith// Create an outside event for another synthetic event and give it
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith// a different name.
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke SmithY.Event.defineOutside('tripleclick', 'omgletmeout');
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith// would have been tripleclickoutside
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smithgooeymess.on('omgletmeout', okYouCanGo);
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith```
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<h2>Caveats</h2>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<p>Outside events require DOM events to bubble to the `document` so the following caveats apply to their use:</p>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith<ol>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith Separate subscriptions for the triggering event added to any element
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith below the `document` will execute before the outside event.
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith </li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith If a subcriber from #1 calls `e.stopPropagation()`, the outside event
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith won't fire.
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith </li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith "outside" is determined by DOM hierarchy, not visual placement of an
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith element, so if a child element of the outside subscriber is placed
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith elsewhere on the page, clicking on that child will not trigger the
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith outside event.
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith </li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith <li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith Some DOM events do not bubble, and some (e.g. `submit` and `reset`)
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith bubble only in certain browsers. Unless a workaround synthetic event
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith such as <a href="focus.html">`event-focus`</a> is in place,
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith outside versions of these events won't fire.
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith </li>
77c61f48946d06f2e1a4339a1ea83fa6f49ed085Luke Smith</ol>