jQuery setTimeout issue - javascript

I have a simple function that animates a bunch of images by crossfading them. A simple banner rotation. I set up the function so that calling animateSlideshow("play") it should set the timeout and start animating and by calling animateSlideshow("stop") it should stop.
When I call stop, however, the animation happens one more time. What is the cause for this one extra animation and how can I deal with it?
this calls the function on the bottom
function prevSlide(e){
if(curHashIndex !== 0){
$(prevBtn).off();
// Stop the current slideshow
animateSlideshow("stop");
// Reset the current slideshow
$("li.active .rightSlide > li").fadeOut(600).eq(0).fadeIn(600).addClass("actvImg");
$(".rightSlides").animate({
"left" : '+=345'
}, 600, function(){
$(prevBtn).on('click', prevSlide);
});
$(".leftSlides").animate({
"left" : '+=417'
}, 600);
// Activate the new slide
$(".rightSlides li.active").removeClass("active").prev().addClass("active");
activeSlide = $(".rightSlides li.active");
total = $(".rightSlides li.active .rightSlide > li").length;
// Start slideshow on the new slide
var delay = setTimeout(animateSlideshow("play"), 10000);
updateHash();
}
}
function animateSlideshow(action){
if(action === "play"){
$(activeSlide).data('animateSlideshow',
setTimeout(function(){
if( $(actvImg).index() === total - 1 ){
$(actvImg).fadeOut(animationSpeed).removeClass("actvImg").siblings().eq(0).fadeIn(animationSpeed).addClass("actvImg");
}else{
$(actvImg).fadeOut(animationSpeed).removeClass("actvImg").next().fadeIn(animationSpeed).addClass("actvImg");
}
actvImg = $(".rightSlides li.active .rightSlide > li.actvImg");
actvImgIndx = $(actvImg).index();
updateBreadcrumbs();
animateSlideshow("play")
}, animationTimeout)
);
}else{
clearTimeout($(activeSlide).data('animateSlideshow'));
};
};

You should use setInterval() / clearInterval() rather than recalling the function using setTimeout().
function animateSlideshow(action){
if(action === "play"){
$(activeSlide).data('animateSlideshow',
setInterval(function(){
if( $(actvImg).index() === total - 1 ){
$(actvImg).fadeOut(animationSpeed).removeClass("actvImg").siblings().eq(0).fadeIn(animationSpeed).addClass("actvImg");
}else{
$(actvImg).fadeOut(animationSpeed).removeClass("actvImg").next().fadeIn(animationSpeed).addClass("actvImg");
}
actvImg = $(".rightSlides li.active .rightSlide > li.actvImg");
actvImgIndx = $(actvImg).index();
updateBreadcrumbs();
}, animationTimeout);
);
}else{
clearInterval($(activeSlide).data('animateSlideshow'));
};
};

I am not sure why it is failing for you, but I tried a similar demo and it worked for me..
DEMO here
Additionally, I used .stop() to stop the current animation. You can use it if you want to stop the current animation on that object.

Related

Javascript setTimeout call multiple time

I have a one page horizontal sliding site. each slider has a question and a timer. when user slides to next, it should reset the timer and start from beginning. here is my jquery code:
$(document).ready(function(){
var mytimer;
$('#main').on('click', '.slidinglink', function(e){
e.preventDefault();
var section = $(this).attr('href');
var slide = $(this).data('slide');
var left = '';
if(section != '#'){
$('.timer').show();
left = '-100%';
var $active_question = $('.answer-list.active');
//mytimer = null;
clearTimeout( mytimer );
mytimer = setTimeout(function () {
finish_question( $('.answer-list > li.checked') );
}, 5000);
do_sliding(left, section, slideback);
}
});
});
The timer works for the first time. but if i go to next section, the timer does not work. What seems to be the problem? I have 2 other setTimeout functions which are also called during slide. They are like this (both similar):
setTimeout(function(){
item.removeClass('clone');
}, 20);

How to handle click event being called multiple times with jquery animation?

I have a click event that has a Jquery animation in it.
How can i guarantee that the animation has finished when multiple click events are being fired.
$(this._ScrollBarTrack).click(function(e) {
if(e.target === this && _self._horizontalClickScrollingFlag === false){
_self._horizontalClickScrollingFlag = true;
if(_self._isVertical){
} else{ //horizontal
if(e.offsetX > (this.firstChild.offsetWidth + this.firstChild.offsetLeft)){ // Moving Towards Right
var scrollableAmountToMove = _self._arrayOfCellSizes[_self._scrollBarCurrentStep + 1]; // additional amount to move
var scrollableCurrentPosition = -($(_self._bodyScrollable).position().left);
var scrollBarCurrentPosition = $(_self._ScrollBarTrackPiece).position().left;
var scrollBarAmountToMove = _self.getScrollBarTrackPiecePositionBasedOnScrollablePosition(scrollableAmountToMove);
$(".event-scroll-horizontally").animate({left:-(scrollableCurrentPosition+ scrollableAmountToMove)});
$(_self._ScrollBarTrackPiece).animate({left: (scrollBarCurrentPosition + scrollBarAmountToMove)});
_self._scrollBarCurrentStep += 1;
} else{
var scrollableAmountToMove = _self._arrayOfCellSizes[_self._scrollBarCurrentStep - 1]; // additional amount to move
var scrollableCurrentPosition = -($(_self._bodyScrollable).position().left);
var scrollBarCurrentPosition = $(_self._ScrollBarTrackPiece).position().left;
var scrollBarAmountToMove = _self.getScrollBarTrackPiecePositionBasedOnScrollablePosition(scrollableAmountToMove);
$(".event-scroll-horizontally").animate({left:-(scrollableCurrentPosition - scrollableAmountToMove)});
$(_self._ScrollBarTrackPiece).animate({left: (scrollBarCurrentPosition - scrollBarAmountToMove)});
_self._scrollBarCurrentStep -= 1;
}
}
_self._horizontalClickScrollingFlag = false;
}
});
jQuery has a hidden (I'm not sure why it's not in the docs someplace) variable $.timers that you can test against.
I made this function a long time ago to handle situations like this. Mind you, this will test to make sure there are NO animations currently being executed.
function animationsTest (callback) {
var testAnimationInterval = setInterval(function () {
if ($.timers.length === 0) { // any page animations finished
clearInterval(testAnimationInterval);
callback(); // callback function
}
}, 25);
};
Useage: jsFiddle DEMO
animationsTest(function () {
/* your code here will run when no animations are occuring */
});
If you want to test against one individually you could do a class/data route.
$('#thing').addClass('animating').animate({ left: '+=100px' }, function () {
// your callback when the animation is finished
$(this).removeClass('animating');
});
You could declare a global boolean called isAnimating and set it to true right when you begin the animation. Then add a done or complete function to the animation that sets it back to false. Then set your click event to only begin the animation if isAnimating is false.

Can't See Why setInterval() is Being Cleared

I can't for the life of me see why my setInterval() function is only executing one time. I believe I am doing it right according to its usage. It's a slideshow script that takes a group of slides as part of a slideshow object called TheBand and changes slides using setInterval().
This is the timer:
current_band.obj_timer = window.setInterval(function () {
TheBand.nextSlide(current_band_id);
}, current_band.timer);
This is the nextSlide function:
nextSlide : function (band_id) {
var obj_band = TheBand.bands[band_id];
if (band_id == 0) {
console.log(obj_band.current_slide, obj_band.slide_count)
}
if (obj_band.current_slide + 1 >= obj_band.slide_count) {
new_slide = 0;
} else {
new_slide = obj_band.current_slide + 1;
}
TheBand.changeSlide(band_id, new_slide);
},
Then the changeSlide function:
changeSlide : function (band_id, slide_id) {
var obj_band = TheBand.bands[band_id];
if (slide_id != obj_band.current_slide) {
// Get the viewport width for display purposes
var slide_width = jQuery(obj_band.viewport).width();
// Set up the slide objects
var current_slide = jQuery(obj_band.slides[obj_band.current_slide]);
var new_slide = jQuery(obj_band.slides[slide_id]);
// Set the left value for the new slide and show it
new_slide.css('left', slide_width).width(slide_width).height(obj_band.max_height);
new_slide.show();
// Animate the slide transition
current_slide.animate({ left: -slide_width }, obj_band.transition_time);
new_slide.animate({ left: 0 }, obj_band.transition_time, 'swing');
if (new_slide.css('background-color') != current_slide.css('background-color')) {
jQuery(obj_band.back).animate({ backgroundColor : new_slide.css('background-color') }, obj_band.transition_time);
}
// Set the class for the nav buttons
jQuery(obj_band.nav_buttons[obj_band.current_slide]).removeClass('selected');
jQuery(obj_band.nav_buttons[slide_id]).addClass('selected');
// Run the slide javascript - be careful with this!
eval(obj_band.slide_script[obj_band.current_slide].unload);
eval(obj_band.slide_script[slide_id].load);
window.setTimeout(function () {
eval(obj_band.slide_script[slide_id].ready);
}, obj_band.transition_time);
// Set the current slide variable
obj_band.current_slide = slide_id;
// Set the correct Nav color
TheBand.setNavColor(band_id);
}
},
Seems simple enough, but I only get to the second slide!? No errors or warnings in console and if I watch the clear timer breakpoint it does show a clear timer event, but its not from this code... Please help?
P.S. The setInterval() timer does not break if I comment out the changeSlide function.

Start and stop with the same div (javascript-jquery)

I want to start and stop an animation when click on the same div.
$('div').click(function(){
//if is the first click -->do animation in loop
//if is the second click--->stop animation
});
How do u do it?
I had resolve only the animation start with loop:
var play = 0;
function myAnimateGreen(){
$('green').animate(
{left:'+250px'},
1000,
);
while(play==1) {myAnimateGreen();}
}
$('green').click(function(){
play = 1;
myAnimateGreen();}
});
But I can't resolve the stop!
You can use the :animated selector to detect if the animation is currently happening
$('div').click(function(){
if( !$(".green").is(':animated') ) {
//Do animation
} else {
//Stop animation
}
});
function animateGreen(el) {
var delay = 500,
time = 1000,
distance = 150;
el.animate({left:'+='+distance+'px'}, time, "linear");
el.data("anim_green", setTimeout(animateGreen, time+delay, el));
}
$('green').click(function() {
var self = $(this);
if (self.data("anim_green")) {
clearTimeout(self.data("anim_green"));
self.data("anim_green", false);
return;
}
animateGreen(self);
});
Should do it, just paste! Proof: http://jsbin.com/ajagij/3/edit

Stopping increment at specific height

I am animating images within a logo in a slot-machine type of animation. I need it to stop animating once it gets to the top of the image (and send a callback if possible).
Currently, this is how I'm accomplishing the animation:
window.setInterval(function() {
$('#title-1 img').animate({bottom : '-=60px'})
}, 5000);
Any ideas on how I would get it to stop, and to send the callback?
So I assume you have a sprite image containing multiple logos, you want them to slide each 5 seconds until you reach the last one, and then call the callback?
var cnt = 6,
$img = $('#title-1 img'),
i = 0;
function animate_logo(cb) {
if (i < cnt) {
$('#title-1 img').animate({bottom : '-=60px'});
i += 1;
setTimeout(function () {animate_logo(cb)}, 5000);
}
else {
cb();
}
}();
var interval = window.setInterval(function() {
$('#title-1 img').animate({bottom : '-=60px'},
function(){
if(`some stop point`) clearInterval(interval);
}
);
}, 5000);
I would not suggest using a setInterval when dealing with animations due to the way newer browsers are making changes to the way setInterval and setTimeout work when the tab is not the active tab.
var $title1 = $("#title-1");
var $title1img = $title1.find('img');
function anim(){
if ($title1.height() < parseInt($title1img.css("bottom"))) {
setTimeout(function(){
$title1img.animate({bottom : '-=60px'},anim);
},5000);
}
}
$title1img.animate({bottom : '-=60px'},anim);
Edit: another reason not to use setInterval to fire off animations is due to the reqeustAnimationFrame that was implemented in 1.6 and removed in 1.6.3, which will more than likely be added back in 1.7. If you write code now that will be compatible later, that's less maintenance you will have to do later if you end up being required to upgrade.
Here's a jsfiddle http://jsfiddle.net/czUnU/
Edit: function...
function animColumn(title,img){
function anim(){
if (title.height() < parseInt(img.css("bottom")) {
setTimeout(function(){
img.animate({bottom : '-=60px'},anim);
},5000);
}
}
img.animate({bottom : '-=60px'},anim);
}
animColumn($("#title-1"),$("#title-1 img"));
animColumn($("#title-2"),$("#title-2 img"));
animColumn($("#title-3"),$("#title-3 img"));
http://jsfiddle.net/czUnU/1/

Categories

Resources