--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui_3.10.3/docs/event/delegation.html Tue Jul 16 14:29:46 2013 +0200
@@ -0,0 +1,441 @@
+<!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>