Question

Good day: I am creating a small and simple software to spell words letter by letter, I can make it spell a letter, but so far I have not managed to make it spell the word letter after letter. And the problem is that I have not managed to understand how the time functions work in javascript. I have two function the following that says a letter and it work fine:

    //play the sound
    function playSound(soundfile) {
      document.getElementById("dummy").innerHTML= 
              "<embed src='"+soundfile+"' hidden='true' autostart='true' loop='false' />";          
    }

and another one that is supposed to call this function every 2 and a half seconds to say the next letter until the word is finished, but I have tried a few functions and nothing seems to work for me. I just need a function that waits for 2500 milliseconds and calls again the next function with the next letter of the word to spell.

 function timingSpell (i){
        if (i == 0){
            var wordToSpell = document.getElementById("WordToSpell");
            var aux = wordToSpell.value;
        }
        var myVar=setInterval(function(){playSound('sounds/'+aux[i]+'.mp3')},2500);
        i++;
        timingSpell(i);                        
    }

WordToSpell is a textfielf with a word as value. What is happening now is that is saying only the last letter of the word. If any one can give any Idea about how to make javascript wait for some time before executing a function again, I would appreciate it. Thank you in advanced.

Was it helpful?

Solution

You might try something like this. Using setTimeout is considered better than setInterval because of the screwy ways that JS's event loop works. For the purposes of this example I'm passing in the word and div where the word is meant to appear as parameters to the readWord function.

The function sets up some variables and a named anonymous function (yes) in order for the setTimeout to work. The readLetter function immediately invokes when the function is first run, and then relies on the setTimeout to continue. The important thing here is to check whether the letter count is less that the number of letters in the word.

var word = 'foshizzle';
var div = document.getElementById('div');

function readWord(word, el) {
  var pos = 0;
  var duration = 2500;
  var text = '';
  var readLetter = (function readLetter () {
    if (pos < word.length) {
        var letter = word.substr(pos, 1);

        // show or say letter here
        playSound('sounds/' + letter + '.mp3')
        text += letter;
        div.innerHTML = text;
        pos++;
        setTimeout(readLetter, duration);
    }
  })();
}

readWord(word, div);

Demo

OTHER TIPS

Try changing timingSpell to this:

function timingSpell (){
    var wordToSpell = document.getElementById("WordToSpell");
    var aux = wordToSpell.value;
    var i=0;

    var myInterval = setInterval(function(){
        playSound('sounds/'+aux[i]+'.mp3');
        alert(i + '' + aux[i]);
        i++;
        if(typeof aux[i] === "undefined"){
            clearInterval(myInterval);
        }

    },2500);
}

There are a few things worth looking at here:

  • having a function unconditionally calling itself is a potential indicator of recursive function calling (leading to a stackoverflow error!)
  • You should declare i at the start of your function, and not just hope it is 0.
  • Increment inside your setInterval function, not outside (otherwise your computer will have incremented through the loop before 2.5 seconds
  • Use clearInterval when you've reached the end of your word.

switch the function timingSpell to:

function play() {
    var wordToSpell = document.getElementById("WordToSpell");
    var aux = wordToSpell.value;

    function timingSpell(i) {
        if (i >= aux.length) {
            return;
        }
        var myVar = setTimeout(function () {
            playSound('sounds/' + aux[i] + '.mp3');
            i++;
            timingSpell(i);
        }, 2500);
    }
    timingSpell(0);
}

the new function use recursion.

The answer from @Andy helped a lot, this is the way that it's currently working fine:

     //read a full wod.
    function readWord() {
      var word = document.getElementById('WordToSpell').value;
      var pos = 0;
      var duration = 2500;
      var text = '';
      var readLetter = (function readLetter () {
        if (pos < word.length) {
            var letter = word.substr(pos, 1);
            // show or say letter here
            playSound('sounds/' + letter + '.mp3');
            //text += letter;
            //div.innerHTML = text;
            pos++;
            setTimeout(readLetter, duration);
        }
      })();
    } 

The only modifications from the original are minimal, just to addap it to my current specific problem. Any way I appreciate the other answers as well they are also pretty simmilar to what I need, thank you Guys... I appreciate your help.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top