e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<div class="intro">
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <p>The `event-base` module includes three special events that can be used to execute code as soon as the DOM, or certain elements in the DOM tree, are ready to be scripted.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <p>Because all of these events are designed to target elements that aren't present or parsed yet, <strong>you must use `Y.on(...)` to subscribe to them</strong>. `Y.one('#notHereYet')` will return `null`, and you can't do much with `null`.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <p>Be sure to read <a href="#caveat">the final note on this page</a> about performance.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</div>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<h2 id="domready">`domready`</h2>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith```
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<!doctype html>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<html>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<head>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <meta charset="utf-8">
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <title>domready</title>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <script src="...yui-min.js"></script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith YUI().use('event-base', function (Y) {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith var notHereYet = Y.one('#readygo'); // null
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith Y.on('domready', function () {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith Y.one('#readygo').on('click', function () {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith Y.log('This works fine, before the images are loaded');
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith });
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith });
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith });
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith </script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</head>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<body>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith ... lots of markup including images and stuff
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <button id="readygo">Go!</button>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</body>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</html>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith```
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<p>Modern browsers support an event that signals when the markup has been
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smithcompletely parsed and the DOM tree is built. This event happens before the
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smithwindow's `load` event, which fires when all images and other resources have
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smithbeen fetched. For setting up event subscriptions and core page interactivity,
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smithit's usually enough that all DOM elements are available, regardless of their
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smithloading state.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<p>The `domready` event abstracts over the patchwork necessary for browsers without a native "domready" event.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<p>Note the subscription signature does not include a target, only the event name and callback.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<h2 id="contentready">`contentready`</h2>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith```
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<!doctype html>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<html>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<head>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <meta charset="utf-8">
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <title>contentready</title>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <script src="...yui-min.js"></script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith YUI().use('event-base', function (Y) {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith var notHereYet = Y.one('#list'); // null
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith function addItem() {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith // children of #todo are in the DOM tree
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith this.one('ul').append('<li>This will be four</li>');
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith }
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith Y.on('contentready', addItem, '#todo');
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith });
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith </script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</head>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<body>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith ... lots of markup including images and stuff
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <div id="todos">
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <ul>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <li>one</li>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <li>two</li>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <li>three</li>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith </ul>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith </div>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith ... more markup
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</body>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</html>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith```
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<p>You may want to script some nodes that are in the middle of the page markup inside a specific containing element. You just need to know that the container and its children have been parsed from markup and added to the DOM tree. But you don't want to wait for the entire DOM tree to finish. That's what the `contentready` event is for.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<p>YUI will check the DOM periodically, looking for an element matching the selector passed as the the third argument. When it finds one and can verify that that element's children are also in the DOM tree, it will execute the callback.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<p>Callbacks will be executed with `this` assigned to the Node matching the selector.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<h2 id="available">`available`</h2>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith```
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<!doctype html>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<html>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<head>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <meta charset="utf-8">
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <title>available</title>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <script src="...yui-min.js"></script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith YUI().use('event-hover', function (Y) {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith var notHereYet = Y.one('#highlight-me'); // null
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith function over() {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith this.addClass("over");
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith }
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith function out() {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith this.removeClass("over");
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith }
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith function addSubscribers() {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith this.on('hover', over, out);
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith }
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith Y.on('available', addSubscribers, '#highlight-me');
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith });
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith </script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</head>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<body>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith ... lots of markup including images and stuff
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith <div id="highlight-me">
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith ... stuff that doesn't need to be ready
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith </div>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith ... more markup
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</body>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</html>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith```
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<p>The `available` event is almost identical to <a href="#contentready">`contentready`</a> except it does not wait for children of the matching element to be ready. If your code only needs to reference the targeted Node, not any of its children, use `available` instead of `contentready`.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<h2 id="caveat">Just put your &lt;script&gt; tags at the bottom</h2>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<p>You might not need to use any of these events, and maybe you shouldn't.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<p>It is always safe to script nodes defined in the markup above the JavaScript that references it. In practice, if you have the option, it is preferable to move &lt;script&gt; tags below the markup that it needs in place, and often it is best to simply <a href="http://developer.yahoo.com/blogs/ydn/posts/2007/07/high_performanc_5/">move scripts to the bottom of the page</a>.</p>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith```
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<div id="stuff-i-need">
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith ...
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</div>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith<script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith// Scripts below markup can access the DOM elements above
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke SmithYUI().use('node', function (Y) {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith Y.one('#stuff-i-need', function () {
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith Y.log('This will always work');
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith });
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith});
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith</script>
e9b01de77b1a53553e58caf4f0c5392735102fc1Luke Smith```