Reputation: 10558
I am using the setTimeout
and clearTimeout
functions to highlight words in a textarea
element at certain specified intervals. The steps I am following are:
textarea
element. textarea
element every 5 seconds. The code is:
<html>
<head>
<script type="text/javascript">
/* this function does the folloeing:
* 1. takes all the words in the textarea.
* 2. Separates them into words.
* 3. Iterate through the list of words.
* 4. Search and highlight each word for 1 second.
*/
var highlightBtn = document.getElementById("start");
var continueHighlight = false;
var text;
var highlighter;
var words;
function startHighlight(val) {
continueHighlight = val;
console.log("Highlight = " + continueHighlight);
//1. get words within textarea.
var textarea = document.getElementById("inputText");
text = textarea.value;
console.log("text = " + text);
//2. split text into words.
var words = text.split(' ');
console.log("There are " + words.length + " words in the text.");
//highlight();
if(continueHighlight) {
//3. iterate through list of words.
var i = 0;
while(i < words.length) {
highlighter = setTimeout(searchAndHighlight, 5000, words[i]);
//console.log("Word highlighting = " + words[i]);
i = i + 1;
}
} else {
console.log("Stopping highlighting.");
clearTimeout(highlighter);
}
}
function highlight() {
if(continueHighlight) {
//3. iterate through list of words.
var i = 0;
while(i < words.length) {
highlighter = setTimeout(searchAndHighlight, 5000, words[i]);
//console.log("Word highlighting = " + words[i]);
i = i + 1;
}
} else {
console.log("Stopping highlighting.");
clearTimeout(highlighter);
}
}
function searchAndHighlight(word) {
console.log("Highlighting word = " + word);
var output = document.getElementById("output");
output.value = word;
}
</script>
</head>
<body>
<textarea id="inputText"></textarea>
<br/>
<button id="start" onclick="startHighlight('true')">Start!</button>
<br/>
<button id="stop" onclick="startHighlight('false')">Stop!</button>
<br/>
<textarea id="output"></textarea>
</body>
</html>
I expected every word to be displayed in the second textarea
every 5 seconds. This is not happening. Instead, I get nothing for 5 seconds and then all words in quick succession. This happens even if I press the stop button. My questions:
Where am I going wrong in using the setTimeout
function?
Upvotes: 0
Views: 385
Reputation: 798
Here is a solution that fixes the stop button problem. If you keep track of i, you could also have the highlight function resume where it left off.
<html>
<head>
<script type="text/javascript">
/* this function does the folloeing:
* 1. takes all the words in the textarea.
* 2. Separates them into words.
* 3. Iterate through the list of words.
* 4. Search and highlight each word for 1 second.
*/
var highlightBtn = document.getElementById("start");
var continueHighlight = false;
var text;
var highlighter;
var words;
function startHighlight(val) {
continueHighlight = val;
console.log("Highlight = " + continueHighlight);
//1. get words within textarea.
var textarea = document.getElementById("inputText");
text = textarea.value;
console.log("text = " + text);
//2. split text into words.
var words = text.split(' ');
console.log("There are " + words.length + " words in the text.");
//highlight();
//3. iterate through list of words.
var i = 0;
highlighter = setTimeout( function( ){
searchAndHighlight( words, 0 );
}, 5000);
function searchAndHighlight(words, i ) {
if(i >= words.length){
clearTimeout(highlighter);
}else{
console.log("Highlighting word = " + words[i]);
var output = document.getElementById("output");
output.value = words[i];
i++;
highlighter = setTimeout( function( ){
searchAndHighlight( words, i );
}, 5000);
}
}
}
function stopHighlight(){
console.log("Stopping highlighting.");
clearTimeout(highlighter);
}
</script>
</head>
<body>
<textarea id="inputText"></textarea>
<br/>
<button id="start" onclick="startHighlight()">Start!</button>
<br/>
<button id="stop" onclick="stopHighlight()">Stop!</button>
<br/>
<textarea id="output"></textarea>
</body>
</html>
Upvotes: 1
Reputation: 707318
This piece of code:
var i = 0;
while(i < words.length) {
highlighter = setTimeout(searchAndHighlight, 5000, words[i]);
//console.log("Word highlighting = " + words[i]);
i = i + 1;
}
is rapidly calling setTimeout()
a bunch of times in a row and setting them all for the same time. That will match your symptoms of waiting 5 seconds and then running them all at once.
You will either have to set each successive timeout for a longer period of time or change the structure of the code to not start the next timer until the first one fires.
Here's how you could solve it by only setting one setTimeout()
at a time. This would also solve the stop button problem:
function highlight() {
if(continueHighlight) {
var i = 0;
function next() {
if (i < words.length) {
highlighter = setTimeout(function() {
searchAndHighlight(words[i]);
i++;
next();
}, 5000);
}
}
next();
} else {
console.log("Stopping highlighting.");
clearTimeout(highlighter);
}
}
When you want to stop the progressive highlighting, I don't understand why you're taking such a circuitous route. You should just call the clearTimeout(highlighter)
. There's no need to go through multiple functions like you're doing just to do that.
Or, the solution that sets successively longer timers could work like this:
var i = 0;
while(i < words.length) {
highlighter = setTimeout(searchAndHighlight, 5000 * (i+1), words[i]);
//console.log("Word highlighting = " + words[i]);
i = i + 1;
}
If you want to use this type of solution, then to fix the stop button problem, you will have to keep all the timer ids in an array and cancel all of them. Personally, I'd probably restructure the code and only have one setTimeout()
in flight at a time and when each one fires you kick off the next one. Then, you only have one setTimeout()
going at once so it's simpler to cancel.
Upvotes: 1