In the first part of this tutorial series, we were talking about a very straight forward way of attaching events to elements in the DOM. This article will tell you how to even create our own Custom Events and trigger them. This is what the YUI guys call an “interesting moment” in your application.
Introduction
The DOM offers various Events that you can listen and attach a function to, e.g. onclick, onmouseover. But sometimes, these might offer you not enough functionality in your own web application. With YAHOO.util.CustomEvent, you are able to create your own Custom Events, which can be described as an “interesting moment” within the flow of your application. If that “interesting moment” happens, you can fire (i.e. trigger) that event and run a function which is “subscribed” to this event. A checklist of creating a simple Custom Event could read as follows:
- Create a Custom Event Object in your code (using YAHOO.util.CustomEvent)
- Declare a function that should get executed when this “interesting moment” happens
- “Subscribe” this function to the Custom Event (which will be called when the event gets fired)
The following exercise will show you how to create a Custom Event and trigger it when a certain condition within the code is met.
The Mission Statement
We have a blurred version of a picture which shows a very famous James Bond actor (step 1). The picture is split into 9 parts and when clicking on one of them, the clear (i.e. unblurred) version gets displayed (step 2). When all parts of the in-focus picture are available, a speech bubble should be displayed at the position of the mouse cursor (step 3). Inside the speech bubble, a random James Bond movie quote should be displayed.
The Plan
Based on this information, we can make a step-by-step plan of what is supposed to happen and how we are going to do it:
- When the page gets loaded, the user will see the blurred version of the image (made up of an unordered list)
- We will attach an onclick event to the ul which captures mouseclicks within the list
- If the user clicks on the image (i.e. on one of the 9 parts) we will replace the respective part with the focused version
- When the last image is swapped, we will trigger a Custom Event (this is our “interesting moment”)
- This Custom Event caters for the display of a speech bubble, with a random James Bond movie quote, at the last mouse cursor position
The Implementation
The first steps involve creating the HTML markup and adding some styling rules. As tables are evil, we will use an ul to put the 9 image parts together. Unfortunately, we need to introduce a little hack to remove the little horizontal gaps which will otherwise get displayed in the browser:
#container li {
float: left;
list-style: none;
font-size: 0; // needed to get rid of gaps between rows
}
Step two is implementing the image swap function. This will be triggered by an onclick Event attached to the unordered list. We can attach it to the ul, because through Event bubbling the parent element will capture any events the are triggered by it’s child elements. The function imgSwap() will then replace the src attribute of the image with the one in focus.
We also need to know which image has been clicked and when all 9 images got replaced. Because of that, we will get all the img elements on the page, loop through them and put each of them into an array. We will need an array, because JavaScript offers a nice function called splice() which lets you remove elements from an array (but not from an object). Therefore: get all the images (which returns an object with all the images) and feed them into array.
var init = function () {
// attach event to whole unordered list
var imgContainerEl = YAHOO.util.Dom.get("container");
YAHOO.util.Event.addListener(imgContainerEl, "click", imgSwap);
// get all image elements
tmp = document.getElementsByTagName("img");
imgArrayLength = tmp.length;
// unfortunately, tmp is an object (not an array)
// we need to therefor put all the items into an array in order
// to use splice() to remove an item when it gets clicked
imgArray = [];
for (var i = 0; i < imgArrayLength; i++) {
imgArray.push(tmp[i]); // move elements from object into array
}
};
imgSwap() then caters for the actual replacement of the image. It uses YAHOO.util.Event.getTarget(e) to retrieve the target of the onclick event (which, in our case, will be one of the 9 image elements). It will then check if the src attribute will contain “blur_” and replace it with an empty string. Conveniently, I named to images in a way that this works (e.g. blurred: connery_blur_01.gif, unblurred: connery_01.gif). Using splice() it is then possible to remove that respective image from the array which holds all the images on the page. With every click, the length of that array decreases until it is empty, which tells us that all 9 images got swapped and our Custom Event should be triggered.
var imgSwap = function (e) {
var imgEl = YAHOO.util.Event.getTarget(e);
if (imgEl.src.indexOf("blur") !== -1) {
// on click on image swap background image to unblurred version
var oldSrc = imgEl.src;
var newSrc = oldSrc.replace("blur_", "");
imgEl.src = newSrc;
for (var i = 0; i < imgArrayLength; i++) {
// loop through array which holds all images on page
if (imgArray[i].src.indexOf(newSrc) !== -1) {
// find the one which just got clicked and remove it from array
imgArray.splice(i, 1);
imgArrayLength = imgArray.length; // adjust length of array
}
}
}
};
Now it is time for creating our Custom Event. At the beginning of our module code, we will therefor create new Custom Event Object like this:
var onAllClicked = new YAHOO.util.CustomEvent("allClicked");
When creating the new object, you can pass in a parameter which will be the type of the event. This is basically your own custom name for this special event and can be used to trigger different behavior.
In our init() function, we will then subscribe a function to this Custom Event:
onAllClicked.subscribe(showQuotesBubble);
This means basically: “When the Custom Event ‘allClicked’ gets triggered, call the function ‘showQuotesBubble’”. Now all we need to do is fire the event at the right moment. This moment is exactly when the image array is empty. In the example, the showQuotesBubble function does nothing else but alerting a string.
if (imgArrayLength < 1) {
onAllClicked.fire();
}
Now the major parts are done. When examining the example, you have probably noticed that the function which is subscribed to the Custom Event takes two arguments, type and args. type is basically the event type you can state when creating the object (“allClicked” in our case) and args is just an array of arguments passed into the array. We will use this functionality to pass in the coordinates of the mouse cursor when the last image gets clicked:
onAllClicked.fire({x: e.clientX, y: e.clientY});
As far as Custom Events go, this example is basically finished. All that is left is create a new element in the DOM (a blockquote which holds a random James Bond quote) and use the X/Y values to display that element at these coordinates. You can take a look at the final result with the finishing touches applied.
Further reading
- YUI: Event Utility: Using Custom Events
- A basic example using Custom Objects on the YUI site
- PPK on Event bubbling
[...] Agent YUI: Mission 3 – Create Your Own Events « klauskomenda.com (tags: yui ajax javascript tutorial) [...]
Great tutorial Klaus! …. very helpful!