1

I have an array of words and I would like to change a div tag to each word in sequence with a delay.

<script>
    function printWord(w) {
    setTimeout(function() {
        $("#word").text(w);
        }, 1000);

     }

function readBook() {
    var array = $("#offscreen_text").text().toString().split(/[\s\n]+/);
    for (i =1; i < array.length; i++){
        printWord(array[i]);
    }

}
</script>
<body onload="readBook()">
<div id="word"></div>
<div id="offscreen_text">hi hello bye goodbye this is a test with some random text</div>
</body>

When I run readBook() nothing seems to be happening.

5
  • Where do you run readBook()? Commented Feb 16, 2015 at 4:22
  • i have it in body, onload. it's not in the code. i'll add it now. Commented Feb 16, 2015 at 4:25
  • 1
    if you're going to add jQuery to do something so simple, why not actually make use of it? Commented Feb 16, 2015 at 4:29
  • ok..... do you have an example or solution or just a comment? Commented Feb 16, 2015 at 4:30
  • @Alex, challenge accepted. Commented Feb 16, 2015 at 4:57

8 Answers 8

6

You can use setInterval without using a for loop.

function readBook() {
    var array = $("#offscreen_text").text().toString().split(/[\s\n]+/);
    var i=0;
    setInterval(function(){
        $("#word").text(array[i]); i++;    
    },1000);   
}

Demo : http://jsfiddle.net/sywzno5p/

Edit Fiddle with clearInterval() : http://jsfiddle.net/gn6eh7t1/

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

2 Comments

@AlexanderO'Mara : Should I add it inside setInterval()? Can you correct the fiddle please ?
@AlexanderO'Mara : That's what I asked. Thanks :)
3

Array indices are 0-based.

for (i = 1; i < array.length; i++)

should be

for (i = 0; i < array.length; i++)
//       ^

printWord(w)

doesn't account for a successive delay. The first time it's called, it'll tell the script to wait 1000ms before continuing, and every successive call (which will happen at approximately 1ms after the previous call) will also wait 1000ms. What this means is that the script will wait approximately 1 second before showing the last word.

If you're going to keep using setTimeout change the function to something along the lines of:

function printWord(w, d) {
    setTimeout(function() {
        $("#word").text(w);
    }, 1000 * d);
}

You're using jQuery as a dependency. Read the API and USE IT, or drop the dependency.

.text() always returns a string. .toString() is unnecessary. Get rid of it.

$("#offscreen_text").text().toString().split(/[\s\n]+/);
//                         ^^^^^^^^^^^

Also, \s matches \n, so [\s\n] is redundant. Simplify to /\s+/

jQuery(function ($) {}) is the aliasing short-hand for document.ready, which is the appropriate way to call readBook:

function readBook($) {
    ...
}

jQuery(readBook);

setTimeout has no queueing behavior. Use delay(1000) and queue(fn):

function printWord(w) {
    $('#word').delay(1000).queue(function (next) {
        $(this).text(w);
    });
}

You made a mistake iterating with a simple for loop. jQuery has a utility $.each method which would have prevented such a simple error:

$.each(array, function (index, value) {
    ...
});

All together now

jQuery(function ($) {
  var words;
  words = $('#offscreen_text').text().split(/\s+/);
  $.each(words, function (i, word) {
    $('#word').delay(1000).queue(function (next) {
      $(this).text(word);
      next();
    });
  });
});
#offscreen_text {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="word"></div>
<div id="offscreen_text">hi hello bye goodbye this is a test with some random text</div>

2 Comments

@AlexanderO'Mara, i'm getting there
This was a good answer with a lot of useful stuff in it, not sure why you didn't get more up votes
1

See http://jsfiddle.net/ta9q32v7/

function readBook() {
    var array = $("#offscreen_text").text().toString().split(/[\s\n]+/);
    var i = 0;
    setInterval(function(){ $("#word").text(array[i % array.length]); i++;}, 1000);
}

readBook();

Comments

1

You are calling the printWord function over and over without giving it time to execute the code, so each time it runs, it overwrites the previous run, giving it only chance to print the last word...

I modified your code to be a single function that only calls itself when it knows that there are more words to be "read".

I declared the array in the global scope as well as the iterator for the word count. the function readBook will increment the iterator once a word has been 'read'.

Please run the code snippet.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="word"></div>
<div id="offscreen_text">hi hello bye goodbye this is a test with some random text</div>
<script>
  var i = 0;
  var array = $("#offscreen_text").text().toString().split(/[\s\n]+/);

  function readBook() {

    $("#word").text(array[i]);
    i++;
    if (i < array.length) {
      setTimeout(readBook, 1000);
    }


  }



  readBook();
</script>

Comments

1

The Problems:

  1. All the printWord calls are made at the same time, so every setInterval call within the function will fire at roughly the same time.
  2. Array indexes start at 0, so i =1 will skip the first word.
  3. While not a problem so much as it is unpleasant, you don't need to use onload when using jQuery, you can use jQuery's document.ready.
  4. Also, there is no need to call .toString() on $("#offscreen_text").text(), since jQuery.text will always return a string, even if no elements are selected.

A Solution:

You could use a setTimeout-based loop to iterate over the words.

$(function() {//document.ready wrapper (no need for onload).
  function readBook() {
    var array = $("#offscreen_text").text().split(/[\s\n]+/);
    var wordIndex = 0;//Keep track of the word to show.
    var nextWord = function() {
      if (wordIndex < array.length) {//Check if there are more words to show.
        $("#word").text(array[wordIndex]);//Set the word.
        setTimeout(nextWord, 1000);//Set the next word timeout.
        wordIndex++;//Increment the word counter.
      }
    }
    nextWord();//Start the word loop.
  }
  readBook();
});
#offscreen_text {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="word"></div>
<div id="offscreen_text">hi hello bye goodbye this is a test with some random text</div>

Comments

1

I have created a jsfiddle with a solution for you. The readBook() method was not being called. If you did call it with it written the way you have it it would seem as though it only did the last word of the array because the setTimeoutswould all happen at once since they all were called while the loop was being iterated (nearly at the same time)... to fix this i simply added a multiplier to the timeout for how far in the loop you are. This solution is probably not very efficient though since it will set as many timeouts as there are words.

also, you have i=1 which others have stated will skip the first word of the array.

http://jsfiddle.net/782pmv64/2/

function printWord(w, i) {
  setTimeout(function() {
    $("#word").text(w);
    }, 800 * i);
}

Comments

0

Don't like to over complicating things like this, solution could be as easy as

function printWord(word,index,life) {
    setTimeout(function() {
         $("#word").text(word);
    }, index*life);

}

function readBook() {
    var array = $("#offscreen_text").text().split(/[\s\n]+/);

    for (i =0; i < array.length; i++){
        printWord(array[i],i,1000);
    }

}

$(readBook);

Basically you are having the time that the action takes place occur X amount of time after the previous

also this is something that can be done without using jQuery

 function printWord(w,i,life) {

    setTimeout(function() {
        document.getElementById("word").innerText = w;
    }, i*life);

 }

function readBook() {
    var array = document.getElementById("offscreen_text").innerText.split(/[\s\n]+/);

    for (i =0; i < array.length; i++){
        printWord(array[i],i,1000);
    }

}

document.addEventListener('DOMContentLoaded', readBook);

Comments

0

Everything is happening at once. I passed in the index value i to multiply by the 1000ms.

<!DOCTYPE html>
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
</head>
<body onload="readBook()">
<div id="word"></div>
<div id="offscreen_text">hi hello bye goodbye this is a test with some random text</div>
<div id="sentence">This is some sentence that has the word is.</div>
<script>
    function printWord(w,i) {
    setTimeout(function() {
        $("#word").text(w);
        }, 1000*i);

     }

function readBook() {
    var array = $("#offscreen_text").text().toString().split(/[\s\n]+/);
    for (i =0; i < array.length; i++){
        printWord(array[i],i);
    }

}
</script>
</body>
</html> 

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.