Debe manejar el evento de clic en el nivel del documento. En el objeto de evento, tiene una targetpropiedad, el elemento DOM más interno en el que se hizo clic. Con esto se revisa y recorre sus padres hasta el elemento del documento, si uno de ellos es su elemento observado.
Vea el ejemplo en jsFiddle
document.addEventListener("click", function (e) {
var level = 0;
for (var element = e.target; element; element = element.parentNode) {
if (element.id === 'x') {
document.getElementById("out").innerHTML = (level ? "inner " : "") + "x clicked";
return;
}
level++;
}
document.getElementById("out").innerHTML = "not x clicked";
});
Como siempre, esto no es compatible con navegadores defectuosos debido a addEventListener / attachEvent, pero funciona así.
Se hace clic en un niño, cuando no es event.target, pero uno de sus padres es el elemento observado (simplemente estoy contando el nivel para esto). También puede tener una var booleana, si el elemento se encuentra o no, para no devolver el controlador desde dentro de la cláusula for. Mi ejemplo se limita a que el controlador solo termina, cuando nada coincide.
Agregando compatibilidad entre navegadores, generalmente lo hago así:
var addEvent = function (element, eventName, fn, useCapture) {
if (element.addEventListener) {
element.addEventListener(eventName, fn, useCapture);
}
else if (element.attachEvent) {
element.attachEvent(eventName, function (e) {
fn.apply(element, arguments);
}, useCapture);
}
};
Este es un código compatible con varios navegadores para adjuntar un detector / manejador de eventos, incluida la reescritura thisen IE, para que sea el elemento, como lo hace jQuery para sus manejadores de eventos. Hay muchos argumentos para tener en cuenta algunos bits de jQuery;)