add some more custom config and put every thing in comment in the custom.yaml template
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Intro to Event Delegation</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>Intro to Event Delegation</h1>
<div class="yui3-g">
<div class="yui3-u-3-4">
<div id="main">
<div class="content"><style>
#todo-example {
margin-top: 2em;
max-width: 300px;
*width: 300px;
border: 2px solid #aaa;
padding: 10px;
}
#todo-example legend {
color: #888;
position: relative;
bottom: .4em;
font-size: 1.3em;
*position: auto;
}
#todo-example ol {
list-style: decimal;
padding-left: 0;
margin: 0 0 1em;
}
#todo-example li {
clear: right;
margin-left: 25px;
margin-right: 30px;
*margin-left: 0;
padding: 0;
}
#todo-example .delete-todo {
float: right;
position: relative;
right: -30px;
background: url(../assets/event/remove.png) no-repeat right;
border: 0 none;
width: 30px;
overflow: hidden;
text-indent: 30px;
opacity: 0.5;
*filter: alpha(opacity=50);
}
#todo-example input {
width: 220px;
border: 1px solid #aaa;
xbackground: url(../assets/event/add.png) no-repeat right;
padding: 5px 0 5px 5px;
}
</style>
<h2 id="understanding-the-problem">Understanding the problem</h2>
<p>Consider the following Todo List widget:</p>
<fieldset id="todo-example">
<legend>Todo List</legend>
<ol>
<li><button class="delete-todo" title="remove">remove</button>Read YUI documentation</li>
<li><button class="delete-todo" title="remove">remove</button>Build awesome web app</li>
<li><button class="delete-todo" title="remove">remove</button>Profit!</li>
</ol>
<input id="todo"> <button id="add-todo" type="button">add</button>
</fieldset>
<script>
YUI().use('node-event-delegate', 'event-key', function (Y) {
var todoList = Y.one('#todo-example ol'),
newTask = Y.one('#todo');
todoList.delegate('click', function () {
this.ancestor('li').remove();
}, 'button');
function addTodo() {
todoList.append(
'<li><button class="delete-todo">remove</button>' +
newTask.get('value') +
'</li>');
newTask.set('value', '');
}
Y.one('#add-todo').on('click', addTodo);
newTask.on('key', addTodo, 'enter');
});
</script>
<p>All tasks are given a "remove" button. When new tasks are added, they
should get a remove button that removes that task. Here's the markup for
this:</p>
<pre class="code prettyprint"><fieldset id="todo-example">
<legend>Todo List</legend>
<ol>
<li><button class="delete-todo">remove</button>Read YUI documentation</li>
<li><button class="delete-todo">remove</button>Build awesome web app</li>
<li><button class="delete-todo">remove</button>Profit!</li>
</ol>
<input id="todo"> <button id="add-todo" type="button">add</button>
</fieldset></pre>
<p>In the old days, you would have four click subscriptions:</p>
<ol>
<li>The remove button for #1</li>
<li>The remove button for #2</li>
<li>The remove button for #3</li>
<li>The add button for creating new tasks</li>
</ol>
<p>When a user types in a new task and clicks the <em>add</em> button, a new
<li> and corresponding <button> are created, and a fifth click
subscription is added, one for the new button. The callback for the remove
buttons could be unique for each button, or a generic function that determined
which item to remove based on some other info from the event or button.</p>
<p>When a user clicks on one of the remove buttons, the item is removed. The
associated click event subscription is left in the system, taking up memory.
So to solve this, maybe the event subscription is detached before the item is
removed. Now there are four initial subscriptions and additional logic to
properly detach subscriptions before items are removed.</p>
<p>Over time, the number of items on the todo list grows, and so the number of
subscriptions in the system, and thus memory consumed, grows with it.
Additionally, if at some point, the entire list needs to be cleared, that's a
lot of subscriptions to detach before it's ok to flush the list's
<code>innerHTML</code>.</p>
<h2 id="what-is-event-delegation">What is event delegation?</h2>
<p>Event delegation is a way to reduce the number of subscriptions used to
support this system. In the example case, only two click subscriptions are
needed: one for the add button, and one for every remove button click. The
second one is the <em>delegated subscription</em>. Here's how to think about
it:</p>
<p>The key to event delegation is understanding that a click on a remove button
is also a click on</p>
<ul>
<li>the list item that the button is in</li>
<li>the list itself</li>
<li>the <fieldset> that the list is in</li>
<li>etc up to the <body> and finally the <code>document</code><a
href="#footnote1">[1]</a></li>
</ul>
<p>Instead of subscribing to the button's "click" event, <em>you can subscribe
to the list's "click" event</em><a href="#footnote2">[2]</a>.</p>
<h2 id="you-clicked-somewhere-but-where">You clicked somewhere, but <em>where</em>?</h2>
<p>When you click anywhere on the document, the browser dispatches a click
event that is assigned an <code>e.target</code> property corresponding to <em>the element
that triggered the event</em>. For example, if you click on "Profit!", the
event originated from the <li> with "Profit!" in it, so <code>e.target</code> will
be that <li> element<a href="#footnote2">[3]</a>.</p>
<p>With these two bits of information, we can create a single click
subscription to respond to every button click in the Todo list.</p>
<pre class="code prettyprint">function handleClick(e) {
// look at e.target
}
Y.one('#todo-example ol').on('click', handleClick);</pre>
<p>Now since there are no subscriptions tied directly to the individual
buttons, we can add new items to the list without needing to add more
subscriptions. Similarly, we can remove items or even clear the list's
<code>innerHTML</code> without needing to detach subscriptions because there aren't any
subscriptions inside the list to clear.</p>
<h2 id="more-work-in-the-event-subscriber">More work in the event subscriber</h2>
<p>Since any click inside the list is now triggering the event subscriber, it
will be executed for button clicks, but also for clicks on the task item's text
(e.g. "Profit!"). To make sure this click happened on a button, we need to
inspect <code>e.target</code> to make sure it is a button.</p>
<pre class="code prettyprint">function handleClick(e) {
if (e.target.get('tagName').toLowerCase() === 'button') {
// remove the item
}
}</pre>
<p>This can start to get tricky when you're triggering on an element that can
contain children. For example, if there were no buttons, but instead you
wanted to remove items just by clicking on the <li>, you'd need to check
if <code>e.target</code> was an <li>. But if it's not, you have to look at
<code>e.target</code>'s <code>parentNode</code> and potentially that node's <code>parentNode</code> and so on,
because <code>e.target</code> will always refer to the most specific element that received
the click. This can amount to a lot of filtering code wrapping the item
removal logic, which hinders the readability of your app.</p>
<h2 id="let-nodedelegate-do-the-work-for-you">Let <code>node.delegate(...)</code> do the work for you</h2>
<p>This is where <a href="../event/#event-delegation"><code>node.delegate(...)</code></a>
comes in. <code>node.delegate(...)</code> boils down the filtering logic to a css
selector, passed as the third argument. The subscribed callback will only
execute if the event originated from an element that matches (or is contained
in an element that matches) this css selector. This allows the code to power
our Todo widget to look like this:</p>
<pre class="code prettyprint">YUI().use('node-event-delegate', 'event-key', function (Y) {
var todoList = Y.one('#todo-example ol'),
newTask = Y.one('#todo');
// clicks inside the todo list on a <button> element will cause the
// button's containing <li> to be removed
todoList.delegate('click', function () {
this.ancestor('li').remove();
}, 'button');
// Adding a new task is only appending a list item
function addTodo() {
todoList.append(
'<li><button class="delete-todo">remove</button>' +
newTask.get('value') +
'</li>');
newTask.set('value', '');
}
Y.one('#add-todo').on('click', addTodo);
newTask.on('key', addTodo, 'enter'); // enter also adds todo (see event-key)
});</pre>
<hr>
<h3 id="footnotes">Footnotes</h3>
<ol id="footnotes">
<li id="footnote1">If there are click subscriptions at multiple points in
the DOM heirarchy, they will be executed in order from most specific (the
button) to least specific (document) unless <code>e.stopPropagation()</code> is
called along the line. This will prevent subscriptions from elements higher
up the parent axis from executing.</li>
<li id="footnote2">We're using the "click" event here, but this all applies
to other events as well.</li>
<li id="footnote3">Actually the event originated from the text node inside
the <li>, but IE reports the origin (the <code>srcElement</code> in IE) as the
<li>, which is probably what developers want, anyway. YUI fixes
<code>e.target</code> to bet the element for browsers that report it as the text
node.</li>
</ol>
</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="#understanding-the-problem">Understanding the problem</a>
</li>
<li>
<a href="#what-is-event-delegation">What is event delegation?</a>
</li>
<li>
<a href="#you-clicked-somewhere-but-where">You clicked somewhere, but <em>where</em>?</a>
</li>
<li>
<a href="#more-work-in-the-event-subscriber">More work in the event subscriber</a>
</li>
<li>
<a href="#let-nodedelegate-do-the-work-for-you">Let <code>node.delegate(...)</code> do the work for you</a>
<ul class="toc">
<li>
<a href="#footnotes">Footnotes</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="Use the Event Utility to attach simple DOM event handlers.">
<a href="basic-example.html">Simple DOM Events</a>
</li>
<li data-description="Using the synthetic event API to create a DOM event that fires in response to arrow keys being pressed.">
<a href="synth-example.html">Creating an Arrow Event for DOM Subscription</a>
</li>
<li data-description="Supporting cross-device swipe gestures, using the event-move gesture events">
<a href="swipe-example.html">Supporting A Swipe Left Gesture</a>
</li>
</ul>
</div>
</div>
<div class="sidebox">
<div class="hd">
<h2 class="no-toc">Examples That Use This Component</h2>
</div>
<div class="bd">
<ul class="examples">
<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.">
<a href="../node-focusmanager/node-focusmanager-button.html">Accessible Menu Button</a>
</li>
<li data-description="Shows how to extend the base widget class, to create your own Widgets.">
<a href="../widget/widget-extend.html">Extending the Base Widget Class</a>
</li>
<li data-description="Example Photo Browser application.">
<a href="../dd/photo-browser.html">Photo Browser</a>
</li>
<li data-description="Portal style example using Drag & Drop Event Bubbling and Animation.">
<a href="../dd/portal-drag.html">Portal Style Example</a>
</li>
<li data-description="Use IO to request data over HTTP.">
<a href="../io/get.html">HTTP GET to request data</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',
name: 'event',
title: 'Intro to Event Delegation',
newWindow: '',
auto: false
};
YUI.Env.Tests.examples.push('basic-example');
YUI.Env.Tests.examples.push('synth-example');
YUI.Env.Tests.examples.push('swipe-example');
YUI.Env.Tests.examples.push('node-focusmanager-button');
YUI.Env.Tests.examples.push('widget-extend');
YUI.Env.Tests.examples.push('photo-browser');
YUI.Env.Tests.examples.push('portal-drag');
YUI.Env.Tests.examples.push('get');
</script>
<script src="../assets/yui/test-runner.js"></script>
</body>
</html>