observe

Event.observe(element, eventName, handler[, useCapture = false])

Registers an event handler on a DOM element.

An important note

First, if you're coming from a background where you'd use HTML event attributes (e.g. <body onload="return myFunction()">) or DOM Level-0 event properties (e.g. window.onload = myFunction;), you must shed those vile ways :-) and understand what observe does.

It does not replace existing handlers for that same element+event pair. It adds to the list of handlers for that pair. Using observe will never incapacitate earlier calls.

What are those arguments about?

  1. The DOM element you want to observe; as always in Prototype, this can be either an actual DOM reference, or the ID string for the element.
  2. The standardized event name, as per the DOM level supported by your browser (usually DOM Level 2 Events, see section 1.6 for event names and details). This can be as simple as 'click'.
  3. The handler function. This can be an anonymous function you create on-the-fly, a vanilla function, a bound event listener, it's up to you.
  4. Optionally, you can request capturing instead of bubbling. The details are in the DOM spec referred to above. Note that capturing is not supported on several major browsers, and is seldom what you need, anyway. Most often, you won't even provide this argument.

The requirement people too often forget…

To register a function as an event handler, the DOM element that you want to observe must already exist in the DOM (in other words, it must have appeared in the source, or been dynamically created and inserted, before your handler-registration script line runs).

A simple example

Let us assume the following (X)HTML fragment:


<form id="signinForm" method="post" action="/auth/signin">
…
</form>

Here's how to register your function checkForm on form submission:


Event.observe('signinForm', 'submit', checkForm);

Of course, you'd want this line of code to run once the form exists in the DOM; but putting inline scripts in the document is pretty obtrusive, so instead we'll go for a simple approach that waits till the page is fully loaded:


Event.observe(window, 'load', function() {
  Event.observe('signinForm', 'submit', checkForm);
});

Just a little wrapping…

Note that if your page is heavy, you might want to run this code before the page is fully loaded: just wait until the DOM is loaded, that will be enough. There is currently no standard event for this, but here is a helpful article you can use.

The tricky case of methods that need this

Passing your event handler as a function argument, you lose its binding. That is, you lose its ability to know what this means to the original function. If you're passing in a method that does need to use the this reference (for instance, to access fields of its container object), you're in trouble.

Or not.

This is an issue specifically addressed by Prototype's bindAsEventListener function. Check it out if you don't know it already. Usage is simple:


var Checks = {
  // some stuff our 'generic' function needs

  generic: function(event) {
    // Some generic, all-purpose checking (e.g. empty required fields)
  }
};

Event.observe('signinForm', 'submit', Checks.generic.bindAsEventListener(Checks));

See also

The stopObserving and unloadCache methods are closely related, and worth a look.