Efficient Event Handling
In this page:
$(parent).on("eventName", "childSelector", function () {
// delegated handler
});
What is Event Delegation?
Event delegation attaches a single listener to a stable parent element and lets it catch events bubbling up from matching descendants, rather than binding a separate listener to each individual child element. This means one handler can cover many elements — including ones that don't exist yet — instead of needing one handler per element.
Example: What is Event Delegation?
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<ul id="list"><li>Item 1</li></ul>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
function init() {
$("#list").on("click", "li", function() {
$("#output").append($("<div>").text("Clicked: " + $(this).text()));
});
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
init();
});
</script>
</body>
</html>
Dynamic Elements
Delegation works for elements added to the page after the event handler was originally created, which is a major advantage over binding handlers directly to each element. A new list item added later is automatically covered by the parent's existing delegated handler, with nothing extra to wire up.
Example: Dynamic Elements
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<ul id="list"><li>Item 1</li></ul>
<button id="add">Add Item</button>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
function init() {
$("#list").on("click", "li", function() {
$("#output").append($("<div>").text($(this).text()));
});
$("#add").on("click", function() {
$("#list").append("<li>New Item</li>");
});
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
init();
});
</script>
</body>
</html>
Direct Binding vs Delegation
Direct binding attaches a handler to each existing element individually, which means any element added afterward needs its own new handler attached manually. Delegation instead uses one handler on a stable parent, making it a much better fit for lists, tables, or menus whose contents can change over time.
Example: Direct Binding vs Delegation
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<ul id="list"><li>Item 1</li></ul>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
function init() {
$("#list li").on("click", function() { $("#output").append($("<div>").text("Direct")); });
$("#list").on("click", "li", function() { $("#output").append($("<div>").text("Delegated")); });
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
init();
});
</script>
</body>
</html>
Delegating Different Events
The on() method can delegate many different event types this way — click, mouseenter, change, and others — by passing a selector as the second argument so the handler only reacts to events from elements matching that selector.
Example: Delegating Different Events
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<ul id="list"><li>Item 1</li></ul>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
function init() {
$("#list").on("click", "li", function() { $("#output").append($("<div>").text("Clicked")); });
$("#list").on("mouseenter", "li", function() { $("#output").append($("<div>").text("Hovered")); });
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
init();
});
</script>
</body>
</html>
Small Delegation Project
Delegation is especially valuable for lists, tables, menus, and any interface that creates or removes elements dynamically, since it avoids the bookkeeping of attaching and detaching individual handlers as elements come and go.
Example: Small Delegation Project
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
.selected { background: yellow; }
</style>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<table id="rows"><tr><td>Row 1</td></tr></table>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
function init() {
$("#rows").on("click", "tr", function() {
$(this).toggleClass("selected");
});
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
init();
});
</script>
</body>
</html>
- Binding
$("li").on("click", ...)to each item and expecting it to work for items added later, when delegation like$("#list").on("click", "li", ...)is needed. - Delegating to
$(document)for everything, which forces every click on the page through the handler; use the nearest stable parent. - Using the deprecated
.live()or.delegate(), when.on()with a selector replaces both.
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: