Events

By now we know how to find our way around the document and change elements and attributes in it, but what do we use it for? To make a page really dynamic we need some user interaction. Each time the user clicks a button or a link, types something into a form or even moves the mouse, the browser fires events letting us know about it. We can subscribe to these events in order to make something happen.

Subscribing to events

Events happen on elements in the page, like a link. We subscribe to events on individual elements, and when that event happens on that element, we get notified and our action gets run. To subscribe to an event, we can use Prototype's observe method:

1 //First, get the element on which the event will/may happen
2 var element = $('my_link'); //The $() function finds an element using its "id" attribute
3 
4 //Then, subscribe to the "click" event, supplying a function that will be run when it happens
5 element.observe('click', function(){
6   alert('Thank you for clicking my link');
7 });

With the above code, whenever a user clicks the link with the "my_link" ID, our function will run, alerting the message. The "click" event is probably the most-used event by far, but there are a few other useful events that can happen on elements:

  • mouseover - Happens when the mouse pointer "enters" the element from outside
  • mouseout - Happens when the mouse pointer "exits" the element's boundaries
  • change - This event is only available on form elements and happens when the user changes the value of the element

A practical example

If we go back to our book list:

 1 <html>
 2   <head>
 3     <title>Book Club</title>
 4   </head>
 5   <body>
 6     <h1>My books</h1>
 7 
 8     <ul class="books">
 9       <li class="book">War and Peace</li>
10       <li class="book">The Origin of the Species</li>
11       <li class="book read">101 Really Funny Jokes</li>
12     </ul>
13   </body>
14 </html>

Note: We've updated the HTML to only contain the "read" class for read books and not "unread" for the others

Let's say we wanted to let the user mark each book as read or unread by simply clicking the title. To do this, we have to find all the book elements and then subscribe to the "click" event. When the click happens, we want to add or remove the "read" class on the element.

 1 //We're iterating the book array directly without saving it to
 2 //the "books" variable first.
 3 $$('ul.books li.book').each(function(book){
 4 
 5   //Then, for each book, subscribe to the "click" event
 6   book.observe('click', function(){
 7     //When the click happens, "toggle" (add or remove) the "read" attribute
 8     book.toggleClassName('read');
 9   });
10 
11 });

Now, when the user clicks a book title (the <li> element) our function will run and toggle the "read" class name for that element. To let the user know in which state a book is, we could use CSS to give them different background colors depending on their class name:

 1 /* Let unread books have a red background */
 2 ul.books li.book {
 3   background-color: red;
 4 }
 5 
 6   /* And read books have a green background */
 7   ul.books li.book.read {
 8     background-color: green;
 9   }

Note: In this example, we could say that books are unread by default, and thus red, and only become read when we add the "read" class name.

Also available in: HTML TXT