Demo here. The demo uses React and a list of blog post titles that get immediately filtered when you type in a search. I.e. you have the whole list but show less when a search term is entered.
That the demo uses React isn't important. What's important is the search function. It looks like this:
function filterList(q, list) {
function escapeRegExp(s) {
return s.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
}
const words = q
.split(/\s+/g)
.map(s => s.trim())
.filter(s => !!s);
const hasTrailingSpace = q.endsWith(" ");
const searchRegex = new RegExp(
words
.map((word, i) => {
if (i + 1 === words.length && !hasTrailingSpace) {
// The last word - ok with the word being "startswith"-like
return `(?=.*\\b${escapeRegExp(word)})`;
} else {
// Not the last word - expect the whole word exactly
return `(?=.*\\b${escapeRegExp(word)}\\b)`;
}
})
.join("") + ".+",
"gi"
);
return list.filter(item => {
return searchRegex.test(item.title);
});
}
I use this in a single-page content management app. There's a list of records and a search input. Every character you put into the search bar updates the list of records shown.
What it does is that it allows you to search texts based on multiple whole words. But the key feature is that the last word doesn't have to be whole. For example, it will positively match "This is a blog post about JavaScript"
if the search is "post javascript"
or "post javasc"
. But it won't match on "pos blog"
.
The idea is that if a user has typed in a full word followed by a space, all previous words needs to be matched fully. For example if the input is "java "
it won't match on "This is a blog post about JavaScript"
because the word java
, alone, isn't in the search text.
Sure, there are different ways to write this but I think this functionality is good for this kind of filtering search. A different implementation would have a function that returns the regex and then it can be used both for filtering and for highlighting.
Hope it helps.