Categories
josephscott

Javascript Events With Prototype

One the problems I ran into with the EditInPlace code was that the saving text was still clickable for edit. This meant that if you were fast enough you could click on the saving text and get the form field to shop and edit the contents of the saving message instead of the id you had set to be edited. After bulking up on Prototype Event foo I was finally able to fix this bug.

Before I get into this though let me point out the references for this information. Encytemedia‘s Working With Events In Prototype from earlier this year does a good job of covering this topic. For a simple and straight to the point example check the Event.stopObserving and Function.bindAsEventListener docs at Script.aculo.us. Reading those pages may answer all your questions.

If after reading all of the above you still aren’t sure how to deal with events I’ll see if I can shine some additional light on the subject. As example we’ll look at adding a mouseover event to an id called myid that will add a new CSS class called newcss. And because we want to remove the class when the mouse moves away from myid we’ll add a mouseout event that will remove newcss. One very easy way to do this with Prototype would be:

Event.observe(
  'myid',
  'mouseover',
  function() { Element.addClassName('myid', 'newcss'); }
);

Event.observe(
  'myid',
  'mouseout',
  function() { Element.removeClassName('myid', 'newcss'); }
);

Easy enough, and it even works! Going back to my bug in EditInPlace, lets say that there are times at which you don’t want the mouseover and mouseout events to be active (like when display the saving text). There is Event.stopObserving which exists to stop listening for events, but it turns out that we can’t use that with anonymous functions (which is what we used in the example above).

You can not use Event.stopObserving if you used an anonymous function in Event.observe.

Reread the above line about a dozen times, it is a critical point if you want to turn off events later that you started listening to with Event.observe. The bottom line is that with the example above you can not turn off the mouseover and mouseout events with Event.stopObserving. With that out of the way we’ll go on to a second example that we can use Event.stopObserving with:

function add_css(event) {
  Element.addClassName('myid', 'newcss');
}
add_css_bind = add_css.bindAsEventListener();

function remove_css(event) {
  Element.removeClassName('myid', 'newcss');
}
remove_css_bind = remove_css.bindAsEventListener();

Event.observe('myid', 'mouseover', add_css_bind);
Event.observe('myid', 'mouseout', remove_css_bind);

In this example we’ve really only done two things differently. First off instead of using anonymous functions we defined functions that will be called when the mouseover and mouseout events happens. Second we used Function.bindAsEventListener and used it in place of the anonymous functions in the Event.observe calls. More lines of code, but this does the same thing as the first example with the added bonus that we can use Event.stopObserving to turn off these events:

Event.stopObserving('myid', 'mouseover', add_css_bind);
Event.stopObserving('myid', 'mouseout', remove_css_bind);

You can always turn them back on with Event.observe again:

Event.observe('myid', 'mouseover', add_css_bind);
Event.observe('myid', 'mouseout', remove_css_bind);

The rule is, if you want to stop listening to an event then you can’t use anonymous functions. If you do want to stop events then you’ll have to define the action functions specifically and use Function.bindAsEventListiner on it and the resulting bind variable as the observer function in Event.observe.

Hopefully this has helped clarify Javascript events with Prototype.

4 replies on “Javascript Events With Prototype”

Hi Joseph,

You can actually stop listening. You do:
$(“myID”).stopObserving();
Granted, it will stop observing all actions, but sometimes, that’s OK and better than registering all sorts of global variables.

Leave a Reply

Your email address will not be published. Required fields are marked *