Reputation: 2546
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 :
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 prop
is either lowercase or uppercase)Upvotes: 2
Views: 518
Reputation: 2546
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>
Upvotes: 1
Reputation: 5767
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>
Upvotes: 0