Nous avons déjà vu les pièges à éviter lors de l'écriture de la gestion d'événements.
- perte du this,
- passage de paramètres.
Voici donc comment écrire la gestion d'événements en Javascript.
Pré-requis : La compréhension fait appel à la notion de closure.
Pour exemple, nous simulons un comportement basique (code jquery)
$( "p" ).on( "click", function() {
$(this).toggleClass("selected");
});
En JavaScript
for (var i = 0; i < ps.length; i++) {
ps[i].addEventListener("click", function(){
this.classList.toggle('selected');
}, true);
}
Allons plus loin.Nous voulons manipuler l'objet cliqué et connaître son indice.
Voici le code en JS (code que nous allons rendre beaucoup plus compréhensif par la suite)
(function(){
var zone = document.body.querySelector("div");
var zonePs = zone.querySelectorAll('p','div');
for (var i = 0; i < zonePs.length; i++) {
zonePs[i].addEventListener("click",
(function(index, para){
return function(e) {
console.log("nb =" + index);
para.classList.toggle('selected');
};
})(i,zonePs[i]),
true);
}
})();
Nous allons décomposer le code en trois étapes
- sélection
- closure
- action
Etape de sélection
var zone = document.body.querySelector("div");
var zonePs = zone.querySelectorAll('p');
Ecriture de la closure
L'idée est simple, la closure va permettre de rendre accessibles à une fonction (portée des variables) des paramètres.
- Les paramètres sont ici le paragraphe et son numéro dans la liste des paragraphe à traiter.
- La fonction est l'action a réaliser lors du clique.
Par défaut seul l'événement est disponible dans la fonction action, la closure rajoute des variables supplémentaires (par exemple : le numéro de paragraphe et l'identifiant).
zonePs[i].addEventListener("click",
closure(i, zonePs[i]),
true);
}
Remarquez que la fonction closure est immédiatement exécutée.
function closure(index, para) {
//closure index et para dispo pour la fonction suivante
console.log("closure index = "+ index);
console.log("closure type = "+ para.nodeName);
//déclaration d'une fonction anonyme actionnée lors du clic
return function(e) {
console.log(e.type + " index = "+ index);
console.log(e.type + " typeNode " + para.nodeName);
action(para);
};
}
Ainsi, lors de l'exécution de la boucle, on exécute deux fois la fonction closure.
Exemple d'application :
Remarque
L'arrivée de Array.from et de la délégation permet de simplifier le code et diminue le nombre d'événement à écrire.