jQuery - Event Handling

jquery

http://www.sitepoint.com/comprehensive-events-jquery/
http://api.jquery.com/category/events/event-object
https://www.sitepoint.com/effective-event-binding-jquery

jquery-event-delegation
jquery-event-namespacing
jquery-custom-event
jquery-special-event-api

http://net.tutsplus.com/tutorials/javascript-ajax/custom-events-and-special-events-api-in-jquery/
http://net.tutsplus.com/tutorials/javascript-ajax/uncovering-jquerys-hidden-features/
http://www.sitepoint.com/effective-event-binding-jquery
http://www.ravelrumba.com/blog/event-delegation-jquery-performance/ Event Delegation, live vs bind vs other options)

How can we disable CTRL+P?

function disablePrintShortcut(e) {
    if ((e.which == 80) && (e.ctrlKey)) {
        var hasPrint = jQuery('#printPrivilege').val();
        if (hasPrint == "NO") {
            e.preventDefault();
            e.stopPropagation();
            alert("You do not have privilege to print this page");
            return false;
        }
    }
}
$(document).ready(function() {
    jQuery(document).bind("keyup keydown", disablePrintShortcut);
    jQuery(window).on('beforeprint', function() { return false; });
});

It seems that it is not possible to silently prevent CTRL+P without the use of window.alert.

What are the properties of the event object?

Property Description
altKey Set to true if the Alt key was pressed when the event was triggered. The Alt key is labeled as Option on most Mac keyboards
ctrlKey Set to true if the Ctrl key was pressed
data The value, if any, that was passed as parameter to the bind() command when the handler was registered
keyCode For keyup and keydown events, this returns the key that was pressed. For alphanumeric characters, the uppercase version of the letter will be returned, regardless of whether the user typed an uppercase or lowercase letter. You can use the shiftKey to determine which case was entered. For keypress events, use the 'which' property which is reliable across browsers.
metaKey Set to tru if the Meta key was pressed when the event was triggered. The Meta key is the Ctrl key on PCs, and the Command key on Mac
pageX For mouse events, specifies the horizontal coordinate of the event relative from the page origin
pageY For mouse events, specifies the vertical coordinate of the event relative from the page origin
relatedTarget For some mouse events, identifies the element that the cursor left or entered when the event was triggered
screenX For mouse events, specifies the horizontal coordinate of the event relative from the screen origin.
screenY For mouse events, specifies the vertical coordinate of the event relative from the screen origin.
shiftKey Set to true if the Shift key was pressed when the event was triggered.
target Identifies the element for which the event was triggered.
type For all events, specifies the type of event that was triggered. This can be useful if you are using one event handler for multiple event types.
which For keyboard events, specifies the numeric code for the key that caused the event, and for mouse events, specifies which button was press (1 for left, 2 for middle, and 3 for right). This should be used instead of 'button' which can't be relied on to function consistently across browsers.

The keypress property is not reliable cross-browser for non-alphanumeric character. For example, the left arrow key has a code of 37, which works reliably on keyup and keydown events. Safari returns nonstandard results for these keys on a keypress event.

We can get a reliable, case-sensitive character code in the 'which' property of keypress events. During keyup and keydown events, we can only get a case-insensitive key code (so a and A both return 65), but we can determine case by checking shiftKey.

How can we listen for an event?

$("#myBtn").bind("click", function(evt) {
});

How can we trigger an event?

$("#myBtn").trigger("click");
$('#myBtn').click();

How can we implement custom events using .bind() and trigger()?

The method .bind() isn’t just limited to browser events, but can be used to implement your own custom events. Let’s begin by creating custom events named collapse and expand for our directory listing example. First, let’s bind a collapse event to all directories represented in our unordered list.

$("#tree li:parent").bind("collapse", function(evt) {
    $(evt.target).children().slideUp().end().addClass("collapsed");
}).bind("expand", function(evt) {
    $(evt.target).children().slideDown().end().removeClass("collapsed");
})).toggle(function() { // toggle between
    $(this).trigger("collapse");
}, function() {
    $(this).trigger("expand");
});

The code above indicates that custom events can be bound to DOM nodes. The code above also use the toggle() function, which display or hide the matched elements. In the above code we are using a ul element to display a directory. The collapse and expand events are bind to the ul element. Within these event handlers, we query for the target of the event (evt.target), which is the ul element, and then we find all children elments, and collapse or expand the children elements. If we run this code, our directories will now toggle when clicked between firing the collapse and expand event. But, if you click a nested directory you’ll notice our events are actually firing multiple times per a click. This is because of event bubbling.

Is event handling ONLY applicable to DOM elements?

No. Event handling is NOT ONLY applicable to DOM elements (or UI elements). It is for other custom objects as well. It is known as "event driven", observer / dispatcher pattern. jQuery allows event driven architecture to be applied to javascript object, as well as native object. See Custom Event

Does jQuery support the beforeunload and error event on the window object?

No. The beforeunload and error events on the window object use nonstandard conventions, and are not supported by jQuery (jQuery does not offer a convenient method for these events). You must attach the handler directly to the window object.

What should we know about the convenient error method?

jQuery has a convenient method name error() which is a shortcut for:

.bind('error', function(event){...});

The error event is sent to elements such as images. It is called if the element is not loaded correctly.

The error event may not be fired correctly when the page is served locally. Since error relies on normal HTTP status code, it will generally not be triggered if the URL use the file protocol.

jQuery error event handler should not be attached to the window object. The browser fires the window's error when a script error occurs. However, the window error event receives different arguments and has different return value requirements than the conventional event handlers.

// Hide javascript errors from the user.  Use this at your own risk
// If you need to log the line numbers where the event happen, etc, look elsewhere on this wiki
$(window).error(function() {
    return true;
});

What happens when an event reaches an element?

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.

How can you bind a handler to multiple events in one shot?

If you have an event handler that is applicable to multiple events, you can bind this handler to multiple events in one shot:

$("#foo").bind('mouseover mouseout', function(event) {...});

You can specify multiple events (separated by space).

How can we bind multiple events to multiple elements in one shot?

$("#foo").bind({
    'click': function(event) { ... },
    'mouseover': function(event) {...}
});

Within the body of your event handler, what is the meaning of the this keyword?

Within the handler, the keyword this refers to the DOM element which the handler is bound. To make use of the element using jQuery, wrap it inside the normal $() function:

$(this)

How can your event handler gain access to the event object?

When your handler is called, the event object is passed to your handler as the first parameter.

What does returning false from inside your handler mean?

Returning false from a handler is equivalent to calling both .preventDefault() and .stopPropagation()

How can we pass additional information (at the time the handler is bound) to your event handler ?

The optional eventData parameter to bind() is not commonly used. When provided, this argument allows you to pass additional information to the handler. One handy use of this parameter is to work around limitation of closures. For example, suppose that we have two event handlers that 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 both refers to messages, both will display 'Not in the face!' when triggered. To sidestep this problem, we can pass the message using 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 refered to directly within the handlers. Instead, the variable is passed in by value through eventData, which fixes the value at the time the event is bound. The first handler now display 'Spoon!'. The second handler now display 'Not in the face!'

How to unbind all click event handlers that are bound to a given element?

$('#foo').unbind('click');

If you have to use unbind() like this, chance are that you are doing something wrong. End user of your plugin may have other handlers attached to the same element. If you want to remove just your click handler, use namespace.

How can we unbind all handlers attached to a given element?

$('#foo').unbind();

This removes all handlers regardless of type. If you have to use unbind() like this, chance are that you are doing something wrong. End user of your plugin may have other handlers attached to the same element.

How can we unbind a handler from within itself?

For example, suppose that we wish to trigger an event handler on 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);
    }
});

Noticed that unbind() is called with the event object. 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.

What are the different between trigger() and triggerHandler()?

  1. While trigger() simulates an event activation, complete with a synthesized event object, it does not perfectly replicate a naturally-occuring event. To trigger handlers bound via jQuery without also triggering the native event, use triggerHandler(). The triggerHandler() method does not cause the default behavior of an event to occur (such as form submission).
  2. trigger() will operate on all elements matched by the jQuery object. triggerHandler() only affect the first matched element.
  3. Events created with triggerHandler() do not bubble up the DOM hierarchy. If they are not handled by the target element directly, they do nothing.
  4. Instead of returning the jQuery object (to allow chaining), triggerHandler() returns whatever value was returned by the last handler it caused to be executed. If no handlers are triggered, it returns undefined.

How can we pass additional information to your handler at the time the event is triggered?

Well, obviously, you have to use trigger() or triggerHandler(). The trigger() method takes eventType as the first parameter. It also takes a second parameter, which is passed to your handler as the second parameter (the first parameter for an event handler is always the event object).

How can we create a jQuery event object?

var event = jQuery.Event("submit");
$("#foo").trigger(event);

How can we pass arbitrary data through an event object using trigger()?

var event = jQuery.Event("logged");
event.user = "foo";
event.pass = "bar";
$("body").trigger(event);

$("body").trigger({
    'type': 'logged',
    'user': 'foo',
    'pass': 'bar'
});

What is the purpose of the proxy() method?

It makes it easy to use OOP for event handler:

$(document).ready(function() {
    function BaseObject(){
    this.sampleValue = 50;
    };
    BaseObject.prototype = { 
    init: function() {
        $(document).bind('click', {arg1:'value1',arg2:'value2'}, $.proxy(obj.showSampleValue, obj));
    },
    showSampleValue: function() {
         alert(this.sampleValue);
    }
    };
    var obj = new BaseObject();
    obj.init();
});

Inside your handler, the this keyword, which is normally the DOM element that cause the event, now is an object of BaseObject. If you need to know the DOM element that the event happen on, your handler need to accept the event object as argument (you can use event.currentTarget), or you can use arguments[0].

The proxy() method takes a function and returns a new one that will always have a particular context. This method is most useful for attaching event handlers to an element where the context is pointing back to a different object.

Additionally, jQuery makes sure that even if you bind the function returned from jQuery.proxy() it will still unbind the correct function, if passed the original.

How can we register an event handler such that it is run only one time and then automatically disabled or removed?

Use the .one method:

one(eventType, data, listener)

How can we unbind a particular event listener?

unbind(eventType, listener)
unbind(eventType)

What is the purpose of the hover command?

The hover command take two parameters, the overListener and the outListener. It simplifies the .mouseover and .mouseout combination a bit.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License