2010-03-02 16 views
154

Tengo un div al que he adjuntado un evento onclick. en este div hay una etiqueta con un enlace. Cuando hago clic en el enlace, también se desencadena el evento onclick del div. ¿Cómo puedo desactivar esto para que si se hace clic en el enlace en el div onclick no se active?jquery stop niño que desencadena el evento principal

guión:

$(document).ready(function(){ 
    $(".header").bind("click", function(){ 
     $(this).children(".children").toggle(); 
    }); 
}) 

código html:

<div class="header"> 
    <a href="link.html">some link</a> 
    <ul class="children"> 
     <li>some list</li> 
    </ul> 
</div> 

Respuesta

344

hacer esto:

$(document).ready(function(){ 
    $(".header").click(function(){ 
     $(this).children(".children").toggle(); 
    }); 
    $(".header a").click(function(e) { 
     e.stopPropagation(); 
    }); 
}); 

Si desea read more on .stopPropagation(), look here.

+2

si ayuda a alguien, he sustituido '$ (" cabecera a. ")' 'Con $ (".header * ")' y seleccionó cualquier elemento secundario (div, forms, input, etc) –

+0

e.stopPropagation(); debe escribirse en la primera línea, a menos que no funcione! – ehsan

+3

@ehsan Quizás quiso decir: "or no funcionará "? –

0

O esto:

$(document).ready(function(){ 
    $(".header").click(function(){ 
     $(this).children(".children").toggle(); 
    }); 
    $(".header a").click(function(e) { 
     return false; 
    }); 
}); 
+8

No pasa nada en (e) si devuelve falso. – Halcyon991

+2

@ Halcyon991 e se pasa de cualquier manera a través de argumentos, e es solo una referencia – qodeninja

+0

@qodeninja Sí, pero una adición innecesaria de caracteres si no se usa. – Halcyon991

15

mejor manera mediante el uso de on() con el encadenamiento como,

$(document).ready(function(){ 
    $(".header").on('click',function(){ 
     $(this).children(".children").toggle(); 
    }).on('click','a',function(e) { 
     e.stopPropagation(); 
    }); 
}); 
3

Las respuestas aquí tomó la pregunta del OP demasiado literalmente. ¿Cómo se pueden expandir estas respuestas a un escenario donde hay MUCHOS elementos secundarios, no solo una sola etiqueta <a>? Aquí hay una manera.

Digamos que tiene una galería de fotos con un fondo oscurecido y las fotos centradas en el navegador. Cuando hace clic en el fondo negro (pero no en el interior), desea que se cierre la superposición.

Aquí hay algunas posibles HTML:

<div class="gallery" style="background: black"> 
    <div class="contents"> <!-- Let's say this div is 50% wide and centered --> 
     <h1>Awesome Photos</h1> 
     <img src="img1.jpg"><br> 
     <img src="img2.jpg"><br> 
     <img src="img3.jpg"><br> 
     <img src="img4.jpg"><br> 
     <img src="img5.jpg"> 
    </div> 
</div> 

Y así es como el código JavaScript funcionaría:

$('.gallery').click(
    function() 
    { 
     $(this).hide(); 
    } 
); 

$('.gallery > .contents').click(
    function(e) { 
     e.stopPropagation(); 
    } 
); 

Esto evitará que los eventos de clic de elementos dentro .contents de cada investigación .gallery por lo que la galería se cerrará solo cuando hace clic en el área de fondo negro difuminado, pero no cuando hace clic en el área de contenido. Esto se puede aplicar a muchos escenarios diferentes.

1

Una forma más corta para hacerlo:

$('.header').on('click', function() { 
    $(this).children('a').on('click', function(e) { 
     e.stopPropagation(); 
     $(this).siblings('.children').toggle(); 
    }); 
}); 
50

O, en lugar de tener un controlador de eventos extra para evitar que otro controlador, puede utilizar el argumento Event Object pasado a su controlador de eventos click para determinar si un niño fue hecho clic. target habrá hecho clic en el elemento y currentTarget será el div .header:

$(".header").click(function(e){ 
    //Do nothing if .header was not directly clicked 
    if(e.target !== e.currentTarget) return; 

    $(this).children(".children").toggle(); 
}); 
+1

Para mí, esta es una solución más elegante ya que no tiene que agregar un preventDefault explícito() a cada elemento secundario. –

+1

Y funciona si tiene eventos independientes en niños a diferencia de la respuesta aceptada. Definitivamente la solución más limpia y mejor –

+2

En la mayoría de los casos, no le importará esto, pero si por alguna razón necesita soportar IE6-8, ellos [no tienen 'currentTarget'] (https://developer.mozilla.org/en -US/docs/Web/API/Event/currentTarget). Una solución es reemplazarlo por 'this', como se sugiere en [otra respuesta] (http://stackoverflow.com/a/6411507/2737565). –

0

me encontré con este problema, en busca de otra respuesta.

Quería evitar que todos los niños activen el elemento principal.

Este es el método más fácil, más legible para que:

$(".parent").click(function() { 
    // Do something 
}).children().on("click", function(e) { 
    e.stopPropagation(); 
}); 
Cuestiones relacionadas