La méthode EventTarget.addEventListener() ajoute l'objet EventListener (écouteur d'évènements) compatible avec le type d'évènement spécifié sur la EventTarget (cible d'évènement) sur laquelle elle est appelée. La cible d'évènements peut être un Element dans un document, le Document lui-même, une Window ou tout autre objet prenant en charge les évènements (comme XMLHttpRequest).

target.addEventListener(type, listener[, options]);
target.addEventListener(type, listener[, useCapture]);
target.addEventListener(type, listener[, useCapture, wantsUntrusted  ]); // Gecko/Mozilla seulement

Syntaxe

Paramètres

  •   capture : Un Boolean indiquant que les évènements de ce type seront envoyés au listener enregistré avant d'être distribués à tout EventTarget en-dessous dans l'arborescence du DOM.
  •   once : Un Boolean indiquant que le listener doit être invoqué au plus une fois après avoir été ajouté. Si la valeur est true (vrai), le listener sera automatiquement supprimé après son appel.
  • passive : Un Boolean indiquant que le listener  n'appellera jamais preventDefault(). S'il doit le faire, l'agent utilisateur doit l'ignorer et générer un avertissement sur la console. Voir Amélioration des performances de défilement avec les écouteurs passifs pour en apprendre plus.
  • mozSystemGroup : Un Boolean indiquant que l'écouteur doit être ajouté au groupe système. Disponible seulement pour le code exécuté dans XBL ou dans le chrome de Firefox.
type 
une chaîne représentant le type d'évènement à écouter.
listener 
l'objet qui recevra une notification (un objet qui implémente l'interface Event) lorsqu'un évènement du type spécifié se produit. Il doit s'agir d'un objet implémentant l'interface EventListener ou une fonction JavaScript.
options Facultatif
un objet options qui spécifie les caractéristiques de l'écouteur d'évènements. Les options disponibles sont :
useCapture Facultatif
Un  Boolean indiquant si les événements de ce type seront distribués au  listener enregistré avant d'être envoyés à toute EventTarget (cible) sous-jacente dans l'arborescence DOM. Les événements propagés dans l'arborescence ne déclenchent pas un écouteur désigné pour la capture. La propagation et la capture d'événements sont deux manières de propager des événements qui se produisent dans un élément imbriqué dans un autre, lorsque les deux éléments ont enregistré un gestionnaire pour cet événement. Le mode de propagation détermine l'ordre dans lequel les éléments reçoivent l'événement. Voir les événements du DOM niveau 3 et l'ordre des événements JavaScript pour une explication détaillée. Si non spécifié, useCapture a la valeur par défaut false.

Note : Pour les écouteurs attachés à la cible, l'évènement est dans la phase cible, plutôt qu'en phase de propagation ou de capture. Les évènements dans la phase cible seront lancés à tous les écouteurs d'un élément dans l'ordre où ils sont enregistrés, quelque soit le paramètre useCapture.

Note : useCapture n'est pas toujours facultatif. Idéalement, vous devez l'inclure pour la plus grande compatibilité de navigateur possible.

wantsUntrusted
Un paramètre spécifique de Firefox (Gecko). Si la valeur est true (vrai), l'écouteur reçoit des événements synthétiques distribués par le contenu web (la valeur par défaut est false pour chrome et true pour les pages web normales). Ce paramètre est utile pour le code trouvé dans les add-ons ainsi que pour le navigateur lui-même. Voir Interaction entre les pages privilégiées et non privilégiées pour un exemple.

Avant l'utilisation d'une valeur particulière dans l'objet options, c'est une bonne idée de s'assurer que le navigateur de l'utilisateur le supporte, car il s'agit d'un ajout que tous les navigateurs n'ont pas pris en charge historiquement. Voir Safely detecting option support pour plus de détails.

Valeur retournée

undefined.

Détection en toute sécurité du support des options

Dans les anciennes versions de la spécification DOM, le troisième paramètre de addEventListener() était une valeur booléenne indiquant si la capture devait ou non être utilisée. Au fil du temps, il est devenu clair que plus d'options étaient nécessaires. Plutôt que d'ajouter plus de paramètres à la fonction (compliquant énormément les choses en traitant des valeurs optionnelles), le troisième paramètre a été changé en objet pouvant contenir diverses propriétés définissant les valeurs des options pour configurer le processus de suppression de l'écouteur d'événement.

Parce que les navigateurs anciens (ainsi que certains navigateurs pas trop vieux) supposent toujours que le troisième paramètre est un booléen, vous devez construire votre code pour gérer ce scénario intelligemment. Vous pouvez le faire en utilisant la détection de fonctionnalités pour chacune des options qui vous intéresse.

Par exemple, vous pouvez vouloir vérifier pour l'option passive  :

var passiveSupported = false;

try {
  var options = Object.defineProperty({}, "passive", {
    get: function() {
      passiveSupported = true;
    }
  });

  window.addEventListener("test", options, options);
  window.removeEventListener("test", options, options);
} catch(err) {
  passiveSupported = false;
}

Cela crée un objet options avec une fonction de récupération pour la propriété passive ; une marque est placée, passiveSupported, à true si elle est appelée. Cela signifie que si le navigateur vérifie la valeur de la propriété passive sur l'objet options, passiveSupported sera défini sur true ; sinon, il restera false. Nous appelons ensuite addEventListener() pour configurer un faux gestionnaire d'événements, en spécifiant ces options, afin qu'elles soient vérifiées si le navigateur reconnaît un objet comme troisième paramètre. Ensuite, nous appelons removeEventListener() pour nettoyer. (Notez que handleEvent() est ignoré sur les écouteurs d'événement qui ne sont pas appelés).

Vous pouvez vérifier si une option est supportée de cette façon. Ajoutez simplement une fonction de récupération pour cette option en utilisant un code similaire à celui montré ci-dessus.

Ensuite, lorsque vous voulez créer un écouteur d'événement réel qui utilise les options en question, vous pouvez faire quelque chose comme ceci :

someElement.addEventListener("mouseup", handleMouseUp, passiveSupported
                               ? { passive: true } : false);

Ici, nous ajoutons un écouteur pour l'événement mouseup sur l'élément someElement. Pour le troisième paramètre, si passiveSupported est true, nous spécifions un objet options avec passive défini à true ; sinon, nous savons que nous devons passer un booléen, et nous passons false comme valeur du paramètre useCapture.

Si vous préférez, vous pouvez utiliser une bibliothèque tierce comme Modernizr ou Detect It pour faire ce test.

Vous pouvez en apprendre plus dans l'article à propos des EventListenerOptions  du Groupe Web Incubator Community.

Exemples

Ajout d'un écouteur simple

HTML

<table id="outside">
    <tr><td id="t1">one</td></tr>
    <tr><td id="t2">two</td></tr>
</table>

JavaScript

// Fonction pour modifier le contenu de t2
function modifyText() {
  var t2 = document.getElementById("t2");
  if (t2.firstChild.nodeValue == "three") {
    t2.firstChild.nodeValue = "two";
  } else {
    t2.firstChild.nodeValue = "three";
  }
}

// ajout d'un écouteur d'évènement au tableau
var el = document.getElementById("outside");
el.addEventListener("click", modifyText, false);

Dans l'exemple ci-dessus, modifieTexte() est un écouteur pour les évènements click enregistré à l'aide de addEventListener(). Un clic n'importe où sur le tableau se propagera jusqu'au gestionnaire et exécutera modifieTexte().

Si vous voulez transmettre des paramètres à la fonction d'écoute, vous pouvez utiliser une fonction anonyme.

Écouteur d'évènement avec une fonction anonyme

HTML

<table id="outside">
    <tr><td id="t1">one</td></tr>
    <tr><td id="t2">two</td></tr>
</table>

JavaScript

// Fonction pour modifier le contenu de t2
function modifyText(new_text) {
  var t2 = document.getElementById("t2");
  t2.firstChild.nodeValue = new_text;    
}
 
// Fonction pour ajouter un écouteur d'évènement au tableau
var el = document.getElementById("outside");
el.addEventListener("click", function(){modifyText("four")}, false);

Écouteur d'évènement avec une fonction flèche

HTML

<table id="outside">
    <tr><td id="t1">one</td></tr>
    <tr><td id="t2">two</td></tr>
</table>

JavaScript

// Fonction pour modifier le contenu de t2
function modifyText(new_text) {
  var t2 = document.getElementById("t2");
  t2.firstChild.nodeValue = new_text;    
}
 
// Ajout d'un écouteur d'évènement au tableau avec une fonction flèche
var el = document.getElementById("outside");
el.addEventListener("click", () => { modifyText("four"); }, false);

Notez que les fonction anonyme et flèche sont similaires, elles ont différentes liaisons this.

Notes

Pourquoi utiliser addEventListener ?

addEventListener est la manière d'enregistrer un écouteur telle que spécifiée dans le DOM du W3C. Ses avantages sont les suivants :

  • Elle permet d'ajouter plus d'un seul gestionnaire pour un évènement. Cela peut s'avérer particulièrement utile pour les bibliothèques DHTML ou les extensions de Mozilla qui doivent fonctionner correctement même si d'autres bibliothèques/extensions sont utilisées.
  • Elle donne un contrôle plus fin sur la phase d'activation de l'écouteur (capture ou propagation)
  • Elle fonctionne sur tout élément DOM, pas uniquement les éléments HTML.

L'ancienne manière alternative d'enregistrer des évènements est décrite ci-dessous.

Ajout d'un écouteur durant la distribution d'un évènement

Si un écouteur (EventListener) est ajouté à une cible (EventTarget) pendant que celle-ci est en train de diffuser un évènement, il ne sera pas déclenché par l'action en cours mais peut être déclenché à un stade ultérieur de l'évènement, par exemple en phase de propagation (bubbling).

Écouteurs multiples et identiques

Si plusieurs écouteurs (EventListeners) sont enregistrés sur la même cible (EventTarget) avec les mêmes paramètres, les instances en double sont ignorées. L'écouteur ne sera pas appelé plusieurs fois, et comme elles seront ignorées elles ne doivent pas être enlevées à l'aide de la méthode removeEventListener.

La valeur de this dans le gestionnaire

Il est souvent souhaitable de référencer l'élément sur lequel le gestionnaire d'évènements a été lancé, comme lors de l'utilisation d'un gestionnaire générique pour un ensemble d'éléments similaires.

Si le gestionnaire est attaché à une fonction à l'aide de addEventListener(), la valeur de this dans le gestionnaire est une référence à l'élément. C'est la même valeur que celle de la propriété currentTarget de l'argument de l'évènement qui est passée au gestionnaire.

Si un attribut d'évènement (par exemple, onclick) est spécifié sur un élément dans la source HTML, le code JavaScript dans la valeur de l'attribut est effectivement compris dans une fonction gestionnaire qui lie la valeur de this d'une manière compatible avec l'addEventListener() ; une occurrence de this dans le code représente une référence à l'élément. Notez que la valeur de this à l'intérieur d'une fonction, appelée par le code dans la valeur d'attribut, se comporte selon les règles standard. Ceci est illustré dans l'exemple suivant :

<table id="t" onclick="modifyText();">
  . . .

La valeur de this au sein de modifyText() est une référence à l'objet global Window (ou undefined dans le cas du mode strict).

Note : JavaScript 1.8.5 introduit la méthode Function.prototype.bind(), qui vous permet de spécifier la valeur qui doit être utilisée pour tous les appels à une fonction donnée. Cette méthode vous permet de contourner facilement les éventuels problèmes, lorsque vous ne savez pas ce qu'il en résultera, en fonction du contexte à partir duquel votre fonction a été appelée. Notez toutefois que vous devrez conserver une référence à l'écouteur afin de pouvoir le supprimer ultérieurement.

Ceci est un exemple avec et sans bind :

var Something = function(element) {
  // |this| est un nouvel objet créé
  this.name = 'Something Good';
  this.onclick1 = function(event) {
    console.log(this.name); // undefined (indéfini), car |this| est l'élément
  };
  this.onclick2 = function(event) {
    console.log(this.name); // 'Something Good', car |this| est lié à un nouvel objet créé
  };
  element.addEventListener('click', this.onclick1, false);
  element.addEventListener('click', this.onclick2.bind(this), false); // Trick
}
var s = new Something(document.body);

Un problème dans l'exemple ci-dessus, c'est que vous ne pouvez pas supprimer l'écouteur avec bind. Une solution est d'utiliser une fonction spéciale appelée par handleEvent (gestion d'évènement) pour atteindre tous les évènements :

var Something = function(element) {
  // |this| est un nouvel objet créé
  this.name = 'Something Good';
  this.handleEvent = function(event) {
    console.log(this.name); // 'Something Good', car this est lié à un nouvel objet créé
    switch(event.type) {
      case 'click':
        // un peu de code ici...
        break;
      case 'dblclick':
        // un peu de code ici...
        break;
    }
  };

  // Notez que l'écouteur dans ce cas est |this| et non this.handleEvent
  element.addEventListener('click', this, false);
  element.addEventListener('dblclick', this, false);

  // Vous pouvez supprimer l'écouteur proprement
  element.removeEventListener('click', this, false);
  element.removeEventListener('dblclick', this, false);
}
var s = new Something(document.body);

Une autre façon de gérer la référence à this est de passer à EventListener une fonction qui appelle la méthode de l'objet qui contient les champs auxquels il est nécessaire d'accéder :

class SomeClass {

  constructor() {
    this.name = 'Something Good';
  }

  register() {
    var that = this;
    window.addEventListener('keydown', function(e) {return that.someMethod(e);});
  }

  someMethod(e) {
    console.log(this.name);
    switch(e.keyCode) {
      case 5:
        // un peu de code ici...
        break;
      case 6:
        //  un peu de code ici...
        break;
    }
  }

}

var myObject = new SomeClass();
myObject.register();

Héritage Internet Explorer et attachEvent

Dans les versions Internet Explorer versions avant IE 9, vous devez utiliser attachEvent, plutôt que la méthode standard addEventListener. Pour que le code fonctionne dans IE, l'exemple ci-dessus peut être adapté en :

if (el.addEventListener) {
  el.addEventListener('click', modifyText, false); 
} else if (el.attachEvent)  {
  el.attachEvent('onclick', modifyText);
}

attachEvent présente un inconvénient : la valeur de this sera une référence à l'objet window, au lieu de l'élément sur lequel il a été lancé.

Compatibilité

Vous pouvez contourner addEventListener(), removeEventListener(), Event.preventDefault() et Event.stopPropagation(), non pris en charge par IE 8, en utilisant le code suivant au début de votre script. Le code prend en charge l'utilisation de handleEvent et l'évènement DOMContentLoaded également.

Note : useCapture n'est pas pris en charge, car IE 8 n'a aucune méthode alternative. Le code suivant ajoute  seulement cette capacité à IE 8. Ce polyfill pour IE 8 fonctionne uniquement en mode standard : une déclaration doctype est nécessaire.

(function() {
  if (!Event.prototype.preventDefault) {
    Event.prototype.preventDefault=function() {
      this.returnValue=false;
    };
  }
  if (!Event.prototype.stopPropagation) {
    Event.prototype.stopPropagation=function() {
      this.cancelBubble=true;
    };
  }
  if (!Element.prototype.addEventListener) {
    var eventListeners=[];
    
    var addEventListener=function(type,listener /*, useCapture (sera ignoré) */) {
      var self=this;
      var wrapper=function(e) {
        e.target=e.srcElement;
        e.currentTarget=self;
        if (typeof listener.handleEvent != 'undefined') {
          listener.handleEvent(e);
        } else {
          listener.call(self,e);
        }
      };
      if (type=="DOMContentLoaded") {
        var wrapper2=function(e) {
          if (document.readyState=="complete") {
            wrapper(e);
          }
        };
        document.attachEvent("onreadystatechange",wrapper2);
        eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper2});
        
        if (document.readyState=="complete") {
          var e=new Event();
          e.srcElement=window;
          wrapper2(e);
        }
      } else {
        this.attachEvent("on"+type,wrapper);
        eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper});
      }
    };
    var removeEventListener=function(type,listener /*, useCapture (sera ignoré) */) {
      var counter=0;
      while (counter<eventListeners.length) {
        var eventListener=eventListeners[counter];
        if (eventListener.object==this && eventListener.type==type && eventListener.listener==listener) {
          if (type=="DOMContentLoaded") {
            this.detachEvent("onreadystatechange",eventListener.wrapper);
          } else {
            this.detachEvent("on"+type,eventListener.wrapper);
          }
          eventListeners.splice(counter, 1);
          break;
        }
        ++counter;
      }
    };
    Element.prototype.addEventListener=addEventListener;
    Element.prototype.removeEventListener=removeEventListener;
    if (HTMLDocument) {
      HTMLDocument.prototype.addEventListener=addEventListener;
      HTMLDocument.prototype.removeEventListener=removeEventListener;
    }
    if (Window) {
      Window.prototype.addEventListener=addEventListener;
      Window.prototype.removeEventListener=removeEventListener;
    }
  }
})();

Ancienne manière d'attacher des évènements

La méthode addEventListener() a été ajoutée dans la spécification DOM 2 Events. Avant cela, les écouteurs d'évènements étaient enregistrés de la manière suivante :

// Utilisation d'une référence à une fonction — notez l'absence de parenthèses
el.onclick = modifyText;
 
// Utilisation d'une fonction directe
element.onclick = function() {
  ...instructions...
};

Cette méthode remplace l'écouteur d'évènement existant click le cas échéant. De même pour les autres évènements et les gestionnaires d'évènements associés comme blur (onblur), et  keypress ( onkeypress) ont des comportements similaires.

Comme elle faisait essentiellement partie du DOM 0, cette méthode est très largement supportée et ne nécessite aucun code spécial pour gérer les différents navigateurs. C'est pourquoi elle est souvent utilisée pour attacher des évènements dynamiquement tant que les fonctionnalités supplémentaires de addEventListener() ne sont pas nécessaires.

Problèmes de mémoire

var i;
var els = document.getElementsByTagName('*');

// Case 1
for(i=0 ; i<els.length ; i++){
  els[i].addEventListener("click", function(e){/*faire quelque chose*/}, false);
}

// Case 2
function processEvent(e){
  /*faire quelque chose*/
}

for(i=0 ; i<els.length ; i++){
  els[i].addEventListener("click", processEvent, false);
}

Dans le premier cas, une nouvelle fonction (anonyme) est créée avec chaque itération de la boucle. Dans le second cas, la même fonction est déclarée préalablement et utilisée comme gestionnaire d'évènements. Cela entraîne une consommation de mémoire réduite. De plus, dans le premier cas, il n'est pas possible d'appeler removeEventListener() parce qu'aucune référence à la fonction anonyme n'est conservée. Dans le second cas, il est possible de faire myElement.removeEventListener("click", processEvent, false).

Amélioration des performances de défilement avec les écouteurs passifs

La valeur par défaut pour l'option passive est false (faux). À partir de Chrome 56 (bureau, Chrome pour Android et Android), la valeur par défaut pour touchstart et touchmove est true et les appels à preventDefault() ne sont pas autorisés. Pour remplacer ce comportement, vous pouvez définir l'option passive à false comme montré dans l'exemple ci-dessous. Cette modification empêche l'écouteur de bloquer le rendu de la page pendant que l'utilisateur fait défiler. Une démo est disponible sur le site Google Developer. Notez que Edge ne prend pas en charge l'argument options  et l'ajouter emêchera l'utilisation de l'argument useCapture sans l'utilisation appropriée de la fonctionnalité de détection.

/* Fonctionnalité de détection */
var passiveSupported = false;

try {
  window.addEventListener("test", null, Object.defineProperty({}, "passive", { get: function() { passiveSupported = true; } }));
} catch(err) {}

/* Écouteur d'évènements */
var elem = document.getElementById('elem');

elem.addEventListener('touchmove', function listener() {
  /* faire quelque chose */
}, passiveSupported ? { passive: false } : false);

La définition de passive n'est pas importante pour l'évènement scroll de base, car il ne peut être annulé, aussi ses écouteurs n'ont aucun moyen de bloquer le rendu de la page.

Spécifications

Spécification Statut Commentaire
DOM
La définition de 'EventTarget.addEventListener()' dans cette spécification.
Standard évolutif  
DOM4
La définition de 'EventTarget.addEventListener()' dans cette spécification.
Obsolete  
Document Object Model (DOM) Level 2 Events Specification
La définition de 'EventTarget.addEventListener()' dans cette spécification.
Obsolete Définition initiale.

Compatibilité des navigateurs

FonctionnalitéChromeEdgeFirefoxInternet ExplorerOperaSafari
Support simple11121

9

Oui2 3

71
useCapture parameter made optional1 Oui6911.6 Oui
Form with options object supported (third parameter can be either options or a Boolean, for backwards compatibility)49 Oui49 Non Oui10
options: capture option52 Oui Oui Non Oui Oui
options: once option55 Oui50 Non42 Oui
options: passive option51 Oui Oui Non Oui Oui
options: passive option defaults to true for touchstart and touchmove events55 Non Non Non ? Non
FonctionnalitéAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Support simple1111 Oui471 Oui
useCapture parameter made optional11 Oui611.6 Oui Oui
Form with options object supported (third parameter can be either options or a Boolean, for backwards compatibility)4949 Oui49 Oui105.0
options: capture option5252 Oui Oui Oui Oui6.0
options: once option5555 Oui5042 Oui6.0
options: passive option5151 Oui Oui Oui Oui5.0
options: passive option defaults to true for touchstart and touchmove events5555 Non Non ? Non6.0

1. Before Chrome 49, the type and listener parameters were optional.

2. Older versions of IE supported an equivalent, proprietary, EventTarget.attachEvent() method.

3. Supported as attachEvent.

Voir aussi

Étiquettes et contributeurs liés au document

 Dernière mise à jour par : cedeber,