Reputation: 13446
My problem is that when I move mouse quickly over square element and then go out with my cursor it sometimes doesn't finish the "mouseout" part of hover function
My HTML:
<div id="wrapper">
<div id="o1" class="square"></div>
<div id="o2" class="square"></div>
</div>
CSS
#wrapper {
width: 100px;
height: 100px;
position: relative;
}
.square {
width: 100px;
height: 100px;
position: absolute;
}
#o1 {
background: red;
}
#o2 {
background: blue;
display:none;
}
Javascript:
$(function(){
var o1 = $("#o1");
var o2 = $("#o2");
$('#wrapper').hover(function() {
o1.fadeOut(400,function () {
o2.fadeIn(400);
});
}, function() {
o2.fadeOut(400,function () {
o1.fadeIn(400);
});
});
});
jsFiddle: http://jsfiddle.net/TQ37t/
I have tried using stop()
with different parameter on different places in my code but without success. Thanks
Upvotes: 0
Views: 1883
Reputation: 11307
The easiest solution I came up with was to make sure all the queues were stopped before adding any new animations:
var o1 = $("#o1");
var o2 = $("#o2");
$('#wrapper').hover(function() {
o2.stop(true, true);
o1.stop(true, true);
o1.fadeOut(400,function () {
o2.fadeIn(400);
});
}, function() {
o1.stop(true, true);
o2.stop(true, true);
o2.fadeOut(400,function () {
o1.fadeIn(400);
});
});
Note that order matters when stopping the queues. Consider the following sequence:
o1.fadeOut(400,function () {
o2.fadeIn(400);
});
o2.stop(true, true); // at this point, o1 can still queue a new animation onto o2
// at this point, o1 might finish fadeOut() and begin o2.fadeIn()
o1.stop(true, true); // We should have stopped this one first
Upvotes: 2
Reputation: 11307
Because there are two different queues running at the same time, getting them to stop was a problem. One solution I came up with was to create a single queue that could be controlled, stopped, etc.. The Javascript looks like this:
var o1 = $("#o1");
var o2 = $("#o2");
var wrapper = $('#wrapper');
function funcToFadeInOutDequeue(jq, isIn) {
if (isIn) {
return function() {
jq.fadeIn(400, function() {
wrapper.dequeue();
});
};
} else {
return function() {
jq.fadeOut(400, function() {
wrapper.dequeue();
});
};
}
}
wrapper.hover(function() {
wrapper.stop(true);
wrapper.queue( funcToFadeInOutDequeue(o1, false) );
wrapper.queue( funcToFadeInOutDequeue(o2, true) );
}, function() {
wrapper.stop(true);
wrapper.queue( funcToFadeInOutDequeue(o2, false) );
wrapper.queue( funcToFadeInOutDequeue(o1, true) );
});
See the fiddle...
Upvotes: 1
Reputation: 3518
Stop actually takes care of the problem (if this is the effect you are after):
$(function(){
var o1 = $("#o1");
var o2 = $("#o2");
$('#wrapper').hover(function() {
o1.fadeOut(400,function () {
o2.fadeIn(400);
});
}, function() {
o1.stop();
o2.fadeOut(400,function () {
o1.fadeIn(400);
});
});
});
http://jsfiddle.net/adam_gajzlerowicz/TQ37t/3/
Upvotes: 0
Reputation: 2352
Let's assume that o1 is visible and o2 is hidden. If we quickly hover in and out, the following happens:
What you get is both shapes being visible at the same time. This then causes further inconsistencies later.
What you need to do is have a flag which you set on mouseover/mouseout, which defines whether the mouse is over the #wrapper
or not. You also have similar fadeIn/fadeOut instructions, just like you have now. But for the callback, run a function that reads the flag and determines which object needs to be faded in.
$(function(){
var o1 = $("#o1");
var o2 = $("#o2");
var over = false;
choose = function() {
if (over) {
o2.fadeIn(400);
} else {
o1.fadeIn(400);
}
}
$('#wrapper').hover(function() {
over = true;
o1.fadeOut(400,choose);
}, function() {
over = false;
o2.fadeOut(400,choose);
});
});
JSFiddle: http://jsfiddle.net/TQ37t/2/
Upvotes: 1