2010-01-19 8 views
6

Ho un contenitore a discesa simile a un menu che nasconde collegando l'evento "mouseleave".Funky comportamento jQuery mouseleave

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

Il problema che sto avendo è quando gli elementi figlio di mio container contengono un oggetto SELEZIONA dove le opzioni di SELECT fisicamente si estendono al di fuori dei confini del contenitore. Di conseguenza, passando sopra le OPZIONI al di fuori dei limiti, si attiva l'evento "Mouseleave" per sparare e si chiude la discesa. SELECT è figlio del contenitore, quindi in questo caso mi aspetterei che l'evento Mouseleave lo riconosca.

+0

Perché non rendere il contenitore sempre abbastanza grande da contenere i suoi bambini? –

+0

Il numero di opzioni è molto più grande dell'elemento contenitore. Voglio mantenere l'interfaccia utente il più semplice possibile. – Blocka

risposta

4

Un aggiornamento sulla soluzione di blocka quanto non funziona con Firefox correttamente:

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

Forse quando il menu a discesa è espanso, è possibile impostare un flag. Cancella la bandiera quando viene selezionato un oggetto. Quando si verifica un mouseleave, non nascondere il menu a meno che il flag non sia chiaro.

Mi innervosisco sempre per l'hacking degli eventi dell'interfaccia utente, anche se è probabile che finirai per lasciare qualche browser in uno stato totalmente inutilizzabile.

+0

Grazie per la vostra risposta. Idealmente, mi piacerebbe che l'evento mouseleave si attivasse quando lasciavo i tag OPTION senza tornare al SELECT o al DIV contenente. Il trucco è evitare gli eventi di associazione ai tag OPTION. Ci sono un certo numero di piccoli hack che potrei provare ma stavo cercando una soluzione più strutturata. – Blocka

1

La maggior parte dei renderer (tutti tranne Gecko, penso) implementano i menu aperti <select> e le relative opzioni in una "finestra" separata, non come elementi nella pagina. La pagina non è quindi necessariamente a conoscenza dell'interazione dell'utente con un menu aperto <select>. È molto improbabile che tu possa ottenere l'effetto desiderato su tutti i principali browser ...

Modifica: ... ma forse è così. Questo funziona per me in Safari e Firefox. Non riesco a testare in IE in questo momento, ma dare un colpo:

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); 
    } 
}); 

Edit 2: in realtà, Safari non scatta mouseleave (o mouseout) a tutti quando la "finestra" <select> è aperta.

2

Grazie senza occhi! In realtà ho trovato un'altra risposta a questo problema la scorsa notte che è molto simile a quello che hai postato.

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

L'oggetto e.fromElement fornisce il conteggio degli oggetti OPTION in SELECT. Questo oggetto non è definito per altri tag HTML. Non ho provato la tua soluzione, ma funziona anche per me.

4

Una soluzione molto semplice ed efficace a questo è quello di controllare il puntatore del mouse coordinate prima di eseguire l'azione. Se il contenitore sfocato per mettere a fuoco sull'elemento "seleziona", controlla il puntatore. Se il puntatore è all'interno del contenitore, non esegue alcuna azione, se questa è l'azione elemento contenitore viene eseguita

$('#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 e clientY a "position:relative;" pageX e Pagey a "position:absolute;"

Problemi correlati