Reputation: 28427
Relevant code (also annotated in fiddle):
// tooltip positioning on hover and overlay fade on all li's except for submenu items that are not the last child
$("ul:not(.sub-menu) > li, ul.sub-menu > li:last-child").not(":has(ul.sub-menu)").hover(function () {
var $this = $(this),
title = $(this).children("a").data("title"),
posL = $this.offset().left + ($this.width() / 2),
posT = $this.height(),
tooltip = $("#tooltip"),
overlay = $("#overlay");
$this.addClass("over-down");
overlay.stop(true).fadeIn("slow"); // RELEVANT FOR QUESTION
tooltip.stop(true, true).text(title).animate({ // RELEVANT FOR QUESTION
"left": posL - (tooltip.width() / 2),
"top": posT + $this.offset().top + 20
}, 300).fadeIn("fast");
}, function () {
var $this = $(this),
tooltip = $("#tooltip"),
overlay = $("#overlay");
$this.removeClass("over-down");
overlay.stop(true).fadeOut("slow"); // RELEVANT FOR QUESTION
tooltip.stop(true).fadeOut(400); // RELEVANT FOR QUESTION
});
In the fiddle, try hovering over an item, then briefly leaving it and hovering another item. You will see that the #overlay
div has partially faded out, as has the #tooltip
span. What I want is a smooth transition between the two, so normally, tooltip and overlay should fadeIn again to a 100%, but they don't. I have been messing around with that .stop()
but nothing seems to work.
This problem occurs on every browser tested (IE10, FF, Chrome).
Upvotes: 1
Views: 132
Reputation: 70139
When you .stop(true)
in the middle of a fadeOut
, the item will not be set to display:none
hence the next fadeIn
will have no effect.
There are 2 possible solutions:
Using .stop(true, true)
before the fadeIn
will force an abrupt display:none
on the element and hence enable a fadeIn
in succession. This is not a very smoothly solution. Fiddle
Another solution is to use fadeTo
instead of fadeIn
. fadeTo
will animate the opacity similar to fadeIn
, but without the display:none
requirement. It also works on hidden elements fading them in as fadeIn
does:
$this.addClass("over-down");
overlay.stop(true).fadeTo(600, .75); //edited here
tooltip.stop(true, true).text(title).animate({ //here*
"left": posL - (tooltip.width() / 2),
"top": posT + $this.offset().top + 20
}, 300).fadeTo(200, 1); //and here
This is a way more smoothly solution. It will animate the element properly back to .75
opacity independently of its current opacity or display.
*Added a .stop(true, true)
to the tooltip so it doesn't stay half-faded while your fadeTo
is queued. If you want to slide such them, try:
var do_dequeue = tooltip.is(':visible');
tooltip.stop(true).text(title).animate({ // RELEVANT FOR QUESTION
"left": posL - (tooltip.width() / 2),
"top": posT + $this.offset().top + 20,
}, 300).fadeTo(200, 1);
if (do_dequeue) tooltip.dequeue();
The do_dequeue
var keeps track of whether the tooltip was partially faded before preparing the move then fade queue, if it is partially faded then it won't wait for the tooltip to be placed under the element before fading it back to full opacity. I guess this is the smoother it can get. =]
Upvotes: 1