2017-04-04 8 views
0

Ich habe ein ziemlich einfaches Hover-Menü, und ich versuche herauszufinden, wie man mit Timing umgehen.Verzögerung jQuery mouseleave oder toggleClass

Ziel ist es, das Ereignis mouseleave um 500 zu verzögern und/oder nicht auf schnelle Pässe über andere Menüelemente zu reagieren.

Die Grundfunktion:

$('.button').on({ 
    mouseenter: function() { 
    $(this).children('.menu').addClass('open'); 
    }, 
    mouseleave: function() { 
    $(this).children('.menu').removeClass('open'); 
    }, 
}); 

Das Hauptproblem dabei ist, der Pixel Spalt zwischen dem Knopf und Menü - wenn ein Benutzer mit der Maus auf das Menü bewegt sich dann, die auslöst, die mouseleave Funktion.

Ein zweites Ärgernis ist, wenn die Maus schnell über Geschwister-Tasten übergeben sie auch ihre mouseenter Funktionen auslösen.

ich auch versucht, aber keine Reaktion ...

mouseleave: function() { 

    setTimeout(function() { 
    $(this).children('.menu').removeClass('open'); 
    }, 500);}, 

}); 

und ich habe auch versucht,

mit
.delay(500).queue(function(){ 
    $(this).removeClass("open").dequeue(); 

aber es scheint mir unsicher.

console.log($.ui.version) druckt 1.11.4

Antwort

1

Betrachten Sie die 500ms warten, dann überprüfen, ob die Bedingung, die Sie gerade betrachten (vs. nicht schwebte) ist immer noch wahr.

Wenn ja, dann ergreifen Sie die entsprechenden Maßnahmen.

$('.button').on({ 
 
    mouseenter: function() { 
 
    waitEnterExit(this, true); 
 
    }, 
 
    mouseleave: function() { 
 
    waitEnterExit(this, false); 
 
    }, 
 
}); 
 

 

 
function waitEnterExit(el, inside) { 
 
    var button = $(el); 
 

 
    setTimeout(function() { 
 
    var hovered = button.is(':hover'); 
 

 
    if (hovered && inside) 
 
     button.children('.menu').addClass('open'); 
 
    else if (!hovered && !inside) 
 
     button.children('.menu').removeClass('open'); 
 
    }, 500); 
 
}
p { 
 
    display: none; 
 
} 
 

 
.open { 
 
    display: block; 
 
} 
 

 
.button { 
 
    border: 1px solid red; 
 
    margin-bottom: .5em; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div class=button>1 
 
    <p class=menu>inner</p> 
 
</div> 
 
<div class=button>2 
 
    <p class=menu>inner</p> 
 
</div> 
 
<div class=button>3 
 
    <p class=menu>inner</p> 
 
</div> 
 
<div class=button>4 
 
    <p class=menu>inner</p> 
 
</div>

+0

Danke Paul Roub, perfekte Lösung und Präsentation! – petergus

1

Die Antwort oben richtig ist, aber ich möchte nur eine Notiz machen (kann nicht kommentieren, wegen der niedrigen Ruf, so dass es als eine Antwort, die ich verlasse).

Beachten Sie, dass das von Ihnen verwendete mouseleave nicht funktioniert, um die Klassen in diesem Fall zu entfernen.

Was passiert ist, dass das $ (this) in der setTimeout-Funktion das Fenster ist, nicht Ihre Schaltfläche. Wenn Sie Ihre Schaltfläche anvisieren möchten, müssen Sie sie für die setTimeout-Funktion übergeben. Eine Möglichkeit besteht darin, eine Variable mit diese zu erstellen. Sie können es testen, indem Sie console.log mit $ (this) innerhalb und außerhalb der Funktion setTimeout aufrufen, um zu sehen, was in der Konsole gedruckt wird.

mouseleave: function() { 
    // caller now is the equivalent to this 
    var caller = this; 
    setTimeout(function() { 
    // $(this) equivalent to the .button in this case 
    $(caller).children('.menu').removeClass('open'); 
    }, 500);}, 
}); 
+0

Vielen Dank für das Hinzufügen! – petergus