Events are actions that happen in the browser — clicks, key presses, form submissions, page load, and more. JavaScript lets you respond to these events with event listeners.

Adding Event Listeners

  let button = document.querySelector('#myBtn');

// Recommended: addEventListener
button.addEventListener('click', function() {
    console.log('Button clicked!');
});

// Arrow function
button.addEventListener('click', () => {
    console.log('Clicked with arrow function');
});
  

Avoid inline handlers like onclick="..." in HTML for maintainability and separation of concerns.

The Event Object

When an event fires, the handler receives an event object with useful properties:

  button.addEventListener('click', (event) => {
    console.log(event.type);   // 'click'
    console.log(event.target); // element that triggered the event
    event.preventDefault();    // cancel default behavior (e.g. form submit)
    event.stopPropagation();   // stop bubbling to parent elements
});
  

Common Event Types

Event Fires when
click Element is clicked
dblclick Double-click
mouseenter / mouseleave Mouse enters/leaves element
keydown / keyup Key pressed/released
input Input value changes
change Input loses focus after change
submit Form is submitted
load Page or resource finishes loading
DOMContentLoaded HTML parsed, DOM ready

Keyboard Events

  document.addEventListener('keydown', (e) => {
    console.log(e.key);      // 'Enter', 'a', 'Shift', etc.
    console.log(e.code);     // physical key code
    if (e.key === 'Escape') {
        console.log('Escape pressed');
    }
});
  

Form Events

  <form id="myForm">
    <input id="email" type="email" required>
    <button type="submit">Submit</button>
</form>

<script>
    document.querySelector('#myForm').addEventListener('submit', (e) => {
        e.preventDefault(); // prevent page reload
        const email = document.querySelector('#email').value;
        console.log('Submitted:', email);
    });

    document.querySelector('#email').addEventListener('input', (e) => {
        console.log('Typing:', e.target.value);
    });
</script>
  

Event Propagation: Bubbling and Capturing

Events travel in two phases:

  1. Capturing — from document down to the target
  2. Bubbling — from the target back up to document

By default, listeners run during the bubbling phase.

  document.querySelector('#parent').addEventListener('click', () => {
    console.log('Parent clicked');
});

document.querySelector('#child').addEventListener('click', (e) => {
    console.log('Child clicked');
    // e.stopPropagation(); // uncomment to prevent parent from firing
});
  

Event Delegation

Attach one listener to a parent instead of many listeners on children. Useful for dynamic lists:

  document.querySelector('#list').addEventListener('click', (e) => {
    if (e.target.tagName === 'LI') {
        e.target.classList.toggle('done');
    }
});
  

Removing Listeners

  function handleClick() {
    console.log('Clicked');
}

button.addEventListener('click', handleClick);
button.removeEventListener('click', handleClick); // same function reference required
  

{ once: true } and Other Options

  button.addEventListener('click', handler, { once: true }); // auto-remove after first fire
button.addEventListener('click', handler, { passive: true }); // scroll performance
  

Complete Example

  <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Events Example</title>
</head>
<body>
    <button id="btn">Click me</button>
    <p id="output">Waiting...</p>

    <script>
        const btn = document.querySelector('#btn');
        const output = document.querySelector('#output');
        let count = 0;

        btn.addEventListener('click', () => {
            count++;
            output.textContent = `Clicked ${count} time(s)`;
        });

        document.addEventListener('keydown', (e) => {
            if (e.key === 'r') {
                count = 0;
                output.textContent = 'Reset!';
            }
        });
    </script>
</body>
</html>