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.

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):

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

All 6 Replies

<!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&nbsp;<input id="readingRate" value="" size="5">&nbsp;
<input type="button" onclick="highlightText();" value ="Go">
</body>
</html>

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&nbsp;<input id="readingRate" value="" size="5">&nbsp;
<input type="button" onclick="highlightText();" value ="Go">
</body>
</html>

Airshow

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.

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&nbsp;<input id="readingRate" value="" size="5">&nbsp;
<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&nbsp;<input id="readingRate2" value="2" size="5">&nbsp;
<input type="button" onclick="Highlighter.start();" value ="Start">&nbsp;
<input type="button" onclick="Highlighter.stop();"  value ="Stop">&nbsp;
<input type="button" onclick="Highlighter.reset();" value ="Reset">&nbsp;

</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

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....

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.