O'Reilly logo

jQuery Pocket Reference by David Flanagan

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Chapter 4. Events

One of the difficulties of working with events in client-side JavaScript is that IE (until IE9) implements a different event API than all other browsers. To address this difficulty, jQuery defines a uniform event API that works in all browsers. In its simple form, the jQuery API is easier to use than the standard or IE event APIs. And in its more complex full-featured form, the jQuery API is more powerful than the standard API. The sections below have all the details.

Simple Event Handler Registration

jQuery defines simple event registration methods for each of the commonly used and universally implemented browser events. To register an event handler for “click” events, for example, just call the click() method:

// Clicking on any <p> gives it a gray background
$("p").click(function() {
    $(this).css("background-color", "gray");
});

Calling a jQuery event registration method registers your handler on all of the selected elements. This is typically much easier than one-at-a-time event handler registration with addEventListener() or attachEvent().

These are the simple event handler registration methods jQuery defines:

blur()       focusin()       mousedown()     mouseup()
change()     focusout()      mouseenter()    resize()
click()      keydown()       mouseleave()    scroll()
dblclick()   keypress()      mousemove()     select()
error()      keyup()         mouseout()      submit()
focus()      load()          mouseover()     unload()

Most of these registration methods are for common event types with which you are probably already familiar. A few notes are in order, however. “focus” and “blur” events do not bubble, but the “focusin” and “focusout” events do, and jQuery ensures that these events work in all browsers. Conversely, the “mouseover” and “mouseout” events do bubble, which is often inconvenient because it is difficult to know whether the mouse has left the element you’re interested in, or whether it has simply moved out of one of the descendants of that element. “mouseenter” and “mouseleave” are nonbubbling events that solve this problem. These event types were originally introduced by IE, and jQuery ensures that they work correctly in all browsers.

The “resize” and “unload” event types are only ever fired on the Window object, so if you want to register handlers for these event types, you should invoke the resize() and unload() methods on $(window). The scroll() method is also most often used on $(window), but it can also be used on any element that has scrollbars (such as when the CSS overflow attribute is set to “scroll” or “auto”). The load() method can be called on $(window) to register a “load” handler for the window, but it is usually better to pass your initialization function directly to $(), as shown in The jQuery() Function. You can use the load() method on iframes and images, however. Note that when invoked with different arguments, load() is also used to load new content (via scripted HTTP) into an element—see The load() Method. The error() method can be used on <img> elements to register handlers that are invoked if an image fails to load. It should not be used to set the Window onerror property.

In addition to these simple event registration methods, there are two special forms that are sometimes useful. The hover() method registers handlers for “mouseenter” and “mouseleave” events. Calling hover(f,g) is like calling mouseenter(f) and then calling mouseleave(g). If you pass just one argument to hover(), that function is used as the handler for both enter and leave events.

The other special event registration method is toggle(). This method binds event handler functions to the “click” event. You specify two or more handler functions and jQuery invokes one of them each time a click event occurs. If you call toggle(f,g,h), for example, the function f() is invoked to handle the first click event, g() is invoked to handle the second, h() is invoked to handle the third, and f() is invoked again to handle the fourth click event. Be careful when using toggle(): as we’ll see in Simple Effects, this method can also be used to show or hide (i.e., toggle the visibility of) the selected elements.

We’ll learn about other more general ways to register event handlers in the section Advanced Event Handler Registration, and we’ll end this section with one more simple and convenient way to register handlers. Recall that you can pass a string of HTML to $() to create the elements described by that string, and that you can pass (as a second argument) an object of attributes to be set on the newly created elements. This second argument can be any object that you would pass to the attr() method. But, if any of the properties have the same name as the event registration methods listed above, the property value is taken as a handler function and is registered as a handler for the named event type. For example:

$("<img/>", {
    src: image_url,
    alt: image_description,
    className: "translucent_image",
    click: function() { $(this).css("opacity", "50%"); }
});

jQuery Event Handlers

The event handler functions in the examples above expect no arguments and return no values. It is quite normal to write event handlers like that, but jQuery does invoke every event handler with one or more arguments, and it does pay attention to the return value of your handlers. The most important thing you should know is that every event handler is passed a jQuery event object as its first argument. The fields of this object provide details (like mouse pointer coordinates) about the event. jQuery simulates the W3C standard Event object, even in browsers that do not support it (like IE8 and before), and jQuery event objects have the same set of fields in all browsers. This is explained in detail in The jQuery Event Object.

Normally, event handlers are invoked with only the single event object argument. But if you explicitly trigger an event with trigger() (see Triggering Events), you can pass an array of extra arguments. If you do this, those arguments will be passed to the event handler after the first event object argument.

Regardless of how they are registered, the return value of a jQuery event handler function is always significant. If a handler returns false, both the default action associated with the event and any future propagation of the event are canceled. That is, returning false is the same as calling the preventDefault() and stopPropagation() methods of the Event object. Also, when an event handler returns a value (other than undefined), jQuery stores that value in the result property of the Event object where it can be accessed by subsequently invoked event handlers.

The jQuery Event Object

jQuery hides implementation differences among browsers by defining its own Event object. When a jQuery event handler is invoked, it is always passed a jQuery Event object as its first argument. The jQuery Event object is based heavily on W3C standards, but it also codifies some de-facto event standards. jQuery does not define a hierarchy of Event object types, for example, there are not separate Event, MouseEvent, and KeyEvent types. jQuery copies all of the following fields from the native Event object into every jQuery Event object (though some of them will be undefined for certain event types):

altKey        ctrlKey         newValue        screenX
attrChange    currentTarget   offsetX         screenY
attrName      detail          offsetY         shiftKey
bubbles       eventPhase      originalTarget  srcElement
button        fromElement     pageX           target
cancelable    keyCode         pageY           toElement
charCode      layerX          prevValue       view
clientX       layerY          relatedNode     wheelDelta
clientY       metaKey         relatedTarget   which

In addition to these properties, the Event object also defines the following methods:

preventDefault()           isDefaultPrevented()
stopPropagation()          isPropagationStopped()
stopImmediatePropagation() isImmediatePropagationStopped()

Most of these event properties and methods are standardized by the W3C, and you can read about them in any JavaScript reference. Some of these fields, shown in the following list, are specially handled by jQuery to give them a uniform cross-browser behavior:

metaKey

If the native event object does not have a metaKey property, jQuery sets this to the same value as the ctrlKey property. In MacOS, the Command key sets the metaKey property.

pageX, pageY

If the native event object does not define these properties but does define the viewport coordinates of the mouse pointer in clientX and clientY, jQuery computes the document coordinates of the mouse pointer and stores them in pageX and pageY.

target, currentTarget, relatedTarget

The target property is the document element on which the event occurred. If the native event object has a text node as the target, jQuery reports the containing Element instead. currentTarget is the element on which the current executing event handler was registered. This should always be the same as this.

If currentTarget is not the same as target, you’re handling an event that has bubbled up from the element on which it occurred, and it may be useful to test the target element with the is() method (see Queries and Query Results):

// Ignore events that start on links
if ($(event.target).is("a")) return; 

relatedTarget is the other element involved in transition events such as “mouseover” and “mouseout”. For “mouseover” events, for example, the relatedTarget property specifies the element that the mouse pointer exited as it moved over the target. If the native event object does not define relatedTarget but does define toElement and fromElement, relatedTarget is set from those properties.

timeStamp

The time at which the event occurred, in the millisecond representation returned by the Date.getTime() method. jQuery sets the field itself to work around a long-standing bug in Firefox.

which

jQuery normalizes this nonstandard event property so that it specifies which mouse button or keyboard key was pressed during the event. For keyboard events, if the native event does not define which but defines charCode or keyCode, then which will be set to whichever of those properties is defined. For mouse events, if which is not defined but the button property is defined, which is set based on the button value: 0 means no buttons are pressed, 1 means the left button is pressed, 2 means the middle button is pressed, and 3 means the right button is pressed. (Note that some browsers don’t generate mouse events for right-button clicks.)

In addition, the following fields of the jQuery Event object are jQuery-specific additions that you may sometimes find useful:

data

If additional data was specified when the event handler was registered (see ), it is made available to the handler as the value of this field.

handler

A reference to the event handler function currently being invoked.

result

The return value of the most recently invoked handler for this event, ignoring handlers that do not return a value.

originalEvent

A reference to the native Event object generated by the browser.

Advanced Event Handler Registration

We’ve seen that jQuery defines quite a few simple methods for registering event handlers. Each of these simply invokes the single, more complex method bind() to bind a handler for a named event type to each of the elements in the jQuery object. Using bind() directly allows you to use advanced event registration features that are not available through the simpler methods.[2]

In its simplest form, bind() expects an event type string as its first argument and an event handler function as its second. The simple event registration methods use this form of bind(). The call $('p').click(f), for example, is equivalent to:

$('p').bind('click', f);

bind() can also be invoked with three arguments. In this form, the event type is the first argument and the handler function is the third. You can pass any value between those two and jQuery will set the data property of the Event object to the value you specify before it invokes the handler. It is sometimes useful to pass additional data to your handlers in this way without having to use closures.

There are other advanced features of bind() as well. If the first argument is a space-separated list of event types, the handler function will be registered for each of the named event types. The call $('a').hover(f) (see Simple Event Handler Registration), for example, is the same as:

$('a').bind('mouseenter mouseleave', f);

Another important feature of bind() is that it allows you to specify a namespace (or namespaces) for your event handlers when you register them. This allows you to define groups of handlers, which comes in handy if you later want to trigger or de-register the handlers in a particular namespace. Handler namespaces are especially useful for programmers who are writing libraries or modules of reusable jQuery code. Event namespaces look like CSS class selectors. To bind an event handler in a namespace, add a period and the namespace name to the event type string:

// Bind f as a mouseover handler in namespace "myMod"
$('a').bind('mouseover.myMod', f);

You can even assign a handler to multiple namespaces, like this:

// Bind f as a mouseout handler in two namespaces
$('a').bind('mouseout.myMod.yourMod', f);

The final feature of bind() is that the first argument can be an object that maps event names to handler functions. To reuse the hover() method example, the call $('a').hover(f,g) is the same as:

$('a').bind({mouseenter:f, mouseleave:g});

When you use this form of bind(), the property names in the object you pass can be space-separated strings of event types and can include namespaces. If you specify a second argument after the first object argument, that value is used as the data argument for each of the event bindings.

jQuery has another event handler registration method: one(). This method is invoked and works just like bind(), except that the event handler you register will automatically de-register itself after it is invoked. As the method name implies, this means that event handlers registered with one() will never be triggered more than once.

One feature that bind() and one() do not have is the ability to register capturing event handlers as you can with addEventListener(). IE (until IE9) does not support capturing handlers, and jQuery does not attempt to simulate that feature.

Deregistering Event Handlers

After registering an event handler with bind() (or with any of the simpler event registration methods) you can deregister it with unbind() to prevent it from being triggered by future events. (Note that unbind() only deregisters event handlers registered with bind() and related jQuery methods. It does not deregister handlers passed to addEventListener() or the IE method attachEvent(), and it does not remove handlers defined by element attributes such as onclick and onmouseover.) With no arguments, unbind() deregisters all event handlers (for all event types) for all elements in the jQuery object:

// Remove all jQuery event handlers from all elements!
$('*').unbind();  

With one string argument, all handlers for the named event type (or types, if the string names more than one) are unbound from all elements in the jQuery object:

// Unbind all mouseover and mouseout handlers
// of all <a> tags
$('a').unbind("mouseover mouseout"); 

This is a heavy-handed approach and should not be used in modular code because someone might also be using other modules that register their own handlers for the same event types on the same elements. If your module registered event handlers using namespaces, however, you can use this one-argument version of unbind() to deregister only the handlers in your namespace:

// Unbind all mouseover and mouseout handlers
// in the "myMod" namespace
$('a').unbind("mouseover.myMod mouseout.myMod"); 
// Unbind handlers for any event in the myMod namespace
$('a').unbind(".myMod");
// Unbind click handlers that are in both namespaces
$('a').unbind("click.ns1.ns2");

If you want to be careful to unbind only event handlers you registered yourself, and you did not use namespaces, you must retain a reference to the event handler functions and use the two-argument version of unbind(). In this form, the first argument is an event type string (without namespaces), and the second argument is a handler function:

$('#mybutton').unbind('click', myClickHandler);

When invoked this way, unbind() deregisters the specified event handler function for events of the specified type (or types) from all elements in the jQuery object. Note that event handlers can be unbound using this two-argument version of unbind(), even when they were registered with an extra data value using the three-argument version of bind().

You can also pass a single object argument to unbind(). In this case, unbind() is invoked recursively for each property of the object. The property name is used as the event type string, and the property value is used as the handler function:

$('a').unbind({  // Remove specific event handlers
   mouseover: mouseoverHandler,
   mouseout: mouseoutHandler
});

Finally, there is one more way that unbind() can be invoked. If you pass a jQuery Event object to it, it unbinds the event handler to which that event was passed. Calling unbind(ev) is equivalent to unbind(ev.type, ev.handler).

Triggering Events

The event handlers you register are automatically invoked when the user uses the mouse or keyboard, or when other kinds of events occur. Sometimes, however, it is useful to be able to trigger events manually. The simple way to do this is to invoke one of the event registration methods (like click() or mouseover()) with no argument. Just as many jQuery methods serve as both getters and setters, these event methods register an event handler when invoked with an argument, and trigger event handlers when invoked with no arguments. For example:

// Act as if the user clicked the Submit button
$("#my_form").submit();    

The submit() method in the line above synthesizes an Event object and triggers any event handlers that have been registered for the “submit” event. If none of those event handlers returns false or calls the preventDefault() method of the Event object, the form will actually be submitted. Note that events that bubble will do so even when triggered manually. This means that triggering an event on a selected set of elements may also trigger handlers on the ancestors of those elements.

It is important to note that jQuery’s event triggering methods will trigger any handlers registered with jQuery’s event registration methods, and they will also trigger handlers defined on HTML attributes or Element properties such as onsubmit. But you cannot manually trigger event handlers registered with addEventListener() or attachEvent() (those handlers will still be invoked when a real event occurs, however).

It is also important to note that jQuery’s event triggering mechanism is synchronous—there is no event queue involved. When you trigger an event, event handlers are invoked immediately, before the triggering method you called returns. If you trigger a “click” event, and one of the triggered handlers triggers a “submit” event, all of the matching submit handlers are invoked before the next “click” handler is invoked.

Methods like submit() are convenient for binding and triggering events, but just as jQuery defines a more general bind() method, it also defines a more general trigger() method. Normally, you invoke trigger() with an event type string as the first argument, and it triggers the handlers registered for events of that type on all elements in the jQuery object. So, the submit() call above is equivalent to:

$("#my_form").trigger("submit");

Unlike the bind() and unbind() methods, you cannot specify more than one event type in this string. Like bind() and unbind(), however, you can specify event namespaces to trigger only the handlers defined in that namespace. If you want to trigger only event handlers that have no namespace, append an exclamation mark to the event type. Handlers registered through properties like onclick are considered to have no namespace:

// Trigger button click handlers in namespace ns1
$("button").trigger("click.ns1");  
// Trigger button click handlers in no namespace
$("button").trigger("click!");     

Instead of passing an event type string as the first argument to trigger(), you can also pass an Event object (or any object that has a type property). The type property will be used to determine what kind of handlers to trigger. If you specified a jQuery Event object, it will be the one passed to the triggered handlers. If you specified a plain object, a new jQuery Event object will be created, and the properties of the object you passed will be added to it. This is an easy way to pass additional data to event handlers:

// The onclick handler of button1 triggers
// the same event on button2
$('#button1').click(function(e) {
    $('#button2').trigger(e);
});

// Add extra property to the event object when triggering
$('#button1').trigger({type:'click', synthetic:true});

// Test extra property to distinguish real from synthetic
$('#button1').click(function(e) {
    if (e.synthetic) {...};
});

There is another way to pass additional data to event handlers when you trigger them manually. The value you pass as the second argument to trigger() will become the second argument to each of the event handlers that is triggered. If you pass an array as the second argument, each of its elements will be passed as arguments to the triggered handlers:

// Pass a single extra argument
$('#button1').trigger("click", true);    
// Pass three extra arguments
$('#button1').trigger("click", [x,y,z]); 

Sometimes you may want to trigger all handlers for a given event type, regardless of which document element those handlers are bound to. You could select all elements with $('*') and then call trigger() on the result, but that would be very inefficient. Instead, call the jQuery.event.trigger() utility function, which takes the same arguments as the trigger() method but efficiently triggers event handlers for the specified event type throughout the document. Note that “global events” triggered in this way do not bubble, and only handlers registered using jQuery methods (not event handlers registered with DOM properties like onclick) are triggered with this technique.

After invoking event handlers, trigger() (and the convenience methods that call it) perform whatever default action is associated with the triggered event (assuming that the event handlers didn’t return false or call preventDefault() on the event object). For example, if you trigger a “submit” event on a <form> element, trigger() will call the submit() method of that form, and if you trigger a “focus” event on an element, trigger() will call the focus() method of that element.

If you want to invoke event handlers without performing the default action, use triggerHandler(), which works just like trigger() except that it first calls the preventDefault() and cancelBubble() methods of the Event object. This means that the synthetic event does not bubble or perform the default action associated with it.

Custom Events

jQuery’s event management system is designed around the standard events like mouse clicks and key presses that web browsers generate. But it is not tied to those events, and you can use any string you want as an event type name. With bind(), you can register handlers for this kind of “custom event”, and with trigger() you can cause those handlers to be invoked.

This kind of indirect invocation of custom event handlers turns out to be quite useful for writing modular code and implementing a publish/subscribe model or the Observer pattern. When using custom events you may find it useful to trigger them globally with the jQuery.event.trigger() function instead of the trigger() method:

// When the user clicks the "logoff" button, broadcast a
// custom event to any interested observers that need to
// save their state and then navigate to the logoff page.
$("#logoff").click(function() {
    $.event.trigger("logoff");      // Broadcast an event
    window.location = "logoff.php"; // Go to a new page
});

We’ll see in Ajax Events that jQuery’s Ajax methods broadcast custom events like this to notify interested listeners.

Live Events

The bind() method binds event handlers to specific document elements, just as addEventListener() and attachEvent() do. But web applications that use jQuery often dynamically create new elements. If we’ve used bind() to bind an event handler to all <a> elements in the document, and then we create new document content with new <a> elements, those new elements will not have the same event handlers as the old ones, so they will behave differently.

jQuery addresses this issue with “live events”. To use live events, use the delegate() and undelegate() methods instead of bind() and unbind(). delegate() is usually invoked on $(document) and is passed a jQuery selector string, a jQuery event type string, and a jQuery event handler function. It registers an internal handler on the document or window (or on whatever elements are in the jQuery object). When an event of the specified type bubbles up to this internal handler, it determines whether the target of the event (the element that the event occurred on) matches the selector string. If so, it invokes the specified handler function. So to handle “mouseover” events on both old and newly created <a> elements, you might register a handler like this:

$(document).delegate("a", "mouseover", linkHandler);

Or, you might use bind() in the static portions of your document and then use delegate() to handle the portions that change dynamically:

// Static event handlers for static links
$("a").bind("mouseover", linkHandler);
// Live event handlers for dynamic parts of the document
$(".dynamic").delegate("a", "mouseover", linkHandler);

Just as the bind() method has a three-argument version that allows you to specify the value of the data property of the event object, the delegate() method has a four-argument version that allows the same thing. To use this version, pass the data value as the third argument and the handler function as the fourth.

It is important to understand that live events depend on event bubbling. By the time an event bubbles up to the document object, it may have already been passed to a number of static event handlers. And if any of those handlers called the cancelBubble() method of the Event object, the live event handler will never be invoked.

jQuery defines a method named live() that can also be used to register live events. live() is a little harder to understand than delegate(), but it has the same two- or three-argument signature as bind() and is more commonly used. The two calls to delegate() shown above could also be written using live():

$("a").live("mouseover", linkHandler);
$("a", $(".dynamic")).live("mouseover", linkHandler);

When the live() method is invoked on a jQuery object, the elements in that object are not actually used. What matters instead is the selector string and the context object (the first and second arguments to $()) that were used to create the jQuery object. jQuery objects make these values available through their context and selector properties (see Queries and Query Results). Normally, you invoke $() with only one argument and the context is the current document. So for a jQuery object x, the following two lines of code do the same thing:

x.live(type,handler);
$(x.context).delegate(x.selector, type, handler);

To deregister live event handlers, use die() or undelegate(). die() can be invoked with one or two arguments. With one event type argument, it removes all live event handlers that match the selector and the event type. And with an event type and handler function argument, it removes only the one specified handler. Some examples:

// Remove all live handlers for mouseover on <a> tags
$('a').die('mouseover');  
// Remove just one specific live handler
$('a').die('mouseover', linkHandler); 

undelegate() is like die() but more explicitly separates the context (the elements on which the internal event handlers are registered) and the selector string. The calls to die() above could instead be written like this:

// Remove all live handlers for <a> tags
$(document).undelegate('a'); 
// Remove all live mouseover handlers for <a> tags
$(document).undelegate('a', 'mouseover'); 
// Remove one live mouseover handler for <a> tags
$(document).undelegate('a', 'mouseover', linkHandler);

Finally, undelegate() can also be called with no arguments at all. In this case, it deregisters all live event handlers that are delegated from the selected elements.



[2] jQuery uses the term “bind” for event handler registration. ECMAScript 5, and a number of JavaScript frameworks, define a bind() method on functions, and use the term for the association of functions with objects on which they are to be invoked. jQuery’s version of the Function.bind() method is a utility function named jQuery.proxy(), which you can read about in Chapter 7.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required