Events
When an event handler is fired, an instance of an object name Event is passed to the handler as its first parameter
on(eventType[, selector][, data], handler)
on(eventsHash[, selector][, data])
// passing data to the event handler
$('#my-button').on('click', {
name: 'John Resig'
}, function (event) {
console.log('The name is: ' + event.data.name);
return false;
});
// return false from an event handler
// added using this JQuery method is the same as calling preventDefault()
// and stopPropgation(), whereas returning false in a event handler added
// using an native method is equivalent to only invoking preventDefault()
Event Instance
In reality, jQuery defines an object of type of jQuery.Event that it passes to the handlers. jQuery copies most of hte original Event properties to this object.
Event Delegation
It is an important technique that suggest that you attach the handler to a parent of the element(s) instead of the element(s) itself.
The events will be bound to all of the elements within the list, which use more memory than it is needed. We can get around this by using event delegation, where we can shift to binding one event handler to a single ancestor element that serves multiple descendants.
Event delegation relies on the use of event propagation, or event bubbling.
The event is dispatched in one of three phases: capturing, target, and bubbling.
// Attach a delegated event handler
$('a').on('click', function () {
$(this).css('background-color', '#f00');
});
// Attach a single click event listener to list that will listen
// for clicks on its descendant anchors, instead of attaching an
// unknown number of directly bound events to th existing anchor tags only.
$( "#list" ).on( "click", "a", function( event ) {
event.preventDefault();
console.log( $( this ).text() );
});
// Attach a directly bound event handler
$( "#list a" ).on( "click", function( event ) {
event.preventDefault();
console.log( $( this ).text() );
});
Allows us to attach a single event listener, to a parent element, that will fire for all descendants matching a selector, whether those descendants exits now or are added in the future.
Refers to the process of using event propagation (bubbling) to handle events at a higher level in the DOM than the element on which the event originated. It allows us to attach a single event listener for elements that don't exist now.
If we trigger an event on a specific element, such as an anchor tag for example, then this will be allowed to handle the event fist. The event will bubble up until it reaches document level, or a lower event handler decides to stop event propagation. This last part is key – without control, we could end up with unexpected results, where event handlers have responded, or not fried, contrary to expectations.
<ul id="list"> <li class="ui-widget-content"><a href="#">remove1</a></li> <li class="ui-widget-content"><a href="#">remove2</a></li> <li class="ui-widget-content"><a href="#">remove3</a></li> <li class="ui-widget-content"><a href="#">remove4</a></li> <li class="ui-widget-content"><a href="#">remove5</a></li> <li class="ui-widget-content"><a href="#">remove6</a></li> </ul> /* element "li" event is invoked, so the event is bubbled to its parent "ul", when "ul" invokes the event (removelistItem), it removes the list items. */ $('ul').on("click", "li", removelistItem);
To control which elements might trigger a delegated event handler, we can use one of the following two tricks:
event.stopPropagation()
document.ready(function ($) { $('div'). on("click", function (event) { console.log('You clicked the outer div'); }); $('span').on("click", function (event) { console.log('You clicked a span inside of a div element'); event.stopPropagation(); }); })
trapping the event target, and determining if it matches a given set of conditions (such as a specifi class or data- name), it can prevent parent elements to invoke the event
$("ul.my-list").click(function(event) { if ( $( event.target).hasClass("my-item") ) { handleListItemAction(event.target); } else if ( $( event.target).hasClass("my-button") ) { handleButtonClickedAction(evt.target); } }); // the event will be called if it has a class name as "my-item" $("ul.my-list").on("click",".my-item", function(evt) { //do stuff });
Event Capturing
One strategy for allowing multiple elements to respond to a user interaction is called event capturing. With event capturing, the event is first given to the most allencompassing element, and then to progressively more specific ones.
Event Bubbling
The event gets sent to the most specific element, and after this element has an opportunity to react, the event bubbles upto more general elements
// Unfinished code
$(document).ready(function() {
$('#switcher').click(function(event) {
if (event.target == this) {
$('#switcher button').toggleClass('hidden');
}
});
});
// This code ensures that the item clicked on was <div id="switcher">, not one of its sub-elements.
// Now, clicking on buttons will not collapse the style switcher,
// but clicking on the switcher's background will.
// However, clicking on the label, <h3>, now does nothing, because it too is a sub-element.
// Instead of placing this check here, we can modify the behavior of the buttons to achieve our goals
$(document).ready(function() {
$('#switcher-default').addClass('selected');
$('#switcher button').click(function(event) {
var bodyClass = this.id.split('-')[1];
$('body').removeClass().addClass(bodyClass);
$('#switcher button').removeClass('selected');
$(this).addClass('selected');
// call event.stopPropagation()to prevent any other DOM element from responding to the event.
// Now our click is handled by the buttons, and only the buttons;
// clicks anywhere else on the style switcher will collapse or expand it.
event.stopPropagation();
});
});
trigger
trigger(eventTarget[, data])
// event: the name of the event type
// data: any data to be passed to the handler
// if any array is provided, the elements are passed to the handler as different parameters.
// event
$('#foo').on('click', function (event, par1, par2, par3) {
console.log(par1, par2, par3);
});
// trigger
$('#foo').trigger('click', 1, 2, 3);
// result: 1 undefined undefined
$('#foo').trigger('click', [1, 2, 3]);
// result: 1 2 3
triggerHandler
Trigger a handler but not cause propagation of the event and execution of semanic actions.
Event Short Cut
Event Shortcut Trigger
$('#btn')
.on('click', function() {
console.log('Button clicked');
})
.trigger('click');
// Using the shortcuts just discussed, you can change it as follows:
$('#btn')
.click(function() {
console.log('Button clicked');
})
.click();
hover works differently
Custom Events
It turns out that custom events offer a whole new way of thinking about event-driven JavaScript. Instead of focusing on the element that triggers an action, custom events put the spotlight on the element being acted upon.
They put the emphasis on the target of a behavior, not on the element that triggers it.
trigger(eventType[, data])
// A basic example of creating and using a custom event is shown here:
$('#btn').on('customEvent', function(){
alert('customEvent');
});
// call from other
$('#anotherBtn').click(function() {
$('#btn').trigger('customEvent');
});
<!--
Suppose you have a lightbulb in a room in a house.
The lightbulb is currently turned on, and it's controlled by two three-way switches and a clapper:
-->
<div class="room" id="kitchen">
<div class="lightbulb on"></div>
<div class="switch"></div>
<div class="switch"></div>
<div class="clapper"></div>
</div>
// without custom event
$( ".switch, .clapper" ).click(function() {
var light = $( this ).closest( ".room" ).find( ".lightbulb" );
if ( light.is( ".on" ) ) {
light.removeClass( "on" ).addClass( "off" );
} else {
light.removeClass( "off" ).addClass( "on" );
}
});
// with custom event "ligt:toggle"
$( ".lightbulb" ).on( "light:toggle", function( event ) {
var light = $( this );
if ( light.is( ".on" ) ) {
light.removeClass( "on" ).addClass( "off" );
} else {
light.removeClass( "off" ).addClass( "on" );
}
});
$( ".switch, .clapper" ).click(function() {
var room = $( this ).closest( ".room" );
room.find( ".lightbulb" ).trigger( "light:toggle" );
});
Examples
//
$('p').on('click', function () {
alert($(this).text());
});
//
function myHandler (event) {
alert(event.data.foo);
}
$('p').on('click', {foo: "bar"}, myHandler);
// cancel a form submit action and prevent the event from bubbling up by returning false
$("form").on("submit", false);
// cancel only the default action by using .preventDefault()
$("form").on("submit", function (event) {
event.preventDefault();
});
// stop submit events from bubbling without preventing from submit, using .stopPropgation()
$("form").on("submit", function (event) {
event.stopPropagation();
});
// Pass data to the event handler using the second argument to .trigger()
$( "div" ).on( "click", function( event, person ) {
alert( "Hello, " + person.name );
});
$( "div" ).trigger( "click", { name: "Jim" } );
// Use the second argument of .trigger() to pass an array of data to the event handler
$( "div" ).on( "click", function( event, salutation, name ) {
alert( salutation + ", " + name );
});
$( "div" ).trigger( "click", [ "Goodbye", "Jim" ] );
// Attach and trigger custom (non-browser) events
$( "p" ).on( "myCustomEvent", function( event, myName ) {
$( this ).text( myName + ", hi there!" );
$( "span" )
.stop()
.css( "opacity", 1 )
.text( "myName = " + myName )
.fadeIn( 30 )
.fadeOut( 1000 );
});
$( "button" ).click(function () {
$( "p" ).trigger( "myCustomEvent", [ "John" ] );
});
//Attach multiple event handlers simultaneously
// using a plain object
$( "div.test" ).on({
click: function() {
$( this ).toggleClass( "active" );
}, mouseenter: function() {
$( this ).addClass( "inside" );
}, mouseleave: function() {
$( this ).removeClass( "inside" );
}
});
// Display each paragraph's text in an alert box whenever it is clicked:
$( "body" ).on( "click", "p", function() {
alert( $( this ).text() );
});
// Cancel a link's default action using the .preventDefault() method:
$( "body" ).on( "click", "a", function( event ) {
event.preventDefault();
});
// Attach multiple events—one on mouseenter and one on mouseleave to the same element:
$( "#cart" ).on( "mouseenter mouseleave", function( event ) {
$( this ).toggleClass( "active" );
});