Highlight Text Range Using JavaScript

Highlight text range using JavaScript

Below is a function to set the selection to a pair of character offsets within a particular element. This is naive implementation: it does not take into account any text that may be made invisible (either by CSS or by being inside a <script> or <style> element, for example) and may have browser discrepancies (IE versus everything else) with line breaks, and takes no account of collapsed whitespace (such as 2 or more consecutive space characters collapsing to one visible space on the page). However, it does work for your example in all major browsers.

For the other part, the highlighting, I'd suggest using document.execCommand() for that. You can use my function below to set the selection and then call document.execCommand(). You'll need to make the document temporarily editable in non-IE browsers for the command to work. See my answer here for code: getSelection & surroundContents across multiple tags

Here's a jsFiddle example showing the whole thing, working in all major browsers: http://jsfiddle.net/8mdX4/1211/

And the selection setting code:

function getTextNodesIn(node) {
var textNodes = [];
if (node.nodeType == 3) {
textNodes.push(node);
} else {
var children = node.childNodes;
for (var i = 0, len = children.length; i < len; ++i) {
textNodes.push.apply(textNodes, getTextNodesIn(children[i]));
}
}
return textNodes;
}

function setSelectionRange(el, start, end) {
if (document.createRange && window.getSelection) {
var range = document.createRange();
range.selectNodeContents(el);
var textNodes = getTextNodesIn(el);
var foundStart = false;
var charCount = 0, endCharCount;

for (var i = 0, textNode; textNode = textNodes[i++]; ) {
endCharCount = charCount + textNode.length;
if (!foundStart && start >= charCount
&& (start < endCharCount ||
(start == endCharCount && i <= textNodes.length))) {
range.setStart(textNode, start - charCount);
foundStart = true;
}
if (foundStart && end <= endCharCount) {
range.setEnd(textNode, end - charCount);
break;
}
charCount = endCharCount;
}

var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (document.selection && document.body.createTextRange) {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(true);
textRange.moveEnd("character", end);
textRange.moveStart("character", start);
textRange.select();
}
}

How to highlight text using javascript

You can use the jquery highlight effect.

But if you are interested in raw javascript code, take a look at what I got
Simply copy paste into an HTML, open the file and click "highlight" - this should highlight the word "fox". Performance wise I think this would do for small text and a single repetition (like you specified)

function highlight(text) {  var inputText = document.getElementById("inputText");  var innerHTML = inputText.innerHTML;  var index = innerHTML.indexOf(text);  if (index >= 0) {    innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);   inputText.innerHTML = innerHTML;  }}
.highlight {  background-color: yellow;}
<button onclick="highlight('fox')">Highlight</button>
<div id="inputText"> The fox went over the fence</div>

How can I highlight the text of the DOM Range object?

I would suggest using document's or the TextRange's execCommand method, which is built for just such a purpose, but is usually used in editable documents. Here's the answer I gave to a similar question:

The following should do what you want. In non-IE browsers it turns on designMode, applies a background colour and then switches designMode off again.

UPDATE

Fixed to work in IE 9.

UPDATE 12 September 2013

Here's a link detailing a method for removing highlights created by this method:

https://stackoverflow.com/a/8106283/96100

function makeEditableAndHighlight(colour) {
var range, sel = window.getSelection();
if (sel.rangeCount && sel.getRangeAt) {
range = sel.getRangeAt(0);
}
document.designMode = "on";
if (range) {
sel.removeAllRanges();
sel.addRange(range);
}
// Use HiliteColor since some browsers apply BackColor to the whole block
if (!document.execCommand("HiliteColor", false, colour)) {
document.execCommand("BackColor", false, colour);
}
document.designMode = "off";
}

function highlight(colour) {
var range;
if (window.getSelection) {
// IE9 and non-IE
try {
if (!document.execCommand("BackColor", false, colour)) {
makeEditableAndHighlight(colour);
}
} catch (ex) {
makeEditableAndHighlight(colour)
}
} else if (document.selection && document.selection.createRange) {
// IE <= 8 case
range = document.selection.createRange();
range.execCommand("BackColor", false, colour);
}
}

highlight the text of the DOM range element,

The execCommand method is a method of the document, not the Range. Also, hilitecolor only works in Firefox, so you should fall back to using backcolor in WebKit and Opera.

UPDATE

Fixed in IE 9.

function makeEditableAndHighlight(colour) {
var sel = window.getSelection();
var range = null;
if (sel.rangeCount && sel.getRangeAt) {
range = sel.getRangeAt(0);
}
document.designMode = "on";
if (range) {
sel.removeAllRanges();
sel.addRange(range);
}
// Use HiliteColor since some browsers apply BackColor to the whole block
if (!document.execCommand("HiliteColor", false, colour)) {
document.execCommand("BackColor", false, colour);
}
document.designMode = "off";
}

function highlight(colour) {
var range, sel;
if (window.getSelection) {
// IE9 and non-IE
try {
if (!document.execCommand("BackColor", false, colour)) {
makeEditableAndHighlight(colour);
}
} catch (ex) {
makeEditableAndHighlight(colour)
}
} else if (document.selection && document.selection.createRange) {
// IE <= 8 case
range = document.selection.createRange();
range.execCommand("BackColor", false, colour);
}
}

Highlighting multiple lines in text from start index to end index (Range highlighting)

This is one of the rare use cases of .reduceRight(). As @Robert Sabitz mentions starting from the end of the string would keep it's indices of interest unchanged.

var prg = document.getElementById("lorem"),
btn = document.getElementById("btn"),
ixs = [{start:28, end:39}, {start:101, end:111}],
clr = "lightgreen";


function highlighter(str,ixs,color){
return ixs.reduceRight( (s,ix) => `${s.slice(0, ix.start)}<span style="background-color:${color}">${s.slice(ix.start,ix.end)}</span>${s.slice(ix.end)}`
, str
);
}

btn.addEventListener("click", _ => prg.innerHTML = highlighter(prg.textContent,ixs,clr));
<p id="lorem">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus tincidunt dictum sapien, sit amet vestibulum ex tempus eget. Ut vitae.</p>
<button id="btn">Highlight</button>

How to change the highlight color of selected text in a textarea, using selection range?

I don't understand exactly what you want.

Did you want an answer like the code below?

https://codepen.io/jyh7a/pen/xxpLMZZ

HTML

<input type="text" id="text-box" size="20" value="Mozilla">
<button onclick="selectText()">Select text</button>

<hr/>

<textarea rows="6" cols="40">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Porro maxime excepturi autem nostrum minus quae magni, esse optio ab, dolor ut iste earum sapiente molestiae nihil totam rem ipsam officia?</textarea>

<hr/>

<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Porro maxime excepturi autem nostrum minus quae magni, esse optio ab, dolor ut iste earum sapiente molestiae nihil totam rem ipsam officia?</p>

CSS

::selection {
background-color: rgba(255,0,0,0.2);
}

JS

function selectText() {

const input = document.getElementById('text-box');
input.focus();
input.setSelectionRange(2, 5);

setTimeout(() => {
const textarea = document.querySelector('textarea');
textarea.focus();
textarea.setSelectionRange(0, 20);
}, 1000)


// // ERROR!
// // setSelectionRange function only use HTMLInputElements
// const p = document.querySelector('p');
// p.setSelectionRange(0, 20);
}

I searched for setSelectionRange

I made the above example by looking at the MDN official documentation.

(Link: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange )

Hope the above code was helpful to you.



Related Topics



Leave a reply



Submit