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>
readBook()?