web-dev-qa-db-fra.com

addEventListener sur NodeList

NodeList prend-il en charge addEventListener? Sinon, quel est le meilleur moyen d'ajouter EventListener à tous les nœuds de NodeList. Actuellement, j'utilise l'extrait de code comme indiqué ci-dessous. Existe-t-il un meilleur moyen de le faire?.

var ar_coins = document.getElementsByClassName('coins');
for(var xx=0;xx < ar_coins.length;xx++)
{
        ar_coins.item(xx).addEventListener('dragstart',handleDragStart,false);
}
21
Dinesh P.R.

Il n'y a aucun moyen de le faire sans parcourir tous les éléments. Vous pouvez bien sûr écrire une fonction pour le faire à votre place.

function addEventListenerList(list, event, fn) {
    for (var i = 0, len = list.length; i < len; i++) {
        list[i].addEventListener(event, fn, false);
    }
}

var ar_coins = document.getElementsByClassName('coins');
addEventListenerList(ar_coins, 'dragstart', handleDragStart); 

ou une version plus spécialisée:

function addEventListenerByClass(className, event, fn) {
    var list = document.getElementsByClassName(className);
    for (var i = 0, len = list.length; i < len; i++) {
        list[i].addEventListener(event, fn, false);
    }
}

addEventListenerByClass('coins', 'dragstart', handleDragStart); 

Et, bien que vous n’ayez pas posé de question sur jQuery, c’est le genre de choses pour lesquelles jQuery est particulièrement doué:

$('.coins').on('dragstart', handleDragStart);
27
jfriend00

Il y a en fait est un moyen de faire ceci sans une boucle: 

[].forEach.call(nodeList,function(e){e.addEventListener('click',callback,false)})

Et cette méthode est utilisée dans l’une de mes bibliothèques d’aide unique - nanoQuery .

13
Multiversum

Le mieux que j'ai pu trouver était ceci:

const $coins = document.querySelectorAll('.coins')
[...$coins].forEach($coin => $coin.addEventListener('dragstart', handleDragStart));

Notez que ceci utilise les fonctionnalités de l'ES6, alors assurez-vous de le copier d'abord!

11
Kris Selbekk

dans es6, vous pouvez créer un tableau à partir de nodelist, en utilisant Array.from, par exemple.

ar_coins = document.getElementsByClassName('coins');
Array
 .from(ar_coins)
 .forEach(addEvent)

function addEvent(element) {
  element.addEventListener('click', callback)
}

ou utilisez simplement les fonctions fléchées

Array
  .from(ar_coins)
  .forEach(element => element.addEventListener('click', callback))
4
Darlan Mendonça

L’exemple le plus simple consiste à ajouter cette fonctionnalité à NodeList

NodeList.prototype.addEventListener = function (event_name, callback, useCapture)
{
    for (var i = 0; i < this.length; i++)
    {
      this[i].addEventListener(event_name, callback, useCapture);
    }
};

Maintenant vous pouvez faire:

document.querySelectorAll(".my-button").addEventListener("click", function ()
{
    alert("Hi");
});

De la même manière, vous pouvez faire une boucle forEach

NodeList.prototype.forEach = function (callback)
{
    for (var i = 0; i < this.length; i++)
    {
      callback(this[i], i);
    }
};

En utilisant:

document.querySelectorAll(".buttons").forEach(function (element, id)
{
    input.addEventListener("change", function ()
    {
        alert("button: " + id);
    });
});

EDIT: notez que NodeList.prototype.forEach existe depuis novembre 2016 dans FF. Pas de support IE cependant

4
Profesor08

Je suppose qu'une autre option serait de définir addEventListener sur NodeList en utilisant Object.defineProperty. De cette façon, vous pouvez traiter la liste de noeuds comme vous le feriez avec un seul noeud.

Par exemple, j'ai créé un jsfiddle ici: http://jsfiddle.net/2LQbe/

Le point clé est le suivant:

Object.defineProperty(NodeList.prototype, "addEventListener", {
    value: function (event, callback, useCapture) {
        useCapture = ( !! useCapture) | false;
        for (var i = 0; i < this.length; ++i) {
            if (this[i] instanceof Node) {
                this[i].addEventListener(event, callback, useCapture);
            }
        }
        return this;
    }
});
1
Duncan

Vous pouvez également utiliser le prototypage

NodeList.prototype.addEventListener = function (type, callback) {
    this.forEach(function (node) {
        node.addEventListener(type, callback);
    });
};
0
caliburn

Une autre solution consiste à utiliser la délégation d'événement. Vous ajoutez simplement un eventlistener au parent de closets du ".coins" et utilisez event.target dans le rappel pour vérifier si le clic était vraiment sur un élément de la classe "pièces".

0
user414873