I am trying to build a basic JavaScript search functionality. So I have a couple of divs and an input search field:
<div class="notes">
<div class="firstNote">FIRST NOTE</div>
<div class="secondNote">SECOND NOTE</div>
<div class="thirdNote">THIRD NOTE</div>
<div class="fourthNote">THIRDDD NOTE</div>
<div class="fifthNote">THIRL NOTE</div>
</div>
<div class="search">
<input type="text" placeholder="Search...">
</div>
The idea is that when the user types in the search box, it checks what they typed against the innerHTML
values of the divs inside the parent notes
div. While those values match, it should apply the searched
class to those divs where the matching value is found. And then hide all the other divs by giving them display:none
. Once it stops finding a match, it should remove the searched
class from all the divs and display them all again by giving them display:block
.
The trouble is that this works only for the first div it finds where there is a match. I've created a couple of them starting with the letters 'THIR' for testing. If I start typing 'thir', it only shows (ie applies the 'searched' class to) the first div whose text matches (the one with the thirdNote
class), but not the other two even though they still also match. Here's the JS code:
const notes = document.querySelectorAll(".notes div");
const search = document.querySelector(".search input");
let count = 0; //detecting the number of times the user typed in the input field
search.addEventListener("keyup", function(e){
let x = 1; //will use this to compare the values of the search box and the divs
if(e.which === 16) //if the user presses Shift, don't do anything
return;
if(e.which !== 8) //if pressed anything but Backspace, increase the count
count++;
else if(e.which === 8 && count >= 1) { // otherwise decrease the count
count--;
}
const textSearched = this.value; //what the user typed in the searchbox
//if there is no text in the search box, remove the 'searched' class from all the divs, show all of them, and reset x back to 1
if(count === 0 || textSearched === ""){
notes.forEach(function(el){
if(el.style.display === "none")
el.style.display = "block";
if(el.classList.contains("searched"))
el.classList.remove("searched");
});
x = 1;
}
notes.forEach((body) => {
//while the search box and the div text values match, and x is not greater than the div text length, add the 'searched' class and increment x
while(textSearched.substring(0, x).toLowerCase() === body.innerHTML.substring(0, x).toLowerCase() && x <= body.innerHTML.length) {
body.classList.add("searched");
x++;
//if count is less than x, it means there is a match. So show all the matching divs, and hide all the other ones
if(count < x) {
notes.forEach((el) => {
if(!el.classList.contains("searched"))
el.style.display = "none";
else
el.style.display = "block";
});
}
// if count is equal or greater than x, it means no more matching, so show all the divs and remove the 'searched' class
else {
notes.forEach(function(el){
if(el.style.display === "none")
el.style.display = "block";
if(el.classList.contains("searched"))
el.classList.remove("searched");
});
}
}
});
});
Here is a working JS Fiddle: https://jsfiddle.net/tpxd5cqm/4/
Thanks!
This is what I'd do: toggle a class on the parent container when matching search elements are detected, and remove the class when there are no matches, or when the input is empty. When the parent class is active, highlight all .searched
children, and hide all non- .searched
children:
const container = document.querySelector('.notes'); const notes = [...container.children]; const input = document.querySelector('input'); input.addEventListener('keydown', () => { // Wait for the input field to contain its final value: setTimeout(checkInput); }); const checkInput = () => { const value = input.value.toLowerCase(); const matchingNotes = notes.filter(note => note.textContent.toLowerCase().includes(value)); if (!value || matchingNotes.length === 0) { container.classList.remove('searchActive'); return; } container.classList.add('searchActive'); for (const note of notes) { if (matchingNotes.includes(note)) { note.classList.add('searched'); } else { note.classList.remove('searched'); } } }
.searchActive > .searched { background-color: yellow; } .searchActive > *:not(.searched) { display: none; }
<div class="notes"> <div>FIRST NOTE</div> <div>SECOND NOTE</div> <div>THIRD NOTE</div> <div>THIRDDD NOTE</div> <div>THIRL NOTE</div> </div> <div> <input type="text" placeholder="Search..."> </div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.