.on(events [, selector] [, data], handler) attaches event handlers to the selected elements (since 1.7). Omit selector for a direct bind; pass a selector for delegated events on current and future descendants.
Remember
// Direct
$("p").on("click", function () {
alert($(this).text());
});
// Delegated (dynamic children OK)
$("body").on("click", "p", function () {
$(this).after("
Another paragraph!
");
});
// Remove with .off()
$("body").off("click", "p");
Pick direct binding for fixed elements, or delegation for lists that grow.
Select the element that will own the listener (button, list, form, or document).
Call .on(events, handler) for a direct bind.
Or call .on(events, selector, handler) to handle matching descendants.
Optional: pass data, use namespaces (click.myPlugin), or an events object map.
Clean up later with a matching .off().
Piece
Required?
Role
events
Yes
Event name(s) / namespaces, or a map of event → handler
selector
Optional
Filter descendants (delegation). Omit for direct binds
data
Optional
Available as event.data in the handler
handler
Yes*
Function to run, or false (*not needed with an events map)
Pseudocode
Pseudocode
attach listener on ROOT for EVENTS
if no SELECTOR (direct):
when event reaches ROOT → run HANDLER
this = ROOT
if SELECTOR (delegated):
when event bubbles to ROOT:
if a matching descendant is on the path:
run HANDLER
this = that matched descendant
new matching children:
work automatically (delegated only)
Reference
Cheat Sheet
Core facts while wiring UI events.
Topic
Detail
Returns
jQuery (chainable)
Since
1.7
Direct
.on(events, handler)
Delegated
.on(events, selector, handler)
this
Bound element (direct) or matched descendant (delegated)
false
Shorthand for function () { return false; }
Remove
.off() with matching filters
Try it
Live Preview
Switch between direct and delegated binding — then add items and click them.
After a direct bind, new items will not respond until you rebind — delegated items will.
Log
Ready — Run “delegated”, then click an item.
Code
jQuery Examples
Short, copy-ready snippets. Open DevTools Console, or use Try It Yourself for a live editor.
Example 1 — Direct Click
Bind a click handler straight to matching paragraphs.
jQuery
$("p").on("click", function () {
$("#out").text($(this).text());
});
Trigger. Button fires that event and passes extra data.
Args. Extra trigger values arrive after event.
Use. Decouple components without a native DOM event type.
Edge Cases & Pitfalls
Watch for these when attaching handlers.
timing
Elements must exist for direct binds
Direct .on() only attaches to elements present now. Prefer delegation or wait for DOM ready.
root
Delegate close to the target
Avoid dumping every delegated handler on document in large pages — attach nearer the content.
svg
Delegated handlers and SVG
Official note: delegated event handlers do not work for SVG — bind directly when needed.
bubble
Some events do not bubble
load, scroll, and error (and a few others) are poor fits for delegation — attach them directly.
Compatibility
Browser Support
.on() has been part of jQuery since 1.7 and is the standard event-binding API. It works wherever your loaded jQuery version runs.
✓ Stable · jQuery 1.7+
.on()
Works in every browser that runs your loaded jQuery version. Prefer a current jQuery 3.x build for modern projects.
100%With jQuery 1.7+
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
.on()Universal
Bottom line: Production-ready. Use .on() / .off() for all new event code; migrate away from .bind(), .delegate(), and .live().
Analysis
Performance Notes
Approach
Cost
Best for
One delegated handler near targets
Low
Long lists / dynamic UI
Handler per row
Higher
Avoid on large tables
Many filters on document
Higher
Prefer closer roots + simple selectors
mousemove / scroll floods
High
Throttle / keep handlers light
Delegation is usually cheaper than mass direct binds. Keep selectors simple (tag, #id, .class) when filtering bubbled events.
Remember
Key Takeaways
Role: one modern API for direct and delegated event binding.
Delegate: pass a selector so future children stay covered.
Cleanup: pair with .off(); use namespaces in plugins.
Replace: prefer .on() over .bind(), .delegate(), and .live().
One line:.on() is how modern jQuery attaches events — direct for fixed elements, delegated for dynamic ones.
Frequently Asked Questions
.on() attaches event handlers to the selected elements. Since jQuery 1.7 it is the unified binding API for direct handlers, delegated handlers, namespaces, event data, and multiple events — replacing .bind(), .delegate(), and .live().
Direct: $("button").on("click", fn) runs for that button. Delegated: $("#list").on("click", "li", fn) listens on #list and runs for matching li descendants — including ones added later.
Use .off() with matching filters: event type, namespace, selector, and/or handler function. Example: $("#list").off("click", "li", fn).
Append a suffix like click.myPlugin. You can then .off(".myPlugin") or .trigger("click.myPlugin") without affecting other click handlers. Namespaces are not hierarchical — one matching name is enough.
Yes. .on("click", { foo: "bar" }, handler) puts that object on event.data. If data is a string and you also need a selector, pass the selector explicitly (or null) so the string is not treated as a selector.
Yes. .on("myCustomEvent", fn) listens for events you fire with .trigger("myCustomEvent") or .trigger("myCustomEvent", [extraArgs]).