Il n'y a rien de mal à cette configuration (ou n'y en a-t-il pas ?), mais puis-je l'adoucir un peu ?
Envisagez plutôt de recourir à la délégation d'événements. Il s'agit de guetter l'événement sur un conteneur qui ne disparaître, puis utiliser event.target
(ou event.srcElement
sur IE) pour déterminer où l'événement s'est réellement produit et le traiter correctement.
De cette façon, vous n'attachez le(s) gestionnaire(s) qu'une seule fois et il(s) continue(nt) à fonctionner même si vous changez de contenu.
Voici un exemple de délégation d'événements sans utiliser de librairie d'aide :
(function() {
var handlers = {};
if (document.body.addEventListener) {
document.body.addEventListener('click', handleBodyClick, false);
}
else if (document.body.attachEvent) {
document.body.attachEvent('onclick', handleBodyClick);
}
else {
document.body.onclick = handleBodyClick;
}
handlers.button1 = function() {
display("Button One clicked");
return false;
};
handlers.button2 = function() {
display("Button Two clicked");
return false;
};
handlers.outerDiv = function() {
display("Outer div clicked");
return false;
};
handlers.innerDiv1 = function() {
display("Inner div 1 clicked, not cancelling event");
};
handlers.innerDiv2 = function() {
display("Inner div 2 clicked, cancelling event");
return false;
};
function handleBodyClick(event) {
var target, handler;
event = event || window.event;
target = event.target || event.srcElement;
while (target && target !== this) {
if (target.id) {
handler = handlers[target.id];
if (handler) {
if (handler.call(this, event) === false) {
if (event.preventDefault) {
event.preventDefault();
}
return false;
}
}
}
else if (target.tagName === "P") {
display("You clicked the message '" + target.innerHTML + "'");
}
target = target.parentNode;
}
}
function display(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
})();
Exemple concret
Notez que si vous cliquez sur les messages qui sont ajoutés dynamiquement à la page, votre clic est enregistré et traité même s'il n'y a pas de code pour accrocher des événements sur les nouveaux paragraphes qui sont ajoutés. Notez également que vos gestionnaires ne sont que des entrées dans une carte, et que vous avez un sur le gestionnaire document.body
qui s'occupe de tout le dispatching. Maintenant, vous devez probablement Rooter ceci dans quelque chose de plus ciblé que document.body
mais vous voyez l'idée. De plus, dans ce qui précède, nous envoyons essentiellement par id
mais vous pouvez faire des correspondances aussi complexes ou simples que vous le souhaitez.
Les bibliothèques JavaScript modernes telles que jQuery , Prototype , YUI , Fermeture o un autre parmi d'autres devrait offrir des fonctions de délégation d'événements afin d'aplanir les différences entre les navigateurs et de gérer proprement les cas particuliers. jQuery le fait assurément, avec ses deux modules live
y delegate
qui vous permettent de spécifier des gestionnaires utilisant une gamme complète de sélecteurs CSS3 (et plus encore).
Par exemple, voici le code équivalent en utilisant jQuery (sauf que je suis sûr que jQuery gère les cas limites, ce qui n'est pas le cas de la version brute ci-dessus) :
(function($) {
$("#button1").live('click', function() {
display("Button One clicked");
return false;
});
$("#button2").live('click', function() {
display("Button Two clicked");
return false;
});
$("#outerDiv").live('click', function() {
display("Outer div clicked");
return false;
});
$("#innerDiv1").live('click', function() {
display("Inner div 1 clicked, not cancelling event");
});
$("#innerDiv2").live('click', function() {
display("Inner div 2 clicked, cancelling event");
return false;
});
$("p").live('click', function() {
display("You clicked the message '" + this.innerHTML + "'");
});
function display(msg) {
$("<p>").html(msg).appendTo(document.body);
}
})(jQuery);
Copie en direct