I need a script for my website in which there will be a paragraph provided to our visitor. He will be asked for his reading rate like words per minute he can read. Then according to this asked rate the words in that particular paragraph will get highlighted.
yehtech 0 Newbie Poster
Dani AI
Generated
's two prototypes provide a clear, working demo for 's request: a simple one-shot highlighter and a timed "karaoke" highlighter. Those posts are a helpful learning step, but they rely on treating the paragraph as a single HTML string. That string-based approach will break when the paragraph contains inline markup, nested tags, non‑breaking spaces, or event-bound elements. Production-grade behavior calls for a DOM-aware solution.
A robust strategy (high level):
- Walk the element's text nodes (TreeWalker/NodeIterator) rather than using innerHTML string split.
- Tokenize each text node into word and spacer tokens while preserving punctuation and whitespace.
- Build wrapped tokens (spans with data attributes) via DocumentFragment and replace nodes—this avoids destroying listeners and fragile markup.
- Convert user WPM to words per tick (for a tick interval tickMs):
Math.max(1, Math.round(wpm * tickMs / 60000)). - Advance the highlighted window by toggling a CSS class on the wrapped spans (update a small set of elements each tick rather than rebuilding the whole HTML).
Accessibility, UX and perf notes:
- Expose start/stop controls, keyboard shortcuts and an ARIA live region so screen readers receive progress updates.
- Use a visible focusable control to pause/resume; make highlight contrast meet contrast guidelines.
- For very long text, consider wrapping only the visible range (virtualize) to reduce DOM size.
- Avoid repeated innerHTML rewrites — they reparse markup, remove handlers, and cause extra reflow.
Recommended reading (practical, modern):
- MDN JavaScript and DOM guides: https://developer.mozilla.org/en-US/docs/Web/JavaScript
- DOM helpers: TreeWalker and Range
- DocumentFragment: https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment
- Tutorials/books: https://eloquentjavascript.net/ and https://github.com/getify/You-Dont-Know-JS
The thread's examples are an excellent starting point; for a reliable, accessible widget, move from string-manipulation to DOM-node tokenization and small-class updates.
Recommended Answers
Jump to Post— Airshow 425<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Airshow :: Highlight words</title> <style type="text/css"> #para { margin:0 0 012px 0; width:400px; padding:10px; border:1px solid #999999; font-family:vaerdana,arial; font-size:11pt; } …
Jump to Post— Airshow 425Yehtech,
Even better, try this version with bug fix for Opera/Firefox, which for some reason behave slightly differently from IE. Probably in
replace().<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
All 6 Replies
Airshow 425 WiFi Lounge Lizard Team Colleague
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Airshow :: Highlight words</title>
<style type="text/css">
#para { margin:0 0 012px 0; width:400px; padding:10px; border:1px solid #999999; font-family:vaerdana,arial; font-size:11pt; }
.highlight { background-color:yellow; }
</style>
<script>
function highlightText(){
var p = document.getElementById('para');//Get the text div
var r = document.getElementById('readingRate');//Get the reading rate
if(!p || !r) { return; }//exit the function if
var txt = p.innerHTML;//Get the text
var rr = parseInt(r.value);//Get the reading rate value
//Apply algorithm here as necessary to multiply/divide/add/subtract the user's value into what you actually want, eg ...
//rr = rr * 4;
//or just let the user value pass through with no algorithm.
var openingTag = '<span class="highlight">';//used to start the highlight
var closingTag = '</span>';//used to terminate the highlight
var openingTagPattern = /<span class=.?highlight.?>/i;//Used to remove the highlight start tag
var closingTagPattern = /<\/span>/i;//Used to remove the highlight end tag
txt = txt.replace(openingTagPattern, '').replace(closingTagPattern, '');//Remove existing span tags
var txtArray = txt.split(' ');// Each word is now an element in an array.
txtArray = txtArray.slice(0, rr).concat([closingTag]).concat(txtArray.slice(rr));// ... and closing tag after n words.
p.innerHTML = openingTag + txtArray.join(' ');
}
</script>
</head>
<body>
<div id="para">
I need a script for my website in which there will be a paragraph provided to our visitor. He will be asked for his reading rate like words per minute he can read. Then according to this asked rate the words in that particular paragraph will get highlighted.
</div>
Reading rate <input id="readingRate" value="" size="5">
<input type="button" onclick="highlightText();" value ="Go">
</body>
</html> Airshow 425 WiFi Lounge Lizard Team Colleague
Yehtech,
Even better, try this version with bug fix for Opera/Firefox, which for some reason behave slightly differently from IE. Probably in replace() .
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Airshow :: Highlight words</title>
<style type="text/css">
#para { margin:0 0 012px 0; width:400px; padding:10px; border:1px solid #999999; font-family:vaerdana,arial; font-size:11pt; }
.highlight { background-color:yellow; }
</style>
<script>
function highlightText(){
var p = document.getElementById('para');//Get the text div
var r = document.getElementById('readingRate');//Get the reading rate
if(!p || !r) { return; }//exit the function if either element is not found
var txt = p.innerHTML;//Get the text
var rr = (!r || r.value === '') ? 0 : parseInt(r.value);//Get the reading rate value
//Apply algorithm here as necessary to multiply/divide/add/subtract the user's value into what you actually want, eg ...
//rr = rr * 4;
//or just let the user value pass through with no algorithm.
var openingTag = '<span class="highlight">';//used to start the highlight
var closingTag = '</span>';//used to terminate the highlight
var openingTagPattern = /<span class=.?highlight.?>/i;//Used to remove the highlight start tag
var closingTagPattern = /<\/span>/i;//Used to remove the highlight end tag
txt = txt.replace(openingTagPattern, '').replace(closingTagPattern, '').replace(' ', ' ');//Remove existing span tags and double spaces
var txtArray = txt.split(' ');// Each word is now an element in an array.
txtArray = txtArray.slice(0, rr).concat([closingTag]).concat(txtArray.slice(rr));// Add closing tag after rr words.
p.innerHTML = openingTag + txtArray.join(' ');// Prepend opening tag to re-joined text and insert back in its div.
}
</script>
</head>
<body>
<div id="para">
I need a script for my website in which there will be a paragraph provided to our visitor. He will be asked for his reading rate like words per minute he can read. Then according to this asked rate the words in that particular paragraph will get highlighted.
</div>
Reading rate <input id="readingRate" value="" size="5">
<input type="button" onclick="highlightText();" value ="Go">
</body>
</html> Airshow
yehtech 0 Newbie Poster
dude thanks for this script....i want also that after 1 minute the next words get selected according to the entered rate....
like see
for example
Paragraph:
My name is yehtech. I am a man.
in this paragraph if user enters 2 words per minute then firstly
My name is yehtech. I am man.
then after one min this changes to
My name is yehtech. I am man.
then after one min again
My name is yehtech. I am man.
Airshow 425 WiFi Lounge Lizard Team Colleague
Aha, you should have said - it's Karaoke! :D
You'll like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Airshow :: Highlight words</title>
<style type="text/css">
.para { margin:12px 0 012px 0; width:400px; padding:10px; border:2px solid #999999; font-family:vaerdana,arial; font-size:11pt; }
.highlight { background-color:yellow; }
</style>
<script>
function highlightText(){
var p = document.getElementById('para');//Get the text div
var r = document.getElementById('readingRate');//Get the reading rate
if(!p || !r) { return; }//exit the function if either element is not found
var txt = p.innerHTML;//Get the text
var rr = (!r || r.value === '') ? 0 : parseInt(r.value);//Get the reading rate value
//Apply algorithm here as necessary to multiply/divide/add/subtract the user's value into what you actually want, eg ...
//rr = rr * 4;
//or just let the user value pass through with no algorithm.
var openingTag = '<span class="highlight">';//used to start the highlight
var closingTag = '</span>';//used to terminate the highlight
var openingTagPattern = /<span class=.?highlight.?>/i;//Used to remove the highlight start tag
var closingTagPattern = /<\/span>/i;//Used to remove the highlight end tag
txt = txt.replace(openingTagPattern, '').replace(closingTagPattern, '').replace(' ', ' ');//Remove existing span tags and double spaces
var txtArray = txt.split(' ');// Each word is now an element in an array.
txtArray = txtArray.slice(0, rr).concat([closingTag]).concat(txtArray.slice(rr));// Add closing tag after rr words.
p.innerHTML = openingTag + txtArray.join(' ');// Prepend opening tag to re-joined text and insert back in its div.
}
var Highlighter = function (){
var allow=false, t=null, pos=0, p=null, r=null, txt='', txtArray=[];
var openingTag = '<span class="highlight">';// Used to start the highlight
var closingTag = '</span>';// Used to terminate the highlight
var openingTagPattern = /<span class=['"]?highlight['"]?>\s?/i;// Used to remove the highlight start tag
var closingTagPattern = /<\/span>\s?/i;// Used to remove the highlight end tag
var get = function() { txt = p.innerHTML; };
var remove = function() {
txt = txt.replace(openingTagPattern, '').replace(closingTagPattern, '').replace(' ', ' ');
};//Remove existing span tags and reduce double spaces
var split = function() { txtArray = txt.split(/ /); };// Each word is now an element in an array.
var write = function() {
p.innerHTML = txtArray.join(' ');
};// Re-joined text and insert back in its div.
var setAllow = function(bool) {
allow = bool;
p.style.borderColor = (bool) ? 'blue' : '#999999';
};
return {
init : function() {
p = document.getElementById('para2');// Get the text div
r = document.getElementById('readingRate2');// Get the reading rate
},
highlight : function() {
clearTimeout(t);// In case there's another call up the spout.
if(!p || !r) { return; }// Exit the function if either element is not found
var rr = (!r || r.value === '') ? 0 : parseFloat(r.value);// Get the reading rate value
get();
remove();
split();
txtArray = txtArray.slice(0, pos)
.concat([openingTag])
.concat(txtArray.slice(pos, pos+rr))
.concat([closingTag])
.concat(txtArray.slice(pos+rr));// Insert highlight tags
write();
if(allow && (pos+rr)<txtArray.length) {
pos += rr;
t = setTimeout('Highlighter.highlight()', 1000);//Set to 60000 for one minute intervals
}
else {
Highlighter.stop();
Highlighter.reset();
}
},
start : function() {
setAllow(true);
t = null;
Highlighter.highlight();
},
stop : function() {
setAllow(false);
clearTimeout(t);
},
reset : function() {
pos = 0;
get();
remove();
split();
write();
}
};
}();
onload = function(){
Highlighter.init();
}
</script>
</head>
<body>
<div id="para" class="para">
I need a script for my website in which there will be a paragraph provided to our visitor. He will be asked for his reading rate like words per minute he can read. Then according to this asked rate the words in that particular paragraph will get highlighted.
</div>
Reading rate <input id="readingRate" value="" size="5">
<input type="button" onclick="highlightText();" value ="Go">
<div id="para2" class="para">
In the town where I was born <br>
Lived a man who sailed the seas <br>
And he told us of his life <br>
In the <b>land of</b> submarines <br>
So we sailed up to the sun <br>
Till we found the sea of green <br>
And we lived beneath the waves <br>
In our yellow submarine <br>
We all <b>live in a</b> yellow submarine <br>
Yellow submarine, yellow submarine <br>
We all live in a yellow submarine <br>
Yellow submarine, yellow submarine
</div>
Reading rate <input id="readingRate2" value="2" size="5">
<input type="button" onclick="Highlighter.start();" value ="Start">
<input type="button" onclick="Highlighter.stop();" value ="Stop">
<input type="button" onclick="Highlighter.reset();" value ="Reset">
</body>
</html> Tested in IE6, FF 3.0.10, Opera 9.01 .
Note that the code doesn't like HTML markup. I found that I could get away with <br>s but only with spaces before them. Just about any other markup breaks the text with random unpredictable results.
With more time the code could be improved to handle markup but for now avoid it. Maybe someone can offer improvements to my code. There may be a wholly RegExp solution, not involving .split() .join()?
Timing is set to 1000 milliseconds (one second) for debugging. Set to 60000 for one minute. The line has a comment against it.
Airshow
yehtech 0 Newbie Poster
thanks Airshow....its awesome....i loved it.....good job man...i think u r an expert at javascript....
can u guide me where i can learn advanced javascript from....
Airshow 425 WiFi Lounge Lizard Team Colleague
Yehtech,
Just pleased to know you're happy with it.
can u guide me where i can learn advanced javascript from....
Simple. Read and watch everything by Douglas Crockford.
And enjoy every minute of it.
Airshow
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.