2

I have tried help from :
How to highlight text using javascript - Stackoverflow link
How do I get the starting and ending index of a highlighted piece of a string in Javascript? - Stackoverflow link
A one-line solution to highlighting search matches - Outside link

But reached upto a certain mark of achievement.

Now only first letters are highlighted . Also they get lowercase if I enter a lowercase letter in search and vice-versa
When the input is cleared , than the whole replace is shown including tag names

Here is what I reached upto :

function refree() {
  var reed = document.getElementById("search").value;
  var reed1 = reed.toLowerCase();
  var reader = document.getElementsByClassName("deviceNameCardHead")

  // for (let i = 0; i < reader.length; i++) {
  reader[0].innerHTML = reader[0].innerHTML.replace(new RegExp(reed1, 'gi'), `<span class="highlight">${reed}</span>`);
}
//}
.highlight {
  background: yellow;
}
<div id="devicesBtnData">
  <div class="searchDevice">
    <span class="searchDeviceBtn">Search Device</span>
    <input id="search" type="search" placeholder="Try it" oninput="refree()">
    <br>
  </div>

  <div class="deviceNameCard">
    <h3 class="deviceNameCardHead">Lenova Yoga laptop Pro</h3>
  </div>

</div>

Below answer solved most of the problems . But can there be a way such that :

  • User enter p in input than all occurrences of p are highlighted whether it is lowercase or uppercase without changing its all occurrences to lowercase if p entered is in lowercase like this : Lenova Yoga laptop pro
    but should be like this
    Lenova Yoga laptop Pro (when p is either lowercase or uppercase)
Rana
  • 2,500
  • 2
  • 7
  • 28

2 Answers2

1

This can be the solution . But I don't know how match used here . It is my first time use of it . If anyone can tell about it in comments will be helpful

const reader = document.querySelector(".deviceNameCardHead");
const reader_text = reader.textContent;

function refree() {
  var reed = document.getElementById("search").value;
  var reed1 = reed.toLowerCase();

  // for (let i = 0; i < reader.length; i++) {
  reader.innerHTML = reader_text.replace(new RegExp(reed1, 'gi'), (match) => `<span class="highlight">${match}</span>`);
}
//}
.highlight {
  background: yellow;
}
<div id="devicesBtnData">
  <div class="searchDevice">
    <span class="searchDeviceBtn">Search Device</span>
    <input id="search" type="search" placeholder="Try it" oninput="refree()">
    <br>
  </div>

  <div class="deviceNameCard">
    <h3 class="deviceNameCardHead">Lenova Yoga laptop Pro</h3>
  </div>

</div>
Rana
  • 2,500
  • 2
  • 7
  • 28
0

Your regex isn't working if there is a span tag between the letters. Therefor you could replace reader[0].innerHTML with reader[0].textContent. This also solves the issue when the input is cleared.

By the way: if you use document.querySelector(...) you can omit the [0] in reader[0] because it only selects the first element with that selector.

Working example: (simple for demonstration)

function refree() {
  var reed = document.getElementById("search").value;
  var reed1 = reed.toLowerCase();
  var reader = document.querySelector(".deviceNameCardHead");

  reader.innerHTML = reader.textContent.replace(new RegExp(reed1, 'gi'), `<span class="highlight">${reed}</span>`);
}
.highlight {
  background: yellow;
}
<div id="devicesBtnData">
  <div class="searchDevice">
    <span class="searchDeviceBtn">Search Device</span>
    <input id="search" type="search" placeholder="Try it" oninput="refree()">
  </div>

  <div class="deviceNameCard">
    <h3 class="deviceNameCardHead">Lenova Yoga laptop Pro</h3>
  </div>
</div>

To solve the issue that it changes the case of the yellow letters you need a bit more code.

First you have to store the string from .deviceNameCardHead in a variable (for example reader_text), convert it to lower case for a case insensitive search and store that also in a variable (for example lower_text):

const reader_text = reader.textContent;
const lower_text = reader_text.toLowerCase();

Then you have to loop over all chars of reader_text to find all occurrences of the search string and store all index values in an array (for example index_array):

for(i = 0; i < lower_text.length; i++) {
  const reed_index = lower_text.indexOf(reed1, i);
    
  if(reed_index >= 0) {
    index_array.push(reed_index);
  }
}

Then you have to loop over the index_array and store all occurrences from the original string in an array (for example highlight_array) to obtain lower and upper case letters. To minimize an array to unique values you can use the Set() constructor and spread syntax [...].

index_array = [...new Set(index_array)];
index_array.forEach(function(val) {
  highlight_array.push(reader_text.substr(val, reed.length));
});

After that you have to loop over the highlight_array and replace all upper and lower case occurrences separately with span.highlight-wrapped values. To prevent the overwriting of reader_text use a separate variable (for example highlight_text):

let highlight_text = reader_text;

highlight_array = [...new Set(highlight_array)];
highlight_array.forEach(function(val) {
  highlight_text = highlight_text.replaceAll(val, `<span class="highlight">${val}</span>`);
});

And finally you have to replace the string from .deviceNameCardHead with highlight_text:

reader.innerHTML = highlight_text;

Working example:

const reader = document.querySelector(".deviceNameCardHead");
const reader_text = reader.textContent;
const lower_text = reader_text.toLowerCase();

function refree() {
  const reed = document.getElementById("search").value;
  const reed1 = reed.toLowerCase();
  let highlight_text = reader_text;
  let highlight_array = [];
  let index_array = [];
  
  for(i = 0; i < lower_text.length; i++) {
    const reed_index = lower_text.indexOf(reed1, i);
    
    if(reed_index >= 0) {
      index_array.push(reed_index);
    }
  }

  index_array = [...new Set(index_array)];
  index_array.forEach(function(val) {
    highlight_array.push(reader_text.substr(val, reed.length));
  });

  highlight_array = [...new Set(highlight_array)];
  highlight_array.forEach(function(val) {
    highlight_text = highlight_text.replaceAll(val, `<span class="highlight">${val}</span>`);
  });
  
  reader.innerHTML = highlight_text;
}
.highlight {
  background: yellow;
}
<div id="devicesBtnData">
  <div class="searchDevice">
    <span class="searchDeviceBtn">Search Device</span>
    <input id="search" type="search" placeholder="Try it" oninput="refree()">
  </div>

  <div class="deviceNameCard">
    <h3 class="deviceNameCardHead">Lenova Yoga press laptop Pro</h3>
  </div>
</div>
biberman
  • 5,606
  • 4
  • 11
  • 35
  • Thanks a lot . Can it be like this : if I search for `p` then all `p` are highlighted irrespective of there being lowercase or uppercase . And **p** in text don't change to lowercase or uppercase as of the search – Rana Sep 09 '21 at 14:52
  • Still changing all occurrence of `p` to case in which it is entered like : Lenova Yoga la**p**to**p** **p**ro . If `p` is entered in lowercase – Rana Sep 09 '21 at 15:09
  • Also Lenova Yoga la**P**to**P** **P**ro . If `p` is entered in uppercase – Rana Sep 09 '21 at 15:10
  • Can it be like this : Lenova Yoga la**p**to**p** **P**ro . Either `p` is entered in lowercase or uppercase – Rana Sep 09 '21 at 15:10
  • Sorry, couldn't use a computer for the last hours. Give me some time... – biberman Sep 09 '21 at 18:35
  • No worries @biberman . It is nice of you for solving my problem . If get to a result plz post the answer plz – Rana Sep 09 '21 at 19:27
  • When you enter `.` or stuff like `.*` you got some funky stuff going on. There's much more into RegExp than *"just use RegExp"* :) – Roko C. Buljan Sep 09 '21 at 21:35
  • @biberman thanks brother for your time and effort – Rana Sep 10 '21 at 18:44
  • @biberman I get the answer from your code and some other . Thanks a lot . I used `match` method in the 3rd link of question . A one line solution one – Rana Sep 11 '21 at 11:38
  • @biberman I have posted the answer you can check it but if you can tell the use of `match` in it , will be very helpful – Rana Sep 11 '21 at 11:47