How to Highlight Text Using JavaScript

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>

Find and highlight word in text using JS

Here is my solution. I found there are two ways to achieve this. In Firefox, you can use selection api. Unfortunately, it will not work in Chrome. A simpler solution is to just match the search text and highlight it by enclosing it in <mark> tags.

var opar = document.getElementById('paragraph').innerHTML;

function highlight() {
var paragraph = document.getElementById('paragraph');
var search = document.getElementById('typed-text').value;
search = search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); //https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex

var re = new RegExp(search, 'g');

if (search.length > 0)
paragraph.innerHTML = opar.replace(re, `<mark>$&</mark>`);
else paragraph.innerHTML = opar;
}
<div id="highlights">
<div class="container">
<div class="row">
<div class="col-md-12" id="paragraph">
<p>
Robotics is an interdisciplinary branch of engineering and science that includes mechanical engineering, electronics engineering, information engineering, computer science, and others. Robotics deals with the design, construction, operation, and use of
robots, as well as computer systems for their control, sensory feedback, and information processing. These technologies are used to develop machines that can substitute for humans and replicate human actions. Robots can be used in many situations
and for lots of purposes, but today many are used in dangerous environments (including bomb detection and deactivation), manufacturing processes, or where humans cannot survive (e.g. in space). Robots can take on any form but some are made to
resemble humans in appearance. This is said to help in the acceptance of a robot in certain replicative behaviors usually performed by people. Such robots attempt to replicate walking, lifting, speech, cognition, and basically anything a human
can do. Many of today's robots are inspired by nature, contributing to the field of bio-inspired robotics. The concept of creating machines that can operate autonomously dates back to classical times, but research into the functionality and
potential uses of robots did not grow substantially until the 20th century.[1] Throughout history, it has been frequently assumed that robots will one day be able to mimic human behavior and manage tasks in a human-like fashion. Today, robotics
is a rapidly growing field, as technological advances continue; researching, designing, and building new robots serve various practical purposes, whether domestically, commercially, or militarily. Many robots are built to do jobs that are hazardous
to people such as defusing bombs, finding survivors in unstable ruins, and exploring mines and shipwrecks. Robotics is also used in STEM (science, technology, engineering, and mathematics) as a teaching aid. Robotics is a branch of engineering
that involves the conception, design, manufacture, and operation of robots. This field overlaps with electronics, computer science, artificial intelligence, mechatronics, nanotechnology and bioengineering.
</p>
</div>
<div class="col-md-12 input-group mt-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">
<i class="fas fa-pencil-alt"></i>
</span>
</div>
<input id="typed-text" type="text" class="form-control" placeholder="Type text" onkeyup="highlight()">
</div>
</div>
</div>
</div>

How can I highlight the inner text of an HTML article element by index with just vainilla js?

//get text of article
const article = document.querySelector('article').innerText;

//find index of word 'in'
const index = article.indexOf('in');

//opening and closing tags
const openingTag = '<span style="color:red">'
const closingTag = '</span>'

//insert tags into article
const newHTML
= article.slice(0, index)
+ openingTag + 'in' + closingTag
+ article.slice(index + 2);
document.querySelector('article').innerHTML = newHTML;

This code styles the first occurrence of the word "in" by setting the text color to red. If you want to do something else, change the style attribute of the opening tag.

article.slice(0, index) returns everything before the word "in." In your example, this would evaluate to 'My text '. article.slice(index + 2) returns everything after the word "in" because "in" is 2 letters long. In your example, this would evaluated to ' an element'. When all the strings are concatenated together, the result is 'My text <span style="color:red">in</span> an element'.

How to highlight search text from string of html content without breaking

One thing you can use is getClientRects method of the Range object: https://developer.mozilla.org/en-US/docs/Web/API/range/getClientRects

This allows you to add divs with the coordinates of your search, allowing you to highlight text without having to manipulate the DOM.

Finding the nodes isn't that straighforward (especially if you have a complicated structure), but you can iterate through all text nodes to match the index of the search in the textContent of the element in which you want to search.

So first you match the search result to the DOM. In the example I use a recursive generator, but any recursive loop will do. Basically what you need to do is go through every text node to match the index of a search. So you go through every descendant node and count the texts length so you can match your search to a node.

Once this is done, you can create a Range from these results, and then you add elements with the coordinates of the rectangles you get with getClientRects. By giving then a z-index negative and an absolute position, they will appear under the text at the right place. So you'll have a highlight effect, but without touching the HTML you are searching.
Like this:

document.querySelector('#a').onclick = (e) => {

let topParent = document.querySelector('#b');

let s, range;

let strToSearch = document.querySelector('#search').value

let re = RegExp(strToSearch, 'g')

removeHighlight()

s = window.getSelection();

s.removeAllRanges()

// to handle multiple result you need to go through all matches

while (match = re.exec(topParent.textContent)) {

let it = iterateNode(topParent);

let currentIndex = 0;

// the result is the text node, so you can iterate and compare the index you are searching to all text nodes length

let result = it.next();

while (!result.done) {

if (match.index >= currentIndex && match.index < currentIndex + result.value.length) {

// when we have the correct node and index we add a range

range = new Range();

range.setStart(result.value, match.index - currentIndex)

}

if (match.index + strToSearch.length >= currentIndex && match.index + strToSearch.length < currentIndex + result.value.length) {

// when we find the end node, we can set the range end

range.setEnd(result.value, match.index + strToSearch.length - currentIndex)

s.addRange(range)

// this is where we add the divs based on the client rects of the range

addHighlightDiv(range.getClientRects())

}

currentIndex += result.value.length;

result = it.next();

}

}

s.removeAllRanges()

}

function* iterateNode(topNode) {

// this iterate through all descendants of the topnode

let childNodes = topNode.childNodes;

for (let i = 0; i < childNodes.length; i++) {

let node = childNodes[i]

if (node.nodeType === 3) {

yield node;

} else {

yield* iterateNode(node);

}

}

}

function addHighlightDiv(rects) {

for (let i = 0; i < rects.length; i++) {

let rect = rects[i];

let highlightRect = document.createElement('DIV')

document.body.appendChild(highlightRect)

highlightRect.classList.add('hl')

highlightRect.style.top = rect.y + window.scrollY + 'px'

highlightRect.style.left = rect.x + 'px'

highlightRect.style.height = rect.height + 'px'

highlightRect.style.width = rect.width + 'px'

}

}

function removeHighlight() {

let highlights = document.querySelectorAll('.hl');

for (let i = 0; i < highlights.length; i++) {

highlights[i].remove();

}

}
.hl {

background-color: red;

position: absolute;

z-index: -1;

}
<input type="text" id="search" /><button id="a">search</button>

<div id="b">

<h1>Lorem ipsum dolor sit amet</h1>, consectetur

<h2>adipiscing elit, sed do</h2> eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud <strong>exercitation <span>ullamco laboris</span> nisi ut aliquip ex ea commodo</strong> consequat. Duis aute irure dolor

in reprehenderit in voluptate velit <em>esse cillum dolore eu fugiat nulla pariatur.</em> Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

</div>

How to highlight text in para using array of values?

Here is a super simple to use reusable component for text highlighting by tags:

function Highlight({ children: text = "", tags = [] }) {
if (!tags?.length) return text;
const matches = [...text.matchAll(new RegExp(tags.join("|"), "ig"))];
const startText = text.slice(0, matches[0]?.index);
return (
<span>
{startText}
{matches.map((match, i) => {
const startIndex = match.index;
const currentText = match[0];
const endIndex = startIndex + currentText.length;
const nextIndex = matches[i + 1]?.index;
const untilNextText = text.slice(endIndex, nextIndex);
return (
<span key={i}>
<mark>{currentText}</mark>
{untilNextText}
</span>
);
})}
</span>
);
}

export default function App() {
return (
<div className="App">
<h1>
<Highlight tags={["Hel", "co", "nd"]}>Hello CodeSandbox</Highlight>
</h1>
<h2>
<Highlight tags={["ditin", "e"]}>
Start editing to see some magic happen!
</Highlight>
</h2>
</div>
);
}

Demo in Codesndbox

example code output

Using it with your example:

const tags = ["Hello", "moment", "somewhere"];
const paras = [
{
text: "Hello, tina. Thank you for all waiting. Hello?"
},
{
text: "When can I go? Okay. One moment. Let me just"
},
{
text: "if I can help you somewhere, if you are interested"
}
];
function ParasList() {
return (
<ul>
{paras.map((para, i) => (
<li key={i}>
<Highlight tags={tags}>{para.text}</Highlight>
</li>
))}
</ul>
);
}

example code #2 output

Explanation:

The Highlight component is easy to use, you just wrap around some text, and put on the "tags" attribute: <Highlight tags={["some"]}>some text</Highlight>

Inside the component, I'm using the new and shiny string.prototype.matchAll function, which gives us information about the match and the index where it was found.

Also, I'm creating the regex using join("|") on the tags, so they have an "OR" relationship between them. The flag i makes the highlight case insensitive, but you could delete it if you would want to keep case sensitivity. The g flag is the global flag, so duplicate matches are found and highlighted. It is required in a matchAll search.

Lastly, I'm using the <mark> html tags for highlighting, but you could easily change this, or even pass a custom tag through props for more versatility. You could also just enclose the "marked" bits with a regular span, and mark them with a "highlighted" className, and customize the appearance that way, using CSS.



Related Topics



Leave a reply



Submit