2010-10-05 20 views
26

Así que tengo el siguiente escenario:Cómo ignorar eventos de clic cuando se hace clic en los niños

<div id="block"> 
Sample text. 
<a href="#">Anchor link</a> 
</div> 

<script type="text/javascript"> 
    $("#block").click(function() { alert('test'); }); 
</script> 

Al hacer clic en cualquier lugar dentro del div, me estoy poniendo alerta del 'test'. Pero, quiero evitar que eso suceda cuando hago clic en el "enlace de anclaje". ¿Cómo puedo implementar eso?

Gracias

Respuesta

27

Puede detener los clics de burbujeo de enlaces con un controlador adicional, como esto:

$("#block a").click(function(e) { e.stopPropagation(); }); 

La alternativa que estábamos discutiendo en los comentarios:

$("#block").delegate('a', 'click', function(e){ e.stopImmediatePropagation(); }) 
      .click(function() { alert('test'); });​ 

Esto evitaría cualquier niño enlaces de burbujeo (bueno, no realmente, pero sus controladores se ejecutan), pero no crean un controlador para cada elemento, esto se hace a través de .stopImmediatePropagation().

+4

Se siente un poco "exagerado" para agregar un controlador de clic a cada enlace solo para evitar la propagación de eventos (por supuesto, depende de la cantidad de enlaces). Pero esta es una buena forma de evitar la propagación de eventos para cualquier elemento específico. –

+0

@Felix - Si hay muchos enlaces, tomaría un enfoque completamente distinto con un conjunto de manejadores '.delegate()' :) (podría usar una versión delegada de lo anterior * antes * del otro manejador de clics también) . –

+0

Acabo de probar con 'delegate()' y no funciona para mí: http://jsfiddle.net/cxcfA/. Supongo que porque el evento ya se hizo borroso. ¿O quieres decir algo más? –

14

Esto es lo que necesita: http://api.jquery.com/event.target/.

Simplemente compare para verificar si el elemento fue activado por el elemento que desea o uno de sus elementos secundarios.

+1

En mi opinión, la mejor solución ... – Arxeiss

6

Puede probar qué nodo se ha hecho clic con la propiedad target del objeto de evento:

$("#block").click(function(event) { 
    if(event.target.nodeName != 'A') { 
     alert('test'); 
    } 
}); 

sugiero leer Event Properties from quirksmode.org.

3
$("#block").click(function(event) { 
    if($(event.target).attr('id') == $(this).attr('id')) 
    { 
     alert('test'); 
    } 
}); 
+0

Trabajó una delicia. ¡Gracias! – hiroki

0

Aquí es una demo (jsfiddle) con unas formas y dos campos:

<div id="container"> 
    <form> 
     <div class="field"> 
      <input id="demo" type="text" name="demo" /> 
     </div> 
     <div class="field"> 
      <input id="demo2" type="text" name="demo2" /> 
     </div> 
    </form> 
</div> 

El código es el siguiente:

$(document).ready(function() { 
    $('#container').click(function(evt) { 
     if(this == evt.target) { 
      console.log('clicked container',evt.target); 
      $('#demo').focus(); 
     } else { 
      console.log('clicked child -> ignoring'); 
     } 
    }); 

    $('.field').click(function(evt) { 
     if(this == evt.target) { 
      console.log('clicked field div',evt.target); 
      $(this).find('input').focus(); 
     } else { 
      console.log('clicked child -> ignoring'); 
     } 
    }); 
}); 

Puede clic en el contenedor que contiene el formulario para establecer el foco en el primer campo de entrada o detrás del campo de entrada para establecer el foco en él.

Si hace clic en el campo, se ignorará el clic.

El código anterior funciona desde jQuery asigna el nodo DOM para this antes de llamar a los controladores de eventos, por lo que se puede comprobar fácilmente si el evento actual fue publicado por el nodo DOM comprobando

this == evt.target 

CSS:

#container { 
    width: 600px; 
    height: 600px; 
    background: blue; 
} 

.field { 
    background: green; 
} 
Cuestiones relacionadas