6
<link rel="stylesheet" href="http://yui.yahooapis.com/3.4.0pr3/build/cssgrids/grids-min.css">
7
<link rel="stylesheet" href="../assets/css/main.css">
8
<link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
9
<script src="../../build/yui/yui-min.js"></script>
17
<a href="#toc" class="jump">Jump to Table of Contents</a>
21
<div id="main" class="yui3-u">
22
<div class="content"><style>
27
background-color: #E6E9F5;
29
.yui3-skin-sam .yui3-datatable td {
30
background-color: transparent;
34
<div class="intro component">
35
<p>The YUI Event Utility provides APIs for working with the browser's DOM
36
event system. It simplifies tasks like subscribing to button <code>click</code>s or
37
canceling <form> <code>submit</code>s to, for example, allow sending data to the
40
<p>In addition, the "Synthetic event" system supplies <em>entirely new</em>
41
DOM events to subscribe to as well as fixing events that behave differently
42
across browsers. Implementers can create their own DOM events triggered by
43
specific user actions or other environmental criteria.</p>
45
<p>The API for working with DOM events is provided by the EventTarget class,
46
which also services the Custom event infrastructure that is used throughout
47
YUI. Read more about working with custom events <a
48
href="../event-custom/index.html">in the EventTarget user guide</a>.</p>
51
<h2 id="getting-started">Getting Started</h2>
54
To include the source files for Event and its dependencies, first load
55
the YUI seed file if you haven't already loaded it.
58
<pre class="code prettyprint"><script src="http://yui.yahooapis.com/3.4.1/build/yui/yui-min.js"></script></pre>
62
Next, create a new YUI instance for your application and populate it with the
63
modules you need by specifying them as arguments to the <code>YUI().use()</code> method.
64
YUI will automatically load any dependencies required by the modules you
68
<pre class="code prettyprint">// Create a new YUI instance and populate it with the required modules.
69
YUI().use('event', function (Y) {
70
// Event is available and ready for use. Add implementation
71
// code here.
76
For more information on creating YUI instances and on the
77
<a href="http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_use"><code>use()</code> method</a>, see the
78
documentation for the <a href="../yui/index.html">YUI Global object</a>.
82
<h2 id="the-basics">The Basics</h2>
84
<h4 id="listening-for-events">Listening for events</h4>
85
<pre class="code prettyprint">// Step 1. Capture a button node
86
var button = Y.one("#readygo");
88
// Step 2. Subscribe to its click event with a callback function
89
button.on("click", function (e) {
91
// Step 3. do stuff when the button is clicked
96
<p><code>on(<em>type</em>, <em>callback</em>)</code> is the main
97
subscription method, and is available on every <a href="../node/"><code>Node</code></a>
98
and <a href="../node/#nodelist"><code>NodeList</code></a>.</p>
100
<p>Replace "click" with <a href="#event-whitelist">any other event name</a> to subscribe to that event.</p>
102
<h4 id="the-callback-and-the-event-object">The Callback and the Event Object</h4>
104
<pre class="code prettyprint">button.on('click', function (e) {
105
// `this` is the button Node, NOT the DOM element
106
this.get('id'); // ==> 'readygo' (from <button id="readygo">...</button>)
108
// Event properties that point to the DOM are also Node instances
109
e.target.get('id'); // => 'readygo'
111
// Stop the event's default behavior
114
// Stop the event from bubbling up the DOM tree
119
<p>Subscribed callbacks are passed a <a href="#facade-properties">a normalized
120
event object</a> as their first argument.</p>
122
<p>The keyword "<code>this</code>" in the callback will refer to the Node or NodeList
123
that you subscribed from.</p>
125
<h4 id="epreventdefault-and-estoppropagation"><code>e.preventDefault()</code> and <code>e.stopPropagation()</code></h4>
127
<p>Many events have a default behavior, such as the <code>submit</code> event serializing
128
form data and making a new page request. Disable this behavior with
129
<code>e.preventDefault()</code>.</p>
131
<pre class="code prettyprint">function setFilter(e) {
132
// Stop the link from loading the href page
135
// Now do my own thing instead
136
var url = this.get('href').replace(/page/, 'partial');
138
Y.one('#contentArea').load(url);
140
// `return false` is supported, but not preferred. use e.preventDefault()
144
Y.one('#table-filter-link').on('click', setFilter);</pre>
147
<p>Most events can be listened for on the specific element that originates them
148
<em>or from any of their parent elements</em>, all the way up to the
149
<code>document</code>. Prevent dispatching the event to subscriptions bound to elements
150
further up the DOM tree with <code>e.stopPropagation()</code>. In practice, this is
153
<p>Returning <code>false</code> from a callback will also stop the propagation of the
154
event, which may cause unintended side effects.</p>
156
<p><code>e.stopPropagation()</code> won't prevent the execution of other subscribers
157
listening to the same element, only elements further up the DOM tree. If you
158
need to stop all execution, use <code>e.stopImmediatePropagation()</code> or
159
<code>e.halt(true)</code>. The latter will also call <code>e.preventDefault()</code>.</p>
161
<h4 id="detaching-subscriptions">Detaching subscriptions</h4>
163
<p><code>node.on()</code> and all
164
<a href="#more">other subscription methods</a> return a
165
subscription object that can be used to unbind that subscription. Node also
166
supports a <code>detach()</code> method and <a href="#detach-methods">other ways to cleaup
167
subscriptions</a>.</p>
169
<pre class="code prettyprint">// on() returns a subscription handle...
170
var sub = button.on("click", handleClick);
172
// ...that can be used to unbind the subscription
175
// Alternately, use the Node's detach() method
176
button.detach("click", handleClick);</pre>
179
<p>Just this should take care of most of the simple event bindings you'll need.
180
There's <a href="#more">a lot more you can do</a>, though, so read on!</p>
182
<h2 id="modules">What to <code>use()</code></h2>
185
Before we get into <a href="#more">more API goodies</a>, let's talk about
186
the Event Utility's module breakdown.
190
For starters, in most cases <em>you probably won't <code>use('event')</code></em>.
191
The core DOM event system ("event-base") is required by the "node-base"
192
module, which itself if required by just about everything in YUI. So you
193
probably already have the DOM event API and didn't know it!
196
<p>Here is the full breakdown of modules in the DOM event system:</p>
201
<th><code>use("______", ...)</code></th>
202
<th>What's in it?</th>
207
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-base.html"><code>event-base</code></a></td>
210
The core DOM event subscription system as well as the DOM
211
lifecycle events <a href="domready.html"><code>domready</code>,
212
<code>contentready</code>, and <code>available</code></a>. Notably, it does NOT
216
<li>event delegation</li>
217
<li>event simulation</li>
218
<li>synthetic events</li>
221
<p>If you've <code>use()</code>d anything, you probably have this already.</p>
225
<td><a href="http://yuilibrary.com/yui/docs/api/module_event.html"><code>event</code></a></td>
227
A rollup of all modules below except
229
<li>"event-simulate"</li>
230
<li>"node-event-simulate"</li>
231
<li>"node-event-delegate" (which is in the "node" rollup)</li>
236
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-delegate.html"><code>event-delegate</code></a> &
238
<a style="white-space: nowrap;" href="http://yuilibrary.com/yui/docs/api/module_node-event-delegate.html"><code>node-event-delegate</code></a></td>
240
Adds the <code>Y.delegate(...)</code> and <code>node.delegate(...)</code> methods,
241
respectively, for <a href="#delegation">event delegation</a>
246
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-simulate.html"><code>event-simulate</code></a> &
248
<a style="white-space: nowrap;" href="http://yuilibrary.com/yui/docs/api/module_node-event-simulate.html"><code>node-event-simulate</code></a></td>
252
Adds <code>Y.Event.simulate(...)</code> and <code>node.simulate(...)</code> for
253
<a href="#simulate">triggering native DOM events</a> for
257
<strong>Note: <a href="simulate.html#faking">Faking DOM events
258
should not be used in user facing code</a></strong>.
263
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-synthetic.html"><code>event-synthetic</code></a></td>
265
<p>Supplies the infrastructure for creating new DOM events, "fixing"
266
existing events with undesirable or inconsistent behavior, and
267
<a href="synths.html">all sorts of other things</a>.</p>
269
<p>All of the modules below are synthetics.</p>
273
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-flick.html"><code>event-flick</code></a></td>
275
Adds a <a href="touch.html#flick">"flick" event</a> for touch or
280
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-focus.html"><code>event-focus</code></a></td>
282
<a href="focus.html">Fixes <code>focus</code> and <code>blur</code> events</a> to bubble
286
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-gestures.html"><code>event-gestures</code></a></td>
288
<p>A rollup of the following modules:</p>
291
<li>"event-touch"</li>
292
<li>"event-move"</li>
293
<li>"event-flick"</li>
296
<p>In the future, may contain more gesture abstraction modules.</p>
299
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-hover.html"><code>event-hover</code></a></td>
301
Adds a <a href="mouseenter.html#hover">"hover" event</a> which
302
binds to two callbacks, one for the start, and one for the end of a
307
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-key.html"><code>event-key</code></a></td>
309
Adds a <a href="key.html">"key" event</a> which listens for
310
specific, implementer defined, keys being pressed by the user.
314
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-mouseenter.html"><code>event-mouseenter</code></a></td>
316
Adds <a href="mouseenter.html">"mouseenter" and "mouseleave"
317
events</a>. You probably want to use these instead of "mouseover"
322
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-mousewheel.html"><code>event-mousewheel</code></a></td>
324
<p>Adds a "mousewheel" event for monitoring users scrolling the
325
window with the mousewheel. Event facades passed to the callback
326
will have an <code>e.wheelDelta</code> property corresponding to the amount of
329
<p>Currently, this event can only be subscribed with
330
<code>Y.on("mousewheel", callback)</code>;</p>
334
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-move.html"><code>event-move</code></a></td>
336
Adds <a href="touch.html#move">"gesturemovestart", "gesturemove",
337
and "gesturemoveend" events</a> that serve as abstractions over
338
mouse and touch events, forking internally based on the client
343
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-outside.html"><code>event-outside</code></a></td>
345
Adds a <a href="outside.html">"clickoutside" and several other
346
outside events</a> to trigger behavior based on actions taken
347
outside a specific element.
351
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-resize.html"><code>event-resize</code></a></td>
353
<p>Adds a "windowresize" event that only fires after a user has
354
stopped dragging a window's resize handle. This normalizes the
355
<code>window.onresize</code> event across browsers.</p>
357
<p>This event can only be subscribed with
358
<code>Y.on("windowresize", callback)</code>;</p>
362
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-touch.html"><code>event-touch</code></a></td>
364
Adds support for <a href="touch.html">subscribing to native touch
365
and gesture events</a>.
369
<td><a href="http://yuilibrary.com/yui/docs/api/module_event-valuechange.html"><code>event-valuechange</code></a></td>
371
Adds a <a href="valuechange.html">"valueChange" event</a> that fires when input element text
372
changes (this is harder than you think).
378
<h2 id="delegation">Event Delegation</h2>
380
<p>If you don't already know what event delegation is, you should <a
381
href="delegation.html">read this quick overview</a>. Short form: <em>you need
382
to be using this</em>.</p>
384
<pre class="code prettyprint">// single element subscription
385
node.on("click", handleClick);
387
// delegated subscription for all button clicks from inside the node
388
node.delegate("click", handleClick, "button, input[type=button]");</pre>
391
<p>Creating a delegated subscription looks very much like creating any other
392
event subscription with two differences. First, it's a different method name,
393
<code>delegate</code>. Second, there is another argument: a CSS selector that is used to
394
test the event's originating element to decide if the callback should be
395
executed. If the event started at or inside an element matching the selector,
396
the callback will execute.</p>
398
<p>Unlike <code>node.on()</code> subscriptions, the <code>this</code> object in <code>node.delegate()</code>
399
callbacks will refer to the element that matched the css filter, not to <code>node</code>.
400
We did this because likely your logic revolves around the nodes described by
401
the filter, not around the element that contains them.</p>
403
<pre class="code prettyprint">function handleClick (e) {
404
// `this` is the button with class .remove, not the #items element
405
// remove the containing LI
406
this.ancestor('li').remove();
408
// e.currentTarget is also the button.remove
409
// e.container === Y.one('#items')
412
Y.one('#items').delegate('click', handleClick, 'button.remove');</pre>
415
<p>For more complex target filtering, a function can be passed instead of a css
417
<a href="http://yuilibrary.com/yui/docs/api/module_event-delegate.html#method_delegate">API docs</a>
418
for more details.</p>
420
<p>As noted <a href="#modules">above</a>, the <code>event-delegate</code> module is
421
included in the <code>event</code> rollup, but <code>node-event-delegate</code> isn't. We recommend
422
using delegation from the Node API, so you should <code>use()</code> either
423
<code>node-event-delegate</code> or the <code>node</code> rollup.</p>
426
<h2 id="more">More Event API Goodness</h2>
429
Here is a sampling of some of the other ways to manage event subscriptions
433
<h4 id="y-on">Subscribe from <code>Y</code></h4>
435
<pre class="code prettyprint">// Y.on() takes a third argument which is the Node, DOM element,
436
// or CSS selector of the element(s) to bind
437
Y.on("click", handleClick, "#readygo");
439
// Y.delegate() similarly takes the containing element or selector
440
// as the third argument
441
Y.delegate("click", handleClick, "#container", "button, input[type=button]");</pre>
445
An alternate syntax for DOM subscriptions is using <code>Y.on()</code> or
446
<code>Y.delegate()</code>. When identifying the target by a CSS selector, these
447
methods can be used regardless if the element is currently available for
448
scripting. If it's not yet on the page, a poll will regularly look for it
449
(for a few seconds) and the subscription will be automatically attached
450
when the element is found. Relying on this behavior can introduce race
451
conditions, though, so use it wisely.
454
Use of <code>Y.on()</code> instead of <code>node.on()</code> is largely a stylistic preference,
455
though <a href="#y-on-vs-node-on">there are some technical differences</a>.
459
<h4 id="once">One time subscriptions</h4>
461
<pre class="code prettyprint">tabLabel.once('mouseover', loadTabContent);</pre>
464
<p>If you only want to execute a callback on the first occurrence of an event, use <code>node.once()</code> or <code>Y.once()</code>. The subscription will automatically be detached after the event fires.</p>
466
<p>The signature for <code>once()</code> is the same as <code>on()</code>.</p>
468
<h4 id="grouping-subscriptions">Grouping subscriptions</h4>
470
<p>Pass an object to subscribe to multiple events, each with their own
473
<pre class="code prettyprint">function validate(e) { ... }
474
function clearPlaceholder(e) { ... }
476
var groupSub = inputNode.on({
479
focus : clearPlaceholder
482
// Detach the blur, keypress, and focus subscriptions in one call
483
groupSub.detach();</pre>
486
<p>Pass an array to subscribe to multiple events with the same callback</p>
487
<pre class="code prettyprint">function activate(e) { ... }
489
groupSub = inputNode.on(['focus', 'mouseover'], activate);
491
// Detach the focus and mouseover subscriptions
492
groupSub.detach();</pre>
495
<p>Prefix the event name with a category to allow detaching multiple
496
subscriptions by that category.</p>
498
<pre class="code prettyprint">inputNode.on('my-category|focus', activate);
499
inputNode.on('my-category|mouseover', activate);
501
// You can detach specific subscriptions by 'my-category|focus' or all with |*
502
inputNode.detach('my-category|*');</pre>
505
<p>The <code>once()</code> and <code>delegate()</code> methods also support these alternate
508
<h4 id="extended-signature">Binding <code>this</code> and additional callback arguments</h4>
511
By default, the "<code>this</code>" object in subscription callbacks will be the Node
512
or NodeList that subscribed to them. Override this default by passing your
513
own <code>this</code> object as the third argument to <code>on()</code> or the fourth to
514
<code>delegate()</code>. Note that the argument index is shifted when using <code>Y.on()</code>
515
and <code>Y.delegate()</code> or <a href="synths.html">synthetic events with custom
519
<pre class="code prettyprint">// equivalent to node.on('click', function (e) { overlay.hide(e); });
520
node.on('click', overlay.show, overlay);
522
node.once('mouseover', door.unlock, door);
524
// `this` override comes after the filter; also shifted for the 'key' event's
525
// custome signature.
526
container.delegate('key', validator.isValid, 'enter,tab', 'input', validator);
528
// Corresponding alternatives from Y
529
Y.on('click', overlay.show, '#show', overlay);
531
Y.once('mouseover', door.unlock, '#gate13', door);
533
Y.delegate('key', validator.isValid, '#myForm', 'enter,tab', 'input', validator);</pre>
536
<p>Additional arguments passed to the subscription methods will be sent along
537
to the callback after the event facade. If you want to bind extra arguments,
538
but don't want to override the "<code>this</code>" object, pass <code>null</code> for the <code>this</code>
541
<pre class="code prettyprint">MyClass.prototype = {
542
someMethod: function (param) {
543
Y.log(param); // => "I'm Extra!"
546
handleClick: function (e, extraParam) {
547
this.someMethod(extraParam);
553
var instance = new Y.MyClass();
555
// The extra arg is passed as the second param to the callback after `e`
556
Y.one('#readygo').on('click', instance.handleClick, instance, "I'm Extra!");</pre>
559
<h4 id="detach-methods">More ways to clean up subscriptions</h4>
561
<p>There are a lot of options for detaching events in YUI. See the table below for details.</p>
567
<th>What it does</th>
573
<pre class="code prettyprint">var subscription = node.on('click', callback);
575
subscription.detach();</pre>
580
Removes a specific subscription or, if created with one of the
581
group subscription methods, a group of subscriptions.
584
Generally, this is the best method to use.
588
<tr id="remove-by-category">
590
<pre class="code prettyprint">node.on('foo-category|click', callback);
592
node.detach('foo-category|click');
594
node.detach('foo-category|*');</pre>
599
Removes a subscription or group of subscriptions that included
600
the specified category in the subscription event type.
603
This is typically only safe in implementation code, not
604
module code, because multiple subscriptions using the same type
605
and category will be detached by the call to <code>detach</code>.
611
<pre class="code prettyprint">node.detach('click', callback);
613
node.detach('click');
620
If you have a reference to the subscribed callback function,
621
(but not a subscription handle) use the two argument signature.
624
With one argument, <code>detach</code> will remove all subscriptions for
625
the specified event. With no arguments, it removes all
626
subscriptions for all events.
629
<code>detach</code> does not remove subscriptions from descendant nodes.
635
<pre class="code prettyprint">node.detachAll();</pre>
640
Works the same as <code>node.detach()</code>.
646
<pre class="code prettyprint">node.purge();
650
node.purge(true, 'click');</pre>
655
With no arguments, <code>purge</code> works the same as <code>node.detach()</code>.
658
Passing <code>true</code> as a first argument will remove all
659
subscriptions for all events from the node <em>and its
660
descendant subtree</em>. Passing an event type as a second
661
argument will only deep purge subscriptions to that event.
667
<pre class="code prettyprint">node.empty();</pre>
672
Removes subscriptions for all events <em>only from the
673
descendants of a node</em> after removing them from the DOM.
679
<pre class="code prettyprint">node.destroy();
681
node.destroy(true);</pre>
686
With no arguments, works like <code>node.detach()</code>.
689
With <code>true</code> as a first argument, it works like
690
<code>node.purge(true)</code>.
693
The <code>destroy</code> method does more than detaching event
694
subscribers. Read the
695
<a href="http://yuilibrary.com/yui/docs/api/classes/Node.html#method_destroy">API
696
docs</a> for details.
702
<pre class="code prettyprint">Y.Event.detach('click', callback, '#foo');</pre>
707
Same as <code>Y.one('#foo').detach( [other args] )</code>.
713
<pre class="code prettyprint">Y.Event.purgeElement('#foo', true, 'click');</pre>
718
Same as <code>Y.one('#foo').purge( [other args] )</code>.
725
<h2 id="simulate">Simulate browser events</h2>
728
For creating automated functional tests, being able to simulate user
729
interaction can be crucial. That's where the <code>node-event-simulate</code> module
733
<pre class="code prettyprint">YUI().use('test', 'node-event-simulate', 'fancy', function (Y) {
735
var test = new Y.Test.Case({
738
"clicking close button should dismiss UI": function () {
740
var widget = new Y.MyFancyWidget().render('#here'),
741
uiBox = widget.get('boundingBox'),
742
closeButton = uiBox.one('.close-button');
744
closeButton.simulate('click');
746
Y.Assert.isFalse( uiBox.inDoc() );
752
<code>node.simulate( type, eventProperties )</code> creates a native DOM event that
753
will bubble (if appropriate), but will not trigger native default behavior.
754
For example, <code>node.simulate('submit')</code> will not send data to the server for
758
<p>Read <a href="simulate.html">more about event simulation here</a>.</p>
760
<h2 id="synthetic-events">Synthetic Events</h2>
762
<p>The event system supports adding new abstractions over the native DOM
763
environment that behave like DOM events. These abstractions are called
764
synthetic events, and you can subscribe to them like any other DOM event with
765
<code>node.on()</code> or <code>node.delegate()</code>.</p>
767
<pre class="code prettyprint">Y.one('#dialog').on('clickoutside', function (e) {
768
this.transition('fadeOut');
771
Y.one('#editable-table').delegate('key', saveAndAdvance, 'tab', 'input');</pre>
775
The synthetic events that are available as core YUI modules are listed in
776
<a href="#modules">the table of modules above</a>, though there are others
777
<a href="http://yuilibrary.com/gallery/">in the Gallery</a>. Most events
778
listed in the table are linked to pages that describe the specific event in
782
<h4 id="creating-dom-events">Creating DOM events</h4>
784
<p>Create your own synthetic events with <code>Y.Event.define(type, config)</code>.</p>
786
<pre class="code prettyprint">Y.Event.define("tripleclick", {
788
// The setup logic executed when node.on('tripleclick', callback) is called
789
on: function (node, subscription, notifier) {
790
// supporting methods can be referenced from `this`
791
this._clear(subscription);
793
// To make detaching easy, a common pattern is to add the subscription
794
// for the supporting DOM event to the subscription object passed in.
795
// This is then referenced in the detach() method below.
796
subscription._handle = node.on('click', function (e) {
797
if (subscription._timer) {
798
subscription._timer.cancel();
801
if (++subscription._counter === 3) {
802
this._clear(subscription);
804
// The notifier triggers the subscriptions to be executed.
805
// Pass its fire() method the triggering DOM event facade
808
subscription._timer =
809
Y.later(300, this, this._clear, [subscription]);
814
// The logic executed when the 'tripleclick' subscription is `detach()`ed
815
detach: function (node, subscription, notifier) {
816
// Clean up supporting DOM subscriptions and other external hooks
817
// when the synthetic event subscription is detached.
818
subscription._handle.detach();
820
if (subscription._timer) {
821
subscription._timer.cancel();
825
// Additional methods can be added to support the lifecycle methods
826
_clear: function (subscription) {
827
subscription._counter = 0;
828
subscription._timer = null;
835
<p>After the synthetic event is defined, it is available for every Node and
836
NodeList to subscribe to.</p>
838
<pre class="code prettyprint">Y.one('#hellokitty').on('tripleclick', omgYayCantClickEnough);</pre>
841
<p>There is additional configuration to <a href="synths.html">add support for
842
<code>delegate()</code> or extra subscription arguments</a>, but often very little extra
845
<h2 id="troubleshootingfaq">Troubleshooting/FAQ</h2>
848
<li><a href="#function-reference">My callback is executing at the wrong time. What's going on?</a></li>
849
<li><a href="#wrong-this">I'm getting an error in my callback that "(some object) has no method (someMethodOnMyObject)". What am I missing?</a></li>
850
<li><a href="#which-events">What events can I subscribe to?</a></li>
851
<li><a href="#why-on-no-chain">Why isn't on() chainable?</a></li>
852
<li><a href="#y-on-vs-node-on">Why would I use <code>Y.on()</code> or <code>Y.delegate()</code> instead of <code>node.on()</code> and <code>node.delegate()</code>?</a></li>
853
<li><a href="#after">EventTarget also provides an <code>after()</code> method. How does that work for DOM events?</a></li>
854
<li><a href="#nodelist-this">When I subscribe to an event from a NodeList, <code>this</code> is the NodeList, not the individual Node. What's up with that?</a></li>
855
<li><a href="#nodelist-delegate">Where is <code>nodelist.delegate()</code>?</a></li>
856
<!--li><a href="#">What works and what doesn't on mobile browsers?</a></li-->
859
<h4 id="function-reference">My callback is executing at the wrong time. What's going on?</h4>
861
<p>It's likely that you've included parenthese in the subscription.</p>
862
<pre class="code prettyprint">// WRONG
863
node.on('click', someFunction());
864
node.on('click', myObject.someFunction());
867
node.on('click', someFunction);
868
node.on('click', myObject.someFunction, myObject);</pre>
872
Including the parens makes the function execute immediately, and pass the
873
return value from the function to <code>node.on('click', [RETURN VALUE])</code>. To
874
pass a function around, just omit the parens.
877
<h4 id="wrong-this">I'm getting an error in my callback that "<code>(some object) has no method (someMethodOnMyObject)</code>". What am I missing?</h4>
880
You may be passing an object method to <code>on()</code>, but forgot to include
881
<a href="#extended-signature">the <code>this</code> object override parameter</a> in
886
Another option to make sure object methods are called with the correct
887
<code>this</code> object is to use
888
<a href="http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_bind">`Y.bind(obj.method,
890
<a href="http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_rbind">`Y.rbind(obj.method,
894
<pre class="code prettyprint">// WRONG
895
node.on('click', myObj.method);
898
node.on('click', myObj.method, myObj);
900
// RIGHT (alternate)
901
node.on('click', Y.rbind(obj.method, obj));</pre>
904
<h4 id="which-events">What events can I subscribe to?</h4>
907
It depends what modules you've included. Check out the
908
<a href="#event-whitelist">whitelisted events table</a>.
911
<h4 id="why-on-no-chain">Why isn't on() chainable?</h4>
914
After much deliberation, the YUI team decided that returning a subscription
915
handle was preferable to chaining in order to better support clean event
916
detaching across the various scenarios that DOM and custom events are used.
919
In any sizable application, managing event subscriptions becomes
920
increasingly important, and detaching events must be done with precision.
921
Because YUI allows duplicate subscriptions, any host-based detach method
922
will necessarily be less than 100% reliable with respect to avoiding
923
removal of subscriptions made by other parts of the system.
926
Otherwise, it's common to subscribe to events with anonymous functions,
927
which makes it impossible to detach the specific subscription by signature
928
because you don't have a function reference to use to identify the specific
929
subscription to remove. Subscription categories can be used, but
930
<a href="#remove-by-category">are also less precise</a> than
931
dealing with a specific subscription object.
934
<h4 id="y-on-vs-node-on">Why would I use <code>Y.on()</code> or <code>Y.delegate()</code> instead of <code>node.on()</code> and <code>node.delegate()</code>?</h4>
937
It's <a href="#y-on">largely a stylistic preference</a>, but there are some
938
technical differences when passing a selector string as a the third
939
argument to <code>Y.on()</code> or <code>Y.delegate()</code> (ala
940
<code>Y.on('click', callback, '#some select.or-string')</code>.
946
<code>Y.on()</code> uses the
947
<a href="http://yuilibrary.com/yui/docs/api/classes/Selector.html">Selector engine</a>
948
directly rather than calling through <code>Y.all(...)</code>.
951
The benefit here is that the Node and NodeList constructors add the
952
slightest bit of overhead to the subscription process.
956
When passing a selector that matches multiple elements, the <code>this</code> in
957
the callback will be the individual Node, not a
958
<a href="#nodelist-this">NodeList wrapping all matched elements</a>.
962
If called before the elements matching the selector are attached to
963
the DOM, it will poll for a few seconds and automatically attach
964
the subscription when the first matching element is found.
967
Note, if using a selector that matches multiple elements, the poll
968
will attach the subscription the first time Selector finds a match.
969
This <em>may not include all the elements</em> because either the
970
DOM is not fully updated yet, or the code that adds the matching
971
elements may happen in batches.
973
<p>In practice, it is best to avoid reliance on this behavior.</p>
977
<h4 id="after"><code>EventTarget</code> also provides an <code>after()</code> method. How does that work for DOM events?</h4>
980
<code>node.after(...)</code> is equivalent to <code>node.on(...)</code>. The DOM doesn't expose
981
an "after" moment to hook into.
984
<h4 id="nodelist-this">When I subscribe to an event from a NodeList, <code>this</code> is the NodeList, not the individual Node. What's up with that?</h4>
987
In the callback, <code>e.currentTarget</code> will always refer to the individual Node.
991
<pre class="code prettyprint">Y.all('#some select.or-string').on('click', function (e) {
992
// how do I reference the NodeList?
997
you can't reference the NodeList captured by <code>Y.all()</code> without calling
998
<code>Y.all()</code> again, but that results in unnecessary overhead, and may match
999
different elements in the subsequent call.
1003
In general, you should avoid <code>nodelist.on()</code> anyway,
1004
<a href="#delegation">in favor of event delegation</a>.
1007
<h4 id="nodelist-delegate">Where is <code>nodelist.delegate()</code>?</h4>
1010
The point of delegation is to reduce the number of subscriptions being made.
1011
<code>nodelist.delegate()</code> would be philosophically at odds with that. Either
1012
call <code>node.delegate()</code> from an element higher up the DOM tree, or <em>if
1013
you must</em> delegate the same event and callback from multiple
1017
<pre class="code prettyprint">nodelist.each(function (node) {
1018
node.delegate('click', callback, '.not-recommended');
1022
<h2 id="event-whitelist">Appendix A: Whitelisted DOM events</h2>
1038
<td>beforeunload</td>
1062
<td>contextmenu</td>
1070
<td>DOMMouseScroll</td>
1150
<td>mousemultiwheel</td>
1170
<td>orientationchange</td>
1186
<td>selectstart</td>
1207
<td>DOMActivate</td>
1208
<td>node-event-html5</td>
1211
<td>DOMContentLoaded</td>
1212
<td>node-event-html5</td>
1216
<td>node-event-html5</td>
1219
<td>beforeprint</td>
1220
<td>node-event-html5</td>
1224
<td>node-event-html5</td>
1227
<td>canplaythrough</td>
1228
<td>node-event-html5</td>
1231
<td>durationchange</td>
1232
<td>node-event-html5</td>
1236
<td>node-event-html5</td>
1240
<td>node-event-html5</td>
1244
<td>node-event-html5</td>
1248
<td>node-event-html5</td>
1252
<td>node-event-html5</td>
1256
<td>node-event-html5</td>
1260
<td>node-event-html5</td>
1263
<td>loadedmetadata</td>
1264
<td>node-event-html5</td>
1268
<td>node-event-html5</td>
1272
<td>node-event-html5</td>
1276
<td>node-event-html5</td>
1280
<td>node-event-html5</td>
1284
<td>node-event-html5</td>
1288
<td>node-event-html5</td>
1292
<td>node-event-html5</td>
1296
<td>node-event-html5</td>
1300
<td>node-event-html5</td>
1304
<td>node-event-html5 or history</td>
1308
<td>node-event-html5</td>
1312
<td>node-event-html5</td>
1315
<td>readystatechange</td>
1316
<td>node-event-html5</td>
1320
<td>node-event-html5</td>
1324
<td>node-event-html5</td>
1328
<td>node-event-html5</td>
1332
<td>node-event-html5</td>
1336
<td>node-event-html5</td>
1340
<td>node-event-html5</td>
1344
<td>node-event-html5</td>
1348
<td>node-event-html5</td>
1351
<td>volumechange</td>
1352
<td>node-event-html5</td>
1356
<td>node-event-html5</td>
1361
<td>event-touch</td>
1365
<td>event-touch</td>
1369
<td>event-touch</td>
1372
<td>touchcancel</td>
1373
<td>event-touch</td>
1376
<td>gesturestart</td>
1377
<td>event-touch</td>
1380
<td>gesturechange</td>
1381
<td>event-touch</td>
1385
<td>event-touch</td>
1389
<td>transitionend or webkitTransitionEnd</td>
1390
<td>transition-native</td>
1396
YUI({ filter: 'raw' }).use('selector-css3', 'datatable-sort', function (Y) {
1398
node = Y.one('#events');
1400
node.all('td:nth-of-type(1)').each(function (node, i) {
1402
Event: node.get('text'),
1403
"Added By": node.next().get('text')
1407
node.empty().addClass('yui3-skin-sam');
1408
new Y.DataTable.Base({
1410
{ key: 'Event', sortable: true },
1411
{ key: 'Added By', sortable: true }
1414
}).plug(Y.Plugin.DataTableSort).render(node);
1419
<h4 id="adding-to-the-dom-event-whitelist">Adding to the DOM event whitelist</h4>
1421
<p>If you need to use an event that isn't included in this list, and not
1422
supplied by a synthetic event, you can expand the whitelist by adding the event
1423
names to the <code>Y.Node.DOM_EVENTS</code> object.</p>
1425
<pre class="code prettyprint">// Allow for subscription to some mostly cross-browser mutation events
1426
Y.mix(Y.Node.DOM_EVENTS, {
1427
DOMNodeInserted: true,
1428
DOMNodeRemoved: true,
1429
DOMCharacterDataModified: true
1433
<h2 id="facade-properties">Appendix B: EventFacade properties and methods</h2>
1435
<h4 id="methods">Methods</h4>
1437
<dt><code>e.preventDefault()</code></dt>
1439
Prevents the default action associated with the event. E.g. page
1440
navigation from an <a>nchor <code>click</code> or form submission and
1441
page reload from a %lt;form> <code>submit</code>.
1443
<dt><code>e.stopPropagation()</code></dt>
1445
Stops the event from bubbling further up the DOM tree. This does
1446
not prevent the default action if there is one. Subsequent event
1447
subscribers will be executed.
1449
<dt><code>e.stopImmediatePropagation()</code></dt>
1451
Stops the event from bubbling further up the DOM tree. This does
1452
not prevent the default action if there is one. Subsequent event
1453
subscribers will NOT be executed.
1455
<dt><code>e.halt( [immediate=false] )</code></dt>
1457
Alias for <code>e.preventDefault(); e.stopPropagation();</code> or
1458
<code>e.preventDefault(); e.stopImmediatePropagation();</code>, depending on
1459
the <em>immediate</em> parameter.
1463
<h4 id="basics">Basics</h4>
1465
<dt><code>e.type</code></dt>
1467
The name of the event. E.g. "click", "keyup", or "load".
1470
<dt><code>e.target</code></dt>
1472
The Node instance that originated the event (see <a
1473
href="delegation.html">the description of event delegation</a> for
1476
<dt><code>e.currentTarget</code></dt>
1478
The Node instance that subscribed to the event. In the case of
1479
subscriptions from NodeLists, this is still the individual Node
1480
instance (see <a href="#nodelist-this">When I subscribe to an event
1481
from a NodeList, <code>this</code> is the NodeList...</a>).
1483
<dt><code>e.relatedTarget</code></dt>
1485
For <code>mouseover</code> events, this will be the Node instance of where the
1486
mouse travelled <em>from</em>. For <code>mouseout</code>, it will be the Node
1487
that the mouse travelled <em>to</em>.
1491
<h4 id="keyboard-event-properties">Keyboard event properties</h4>
1492
<dt><code>e.keyCode</code></dt>
1494
The unicode value of a non-character key in a <code>keypress</code> event or
1495
any key in <code>keydown</code> or <code>keyup</code>. See <a
1496
href="https://developer.mozilla.org/en/DOM/event.keyCode">event.keyCode
1499
<dt><code>e.charCode</code></dt>
1501
The Unicode value of a character key pressed during a keypress
1503
href="https://developer.mozilla.org/en/DOM/event.charCode">event.charCode
1506
<dt><code>e.shiftKey</code></dt>
1508
<code>true</code> if the shift key was depressed during a key event.
1510
<dt><code>e.ctrlKey</code></dt>
1512
<code>true</code> if the control key was depressed during a key event.
1514
<dt><code>e.altKey</code></dt>
1516
<code>true</code> if the alt/option key was depressed during a key event.
1518
<dt><code>e.metaKey</code></dt>
1520
<code>true</code> if the "Windows" key on PCs or command key on Macs was
1521
depressed during a key event.
1525
<h4 id="mouse-event-properties">Mouse event properties</h4>
1526
<dt><code>e.button</code></dt>
1528
For <code>mouseup</code> events (<em>NOT <code>click</code> events</em>), indicates
1529
which mouse button is pressed.<br>
1530
<code>1</code> = left click, <code>2</code> = middle click, <code>3</code> = right click.
1532
<dt><code>e.which</code></dt>
1537
<dt><code>e.pageX</code></dt>
1539
The horizontal coordinate of the event relative to whole document.
1541
<dt><code>e.pageY</code></dt>
1543
The vertical coordinate of the event relative to whole document.
1545
<dt><code>e.clientX</code></dt>
1547
The horizontal coordinate of the event relative to viewport,
1548
regardless of scrolling.
1550
<dt><code>e.clientY</code></dt>
1552
The vertical coordinate of the event relative to viewport,
1553
regardless of scrolling.
1556
<dt>[<code>e.wheelDelta</code>]</dt>
1558
For <code>mousewheel</code> or <code>DOMMouseScroll</code> events, the pixel distance of
1563
<h4 id="touch-event-properties">Touch event properties</h4>
1565
<dt>[<code>e.touches</code>]</dt>
1568
An array of <code>Touch</code> objects, where each <code>Touch</code> object represents a finger
1569
currently touching the surface (regardless of the target of the current event).
1570
For example, if you have two fingers on the surface, this array would have two
1571
<code>Touch</code> objects, one for each finger.
1575
The common set of properties currently on a <code>Touch</code> object, which can be
1576
relied up across environments, are <code>target</code>, <code>clientX</code>, <code>clientY</code>, <code>pageX</code>,
1577
<code>pageY</code>, <code>screenX</code>, <code>screenY</code> and <code>identifier</code>.
1580
<dt>[<code>e.targetTouches</code>]</dt>
1583
An array of <code>Touch</code> objects for every point of contact that is touching the
1584
surface, and started on the element that is the target of the current event.
1587
<dt>[<code>e.changedTouches</code>]</dt>
1590
An array of <code>Touch</code> objects representing all touches that changed in this event.
1594
This property is most useful in <code>touchEnd</code> events, to identify the set of touches
1595
which were removed from the surface, which resulted in the firing of the event.
1600
<h4 id="gesture-event-properties-currently-ios-specific">Gesture event properties (currently iOS specific)</h4>
1601
<p>These properties are unique to Webkit on iOS currently, and are provided on the event facade when listening for the iOS <code>gesturestart</code>, <code>gesturechange</code> and <code>gestureend</code> multi-touch events.</p>
1603
<dt>[<code>e.scale</code>]</dt>
1605
See Apple's documentation for <a href="http://developer.apple.com/library/safari/documentation/UserExperience/Reference/GestureEventClassReference/GestureEvent/GestureEvent.html#//apple_ref/javascript/instp/GestureEvent/scale">scale</a>.
1607
<dt>[<code>e.rotation</code>]</dt>
1609
See Apple's documentation for <a href="http://developer.apple.com/library/safari/documentation/UserExperience/Reference/GestureEventClassReference/GestureEvent/GestureEvent.html#//apple_ref/javascript/instp/GestureEvent/rotation">rotation</a>.
1613
<p>See the <a href="http://www.w3.org/TR/touch-events/">W3C Touch Events Specification</a>, derived from the Webkit model, for more details.</p>
1615
<p>Synthetic events may add or modify event facade properties. These should be included in the documentation for the specific synthetic event.</p>
1617
<p>For more details, check out the <a
1618
href="https://developer.mozilla.org/en/DOM/event#Properties">MDC
1619
documentation</a>.</p>
1623
<div id="sidebar" class="yui3-u">
1625
<div id="toc" class="sidebox">
1627
<h2 class="no-toc">Table of Contents</h2>
1633
<a href="#getting-started">Getting Started</a>
1636
<a href="#the-basics">The Basics</a>
1639
<a href="#listening-for-events">Listening for events</a>
1642
<a href="#the-callback-and-the-event-object">The Callback and the Event Object</a>
1645
<a href="#epreventdefault-and-estoppropagation"><code>e.preventDefault()</code> and <code>e.stopPropagation()</code></a>
1648
<a href="#detaching-subscriptions">Detaching subscriptions</a>
1653
<a href="#modules">What to <code>use()</code></a>
1656
<a href="#delegation">Event Delegation</a>
1659
<a href="#more">More Event API Goodness</a>
1662
<a href="#y-on">Subscribe from <code>Y</code></a>
1665
<a href="#once">One time subscriptions</a>
1668
<a href="#grouping-subscriptions">Grouping subscriptions</a>
1671
<a href="#extended-signature">Binding <code>this</code> and additional callback arguments</a>
1674
<a href="#detach-methods">More ways to clean up subscriptions</a>
1679
<a href="#simulate">Simulate browser events</a>
1682
<a href="#synthetic-events">Synthetic Events</a>
1685
<a href="#creating-dom-events">Creating DOM events</a>
1690
<a href="#troubleshootingfaq">Troubleshooting/FAQ</a>
1693
<a href="#function-reference">My callback is executing at the wrong time. What's going on?</a>
1696
<a href="#wrong-this">I'm getting an error in my callback that "<code>(some object) has no method (someMethodOnMyObject)</code>". What am I missing?</a>
1699
<a href="#which-events">What events can I subscribe to?</a>
1702
<a href="#why-on-no-chain">Why isn't on() chainable?</a>
1705
<a href="#y-on-vs-node-on">Why would I use <code>Y.on()</code> or <code>Y.delegate()</code> instead of <code>node.on()</code> and <code>node.delegate()</code>?</a>
1708
<a href="#after"><code>EventTarget</code> also provides an <code>after()</code> method. How does that work for DOM events?</a>
1711
<a href="#nodelist-this">When I subscribe to an event from a NodeList, <code>this</code> is the NodeList, not the individual Node. What's up with that?</a>
1714
<a href="#nodelist-delegate">Where is <code>nodelist.delegate()</code>?</a>
1719
<a href="#event-whitelist">Appendix A: Whitelisted DOM events</a>
1722
<a href="#adding-to-the-dom-event-whitelist">Adding to the DOM event whitelist</a>
1727
<a href="#facade-properties">Appendix B: EventFacade properties and methods</a>
1730
<a href="#methods">Methods</a>
1733
<a href="#basics">Basics</a>
1736
<a href="#keyboard-event-properties">Keyboard event properties</a>
1739
<a href="#mouse-event-properties">Mouse event properties</a>
1742
<a href="#touch-event-properties">Touch event properties</a>
1745
<a href="#gesture-event-properties-currently-ios-specific">Gesture event properties (currently iOS specific)</a>
1755
<div class="sidebox">
1757
<h2 class="no-toc">Examples</h2>
1761
<ul class="examples">
1764
<li data-description="Use the Event Utility to attach simple DOM event handlers.">
1765
<a href="basic-example.html">Simple DOM Events</a>
1770
<li data-description="Using the synthetic event API to create a DOM event that fires in response to arrow keys being pressed.">
1771
<a href="synth-example.html">Creating an Arrow Event for DOM Subscription</a>
1776
<li data-description="Supporting cross-device swipe gestures, using the event-move gesture events">
1777
<a href="swipe-example.html">Supporting A Swipe Left Gesture</a>
1797
<div class="sidebox">
1799
<h2 class="no-toc">Examples That Use This Component</h2>
1803
<ul class="examples">
1812
<li data-description="Shows how to extend the base widget class, to create your own Widgets.">
1813
<a href="../widget/widget-extend.html">Extending the Base Widget Class</a>
1818
<li data-description="Creating an accessible menu button using the Focus Manager Node Plugin, Event's delegation support and mouseenter event, along with the Overlay widget and Node's support for the WAI-ARIA Roles and States.">
1819
<a href="../node-focusmanager/node-focusmanager-3.html">Accessible Menu Button</a>
1824
<li data-description="Use IO to request data over HTTP.">
1825
<a href="../io/get.html">HTTP GET to request data</a>
1830
<li data-description="Example Photo Browser application.">
1831
<a href="../dd/photo-browser.html">Photo Browser</a>
1836
<li data-description="Portal style example using Drag & Drop Event Bubbling and Animation.">
1837
<a href="../dd/portal-drag.html">Portal Style Example</a>
1849
<script src="../assets/vendor/prettify/prettify-min.js"></script>
1850
<script>prettyPrint();</script>