JQuery not executing within a For loop - javascript

Im a JQuery noob trying to write a simple jQuery code to get a text to blink three times. My initial code was as follows:
$("#welcome").click(function () {
var i = 1;
while (++i < 10) {
$("#welcome").fadeOut("slow", function () { $("#welcome").fadeIn("slow"); })();
}
});
But since I probably meddled in forces I could not comprehend, the above code made the text blink only once. I read up on closures and got convinced that the below code could make a change. Unfortunately, it doesnt.
$("#welcome").click(function () {
var i = 1;
while (++i < 10) {
(function (i) {
$("#welcome").fadeOut("slow", function () { $("#welcome").fadeIn("slow"); })();
})(i);
}
});
Can anyone tell me whats going on here?

You need make use of the animation queue
var $welcome = $("#welcome").click(function () {
var i = 1;
//clear previous animations
$welcome.stop(true, true);
while (++i < 10) {
$welcome.fadeOut("slow").fadeIn("slow");
}
});
Demo: Fiddle

Fading in and out takes some time, and you have to wait for your animation to be over before you can run the next one.
The provided answers solve your problem since jQuery is clever enough to bufferize your animation queue, but it may creates even more confusion for begginers, and also if you want to do something else between the fading animations, you can't rely on it anymore.
You then have to write your code on what is called an asynchronous recursive way (woah). Simply trying to understand that snippet may help you a lot with javascript general programming.
function blink(nbBlinks) {
// Only blink if the nbBlinks counter is not zero
if(nbBlinks > 0) {
$('#welcome').fadeOut('slow', function() {
// Do stuff after the fade out animation
$(this).fadeIn('slow', function() {
// Now we're done with that iteration, blink again
blink(nbBlinks-1);
})
});
}
}
// Launch our blinking function 10 times
blink(10);

This works perfectly. Demo http://jsfiddle.net/X5Qy3/
$("#welcome").click(function () {
for (var x = 0; x < 3; x += 1) {
$("#welcome").fadeOut("slow");
$("#welcome").fadeIn("slow");
}
});
Also, if you know how many times you want to do something. You should use a For Loop. While Loops are for when you don't know how many times you want it to run.

Set in queue
$("#welcome").click(function () {
var i = 1;
//clear animations whcih are running at that time
$(this).stop(true, true);
while (++i < 10) {
$(this).fadeOut("slow").fadeIn("slow");
}
});

You can not use jQuery delay function inside a looping/iteration hence you have to user closures:
$(document).ready(function(){
$(".click1").click(function () {
for (i=0;i<=10;i++) {
setTimeout(function(x) {
return function() {
$("#wrapper").fadeOut("slow", function () { $("#wrapper").fadeIn("slow"); })();
};
}(i), 1000*i);
}
});
});
<div id="wrapper"></div><div class="click1">click</div>
You can later change the count how many times you want to blink the <div>.

Related

prevent animation double click issue

Hi I have problem with my slider please visit this site and check http://paruyr.bl.ee/
after click on my arrows it becomes work in an asynchronous way, ones it changes very fast and then slow and it repeats.
I think it is from start slider and stop slider.
var sliderPrev = 0,
sliderNext = 1;
$("#slider > img").fadeIn(1000);
startSlider();
function startSlider(){
count = $("#slider > img").size();
loop = setInterval(function(){
if (sliderNext>(count-1)) {
sliderNext = 0;
sliderPrev = 0;
};
$("#slider").animate({left:+(-sliderNext)*100+'%'},900);
sliderPrev = sliderNext;
sliderNext=sliderNext+1;
},6000)
}
function prev () {
var newSlide=sliderPrev-1;
showSlide(newSlide);
}
function next () {
var newSlide=sliderPrev+1;
showSlide(sliderNext);
}
function stopLoop () {
window.clearInterval(loop);
}
function showSlide(id) {
stopLoop();
if (id>(count-1)) {
id = 0;
} else if(id<0){
id=count-1;
}
$("#slider").animate({left:+(-id)*100+'%'},900);
sliderPrev = id;
sliderNext=id+1;
startSlider();
};
$("#slider, .arrows").hover(function() {
stopLoop()
}, function() {
startSlider()
});
function onlyNext () {
var newSlide=sliderPrev+1;
onlyShowSlide(newSlide);
}
function onlyShowSlide(id) {
if (id>(count-1)) {
id = 0;
} else if(id<0){
id=count-1;
}
$("#slider").animate({left:+(-id)*100+'%'},900);
sliderPrev = id;
sliderNext=id+1;
};
I think the best option would be to check if the animation is in progress and prevent the action if it is, something like this:
function prev () {
if(!$('#slider').is(":animated"))
{
var newSlide=sliderPrev-1;
showSlide(newSlide);
}
}
function next () {
if(!$('#slider').is(":animated"))
{
var newSlide=sliderPrev+1;
showSlide(sliderNext);
}
}
To illustrate the difference between this and just sticking a stop() in, check this JSFiddle. You will notice some choppy movements if you click multiple times in the stop() version.
What I would do is add a class to your slider when the animation starts and remove the class when it finishes:
$("#slider").animate({left:+(-id)*100+'%'}, {
duration: 900,
start: function() {
$('#slider').addClass('blocked');
},
complete: function() {
$('#slider').removeClass('blocked');
}
});
Now check on each click event if the slider is blocked or not:
function next () {
if (!$('#slider').hasClass('blocked')) {
var newSlide=sliderPrev+1;
showSlide(sliderNext);
}
}
This is a very simple solution, I'm sure there is a better one.
EDIT: As marcjae pointed out, you could stop the animations from queuing. This means when you double click, the slideshow still will move 2 slides. With my approach the second click will be ignored completely.
You can use a variable flag to control if the animation is still being done, or simply use .stop() to avoid stacking the animation.
$("#pull").click(function(){
$("#togle-menu").stop().slideToggle("slow");
});
It is occurring because your animations are being queued.
Try adding:
.stop( true, true )
Before each of your animation methods. i.e.
$("#slider").stop( true, true ).animate({left:+(-id)*100+'%'},900);
The answers about stop are good, but you have a bigger issue that is causing the described behavior. The issue is here:
$("#slider, .arrows").hover(function() {
stopLoop()
}, function() {
startSlider()
});
You have bound this to the .arrows as well as the #slider and the arrows are contained within the slider. So, when you mouse out of an arrow and then out of the entire slider, you are calling start twice in a row without calling stop between. You can see this if you hover onto the arrow and then off of the slider multiple times in a row. The slides will change many times after 6 seconds.
Similarly, consider the case of a single click:
Enter the `#slider` [stopLoop]
Enter the `.arrows` [stopLoop]
Click the arrow [stopLoop]
[startSlider]
Leave the `.arrows` [startSlider]
Leave the `#slider` [startSlider]
As you can see from this sequence of events, startSlider is called 3 times in a row without calling stopLoop inbetween. The result is 3 intervals created, 2 of which will not be stopped the next time stopLoop is called.
You should just have this hover on the #slider and more importantly, add a call to stopLoop as the first step in startSlider. That will ensure that the interval is always cleared before creating a new one.
$("#slider").hover(function() {
stopLoop()
}, function() {
startSlider()
});
function startSlider(){
stopLoop();
/* start the slider */
}

How to initiate an action after 3 mouse clicks

I am new to writing code but I'm trying to figure out to have a div disappear after being clicked three times. I know how to get it to disappear after one or two clicks but I'm not sure how to do it after three. I wrote a while loop that should iterate up once after each click but instead the function doesn't wait for the div to be clicked and goes ahead and fades out the div.
var threeClick = function() {
var n = 0;
while(n > 2) {
$(document).ready(function() {
$('div').click(function(){
n++;
});
});
$(document).ready(function(){
$('div').fadeOut('slow');
});
}
}
threeClick();
var n
$(document).ready(function()
{
n=0;
$('div').click(function()
{
n++;
if(n==3)
{
n=0;
$('div').fadeOut('slow');
}
});
}
$(document).ready(function() {
var n = 0;
$('div').click(function() {
n++;
if (n == 3) {
$(this).fadeOut('slow');
}
});
});
see this
You don't have to repeat $(document).ready. This is a method (from jQuery) called when DOM is ready. So your code should go in this function;
This should work:
$(document).ready(function() {
var n = 0;
$('div').click(function() {
n++;
if(n == 3) {
$('div').fadeOut('slow');
}
});
});
I'm wondering why your while loop doesn't block execution while it sits and spins. JavaScript is not multi-threaded; there is a single thread of execution and I would imagine that the while would block that thread. But aside from that it won't really work because you're never checking the value of n before you fade out the div. This is why the fade-out happens almost immediately. There is also no need for numerous $(document).ready(...) calls; one will do.
I would also recommend using .on:
$(document).ready(function() {
var n = 0;
$('div').on('click', function() {
n++;
if(n >= 3) {
$('div').fadeOut('slow');
}
});
});
This works because the n which has been defined in the anonymous function (passed to .ready) is available to the callback (closure) passed to .on or .click. Closures are lexically bound to the scope in which they are defined, which means that anything defined in the enclosed scope is available to the closure. So your n's value will be updated and available to the closure.
You may try this too
$(function(){
$('#myDiv').on('click', function(){
var clicks = $(this).data('clicks') || 0;
$(this).data('clicks', clicks+1);
if($(this).data('clicks') >=3 ) $(this).fadeOut();
});
});
DEMO.
You need to create the variable holding the count outside of the function or it will reset each time the function is called. Give the div a class name - here i have used 'divClassName'.
var numClicks = 0;
$(function() {
$(document).on("click",".divClassName",function() {
numClicks+=1;
if (numClicks > 2) {
$('div').fadeOut('slow');
}
}
};
With jQuery you could do something like that
var counter=0;
$('div').on('click',function(){
counter++;
if(counter==3)$('div').fadeOut();}
);

Timer won't die javascript

I am doing some long polling.. and I have a function to make a button blink when a certain statement is true.. Here it is:
function blinking(object, x) {
console.log(x);
if(x>0){
var existing_timer = object.data('clock');
if (existing_timer){
clearInterval(existing_timer);
}
timer = setInterval(blink, 10);
function blink() {
object.fadeOut(400, function() {
object.fadeIn(400);
});
}
}
}
Now.. Notice the timer being set as 'timer'. When someone does something that makes the statement false (making x=0), I want the timer to stop making the button blink when it sees that x=0. This may sound easy but I have tried everything ha.
I've been researching and trying different things, but It doesn't seem to work.
If your variable timer is global, then you should be able to clear the interval using that:
clearInterval(timer);
The integer returned from the setInterval is unique to that timer, so that is what you need to clear.
Here's a simple implementation.
http://jsfiddle.net/AQgBc/
var $led = $('#led'),
blinkState = 0,
blinkTimer,
blinkDuration = 300,
blink = function () {
if (blinkState) {
$led.toggleClass('on');
}
console.log('blink');
blinkTimer = setTimeout(blink, blinkDuration);
};
$('button').on('click', function () {
blinkState = (blinkState) ? 0 : 1;
});
blink();
I just wrote my own without duplicating yours, but the most relevant issue, I think, is just using a setTimeout rather than worrying about a setInterval and clearing that interval.
Edit in response to comment:
If you want it to blink until a user action, then stop polling, it's even simpler.
http://jsfiddle.net/AQgBc/1/
var $led = $('#led'),
blinkState = 1,
blinkTimer,
blinkDuration = 300,
blink = function () {
if (blinkState) {
console.log('blink');
$led.toggleClass('on');
blinkTimer = setTimeout(blink, blinkDuration);
}
};
$('button').on('click', function () {
blinkState = (blinkState) ? 0 : 1;
});
blink();

JavaScript/jQuery - Add Delay between Add and Remove Class and next function [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
jquery add a fade to an .addClass
Here is my jsFiddle example: http://jsfiddle.net/sLzGc/
I am trying to create an effect where it appears options 1 through 3 are being rotated. Every 1.2 seconds the green class is removed from the option that has it and the green class is added to the next option. The idea is that the rotation through the three options happens five times (i<5) before the final function alert('Finished') is executed.
I'm trying to use setTimeout(), but I'm open to using .delay(), another jQuery function, or some other option.
Here is my JavaScript/jQuery:
alert('Start');
sampleFunction();
function sampleFunction() {
for (i=0; i<5; i++) {
setTimeout(function() {
$('#option2').addClass('green');
$('#option1').removeClass('green');
},1200);
setTimeout(function() {
$('#option3').addClass('green');
$('#option2').removeClass('green');
},1200);
setTimeout(function() {
$('#option1').addClass('green');
$('#option2').removeClass('green');
},1200);
}//end for loop
}
alert('Finished');​
My whole example is on jsFiddle: http://jsfiddle.net/sLzGc/
Thanks for any help or insight you can offer!
Here's how I would approach the problem:
​(​function() {
var options = [$("#option1"), $("#option2"), $("#option3")],
cycles = 5,
i = 0,
$last = $(null);
(function next() {
if(i < cycles * options.length) {
$last.removeClass("green");
$last = options[i % options.length].addClass("green");
i++;
setTimeout(next, 1200);
} else {
$last.removeClass("green");
alert("finished!"); //do any other "we're done" stuff here.
}
}());
}());​
It's pretty straightforward and the cool part is that you can add elements to the list of elements to cycle through pretty easily (just add them to options). You can also set the number of cycles if you want. I didn't make the class or delay length a variable, but that would be very simple in case you wanted to do that.
You can see a demo here:
http://jsfiddle.net/D7SR8/
You might also consider having a callback function at the end and putting the alert() in there. That would be more reusable.
If you are wanting to use setTimeouts then your code could look something like this:
var iteration = 0;
alert('start');
rotateColors();
function rotateColors() {
setTimeout(function() {
$('#option2').addClass('green');
$('#option1').removeClass('green');
setTimeout(function() {
$('#option3').addClass('green');
$('#option2').removeClass('green');
setTimeout(function() {
$('#option1').addClass('green');
$('#option3').removeClass('green');
iteration += 1;
if(iteration < 5)
rotateColors();
else
alert('finished');
},1200);
},1200);
},1200);
}
Live DEMO
alert('Start');
var varobj=0;
sampleFunction();
function sampleFunction() {
setTimeout(function() {
$('#option2').addClass('green');
$('#option1').removeClass('green');
},1200, setTimeout(function() {
$('#option3').addClass('green');
$('#option2').removeClass('green');
},1200,setTimeout(function() {
$('#option1').addClass('green');
$('#option3').removeClass('green'); if(varobj<5){varobj=varobj+1;sampleFunction();}else{ alert('finished');}
},1200);););}
this is a approch how call function after execution of other in settimeout
I use both setTimeout() and setInterval() to do this and then clear the interval after 5 executions. If you want them to all end on a certain color or any other modifications let me know! I just modified it to loop through how you asked.
http://jsfiddle.net/sLzGc/9/
sampleFunction();
function sampleFunction() {
alert('Start');
$('#option1').addClass('disabled');
var i = 0;
var shift = function() {
setTimeout(function() {
$('#option1').toggleClass('disabled');
$('#option2').toggleClass('disabled');
}, 0);
setTimeout(function() {
$('#option2').toggleClass('disabled');
$('#option3').toggleClass('disabled');
}, 400);
setTimeout(function() {
$('#option3').toggleClass('disabled');
$('#option1').toggleClass('disabled');
}, 800);
};
var interval = setInterval(function() {
++i;
if (i == 5) {
clearTimeout(interval);
alert('Finished');
} else {
shift();
}
}, 1200);
shift();
}​

How to create a looped animation with JQuery

I have been sitting on this for a few hours and cannot figure this out. I am trying to create an slideshow (3 slides) that loops endlessly. Each slide is a li inside #slideshow. I have walked through this with a debugger and all variables get set correctly, but I don't understand why the animations dont actually happen. I have this which ends up displaying all images on the page:
$(document).ready(function() {
$slideshow = $('#slideshow');
$slideshowItems = $slideshow.find('li');
$slideshowItems.hide();
nextI = function(x) {
if ((x+1) < $slideshowItems.length) {
return x+1;
}
else {
return 0;
}
}
animation = function(i) {
$slideshowItems.eq(i).fadeIn(500).delay(1000).fadeOut(500, animation(nextI(i)));
}
animation(0);
If I do:
$slideshowItems.eq(0).fadeIn(500).delay(1000).fadeOut(500,
$slideshowItems.eq(1).fadeIn(500).delay(1000).fadeOut(500,
$slideshowItems.eq(2).fadeIn(500).delay(1000).fadeOut(500));
This works as expected, but it seems ugly and does not loop.
Any idea why I can't get this to work? I feel it is something with my expectations of how JQuery/ JS modifies the DOM or the sequence that the browser uses to execute animations. Thank you for the help!
var $slideshowItems = $('#slideshow').find('li'),
i = 0;
(function loop() {
$slideshowItems.eq( i ).fadeIn(500).delay(1000).fadeOut(500, loop);
i = ++i % $slideshowItems.length;
})();
JSFIDDLE DEMO
You should specify a callback method but your "animation(nextI(i))" returns nothing, so nothing remains to do after the fade out is complete.
Something like this I think will work:
var animation = function(i) {
$slideshowItems.eq(i).fadeIn(500).delay(1000).fadeOut(500, function (){
animation(nextI(i));
});
}
I would try setting that as a function and then using setInterval:
setInterval(function(){
$slideshowItems.eq(0).fadeIn(500).delay(1000).fadeOut(500, function() {
$slideshowItems.eq(1).fadeIn(500).delay(1000).fadeOut(500, function() {
$slideshowItems.eq(2).fadeIn(500).delay(1000).fadeOut(500);
});
});
}, 6000); // 6000 milliseconds before loops

Categories