Wykryj, czy najechanie kursorem na element za pomocą jQuery

150

Nie szukam akcji do wywołania po najechaniu kursorem, ale zamiast tego sposób na sprawdzenie , czy element jest aktualnie najechany . Na przykład:

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

Czy istnieje metoda jQuery, która to umożliwia?

James Skidmore
źródło
Na wszelki wypadek, gdyby ktoś szukał innych rozwiązań stackoverflow.com/questions/1273566/…
Jo E.
1
Oznaczanie jako duplikat wygląda dość źle. Pytanie nie mówi, jaki jest zamiar, aby ktoś inny przeczytał w myślach PO i zdecydował, że jest to pytanie do wykrywania kolizji i oznaczy jako duplikat.
Meligy

Odpowiedzi:

306

Oryginalna (i poprawna) odpowiedź:

Możesz użyć is()i sprawdzić selektor :hover.

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

Przykład: http://jsfiddle.net/Meligy/2kyaJ/3/

(Działa to tylko wtedy, gdy selektor pasuje do maksymalnie JEDNEGO elementu. Zobacz Edycja 3 po więcej)

.

Edycja 1 (29 czerwca 2013 r.): (Dotyczy tylko jQuery 1.9.x, ponieważ działa z wersją 1.10+, zobacz następną edycję 2)

Ta odpowiedź była najlepszym rozwiązaniem w momencie udzielenia odpowiedzi na pytanie. Ten selektor „: hover” został usunięty wraz z .hover()usunięciem metody w jQuery 1.9.x.

Co ciekawe, niedawna odpowiedź udzielona przez „allicarn” pokazuje, że można go użyć :hoverjako selektora CSS (w przeciwieństwie do Sizzle), gdy przedrostkuje się go selektorem $($(this).selector + ":hover").length > 0i wydaje się, że działa!

Ponadto wtyczka hoverIntent wspomniana w innej odpowiedzi również wygląda bardzo ładnie.

Edycja 2 (21 września 2013): .is(":hover") działa

Na podstawie innego komentarza zauważyłem, że oryginalny sposób, w jaki publikowałem, .is(":hover")nadal działa w jQuery, więc.

  1. Działało w jQuery 1.7.x.

  2. Przestał działać w 1.9.1, kiedy ktoś mi to zgłosił i wszyscy myśleliśmy, że jest to związane z usunięciem hoveraliasu do obsługi zdarzeń w tej wersji przez jQuery .

  3. Zadziałało ponownie w jQuery 1.10.1 i 2.0.2 (być może 2.0.x), co sugeruje, że awaria w 1.9.x była błędem lub nie było celowym zachowaniem, jak myśleliśmy w poprzednim punkcie.

Jeśli chcesz to przetestować w konkretnej wersji jQuery, po prostu otwórz przykład JSFidlle na początku tej odpowiedzi, zmień na żądaną wersję jQuery i kliknij „Uruchom”. Jeśli kolor zmienia się po najechaniu kursorem, to działa.

.

Edycja 3 (9 marca 2014 r.): Działa tylko wtedy, gdy sekwencja jQuery zawiera pojedynczy element

Jak pokazuje @Wilmer w komentarzach, ma skrzypce, które nawet nie działają przeciwko wersjom jQuery, które ja i inni tutaj testowaliśmy. Kiedy próbowałem dowiedzieć się, co jest wyjątkowego w jego przypadku, zauważyłem, że próbuje sprawdzić wiele elementów naraz. To było rzucanie Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: hover.

Więc pracując ze skrzypcami, to NIE działa:

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

Chociaż robi pracy:

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

Działa również z sekwencjami jQuery, które zawierają pojedynczy element, na przykład jeśli oryginalny selektor pasował tylko do jednego elementu lub jeśli wywołałeś .first()wyniki itp.

Jest to również wspomniane w moim biuletynie JavaScript + Web Dev Tips & Resources .

Meligy
źródło
1
Działa świetnie, prosto. Dzięki, Mohamed!
James Skidmore
18
Zgłasza błąd w IE 8: Syntax Error, unrecognized expression: hover. jquery-1.7.js line 4179.
RobG
To prawda. Właśnie to przetestowałem. W przypadku IE6 wypróbuj ten hack opisany tutaj peterned.home.xs4all.nl/csshover.html lub powróć do normalnego najechania, dodaj jakiś stan i wyczyść to później rodzaj rozwiązania.
Meligy
1
@Meligy: Rozwidliłem twoje skrzypce, aby zilustrować, że nie działa z wieloma przedmiotami w zaznaczeniu: jsfiddle.net/p34n8
SuperNova
1
Również, jeśli używasz jQuery mobile, to również go schrzanił - sprawdź odpowiedź na skrzypce w gideonach i włącz pudełko jQuery Mobile 1.4.4 i widzisz, że nie działa ... Mogę potwierdzić to samo z 1.4.2 aswell :(
David O'Sullivan,
32

Posługiwać się:

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

jQuery 1.9+

user2444818
źródło
1
Działa to znakomicie. Najlepsze rozwiązanie znalezione podczas przeglądania w poszukiwaniu zamiennika funkcji .hover i: selektora hover. Dziękuję Ci!
Tyler
1
Działa jak marzenie! :)
jroi_web
9

Nie działa w jQuery 1.9. Utworzono tę wtyczkę na podstawie odpowiedzi użytkownika2444818.

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

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

allicarn
źródło
5

Ustaw flagę po najechaniu:

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

Następnie po prostu sprawdź swoją flagę.

kinakuta
źródło
Proste, ale niełatwe do ponownego użycia. : /
Trevor
Wydawało się, że nie działa w mojej konkretnej sytuacji, ale zgadzam się, że jest to dobry sposób na inne rozwiązanie. W moim przypadku, gdy mam mouseleavejeden element, chcę sprawdzić, czy myszka weszła w inny konkretny element.
James Skidmore
@JamesSkidmore - w wydarzeniu mouseleave możesz używać e.fromElementi e.toElement. Czy to zadziała dla Ciebie?
mrtsherman
Możesz zaktualizować to, aby użyć selektora, który obejmuje wszystkie odpowiednie elementy i zapisać flagę na poszczególnych elementach za pomocą .data().
nnnnnn
@Trevor - prawda - musiałbyś zapisać stan elementu, a następnie utworzyć funkcję, która sprawdza stan elementu (prawdopodobnie znacznik danych).
kinakuta
4

Kilka aktualizacji do dodania po dłuższej pracy nad tym tematem:

  1. wszystkie rozwiązania z .is (": hover") psują się w jQuery 1.9.1
  2. Najbardziej prawdopodobnym powodem sprawdzenia, czy wskaźnik myszy nadal znajduje się nad elementem, jest próba zapobieżenia wystrzeliwaniu zdarzeń. Na przykład mieliśmy problemy z wyzwalaniem i kończeniem działania mouseleave przed zakończeniem zdarzenia mouseenter. Oczywiście było to spowodowane szybkim ruchem myszy.

Użyliśmy hoverIntent https://github.com/briancherne/jquery-hoverIntent, aby rozwiązać ten problem za nas. Zasadniczo uruchamia się, jeśli ruch myszy jest bardziej zamierzony. (należy zauważyć, że wywoła to zarówno wejście myszy, jak i wyjście - jeśli chcesz użyć tylko jednego przebiegu, konstruktor jest pustą funkcją)

Donald A Nummer Jr
źródło
4

Możesz odfiltrować swój element ze wszystkich elementów znajdujących się na kursie. Problematyczny kod:

element.filter(':hover')

Zapisz kod:

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

Aby zwrócić wartość logiczną:

jQuery(':hover').filter(element).length===0
Mino
źródło
4

Zaakceptowana odpowiedź nie działa dla mnie w JQuery 2.x .is(":hover")zwraca false przy każdym połączeniu.

Skończyło się na całkiem prostym rozwiązaniu, które działa:

function isHovered(selector) {

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

}
gidim
źródło
3

Rozwinięcie odpowiedzi @ Mohameda. Możesz użyć trochę hermetyzacji

Lubię to:

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

Używaj go jak:

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

Rozwidlone skrzypce: http://jsfiddle.net/cgWdF/1/

gideon
źródło
6
aby to zrobić, równie dobrze możesz zrobić: jQuery.fn.mouseIsOver = function () {return $ (this [0]). is (': hover')}; mniej kodu
Lathan
32
jak trudno jest po prostu zrobić $ ('# elem'). is (': hover')
luckykrrish
nie jest to sprawa trudna, ale bardziej intencja jest jasno wyrażona. Ale dla każdego jest to własne.
gideon
1

Podoba mi się pierwsza odpowiedź, ale dla mnie to dziwne. Próbując sprawdzić mysz zaraz po załadowaniu strony, muszę ustawić co najmniej 500 milisekund opóźnienia, aby zadziałała:

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

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

molokoloco
źródło
0

Ustawienie flagi dla odpowiedzi kinakuta wydaje się rozsądne, możesz umieścić słuchacza na ciele, abyś mógł sprawdzić, czy w danym momencie jakiś element jest najechany kursorem.

Jak jednak chcesz radzić sobie z węzłami podrzędnymi? Być może powinieneś sprawdzić, czy element jest przodkiem aktualnie zaznaczonego elementu.

<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>
RobG
źródło