Introduction to DOM Events
In JavaScript, DOM events are actions that occur in the browser, such as a user clicking a button, pressing a key, or moving the mouse. These events can be listened to and handled using addEventListener
.
Everything in JavaScript happens inside the browser environment through these events. You write functions that respond to those events — known as event handlers.
Listening to Events with addEventListener
You can attach a listener to any DOM element that listens for a specific event like click
, keydown
, mouseenter
, etc.
// Select an element by ID
const button = document.getElementById('myButton');
// Add click event listener
button.addEventListener('click', function () {
console.log('Button was clicked!');
});
Output:
Button was clicked!
What Happens When You Click?
When the user clicks on the button, the callback function inside addEventListener
is triggered and logs the message.
Why Use Event Delegation?
Imagine you have a long list of items, and you want to handle clicks on each of them. Attaching individual listeners to each item would be inefficient.
Event delegation solves this by attaching a single listener to a common parent. The event bubbles up from the child to the parent, and we handle it at the parent level.
Example: Event Delegation with a List
// Parent container
const parent = document.getElementById('listContainer');
// Add one listener to the parent
parent.addEventListener('click', function (event) {
if (event.target.tagName === 'LI') {
console.log('Clicked item:', event.target.textContent);
}
});
Output:
Clicked item: Item 3
How Does This Work?
Every time you click on a list item, the event bubbles up to the parent #listContainer
. The parent handles the event and checks if the original click was on an LI
tag using event.target
.
💡 Question:
What would happen if you clicked on whitespace in the parent that is not part of a child LI
?
Answer: Nothing would be logged because the condition event.target.tagName === 'LI'
would be false.
Real-World Use Case
Event delegation is commonly used in dynamic lists, menus, or UI elements generated at runtime — where attaching listeners to each element is either costly or impossible ahead of time.
Example: Handling Buttons with Delegation
// Wrapper that contains multiple buttons
const wrapper = document.getElementById('buttonWrapper');
// Single event listener for all buttons
wrapper.addEventListener('click', function (e) {
if (e.target.tagName === 'BUTTON') {
console.log('You clicked:', e.target.textContent);
}
});
Output:
You clicked: Save
Benefits of Event Delegation
- Performance: Fewer listeners means less memory usage.
- Dynamic Support: Works for elements added after page load.
- Cleaner Code: Keeps logic in one place (the parent).
Tips for Beginners
- Use
event.target
to determine what was clicked. - Use
event.currentTarget
to refer to the element the listener is bound to. - Always check the
tagName
or use class checks to avoid unwanted triggers.
Common Mistakes to Avoid
- Not checking
event.target
— which can lead to errors when parent or whitespace is clicked. - Attaching too many listeners — slows down performance on large DOM trees.