DOM Events

Dr. Greg Bernstein

Updated September 12th, 2021

DOM Events

Learning Objectives

  • Understand the role DOM events play in creating GUI
  • Be able to listen for and stop listening for events
  • Understand event propagation model and its uses
  • Understand and use event information in GUIs

Demonstration and Practice Pages

Readings

  1. Introduction to DOM Events

  2. Events and the DOM

References

What are DOM events?

Almost anything interaction or change with or to a web page is accompanied by an event, e.g., click, scroll, load, drag, change, input, error, resize, etc…

This allows us as JavaScript programmers great flexibility in interacting with users.

Where do events come from and go?

From “Intro to DOM Events”:

Events can be triggered on any part of a document, whether by a user’s interaction or by the browser. They don’t just start and end in one place; they flow through the document, on a life cycle of their own. This life cycle is what makes DOM events so extensible and useful.

Compatibility

In the past different browsers implemented events differently, however modern browsers adhere well to the W3C standards. So we will use the standard interfaces rather than a library such as jQuery which did a great job at dealing with inconsistencies across browsers for us.

DOM Inheritance

EventTarget is an interface implemented by Element, document, and window as well as others. Key methods are:

  • EventTarget.addEventListener(): Register an event handler of a specific event type.

  • EventTarget.removeEventListener(): Removes an event listener.

Listening for Events

element.addEventListener(type, callback, capture);

  • type (string): This is the name or type of event that you would like to listen to.

  • callback (function): The event object, containing data about the event, is passed as the first argument.

  • capture (boolean): This declares whether the callback should be fired in the “capture” phase — more on this later.

Listener Example (HTML)

See file DOMEvents1.html.

<h3 id="Test1">Click Me</h3>
<p>Response follows:</p>
<p id="Test1Result"></p>

Listener Example (JS)

let el1 = document.getElementById("Test1");
let el2 = document.getElementById("Test1Result");
function myCallback() {
    let content = "Test1 executed at " + new Date();
    el2.innerHTML = content;
}
// Add listener
el1.addEventListener('click', myCallback);

Removing a Listener Example (HTML)

<h3 id="Test2" class="ClickTarget">Click Me</h3>
<p>Response follows:</p>
<h4 id="Test2Result"></h4>

Removing a Listener Example (JS)

let el3 = document.getElementById("Test2");
let el4 = document.getElementById("Test2Result");
function myCallback2() {
    let content = "Test1 executed at " + new Date();
    el4.innerHTML = content;
    el3.removeEventListener('click', myCallback2);
}
// Add listener
el3.addEventListener('click', myCallback2);

The Event Object

“What” and “from where” properties from MDN:

  • Event.type: The name of the event
  • Event.target: the target to which the event was originally dispatched
  • Event.currentTarget: the currently registered target for the event
  • And more…

MouseEvent Object

Inherits from Event and adds:

  • MouseEvent.button, .buttons: The buttons being pressed when the mouse event was fired

  • MouseEvent.clientX, .clientY: The X and Y coordinates of the mouse pointer in local (DOM content) coordinates.

  • MouseEvent.altKey, .ctrlKey, .metaKey, .shiftKey: Was a particular key also pressed when the mouse event happened.

Event Object Example (HTML)

DOMEvents1.html

<h2>The Event Object</h2>
<p>We'll set up the div below as a mouse down target.</p>
<div id="MouseTarget" style="width: 500px; height: 200px;
    cursor: pointer; background-color: aqua;"></div>
<h4>Event Info:</h4>
<p id="EventInfo"></p>

Event Object Example (JS)

DOMEvents1.html

let mouseTarget = document.getElementById("MouseTarget");
let infoOutput = document.getElementById("EventInfo");
function mouseHandler(event) {
    let info = "type: " + event.type;
    info += " target: " + event.target;
    info += " currentTarget: " + event.currentTarget;
    info += " clientX: " + event.clientX;
    info += " clientY: " + event.clientY;
    infoOutput.innerHTML = info;
    console.log(event);
}
mouseTarget.addEventListener("mousedown", mouseHandler);

Event Propagation

More Event Object

“Status and such” properties from MDN:

  • bubbles: Boolean indicating whether the event bubbles up through the DOM
  • cancelable: Boolean indicating whether the event is cancelable
  • isTrusted: Indicates whether or not the event was initiated by the browser or by a script
  • And more…

The Event Object

Some methods from MDN:

  • preventDefault(): Cancels the event (if it is cancelable).
  • stopPropagation(): Stops the propagation of events further along in the DOM.
  • stopImmediatePropagation(): For this particular event, no other listener will be called.
  • And more…

Event Propagation 1

From W3C:

  • capture phase: The event object propagates through the target’s ancestors from the Window to the target’s parent.

  • target phase: The event object arrives at the event object’s event target. If the event type indicates that the event doesn’t bubble, then the event object will halt after completion of this phase.

Event Propagation 2

From W3C:

  • bubble phase: The event object propagates through the target’s ancestors in reverse order, starting with the target’s parent and ending with the Window.

Event Propagation 3

Event Flow Diagram

Event Propagation

The Event.eventPhase values:

  • 1: Capturing Phase
  • 2: At Target
  • 3: Bubbling Phase

Graphical Example (HTML)

From MDN Event.eventPhase page

For HTML set up a nested series of <div>s:

<input type="checkbox" id="chCapture" />
<label for="chCapture">Use Capturing</label>
<div id="d1">d1
    <div id="d2">d2
        <div id="d3">d3
            <div id="d4">d4</div>
        </div>
    </div>
</div>

Graphical Example (JS)

divInfo = document.getElementById("divInfo");
divs = document.getElementsByTagName('div');
chCapture = document.getElementById("chCapture");

Graphical Example (CSS)

Use some CSS and JS to turn divs into boxes. Also see my file DOMEvents2.html

    div {
        margin: 20px;
        padding: 4px;
        border: thin black solid;
    }
divs[i].style.backgroundColor = (i & 1) ? "#f6eedb" : "#cceeff";

Graphical Example (Rendered)

Screenshot

Graphical Example (Listeners)

Attach listeners:

// In for loop over divs
d.addEventListener("click", OnDivClick, false);
// Use capture checkbox info.
if (chCapture.checked)
    d.addEventListener("click", OnDivClick, true);

Try it at DOMEvents2.html

Delegate Event Listeners

Too Many Listeners to Manage?

  • Do we need to attach a listener for every element we want to hear events from?
  • No. We’ve got bubbling!
  • Do we need a separate event handler for every element?
  • No. We get Event information so we can create more general handlers.

Example Many Buttons (HTML)

<p>Here are a lot of buttons:</p>
<section id="Controls">
    <input type="button" value="Hi">
    <input type="button" value="World">
    <input type="button" value="Web">
    <input type="button" value="Code">
    <input type="button" value="Clear">
    <input type="button" value="HTML">
    <input type="button" value="JavaScript">
    <input type="button" value="HTTP">
    <input type="button" value="CSS">
    <input type="button" value="DOM Events">
</section>
<p>Output below:</p>
<section id="Output">
</section>

Many Buttons (Screen)

Screenshot

Many Buttons (Goal)

Want to add text to output area based on buttons click. May add lots more buttons later or change words on buttons.

Put callback on “container”

let controls, output; // Variables for Elements
window.onload = function() {
    controls = document.getElementById("Controls");
    output = document.getElementById("Output");
    // Add listener to controls section
    controls.addEventListener('click', handleButtons);
}

Make callback Generic

    function handleButtons(event) {
        let target = event.target;
        let value = target.getAttribute("value");
        if (value === "Clear") {
            output.innerHTML = "";
        } else {
            output.innerHTML += value + " ";
        }
    }

Give it a Try

At DOMEvents3.html

// reveal.js plugins