Event Listeners

Event Listeners are used to add and remove JavaScript Events. The most preferred and recommended way to deal with JavaScript events is to use event listeners. These event listeners were introduced in ES5 (2009). Thus, all modern web browsers support them (except IE 8 and below).

To use event listeners, we use the addEventListener() function to add an event and the removeEventListener() function to remove an event.

Advantages of using Event Listeners

  1. Allows adding multiple handlers for the same event.
  2. Listeners can be removed using removeEventListener().
  3. Event propagation behavior (bubbling/capturing) can be controlled.
  4. Supports options such as capture, passive, and once.
  5. Supports custom events and device-specific events such as touch events.

Types of Event Listeners

  1. addEventListener
  2. removeEventListener

addEventListener

addEventListener is the most preferred and recommended way to handle JavaScript events.

Inside the addEventListener function, the first parameter is an event type string, like click, mouseover, mouseout, scroll, etc. The second parameter is the function that will be called when the event occurs. The second parameter can also be an anonymous function. The third parameter is a boolean.

addEventListener with callback function


document.body.addEventListener("click",doThis,options);
    
function doThis(){
    console.log(this.textContent);
}      

addEventListener with anonymous function


document.body.addEventListener("click",function(){

});

In this example, we are using the click event on the body element. addEventListener uses two parameters. The first is the event type, and the second is the callback function that is invoked when the event occurs. The third parameter (Boolean value true or false) is optional, as it is used only when we change event propagation.

Options Parameter

The third parameter of addEventListener is optional. It is used to change event propagation. By default, all events are bubbling type. But if we want to change an event to capturing type, we can use the third parameter as true.

Options Object

The third parameter can also be an object, which can have the following properties.

Property Default Description
capture false Boolean value. If true, the event will be capturing type; otherwise, it will be bubbling type.
once false Boolean value. If true, the event will be called only once.
passive false Boolean value. If true, the event listener will never call preventDefault().

removeEventListener

Event listeners can be removed using the removeEventListener() method. This is another advantage of using event listeners. Here is an example.

Click here once


    const btn=document.querySelector("button");
    btn.addEventListener("click", remove);
        
    function remove(){
        console.log("Clicked");
        btn.removeEventListener("click",remove)
    }

Event Propagation

Event Propagation is the order in which events fire from a child element to its parent. By default, events propagate from the child to the parent node, which is also known as bubbling.

Types of event propagation

Event Bubbling

Event Bubbling is when an event fires on an element and then bubbles up to the parent elements until it reaches the root node. By default, all events are bubbling type. In the example shown, click events are used on both the parent div and the child button, but the button event will be called first.


<div id="div1">
    <button id="button1">Button 1</button>
</div>
    
<script>
document.querySelector("#div1").addEventListener("click",function(){
    console.log("you clicked div");
});
document.querySelector("#button1").addEventListener("click",function(){
    console.log("you clicked button");
});
</script>

Event capturing

Event capturing is when the root node is fired first and then propagates downward until it reaches the targeted element. Capturing is possible by using the third boolean parameter (true) in the event listener. Here is an example.


<div id="div2">
    <button id="button2">Button 1</button>
</div>
    
<script>
document.querySelector("#div2").addEventListener("click",function(){
    console.log("you clicked div");
},true);
document.querySelector("#button2").addEventListener("click",function(){
    console.log("you clicked button");
},true);
</script>
        

eventDelegation

Bubbling can be used for Event Delegation. Event Delegation is a technique where we use a single event to interact with multiple child elements by using event.target.

Consider a case where we need to add events to 16 columns of a single parent. Instead of using 16 click events, we can use the event delegation technique for efficient work. See the example below.

Row 1, Col 1
Row 2, Col 2
Row 3, Col 3
Row 4, Col 4
Row 1, Col 1
Row 2, Col 2
Row 3, Col 3
Row 4, Col 4
Row 1, Col 1
Row 2, Col 2
Row 3, Col 3
Row 4, Col 4
Row 1, Col 1
Row 2, Col 2
Row 3, Col 3
Row 4, Col 4


const t=document.querySelector("table");
t.addEventListener("click",function(e){
    if(e.target.tagName == "TD"){
        e.target.classList.toggle('active');
    }
});

event.stopPropagation()

The event.stopPropagation() method stops propagation of an event from child to parent in bubbling, or from parent to child in the case of capturing.

event.stopPropagation in bubbling

event.stopPropagation() in bubbling stops propagation of an event from the child to the parent node. In short, the child event will be triggered, but the parent event won't.


<div id="div3">
    <button id="btn3">Button</button>
</div>
            
<script>
document.querySelector("#div3").addEventListener("click",function(){
    alert("you clicked div");
});

document.querySelector("#btn3").addEventListener("click",function(e){
    alert("you clicked button");
    e.stopPropagation();
});
</script>

event.stopPropagation in capturing

event.stopPropagation() in capturing stops propagation of an event from the parent to the child node. In short, the parent event will be triggered, but the child event won't.


<div id="div4">
<button id="btn4">Button</button>
</div>

<script>
document.querySelector("#div4").addEventListener("click",function(e){
alert("you clicked div");
e.stopPropagation();
});

document.querySelector("#btn4").addEventListener("click",function(){
alert("you clicked button");
});
</script>

event.stopImmediatePropagation()

The event.stopImmediatePropagation() method also stops the propagation of other event listeners on the same element node.

If an element has two event listeners, and the parent has one listener, stopPropagation will only stop the parent event, but both listeners of the element will be triggered. But with stopImmediatePropagation, only the first event listener is triggered. The second event listener of the same element and the parent event will not be triggered. See the example below.

with event.stopPropagation


const btn=document.querySelector("button");
const div=document.querySelector("div");

btn.addEventListener("click",function(e){ 
    alert(1);
    e.stopPropagation();
});

btn.addEventListener("click",function(){ alert(2)});

div.addEventListener("click",function(){ alert(3)});

with event.stopImmediatePropagation


const btn=document.querySelector("button");
const div=document.querySelector("div");

btn.addEventListener("click",function(e){ 
    alert(1);
    e.stopImmediatePropagation();
});

btn.addEventListener("click",function(){ alert(2)});
    
div.addEventListener("click",function(){ alert(3)});


Touch Events

ES5 introduced touch-based events in JavaScript. Touch events are applicable only to touch-based devices.

Types of Touch Events

  1. touchstart
  2. touchmove
  3. touchend

Touch Event Example




const img=document.querySelector("img");

img.addEventListener("touchstart",function(){
    this.style.boxShadow="0px 0px 5px 1px #000";
});   

img.addEventListener("touchmove",function(e){
   e.preventDefault();
   if (e.targetTouches.length == 1) {
    let touch = e.targetTouches[0];
    // Place element where the finger is
    obj.style.left = (touch.clientX-obj.clientLeft) + 'px';
    obj.style.top = (touch.clientY-obj.clientTop-350) + 'px';
    
    // position of image should be relative in css
   }
});   

img.addEventListener("touchend",function(){
    this.style.boxShadow="0px 0px 5px 1px transparent";   
});       

Event Listeners are not supported in IE 8 and older browsers. For old browser support, use property-based click events or jQuery.