web-dev-qa-db-fra.com

Écouteur d'événement de clic JavaScript sur la classe

J'essaie actuellement d'écrire du code JavaScript pour obtenir l'attribut de la classe sur laquelle l'utilisateur a cliqué. Je sais que pour faire ceci correctement, je devrais utiliser un écouteur d'événement. Mon code est le suivant:

var classname = document.getElementsByClassName("classname");

var myFunction = function() {
    var attribute = this.getAttribute("data-myattribute");
    alert(attribute);
};

classname.addEventListener('click', myFunction(), false);

Je m'attendais à recevoir une alerte chaque fois que je cliquais sur l'une des classes pour me dire l'attribut, mais malheureusement, cela ne fonctionne pas. Quelqu'un peut-il aider s'il vous plaît?

(Note - Je peux le faire assez facilement dans jQuery mais je voudrais PAS aimerais l'utiliser )

174
30secondstosam

Cela devrait marcher. getElementsByClassName renvoie un tableau Objet de type tableau (voir édition) des éléments correspondant aux critères.

var classname = document.getElementsByClassName("classname");

var myFunction = function() {
    var attribute = this.getAttribute("data-myattribute");
    alert(attribute);
};

for (var i = 0; i < classname.length; i++) {
    classname[i].addEventListener('click', myFunction, false);
}

jQuery fait la partie en boucle pour vous, ce que vous devez faire en JavaScript.

Si vous avez le support ES6 , vous pouvez remplacer votre dernière ligne par:

    Array.from(classname).forEach(function(element) {
      element.addEventListener('click', myFunction);
    });

Note: Les anciens navigateurs (comme IE6, IE7, IE8) ne supportent pas getElementsByClassName et retournent donc undefined.


EDIT: Correction

getElementsByClassName ne renvoie pas de tableau, mais une plupart des navigateurs (ou HTMLCollection), ou quelques-uns des navigateurs ( Mozilla ref ). Ces deux types sont de type tableau (c'est-à-dire qu'ils possèdent une propriété length et que les objets sont accessibles via leur index), mais qu'ils ne sont pas strictement un tableau ou qu'ils sont hérités d'un tableau. (ce qui signifie que d'autres méthodes pouvant être effectuées sur un tableau ne peuvent pas être effectuées sur ces types)

Merci à l'utilisateur @ Nemo pour l'avoir signalé et m'avoir fait creuser pour bien comprendre.

296
Anudeep Bulla

* Ceci a été modifié pour permettre aux enfants de la classe cible de déclencher les événements. Voir le bas de la réponse pour plus de détails. *

Une autre solution consiste à ajouter un écouteur d'événement à une classe dans laquelle des éléments sont fréquemment ajoutés et supprimés. Ceci est inspiré de la fonction on de jQuery dans laquelle vous pouvez passer un sélecteur pour un élément enfant sur lequel l'événement est en cours d'écoute.

var base = document.querySelector('#base'); // the container for the variable content
var selector = '.card'; // any css selector for children

base.addEventListener('click', function(event) {
  // find the closest parent of the event target that
  // matches the selector
  var closest = event.target.closest(selector);
  if (closest && base.contains(closest)) {
    // handle class event
  }
});

Violon: https://jsfiddle.net/u6oje7af/94/

Cela écoutera les clics sur les enfants de l'élément base et si la cible d'un clic a un parent correspondant au sélecteur, l'événement de classe sera géré. Vous pouvez ajouter et supprimer des éléments à votre guise sans avoir à ajouter d'autres écouteurs de clic aux éléments individuels. Cela les interpellera même pour les éléments ajoutés après l'ajout de cet écouteur, tout comme pour la fonctionnalité jQuery (qui, j'imagine, est un peu similaire sous le capot).

Cela dépend de la propagation des événements, donc si vous stopPropagation sur l'événement ailleurs, cela risque de ne pas fonctionner. De plus, la fonction closest a quelques problèmes de compatibilité avec IE apparemment (qu'est-ce qui ne va pas?).

Cela pourrait être transformé en une fonction si vous devez effectuer ce type d’action en écoutant de manière répétée, comme

function addChildEventListener(base, eventName, selector, handler) {
  base.addEventListener(eventName, function(event) {
    var closest = event.target.closest(selector);
    if (closest && base.contains(closest)) {
      // passes the event to the handler and sets `this`
      // in the handler as the closest parent matching the
      // selector from the target element of the event
      handler.call(closest, event);
    }
  });
}

========================================
EDIT: ce message utilisait à l'origine la fonction matches pour les éléments DOM sur la cible de l'événement, mais cela limitait les cibles des événements à la classe directe uniquement. Il a été mis à jour pour utiliser la fonction closest à la place, permettant ainsi aux événements sur les enfants de la classe souhaitée de les déclencher. Le code original matches peut être trouvé sur le violon original: https://jsfiddle.net/u6oje7af/23/

9
obermillerk

Vous pouvez utiliser le code ci-dessous:

document.body.addEventListener('click', function (evt) {
    if (evt.target.className === 'databox') {
        alert(this)
    }
}, false);
3
Rajat kumar