Learnwizy Technologies Logo

Learnwizy Technologies

Class 12: JavaScript Events & Asynchronous Programming

In the previous class, we learned how to manipulate the DOM to dynamically change web page content and styles. Now, we'll dive into how JavaScript can react to user actions and manage tasks that don't happen instantly. This class introduces JavaScript Events for handling user interactions and the basics of Asynchronous Programming.

Synchronous vs Asynchronous Programming Diagram

Handling User Interactions with Events

Events are actions or occurrences that happen in the system you are programming, which the system tells you about so your code can react. When a user clicks a button, submits a form, or types into an input field, these are all events.

addEventListener()

The addEventListener() method is the most common and recommended way to register an event handler. It attaches an event handler to the specified element without overwriting existing event handlers.

<!-- HTML -->
<button id="myButton">Click Me!</button>
<p id="message">No click yet.</p>

<script>
    const button = document.getElementById("myButton");
    const message = document.getElementById("message");

    // Define the function to be executed when the event occurs
    function handleClick() {
        message.textContent = "Button was clicked!";
        console.log("Button clicked!");
    }

    // Attach the click event listener to the button
    button.addEventListener("click", handleClick);

    // You can also use an anonymous function directly
    // button.addEventListener("mouseover", () => {
    //     message.textContent = "Mouse over button!";
    // });
</script>

Common DOM Events

Here are some frequently used DOM events:

<!-- HTML -->
<input type="text" id="myInput" placeholder="Type something...">
<form id="myForm">
    <input type="text" placeholder="Name">
    <button type="submit">Submit</button>
</form>
<p id="keyOutput"></p>

<script>
    const myInput = document.getElementById("myInput");
    const myForm = document.getElementById("myForm");
    const keyOutput = document.getElementById("keyOutput");

    myInput.addEventListener("change", (event) => {
        console.log("Input value changed to: ", event.target.value);
    });

    myForm.addEventListener("submit", (event) => {
        event.preventDefault(); // Prevents the default form submission (page reload)
        console.log("Form submitted!");
        alert("Form Submitted! (Check console)");
    });

    document.addEventListener("keydown", (event) => {
        keyOutput.textContent = `Key pressed: ${event.key}`;
        if (event.key === "Escape") {
            alert("Escape key pressed!");
        }
    });
</script>

The Event Object

When an event occurs, an Event object is automatically passed as the first argument to the event listener function. This object contains useful information about the event, such as the element that triggered it (event.target), mouse coordinates, key pressed, etc.

<!-- HTML -->
<div id="clickableDiv" style="width: 100px; height: 100px; background-color: lightblue;">
    Click Me!
</div>
<p id="coords"></p>

<script>
    const clickableDiv = document.getElementById("clickableDiv");
    const coordsParagraph = document.getElementById("coords");

    clickableDiv.addEventListener("click", (event) => {
        console.log("Event type:", event.type);      // "click"
        console.log("Target element:", event.target); // The div element
        console.log("Client X:", event.clientX);    // X coordinate relative to viewport
        console.log("Client Y:", event.clientY);    // Y coordinate relative to viewport
        coordsParagraph.textContent = `Clicked at (${event.clientX}, ${event.clientY})`;
    });
</script>

Event Propagation (Bubbling, Capturing)

When an event occurs on an element, it doesn't just happen on that element. It propagates through the DOM tree.

Most events bubble by default. addEventListener() defaults to the bubbling phase.

<!-- HTML -->
<div id="outer" style="padding: 20px; background-color: #f0f0f0;">
    Outer Div
    <div id="inner" style="padding: 20px; background-color: lightcoral;">
        Inner Div
    </div>
</div>

<script>
    const outer = document.getElementById("outer");
    const inner = document.getElementById("inner");

    // Bubbling Phase (default)
    outer.addEventListener("click", () => {
        console.log("Outer Div (Bubbling)");
    });

    inner.addEventListener("click", () => {
        console.log("Inner Div (Bubbling)");
    });

    // Capturing Phase (third argument true)
    outer.addEventListener("click", () => {
        console.log("Outer Div (Capturing)");
    }, true);

    inner.addEventListener("click", () => {
        console.log("Inner Div (Capturing)");
    }, true);

</script>

event.stopPropagation() can be used inside an event handler to stop the event from propagating further.


Introduction to Asynchronous Programming (Part 1)

JavaScript is primarily single-threaded, meaning it executes one task at a time, in order. However, many operations, like fetching data from a server, reading a file, or waiting for a user click, take time and would "block" the main thread, making the web page unresponsive. Asynchronous JavaScript allows these long-running tasks to run in the background without blocking the main thread.

Think of it like ordering food:

setTimeout()

Executes a function or a block of code after a specified delay (in milliseconds). It's a one-time execution.

console.log("Start of script");

setTimeout(() => {
    console.log("This message appears after 2 seconds.");
}, 2000); // 2000 milliseconds = 2 seconds

console.log("End of script (will appear before the timeout message).");

/* Expected Output:
Start of script
End of script (will appear before the timeout message).
(after 2 seconds)
This message appears after 2 seconds.
*/

setInterval()

Repeatedly executes a function or a block of code with a fixed time delay between each call. It keeps running until stopped.

let count = 0;
const intervalId = setInterval(() => {
    count++;
    console.log(`Interval tick: ${count}`);
    if (count === 3) {
        clearInterval(intervalId); // Stop the interval after 3 ticks
        console.log("Interval stopped.");
    }
}, 1000); // Executes every 1 second

console.log("Counting will start soon...");

/* Expected Output:
Counting will start soon...
(after 1 second)
Interval tick: 1
(after another 1 second)
Interval tick: 2
(after another 1 second)
Interval tick: 3
Interval stopped.
*/

Understanding events allows you to make your web pages interactive, and grasping asynchronous concepts is vital for handling operations that take time, ensuring your applications remain responsive.