Détecter IF survolant l'élément avec jQuery

150

Je ne cherche pas une action à appeler lors du survol, mais plutôt un moyen de savoir si un élément est actuellement survolé. Par exemple:

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

Existe-t-il une méthode jQuery qui accomplit cela?

James Skidmore
la source
Juste au cas où quelqu'un chercherait d'autres solutions stackoverflow.com/questions/1273566/…
Jo E.
1
Le marquage comme duplicata semble assez faux. La question ne dit pas quelle est l'intention, pour quelqu'un d'autre de lire dans l'esprit du PO et de décider qu'il s'agit d'une question de détection de collision et de marquer comme doublon.
Meligy

Réponses:

306

Réponse originale (et correcte):

Vous pouvez utiliser is()et vérifier le sélecteur :hover.

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

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

(Cela ne fonctionne que lorsque le sélecteur correspond à UN élément au maximum. Voir Édition 3 pour plus)

.

Edit 1 (29 juin 2013): (Applicable à jQuery 1.9.x uniquement, car il fonctionne avec 1.10+, voir Next Edit 2)

Cette réponse était la meilleure solution au moment où la question a été répondue. Ce sélecteur ': hover' a été supprimé avec la .hover()suppression de la méthode dans jQuery 1.9.x.

Fait intéressant, une réponse récente de "allicarn" montre qu'il est possible de l'utiliser :hovercomme sélecteur CSS (vs Sizzle) lorsque vous le préfixez avec un sélecteur $($(this).selector + ":hover").length > 0, et cela semble fonctionner!

De plus, le plugin hoverIntent mentionné dans une autre réponse est également très agréable.

Edit 2 (21 septembre 2013): .is(":hover") oeuvres

Sur la base d'un autre commentaire, j'ai remarqué que la manière originale de publier, .is(":hover")fonctionne toujours dans jQuery, donc.

  1. Cela fonctionnait dans jQuery 1.7.x.

  2. Cela a cessé de fonctionner dans la version 1.9.1, quand quelqu'un me l'a signalé, et nous avons tous pensé que c'était lié à la suppression de l' hoveralias par jQuery pour la gestion des événements dans cette version.

  3. Cela a fonctionné à nouveau dans jQuery 1.10.1 et 2.0.2 (peut-être 2.0.x), ce qui suggère que l'échec de la 1.9.x était un bogue ou donc pas un comportement intentionnel comme nous le pensions au point précédent.

Si vous souhaitez tester cela dans une version de jQuery particulière, ouvrez simplement l'exemple JSFidlle au début de cette réponse, passez à la version de jQuery souhaitée et cliquez sur "Exécuter". Si la couleur change au survol, cela fonctionne.

.

Edit 3 (9 mars 2014): cela ne fonctionne que lorsque la séquence jQuery contient un seul élément

Comme le montre @Wilmer dans les commentaires, il a un violon qui ne fonctionne même pas avec les versions de jQuery que j'ai testées et d'autres ici. Quand j'ai essayé de trouver ce qui était spécial dans son cas, j'ai remarqué qu'il essayait de vérifier plusieurs éléments à la fois. C'était jeté Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: hover.

Donc, en travaillant avec son violon, cela ne fonctionne PAS :

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

Bien que ce DOES travail:

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

Il fonctionne également avec les séquences jQuery qui contiennent un seul élément, comme si le sélecteur d'origine ne correspondait qu'à un seul élément, ou si vous avez appelé .first()les résultats, etc.

Ceci est également référencé dans ma newsletter JavaScript + Web Dev Tips & Resources .

Meligy
la source
1
Fonctionne très bien, simple. Merci Mohamed!
James Skidmore
18
Génère une erreur dans IE 8: Syntax Error, unrecognized expression: hover. jquery-1.7.js line 4179.
RobG
C'est vrai. Je viens de le tester. Pour IE6, essayez ce hack décrit ici peterned.home.xs4all.nl/csshover.html ou revenez au survol normal, ajoutez un état et effacez-le plus tard, sorte de solution.
Meligy
1
@Meligy: J'ai bifurqué votre violon pour illustrer qu'il ne fonctionne pas avec plusieurs éléments de la sélection: jsfiddle.net/p34n8
SuperNova
1
Aussi, si vous utilisez jQuery mobile, cela le fout aussi bien - vérifiez la réponse du violon dans gideons et activez la boîte jQuery Mobile 1.4.4 et vous pouvez voir que cela ne fonctionne pas alors ... Je peux confirmer que c'est la même chose avec 1.4.2 aswell :(
David O'Sullivan
32

Utilisation:

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

jQuery 1.9+

user2444818
la source
1
Cela fonctionne très bien. Meilleure solution trouvée lors de la recherche d'un remplacement pour la fonction .hover et: hover selector. Je vous remercie!
Tyler le
1
Fonctionne comme un charme! :)
jroi_web
9

Cela ne fonctionne pas dans jQuery 1.9. Fait ce plugin basé sur la réponse de user2444818.

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

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

allicarn
la source
5

Définissez un drapeau au survol:

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

Ensuite, vérifiez simplement votre drapeau.

kinakuta
la source
Simple, mais pas facilement réutilisable. : /
Trevor
Cela ne semble pas fonctionner dans ma situation particulière, mais je suis d'accord que c'est une bonne façon de procéder autrement. Dans mon cas, lorsque j'ai mouseleaveun élément, je veux vérifier si la souris est entrée dans un autre élément particulier.
James Skidmore
@JamesSkidmore - dans l'événement mouseleave, vous pouvez utiliser e.fromElementet e.toElement. Cela fonctionnera-t-il pour vous?
mrtsherman
Vous pouvez le mettre à jour pour utiliser un sélecteur qui couvre tous les éléments applicables et stocker l'indicateur sur les éléments individuels à l'aide de .data().
nnnnnn
@Trevor - true - vous auriez besoin de stocker l'état sur l'élément puis de créer une fonction qui vérifie (vraisemblablement l'état de la balise de données) de l'élément.
kinakuta
4

Quelques mises à jour à ajouter après avoir travaillé un certain temps sur ce sujet:

  1. toutes les solutions avec .is (": hover") break sur jQuery 1.9.1
  2. La raison la plus probable pour vérifier si la souris est toujours au-dessus d'un élément est d'essayer d'empêcher les événements de se déclencher les uns sur les autres. Par exemple, nous avions des problèmes avec notre mouseleave qui était déclenché et terminé avant même que notre événement mouseenter ne soit terminé. Bien sûr, c'était à cause d'un mouvement rapide de la souris.

Nous avons utilisé hoverIntent https://github.com/briancherne/jquery-hoverIntent pour résoudre le problème pour nous. Essentiellement, il se déclenche si le mouvement de la souris est plus délibéré. (une chose à noter est qu'il se déclenchera à la fois à l'entrée et à la sortie d'un élément par la souris - si vous ne voulez utiliser qu'une seule passe le constructeur une fonction vide)

Donald A Nummer Jr
la source
4

Vous pouvez filtrer votre élément de tous les éléments survolés. Code problématique:

element.filter(':hover')

Enregistrer le code:

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

Pour renvoyer booléen:

jQuery(':hover').filter(element).length===0
Mino
la source
4

La réponse acceptée n'a pas fonctionné pour moi sur JQuery 2.x .is(":hover")renvoie false à chaque appel.

Je me suis retrouvé avec une solution assez simple qui fonctionne:

function isHovered(selector) {

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

}
gidim
la source
3

Développant la réponse de @ Mohamed. Vous pourriez utiliser un peu d' encapsulation

Comme ça:

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

Utilisez-le comme:

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

A fourché le violon: http://jsfiddle.net/cgWdF/1/

Gédéon
la source
6
pour cela, vous pourriez aussi bien faire: jQuery.fn.mouseIsOver = function () {return $ (this [0]). is (': hover')}; moins de code
Lathan
32
combien il est difficile de faire simplement $ ('# elem'). is (': hover')
luckykrrish
pas une question de dur mais plus l'intention est clairement exprimée. Mais à chacun c'est propre.
gideon
1

J'aime la première réponse, mais pour moi c'est bizarre. Lorsque je tente de vérifier juste après le chargement de la page pour la souris, je dois mettre au moins un délai de 500 millisecondes pour que cela fonctionne:

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

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

molokoloco
la source
0

Définir un indicateur par réponse de kinakuta semble raisonnable, vous pouvez mettre un auditeur sur le corps afin de pouvoir vérifier si un élément est survolé à un instant particulier.

Cependant, comment voulez-vous traiter les nœuds enfants? Vous devriez peut-être vérifier si l'élément est un ancêtre de l'élément actuellement survolé.

<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
la source