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


220

J'essaie actuellement d'écrire du JavaScript pour obtenir l'attribut de la classe qui a été cliquée. Je sais que pour le faire correctement, je dois utiliser un écouteur d'événements. 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 boîte d'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?

( Remarque - je peux le faire assez facilement, jQuerymais je ne voudrais pas l' utiliser )


2
Il y a un problème avec le code qui ajoute l'écouteur d'événements. addEventListener prend le nom de l'événement («clic»), la référence à la fonction (et non le résultat de la fonction telle qu'elle est maintenant en appelant myFunction () avec des parens) et un indicateur pour indiquer le bouillonnement de l'événement. L'appel addEventListener doit ressembler à: elem.addEventListener ('click', myFunction, false) et classname est un type NodeList. Vous devez parcourir tous les éléments et attacher l'auditeur à chacun dans la liste.
Joey Guerra

Réponses:


373

Cela devrait fonctionner. getElementsByClassNamerenvoie un tableau de type tableau (voir modification) des éléments correspondant aux critères.

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

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

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

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

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

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

Remarque: les navigateurs plus anciens (comme IE6, IE7, IE8) ne prennent pas en charge getElementsByClassNameet reviennent donc undefined.


EDIT: correction

getElementsByClassNamene renvoie pas de tableau, mais une HTMLCollection dans la plupart des cas, ou une NodeList dans certains navigateurs ( ref Mozilla ). Ces deux types sont de type tableau (ce qui signifie qu'ils ont une propriété length et que les objets sont accessibles via leur index), mais ne sont pas strictement un tableau ou hérités d'un tableau. (ce qui signifie que d'autres méthodes pouvant être exécutées sur un tableau ne peuvent pas être exécutées sur ces types)

Merci à l'utilisateur @ Nemo de l' avoir signalé et de m'avoir invité à comprendre.


6
Cela fonctionne parfaitement. Je vous remercie. En fait, je ne savais pas que jQuery faisait la boucle. Grande aide Anudeep. Voici votre réponse de travail: jsfiddle.net/LWda3/2
30secondstosam

2
document.getElementsByClassNameretourne en fait toujours un tableau, même si un seul élément correspond aux critères
Guilherme Sehn

Attention, le premier élément du tableau est tous les éléments dom. Alors commencez votre boucle for avec 1
Vishal Sakaria

11
stackoverflow.com/a/13258908/1333493 "document.getElementsByClassName ne renvoie pas de tableau. Il renvoie une liste de nœuds traversée comme un fichier XML."
Nemo

9
Array.from()a un deuxième paramètre qui est une fonction de carte de sorte que ce qui précède (en supposant le support es6) pourrait être écrit Array.from(classname, c => c.addEventListener('click', myFunction));.
Kilmazing

12

* 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 réponse alternative pour ajouter un écouteur d'événements à une classe où des éléments sont fréquemment ajoutés et supprimés. Ceci est inspiré par la onfonction de jQuery où vous pouvez passer un sélecteur pour un élément enfant que l'événement é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' baseélément 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 comme vous le souhaitez sans avoir à ajouter plus d'écouteurs de clic aux éléments individuels. Cela les rattrapera même pour les éléments ajoutés après l'ajout de cet écouteur, tout comme la fonctionnalité jQuery (qui, j'imagine, est quelque peu similaire sous le capot).

Cela dépend des événements qui se propagent, donc si vous êtes stopPropagationsur l'événement ailleurs, cela peut ne pas fonctionner. De plus, la closestfonction a apparemment des problèmes de compatibilité avec IE (qu'est-ce qui ne l'est pas?).

Cela pourrait être transformé en une fonction si vous devez effectuer ce type d'action en écoutant à plusieurs reprises, 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 matchesfonction pour Éléments DOM sur la cible de l'événement, mais cela a limité les cibles des événements à la classe directe uniquement. Il a été mis à jour pour utiliser la closestfonction à la place, permettant aux événements sur les enfants de la classe souhaitée de déclencher également les événements. Le matchescode d' origine se trouve sur le violon d'origine: https://jsfiddle.net/u6oje7af/23/


3

Vous pouvez utiliser le code ci-dessous:

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

Je vais devoir essayer, c'est une approche unique qui pourrait en fait être plus facile à maintenir et à exécuter mieux que la boucle!
Cliff Helsel

4
si l'élément a plusieurs classes, vous devrez vérifier la valeur correcte dans ces champs, par exemple. cours et ordre. je préfère y allerevt.target.classList.contains('databox')
honk31

8
Cela me semble extrêmement inefficace. Chaque événement sur le corps passerait par cette fonction. Qu'est-ce qui est si difficile à maintenir à propos d'une boucle?
JosefAssad

C'est très inefficace, vous devez parcourir chaque élément comme l'a dit @JosefAssad.
nullwriter

3

Avec le JavaScript moderne, cela peut être fait comme ceci:

const divs = document.querySelectorAll('.a');

divs.forEach(el => el.addEventListener('click', event => {
  console.log(event.target.classList[1]);
}));
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Example</title>
  <style>
    .a {
      background-color:red;
      height: 33px;
      display: flex;
      align-items: center;
      margin-bottom: 10px;
      cursor: pointer;
    }
    
    .b {
      background-color:#00AA00;
      height: 50px;
      display: flex;
      align-items: center;
      margin-bottom: 10px;
    }
  </style>
</head>
<body>
  <div class="a a-1">1</div>
  <div class="b">2</div>
  <div class="a a-2">11</div>
</body>
</html>

  1. Obtient tous les éléments par nom de classe
  2. Boucle sur tous les éléments avec l'utilisation de forEach
  3. Attachez un écouteur d'événements à chaque élément
  4. Utilise event.targetpour récupérer plus d'informations pour un élément spécifique
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.