ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith<link type="text/css" rel="stylesheet" href="{{yuiBuildUrl}}/cssbutton/cssbutton-min.css">
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith<div class="intro">
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith <p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith The YUI Custom Event System enables you to define and use events beyond
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith those available in the DOM &mdash; events that are specific to and of
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith interest in your own application. Custom Events are designed to work
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith much like DOM events. They can bubble, pass event facades, have their
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith propagation and default behaviors suppressed, etc.
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith </p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith <p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith The APIs for working with custom events are provided by the
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith `EventTarget` class. All other infrastructure classes extend
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith `EventTarget`, but if you just need the custom event APIs, you can
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith `extend` or `augment` your classes with `EventTarget` directly.
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith </p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <!--p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith Bundled with `EventTarget` are <a
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith href="http://en.wikipedia.org/wiki/Aspect_oriented_programming">Aspect
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Oriented Programming</a> methods that allow you to subscribe to the
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith execution of object methods, and
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith their own.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </p-->
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith</div>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<!-- insert Events Evolved video here -->
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith{{>getting-started}}
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith<h2>Video Overview</h2>
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith<iframe width="640" height="360" src="http://www.youtube.com/embed/s_7VjN3qxe8" frameborder="0" allowfullscreen></iframe>
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith<p>
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith This video from YUIConf 2009 gives a good overview of the YUI event system
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith API. The content covers DOM and custom events. Note: the <a
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith href="../event/index.html#synthetic-events">synthetic event</a> system was
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith updated since this video.
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith</p>
c967f42c8ecf9b590ab1a9fca4f5d5d905fc1dedLuke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h2>The Basics</h2>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith You can get started using custom events and the `EventTarget` API without
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith creating your own class. The YUI instance (typically `Y`) is an
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `EventTarget`, as is pretty much every other class in YUI. We'll go over
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith the basics using `Y`, then move into creating your own `EventTarget`s.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith If you've looked over the <a href="../event/index.html#the-basics">DOM
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Event system docs</a>, this should look very familiar. That's because
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `Node`s are also `EventTarget`s.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3>Subscribing to Events</h3>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Custom events can have any name you want
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.on('anyOldNameYouWant', function () {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith alert("Looky there!");
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Group subscriptions by passing an object or array to on()
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.on({
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith somethingImportant: updateCalendar,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith birthday : eatCake,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith weekendEnd : backToTheGrindstone
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Some events have prefixes
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.once("fuji:available", climb);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Custom events have distinct "after" moments
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.after("spa-category|pedicure", gelatoTime);
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith All `EventTarget`s host methods
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="{{apiDocs}}/classes/EventTarget.html#method_on">`on`</a>,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="{{apiDocs}}/classes/EventTarget.html#method_once">`once`</a>,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="{{apiDocs}}/classes/EventTarget.html#method_after">`after`</a>, and
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="{{apiDocs}}/classes/EventTarget.html#method_onceAfter">`onceAfter`</a>.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Both `once` and `onceAfter` will automatically detach the subscription
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith after the callback is executed the first time. All subscription methods
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith return a subscription object called an
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="{{apiDocs}}/classes/EventHandle.html">EventHandle</a>. The
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith distinction between `on` and `after` is discussed in the
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="#after">"after" phase</a> section below.
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="fire">Firing Events</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// All subscribers to the myapp:ready event will be executed
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.fire('myapp:ready');
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Pass along relevant data to the callbacks as arguments
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.fire('birthday', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith name: 'Walt Disney',
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith birthdate: new Date(1901, 11, 5)
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith});
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p id="event-data-object">
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Notify event subscribers by calling `fire( eventName )`, passing any
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith extra data about the event as additional arguments. Though `fire`
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith accepts any number of arguments, it is preferable to send all event data
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith in an object passed as the second argument. Doing so avoids locking your
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith code into a specific `fire` and callback signature.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Subscription callbacks receive fire() arguments
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.on('birthday', function (name, birthdate) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith var age = new Date().getFullYear() - birthdate.getFullYear();
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith alert('Happy ' + age + ', ' + name + '!');
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Possible, but not recommended
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.fire('birthday', 'A. A. Milne', new Date(1882, 0, 18));
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Instead, try to always pass only one object with all data
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.on('birthday', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith var age = new Date().getFullYear() - e.birthdate.getFullYear();
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith alert('Happy ' + age + ', ' + e.name + '!');
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.fire('birthday', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith name: '"Uncle" Walt Whitman',
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith birthdate: new Date(1819, 4, 31)
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith In the world of DOM events, the `fire` step is something the browser is
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith responsible for. A typical model involves the browser receiving keyboard
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith input from the user and firing `keydown`, `keyup`, and `keypress` events.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Custom events put your code in the position of dispatching events in
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith response to criteria that are relavant to your objects or application.
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3>Callback arguments and event facades</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Simple notification events don't send event objects, only fire() data
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.on('talkie', function (data) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith alert('(' + data.time + ') Walkie ' + data.message);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // data.preventDefault is not defined. data is just a plain object
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.fire('talkie', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith message: 'roger, over.',
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith time: new Date()
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Events configured to emitFacade will send an event object, merged with
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// fire() data
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.publish('bill:due', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith emitFacade: true,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith defaultFn : payUp
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.on('bill:due', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // Event facades have standard properties and methods as well as properties
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // from payload data passed to fire()
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith if (e.payee === 'Rich Uncle Sal') {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith e.preventDefault(); // the `payUp` method won't be called (Sal can wait)
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith }
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Objects passed as the second argument to fire() for facade events will have
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// their properties merged onto the facade received by the callback.
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.fire('bill:due', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith payee: 'Great Aunt Myra',
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith amount: 20
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Custom event callbacks are <em>usually, but not always</em> passed an
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="{{apiDocs}}/classes/EventFacade.html">EventFacade</a> as their
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith first argument. Custom events can be configured to send event facades or
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith only the data they were fired with. <a href="#event-data-object">Always
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith passing event data in an object</a> as the second argument to `fire` allows
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith you to write all your callbacks to expect event data as a single first
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith argument, whether it's an `EventFacade` or just a plain object. The
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `emitFacade` and `defaultFn` configurations are detailed below, in
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="#publishing-events">Publishing Events</a>.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3>Detaching Event Subscriptions</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Subscription methods return a subscription handle...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithvar subscription = Y.on('myapp:ready', initComponents);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// ...with a detach method
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithsubscription.detach();
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Or detach by signature
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.detach('myapp:ready', initComponents);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Or by subscription category
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.on('spa-category|pedicure', gelatoTime);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Detach subscriptions to all events in the spa-category subscription group
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.detach('spa-category|*');
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith The preferred method of detaching subscriptions is to use the
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="{{apiDocs}}/classes/EventHandle.html">EventHandle</a> that is
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith returned from the subscription methods. Alternately you can use the
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="{{apiDocs}}/classes/EventTarget.html#method_detach">`detach` or
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `detachAll` methods</a> which work as described in the
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="../event/index.html#detach-methods">Event user guide</a>.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="extend-event-target">Extending EventTarget</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>Add the `EventTarget` APIs onto any class using `Y.augment()`.</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithfunction MyClass() {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith /* insert constructor logic here */
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith}
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithMyClass.prototype = {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith add: function (item) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // You can assume the APIs are available from your class instances
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.fire("addItem", { item: item });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith },
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith ...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith};
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Make MyClass an EventTarget
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.augment(MyClass, Y.EventTarget);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithvar instance = new MyClass();
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithinstance.on('addItem', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith alert("Yay, I'm adding " + e.item);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithinstance.add('a new item'); // ==> "Yay, I'm adding a new item"
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `Y.augment` works like a lazy `extend` or a mixin. It adds the APIs to the
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith host class, but on the first call to any of the methods, it calls the
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `EventTarget` constructor on the instance to make sure the necessary
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith internal objects are ready for use. If your class extends another,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith augmenting it won't interfere with that inheritance hierarchy.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `EventTarget`s can be set up with a number of default configurations for
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith the events they `fire`. Pass the defaults as the fourth argument to
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `Y.augment`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Make all events fired from MyClass instances send an event facade
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.augment(MyClass, Y.EventTarget, true, null, {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith emitFacade: true
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h2>Publishing Events</h2>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Some custom event <a href="#configs">configurations can be defaulted</a>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith from class configuration, but others need to be specified on a per-event
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith basis. Use the `publish` method to do this.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// publish takes an event name and a configuration object
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.publish('somethingSpecial', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith emitFacade: true,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith broadcast: 2,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith defaultFn: clapClapHallelujah,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith fireOnce: true
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="facade">Event Facades</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith The most common configuration for custom events is `emitFacade`. This is
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith because with the event facades comes a lot of additional functionality,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith such as <a href="#defaultFn">preventable default behaviors</a> and <a
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith href="#bubbling">bubbling</a>.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithfunction Recipe() {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // publishing events is typically done at instantiation
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.publish('add', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith emitFacade: true,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith defaultFn: this._defAddFn
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith}
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Event facades mirror the event objects
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="../event/index.html#facade-properties">you're familiar with from
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith the DOM</a>. They have properties like `e.type` and `e.target` and
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith the same methods, allowing you to call `e.preventDefault()` to disable
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith default behavior you've configured for the event or `e.stopPropagation()`
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith to stop the event from bubbling.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithvar gruel = new Recipe();
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithgruel.on('add', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith if (e.item === "brussel sprouts") {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // call e.preventDefault() just as you would for DOM events
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith e.preventDefault(); // brussel sprouts? eww!
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith }
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith});
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `emitFacade` is typically passed as a default configuration to `Y.augment`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith All other YUI infrastructure classes extend `EventTarget` and set
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `emitFacade` to `true` for you.
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.extend(MyClass, Y.Base, {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith add: function (item) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // This will fire with an event facade because Y.Base sets emitFacade to true
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.fire('addItem', { item: item });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith },
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith ...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="once">`fireOnce` Events</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Important, typically system-level or lifecycle related events can be
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith configured as `fireOnce`. These events mimic things like `window.onload`
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith or the `domready` event.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithWidget.prototype.render = function (where) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith ...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // Widget rendering only happens once
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.publish('render', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith defaultFn: this._defRenderFn,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith fireOnce: true,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith ...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.fire('render', ...);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith};
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith After `fireOnce` events have been `fire()`d, any subsequent (late)
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith subscriptions are immediately executed. This can introduce race
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith conditions, however, since subscribers might expect to be called at a later
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith time, after the code that follows the subscription has also executed. In
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this case, you can configure `fireOnce` events with the `async` flag
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith and post-`fire` subscriptions will be executed in a `setTimeout`,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith allowing all subsequent code to run before the late subscriber is notified.
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// BEFORE
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.publish('myapp:ready', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith fireOnce: true
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// ... elsewhere in the code
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// If myapp:ready has been fired, setStuffUp executes right now, but might
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// expect MyApp.Stuff to be created already. So, boom.
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.on('myapp:ready', setStuffUp);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithMyApp.Stuff = {};
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// AFTER
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.publish('myapp:ready', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith fireOnce: true,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith async : true
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// ... elsewhere in the code
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Even if myapp:ready has been fired, setStuffUp will execute later. So, no boom
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.on('myapp:ready', setStuffUp);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithMyApp.Stuff = {};
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="bubbling">Bubbling Events</h3>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Events that are configured with `emitFacade` support bubbling to other
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `EventTarget`s, allowing you to subscribe to them from other objects, much
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith like DOM event bubbling. Add other `EventTarget`s to an instance's bubble
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith path with `addTarget`.
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithfunction LeafNode() { ... }
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithLeafNode.prototype.rename = function (newName) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith var oldName = this.name;
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.name = newName;
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.fire("update", {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith prevVal: oldName,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith newVal : newName
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith};
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithfunction TreeNode() { ... }
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithTreeNode.prototype.add = function (node) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this._items.push(node);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // The new child node's events will bubble to this TreeNode
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith node.addTarget(this);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith};
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.augment(LeafNode, Y.EventTarget, true, null, { emitFacade: true });
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.augment(TreeNode, Y.EventTarget, true, null, { emitFacade: true });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithvar rootNode = new TreeNode("ROOT"),
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith branchA = new TreeNode("branchA"),
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith leaf1 = new LeafNode("leaf1");
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithrootNode.add(branchA); // ROOT
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithrootNode.add( new LeafNode("leaf2") ); // / \
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // branchA leaf2
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithbranchA.add(leaf1); // / \
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithbranchA.add( new LeafNode("leaf3") ); // leaf1 leaf3
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Subscribe to 'update' events from any leaf or tree node under root
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithrootNode.on('update', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith alert(e.prevVal + " has been renamed " + e.newVal);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithleaf1.rename("Flower!"); // ==> "leaf1 has been renamed Flower!"
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="prefix">Event Prefixes</h3>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Individual events or all events fired by an `EventTarget` can be configured
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith to include a prefix to help filter subscriptions to common event names by
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith their origin. Prefixed event names look like `'prefix:eventName'`.
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Taking the <a href="#bubbling">code snippet above</a>, configuring a default
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `prefix` while augmenting the classes will allow for subscription to
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith only `LeafNode` updates.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// All events fired by LeafNode instances will be prefixed with "leaf:"
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.augment(LeafNode, Y.EventTarget, true, null, {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith emitFacade: true,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith prefix: 'leaf'
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// ...and for TreeNodes, "tree:"
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.augment(TreeNode, Y.EventTarget, true, null, {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith emitFacade: true,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith prefix: 'tree'
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Listen specifically for changes from LeafNodes
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithrootNode.on('leaf:update', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith alert(e.prevVal + " has been renamed " + e.newVal);
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith});
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithleaf1.rename("Flower!"); // ==> "leaf1 has been renamed Flower!"
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithbranchA.rename("Chewbacca!"); // (nothing)
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Subscribing with prefixes is similar to
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="../event/delegation.html">using DOM event delegation</a>, though it
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith is done using `on()` rather than `delegate()`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Optionally, you can omit the prefix when subscribing on the object that
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith fires the event.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// prefix is optional when subscribing on the firing object...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithleaf1.on('leaf:update', worksJustLike);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithleaf1.on('update', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith e.type; // 'leaf:update' -- the event type will remain prefixed
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith ...
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith});
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// ...but prefixes are required from other objects
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithrootNode.on('update', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // will not capture leaf:update events
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Subscribe to all events of a specific type, regardless of prefix, using the
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith wildcard prefix `*:eventName`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Execute the callback if either the group object or one of its items fires an
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// `update` event
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithrootNode.on('*:update', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith switch (e.type) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith case "leaf:update": ...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith case "tree:update": ...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith }
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="defaultFn">Adding Default Behavior</h3>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Custom events can be bound to behaviors just like DOM events (e.g. clicking
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith on a link causes navigation to a new page). This is especially useful when
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith doing
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith operations that you want to expose to other objects in your system to
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith prevent, alter, or enhance.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Add a default behavior to an event by configuring the event's `defaultFn`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith By convention, default functions are named `_def(the name of the event)Fn`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithfunction TreeNode(name) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.name = name;
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this._items = [];
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith // Event publishing is typically done during instantiation
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.publish('add', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith defaultFn: this._defAddFn
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith}
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Adding a child node is an interesting mutation operation. Move the mutation
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// logic from the method to a mutation event's default behavior
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithTreeNode.prototype.add = function (node) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.fire('add', { newNode: node });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith};
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Default functions receive the event facade like other subscribers
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithTreeNode.prototype._defAddFn = function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this._items.push(e.newNode);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith e.newNode.addTarget(this);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith};
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithbranchA.add(leaf1); // without 'add' subscriptions, the behavior is the same
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Unless configured with `preventable: false`, default behaviors can be
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith disabled with `e.preventDefault()` just like the DOM. Unlike their DOM
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith counterparts, though, event subscribers <em>can change facade
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith properties</em> to alter the default behavior by way of effectively changing
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith its input.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithTreeNode.prototype.add = function (node) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.fire('add', {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith newNode: node,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith bubbleEvents: true
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith });
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith};
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Default functions receive the event facade like other subscribers
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithTreeNode.prototype._defAddFn = function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this._items.push(e.newNode);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith if (e.bubbleEvents) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith e.newNode.addTarget(this);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith }
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith};
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// You can prevent default behavior from anywhere along the bubble path
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithrootNode.on('tree:add', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith if (e.newNode.name === "Leafy") {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith e.preventDefault();
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith } else if (e.newNode.name === "James Bond") {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith e.bubbleEvents = false; // Shhhh
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith }
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithrootNode.add( new LeafNode("Leafy") ); // Node NOT added
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithrootNode.add( new LeafNode("James Bond") ); // Node added without event bubbling
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3>Broadcasting Events to Y or Between YUI instances</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Event broadcasting is very similar to bubbling, but with some important
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith distinctions:
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<ol>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Broadcasting is specific to the YUI instance and the `Y.Global` shared
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `EventTarget`
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>Events don't need to be configured with `emitFacade` to broadcast</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>Broadcasting happens after the default behavior, which also means...</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>Event behavior can't be prevented from broadcast subscribers</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>Broadcast can be defaulted for all events for an `EventTarget`</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</ol>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Broadcasting is essentially a "fast track" bubbling configuration allowing
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith you to specify that events can be subscribed to from the YUI instance (with
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `broadcast: 1`) or from `Y.Global` (with `broadcast: 2`).
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// All events from instances of MyClass can be subscribed from Y.on()
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.augment(MyClass, Y.EventTarget, true, null, {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith emitFacade: true,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith prefix: 'awesome',
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith broadcast: 1
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith// Respond to a 'thing' event from any instance of MyClass in the YUI sandbox
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithY.on('awesome:song', partyOn);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithvar instance = new MyClass()
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smithinstance.fire("song", { which: "Bohemian Rhapsody", whom: "Wayne" });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `Y.Global` is an `EventTarget` that is shared between all YUI instances,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith allowing cross-sandbox communication. To avoid feedback loops, it's best
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith to add an instance identity to outgoing events and only respond to
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith incoming events from other identities.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithYUI().use('node', 'event-custom', function (Y) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith var id = "Alpha Beta Base"; // probably Y.guid() would be safer
5abe4e6ccb00e9414eb123e8d3d7e1a8d2a7c317Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith Y.Global.on('message', function (e) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith if (e.origin !== id) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith alert("message received from " + e.origin + ": " + e.message);
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith murdock.fire("message", {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith message: "We'll get you down. And down safe.",
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith origin: id
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith }
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith function Character() {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith this.publish('message', { broadcast: 2 });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith ...
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith }
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Y.augment(Character, Y.EventTarget, true, null, {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith emitFacade: true
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith var murdock = new Character();
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Y.one('#status').on('click', function () {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith murdock.fire("message", {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith message: "You're coming in too fast!",
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith origin: id
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke SmithYUI().use('node', 'event-custom', function (OtherY) {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith var id = "Lunar Shuttle";
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith OtherY.Global.on('message', function (e) {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith if (e.origin !== id) {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith alert("message received from " + e.origin + ": " + e.message);
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith }
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith function Character() {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith this.publish('message', { broadcast: 2 });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith }
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith OtherY.augment(Character, OtherY.EventTarget, true, null, {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith emitFacade: true
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith var striker = new Character()
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith OtherY.one('#report').on('click', function () {
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith striker.fire("message", {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith message: "She's beginning to crack up",
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith origin: id
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith });
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith});
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith<button id="status" class="yui3-button">Come in, Lunar Shuttle</button>
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith<button id="report" class="yui3-button">Can you read me, Alpha Beta?</button>
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith<script>
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke SmithYUI().use('node', 'event-custom', function (Y) {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith var id = "Alpha Beta Base"; // probably Y.guid() would be safer
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith Y.Global.on('message', function (e) {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith if (e.origin !== id) {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith alert("message received from " + e.origin + ": " + e.message);
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith murdock.fire("message", {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith message: "We'll get you down. And down safe.",
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith origin: id
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith }
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith function Character() {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith this.publish('message', { broadcast: 2 });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith }
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith Y.augment(Character, Y.EventTarget, true, null, {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith emitFacade: true
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith var murdock = new Character();
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith Y.one('#status').on('click', function () {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith murdock.fire("message", {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith message: "You're coming in too fast!",
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith origin: id
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith});
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke SmithYUI().use('node', 'event-custom', function (OtherY) {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith var id = "Lunar Shuttle";
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith OtherY.Global.on('message', function (e) {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith if (e.origin !== id) {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith alert("message received from " + e.origin + ": " + e.message);
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith }
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith function Character() {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith this.publish('message', { broadcast: 2 });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith }
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith OtherY.augment(Character, OtherY.EventTarget, true, null, {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith emitFacade: true
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith var striker = new Character()
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith OtherY.one('#report').on('click', function () {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith striker.fire("message", {
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith message: "She's beginning to crack up",
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith origin: id
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith });
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith});
ceaa2978be3f6f2d48f7d1e639f956a1ec7b6b89Luke Smith</script>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<!--h3>Monitoring Events</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>TODO</p-->
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="configs">Available Event Configurations and Defaults</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Events can be configured with the following properties. Properties marked
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith as "Class Configurable" can be passed to the `EventTarget` constructor
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith configuration to default for all events.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<table>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<thead>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <th>Configuration</th>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <th>Description</th>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <th>Default</th>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <th>Class Configurable?</th>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</thead>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<tbody>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`prefix`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `e.type` will always include the configured prefix.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="#prefix">Details above</a>.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>(empty)</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>YES</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`context`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith The default `this` object to execute callbacks with. Rarely set.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>The instance</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>YES</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`emitFacade`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith If `true`, sends event facades to callbacks, allows bubbling and
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith default functions, etc. This is commonly set to true for a class.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="#facade">Details above</a>.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`false`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>YES</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`fireOnce`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith If `true`, events will only fire once. Subscriptions made after
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith firing will be immediately executed.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="#once">Details above</a>.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`false`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>YES</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <!--tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`monitored`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Allows you to subscribe to the event lifecycle moments (publish,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith fire, and subscribe) as separate events.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="#monitor">Details above</a>.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`false`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>YES</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr-->
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`broadcast`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Notify the YUI instance (`broadcast: 1`) or the YUI instance
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <em>and</em> `Y.Global` with the event.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <a href="#broadcast">Details above</a>.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>0 (instance only)</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>YES</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`bubbles`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith For events configured to `emitFacade` allow bubbling events to
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith other `EventTarget`s.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`true`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>YES</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`defaultFn`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Behavior associated with the event. Usually this is preventable
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith (see `preventable` below). <a href="#defaultFn">Details above</a>.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>(none)</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>&nbsp;</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`preventable`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith If set to `false`, `e.preventDefault()` will not disable execution
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith of the event's `defaultFn`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`true`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>&nbsp;</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`preventedFn`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Behavior associated with the event when `e.preventDefault()` is
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith called from a subscriber. Use this function to reset partially
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith applied transactional state.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <p>Incompatible with `preventable: false`.</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>(none)</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>&nbsp;</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`stoppedFn`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Behavior associated with the event when `e.stopPropagation()` is
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith called from a subscriber. Seldom used.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>(none)</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>&nbsp;</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>`async`</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Only applicable to events also configured with `fireOnce: true`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith If `true`, new subscriptions to this event after it has already
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith been fired will be queued to execute in a `setTimeout` instead of
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith immediately (synchronously).
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>false</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <td>&nbsp;</td>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </tr>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</tbody>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</table>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="after">The "after" phase</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Unlike DOM events, custom events also expose an "after" phase that
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith corresponds to the time immediately after an event's <a
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith href="#defaultFn">default behavior</a> executes. Subscribe to an event's
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith "after" phase with the `after(...)` method. The signature is the same as
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `on(...)`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke SmithrootNode.after('tree:add', calc.updateTotals, calc);
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith```
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith The primary benefit of using `after()` subscriptions over `on()`
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith subscriptions is that if any `on()` subscribers call `e.preventDefault()`,
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith neither the event's configured `defaultFn` <em>nor the `after()`
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith subscribers</em> will be executed. If an `after()` subscription is
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith executed, you know that the `defaultFn` did as well.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <strong>Use `after()` to subscribe to events with a default behavior when
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith you want to react to the event with a side effect.</strong>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <strong>Use `on()` to subscribe to events if you need to prevent or alter
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith the default behavior or if they don't have default behavior.</strong>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h2>Event Lifecycle</h2>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>The order of operations when firing an event is as follows:</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="simple-event-lifecycle">Simple Events (no facade)</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<ol>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`on()` subscribers are executed</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`after()` subscribers are executed</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`Y.on()` broadcast subscribers are executed.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`Y.after()` broadcast subscribers are executed.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`Y.Global.on()` broadcast subscribers are executed.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`Y.Global.after()` broadcast subscribers are executed.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</ol>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith If an `on()` or `after()` subscriber returns `false`, no more subscribers
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith will be notified.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<h3 id="complex-event-lifecycle">Complex Events (with facade)</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<ol>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`on()` subscribers are executed</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `on()` subscribers for each bubble target and their respective targets
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith are executed until all targets' bubble paths are walked or a subscriber
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith stops the propagation of the event.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith If the event was prevented, any configured `preventedFn` will execute.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>If not prevented, any configured `defaultFn` will execute.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>If bubbling was stopped, any configured `stoppedFn` will execute.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`Y.on()` broadcast subscribers are executed.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`Y.after()` broadcast subscribers are executed.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`Y.Global.on()` broadcast subscribers are executed.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`Y.Global.after()` broadcast subscribers are executed.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>`after()` subscribers are executed.</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `after()` subscribers for each bubble target and their respective
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith targets are executed.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</ol>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
9c34deaac0f6b83d5bdad476499072bbb44a4915Luke Smith The flow can be interrupted by `on()` subscribers doing any of these
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith things:
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<dl>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dt>`e.preventDefault()`</dt>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <ol>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>The `defaultFn` will not be executed</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>The `preventedFn` will execute</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>No `after()` subscriptions will be executed</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </ol>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dt>`e.stopPropagation()`</dt>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <ol>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>The remainder of subscribers at this `EventTarget` <strong>WILL</strong> execute</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>No bubble targets of this `EventTarget` will be notified</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>The `stoppedFn` will execute</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <li>The `defaultFn` and `after()` subscribers will execute</li>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </ol>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dt>`e.stopImmediatePropagation()`</dt>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Same as `e.stopPropagation()` except no more subscribers at this
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith `EventTarget` will execute.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dt>`e.halt()`</dt>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Same as `e.preventDefault()` plus `e.stopPropagation()`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dt>`e.halt(true)`</dt>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith Same as `e.preventDefault()` plus `e.stopImmediatePropagation()`.
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith </dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dt>`return false`</dt>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith <dd>Same as `e.halt(true)`. Not recommended. Use the API methods.</dd>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</dl>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
acf058cdbd5db47aed5515e9684fb57f4180cf8dLuke Smith<!--h2 class="no-toc">Subscribing to Object Methods with `Y.Do.*`</h2>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
acf058cdbd5db47aed5515e9684fb57f4180cf8dLuke Smith<h3 class="no-toc">Before and After</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
acf058cdbd5db47aed5515e9684fb57f4180cf8dLuke Smith<h3 class="no-toc">Altering the Wrapped Method Behavior</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
acf058cdbd5db47aed5515e9684fb57f4180cf8dLuke Smith<h3 class="no-toc">`EventTarget` API methods</h3>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith<p>
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith TODO
0b9d29819770568053cd440baed0fedeb42aa208Luke Smith</p-->