YUI Library Home

YUI Library Examples: Event Utility: Using Custom Events

Event Utility: Using Custom Events

Clicking in the grey box resizes the blue <div> within it. We consider this an "interesting moment" in our script, so we create a Custom Event called onSizeChange that fires whenever the blue box is resized. This Custom Event, when fired, publishes the blue box's new size. Note: onSizeChange isn't a DOM event — it's an arbitrary "custom" event that has meaning in the context of our script, and an event that we think other scripts on the page might be interested in knowing about.

One subscriber to our onSizeChange Custom Event looks at the new width and resizes the brown box to match. A second subscriber looks at the blue <div>'s new height and resizes the red box to match.

Click anywhere within the grey box to resize me.
Width will resize to match blue box.
Height will resize to match blue box.

Using Custom Events

Custom Events, part of the YUI Event Utility, are special developer-created events that express the occurance of and information about interesting moments taking place on a page. Custom Events can be subscribed to by any script on the page; the publisher of the Custom Event knows nothing about the subscribers, and individual subscribers don't need to know anything about each other.

To illustrate the use of Custom Event, we'll create a single <div> called resizer that resizes itself when its container is clicked. When we resize this <div> we'll publish a Custom Event, onSizeChange, that reports the new height and width of our resizer. We will have two modules that subscribe to this information; the first will respond by changing its height to remain the same as the resizer's height and the second will change its width.

Start with some simple CSS rules and markup for the appearing elements:

1<style type="text/css"
2#container {width:400px; height:100px; padding:10px; border:1px dotted black;background-color:#CCCCCC; cursor:pointer;} 
3#resizer {width:200px; height:75px; background-color:#00CCFF;} 
4#subscriberWidth {width:200px; height:75px; margin-top:10px;background-color:#CC9966;} 
5#subscriberHeight {width:200px; height:75px;  margin-top:10px;background-color:#FF3333;} 
6</style> 
7 
8<div id="container"
9  <div id="resizer"
10    Click anywhere within the grey box  
11    to resize me. 
12  </div> 
13</div> 
14<div id="subscriberWidth"
15  <strong>Width will resize to match blue  
16  box.</strong> 
17</div> 
18<div id="subscriberHeight"
19  <strong>Height will resize to match blue 
20  box.</strong> 
21</div> 
view plain | print | ?

Next, we'll compose our script. We begin by creating our Custom Event instance. We'll fire() this Custom Event — that is, call its fire method — when our click handler executes and changes resizer's width.

1//create a new custom event, to be fired 
2//when the resizer div's size is changed 
3var onSizeChange = new YAHOO.util.CustomEvent("onSizeChange"); 
view plain | print | ?

Our click handler, to be fired when the grey container <div> is clicked, performs a number of housekeeping tasks like figuring out the new size of the resizer element, making sure that a minimum size is maintained, etc. Note that it only fires the Custom Event if the click will result in a sane value for resizer's height or width. Line 35 below is where we ultimately fire the Custom Event. We pass in the new height and width of resizer as an argument when we fire the Custom Event because we want our subscribers to have access to that information.

1//when the container is clicked on, change the  
2//dimensions of the resizer -- as long as it appears 
3//to be a valid new size (>0 width, >12 height). 
4function fnClick(e){ 
5    //0,0 point is the top left corner of the container, 
6    //minus its padding: 
7    var containerX = YAHOO.util.Dom.getX("container"); 
8    var containerY = YAHOO.util.Dom.getY("container"); 
9    var clickX = YAHOO.util.Event.getPageX(e); 
10    var clickY = YAHOO.util.Event.getPageY(e); 
11    //get container padding using Dom's getStyle(): 
12    var containerPaddingX = parseInt(YAHOO.util.Dom.getStyle("container","padding-left"), 10); 
13    var containerPaddingY = parseInt(YAHOO.util.Dom.getStyle("container","padding-top"), 10); 
14    var newWidth = clickX - containerX - containerPaddingX; 
15    var newHeight = clickY - containerY - containerPaddingY; 
16     
17    //if there is a valid new dimension, we'll change 
18    //resizer and fire our custom event 
19    if ((newWidth > 0)||(newHeight > 12)) { 
20        //correct new height/width to guarantee 
21        //minimum of 0x12    
22        if (newWidth < 0) {newWidth = 1;} 
23        if (newHeight < 12) {newHeight = 12;} 
24        //show new dimensions in resizer: 
25        YAHOO.util.Dom.get("resizer").innerHTML = "New size: " + newWidth + "x" + newHeight; 
26        //change the dimensions of resizer, using 
27        //Dom's setStyle: 
28        YAHOO.util.Dom.setStyle("resizer""width", newWidth + "px"); 
29        YAHOO.util.Dom.setStyle("resizer""height", newHeight + "px"); 
30 
31         //fire the custom event, passing 
32         //the new dimensions in as an argument; 
33         //our subscribers will be able to use this 
34         //information: 
35        onSizeChange.fire({width: newWidth, height: newHeight}); 
36    }; 
37
view plain | print | ?

We now have a Custom Event and we're firing it at the right time, passing in the relevant data payload. The next step is to create functions that respond and react to this change. We've specified that we'll have one function that will pay attention to our onSizeChange Custom Event, get the new width of resizer, and change the width of the brown box to match; another function will do the same for the red box's height. Note that the argument we passed in when we fired the Custom Event (an object literal: {width: x, height: y}) is available to us in the second argument received by our handlers. That second argument is an array, and our object is the first item in the array.

1//a handler to respond to the custom event that 
2//we're firing when the resizer changes size; we'll 
3//resize its width to match the resizer. 
4fnSubscriberWidth = function(type, args) { 
5    var elWidth = YAHOO.util.Dom.get("subscriberWidth"); 
6    var newWidth = args[0].width; 
7    YAHOO.util.Dom.setStyle(elWidth, "width", (newWidth + "px")); 
8    elWidth.innerHTML = ("My new width: " + newWidth + "px"); 
9
10 
11//another handler to respond to the custom event that 
12//we're firing when the resizer changes size; this 
13//one cares about the height of the resizer. 
14fnSubscriberHeight = function(type, args) { 
15    var elHeight = YAHOO.util.Dom.get("subscriberHeight"); 
16    var newHeight = args[0].height; 
17    YAHOO.util.Dom.setStyle(elHeight, "height", (newHeight + "px")); 
18    elHeight.innerHTML = ("My new height: " + newHeight + "px"); 
19
view plain | print | ?

The final step in this example is to subscribe our Custom Event handlers to the onSizeChange Custom Event we created in the first script step. We do this by calling onSizeChange's subscribe method and passing in the functions we want to subscribe:

1onSizeChange.subscribe(fnSubscriberWidth); 
2onSizeChange.subscribe(fnSubscriberHeight); 
view plain | print | ?

This is a simple example of how to use Custom Events. One of the powerful things about this concept is how far it can extend — we only have two subscribers in this example, but we could have from zero to n subscribers. Custom Events give you granular control over scope and firing order and are an excellent way to provide inter-module messaging within your application.

Configuration for This Example

You can load the necessary JavaScript and CSS for this example from Yahoo's servers. Click here to load the YUI Dependency Configurator with all of this example's dependencies preconfigured.

Copyright © 2009 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings