Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript find string and highlight

Tags:

javascript

I'm having some issues with searching a string in long text. I want to extract only searched text and bold searched text with maybe 10-20 characters before it and after searched characters.

So basically what I want to achieve is, ex. from that text:

Hi there, I want to achieve a new goal to create a good search bar for my app. It should be just as any other search bar.

So if I want to search "good search", it should return something like:

...achieve a new goal to create a good search bar for my app. It should be just...

What would be a best way to do it? I tried something like:

const text = "Hi there, I want to achieve a new goal to create a good search bar for my app. It should be just as any other search bar."
const search_text = "good search"
const radius = 10;
// To determine where is the first character
const find_first = text.search(search_text)
const search_from = find_first - radius;
    
// To ensure that we are taking from first with length of searched text and additional ones
const search_to = find_first + search_text.length + radius

But still, this is only to determine how to check which characters to get. But how to list them and show with highlight?

like image 892
Rade Iliev Avatar asked Jul 05 '26 16:07

Rade Iliev


2 Answers

const text = "Hi there, I want to achieve a new goal to create a good search bar for my app. It should be just as any other search bar."
const search_text = "good search"
const RADIUS = 20;

const indexPosition = text.search(search_text)
const startPosition = indexPosition - RADIUS 
const endPosition = indexPosition + RADIUS + search_text.length
const searchResult = (`...${text.slice(startPosition, endPosition)}...`).replace(search_text, `<b>${search_text}</b>`)
console.log({searchResult})
  

and then you can apply your highlight with the way you like,(I add <b> tag around search text, I assume u want it as HTML format)

like image 143
KaraX_X Avatar answered Jul 08 '26 06:07

KaraX_X


The following snippet avoids breaking up words by taking up to 5 word-blank combinations (((?:\\S+\\s+){0,5})) before the search pattern pat and up to 5 blank-word combinations after the search pattern to create the formatted string result:

const inp = document.querySelector("input"),
  findPat = () => {
    let html, pat = inp.value.trim();
    if (pat.length) {
      const rx = new RegExp(`(?<=((?:\\S+\\s+){0,5}))\\b(${pat})\\b(?=((?:\\s+\\S+){0,5}))`, "ig");
      html = [...document.querySelectorAll("#content p")].reduce((a, p) => {
        let fnd = [...p.textContent.matchAll(rx)];
        if (fnd.length) a.push(fnd);
        return a;
      }, []).flat().map(([_, pre, txt, post]) =>
        `<p>...${pre}<b>${txt}</b>${post}...`
      ).join("");
    } else html = "";
    document.querySelector("#result").innerHTML = html
  };
inp.addEventListener("input", findPat); // assign the event function to the "input" event
findPat(); // run the event function with the initial value of inp
<div id="content">
  <p>Here we find some random text. It should fill the page but not attract any unnecessary attention to itself if it is done in a good way.</p>
  <p>In a second good paragraph I will hide the text that is of interest here: "Hi there, I want to achieve a new goal to create a good search bar for my good app. It should be just as any other search bar." Just to give it a bit more body this last sentence was also added.</p>
</div>
<input type="text" value="good"></input>
<hr>
<div id="result" value="good"></div>

The positive lookbehind ((?<=((?:\\S+\\s+){0,5}))) and lookahead (?=((?:\\s+\\S+){0,5})) around the search pattern (\\b(${pat})\\b -> the \\b look for a word boundary) are necessary for allowing fully overlapping result strings. The second "good" in: "... to create a good search bar in my good app." could not be matched otherwise.

For simplicity I used <b>...</b> to format the text matching the search pattern bold. This can, of course, be replaced by anything else like <span class="hilight">...</span>.

The new RegExp() expression will probably also need some further attention: should there be "special characters" (like a dot: . or a question mark ?) in the search pattern pat and these are to be found as such, they will need to be masked (by a preceding \\) as otherwise they will be misinterpreted as being part of a regular expression.

like image 21
Carsten Massmann Avatar answered Jul 08 '26 05:07

Carsten Massmann



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!