Rileva IF passando con il mouse sopra l'elemento con jQuery


150

Non sto cercando un'azione da chiamare durante il passaggio del mouse, ma invece un modo per stabilire se un elemento è attualmente sospeso. Per esempio:

$('#elem').mouseIsOver(); // returns true or false

Esiste un metodo jQuery per ottenere questo risultato?


Nel caso in cui qualcuno stia cercando altre soluzioni stackoverflow.com/questions/1273566/…
Jo E.

1
La marcatura come duplicato sembra del tutto errata. La domanda non dice quale sia l'intento, per qualcun altro di leggere la mente del PO e decidere che si tratta di una domanda di rilevamento delle collisioni e contrassegnarla come duplicata.
Meligy,

Risposte:


306

Risposta originale (e corretta):

È possibile utilizzare is()e verificare il selettore :hover.

var isHovered = $('#elem').is(":hover"); // returns true or false

Esempio: http://jsfiddle.net/Meligy/2kyaJ/3/

(Funziona solo quando il selettore corrisponde a UN elemento max. Vedi Modifica 3 per ulteriori informazioni)

.

Modifica 1 (29 giugno 2013): (Applicabile solo a jQuery 1.9.x, poiché funziona con 1.10+, vedere la successiva Modifica 2)

Questa risposta era la soluzione migliore al momento della risposta alla domanda. Questo selettore ': hover' è stato rimosso con la .hover()rimozione del metodo in jQuery 1.9.x.

È interessante notare che una recente risposta di "allicarn" mostra che è possibile utilizzare :hovercome selettore CSS (vs. Sizzle) quando lo si antepone con un selettore $($(this).selector + ":hover").length > 0e sembra funzionare!

Inoltre, il plug-in hoverIntent menzionato in un'altra risposta sembra anche molto bello.

Modifica 2 (21 settembre 2013): .is(":hover") funziona

Sulla base di un altro commento ho notato che il modo originale in cui ho postato .is(":hover"), in realtà funziona ancora in jQuery, quindi.

  1. Ha funzionato in jQuery 1.7.x.

  2. Ha smesso di funzionare in 1.9.1, quando qualcuno me l'ha segnalato e tutti pensavamo fosse correlato a jQuery che rimuoveva l' hoveralias per la gestione degli eventi in quella versione.

  3. Ha funzionato di nuovo in jQuery 1.10.1 e 2.0.2 (forse 2.0.x), il che suggerisce che il fallimento in 1.9.x era un bug o un comportamento non intenzionale come pensavamo nel punto precedente.

Se vuoi testarlo in una particolare versione di jQuery, apri l'esempio JSFidlle all'inizio di questa risposta, passa alla versione jQuery desiderata e fai clic su "Esegui". Se il colore cambia al passaggio del mouse, funziona.

.

Modifica 3 (9 marzo 2014): funziona solo quando la sequenza jQuery contiene un singolo elemento

Come mostrato da @Wilmer nei commenti, ha un violino che non funziona nemmeno contro le versioni jQuery che io e altri qui abbiamo testato. Quando ho cercato di scoprire le particolarità del suo caso, ho notato che stava cercando di controllare più elementi alla volta. Questo stava lanciando Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: hover.

Quindi, lavorando con il suo violino, questo NON funziona:

var isHovered = !!$('#up, #down').filter(":hover").length;

Anche se questo DOES lavoro:

var isHovered = !!$('#up,#down').
                    filter(function() { return $(this).is(":hover"); }).length;

Funziona anche con sequenze jQuery che contengono un singolo elemento, come se il selettore originale corrispondesse a un solo elemento o se hai chiamato .first()i risultati, ecc.

Questo è anche indicato nella mia newsletter JavaScript + Web Dev Tips & Resources .


1
Funziona alla grande, semplice. Grazie Mohamed!
James Skidmore,

18
Genera un errore in IE 8: Syntax Error, unrecognized expression: hover. jquery-1.7.js line 4179.
RobG

È vero. L'ho appena provato. Per IE6, prova questo hack descritto qui peterned.home.xs4all.nl/csshover.html o torna al passaggio del mouse normale aggiungi un po 'di stato e cancellalo in un secondo momento tipo di soluzione.
Meligy,

1
@Meligy: ho biforcuto il tuo violino per illustrare che non funziona con più elementi nella selezione: jsfiddle.net/p34n8
SuperNova

1
Anche se stai usando jQuery mobile, anche questo lo rovina - controlla la risposta del violino in gideons e attiva la casella jQuery Mobile 1.4.4 e puoi vedere che non funziona quindi ... Posso confermare che è lo stesso con 1.4.2 pure :(
David O'Sullivan il

32

Uso:

var hovered = $("#parent").find("#element:hover").length;

jQuery 1.9+


1
Funziona perfettamente. La migliore soluzione trovata durante la ricerca di un sostituto per la funzione .hover e: selettore hover. Grazie!
Tyler,

1
Funziona come un fascino! :)
jroi_web

9

Non funziona in jQuery 1.9. Realizzato questo plugin in base alla risposta di user2444818.

jQuery.fn.mouseIsOver = function () {
    return $(this).parent().find($(this).selector + ":hover").length > 0;
}; 

http://jsfiddle.net/Wp2v4/1/


5

Imposta una bandiera al passaggio del mouse:

var over = false;
$('#elem').hover(function() {
  over = true;
},
function () {
  over = false;
});

Quindi controlla la tua bandiera.


Semplice, ma non facilmente riutilizzabile. : /
Trevor

Non sembra funzionare nella mia situazione particolare, ma sono d'accordo che sia un buon modo per andare diversamente. Nel mio caso, quando ho mouseleaveun elemento, voglio verificare se il mouse è entrato in un altro elemento particolare.
James Skidmore,

@JamesSkidmore - nell'evento mouseleave è possibile utilizzare e.fromElemente e.toElement. Funzionerà per te?
sig.

È possibile aggiornare questo per utilizzare un selettore che copre tutti gli elementi applicabili e memorizzare il flag sui singoli elementi utilizzando .data().
nnnnnn,

@Trevor - true - dovresti archiviare lo stato sull'elemento, quindi creare una funzione che controlli (presumibilmente il tag di dati) dello stato dell'elemento.
Kinakuta,

4

Coppia gli aggiornamenti da aggiungere dopo aver lavorato su questo argomento per un po ':

  1. tutte le soluzioni con .is (": hover") si interrompono su jQuery 1.9.1
  2. Il motivo più probabile per verificare se il mouse si trova ancora sopra un elemento è tentare di evitare che gli eventi si attivino l'un l'altro. Ad esempio, stavamo riscontrando problemi con l'attivazione e il completamento della nostra mouseleave prima ancora che il nostro evento mouseenter fosse completato. Ovviamente questo è dovuto a un rapido movimento del mouse.

Abbiamo usato hoverIntent https://github.com/briancherne/jquery-hoverIntent per risolvere il problema per noi. Fondamentalmente si innesca se il movimento del mouse è più deliberato. (una cosa da notare è che si innescherà sia con il mouse che entra in un elemento che se ne va - se vuoi usare solo un passaggio, la funzione di costruzione è vuota)


4

Puoi filtrare il tuo elemento da tutti gli elementi in bilico. Codice problematico:

element.filter(':hover')

Salva codice:

jQuery(':hover').filter(element)

Per restituire il valore booleano:

jQuery(':hover').filter(element).length===0

4

La risposta accettata non ha funzionato per me su JQuery 2.x .is(":hover")restituisce false su ogni chiamata.

Ho finito con una soluzione piuttosto semplice che funziona:

function isHovered(selector) {

    return $(selector+":hover").length > 0

}

3

Espandendo la risposta di @ Mohamed. Potresti usare un po 'di incapsulamento

Come questo:

jQuery.fn.mouseIsOver = function () {
    if($(this[0]).is(":hover"))
    {
        return true;
    }
    return false;
}; 

Usalo come:

$("#elem").mouseIsOver();//returns true or false

Forked the fiddle: http://jsfiddle.net/cgWdF/1/


6
per farlo, potresti anche fare: jQuery.fn.mouseIsOver = function () {return $ (this [0]). is (': hover')}; meno codice
Lathan,

32
quanto è difficile fare semplicemente $ ('# elem'). is (': hover')
luckykrrish

non è una questione difficile ma più l'intento è chiaramente espresso. Ma per ognuno è proprio.
Gideon,

1

Mi piace la prima risposta, ma per me è strano. Quando tento di controllare subito dopo il caricamento della pagina per il mouse, devo inserire un ritardo di almeno 500 millisecondi affinché funzioni:

$(window).on('load', function() {
    setTimeout(function() {
        $('img:hover').fadeOut().fadeIn();
    }, 500);
});

http://codepen.io/molokoloco/pen/Grvkx/


0

L'impostazione di un flag per la risposta di kinakuta sembra ragionevole, puoi mettere un ascoltatore sul corpo in modo da poter verificare se un elemento viene sospeso su un determinato istante.

Tuttavia, come si desidera gestire i nodi figlio? Dovresti forse verificare se l'elemento è un antenato dell'elemento attualmente in bilico.

<script>

var isOver = (function() {
  var overElement;
  return {

    // Set the "over" element
    set: function(e) {
      overElement = e.target || e.srcElement;
    },

    // Return the current "over" element
    get: function() {
      return overElement;    
    },

    // Check if element is the current "over" element
    check: function(element) {
      return element == overElement;
    },

    // Check if element is, or an ancestor of, the 
    // current "over" element
    checkAll: function(element) {
      while (overElement.parentNode) {
         if (element == overElement) return true;
         overElement = overElement.parentNode;
      }
      return false;
    }
  };
}());


// Check every second if p0 is being hovered over
window.setInterval( function() {
  var el = document.getElementById('p0');
  document.getElementById('msg').innerHTML = isOver.checkAll(el);
}, 1000);


</script>

<body onmouseover="isOver.set(event);">
  <div>Here is a div
    <p id="p0">Here is a p in the div<span> here is a span in the p</span> foo bar </p>
  </div>
  <div id="msg"></div>
</body>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.