2012-08-23 13 views
7

He estado experimentando con la captura de eventos de clic fuera de los elementos usando stopPropagation().Usando .on() y e.stopPropagation() en elementos dinámicos

$(".container").children().on('click',function(e){ 
    e.stopPropagation();  
}); 
$(".container").on("click",function(){ 
    alert("outside the box?");  
})​ 

Here is a jsFiddle set up to demonstrate it functioning. Debería activarse una alerta cuando haga clic en cualquier lugar fuera del cuadro blanco.

Ahora, estoy tratando de aplicar el mismo principio a los elementos creados dinámicamente. Por lo que yo entiendo, el método on() de asignación de eventos en jQuery debería permitir que esto funcione sin cambiar el script.

Here is a second jsFiddle donde primero debe hacer clic en un enlace para crear los elementos. Una vez que haya hecho esto, la teoría es que el mismo script funcionará, pero no es así. ¿Qué me estoy perdiendo sobre este método?

Respuesta

5

En palabra corta que necesita para poner on() el elemento primario existente para que sea funciona:

$('body').on('click', 'a', function(e){ 
    e.preventDefault(); 
    $('<div class="container"><div class="box"></div></div>').appendTo('body'); 
    $(this).remove(); 
}); 

$('body').on('click', '.container > *', function(e){ 
    e.stopPropagation();  
}); 

$('body').on('click', '.container', function(){ 
    alert("outside the box?");  
})​ 

Código: http://jsfiddle.net/GsLtN/5/

Para más cheque detalle '.on()' en el sitio oficial en la sección de 'Eventos directos y delegados'

+0

Spot on. Poca explicación de por qué sería increíble. –

+0

@MildFuzz: Consulte mi respuesta para obtener una explicación. Si no hubiera visto esta respuesta, debe haber publicado mensajes segundos antes. De todos modos. –

2

Debe enlazar el .on() a uno de los elementos principales.

Lo que intenta hacer es vincular el controlador a un elemento primario que escucha un evento y luego verifica si el evento fue desencadenado por un elemento que coincide con ese selector.

$("body").on("click", '.container',function(){ 
    alert("outside the box?");  
})​ 

violín Actualizado here

5

Cuando el elemento se agrega de forma dinámica, se debe adjuntar el manejador al padre más cercano que seguramente va a estar allí - en su caso se trata de body. Puede utilizar on() this way to achieve a functionalitydelegate() que utiliza para ofrecer:

$ (selector de -de-matriz) .en ( eventos, selector-para-dinámico-niños, manejador);

Así que su código reescrito sería simplemente esto:

$("body").on('click', '.container', function(e){ 
    var $target = $(e.target); 
    if ($target.hasClass('container')) { 
     alert("outside the box!"); 
    } 
}); 

que utilizan e.target para encontrar qué elemento activa realmente el caso. En este caso, identifico el artículo comprobando si tiene la clase container.

jsFiddle Demo

+0

buena solución. ¿Esto afecta mi capacidad para eliminar el enlace? Al vincular eventos a elementos dinámicos, generalmente me gusta eliminar el enlace con el evento para evitar el drenaje de memoria. –

+1

@MildFuzz Si desea eliminar los controladores de eventos, puede usar '.off()' (en 'cuerpo', por supuesto, en este caso). Normalmente [espacio de nombres] (http://docs.jquery.com/Namespaced_Events) mis eventos, para facilitar la eliminación. Esto significa que adjunto en 'click.MyNameSpace' en lugar de simplemente' click'. Pero el truco aquí es que en realidad no es necesario eliminar el controlador de eventos, porque no está vinculado al elemento dinámico en sí; solo debe eliminarlo cuando sepa que no se agregarán más elementos dinámicos de este tipo. – kapa

+0

¿El enlace de eventos en sí no consume memoria? –

2

The demo.

Cuando se enlaza un controlador de eventos a un elemento de uso .on, el objetivo que se unen a debe existir en el domcument.

$('body').on('click', '.container > *', function(e){ 
    e.stopPropagation();  
}); 
$('body').on("click",'.container',function(){ 
    alert("outside the box?");  
})​ 
+0

¿significa esto que no puedo eliminar el enlace del evento? Siempre me gusta limpiar mis encuadernaciones para evitar el drenaje de memoria. –

+1

@MildFuzz Aún puede eliminar sus enlaces con '.off()'. – kapa

1

De acuerdo con la documentación para jQuery.on():

Los controladores de eventos sólo están vinculados a los elementos seleccionados actualmente; ellos deben existir en la página en el momento en que su código realiza la llamada al .on().

Deberá vincular el evento a un contenedor primario. Tal vez algo así como THIS.

Cuestiones relacionadas