Reputation: 199
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.net/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.com/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>
Upvotes: 1
Views: 12612
Reputation: 1701
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.com/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
Upvotes: 1
Reputation: 5732
setTimeout
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.
Upvotes: 2
Reputation: 7474
This is what you want: http://jsfiddle.net/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','');
}
Upvotes: 1