Não há nada de errado com essa configuração (ou há?), Mas posso suavizar um pouco?
Considere o uso da delegação de eventos. É onde você realmente observa o evento em um contêiner que não desaparece e, em seguida, usa event.target
(ou event.srcElement
no IE) para descobrir onde o evento realmente ocorreu e tratá-lo corretamente.
Dessa forma, você anexa o (s) manipulador (es) apenas uma vez e eles continuam funcionando mesmo quando você troca o conteúdo.
Aqui está um exemplo de delegação de evento sem usar nenhuma biblioteca auxiliar:
(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);
}
})();
Exemplo vivo
Observe como, se você clicar nas mensagens que são adicionadas dinamicamente à página, seu clique é registrado e manipulado, embora não haja nenhum código para conectar eventos nos novos parágrafos que estão sendo adicionados. Observe também como seus manipuladores são apenas entradas em um mapa, e você tem um manipulador no document.body
que faz todo o despacho. Agora, você provavelmente enraíza em algo mais direcionado do que document.body
, mas essa é a ideia. Além disso, no exemplo acima, basicamente estamos enviando por id
, mas você pode fazer correspondências tão complexas ou simples quanto desejar.
Bibliotecas JavaScript modernas como jQuery , Prototype , YUI , Closure ou qualquer uma das várias outras devem oferecer recursos de delegação de eventos para amenizar as diferenças do navegador e lidar com casos extremos de forma limpa. jQuery certamente o faz, com suas funções live
e delegate
, que permitem especificar manipuladores usando uma gama completa de seletores CSS3 (e mais alguns).
Por exemplo, aqui está o código equivalente usando jQuery (exceto que tenho certeza de que jQuery lida com casos extremos que a versão bruta improvisada acima não):
(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);
Cópia ao vivo