setInterval and setTimeout speed changes - javascript

My problem is within some JavaScript:
var mijnfunctie = function(){
//balk 1 2 3
setTimeout(function(){
$("#balk1").animate({"margin-left": "0px"}, 400);
$("#balk2").animate({"margin-left": "0px"}, 400);
$("#balk3").animate({"margin-left": "0px"}, 400);
});
setTimeout(function(){
$("#balk1").animate({"margin-left": "-2000px"}, 400);
$("#balk2").animate({"margin-left": "4000px"}, 400);
$("#balk3").animate({"margin-left": "-5000px"}, 400);
}, 2000);
//balk 4 5 6
setTimeout(function(){
$("#balk4").animate({"margin-left": "0"}, 400);
$("#balk5").animate({"margin-left": "0"}, 400);
$("#balk6").animate({"margin-left": "0"}, 400);
}, 3000);
setTimeout(function(){
$("#balk4").animate({"margin-left": "2000px"}, 400);
$("#balk5").animate({"margin-left": "-4000px"}, 400);
$("#balk6").animate({"margin-left": "5000px"}, 400);
}, 5000);
setInterval(mijnfunctie, 6000);
};
mijnfunctie();
this is made for a slider and it works fine. For six times, and after the sixth it's starting to mix up. So somewhere the time isn't right, but where?

setInterval will enqueue a repeated function. Since you're doing it at the end of the function you're enqueuing, after twelve seconds, it will run twice. After each six more seconds, the count of them will double. Slowly, this will bring the browser to its knees. You'll have 500 timers set up in mere one minute, 500 000 timers the second minute...
Either move setInterval outside of the function you want to repeat, or (better) change it to setTimeout(which will enqueue just one occurence of the call).
function mijnfunctie(){
...
setTimeout(mijnfunctie, 6000);
}
Secondly, your first call to setTimeout is missing its argument. No matter what the default value is, you should always specify it.
Third, if any animation delays by a few seconds, then the subsequent animations will run immediately after. To prevent this, you may want to chain the animations instead of relying on correct timing. In that case, to prevent the pyramid effect (extreme indenting), I suggest this form:
function phase1(){
$(...).animate(..., phase2);
}
function phase2(){
...
...
function phaseN(){
$(...).animate(..., phase1);
}

You cannot rely on delay in setTimeout, this value means only minimal delay for the function. Instead you should chain those functions.
var mijnfunctie = function(){
setTimeout(function(){
$("#balk1").animate({"margin-left": "0px"}, 400);
$("#balk2").animate({"margin-left": "0px"}, 400);
$("#balk3").animate({"margin-left": "0px"}, 400, function () {
setTimeout(function () {
$("#balk1").animate({"margin-left": "-2000px"}, 400);
$("#balk2").animate({"margin-left": "4000px"}, 400);
$("#balk3").animate({"margin-left": "-5000px"}, 400, function () {
setTimeout(function () {
$("#balk4").animate({"margin-left": "0"}, 400);
$("#balk5").animate({"margin-left": "0"}, 400);
$("#balk6").animate({"margin-left": "0"}, 400, function () {
setTimeout(function () {
$("#balk4").animate({"margin-left": "2000px"}, 400);
$("#balk5").animate({"margin-left": "-4000px"}, 400);
$("#balk6").animate({"margin-left": "5000px"}, 400, function () {
setTimeout(mijnfunctie, 600);
});
}, 1600);
});
}, 600);
});
}, 1600);
});
}, 0);
};
mijnfunctie();
anyway I would rather suggest something like that :)
(function () {
var objects = new Array(6),
index = 0,
steps = [
[[0,'0px'],[1, '0px'],[2, '0px']],
1600,
[[0,'-2000px'],[1,'4000px'],[2,'-5000px']],
600,
[[3,'0px'],[4,'0px'],[5,'0px']],
1600,
[[3,'2000px', '-400px', '5000px']],
600
],
i = 6,
crawler;
while(i--) { objects[i] = $('#balk'+(i + 1)); };
crawler = function () {
var step, k;
if (index >= steps.length) index = 0;
step = steps[index];
++index;
if (typeof(step) == 'number') {
setTimeout(step, crawler);
} else {
k = step.length - 1;
while(k--) {
objects[k[0]].animate({'margin-left': step[k[1]]}, 400, (k ? null : crawler)});
}
}
};
crawler();
}());
or something more generic and reusable

Gerrit you are using setInterval(mijnfunctie, 6000); function inside the same function that's why it is looping itself and calling setInterval(mijnfunctie, 6000); function multiple times..
Therefore calling setInterval(mijnfunctie, 6000); function only once (where first time is called) is adviced.
Enjoy..!

Related

End a script 1 second after the first scripts finishes

I want to run an animation function after another function (handleScreen) has completed. The animation function will fade out parts of the page after 1 sec. I tried adding a .promise function but that doesn't seem to work.
https://jsfiddle.net/Dar_T/eqdk82ru/1/
handleScreen(mql).promise().done(function() {
setTimeout(function() {
$("#name,#splash").fadeOut("slow");
}, 1000);
});
You can use jquery Deferred object to resolve this:
handleScreen creates a $.Deferred that will be passed to the animation function. A promise from this deferred is then returned.
function handleScreen(mql) {
var def = $.Deferred();
mql.matches ? smallBlock(def) : largeBlock(def);
return def.promise();
}
The animation function marks the deferred as resolved once the animation finishes (using TweenLite onComplete argument on the last animation):
function largeBlock(def) {
setTimeout(function () {
TweenLite.defaultEase = Linear.easeNone;
TweenLite.set('.square', { visibility: 'visible' });
var tl = new TimelineLite();
tl.fromTo('.l1', 2, { height: 0 }, { height: 227 });
tl.fromTo('.l2', 3, { width: 0, }, { width: 445 });
tl.fromTo('.l3', 2, { height: 0 }, { height: 227 });
tl.fromTo('.l4', 3, { width: 0 }, { width: 445, onComplete: def.resolve });
tl.timeScale(4);
}, 600);
}
fadeOut is executed once the deferred is done:
handleScreen(mql).done(function() {
setTimeout(function() {
$("#name,#splash").fadeOut("slow");
}, 1000);
});
});
Demo: https://jsfiddle.net/g5f7pex3/1/
A simple approach that addresses the problem in a different way than you were thinking:
var alreadyFaded = false;
function FadeSplash()
{
if(alreadyFaded == false){
//prevent this from running a second time
alreadyFaded = true;
$("#name,#splash").fadeOut("slow");
}
}
$(function () {
//do something
//make the fade happen upon finishing if it hasn't already
FadeSplash();
});
$(function () {
//by default, the fade will happen after 5 seconds if FadeSplash()
//wasn't already called by the above function.
$("#splash,#name").show(), setTimeout(function () {
FadeSplash();
}, 5000)
});
Here's a working JSFiddle to demonstrate:
https://jsfiddle.net/tthhaft1/
Short answer: you can't do it naturally. Long Answer: use an interval to check for a flag, also, there is no need for 2 document ready:
$(document).ready(function () {
var finished = false;
SOME FUNCTION
//Inside SOME FUNCTION do your stuff, and before returning or whatever it is doing:
var intervalCheck = setInterval(function () {
if (finished) {
//Do your stuff you need to do after those 5 secs.
clearInterval(intervalCheck);
}
}, 1000);
$("#splash,#name").show(), setTimeout(function () {
$("#name,#splash").fadeOut("slow")
finished = true;
}, 5000);
});

clearInterval not working with jquery .hover

I have a flipping effect using timeouts and setInterval with the following code:
// Flip and unflip panels
function startFlip() {
$('div#front-page-mosaic .front-box.flip').find('div').stop().rotate3Di('flip', 500, {direction: 'clockwise', sideChange: mySideChange});
setTimeout( function() {
$('div#front-page-mosaic .front-box.flip').find('div').stop().rotate3Di('unflip', 500, {sideChange: mySideChange});
}, 8500);
}
// Global flipping effect hook
var flip_hook;
// Autostart flipping effect
setTimeout( function() {
startFlip();
flip_hook = setInterval(function(){ startFlip(); }, 17000);
}, 8000);
// Stop the flipping effect
function stopFlip() {
clearInterval(flip_hook);
}
// Stop fliping on mouse hover, restart on mouse leave
$('div#front-page-mosaic .front-box.flip').hover(
function () {
stopFlip();
},
function () {
setTimeout( function() {
startFlip();
flip_hook = setInterval(function(){ startFlip(); }, 17000);
}, 8000);
}
);
But it does not stop the effect on mouseover. Seems it is not catching the clearInterval(). Any idea why?
You are calling a setTimeout to fire 8 seconds after. So if the user enters before that last setTimeout fires than it will still run. You need to cancel that timer also.
var delay;
function stopFlip() {
clearInterval(flip_hook);
clearTimeout(delay);
}
// Stop fliping on mouse hover, restart on mouse leave
$('div#front-page-mosaic .front-box.flip').hover(
function () {
stopFlip();
},
function () {
delay = setTimeout( function() {
startFlip();
flip_hook = setInterval(function(){ startFlip(); }, 17000);
}, 8000);
}
);

2 functions same time jQuery slideUp -slideDown + resize

What's the best solution to run those functions at the same time?
Mainly: slideDown and fancybox.resize, as it's now run on function complete, function fancybox.resize has to be run while slidedown is running, otherwise it won't work.
function DisplayLogin() {
jQuery("#sign-up-select").slideUp(400);
jQuery("#login-select").slideDown(400, function(){
jQuery.fancybox.resize()
});
}
Thanks!!
Adam
Thanks for help guys!!
That's what I wanted to get - final result:
function DisplayLogin() {
jQuery("#sign-up-select").slideUp(400);
jQuery("#login-select").slideDown(400);
var interval = setInterval(function(){jQuery.fancybox.resize()}, 100);
setTimeout(function() {
clearInterval(interval);
}, 400);
}
Run another function while other is 'running' using setInterval.
function DisplayLogin() {
jQuery("#sign-up-select").slideUp(400);
jQuery("#login-select").slideDown(400);
var interval = setInterval(function(){jQuery.fancybox.resize()}, 100);
setTimeout(function() {
clearInterval(interval);
}, 400);
}

how to stop an Interval function in my jquery plugin

i wrote a jquery plugin to make a div auto scroll,i used function setInterval to make the div stop for a while and then keeps on scroll.
here is the code
(function($){
"use strict";
function scrolltotop(obj,height,speed){
var ch=parseInt($(obj).css("margin-top"))+29;
$(obj).parent().find(".moving").remove();
$(obj).after($(obj).clone().addClass("copy"));
$(obj).addClass("moving").removeClass("copy").animate({
"margin-top":-27
},speed);
loop=setInterval(function(){
ch+=27;
if(ch < height+27){
$(obj).animate({
"margin-top":-ch
},speed,function(){
loop;
})
}else{
clearInterval(loop);
scrolltotop($(obj).next(".copy"),height,speed);
}
},4000)
}
$.fn.extend({
autoscroll: function(options) {
var defaults = {
speed: 1000,
scroller : '#scroller',
scroller_container : '#scroller_container'
}
var options = $.extend(defaults, options);
var height=$(options.scroller).height();
var stop=stopscroll();
//console.log(height)
scrolltotop(options.scroller,height,options.speed);
},
});
}(jQuery));
$("#list2").autoscroll({scroller:"#list2",scroller_container:"#container_2"});
it works well,but idont know how to make the div stop scroll after i init the plugin.
if I understand the problem you want to move the div scroll line by line waiting 4s until you reach the end.
I simplified your scrolltotop function
function scrolltotop(obj,height,speed){
var ch = 0;
var loop = setInterval(function(){
ch+=27;
$('#container_2').animate({
scrollTop: ch
}, speed);
if(ch >= height){
console.log('Out of loop');
clearInterval(loop);
}
},4000);
}
You can see a working example here http://jsfiddle.net/jCw3y/
May be you can adapt my code to use it in your plugin.
(You're using "use strict". Remember to declare javascript variables always. var loop, var ch e.t.c)
To stop manually you can save the intervalId and call clearInterval when you want.
Check this example: http://jsfiddle.net/ccR4t/
And finally, another example with pure jquery. Using animate and stop functions to control all.
(function ($) {
"use strict";
function scrolltotop($container, options) {
$container.animate({
scrollTop: options.scrollerHeight
}, options.speed, function () {
console.log('Animation completed');
});
}
$.fn.extend({
autoscroll: function (options) {
var $me = this;
var defaults = {
speed: 1000,
scroller_container: '#scroller_container',
scroller: '#list2'
}
var options = $.extend(defaults, options);
options.scrollerHeight = $(options.scroller).height();
scrolltotop($me, options);
},
});
}(jQuery));
$("#container_2").autoscroll({
scroller: '#list2',
speed: 10000
});
// stop scroll after 4 sec
setTimeout(function () {
$('#container_2').stop();
alert('scroll manually stopped')
}, 4000);
Working example:
http://jsfiddle.net/c8Ns8/

Anonymous function in setTimeout not working

I'm trying to create a delay between two loops of the nivo-slider.
Without the setTimeout everything works just fine (but without delay). So the folloing example works:
$('#slider').nivoSlider({
lastSlide: function(){
$('#slider').data('nivo:vars').stop = true;
// setTimeout(function() {
$('#slider').data('nivo:vars').stop = false;
// }, 2000);
},
});
If I uncomment the setTimeout-lines the slider stops but does not start again? Any ideas why?
Update:
http://jsfiddle.net/kgYNX/
2nd update:
Tried it with a wrapping function, too. The function gets called but if I use setTimeout in the new function it stops working: http://jsfiddle.net/kgYNX/1/
Solved it slightly different:
beforeChange: function(){
$('#slider').data('nivo:vars').stop = true;
var delay = 0;
if ($('#slider').data('nivo:vars').currentSlide == $('#slider').data('nivo:vars').totalSlides - 2) {
delay = 2000;
}
setTimeout(function() {
$('#slider').data('nivo:vars').stop = false;
}, delay);
}
I don't know why "totalSlides - 2", but it works: http://jsfiddle.net/kgYNX/15/
As a variant, you may add custom option to slider vars collection to prevent stop execution on lastSlide handler when slider re-enabled by timeout:
lastSlide: function () {
var dontStop = $('#slider').data('nivo:vars').dontStopOnLast;
if (!dontStop) {
$('#slider').data("nivoslider").stop();
setTimeout(function () {
$('#slider').data("nivoslider").start();
}, 2000);
}
$('#slider').data('nivo:vars').dontStopOnLast = !dontStop;
}

Categories