Note: This is the YUI 3.x site. Looking for the YUI 2.x site?

YUI 3: The Event Utility

Event Utility

YUI's Event Utility facilitates the creation of event-driven applications in the browser by giving you a simplified interface for responding to DOM events. The Event Utility package also includes the Custom Event object; Custom Events allow you to publish the interesting moments or events in your own code so that other components on the page can subscribe to those events and respond to them.

The Event Utility package provides the following features:

  • DOM event handling
  • Automatic deferral of handler attachment for elements that are not yet available
  • Automatic scope correction, optional scope assignment
  • An event facade that normalizes browser differences
  • Automatic DOM event listener cleanup
  • Simulation of events in all A-grade browsers
  • Pageload timing events (available and contentready at the element level and domready at the DOM level)
  • Keylistener utility that responds only when certain key combinations are detected.
  • Focus/blur event abstraction layer that provides the ability to use deletegated listening techniques with these events.
  • Custom events that are bubbleable, cancelable, and have intrinsic AOP qualities

Getting Started

Include Dependencies

The easiest way to include the source files for event and its dependencies is to add the YUI seed file to your page, using the following script tag, and allow the YUI instance to download any additional files which may be required:

The YUI instance will automatically pull down event's source files and any missing dependencies when the event module is used. This helps you avoid having to manually manage the list of files needed on your page to support multiple components while also optimizing your initial page weight by loading files only when they are required.

If you do want to include file dependencies manually on your page, the YUI Dependency Configurator can be used to determine the list of files you need to include in order to use event.

The YUI Instance

Once you have the YUI seed file on your page (yui-min.js), you can create a new YUI instance for your application to use and populate it with the modules you need, specified as the first set of arguments to the use method:

The last argument passed to use is a callback function. The callback function will be invoked as soon as the YUI instance is done downloading any required files missing from your page. Once those files are loaded, your local YUI instance will be supplemented with the classes which make up the event module and any modules it depends on. A reference to the populated YUI instance (Y) is passed back to your callback function. Within your callback, then, you can start writing your application code based on your own custom instance of YUI.

For more information on creating instances of YUI and the use method, see the YUI Global object documentation.

DOM Events

To attach an event handler to the DOM, simply define your event handler and pass the event handler to the Event Utility along with a reference to the event for which you want to listen and the element to which you want attach the handler:

These lines of code:

  • Create a YUI instance — Event Utility relies on node, so YUI().use("node") will load everything required to use the utility.
  • Define a callback function, handleClick(e), to handle the specified event.
  • Call the on method on the YUI instance (Y) to bind an event to the DOM element. The on method requires three arguments: the event to bind ("click", as a string), the callback function (handleClick), and the element the event is bound to ("#foo", assuming an element whose ID attribute is foo).

Because we are identifying the element by its HTML ID ("#foo" as a string) rather than by passing in a Node instance or a direct HTMLElement reference, it is possible to refer to an element that does not yet exist on the page. The Event Utility attempts to find the DOM element by its id value; should it fail to find the element immediately, it continues to seek the element for up to 15 seconds after the page has loaded. This "automatic deferral" enables you, in some cases, to write your event attachment code directly into your script rather than separating it out in a function that runs only after the page has loaded.

To attach an event handler to multiple elements, use CSS selector syntax (as above) that selects multiple elements, pass in multiple selector strings as an array, pass in an array of Node instances, or pass in an array of direct element references:

Using on: Controlling Context and Arguments

When you call Y.on, you have the following arguments to work with:

  1. Event name: This is the string reference to the DOM event to which you want to respond (e.g., "click" or "mouseover"). Developers often wonder where they can find a comprehensive list of DOM events that shows in which browsers each event is supported. As far as we know, no perfect list exists. Danny Goodman's DHTML: The Definitive Reference may have the most comprehensive information of this kind; PPK's Event Compatibility Table on quirksmode may have the best compatibility assessment online. The Event Utility does not place any constraints on the events for which you attach handlers; it will attempt to attach listeners for any event name you provide. It's your responsibility to make sure that the event you're using is one that is supported in the browsers for which you're developing.
  2. Handler: A reference to the function that should be called when the specified event takes place.
  3. Element(s): As noted above, this can be one or more elements referenced using selector syntax, Node instances, or direct element references.
  4. Context object: A reference to the object that will provide the context for the event handler — the object to which this will refer when the handler executes. If this is omitted, the context object will be a Node instance based on the target element.
  5. Argument 1 ... n: The fifth thru nth arguments passed to on will be passed to the event handler.

The following code shows these arguments in use. HTML:

Script:

When you run this code and click on "Item one" or "Item three", the following information will be sent to Y.log:

The final object logged, the arguments object, will contain three items: e (the event facade), "argumentOne" (string), and "argumentTwo" (string).

Legacy Methods: Event.addListener and Event.on

The Event Utility contains two legacy methods for attaching event listeners; these are located in the Event package and follow the syntax of the Event Utility from previous versions of YUI. If you are writing code using YUI 3.x, you should avoid using these methods and instead use the syntax described above.

Removing Events

There are three ways to remove an event listener:

  1. Add an event category prefix to the event type parameter, and pass this string to the YUI detach method.
  2. Call detach on the event's handle: The return value of on is an event handle object; that object contains a detach method that can be used to remove the event.
  3. Call the YUI detach method, passing in event type, handler, and element: detach is available as a method on your YUI instance and can be used when you don't have access to the event handle.

Sample code for each of these methods:

Event.purgeElement lets you remove all DOM event listeners that were registered via on from an element. Optionally, a specific type of listener can be specified. In addition, The element's children can also be purged.

Simulating Events

Simulated events are browser-created events that, most of the time, behave exactly as user-initated events. Events bubble as they normally would and event objects are created with properties containing data about the event (sometimes these properties are browser-specific, so it's recommended that you make use of the browser-equalizing methods of Y.Event to retrieve the appropriate values for properties such as target, relatedTarget, and charCode. All event handlers are called synchronously at each event target throughout the event's lifetime. Events are simulated using the Y.Event.simulate() method.

Mouse Events

There are seven mouse events that can be simulated using methods on Y.Event:

  • click
  • dblclick
  • mousedown
  • mouseup
  • mouseover
  • mouseout
  • mousemove

Each event is fired by calling Y.Event.simulate() and passing in three arguments: the element to fire the event on, the type of event to fire, and an optional object specifying additional information for the event. To simulate a click on the document's body element, for example, the following code can be used:

This code simulates a click with all of the default properties on the event object. To specify additional information, such as the Shift key being down, the second argument must be used and the exact DOM name for the event property specified (there is browser-normalizing logic that translates these into browser-specific properties when necessary):

In this updated example, a click event is fired on the document's body while simulating that the Shift key is down.

The extra properties to specify vary depending on the event being simulated and are limited to this list:

  • detail - Indicates the number of times a button was clicked (DOM-compliant browsers only).
  • screenX/screenY - coordinates of the mouse event in relation to the entire screen (DOM-compliant browsers only).
  • clientX/clientY - coordinates of the mouse event in relation to the browser client area.
  • ctrlKey/altKey/shiftKey/metaKey - the state of the Ctrl, Alt, Shift, and Meta keys, respectively (true for down, false for up).
  • button - the button being used for the event, 0 for left (default), 1 for right, 2 for center.
  • relatedTarget - the element the mouse moved from (during a mouseover event) or to (during a mouseout event).

Examples of the different methods and their extra properties:

Key Events

There are three key event simulations available using UserAction:

  • keyup
  • keydown
  • keypress

As with the mouse events, key events are simulated using Y.Event.simulate(). For keyup() and keydown(), the keyCode property must be specified; for keypress(), the charCode property must be included. In many cases, keyCode and charCode may be the same value to represent the same key (97, for instance, represents the "A" key as well as being the ASCII code for the letter "a"). For example:

Key events also support the ctrlKey, altKey, shiftKey, and metaKey event properties.

Note: Due to differences in browser implementations, key events may not be simulated in the same manner across all browsers. For instance, when simulating a keypress event on a textbox, only Firefox will update the textbox with the new character of the key that was simulated to be pressed. For other browsers, the events are still registered and all event handlers are called, however, the textbox display and value property are not updated. These differences should go away as browser support for simulated events improves in the future.

Safari 2.x Developers: Due to a bug in the Safari 2.x codebase, simulating a keydown event may cause the browser to crash. This issue has been resolved in Safari 3.x.

Using the available and contentready events (Formerly the onAvailable and onContentReady methods)

available lets you define a function that will execute as soon as an element is detected in the DOM. The intent is to reduce the occurrence of timing issues when rendering script and html inline. It is not meant to be used to define handlers for elements that may eventually be in the document; it is meant to be used to detect elements you are in the process of loading.

The argument signature for available is illustrated here:

The contentready method shares an identical syntax with available. The material difference between the two methods is that contentready waits until both the target element and its nextSibling in the DOM respond to getElementById. This guarantees that the target element's contents will have loaded fully (excepting any dynamic content you might add later via script). If contentready never detects a nextSibling, it fires with the window.load event.

Using the domready Event (Formerly onDOMReady)

The domready custom event lets you define a function that will execute as soon as the DOM is in a usable state. The DOM is not deemed "usable" until it is structurally complete; a number of bugs, primarily in IE, can lead to the browser crashing or failing to load the page successfully if scripts attempt to insert information into the DOM prior to the DOM being in a complete state.

DOM readiness is achieved before images have finished loading, however, so domready is often an excellent alternative to using the window object's load event.

Using the key Event

The key event lets you define a function that will execute only when a certain key (or set of keys), with or without modifiers, is detected.

Creating a Key Listener

The following will attach a keydown listener to an element with the id of 'text1'. The listener will only be exectued if the return key (keyCode 13) is detected, and the listener is remove the first time this key is detected.

Defining a Key Listener Specification

In the previous example, 'down:13' was provided as the key listener specification. This specifies that the lister should only fire if the return key triggers a keydown event. The specification string consists of three parts:

  1. The key event type followed by a colon ('up:', 'down:, or 'press:')
  2. zero or more keyCodes to listen for, separated by commas. If more than one keyCode is specified, the listener will fire if any of the codes are detected. ('up:12,13,14')
  3. zero or more modifiers keys to listen for, separated by the plus symbol. If modifiers are specified, all must be detected in order for the listener to fire ('+shift+ctrl+alt+meta').

So, the following specification will fire only if keyCode 65 or 66 is detected during a keypress event while shift and control are held down: 'press:65,66+shift+ctrl'

Using the delegate Event

Event delegation is a technique whereby you use a single event handler on a parent element to listen for interactions that affect the parent's descendant elements; because events on the descendant elements will bubble up to the parent, this can be a reliable and extremely efficient mitigation strategy for reducing the number of resource-consuming event handlers you have on any given page. (You can read more about Event Delegation in this YUIBlog article.)

The Event Utility makes using event delegation easy by providing a delegate Custom Event. Using Y.on, pass "delegate" as the first argument, followed by the listener to be called, the Node to which the listener is to be attached, the name of the event to delegate, and finally a CSS selector used to define the descendant Nodes that must match the target of the event in order for the listener to be called.

The following example will bind a single click event listener to a <ul> element with an id of "container", but that listener will only be called if the target of the event is a <li> that is a direct descendant of the <ul>.

Using the focus and blur Events

Since the DOM focus and blur events do not bubble, use the Event Utility's focus and blur custom events as an alternative to attaching discrete DOM focus and blur event handlers to focusable elements. The focus and blur custom events leverage capture-phase DOM event listeners (focusin and focusout for IE), making it possible to attach a single listener to an element and listen for the focus and blur events fired by all its focusable descendents.

Creating a focus Listener

The following will attach a focus listener to an element with the id of "container".

Using the mouseenter and mouseleave Events

Modeled after Internet Explorer's mouseenter and mouseleave events, the Event Utility offers mouseenter and mouseleave Custom Events: events that fire the first time the mouse enters or leaves a specified Node. Think of the mouseenter and mouseleave events as being mouseover and mouseout that don't bubble. As a result, the target of a mouseenter and mouseleave event is always the Node to which it is bound.

Creating a mouseenter Listener

The following will attach a mouseenter listener to an element with the id of "container".

Delegating a mouseenter Listener

It is also possible to delegate a mouseenter or mouseleave event listener by passing a CSS selector as an optional fourth argument that defines the Node(s) that must match the target of the event in order for the listener to be called. The following example will bind a single mouseenter event listener to a <ul> element with an id of "container", but that listener will only be called if the target of the event is a <li> that is a direct descendant of the <ul>.

Using Custom Events

The YUI Custom Event System enables you to define and use events beyond those available in the DOM — events that are specific to and of interest in your own application. Custom Events are designed to work much like DOM events. They can bubble, pass event facades, have their propagation and default behaviors suppressed, etc. This section describes several common uses of YUI Custom Events and provides some sample code. It contains these sections:

Simple Custom Events Using Y.on

You can send out notification of an interesting moment anywhere from your code simply by calling your yui instance's fire method.

This will send out notifications to any function that previously subscribed to that event:

Defining a Custom Event on an Event Target

A common way to create a Custom Event is to augment an object with EventTarget, making it able to host Custom Events and be a target Custom Events that are bubbling from other hosts:

The publish constructor creates a new Custom Event; it takes one required parameter and one optional parameters:

  • type — The type of event. This string is returned to listeners that receive this event so that they know what event occurred.
  • options — The specific configuration options you want to define for this Custom Event. Most properties of the Custom Event class can be set at this time.

Subscribing (Listening) to a Custom Event

To subscribe to a custom event, use its on method. Following the code above, you would subscribe to the publisher:testEvent as follows:

Firing the Event

To trigger or fire a custom event, simpy call its fire method:

YUI on Mobile: Using Event Utility with "A-Grade" Mobile Browsers

About this Section: YUI generally works well with mobile browsers that are based on A-Grade browser foundations. For example, Nokia's N-series phones, including the N95, use a browser based on Webkit — the same foundation shared by Apple's Safari browser, which is found on the iPhone. The fundamental challenges in developing for this emerging class of full, A-Grade-derived browsers on handheld devices are:

  • Screen size: You have a much smaller canvas;
  • Input devices: Mobile devices generally do not have mouse input, and therefore are missing some or all mouse events (like mouseover);
  • Processor power: Mobile devices have slower processors that can more easily be saturated by JavaScript and DOM interactions — and processor usage affects things like battery life in ways that don't have analogues in desktop browsers;
  • Latency: Most mobile devices have a much higher latency on the network than do terrestrially networked PCs; this can make pages with many script, css or other types of external files load much more slowly.

There are other considerations, many of them device/browser specific (for example, current versions of the iPhone's Safari browser do not support Flash). The goal of these sections on YUI User's Guides is to provide you some preliminary insights about how specific components perform on this emerging class of mobile devices. Although we have not done exhaustive testing, and although these browsers are revving quickly and present a moving target, our goal is to provide some early, provisional advice to help you get started as you contemplate how your YUI-based application will render in the mobile world.

More Information:

The Event Utility works in any browser that has DOM2 event support. However, the user interaction model of mobile browsers can make certain browser events behave in a different manner than expected, or not at all.

The iPhone's touch interface supports gestures that prevent certain mouse events from working correctly. For instance, the 'mousedown' event does not fire when the user initially touches the screen over an element. It only fires once the user's finger is removed (the mousedown, mouseup, and click events all fire at this moment). This makes is difficult or impossible to provide certain DHTML interactions that rely on these events, drag and drop being the most obvious.

Since the iPhone has a touch interface, there is no mouse cursor. This means that there are no hover states for elements, and no mouseover events.

Support & Community

Forum & Blog

There is a dedicated mailing list for YUI 3. Click the link to visit the list, or use the form below to subscribe:

 

You might also be interested in the general YUI list: ydn-javascript.

In addition, please visit the YUIBlog for updates and articles about the YUI Library written by the library's developers.

Filing Bugs & Feature Requests

The YUI Library's public bug tracking and feature request repositories are located on the YUILibrary.com site. Before filing new feature requests or bug reports, please review our reporting guidelines.

Copyright © 2009 Yahoo! Inc. All rights reserved. Copyright | Privacy Policy | Terms of Use | Job Openings