web-dev-qa-db-fra.com

Comment désactiver les événements mouseout déclenchés par des éléments enfants?

Permettez-moi de décrire le problème en détail:

Je veux montrer un div positionné absolu lorsque je survole un élément. C'est vraiment simple avec jQuery et fonctionne très bien. Mais lorsque la souris passe sur l'un des éléments enfants, elle déclenche l'événement mouseout du div contenant. Comment empêcher javascript de déclencher l'événement mouseout de l'élément conteneur lors du survol d'un élément enfant.

Quelle est la meilleure et la plus courte façon de le faire avec jQuery?

Voici un exemple simplifié pour illustrer ce que je veux dire:

Html:

<a>Hover Me</a>
<div>
  <input>Test</input>
  <select>
    <option>Option 1</option>
    <option>Option 2</option>
  </select>
</div>

Javascript/jQuery:

$('a').hover( function() { $(this).next().show() }
              function() { $(this).next().hide() } );
102
Sander Versluys

La question est un peu ancienne, mais je l'ai rencontrée l'autre jour.

La façon la plus simple de le faire avec les versions récentes de jQuery est d'utiliser les événements mouseenter et mouseleave plutôt que mouseover et mouseout.

Vous pouvez tester le comportement rapidement avec:

$(".myClass").on( {
   'mouseenter':function() { console.log("enter"); },
   'mouseleave':function() { console.log("leave"); }
});
204
bytebrite

Par souci de simplicité, je voudrais juste réorganiser un peu le code html pour mettre le contenu nouvellement affiché à l'intérieur de l'élément auquel l'événement mouseover est lié:

<div id="hoverable">
  <a>Hover Me</a>
  <div style="display:none;">
    <input>Test</input>
    <select>
      <option>Option 1</option>
      <option>Option 2</option>
    </select>
  </div>
</div>

Ensuite, vous pouvez faire quelque chose comme ceci:

$('#hoverable').hover( function() { $(this).find("div").show(); },
                       function() { $(this).find("div").hide(); } );

Remarque: je ne recommande pas le CSS en ligne, mais cela a été fait pour rendre l'exemple plus facile à digérer.

18
Ryan McGeary

Oui, les gars, utilisez .mouseleave au lieu de .mouseout:

$('div.sort-selector').mouseleave(function() {
    $(this).hide();
});

Ou même l'utiliser en combinaison avec live:

$('div.sort-selector').live('mouseleave', function() {
    $(this).hide();
});
9
Lord Nighton

Vous recherchez l'équivalent jQuery du javascript empêche la propagation des événements.

Regarde ça:

http://docs.jquery.com/Events/jQuery.Event#event.stopPropagation.28.29

Fondamentalement, vous devez intercepter l'événement dans les nœuds DOM enfants et arrêter leur propagation dans l'arborescence DOM. Une autre façon, bien que ce ne soit vraiment pas suggéré (car cela peut gravement perturber les événements existants sur votre page), est de définir la capture d'événements sur un élément spécifique de la page, et il recevra tous les événements. Ceci est utile pour le comportement DnD et autres, mais certainement pas pour votre cas.

8
Yuval Adam

Je vérifie simplement si les coordonnées de la souris se trouvent en dehors de l'élément dans l'événement mouseout.

Cela fonctionne, mais il y a beaucoup de code pour une chose aussi simple :(

function mouseOut(e)
{
    var pos = GetMousePositionInElement(e, element);
    if (pos.x < 0 || pos.x >= element.size.X || pos.y < 0 || pos.y >= element.size.Y)
    {
        RealMouseOut();
    }
    else
    {
         //Hit a child-element
    }
}

Le code réduit pour la lisibilité, ne fonctionnera pas hors de la boîte.

3
balooo

J'ai résolu ce problème en ajoutant pointer-events: none; sur mes éléments enfants css

1
Antoine

Je suis d'accord avec Ryan.

Votre problème est que le "prochain" div n'est pas un "enfant" de A. Il n'y a aucun moyen pour HTML ou jQuery de savoir que votre élément "a" est lié au div enfant dans le DOM. Les envelopper et placer un survol sur l'emballage signifie qu'ils sont associés.

Veuillez noter que son code n'est pas conforme aux meilleures pratiques. Ne définissez pas le style caché en ligne sur les éléments; si l'utilisateur a du CSS mais pas du javascript, l'élément se cachera et ne pourra pas être affiché. Il est préférable de placer cette déclaration dans l'événement document.ready.

1
user37731

La façon dont j'ai généralement vu cela géré est d'avoir un délai d'environ 1/2 seconde entre le déplacement de la souris de l'élément HoverMe. Lorsque vous déplacez la souris dans l'élément survolé, vous souhaitez définir une variable qui signale que vous survolez l'élément, puis empêcher la partie survolée de se cacher si cette variable est définie. Vous devez ensuite ajouter une fonction de masquage similaire OnMouseOut à partir de l'élément survolé pour le faire disparaître lorsque vous retirez la souris. Désolé, je ne peux pas vous donner de code, ou quelque chose de plus concret, mais j'espère que cela vous indique la bonne direction.

0
Kibbee

C'est une vieille question, mais elle n'est jamais obsolète. La bonne réponse doit être celle donnée par bytebrite .

Je voudrais seulement souligner la différence entre mouseover/mouseout et mouseenter/mouseleave. Vous pouvez lire une grande et utile explication ici (allez tout en bas de la page pour une démonstration de travail). Lorsque vous utilisez mouseout, l'événement s'arrête lorsque la souris entre dans un autre élément, même s'il s'agit d'un élément enfant. D'un autre côté, lorsque vous utilisez mouseleave, l'événement n'est pas déclenché lorsque la souris survole un élément enfant, et c'est le comportement que l'OP souhaite obtenir.

0
Erenor Paz