I'm trying to get a row of letters to light up one by one using Javascript/jquery. I created an array using span elements and am looping over each letter to first change its color red and then back to black again. The problem is that the $.each loop function doesn't wait for setTimeout to finish...it loops over all of them instantly making them all turn red instantly instead of one by one. Any ideas how to fix this? Here is my code:
JSFiddle: /
var array = $(".one");
var doIt = function () {
$.each(array, function(index, value){
array.eq(index).css('color','red');
setTimeout(function(){
array.eq(index).css('color','black');
}, 500);
});
};
doIt();
P {
color:black;
}
<script src=".11.1/jquery.min.js"></script>
<p>
<span class="one">H</span><span class="one">e</span><span class="one"></span><span class="one">l</span><span class="one">l</span><span class="one"></span><span class="one">o</span><span class="one"> M</span><span class="one"></span><span class="one">y </span><span class="one">N</span><span class="one"></span><span class="one">a</span>
</p>
I'm trying to get a row of letters to light up one by one using Javascript/jquery. I created an array using span elements and am looping over each letter to first change its color red and then back to black again. The problem is that the $.each loop function doesn't wait for setTimeout to finish...it loops over all of them instantly making them all turn red instantly instead of one by one. Any ideas how to fix this? Here is my code:
JSFiddle: http://jsfiddle/john23/8chu18k9/
var array = $(".one");
var doIt = function () {
$.each(array, function(index, value){
array.eq(index).css('color','red');
setTimeout(function(){
array.eq(index).css('color','black');
}, 500);
});
};
doIt();
P {
color:black;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>
<span class="one">H</span><span class="one">e</span><span class="one"></span><span class="one">l</span><span class="one">l</span><span class="one"></span><span class="one">o</span><span class="one"> M</span><span class="one"></span><span class="one">y </span><span class="one">N</span><span class="one"></span><span class="one">a</span>
</p>
Share
Improve this question
edited Jan 26, 2015 at 17:57
taesu
4,5805 gold badges26 silver badges41 bronze badges
asked Jan 26, 2015 at 17:26
John23John23
1992 gold badges6 silver badges15 bronze badges
1
- 1 you should set the timeout properly while doing so.. try to set it like this setTimeout(....., 500 * (index +1)); ............ The problem in existing logic is that it is setting timeout for all characters at same time in loop so even though it is technically setting it for each character separetly, but effect is not recognized due to fast execution. – K D Commented Jan 26, 2015 at 17:33
3 Answers
Reset to default 2setTimeout
is asynchronous. It will return control back to the calling context immediately, so this code will not work as expected. I suggest using setInterval
instead, which runs the same function repeatedly, at the given interval:
var array = $('.one');
var currentIndex = 0;
var intervalId = setInterval(function(){
array[currentIndex].css('color','black');
currentIndex++;
// We've reached the end of the array, stop calling this function
if (currentIndex == array.length) clearInterval(intervalId);
}, 500);
To clarify a little: setInterval
will return an ID. You can then pass that ID to the function clearInterval
to stop the invocation of the function.
This is what you want: http://jsfiddle/8chu18k9/1/
var array = $(".one");
var i = 0;
var doIt = function () {
setTimeout(loopIt, 500)
};
var loopIt = function() {
if(i < array.length) {
console.log("inner loop")
array.eq(i).css('color','red');
if(i > 0) {
array.eq(i-1).css('color','');
}
i++
setTimeout(loopIt, 500)
}
}
doIt();
If you don't want the letters to go back to black, delete:
if(i > 0) {
array.eq(i-1).css('color','');
}
In case you want the setTimeout solution. Here it is.
Html:
<p>
<span class="one">H</span>
<span class="one">e</span>
<span class="one">l</span>
<span class="one">l</span>
<span class="one">o</span>
<span class="one"> M</span>
<span class="one">y </span>
<span class="one">N</span>
<span class="one">a</span>
</p>
<script src="//code.jquery./jquery-1.11.2.min.js"></script>
Css:
P {
color:black;
}
Js:
var delayBase = 10;
var baseDuration = 500; //Time at which each span stays red for
$(document).ready(function(){
$(".one").each(function(){
flash($(this), delayBase, baseDuration);
delayBase+=1000;
});
});
function flash($element, delay, flashDuration){
//set red
setTimeout(function(){
$element.css('color', 'red');
}, delay );
//set black
setTimeout(function(){
$element.css('color', 'black');
}, (delay+flashDuration) );
}
codepen example: http://codepen.io/anon/pen/zxzeKE