Reputation: 61
Hi I am trying to write code for an image to change every second depending on what is stored in an array. Heres what I have so far:
function parse_input(){
//initializes the input_text and the text_array variables
var input_text=document.getElementById('input_text').value;
var text_array=[];
//loops through input_text and if it is an alphanumeric character...pushes it to the text_array
for(var letter in input_text){
const LETTER_REGEX=/^[a-zA-Z0-9]+$/;
if(LETTER_REGEX.test(input_text[letter])){
text_array.push(input_text[letter]);
}
}
//function to change the image
function change_image(array){
document.getElementById('letter_image').src="images/"+array+".png";
document.getElementById('letter_image').alt=array;
}
//supposed to loop through the text_array and change the image every second.
for(var i=0;i<text_array.length;i++){
setTimeout(function(){change_image(text_array[i])},1000*i);
}
}
window.onload=function(){
document.getElementById('finger_spell_it').onclick=function(){
parse_input();
}
}
When I go to run the test I get an undefined variable. I don't know what I am doing wrong please help.
Upvotes: 0
Views: 86
Reputation: 8080
You need closure
. This is elaborately explained here:
That is a closure. A function doesn't have to return in order to be called a closure. Simply accessing variables outside of your immediate lexical scope creates a closure.
function foo(x) { var tmp = 3; return function (y) { alert(x + y + (++tmp)); } } var bar = foo(2); // bar is now a closure. bar(10);
The above function will also alert 16, because bar can still refer to x and tmp, even though it is no longer directly inside the scope.
for your code example:
for(var i=0;i<text_array.length;i++){
(function(index){
setTimeout(function(){
change_image(text_array[index])
}, 1000 * index);
})(i);
}
closure can also be created using thirdparty tollboxes like jQuery proxy:
for(var i=0;i<text_array.length;i++){
setTimeout($.proxy(function(index){
change_image(text_array[index])
}, this, i)
, 1000*i);
}
or using underscore.js bind
for(var i=0;i<text_array.length;i++){
setTimeout(_.bind(function(index){
change_image(text_array[index])
}, this, i)
, 1000*i);
}
Upvotes: 0
Reputation: 3933
When your setTimeout
runs, i
is already at an undefined index.
You need to create a scope for it:
// ...
for(var i=0;i<text_array.length;i++){
(function(index){
setTimeout(function(){
change_image(text_array[index])
}, 1000 * index);
})(i);
}
// ...
Upvotes: 3