<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Example: Custom Event Bubbling and Behaviors</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>
<h1>Example: Custom Event Bubbling and Behaviors</h1>
<div class="yui3-g">
<div class="yui3-u-3-4">
<div id="main">
<div class="content"><style type="text/css">
#fire {
margin: 1em;
}
#log {
border: 1px dotted #999;
background-color: #FFF;
}
#log li {
padding: 5px;
}
#log li highlight {
color: #930;
}
</style>
<div class="intro">
<p>
The Custom Event framework is one of the principle communication
mechanisms in YUI. An object can be augmented with
<code>EventTarget</code>, enabling it to be both a host and a target
for custom events. Custom events fire from their host and optionally
bubble up to one or more targets. This allows you to make the
interesting moments of your applications broadly available within a
module, within a set of modules, or throughout a complex interface
populated with rich elements.
</p>
<p>
In this example, a simple custom event is illustrated:
<code>testEvent</code>. This custom event is hosted on a Publisher
object and bubbles up to a BubbleTarget object.
</p>
<img src="../assets/event-custom/ce-example.gif"
alt="An illustration of the relationship between the custom event, its host, and its Bubble Target.">
<p>
Like DOM events, custom event bubbling can be stopped with
<code>e.stopPropagation()</code> and default behavior can be suppressed with
<code>e.preventDefault()</code>.
</p>
</div>
<div class="example yui3-skin-sam">
<p>
<button id="fire" value="Fire">Fire testEvent</button>
</p>
<div>
<input type="checkbox" id="stopPropagation">
<label for="stopPropagation">
Stop Propagation (testEvent won't bubble to the BubbleTarget.)
</label>
</div>
<div>
<input type="checkbox" id="preventDefault">
<label for="preventDefault">
Prevent Default (testEvent's <code>defaultFn</code> won't fire.)
</label>
</div>
<ol id="log">
<li>Custom Event log messages will appear here.</li>
</ol>
<script>
// Bubbling events are added by the event-custom module.
YUI().use('event-custom', 'node', function (Y) {
var logger = Y.one("#log");
stopCheckbox = Y.one("#stopPropagation"),
preventCheckbox = Y.one("#preventDefault");
// We'll create two classes, one to fire the event, and another to be a
// bubble target for the other. All events from the Publisher class can
// then be subscribed from either the Publisher instance or the BubbleTarget
// instance that it's related to.
function BubbleTarget() {
Y.log("BubbleTarget constructor executed.");
}
function Publisher(bubbleTo) {
Y.log("Publisher constructor executed.");
this.init(bubbleTo); // see class prototype below
}
// Publishers need to add the provided target to their bubble chain with
// <code>addTarget</code>. We'll do this, and publish an event, in an <code>init</code> method
Publisher.prototype = {
init: function (bubbleTo) {
// <code>addTarget</code> is the EventTarget method to register new bubble
// targets for this instance
this.addTarget(bubbleTo);
// It's only necessary to publish events with special configuration,
// such as default, stop, or prevent behaviors. You can always
// fire any event name you wish, published or unpublished.
this.publish("testEvent", {
// Pass an event facade to subscribers so they can call
// e.preventDefault() and other methods.
emitFacade: true,
// An event's default behavior is defined in defaultFn. This
// will execute unless a subscriber calls <code>e.preventDefault()</code>
defaultFn: function () {
Y.log("defaultFn: testEvent's defaultFn executed.");
},
// You can react to subscribers preventing default behavior as
// well, by defining a preventedFn.
preventedFn: function () {
Y.log("preventedFn: A subscriber to testEvent called preventDefault().");
},
// If a subscriber calls <code>e.stopPropagation()</code>, the event won't
// bubble any further, and the stoppedFn will be called if one
// is defined.
stoppedFn: function () {
Y.log("stoppedFn: A subscriber to testEvent called stopPropagation().");
}
});
}
};
// To fire events or be a bubble target, augment a class with EventTarget
Y.augment(Publisher, Y.EventTarget);
Y.augment(BubbleTarget, Y.EventTarget);
// SEE IT IN ACTION
var bubbleTarget = new BubbleTarget();
// You can subscribe to the "testEvent" from the BubbleTarget, even before
// a Publisher is created
bubbleTarget.subscribe("testEvent", function (e) {
Y.log("testEvent fired on the BubbleTarget object.");
});
// Create a Publisher instance, and link it to our BubbleTarget
var publisher = new Publisher(bubbleTarget);
// We can also subscribe to the testEvent on the Publisher instance.
publisher.on("testEvent", function (e) {
Y.log("testEvent subscriber fired on the publisher object.");
if (stopCheckbox.get("checked")) {
e.stopPropagation();
}
if (preventCheckbox.get("checked")) {
e.preventDefault();
}
});
// Wire up the example button to fire the event from our publisher
Y.one("#fire").on("click", function (e) {
logger.empty(); // clear out the logger:
publisher.fire("testEvent");
});
// A little supporting magic to output Y.log() statements to the screen
Y.on("yui:log", function (e) {
logger.append("<li>" + e.msg + "</li>");
});
});
</script>
</div>
<h2>Source Code</h2>
<p>
The full source code for this example follows. Read through the comments
and code to get an understanding of how you can make use of custom events
in your own application development.
</p>
<pre class="code prettyprint">// Bubbling events are added by the event-custom module.
YUI().use('event-custom', 'node', function (Y) {
var logger = Y.one("#log");
stopCheckbox = Y.one("#stopPropagation"),
preventCheckbox = Y.one("#preventDefault");
// We'll create two classes, one to fire the event, and another to be a
// bubble target for the other. All events from the Publisher class can
// then be subscribed from either the Publisher instance or the BubbleTarget
// instance that it's related to.
function BubbleTarget() {
Y.log("BubbleTarget constructor executed.");
}
function Publisher(bubbleTo) {
Y.log("Publisher constructor executed.");
this.init(bubbleTo); // see class prototype below
}
// Publishers need to add the provided target to their bubble chain with
// `addTarget`. We'll do this, and publish an event, in an `init` method
Publisher.prototype = {
init: function (bubbleTo) {
// `addTarget` is the EventTarget method to register new bubble
// targets for this instance
this.addTarget(bubbleTo);
// It's only necessary to publish events with special configuration,
// such as default, stop, or prevent behaviors. You can always
// fire any event name you wish, published or unpublished.
this.publish("testEvent", {
// Pass an event facade to subscribers so they can call
// e.preventDefault() and other methods.
emitFacade: true,
// An event's default behavior is defined in defaultFn. This
// will execute unless a subscriber calls `e.preventDefault()`
defaultFn: function () {
Y.log("defaultFn: testEvent's defaultFn executed.");
},
// You can react to subscribers preventing default behavior as
// well, by defining a preventedFn.
preventedFn: function () {
Y.log("preventedFn: A subscriber to testEvent called preventDefault().");
},
// If a subscriber calls `e.stopPropagation()`, the event won't
// bubble any further, and the stoppedFn will be called if one
// is defined.
stoppedFn: function () {
Y.log("stoppedFn: A subscriber to testEvent called stopPropagation().");
}
});
}
};
// To fire events or be a bubble target, augment a class with EventTarget
Y.augment(Publisher, Y.EventTarget);
Y.augment(BubbleTarget, Y.EventTarget);
// SEE IT IN ACTION
var bubbleTarget = new BubbleTarget();
// You can subscribe to the "testEvent" from the BubbleTarget, even before
// a Publisher is created
bubbleTarget.subscribe("testEvent", function (e) {
Y.log("testEvent fired on the BubbleTarget object.");
});
// Create a Publisher instance, and link it to our BubbleTarget
var publisher = new Publisher(bubbleTarget);
// We can also subscribe to the testEvent on the Publisher instance.
publisher.on("testEvent", function (e) {
Y.log("testEvent subscriber fired on the publisher object.");
if (stopCheckbox.get("checked")) {
e.stopPropagation();
}
if (preventCheckbox.get("checked")) {
e.preventDefault();
}
});
// Wire up the example button to fire the event from our publisher
Y.one("#fire").on("click", function (e) {
logger.empty(); // clear out the logger:
publisher.fire("testEvent");
});
// A little supporting magic to output Y.log() statements to the screen
Y.on("yui:log", function (e) {
logger.append("<li>" + e.msg + "</li>");
});
});</pre>
</div>
</div>
</div>
<div class="yui3-u-1-4">
<div class="sidebar">
<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: 'flow-example',
title: 'Custom Event Bubbling and Behaviors',
newWindow: '',
auto: false
};
YUI.Env.Tests.examples.push('flow-example');
</script>
<script src="../assets/yui/test-runner.js"></script>
</body>
</html>