Events

Events are "things" that happen to HTML elements, an event will execute specified code using a listener also called a handler. Both the BOM and DOM support events and they can be simple or complex depending on your needs.

Event Flow

To start we need to understand the flow of an event, describes the order in which events are received on a page and there are two concepts

Event Bubbling Event Capturing

DOM event flow specifies there are three phases capturing phase (1-3), target phase (4) and bubbling phase (5-6)

DOM Event Flow

HTML Event Handlers

Events have names like click, load and mouseover (plus many more), then the event can then point to a function, this function is called an event handler. Event handlers has names that start with on, so to summarize a click event has a handler called onclick and a load event has a handler called onload.

A simple event example
<input type="button" value="Click Me" onclick="console.log('Clicked')"/>
A custom handler example
<input type="button" value="Click Me" onclick="customHandler()"/<

<script>
    function customHandler() {
        console.log("A Custom Handler!")
    }
</script>

Event handlers have access to the event object in a variable called event, also you have access to this variable which is the events target element

event and this
<input type="button" value="Event Object" onclick="console.log(event)"/>
<input type="button" value="this Object" onclick="console.log(this)"/>
event and this objects

Also you have access to the local variables without accessing the element itself

local variable/s access
<form method="post">
    <input type="text" name="username" value="">
    <input type="button" value="Echo Username" onclick="console.log(username.value)">  // access to username
</form>

DOM level 0 and 2 handlers

The problem with HTML handlers is the function has to load before the user uses the event otherwise you get an error, also different browsers use different scope chains which can cause issues and finally the HTML and Javascript are tightly coupled meaning you have to change the code in two places.

DOM level 0 and 2 have alternatives to creating an event handler which can be seen below, however browsers like IE use different method names, so developer tend to abstract the various methods into a common one.

DOM level 0 event handler
let btn = document.getElementById("myBtn");
    btn.onclick = function() {
    console.log(this.id); // "myBtn"
};

Note: to stop the event just assign the btn to null
DOM level 2 event handler
let btn = document.getElementById("myBtn");

btn.addEventListener("click", () => {
    console.log(this.id);
}, false);

// You can also add multiple handlers as well
btn.addEventListener("click", () => {
    console.log("Hello world!");
}, false);

btn.removeEventListener("click", handler, false);

Note: you can use removeEventListener() to stop the event

Note: IE use attachEvent() and detachEvent() methods

Event Object

I mentioned the event object about so lets have a closer look, when an event is triggered all the relevant information is stored in the event object, the element that caused the trigger, the type of event, and any data (mouse position for example, key that was pressed), below you can see what a mouseEvent event object contains, as you can see there is lots of information about the event.


Inside the event handler the this object is equal to the currentTarget, whereas the target conatins the actual target of the event.

inside the event handler
let btn = document.getElementById("myBtn");

btn.onclick = function(event) {
    console.log(event.currentTarget === this);                         // true
    console.log(event.target === this);                                // true
};

You can use the preventDefault() method of the event to stop the default action of a particular event, this set the property value of cancelable to true, you can also stop bubbling and capturing using the stopPropagation() method,

preventDefault and stopPropagation
let link = document.getElementById("myLink");

link.onclick = function(event) {                     // notice we pass the event object into the function
    event.preventDefault();
};

let btn = document.getElementById("myBtn");

btn.onclick = function(event) {                      // notice we pass the event object into the function
    console.log("Clicked");
    event.stopPropagation();
};

Event Types

I am going to keep this section very brief as there are many differnt types of events, I will categorize them

I am not going to go into detail on every event but here is a list of all of them and point you to the Javascript documentation for more information

UI Events DOMActive, load/unload, abort, error, select, resize and scroll
Focus Events blur, DOMFocusIn, DOMFocusOut, focus, focusin, focusout
Mouse and Wheel Events click, dblclick, mousedown, mouseenter, mouseleave, mousemove, mouseout, mouseover, mouseup
Text Events textinput
Keyboard Events keydown, keypress, keyup
Composition Events compositionstart, compositionupdate, compositionend
HTML5 Events contextmenu, beforeunload, DOMContentLoaded, readystatechange, pageshow/pagehide, haschange
Device Events orientationchange, deviceorientation, devicemotion, touchstart/touchend/touchmove, touchcancel, gesturestart/gesturechange/gestureend

There are many more like light events, app cache events, battery API events, file API events, etc

Event Delegation

Sometime you may want an event handler on every list item, creating event handler for each one would be overkill and the solution to this problem is called event delegation it takes advantage of bubbling to assign a single event handler to manage a particular type. Event delegation allows you to avoid adding event listeners to specific nodes, instead, the event listener is added to one parent, that event listener analyzes bubbled events to find a match on child elements.

Below is two example of event delegation

Event delegation example
<ul id="myLinks">
    <li id="goSomewhere">Go somewhere</li>
    <li id="doSomething">Do something</li>
    <li id="sayHi">Say hi</li>
</ul>
    
let list = document.getElementById("myLinks");

list.addEventListener("click", (event) => {
    let target = event.target;
    switch(target.id) {
        case "doSomething":
            document.title = "I changed the document's title";
            break;
        case "goSomewhere":
            location.href = "go somewhere";
            break;
        case "sayHi":
            console.log("hi");
            break;
    }
});
Event delegation example
<ul id="parent-list">
    <li id="post-1">Item 1</li>
    <li id="post-2">Item 2</li>
    <li id="post-3">Item 3</li>
    <li id="post-4">Item 4</li>
    <li id="post-5">Item 5</li>
    <li id="post-6">Item 6</li>
</ul>

// Get the element, add a click listener...
document.getElementById("parent-list").addEventListener("click", function(e) {
    // e.target is the clicked element!
    // If it was a list item
    if(e.target && e.target.nodeName == "LI") {
        // List item found!  Output the ID!
        console.log("List item ", e.target.id.replace("post-", ""), " was clicked!");
        
        // You could do something with each element
    }
});