[javascript] Adding click event listener to elements with the same class

I have a list view for delete id. I'd like to add a listener to all elements with a particular class and do a confirm alert.

My problem is that this seems to only add the listener to the first element with the class it finds. I tried to use querySelectorAll but it didn't work.

var deleteLink = document.querySelector('.delete');

deleteLink.addEventListener('click', function(event) {
    event.preventDefault();

    var choice = confirm("sure u want to delete?");
    if (choice) {
        return true;
    }
});

List:

<?php 
    while($obj=$result->fetch_object())
    {
        echo '<li><a class="delete" href="removeTruck.php?tid='.$obj->id.'">'.$obj->id.'</a>'
            . '<a href="#" class="delete"></a>
                      </li>'."\n";
    }
    /* free result set */
    $result->close();       
    $mysqli->close();
?>

This question is related to javascript

The answer is


You have to use querySelectorAll as you need to select all elements with the said class, again since querySelectorAll is an array you need to iterate it and add the event handlers

var deleteLinks = document.querySelectorAll('.delete');
for (var i = 0; i < deleteLinks.length; i++) {
    deleteLinks[i].addEventListener('click', function (event) {
        event.preventDefault();

        var choice = confirm("sure u want to delete?");
        if (choice) {
            return true;
        }
    });
}

A short and sweet solution, using ES6:

document.querySelectorAll('.input')
      .forEach(input => input.addEventListener('focus', this.onInputFocus));

The problem with using querySelectorAll and a for loop is that it creates a whole new event handler for each element in the array.

Sometimes that is exactly what you want. But if you have many elements, it may be more efficient to create a single event handler and attach it to a container element. You can then use event.target to refer to the specific element which triggered the event:

document.body.addEventListener("click", function (event) {
  if (event.target.classList.contains("delete")) {
    var title = event.target.getAttribute("title");

    if (!confirm("sure u want to delete " + title)) {
      event.preventDefault();
    }
  }
});

In this example we only create one event handler which is attached to the body element. Whenever an element inside the body is clicked, the click event bubbles up to our event handler.


(ES5) I use forEach to iterate on the collection returned by querySelectorAll and it works well :

document.querySelectorAll('your_selector').forEach(item => { /* do the job with item element */ });

I find it more convenient to use something like the following:

document.querySelector('*').addEventListener('click',function(event){

    if( event.target.tagName != "IMG"){
        return;
    }

    // HANDLE CLICK ON IMAGES HERE
});