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
How to Swap Two Variables in JavaScript
What's the Fastest Way to Convert String to Number in JavaScript
Download PDF File Using Jquery Ajax
Password Encryption at Client Side
How to Send Variables from One File to Another in JavaScript
Best JavaScript Solution for Client-Side Form Validation and Interaction
Add Elements to the Dom Given Plain Text HTML Using Only Pure JavaScript (No Jquery)
How to Resolve Iframe Cross Domain Issue
Save and Render a Webpage with Phantomjs and Node.Js
Change How Fast "Title" Attribute's Tooltip Appears
How to Open a Url in a New Tab Using JavaScript or Jquery
Window.Open(Url, '_Blank'); Not Working on Imac/Safari
How to Define Custom Sort Function in JavaScript
Overriding a JavaScript Function While Referencing the Original
How to Append a Div Inside an Svg Element
Create a String of Variable Length, Filled with a Repeated Character