8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<style scoped>
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff #demo {
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff position: relative;
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith #homebase {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith margin-left: 100px;
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff position: absolute;
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff left: 0;
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff top: 40px;
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff height: 150px;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith width: 200px;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith .robot {
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff height: 210px;
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff width: 180px;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith position: absolute;
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff top: 0px;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith left: 0;
af2a34339f1f67253636b38975ef84b03a553264Jeff Conniff outline-style: none;
b137e0059e04e5168cb5a731ee7b05e06ab89bb2Jeff Conniff opacity: 0.5;
b137e0059e04e5168cb5a731ee7b05e06ab89bb2Jeff Conniff filter: alpha(opacity=50);
b137e0059e04e5168cb5a731ee7b05e06ab89bb2Jeff Conniff }
b137e0059e04e5168cb5a731ee7b05e06ab89bb2Jeff Conniff .yui3-focused {
b137e0059e04e5168cb5a731ee7b05e06ab89bb2Jeff Conniff opacity: 1;
5cbb7446637c48aa8b871d518f0becf24b6bd94bDav Glass z-index: 1;
b137e0059e04e5168cb5a731ee7b05e06ab89bb2Jeff Conniff filter: alpha(opacity=100);
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith #B {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith left: 125px;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith #demo input {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith margin-left: 4em;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith #demo label {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith font-size: 87%;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith color: #555;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff #detach {
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff margin-top: 150px;
ef72940b6b98893cd35e5e70b9f233c07d5209cfJeff Conniff }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</style>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<div class="intro">
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith <p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith This example will illustrate how to use the synthetic event creation
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith API. We'll create an `arrow` event that fires in response
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith to the user pressing the arrow keys (up, down, left, right) and adds a
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith `direction` property to the generated event.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith </p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith <p>Subscribing to this new event will look like this:</p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith ```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith node.on("arrow", onArrowHandler);
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith ```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith <p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith Support will also be added for delegation, allowing a single subscriber
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith from a node higher up the DOM tree, to listen for the new event
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith emanating from its descendant elements.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith </p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith ```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith containerNode.delegate("arrow", onArrowHandler, ".robot");
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith ```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</div>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
819e90d415ed17d59af3a247b2ad9d6feb0c21b5Luke Smith<div class="example yui3-skin-sam">
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith {{>synth-example-source}}
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</div>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<h2>`on`, `fire`, and `detach`</h2>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith The three interesting moments in the lifecycle of a DOM event subscription
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith are
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<ol>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith <li>The event is subscribed to</li>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith <li>The event is fired</li>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith <li>The event is unsubscribed from</li>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</ol>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith Create a new synthetic DOM event with `Y.Event.define( <em>name</em>,
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith <em>config</em> )`. Define the implementation logic for the
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith `on` and `detach` moments in the configuration.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith Typically the condition triggering the event firing is set up in the
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith `on` phase.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke SmithY.Event.define("arrow", {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith on: function (node, sub, notifier) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // what happens when a subscription is made
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // if (condition) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith notifier.fire(); // subscribers executed
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith },
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith detach: function (node, sub, notifier) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // what happens when a subscription is removed
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith});
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith In the case of arrow handling, the trigger is simply a key event with a
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith `keyCode` between 37 and 40. There are a few browser quirks with arrow
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith handling that warrant listening to `keydown` for some browsers and
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith `keypress` for others, so we'll take care of that transparently for `arrow`
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith subscribers.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith```
8c17117005b705713c4b9310868677a71b236783Luke SmithY.Event.define("arrow", {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith on: function (node, sub, notifier) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith var directions = {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith 37: 'left',
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith 38: 'up',
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith 39: 'right',
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith 40: 'down'
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith };
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Webkit and IE repeat keydown when you hold down arrow keys.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Opera links keypress to page scroll; others keydown.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Firefox prevents page scroll via preventDefault() on either
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // keydown or keypress.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Bummer to sniff, but can't test the repeating behavior, and a
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // feature test for the scrolling would more than double the code size.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith var eventName = (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress';
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // To make detaching the associated DOM event easy, store the detach
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // handle from the DOM subscription on the synthethic subscription
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // object.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith sub._detacher = node.on(eventName, function (e) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Only notify subscribers if one of the arrow keys was pressed
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith if (directions[e.keyCode]) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Add the extra property
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith e.direction = directions[e.keyCode];
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Firing the notifier event executes the arrow subscribers
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Pass along the key event, which will be renamed "arrow"
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith notifier.fire(e);
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith });
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith },
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith detach: function (node, sub, notifier) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Detach the key event subscription using the stored detach handle
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith sub._detacher.detach();
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith} );
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<h2>Add Delegation Support</h2>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith Since the `arrow` event is simply a filtered `keydown` or `keypress` event,
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith no special handling needs to be done for delegate subscriptions. We will
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith extract the key event handler and use it for both `on("arrow", ...)` and
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith `delegate("arrow", ...)` subscriptions.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke SmithY.Event.define("arrow", {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Webkit and IE repeat keydown when you hold down arrow keys.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Opera links keypress to page scroll; others keydown.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Firefox prevents page scroll via preventDefault() on either
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // keydown or keypress.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress',
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith _keys: {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith '37': 'left',
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith '38': 'up',
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith '39': 'right',
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith '40': 'down'
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith },
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith _keyHandler: function (e, notifier) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith if (this._keys[e.keyCode]) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith e.direction = this._keys[e.keyCode];
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith notifier.fire(e);
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith },
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith on: function (node, sub, notifier) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Use the extended subscription signature to set the 'this' object
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // in the callback and pass the notifier as a second parameter to
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // _keyHandler
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith sub._detacher = node.on(this._event, this._keyHandler,
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith this, notifier);
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith },
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith detach: function (node, sub, notifier) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith sub._detacher.detach();
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith },
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Note the delegate handler receives a fourth parameter, the filter
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // passed (e.g.) container.delegate('click', callback, '.HERE');
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // The filter could be either a string or a function.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith delegate: function (node, sub, notifier, filter) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith sub._delegateDetacher = node.delegate(this._event, this._keyHandler,
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith filter, this, notifier);
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith },
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // Delegate uses a separate detach function to facilitate undoing more
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // complex wiring created in the delegate logic above. Not needed here.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith detachDelegate: function (node, sub, notifier) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith sub._delegateDetacher.detach();
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith});
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<h2>Use it</h2>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith Subscribe to the new event or detach the event as you would any other DOM
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith event.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smithfunction move(e) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // to prevent page scrolling
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith e.preventDefault();
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith // See full code listing to show the data set up
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith var xy = this.getData();
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith switch (e.direction) {
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith case 'up': xy.y -= 10; break;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith case 'down': xy.y += 10; break;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith case 'left': xy.x -= 10; break;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith case 'right': xy.x += 10; break;
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith }
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith this.transition({
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith top : (xy.y + 'px'),
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith left: (xy.x + 'px'),
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith duration: .2
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith });
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith}
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith// Subscribe using node.on("arrow", ...);
8966f18bc05afef70f40b84ee4179f0df30e219dLuke SmithY.one("#A").on("arrow", move),
8966f18bc05afef70f40b84ee4179f0df30e219dLuke SmithY.one("#B").on("arrow", move)
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith// OR using container.delegate("arrow", ...);
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smithsubs = Y.one('#demo').delegate('arrow', move, '.robot');
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<h2>Bonus Step: to the Gallery!</h2>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith Synthetic events are perfect candidates for Gallery modules. There are a
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith number already hosted there, and there are plenty of UI interaction
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith patterns that would benefit from being encapsulated in synthetic
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith events.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith The `arrow` event in this example is also
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith <a href="http://yuilibrary.com/gallery/show/event-arrow">in the gallery</a>,
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith but with additional functionality. Check out
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith <a href="https://github.com/lsmith/yui3-gallery/blob/master/build/gallery-event-arrow/gallery-event-arrow-debug.js">its source</a>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith to see what you can do with synthetic events.
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith</p>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith<h2>Full Code Listing</h2>
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith{{>synth-example-source}}
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith```
8966f18bc05afef70f40b84ee4179f0df30e219dLuke Smith