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);
}
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);
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 .
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!
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))
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
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;
}
});
Vous pouvez également utiliser le prototypage
NodeList.prototype.addEventListener = function (type, callback) {
this.forEach(function (node) {
node.addEventListener(type, callback);
});
};
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".