2010-01-19 11 views
6

Tengo un menú desplegable similar a un menú que se oculta vinculando el evento "mouseleave".Funky jQuery mouseleave comportamiento

<div id="container"> 
<select> 
    <option>1</option> 
    <option>2</option> 
    <option>3</option> 
    <option>4</option> 
    <option>5</option> 
</select> 
</div> 

El problema que estoy teniendo es cuando los elementos secundarios de mi contenedores contienen un objeto SELECT donde las opciones de la instrucción SELECT se extienden físicamente fuera de los límites del contenedor. En consecuencia, al pasar las OPCIONES fuera de los límites, se activa el evento "mouseleave" para disparar y se cierra mi menú desplegable. El SELECT es un elemento secundario del contenedor, por lo que en este caso esperaría que el evento mouseleave lo reconozca.

+0

¿Por qué no hacer que el contenedor siempre sea lo suficientemente grande como para contener a sus hijos? –

+0

El número de opciones es mucho mayor que el elemento contenedor. Quiero mantener la interfaz de usuario lo más simple posible. – Blocka

Respuesta

4

una actualización de la solución de Blocka ya que no funciona correctamente con Firefox:

if ((typeof e.fromElement != 'undefined' && !e.fromElement.length) || 
    (typeof e.fromElement == 'undefined' && e.target.tagName != 'SELECT')) { 
    // perform your mouseleave logic 
} 
1

Tal vez cuando se expande el menú desplegable, puede establecer un indicador. Borre la bandera cuando se selecciona un elemento. Cuando se produce un cambio de mouse, no oculte el menú a menos que el indicador sea claro.

Siempre me pongo nervioso por hackear eventos de UI a este grado, ya que es probable que termines dejando un navegador en algún lugar totalmente inutilizable.

+0

Gracias por su respuesta. Idealmente, me gustaría que el evento mouseleave se active cuando dejo las etiquetas OPTION sin volver al SELECT ni al DIV que lo contiene. El truco es evitar eventos vinculantes a las etiquetas OPTION también. Hay una serie de pequeños hacks que podría probar, pero estaba buscando una solución estructurada más. – Blocka

1

La mayoría de los procesadores (todos excepto Gecko, creo) implementan los menús abiertos <select> y sus opciones en una "ventana" separada, no como elementos en la página. La página, entonces, no es necesariamente consciente de la interacción del usuario con un menú abierto <select>. Es muy poco probable que pueda lograr el efecto deseado en todos los principales navegadores ...

Editar: ... pero tal vez sea así. Esto funciona para mí en Safari y Firefox. No puedo probar en IE en este momento, pero le dan un tiro:

var timer; 
$('#container').mouseleave(function(e) { 
    if($(e.target).parents('#container').length) { 
     return; 
    } 
    timer = setTimeout(function() { 
     $('#container select').blur(); 
    }, 50); 
}).mouseenter(function(e) { 
    if(timer) { 
     clearTimeout(timer); 
    } 
}); 

Edición 2: de hecho, Safari no se dispara mouseleave (o mouseout) en todo cuando la "ventana" <select> está abierto.

2

Gracias eyelidlessness! De hecho, encontré otra respuesta a este problema anoche que es muy similar a lo que publicaste.

.bind("mouseleave", function(e) { // ANSWER HERE!!! 
    if (!e.fromElement.length) { 
     _state.filterTrigger.data("open", false); 
     setTimeout(function() { _toggleFilter(_state.filterTrigger); }, 2000); 
    } 
}); 

El objeto e.fromElement proporciona el recuento de objetos OPTION en SELECT. Este objeto no está definido para otras etiquetas HTML. No he probado tu solución, pero esto también funciona para mí.

4

Una solución muy sencilla y eficaz para esto es para controlar el puntero del ratón coordenadas antes de realizar la acción. Si el contenedor está fuera de foco para enfocarse en el elemento "seleccionar", verifica el puntero. Si el puntero se encuentra en el interior del contenedor, ya que no realiza ninguna acción, sin embargo, si esta es la acción elemento contenedor se realiza

$('#div_solapa_lateral').bind("mouseenter",function(){ 
      $(this).animate({left:'0'},500); 
     }); 

    $('#div_solapa_lateral').bind("mouseleave",function(e){ 
      if (e.clientX>360 || e.clientY<60 || e.pageY>625) 
      $(this).animate({left:'-320'},500); 
     }); 

clientX y clientY a "position:relative;" pageX y pageY a "position:absolute;"

Cuestiones relacionadas