0

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.

1

2 Answers 2

3

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);
}

// ...
Sign up to request clarification or add additional context in comments.

2 Comments

This helped me a lot thank you! I am not familiar with what you just did. can you tell me the name of the technique, so that I can look it up?
It is called a javascript closure @FrankieDee
0

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);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.