jQuery: stop animation that is delayed, before it is triggered - javascript

I'm foolin around with the jquery hover functionality. the current code snippet looks like this:
$leftColumn.children().first().hover(
function(event) {
var $this = jQuery(this);
$this.css({
'background-color': '#505050'
}).parent().stop()
.animate(
{
'z-index': '999',
width: '220px'
},
{
duration: '1000'
}
);
},
function(event) {
var $this = jQuery(this);
$this.parent().stop()
.animate(
{
width: '38px',
'z-index': '1'
},
{
duration: '1500',
complete: function() {
$this.css({
'background-color': 'transparent'
});
}
}
);
}
);
What this basically does is increasing the width of a div (which is position absolute) to overlay another div.
I choosed to use jQuerys animate() functionality instead of CSS3s transition because I want to trigger a callback whenever the closing (decreasing the width again) animation is done.
My problem now is, that I want to delay the closing animation for 2 seconds (and yes I know about the delay() vs setTimeout() discussion) which worked fine with setTimeout(). However as the animation is timed out for the given duration it will run, even if I enter the hoverable area again. This of course makes sense as the stop() only triggeres while an animation is on the go, which is not the case if it is timed out.
How can I make this thing work (stop the closing animation when reentering the hoverable area) and still keep a timeout / delay before decreasing the width on "hover leave"?

Related

Mouseenter mysteriously activated when it shouldn't

I have this box which, on hover, plays a loader animation and then expands after 2 seconds:
http://jsfiddle.net/frank_o/WwD5V/23/embedded/result/
But how come it expands immediately (with no loader animation) if I move my mouse in the following V-shaped motion?
var timeout;
$('.wrapper').bind('mouseenter', function () {
if(!$('.wrapper').hasClass('expanded')) {
$('.loader').show();
// http://stackoverflow.com/questions/23922264/jquery-animate-goes-bananas-despite-stop
var timeoutHandle = $(this).data('timeout') || 0;
if (timeoutHandle > 0) clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(function () {
$('.wrapper').animate({
width: '100%'
}, 200);
$('.wrapper').addClass('expanded');
}, 2000);
$(this).data('timeout', timeoutHandle);
}
}).mouseleave(function () {
$('.loader').hide();
$('.wrapper').animate({
width: '120px'
}, 200);
$('.wrapper').removeClass('expanded');
});
When you mouseover, a timeout is set. When you mouseleave, the timeout continues to run. It seems that you need to clear your timeout upon mouseleave.
I did several things to achieve this:
1) Increase the scope of the variable timeoutHandle at the top of the script:
var timeoutHandle;
2) Remove the var from your timeout definition in mouseenter:
timeoutHandle = $(this).data('timeout') || 0;
3) Clear the timeout on mouseleave:
clearTimeout(timeoutHandle);
Working Example (jsfiddle)
As you mentioned, the expanded class is no longer needed. I removed it in the fiddle, below.
Also, I added code to stop any current animation on mouseleave, in case the box is in the middle of animating. I slowed down the "expand" animation to illustrate this more clearly.
$('.wrapper').stop(true,false).animate({
width: '120px'
}, 200);
Working Example (jsfiddle)

How to chain jQuery animations with a pause?

Hi I'm trying to do a simple chain animation in jQuery, with a pause (setTimeout) between each frame.
Say each div animates in with a duration of 3500. I would like to control the duration between each opacity fade in animation. Say between the first div and 2nd div the duration is 5 secs, and maybe 10 secs between the 2nd and 3rd frame.
How would you go about this?
http://codepen.io/leongaban/pen/Feroh
Current code
$('#blue').animate({
opacity: '1'
}, 3500, function(){
// Need 5 sec pause here
$('#blue').fadeOut('fast');
$('#orange').animate({
opacity: '1'
}, 3500, function(){
// Need a 10 sec pause here
$('#orange').fadeOut('fast');
$('#green').animate({
opacity: '1' }, 3500);
});
});
That's what delay() and queue() is for:
$('#blue').animate({opacity: '1'}, 3500).delay(5000).queue(function() {
$(this).fadeOut('fast');
$('#orange').animate({opacity: '1'}, 3500).delay(10000).queue(function() {
$(this).fadeOut('fast');
$('#green').animate({opacity: '1'}, 3500);
});
});
FIDDLE
This is exactly what .delay() is for (http://api.jquery.com/delay/). It allows you to write elegant chains of animations for individual elements like this:
$( "#foo" ).slideUp( 300 ).delay( 800 ).fadeIn( 400 );
Note that you will still need to use callbacks to start animations for other objects, though.
In your case, this should be it (untested):
$('#blue')
.animate({ opacity: '1' }, 3500)
.delay(5000)
.fadeOut('fast',
function() {
$('#orange')
.animate({ opacity: '1' }, 3500)
.delay()
.fadeOut('fast',
function() {
$('#green')
.animate({ opacity: '1' }, 3500);
});
});
You can use jQuery fadeOut/fadeIn methods with callbacks.
See here for more information.
But essentially is;
$(".myClass").fadeOut(1000, function() {
//fadeOut complete
});
The first argument is length of time (in ms) until it completely fades out. After that duration has passed the callback fires. So you can safely assume that when the callback fires that your required waiting time has completed.
It's the same syntax for fadeIn also, but I suggest reading the link I provided. It'll explain it it greater detail.

JQuery animate div entry

I have a webpage with a div container that contains the main content, and inside it there is a div that should appear when I put my mouse in the container. This is the code that I tried:
var running=0;
var running2=0;
$('div.container').mouseenter(function()
{
if (running==0)
{
running=1;
$('div.rightcontainer').css("margin-right",-350)
.animate({marginRight:0}, 750, function(){running=0;});
}
}
);
$('div.container').mouseleave(function() {
if (running2==0) {
running2=1;
$('div.rightcontainer').css("margin-right",0)
.animate({marginRight:-350}, 750, function(){running2=0;});
}
});
This code works:
$('div.container').mouseenter(function() {
console.log('trigger');
$("div.rightcontainer")
.css("visibility","visible")
.css("margin-right",-$("div.rightcontainer").width())
.animate({
marginRight:0
}, 1200);
});
$('div.container').mouseleave(function() {
console.log('leave');
$("div.rightcontainer")
.css("visibility","visible")
.css("margin-right", "320")
.animate({
marginRight:-350
}, 1200);
});
However, the problem is that if the mouse enters multiple times, the object keeps entering and exiting.
Edit:
The .one() only does it once, what I mean is in a way it stacks all the enters and exits and performs the animation that many times.
the .stop() solution was better, however the animation would jump to the end from wherever it was. If there is a way for, if the mouse leaves the container mid-animation, for the animaiton to stop where it is and animate back the other way?
Here is a JSFiddle with a simplified version of the website. The container is anything below the navbar. http://jsfiddle.net/yEzXp/
Use .stop()
$('div.container').mouseenter(function() {
$("div.rightcontainer")
.stop(true, true)
.css("visibility","visible")
.css("margin-right",-$("div.rightcontainer").width())
.animate({
marginRight:0
}, 1200);
});
$('div.container').mouseleave(function() {
$("div.rightcontainer")
.stop(true, true)
.css("visibility","visible")
.css("margin-right", "320")
.animate({
marginRight:-350
}, 1200);
});

Zepto animate callback not animating

I'm attempting to make something similar to github's project viewer where after clicking a link the box moves to the left out of scene and then another box moves in from the right.
The way I attempted to do this is to have just a single div that's animated, and when you click the link the div moves to the left off the screen. Then in the callback of the first animate(), I call .css to move it to the right side of the page (without animating, so it just jumps there) then animate it again to move it back into view from the right.
Here's the JS
$('.mLink').on('click', function(e) {
var
marginR = $('#mover').css('margin-right'),
marginL = $('#mover').css('margin-left');
$('#mover').animate({
'margin-left': '-1500px',
'margin-right': '1500px'
}, 500, 'ease-out', function() {
$('#mover').css({
'margin-left': '1500px',
'margin-right': '-1500px'
});
$('#mover').animate({
'margin-left': marginL,
'margin-right': marginR
}, 500, 'ease-in');
});
});
So what happens is that it animates to the left of the screen then jumps to the right side correctly but then appears in the proper location without actually doing the animation. I'm curious why this is occurring because it means animate() is executing just not showing the animation?
EDIT: for clarification
Try something like this, as I am not able to see all dependencies, and thus not able to create fiddle for the same,
$('.mLink').on('click', function(e) {
var
marginR = $('#mover').css('margin-right'),
marginL = $('#mover').css('margin-left');
$('#mover').animate({
'margin-left': '-1500px',
'margin-right': '1500px'
}, 500, 'ease-out', function() {
$('#mover').animate({
'margin-left': ' 1500px',
'margin-right': '-1500px'
}, 500, 'ease-in', function() {
$('#mover').animate({
'margin-left': marginL,
'margin-right': marginR
}, 500, 'ease-in', function(){return false;});
});
});
});
I hope this will do, as you want two effects you can have two functions. :) or more if you want or all together in one function.

Jquery Timer Slide function

Right now I have a div that slides right to left and then vice versa back to its original place. But overall its not really how I want it to work. My main goal: is for the user to hover over the main div which will then pull out the sliding div. The part that gets tricky is the following: If the user forgets to slide the dive back, I want to give it time frame that will cause it to close automatically after a certain time has passed. Here is my working code so far: jsfiddle.net/eMsQr/14/.
My JavaScript function:
$(document).ready(function() {
$("#arrow").hover(
function(){
$("#inner").stop().animate({marginRight: "0px", opacity: "1px", height: "100px"}, 500 );
},
function(){}
);
});
$("#arrow").click(function(e){
$("#inner").stop().animate({marginRight: "-100px", opacity: "1px", height: "100px"}, 500 );
});
Try this: http://jsfiddle.net/vansimke/cJ5pf/
I hooked into the mouseleave event and added a setTimeout. You might need to catch the timeout if you need to cancel it later (i.e. they reenter the arrow)
Here's a jsFiddle example that sets a 3 second delay via the setTimeout function.:
jQuery
var cto;
$("#arrow").hover(
function() {
clearTimeout(cto);
$("#inner").stop().animate({
marginRight: "0px",
opacity: "1px",
height: "100px"
}, 500);
}, function() {
cto = setTimeout(function(){$('#arrow').trigger('click')}, 3000);
});
$("#arrow").click(function(e) {
$("#inner").stop().animate({
marginRight: "-100px",
opacity: "1px",
height: "100px"
}, 500);
});​
Note that if the user moves his mouse away and then returns it to the div, the box remains open again until they leave at which point the 3 second countdown timer begins.
You need to make sure you utilize the second function() in jQuery's hover method.
At the moment you're only animating your slide-out div when the user hovers over the main div. You want it to also animate on hover out.
Here's the updated jsFiddle.
Inside the hover function you can add an additional line to trigger the click event using the below line:
setTimeout(function() { $("#arrow").trigger('click'); }, 5000);
the 5000 is the number of milliseconds to wait before triggering the click.
see the fiddle here: http://jsfiddle.net/eMsQr/51/
it uses the mouseleave jquery and also delay. Change the value in the delay to get the time you want.
$("#arrow").mouseleave(function(){
$("#inner").stop().delay(500).animate({marginRight: "-100px", opacity: "1px", height: "100px"}, 500 );
});
You need to use setTimeout() to set the delay to closing the div. You also need to use clearTimeout() in the opening function to stop it auto closing if someone mousesout, then back over again:
var timeout;
$("#arrow").hover(
function() {
clearTimeout(timeout); // clear the timer which will close the div, as we now want it open
$("#inner").stop().animate({
marginRight: "0px",
opacity: "1px",
height: "100px"
}, 500);
}, function() {
timeout = setTimeout(function() {
$("#inner").stop().animate({
marginRight: "-100px",
opacity: "1px",
height: "100px"
}, 500);
}, 1000); // close the open div 1 second after mouseout.
}
);
Example fiddle

Categories