I made a search bar that takes everything typed into it and checks if the json file has the name, author or category that matches to it.
How could I make it so that everything typed into the search bar gets highlighted in the part where it displays matched results?
Here is a picture of the search bar for example. I typed in FPS and it found a category with FPS in it. I would want the fps part to be highlighted.
How I made the search bar work:
const search = document.getElementById("search");
const matchList = document.getElementById("match-list");
const searchStates = async searchText => {
const res = await fetch("firebase link");
const states = await res.json();
const listaInformacija2 = Object.values(states)
let matches = listaInformacija2.filter(state => {
const regex = RegExp(`^${searchText}`, "gi");
return state.autor.match(regex) || state.naziv.match(regex) || state.kategorija.match(regex);
});
if(searchText.length === 0) {
matches = []
matchList.innerHTML = "";
}
outputHtml(matches);
};
const outputHtml = matches => {
if(matches.length > 0){
const html = matches.map(match => `
<a href=kurs.html?id=${match.id} id="searchedLink">
<div id="allCourses">
<h4>${match.naziv}</h4>
<p>Kategorija: ${match.kategorija}</p>
<p>Autor: ${match.autor}</p>
</div>
</a>
`).join("");
matchList.innerHTML = html;
}
}
search.addEventListener("input", () => searchStates(search.value));
CodePudding user response:
You can add a specific span element to the highlighted text dynamically, I would also avoid making a Firebase call each search, as it would cost a lot of money if the app scale, here is what I got:
const FIREBASE_URL = '<your firebase url>';
const $search = document.getElementById('search');
const $matchList = document.getElementById('match-list');
const data = {};
function escape(str) {
return str.replace(/[.* ?^${}()|[\]\\]/g, '\\$&');
}
function search(query) {
if (!query) return [];
if (!data.statesList) return [];
const matches = data.statesList.filter(state => query.test(state.autor) || query.test(state.naziv) || query.test(state.kategorija));
return matches;
}
function render(matches, originalValue, query) {
if (!matches.length) {
$matchList.innerHTML = '';
return;
}
const html = matches
.map(match => {
const replacer = `<span >${originalValue}</span>`;
return `
<a href=kurs.html?id=${match.id} >
<div >
<h4>${match.naziv.replace(query, replacer)}</h4>
<p>Kategorija: ${match.kategorija.replace(query, replacer)}</p>
<p>Autor: ${match.autor.replace(query, replacer)}</p>
</div>
</a>`;
})
.join('');
$matchList.innerHTML = html;
}
function inputHandler(event) {
const { value } = event.target;
let query;
if (!value) query = null;
else query = new RegExp(escape(value), 'i');
const matches = search(query);
render(matches, value, query);
}
async function init() {
const response = await fetch(FIREBASE_URL);
data.states = await response.json();
data.statesList = Object.values(data.states);
$search.addEventListener('input', inputHandler);
}
init().catch(console.error);
And your CSS could look like this:
.search-match {
background-color: #e0d392f0;
}

