Events

Binding events with .on(), event delegation for dynamic content, and common event types.

Binding events with .on()

.on() is jQuery's unified method for attaching event handlers — it replaced older, more specialized methods (.bind(), .live(), .delegate()) from earlier jQuery versions:

Javascript
$('#save-btn').on('click', function () {
    console.log('Save clicked');
});

$('#search-input').on('keyup', function () {
    console.log('Current value:', $(this).val());
});

$('#signup-form').on('submit', function (event) {
    event.preventDefault(); // stop the browser's default full-page form submission
    console.log('Form submitted via AJAX instead');
});

Inside a handler, this refers to the raw DOM element the event fired on — wrap it in $(this) to use jQuery methods on it.

Common events

Event Fires when
click An element is clicked
submit A <form> is submitted
keyup / keydown A key is released / pressed, while an element has focus
change A form field's value changes and it loses focus (or immediately, for checkboxes/selects)
input A form field's value changes, fired on every keystroke
mouseenter / mouseleave The pointer enters / leaves an element (doesn't bubble to children, unlike mouseover/mouseout)
focus / blur An element gains / loses keyboard focus

Event delegation

Event delegation attaches a single handler to a stable ancestor element, and listens for events bubbling up from descendants that match a selector — instead of attaching a separate handler to every individual descendant. This matters most for elements added to the page after the page first loads, since a handler bound directly to an element that doesn't exist yet simply never fires for it.

HTML
<ul id="todo-list">
    <li>Buy milk <button class="delete-btn">Delete</button></li>
    <li>Walk the dog <button class="delete-btn">Delete</button></li>
</ul>
<button id="add-item">Add item</button>
Javascript
// WRONG for dynamic content — only binds to buttons that exist right now
$('.delete-btn').on('click', function () {
    $(this).closest('li').remove();
});

// RIGHT — delegated from a stable ancestor that already exists on page load
$('#todo-list').on('click', '.delete-btn', function () {
    $(this).closest('li').remove();
});

$('#add-item').on('click', function () {
    $('#todo-list').append('<li>New task <button class="delete-btn">Delete</button></li>');
});

With the delegated version, clicking "Add item" creates a brand-new <li> with its own .delete-btn — and clicking that button still works, even though it didn't exist when the page loaded, because #todo-list (the element the handler is actually bound to) was always there. jQuery checks, at click time, whether the actual clicked element matches .delete-btn, and only then runs the handler.

Removing handlers

Javascript
function handleClick() {
    console.log('clicked');
}

$('#btn').on('click', handleClick);
$('#btn').off('click', handleClick);   // removes just this specific handler
$('#btn').off('click');                // removes every click handler on this element

Triggering events programmatically

Javascript
$('#save-btn').trigger('click'); // fires the click handler(s) as if a user clicked

Useful in tests, or to reuse the same logic (e.g. programmatically "clicking" a hidden file input from a styled button).

Namespaced events

Attaching a custom namespace to an event lets you remove a specific group of handlers without disturbing others bound to the same event type:

Javascript
$('#panel').on('click.tooltipPlugin', function () { /* ... */ });
$('#panel').on('click.myApp', function () { /* ... */ });

$('#panel').off('click.tooltipPlugin'); // removes only that namespace's handler

Common mistakes

  • Binding handlers directly to elements that are added to the page dynamically (via AJAX, or created in JavaScript) instead of using delegation from a stable ancestor — the handler silently never fires because it was never attached to an element that didn't exist yet.
  • Forgetting event.preventDefault() in a form's submit handler when the intent is to handle the submission via AJAX — without it, the browser still performs its default full-page navigation/submit alongside your handler.
  • Attaching the same handler multiple times (e.g. by re-running setup code on every AJAX page update) without first calling .off(), causing a click to fire the handler two, three, or more times.