Eight Weeks of Prototype: Week 2, How Prototype Extends Elements
Managing an Element's Classes in Real-Time
Prototype makes it easy to manage the classes that an element belongs to by providing three useful elements: addClassName(), removeClassName() and hasClassName(). If you were not using Prototype, you would manually have to deal with the className property on elements; however this is no longer necessary. These methods are especially useful when an element has (or can have) multiple classes.
One of the most frequent occurrences of having to manage class names is when handling hover events on elements. Although browsers that correctly implement CSS (such as Firefox) allow you to change the look of an element when you hover over (using the :hover selector), this is not possible in Internet Explorer (aside from hyperlinks).
Listing 11 shows an example of how CSS should work in all browsers (yet does not necessarily). This code will draw a red box, which will turn blue when the mouse hovers over it.
<html> <head> <title>Using CSS to change the hover style of an element</title> <style type="text/css"> #foo { background : #f00; color : #fff; } #foo:hover { background : #00f; } </style> </head> <body> <div id="foo"> Highlight me! </div> </body> </html>
To make this code work in browsers that don't support this CSS, we can instead use addClassName() and removeClassName(). Each of these methods takes one argument: the class name to add or remove.
Rather than defining a CSS called #foo:hover, I'll instead define one called #foo.hover. This means we can call addClassName('hover') on the #foo element.
Listing 12 shows how this is achieved. Note that in this code I've also used observe(), which is used to observe events in Prototype. Event handling will be covered in detail in the fourth article of this series. For now, all you need to know is that the first argument to observe() is the event name (without on at the beginning) and the second argument is the function to execute when the event is triggered. Additionally, calling this inside the handler function refers to the element on which the event occurred.
<html> <head> <title>Using Prototype to change the hover style of an element</title> <script type="text/javascript" src="/js/prototype.js"></script> <style type="text/css"> #foo { background : #f00; color : #fff; } #foo.hover { background : #00f; } </style> </head> <body> <div id="foo"> Highlight me! </div> <script type="text/javascript"> var elt = $('foo'); elt.observe('mouseover', function(e) { this.addClassName('hover'); }); elt.observe('mouseout', function(e) { this.removeClassName('hover'); }); </script> </body> </html>
Using the hasClassName() method, you can check whether or not an element has a particular class. Listing 13 shows an example of using hasClassName(). It works by checking for the .hover class, then adding it, then checking for it again.
<html> <head> <title>Using Prototype to check if an element has a class</title> <script type="text/javascript" src="/js/prototype.js"></script> <style type="text/css"> #foo { background : #f00; color : #fff; } #foo.hover { background : #00f; } </style> </head> <body> <div id="foo"> Highlight me! </div> <script type="text/javascript"> var elt = $('foo'); if (elt.hasClassName('hover')) { // does not reach this } elt.addClassName('hover'); if (elt.hasClassName('hover')) { // does reach this } </script> </body> </html>




