PhpRiot
Become Zend Certified

Prepare for the ZCE exam using our quizzes (web or iPad/iPhone). More info...


When you're ready get 7.5% off your exam voucher using voucher CJQNOV23 at the Zend Store

Eight Weeks of Prototype: Week 4, Event Handling in Prototype

Finding the Element on Which an Event Was Observed

In all of the event handlers in the examples so far, we have only observed events on a single element. In the event handler we have then used the $() function to select that element again to perform some function on it.

Using the Event.element() function, we can determine exactly which element and event was triggered on. This is useful when an event handler might be used for a particular event that may occur on several items.

Listing 9 shows such an example. In this listing, we use the $$() function select all of the list items so the click event can be observed on each of them. Using the each() method (covered in the third article of this series), we loop over each item and observe the event.

When the event is handled (that is, the onItemClick() method is called), we use Event.element(e) to determine the specific list item that the event was triggered for. We then update its background colour and change its text.

Listing 9 Retrieving an event's element with Event.element() (listing-9.html)
<html>
    <head>
        <title>Retrieving an event's element with Event.element()</title>
        <script type="text/javascript" src="/js/prototype.js"></script>
    </head>
    <body>
        <div>
            <ul id="foo">
                <li>Click Me</li>
                <li>Click Me</li>
                <li>Click Me</li>
                <li>Click Me</li>
                <li>Click Me</li>
                <li>Click Me</li>
                <li>Click Me</li>
            </ul>
        </div>
 
        <script type="text/javascript">
            function onItemClick(e)
            {
                var item = Event.element(e);
 
                item.setStyle({ backgroundColor : '#fc0' });
                item.update('Clicked!');
            }
 
            $$('#foo li').each(function(item) {
                item.observe('click', onItemClick);
            });
        </script>
    </body>
</html>

Sometimes you may not want the specific element on which the event occurred, but rather one of its parent elements. If you look at listing 9, how would we go about retrieving the parent <ul> element rather than the <li> that was clicked?

To do so, Prototype provides the method Event.findElement(). This is similar to Event.element(), except you specify a tag name as the second argument. That, you would use Event.findElement('e', 'ul') to find the parent <ul> element. This is shown in Listing 10.

Listing 10 Finding an event element's ancestor with Event.findElement() (listing-10.html)
<html>
    <head>
        <title>Finding an event element's ancestor with findElement()</title>
        <script type="text/javascript" src="/js/prototype.js"></script>
    </head>
    <body>
        <div>
            <ul id="foo">
                <li>Click Me</li>
                <li>Click Me</li>
                <li>Click Me</li>
            </ul>
        </div>
 
        <script type="text/javascript">
            function onItemClick(e)
            {
                var list = Event.findElement(e, 'ul');
 
                list.setStyle({ border : '2px solid #fc0'});
            }
 
            $$('#foo li').each(function(item) {
                item.observe('click', onItemClick);
            });
        </script>
    </body>
</html>

The only problem with Event.findElement() though is that you can only find ancestor elements based on their tag name. If you wanted a more complex search (such as finding an ancestor with a particular class name), then you would want to combine Event.element() with the up() method (we covered up() in the first article of this series).

Listing 11 shows an example of doing this. In this example we find the div with the class name of outer. If we tried to use Event.findElement(), we would not have been able to retrieve this element since if we passed div as the second argument, the div with class inner would have been returned.

Listing 11 Combining Event.element() with up() (listing-11.html)
<html>
    <head>
        <title>Combining Event.element() with up()</title>
        <script type="text/javascript" src="/js/prototype.js"></script>
    </head>
    <body>
        <div class="outer">
            <div class="inner">
                <ul id="foo">
                    <li>Click Me</li>
                    <li>Click Me</li>
                    <li>Click Me</li>
                </ul>
            </div>
        </div>
 
        <script type="text/javascript">
            function onItemClick(e)
            {
                var item = Event.element(e);
                var outer = item.up('div.outer');
 
                outer.setStyle({ backgroundColor : '#cf9' });
            }
 
            $$('#foo li').each(function(item) {
                item.observe('click', onItemClick);
            });
        </script>
    </body>
</html>

In This Article