I am making a static site in vanilla HTML5, CSS3, and JavaScript (ES6). I have made a user-facing search function using a sitemap (stored as a JS variable), regexes, and JS. I’m not very good at regexes or JS. It works sort of okay, but it’s weird. Here’s an example:
page = {
"titles":["Page Title"],
"headers":["Header 1","Header 2","Header 3"],
"text":"This is a gigantic string that is all the text from the page body after I stripped out any HTML tags."
}
If, in my IDE, I search sitemap.js for the string “How to Use This Guide” it turns up 7 results. Page 1 has a matching header and two matching strings in the page text. Page 2 has a matching title, a matching header, and two matches in the text.
If I use the Search function in my site (which in turn searches the same sitemap.js file) it only turns up Page 1, and only displays one of the two matches in Page 1’s text. The expected behavior is to turn up Page 1 with two matches and Page 2 with two matches. (Also, Page 2 should be displayed before Page 1 since Page 2 has a matching title, which takes priority.)
Here is the section of sitemap.js text with all 7 hits (some irrelevant text removed to shorten it):
“headers”:[“Falcons Onboarding Guide”,”Introduction”,”How to Use This Guide“],”text”:” Home Page Falcons Onboarding Guide Editing the Guide . How to Use This Guide Use the navigation menu on the please see the How to Use This Guide page. “},{“name”:”how-to-use-guide.html”,”lastModified”:”1/12/2022″,”path”:”pages/how-to-use-guide.html”,”titles”:[“How to Use This Guide“],”headers”:[“How to Use This Guide“,”Purpose of the Guide”,”Sharing and Accessing the Guide”],”text”:” How to Use This Guide How to Use This Guide Purpose Sharing and Accessing
Here is the HTML for the search bar:
<form id="search-form" class="search" onsubmit="search(this.getElementsByTagName('input')[0].value);return false;">
<input type="text" placeholder="Search">
<button><i class="magnifying-glass"></i></button>
</form>
Here is the JS code for the search function :
// Adapted from https://gomakethings.com/how-to-create-a-vanilla-js-search-page-for-a-static-website/
function search(query) {
event.preventDefault();
let regx = new RegExp(query, 'gi');
let priority1 = [];
let priority2 = [];
let priority3 = [];
// search all pages in the JSON for the query text and return hits
sitemap.forEach(function (page) {
if (regx.test(page.text)) {
page.hits = [...page.text.matchAll(regx)].map(a => page.text.slice(a.index > 10 ? a.index - 10 : 0, a.index + 100 > page.text.length ? page.text.length : a.index + 100).replace(new RegExp(query, 'i'), '<strong>' + a[0] + '</strong>'));
// sort by priority
if (regx.test(page.titles)) {
priority1.push(page);
} else if (regx.test(page.headers)) {
priority2.push(page);
} else {
priority3.push(page);
}
}
});
let searchResults = [].concat(priority1, priority2, priority3);
let resultsDiv = document.getElementById('search-results');
resultsDiv.innerHTML = searchResults.length < 1 ? createNoResultsHtml(query) : createResultsHtml(searchResults);
};
I’ve spent many, many hours on this search function, as well as the “sitemap generator” util that reads the HTML files and strips them of the HTML. I’ve gotten it to a point where it is usable, but buggy. I also can’t figure out why there are frequently some pages that turn up in the search results, but have no “hits.” So they pass the if (regx.test(page.text)) {
but fail the following [...page.text.matchAll(regx)]
. And some pages don’t make it into the search results at all.
It’s not the HTML generation logic, because when I console.log() the searchResults, it matches exactly what the HTML displays — pages missing from the HTML are missing from the searchResults, hits missing from the HTML are missing from the searchResults.page.hits[]
If some kind soul(s) can help me with this, I would be SO GRATEFUL I can’t even put it into words. TT__TT