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