Event Listeners
Event listeners are what make web pages interactive. They allow you to respond to user actions like clicks, keyboard input, form submissions, and much more.
What Are Events?
Events are things that happen in the browser - a user clicks a button, types in an input field, submits a form, resizes the window, etc. Event listeners are functions that "listen" for these events and run code when they occur.
Basic Event Listener Syntax
To add an event listener to an element, use the addEventListener method:
const button = document.querySelector("button")
button.addEventListener("click", () => {
console.log("Button was clicked!")
})
The addEventListener method takes two main arguments:
- eventType: A string representing the type of event (e.g., "click", "input", "submit")
- function: The function to run when the event occurs
Adding Event Listeners to Elements
You can add event listeners to any DOM element:
const input = document.querySelector("input")
input.addEventListener("input", (e) => {
console.log("Input value:", e.target.value)
})
document.addEventListener("click", () => {
console.log("Document was clicked")
})
window.addEventListener("resize", () => {
console.log("Window resized to:", window.innerWidth, window.innerHeight)
})
Multiple Event Listeners
You can add multiple event listeners to the same element:
const button = document.querySelector("[data-button]")
button.addEventListener("click", () => {
console.log("First listener")
})
button.addEventListener("click", () => {
console.log("Second listener")
})
// When clicked, both will run:
// "First listener"
// "Second listener"
Event listeners never overwrite each other and always run in the order they were added to the element.
Removing Event Listeners
To remove an event listener, you need a reference to the exact same function:
// ✅ This works - named function
function handleClick() {
console.log("Clicked!")
}
const button = document.querySelector("button")
// Add the listener
button.addEventListener("click", handleClick)
// Remove the listener
button.removeEventListener("click", handleClick)
// ❌ This doesn't work - different function objects
button.addEventListener("click", () => {
console.log("Clicked!")
})
// This creates a NEW function, so it won't remove the first one
button.removeEventListener("click", () => {
console.log("Clicked!")
})
The Event Object
Event listener functions automatically receive an event object that contains information about the event:
button.addEventListener("click", (event) => {
console.log(event) // MouseEvent object with lots of info
})
Common Event Object Properties
button.addEventListener("click", (e) => {
// The element that triggered the event
console.log(e.target) // The button element
// The element the listener is attached to
console.log(e.currentTarget) // The button element
// Mouse position (for mouse events)
console.log(e.clientX, e.clientY) // X and Y coordinates
// Modifier keys
console.log(e.ctrlKey) // true if Ctrl was held
console.log(e.shiftKey) // true if Shift was held
console.log(e.altKey) // true if Alt was held
})
target vs currentTarget
target- The actual element that triggered the event (could be a child element)currentTarget- The element the event listener is attached to
document.addEventListener("click", (e) => {
console.log(e.target) // The specific element clicked
console.log(e.currentTarget) // Always the document
})
Generally, currentTarget is what you want when working inside an event listener since it refers to the element you added the listener to.
Common Event Types
Memorizing all event types is impossible, but here are some of the most commonly used ones:
Mouse Events
click- When an element is clickeddblclick- When an element is double-clickedmouseenter- When the mouse enters an elementmouseleave- When the mouse leaves an elementmouseover- When the mouse moves over an element (fires continuously)
Focus Events
focus- When an element (like an input) receives focusblur- When an element loses focus
Input Events
input- Fires every time the value of an input changes (typing, pasting, etc.)change- Fires when the input loses focus and its value has changed
Window Events
resize- When the window is resized
You can add any event listener to the window object, but the only one you will commonly use is resize since it doesn't work on any other element.
Preventing default behavior - preventDefault
Many events have default browser behavior associated with them. For example, clicking a link navigates to a new page, submitting a form redirects you to the form action, etc.
<form>
<input type="text" name="username" placeholder="Username" required />
<button type="submit">Submit</button>
</form>
const form = document.querySelector("form")
form.addEventListener("submit", (e) => {
// Prevent the default form submission behavior
e.preventDefault()
console.log("Form submitted!")
// Now you can handle the form data yourself
const formData = new FormData(e.currentTarget)
const username = formData.get("username")
console.log("Username:", username)
})
// Prevent links from navigating
const link = document.querySelector("a")
link.addEventListener("click", (e) => {
e.preventDefault()
console.log("Link clicked but navigation prevented")
})
// Prevent context menu (right-click menu)
document.addEventListener("contextmenu", (e) => {
e.preventDefault()
console.log("Right-click menu prevented")
})
Common Mistakes
Accidentally Calling the Function
function handleClick() { console.log("Button clicked") } // ❌ Wrong - calling the function immediately button.addEventListener("click", handleClick()) // ✅ Correct - passing the function reference button.addEventListener("click", handleClick)Using
targetinstead ofcurrentTarget<button> <span>Click Me</span> </button>button.addEventListener("click", (e) => { // ❌ Wrong - target is most likely the <span> element console.log(e.target) // ✅ Correct - currentTarget is always the button console.log(e.currentTarget) })