Wie deaktiviere ich Mouseout-Ereignisse, die von untergeordneten Elementen ausgelöst werden?

107

Lassen Sie mich das Problem im Detail beschreiben:

Ich möchte ein absolut positioniertes Div anzeigen, wenn ich über einem Element schwebe. Mit jQuery ist das ganz einfach und funktioniert einwandfrei. Wenn die Maus jedoch über eines der untergeordneten Elemente fährt, wird das Mouseout-Ereignis des enthaltenen div ausgelöst. Wie verhindere ich, dass Javascript das Mouseout-Ereignis des enthaltenen Elements auslöst, wenn der Mauszeiger über ein untergeordnetes Element bewegt wird?

Was ist der beste und kürzeste Weg, dies mit jQuery zu tun?

Hier ist ein vereinfachtes Beispiel, um zu veranschaulichen, was ich meine:

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() } );
Schleifer Versluys
quelle
1
Ohne jQuery-Version dieser Frage
Zach Saucier

Antworten:

209

Die Frage ist ein bisschen alt, aber ich bin neulich darauf gestoßen.

Der einfachste Weg, dies mit neueren Versionen von jQuery zu tun, besteht darin, die Ereignisse mouseenterund mouseleaveanstelle von mouseoverund zu verwendenmouseout .

Sie können das Verhalten schnell testen mit:

$(".myClass").on( {
   'mouseenter':function() { console.log("enter"); },
   'mouseleave':function() { console.log("leave"); }
});
Bytebrite
quelle
4
Hat meinem Problem mit Javascript im Zusammenhang mit Nicht-JQuery geholfen. Ich habe mit meinen Event-Listenern mouseenter / mouseout anstelle von mouseleave verwendet!
Jo E.
1
Aus Suchgründen entsprechen diese Mausereignisverhalten AS3 ROLL_OVERund ROLL_OUTin.
Jeff Ward
2
Hat mir Kopfschmerzen erspart. Es ist seltsam, wie das Schweben auf untergeordneten Elementen das mouseoutEreignis des übergeordneten Elements auslöst , obwohl es sich tatsächlich noch im übergeordneten Element befindet.
javiniar.leonard
18

Der Einfachheit halber würde ich das HTML nur ein wenig neu organisieren, um den neu angezeigten Inhalt in das Element einzufügen, an das das Mouseover-Ereignis gebunden ist:

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

Dann könnten Sie so etwas tun:

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

Hinweis: Ich empfehle kein Inline-CSS, aber es wurde durchgeführt, um das Beispiel leichter verdaulich zu machen.

Ryan McGeary
quelle
Dies ist in der Tat eine sehr einfache und saubere Lösung. Danke, dass du mich erinnert hast. Aber in meiner spezifischen Situation, die nicht genau wie in der Frage ist, ist dies keine Option. Trotzdem danke!
Sander Versluys
Nachdem ich verschiedene Methoden ausprobiert hatte, wie sie von anderen hier bei SO beschrieben wurden, kam ich zu Ihrer Methode zurück und ließ sie in meinem Fall funktionieren. Yay! :-)
Sander Versluys
10

Ja, Leute, benutze .mouseleaveanstelle von .mouseout:

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

Oder verwenden Sie es sogar in Kombination mit live:

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

Sie suchen nach dem jQuery-Äquivalent von Javascript, um das Sprudeln von Ereignissen zu verhindern.

Überprüfen Sie dies heraus:

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

Grundsätzlich müssen Sie das Ereignis in den untergeordneten DOM-Knoten abfangen und dort deren Weitergabe im DOM-Baum stoppen. Eine andere Möglichkeit, die zwar nicht empfohlen wird (da sie die vorhandenen Ereignisse auf Ihrer Seite stark beeinträchtigen kann), besteht darin, die Ereigniserfassung auf ein bestimmtes Element auf der Seite festzulegen und alle Ereignisse zu empfangen. Dies ist nützlich für DnD-Verhalten und dergleichen, aber definitiv nicht für Ihren Fall.

Yuval Adam
quelle
Dies funktioniert wie es sollte, ich weiß nicht, warum Sie es nicht zum Laufen
zappan
3

Ich überprüfe einfach, ob die Mauskoordinaten außerhalb des Elements im mouseout-Ereignis liegen.

Es funktioniert, aber es ist eine Menge Code für eine so einfache Sache :(

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

Code aus Gründen der Lesbarkeit gekürzt, funktioniert nicht sofort.


quelle
1

Ich stimme Ryan zu.

Ihr Problem ist, dass das "nächste" Div kein "Kind" von A ist. HTML oder jQuery können nicht erkennen, dass Ihr "a" -Element mit dem untergeordneten Div im DOM zusammenhängt. Wenn Sie sie einwickeln und einen Schwebeflug auf die Hülle legen, sind sie miteinander verbunden.

Bitte beachten Sie, dass sein Code nicht den Best Practices entspricht. Setzen Sie den versteckten Stil nicht inline auf die Elemente. Wenn der Benutzer über CSS, aber kein Javascript verfügt, wird das Element ausgeblendet und kann nicht angezeigt werden. Es ist besser, diese Deklaration in das Ereignis document.ready aufzunehmen.

user37731
quelle
Ich bin völlig damit einverstanden, das Fell in das Ereignis document.ready einzufügen. Das Inline-CSS sollte lediglich auf einfachste Weise ein voll funktionsfähiges Beispiel vermitteln. Ich werde meine Antwort bearbeiten, um das klar zu machen.
Ryan McGeary
1

Ich habe dieses Problem gelöst, indem pointer-events: none;ich CSS zu meinen untergeordneten Elementen hinzugefügt habe

Antoine
quelle
Dies hat sehr geholfen, als einige ältere Codes repariert wurden, die ihre eigenen Popover mit Mouseover- und Mouseleave-Ereignissen erstellten
CM
0

Die Art und Weise, wie ich das normalerweise gesehen habe, ist eine Verzögerung von ungefähr 1/2 Sekunde zwischen dem Bewegen der Maus vom HoverMe-Element. Wenn Sie die Maus in das schwebende Element bewegen, möchten Sie eine Variable festlegen, die signalisiert, dass Sie über dem Element schweben, und dann im Grunde verhindern, dass sich der schwebende Teil versteckt, wenn diese Variable festgelegt ist. Sie müssen dann eine ähnliche Ausblendfunktion OnMouseOut aus dem schwebenden Element hinzufügen, damit es beim Entfernen der Maus verschwindet. Es tut mir leid, dass ich Ihnen keinen Code oder etwas Konkreteres geben kann, aber ich hoffe, dies weist Sie in die richtige Richtung.

Kibbee
quelle
Ja, ich habe gerade eine solche Lösung implementiert. Es ist ein sehr häufiges Problem. Ich bin wirklich gespannt, welche andere Lösung es gibt ... Danke für die Antwort!
Sander Versluys
0

Es ist eine alte Frage, aber sie wird niemals obsolet. Die richtige Antwort sollte die von Bytebrite sein .

Ich möchte nur auf den Unterschied zwischen Mouseover / Mouseout und Mouseenter / Mouseleave hinweisen. Eine großartige und hilfreiche Erklärung finden Sie hier (eine funktionierende Demo finden Sie ganz unten auf der Seite). Bei Verwendung mouseoutstoppt das Ereignis, wenn die Maus ein anderes Element eingibt, auch wenn es sich um ein untergeordnetes Element handelt. Auf der anderen Seite wird mouseleavedas Ereignis bei Verwendung nicht ausgelöst, wenn die Maus über ein untergeordnetes Element fährt. Dies ist das Verhalten, das das OP erreichen möchte.

Erenor Paz
quelle