Woman, I am bound to you
What will I do?
—Devo,
"The Rope Song"
In this chapter, we'll closely examine each of the available event methods in turn. These methods are used to register behaviors to take effect when the user interacts with the browser, and to further manipulate those registered behaviors.
The following methods are the building blocks of jQuery's event handling module.
Attaches a handler to an event for the elements .bind(eventType[, eventData], handler) |
click
or submit
The .bind()
method is the primary means of attaching behavior to a document. All JavaScript event types are allowed for eventType; the following are cross‑platform and recommended:
blur
change
click
dblclick
error
focus
keydown
keypress
keyup
load
mousedown
mousemove
mouseout
mouseover
mouseup
resize
scroll
select
submit
unload
The jQuery library provides shortcut methods for binding each of these event types, such as .click()
for .bind('click')
. Descriptions of each event type can be found in the description of its shortcut method.
When an event reaches an element, all handlers bound to that event type for the element are fired. If there are multiple handlers registered, they will always execute in the order in which they were bound. After all handlers have executed, the event continues along the normal event propagation path. For a full discussion of event propagation, see Learning jQuery or the W3C specification at http://www.w3.org/TR/DOM-Level-2-Event/. A basic usage of .bind()
is:
$('#foo').bind('click', function() { alert('User clicked on "foo."'); });
This code will cause the element with an ID of foo
to respond to the click
event; when a user clicks inside this element thereafter, the alert will be shown.
Event Handlers
The handler
parameter takes a callback function, as shown; within the handler, the keyword this
is set to the DOM element to which the handler is bound. To make use of the element in jQuery, it can be passed to the normal $()
function. For example:
$('#foo').bind('click', function() { alert($(this).text()); });
After this code is executed, when the user clicks inside the element with an ID of foo
, its text contents will be shown as an alert.
The Event Object
The callback function takes a single parameter; when the handler is called the JavaScript event object will be passed through it.
The event object is often unneccessary and the parameter is omitted, as sufficient context is usually available when the handler is bound to know exactly what needs to be done when the handler is triggered. However, at times it becomes necessary to gather more information about the user's environment at the time the event was initiated. JavaScript provides information such as .shiftKey
(whether the shift key was held down at the time), .offsetX
(the x coordinate of the mouse cursor within the element), and .type
(the kind of event this is).
Some of the event object's attributes and methods are not available on every platform. If the event is handled by a jQuery event handler, however, the library standardizes certain attributes so that they can be safely used on any browser. In particular:
.target
: This attribute represents the DOM element that initiated the event. It is often useful to compare event.target
to this
in order to determine if the event is being handled due to event bubbling..pageX
: This attribute contains the x coordinate of the mouse cursor relative to the left edge of the page..pageY
: This attribute contains the y coordinate of the mouse cursor relative to the top edge of the page..preventDefault()
: If this method is called, the default action of the event will not be triggered. For example, clicked anchors will not take the browser to a new URL..stopPropagation()
: This method prevents the event from bubbling up the DOM tree looking for more event handlers to trigger.Returning false
from a handler is equivalent to calling both .preventDefault()
and .stopPropagation()
on the event object.
Using the event object in a handler looks like this:
$(document).ready(function() { $('#foo').bind('click', function(event) { alert('The mouse cursor is at (' + event.pageX + ', ' + event.pageY + ')'); }); });
Note the parameter added to the anonymous function. This code will cause a click
on the element with ID foo
to report the page coordinates of the mouse cursor at the time of the click.
The optional eventData parameter is not commonly used. When provided, this argument allows us to pass additional information to the handler. One handy use of this parameter is to work around the issues caused by closures. For example, suppose we have two event handlers where both refer to the same external variable:
var message = 'Spoon!'; $('#foo').bind('click', function() { alert(message); }); message = 'Not in the face!'; $('#bar').bind('click', function() { alert(message); });
Because the handlers are closures that both have message
in their environment, both will display the message Not in the face!
when triggered. The variable's value has changed. To sidestep this, we can pass the message in eventData
:
var message = 'Spoon!'; $('#foo').bind('click', {msg: message}, function(event) { alert(event.data.msg); }); message = 'Not in the face!'; $('#bar').bind('click', {msg: message}, function(event) { alert(event.data.msg); });
This time the variable is not referred to directly within the handlers; instead, the value is passed in through eventData
, which fixes the value at the time the event is bound. The first handler will now display Spoon!
while the second will alert Not in the face!
If eventData is present, it is the second argument to the .bind()
method; if no additional data needs to be sent to the handler, then the callback is passed as the second and final argument.
Removes a previously attached event handler from the elements. .unbind([eventType[, handler]]) .unbind(event) |
click
or submit
Any handler that has been attached with .bind()
can be removed with .unbind()
. In the simplest case, with no arguments, .unbind()
removes all handlers attached to the elements:
$('#foo').unbind();
This version removes the handlers regardless of type. To be more precise, we can pass an event type:
$('#foo').unbind('click');
By specifying the "click" event type, only handlers for that event type will be unbound. This approach can still have negative ramifications if other scripts might be attaching behaviors to the same element, however. Robust and extensible applications typically demand the two-argument version for this reason:
var handler = function() { alert('The quick brown fox jumps over the lazy dog.'); }; $('#foo').bind('click', handler); $('#foo').unbind('click', handler);
By naming the handler, we can be assured that no other functions are caught in the crossfire. Note that the following will not work:
$('#foo').bind('click', function() { alert('The quick brown fox jumps over the lazy dog.'); }); $('#foo').unbind('click', function() { alert('The quick brown fox jumps over the lazy dog.'); });
Even though the two functions are identical in content, they are created separately and so JavaScript is free to keep them as distinct function objects. To unbind a particular handler, we need a reference to that function and not to a different one that happens to do the same thing.
The second form of this method is used when we wish to unbind a handler from within itself. For example, suppose we wish to trigger an event handler only three times:
var timesClicked = 0; $('#foo').bind('click', function(event) { alert('The quick brown fox jumps over the lazy dog.'); timesClicked++; if (timesClicked >= 3) { $(this).unbind(event); } });
The handler in this case must take a parameter, so that we can capture the event object and use it to unbind the handler after the third click. The event object contains the context necessary for .unbind()
to know which handler to remove.
This example is also an illustration of a closure. Since the handler refers to the timesClicked
variable, which is defined outside the function, incrementing the variable has an effect even between invocations of the handler.
Attaches a handler to an event for the elements. The handler is executed at most once. .one(eventType[, eventData], handler) |
click
or submit
This method is identical to .bind()
, except that the handler is unbound after its first invocation. For example:
$('#foo').one('click', function() { alert('This will be displayed only once.'); });
After the code is executed, a click on the element with ID foo
will display the alert. Subsequent clicks will do nothing.
This code is equivalent to:
$('#foo').bind('click', function(event) { alert('This will be displayed only once.'); $(this).unbind(event); });
In other words, explicitly calling .unbind()
from within a regularly bound handler has exactly the same effect.
Executes all handlers attached to an element for an event. .trigger(eventType[, extraParameters]) |
click
or submit
Any event handlers attached with .bind()
or one of its shortcut methods are triggered when the corresponding event occurs. They can be fired manually, however, with the .trigger()
method. A call to .trigger()
executes the handlers in the same order they would be if the event were triggered naturally by the user:
$('#foo').bind('click', function() { alert($(this).text()); }); $('#foo').trigger('click');
While .trigger()
simulates an event activation, complete with a synthesized event object, it does not perfectly replicate a naturally‑occurring event. No event bubbling occurs, so the .trigger()
call must be made on the element that actually has the event handlers attached. Default behaviors are also not reliably invoked, so must be called manually with methods such as .submit()
on the DOM elements themselves.
When we define a custom event type using the .bind()
method, the second argument to .trigger()
can become useful. For example, suppose we have bound a handler for the custom event to our element instead of the built-in click
event as we did previously:
$('#foo').bind('custom', function(event, param1, param2) { alert(param1 + "\n" + param2); }); $('#foo').trigger('custom', ['Custom', 'Event']);
The event object is always passed as the first parameter to an event handler, but if additional parameters are specified during a .trigger()
call as they are here, these parameters will be passed along to the handler as well.
Note the difference between the extra parameters we're passing here and the eventData
parameter to the .bind()
method. Both are mechanisms for passing information to an event handler, but the extraParameters
argument to .trigger()
allows information to be determined at the time the event is triggered while the eventData
argument to .bind()
requires the information to be already computed at the time the handler is bound.