jQuery's event system is one of its most powerful features. It normalizes event handling across browsers and provides convenient shorthand methods.
Basic Event Binding
JavaScript
// Click
$('button').on('click', function() {
$(this).toggleClass('active');
});
// Multiple events
$('input').on('focus blur', function(event) {
$(this).toggleClass('focused', event.type === 'focus');
});
// Shorthand methods
$('button').click(handler);
$('input').focus(handler);
$('input').blur(handler);
$('input').change(handler);
$('input').keydown(handler);
$('form').submit(handler);Event Object
JavaScript
$('button').on('click', function(event) {
// event properties
event.type; // 'click'
event.target; // The clicked element (native DOM)
event.currentTarget; // Element handler is attached to
event.pageX; // Mouse X position on page
event.pageY; // Mouse Y position on page
event.which; // Key code (keyboard) or button (mouse)
// Methods
event.preventDefault(); // Prevent default browser behavior
event.stopPropagation(); // Stop event from bubbling up
event.stopImmediatePropagation(); // Stop other handlers on same element
// Custom data
event.data; // Data passed to handler
});Event Delegation
Instead of binding to each element, bind to a parent. Events "bubble up" from children.
JavaScript
// BAD: Doesn't work for dynamically added elements
$('li').on('click', function() { ... });
// GOOD: Works for all current and future <li> elements
$('ul').on('click', 'li', function() {
$(this).toggleClass('selected');
});
// Practical example: table rows
$('#users-table').on('click', 'tr', function() {
var userId = $(this).data('id');
window.location.href = '/users/' + userId;
});Mouse Events
JavaScript
$('.hover-card')
.on('mouseenter', function() {
$(this).stop().animate({ scale: 1.05 }, 200);
})
.on('mouseleave', function() {
$(this).stop().animate({ scale: 1 }, 200);
});
// Mouse position tracking
$(document).on('mousemove', function(e) {
$('#cursor').css({ left: e.pageX, top: e.pageY });
});Keyboard Events
JavaScript
$(document).on('keydown', function(e) {
// Common key codes
if (e.keyCode === 27) { // ESC key
$('.modal').hide();
}
if (e.ctrlKey && e.keyCode === 83) { // Ctrl+S
e.preventDefault();
saveDocument();
}
});
// Specific input handling
$('#search').on('keyup', function(e) {
var query = $(this).val();
if (e.keyCode === 13) { // Enter
performSearch(query);
}
});Custom Events
JavaScript
// Trigger custom events
$('body').on('userLogin', function(event, username) {
console.log(username + ' logged in');
updateUI(username);
});
// Trigger with data
$('body').trigger('userLogin', ['Alice']);
// Custom event in a plugin
$.fn.loading = function(state) {
return this.each(function() {
var $el = $(this);
if (state) {
$el.addClass('loading').trigger('loadingStart');
} else {
$el.removeClass('loading').trigger('loadingEnd');
}
});
};Event Namespace
JavaScript
// Organize events by namespace
$('#element')
.on('click.module1', handler1)
.on('click.module2', handler2)
.on('mouseover.module1', handler3);
// Remove all module1 events
$('#element').off('.module1');
// Remove all click events
$('#element').off('click');Practical: Live Search
JavaScript
var searchTimer;
$('#search-input').on('keyup', function() {
clearTimeout(searchTimer);
var query = $(this).val().trim();
if (query.length < 2) {
$('#results').empty();
return;
}
searchTimer = setTimeout(function() {
$.get('/api/search', { q: query }, function(data) {
var html = data.map(function(item) {
return '<li>' + item.title + '</li>';
}).join('');
$('#results').html(html || '<li>No results</li>');
});
}, 300); // Debounce: wait 300ms after last keystroke
});💡 Tip: Always use event delegation (
.on('click', 'selector', handler)) for elements that may be added dynamically. It's faster and more reliable.
Next: AJAX and Effects