viernes, 17 de septiembre de 2021

Javascript EventListener Optimization Propagation

 Javascript EventListener Optimization Propagation

 
html file

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">  
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
    <link rel="stylesheet" href="css/styles.css">
    <title>Event Propagation</title>
</head>
<body>
    <div class="container">
      <button class="btn-add" id="btn-add">Add Element</button>
      <div class="list" id="list">
        <a href="#">
           Element <i class="bi bi-check-square-fill"></i>
        </a>
        <a href="#">
           Element <i class="bi bi-check-square-fill"></i>
        </a>
        <a href="#">
           Element <i class="bi bi-check-square-fill"></i>
        </a>
      </div>
    </div>
    <script src="./js/code.js"></script>
</body>
</html>
 
css file
 
* {
    margin0;
    padding:0;
    box-sizingborder-box;
}

body {
    min-height100vh;
    displayflex;
    align-itemscenter;
    justify-contentcenter;
    font-family'Roboto'sans-serif;
    backgroundgainsboro;
}

a {
    text-decorationnone;
}

.container {
    displayflex;
    flex-directioncolumn;
    align-itemscenter;
}

.list {
    width500px;
}

.list a {
    padding20px;
    font-size18px;
    displayflex;
    align-itemscenter;
    justify-content:space-between;
    backgroundcornflowerblue;
    color#eee;
    margin-bottom20px;
    border-radius5px;
    transition.3s easy all;
}

.list a i{
    displaynone;
}

.list a.active i{
    displayblock;
}

.list a:hover {
    background:rgb(41111240);
}

.btn-add {
    background:rgb(2289145);
    color:#eee;
    font-size18px;
    line-height45px;
    width30%;
    margin-bottom20px;
    bordernone;
    border-radius5px;
    cursor:pointer;
}

.btn-add:hover {
    background:darksalmon;
    color#fff;
}
 
Let´s add javascript code to add functionality to the button in order to add another element, and add event listener for each element of the list
 
const list = document.getElementById("list");
const btnAdd = document.getElementById("btn-add");

list.childNodes.forEach((element=> {
    element.addEventListener('click', (e=> { 
        console.log(e.target.classList);
        e.target.classList.toggle('active');
        });
});

btnAdd.addEventListener('click', () => {
    const element = 
       <a href="#">
          Element <i class="bi bi-check-square-fill"></i>
       </a>
       `;

    list.innerHTML += element;
});
 
This look like this on browser
 

 We can see in the browser inspector that in the list for each element an event has been added, additional to it, the on one element the click has been ejecuted to toggle the class active to show or not the icon.

When the Add Element button is clicked an element is added, but the events are deleted for all of them


To solve this adjust the code javascript

const list = document.getElementById("list");
const btnAdd = document.getElementById("btn-add");

const addListeners = () => {
  list.childNodes.forEach((element=> {
    element.addEventListener('click', (e=> { 
        e.target.classList.toggle('active');
        });
  });
}

addListeners();

btnAdd.addEventListener('click', () => {
    const element = 
       <a href="#">
          Element <i class="bi bi-check-square-fill"></i>
       </a>
       `;

    list.innerHTML += element;
    addListeners();
});
 
This way addListeners are executed many times, unecessary. to avoid that let´s add the listener to the list and for each element in the list the event will respond, only we need to filter the event when it comes from the element and not from the list.

const list = document.getElementById("list");
const btnAdd = document.getElementById("btn-add");

list.addEventListener('click', (e=> {
    console.log(e);
});

btnAdd.addEventListener('click', () => {
    const element = 
       <a href="#">
          Element <i class="bi bi-check-square-fill"></i>
       </a>
       `;

    list.innerHTML += element;
});
 
See what is in the event when click on the element or in the list
 

 See the event click, in one the target is the 'div' an in the other is an 'a', now filter and apply the toogle for the class active.

const list = document.getElementById("list");
const btnAdd = document.getElementById("btn-add");

list.addEventListener('click', (e=> {
    if(e.target && e.target.tagName === 'A') {
      e.target.classList.toggle('active');
    }
});

btnAdd.addEventListener('click', () => {
    const element = 
       <a href="#">
          Element <i class="bi bi-check-square-fill"></i>
       </a>
       `;

    list.innerHTML += element;
});
 

 
eot

No hay comentarios:

Publicar un comentario