2008-12-08 18 views
95

Permítanme describir el problema en detalle:Cómo deshabilitar los eventos de mouse desencadenados por elementos secundarios?

Quiero mostrar un div posicionado absoluto al pasar el mouse sobre un elemento. Eso es realmente simple con jQuery y funciona bien. Pero cuando el mouse pasa sobre uno de los elementos secundarios, desencadena el evento mouseout del div que contiene. ¿Cómo evito que javascript active el evento mouseout del elemento contenedor al pasar un elemento secundario?

¿Cuál es la mejor y más corta forma de hacer eso con jQuery?

Aquí es un ejemplo simplificado para ilustrar lo que quiero decir:

HTML:

<a>Hover Me</a> 
<div> 
    <input>Test</input> 
    <select> 
    <option>Option 1</option> 
    <option>Option 2</option> 
    </select> 
</div> 

Javascript/jQuery:

$('a').hover(function() { $(this).next().show() } 
       function() { $(this).next().hide() }); 
+0

[Sin la versión de jQuery] (http://stackoverflow.com/q/4697758/2065702) de esta pregunta –

Respuesta

195

La pregunta es un poco antigua, pero me encontré con esto el otro día.

La forma más sencilla de hacer esto con las últimas versiones de jQuery es utilizar los mouseenter y mouseleave acontecimientos en lugar de mouseover y mouseout.

Puede probar el comportamiento rápidamente con:

$(".myClass").on({ 
    'mouseenter':function() { console.log("enter"); }, 
    'mouseleave':function() { console.log("leave"); } 
}); 
+1

Ayudó a mi problema no relacionado con javascript javascript. ¡Estaba usando mouseenter/mouseout en lugar de mouseleave con mis oyentes de eventos! –

+1

Para búsqueda, estos comportamientos de eventos de mouse son equivalentes a 'ROLL_OVER' y' ROLL_OUT' en AS3. –

+2

me salvó algunos dolores de cabeza. Es curioso cómo al pasar el ratón sobre los elementos secundarios desencadena el evento 'mouseout' de los padres, cuando en realidad todavía está dentro del elemento padre. –

18

Por razones de simplicidad, me acaba de reorganizar el html una mordió para poner el contenido recién visualizado dentro del elemento al que se asocia el evento mouseover:

<div id="hoverable"> 
    <a>Hover Me</a> 
    <div style="display:none;"> 
    <input>Test</input> 
    <select> 
     <option>Option 1</option> 
     <option>Option 2</option> 
    </select> 
    </div> 
</div> 

Entonces, se podría hacer algo como esto:

$('#hoverable').hover(function() { $(this).find("div").show(); }, 
         function() { $(this).find("div").hide(); }); 

Nota: No recomiendo CSS en línea, pero se hizo para hacer el ejemplo más fácil de digerir.

+0

T la suya es de hecho una solución muy simple y limpia. Gracias por recordarme. Pero en mi situación específica, que no es exactamente como en la pregunta, esta es una opción. ¡Gracias! –

+0

Después de probar diferentes métodos como otros describen aquí en SO, volví a su método y lo hice funcionar en mi caso. ¡Hurra! :-) –

0

La forma en que generalmente he visto esto manejado es tener un retraso de aproximadamente 1/2 segundo entre mover el mouse del elemento HoverMe. Cuando mueva el mouse al elemento fijo, querrá establecer alguna variable que señale que está sobre el elemento, y luego básicamente evitará que la parte que está cerca se oculte si se establece esta variable. Luego debe agregar una función oculta similar OnMouseOut del elemento fijo para que desaparezca cuando retire el mouse. Lo siento, no puedo darte ningún código, o algo más concreto, pero espero que esto te indique la dirección correcta.

+0

Sí idd Acabo de implementar una solución como esa. Es un problema muy común. Tengo mucha curiosidad por saber qué otra solución hay ... ¡Gracias por responder! –

3

Estoy simplemente comprobando si las coordenadas del mouse están fuera del elemento en el mouseout-event.

Funciona pero es un montón de código para una cosa tan simple :(

function mouseOut(e) 
{ 
    var pos = GetMousePositionInElement(e, element); 
    if (pos.x < 0 || pos.x >= element.size.X || pos.y < 0 || pos.y >= element.size.Y) 
    { 
     RealMouseOut(); 
    } 
    else 
    { 
     //Hit a child-element 
    } 
} 

Código cortado para facilitar la lectura, no va a funcionar fuera de la caja.

+0

Hm Pensé en eso también. Se siente un poco sucio ... pero es muy directo. –

7

Usted está buscando el jQuery equivalente de javascript a prevenir el burbujeo de eventos

mira esto:.

http://docs.jquery.com/Events/jQuery.Event#event.stopPropagation.28.29

Básicamente necesita capturar el evento en los nodos DOM hijos, y detener su propagación en el árbol DOM. Otra forma, aunque realmente no se sugiere (ya que puede afectar seriamente los eventos existentes en su página), es establecer la captura de eventos en un elemento específico de la página, y recibirá todos los eventos. Esto es útil para el comportamiento de DnD y tal, pero definitivamente no para su caso.

+0

Siempre supe que esta debería ser la manera más limpia de hacerlo, pero no puedo hacer que funcione. Estudiará los documentos un poco mejor. ¡Gracias! –

+0

esto funciona como debería, no sé por qué no puede hacerlo funcionar ... solo una información, un enlace a documentos ha cambiado, el nuevo enlace es http://docs.jquery.com/Events/jQuery.Event # event.stopPropagation.28.29 – zappan

1

Estoy de acuerdo con Ryan.

Su problema es que el "siguiente" div no es un "hijo" de A. No hay forma de que HTML o jQuery sepan que su elemento "a" está relacionado con el div infantil en el DOM. Envolverlos y poner un vuelo estacionario sobre el envoltorio significa que están asociados.

Sin embargo, tenga en cuenta que su código no está en línea con las mejores prácticas. No establezca el estilo oculto en línea en los elementos; si el usuario tiene CSS pero no javascript, el elemento se ocultará y no se podrá mostrar. Una mejor práctica es colocar esa declaración en el evento document.ready.

+0

Estoy totalmente de acuerdo con poner el hide en el evento document.ready. El CSS en línea fue solo para transmitir un ejemplo completo de trabajo de la manera más simple posible. Editaré mi respuesta para dejar eso en claro. –

0

Es una vieja pregunta, pero nunca se vuelve obsoleto. La respuesta correcta debe ser la dada por bytebrite.

Solo me gustaría señalar la diferencia entre mouseover/mouseout y mouseenter/mouseleave. Puede leer una gran explicación útil here (vaya al final de la página para ver una demostración en funcionamiento). Cuando usa mouseout, el evento se detiene cuando el mouse ingresa otro elemento, incluso si es un elemento secundario. Por otro lado, cuando usa mouseleave, el evento no se desencadena cuando el mouse pasa por encima de un elemento secundario, y este es el comportamiento que el OP desea lograr.

8

Yeap, chicos, utilice .mouseleave en lugar de .mouseout:

$('div.sort-selector').mouseleave(function() { 
    $(this).hide(); 
}); 

O incluso utilizarlo en combinación con live:

$('div.sort-selector').live('mouseleave', function() { 
    $(this).hide(); 
}); 
0

que resuelve este problema mediante la adición de pointer-events: none; en mis elementos secundarios css

Cuestiones relacionadas