IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Comprendre la délégation d'événement en JavaScript

Le , par Bovino

0PARTAGES

La délégation d'événement, qu'est-ce que c'est ?

La délégation d'événement est une technique assez courante en JavaScript qui consiste à poser des écouteurs d'événement non pas sur l'élément HTML ciblé, mais sur l'un de ses ancêtres dans le DOM.

Comment ça marche ?

Le concept essentiel pour comprendre cette technique est la notion de bouillonnement d'un événement. À de rares exceptions prêt, quasiment tous les événement bouillonnent.
Si l'on se représente une page Web comme une feuille de papier sur laquelle on poserait d'autres feuilles de tailles différentes et placées à des endroits précis selon l'arborescence des balises et la mise en page CSS, on peut se représenter un événement (un clic sur une balise par exemple) comme étant intercepté par l'élément le plus au-dessus de l'empilement (et inversement, le plus profond dans l'arborescence du DOM). C'est donc cet élément qui va recevoir l'événement. Le bouillonnement est le mécanisme qui va faire « remonter » cet événement jusqu'au plus haut niveau de l'arborescence (la première feuille de papier) en passant par tous les éléments se trouvant à l'emplacement où l'événement a été déclenché, permettant ainsi à tous les gestionnaires d'événements associés de se déclencher.

En résumé, si l'on considère le code HTML suivant
Code html : Sélectionner tout
1
2
3
4
5
<body> 
    <div> 
        <span>Cliquer ici</span> 
    </div> 
</body>
et que vous placez un écouteur d'événement clic sur la div, cliquer sur le texte du span déclenchera l'événement de la div bien que ce span « cache » cette dernière. Ceci est possible grâce au bouillonnement.

Pour en revenir à notre délégation d'événement, nous pourrons savoir, avec l'objet Event associé à tout événement, quel élément HTML a réellement déclenché cet événement (Event.target) et si ce dernier est bien celui que nous souhaitons cibler.

À quoi cela peut-il servir ?

Il y a deux cas typiques d'utilisation de la délégation d'événement.

• Lorsque l'on souhaite associer des événements similaires à différents éléments.
Par exemple, imaginons que l'on souhaite afficher un texte initialement masqué en cliquant sur des items d'une liste ordonnée. Plutôt que de définir autant d'événement que d'éléments dans la liste, on pourra n'en utiliser qu'un seul placé sur la balise <ul>
Code html : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
<ul id="maListe"> 
    <li class="element" data-texte="foo">Item 1</li> 
    <li class="element" data-texte="bar">Item 2</li> 
    <li class="element" data-texte="baz">Item 3</li> 
    <li class="element" data-texte="toto">Item 4</li> 
    <li class="element" data-texte="titi">Item 5</li> 
    <li class="element" data-texte="tata">Item 6</li> 
    <li>Item 7</li> 
    <li>Item 8</li> 
    <li>Item 9</li> 
    <li class="element" data-texte="42">Item 10</li> 
</ul>
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
document.getElementById('maListe').addEventListener('click', function(e){ 
    var initElem = e.target; 
    if(initElem.className != 'element'){ // Si l'élément n'est pas un de ceux à traiter 
        return; 
    } 
    alert(initElem.dataset.texte); 
});
Voir l'exemple sur JSFiddle.

Dans ce code, on cherche à afficher le contenu de l'attribut data-texte pour tous les élément ayant la classe element.
On commence d'abord par récupérer l'élément ayant reçu l'événement. On vérifie ensuite si cet élément est bien du type que l'on cible, si ce n'est pas le cas, on stoppe l'exécution de la fonction, sinon, on affiche le message.

• Lorsque l'on veut prévoir des gestionnaires d'événements sur des éléments n'étant pas encore présents dans la page.
Il est de plus en plus fréquent, avec les interfaces riches et AJAX, que le contenu d'une page évolue en fonction des actions de l'utilisateur.
On peut donc avoir à gérer des événements sur des éléments qui n'existent pas au chargement de la page mais qui sont susceptibles d'y apparaitre.
Seulement, lorsque l'on déclare un gestionnaire, il ne peut s'appliquer qu'à des éléments effectivement présents au moment de la déclaration de l'écouteur : JavaScript n'est pas devin ni prédictif.
Pour cela, on pourra facilement poser le gestionnaire sur un ancêtre connu (et existant) dans lequel seront insérés les futurs éléments.
Code html : Sélectionner tout
1
2
<div id="parent"></div> 
<button>Ajouter un élément</button>
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
document.getElementById('ajout').onclick = function(){ 
    document.getElementById('parent').innerHTML = '<span id="enfant">Elément enfant ajouté dynamiquement</span>'; 
}; 
document.getElementById('parent').addEventListener('click', function(e){ 
    var initElem = e.target; 
    if(initElem.id == 'enfant'){ 
        alert('Vous avez cliqué !'); 
    } 
});
Voir l'exemple sur JSFiddle.

Au moment de déclarer l'événement, l'élément enfant n'existe pas, pourtant, lorsqu'on l'insère dans la page et que l'on clique dessus, le message s'affiche.

Aller plus loin
Il est important, quand on utilise la délégation d'événement, de faire attention que si l'élément ciblé possède des éléments enfants, alors Event.target peut ne pas correspondre à celui ciblé, il faudra dans ce cas remonter l'arborescence jusqu'à l'élément sur lequel le gestionnaire est posé en testant à chaque palier si l'élément en cours est celui recherché.
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
var initElem = false, tmpElem = e.target; 
do{ 
    if(tmpElem.id == 'id_recherche'){ 
        initElem = tmpElem; 
    } 
} 
while(tmpElem = tmpElem.parentNode && tmpElem != this); 
if(initElem){ 
    // tmpElem ne vaut pas false si on entre dans cette condition 
    // donc l'élément recherché a été trouvé 
    // on peut donc faire les traitement voulus 
}

Il est aussi à noter que la plupart des bibliothèques JavaScript permettent d'utiliser la délégation d'événement.
Par exemple pour jQuery, la syntaxe
Code javascript : Sélectionner tout
$('#elem1').on('click', '.elems2', callback);
permet de déléguer la gestion des événements clic sur les éléments ayant la classe CSS elems2 sur l'élément dont l'identifiant est elem1.
N'hésitez pas à indiquer dans les commentaires les différentes syntaxes pour les autres frameworks.

Une erreur dans cette actualité ? Signalez-le nous !