// # Javascript Progressive Search for Docket
//
// This file loads a search index that's pre-baked by `docket` at documentation
// compile time. If the search index loads we inject the search box into the
// page and enable the search.
const initialiseSearch = async (rootPath, targetSelector) => {
const searchForm = document.querySelector(targetSelector);
if (searchForm == null) {
return;
}
searchForm.innerHTML = `
Search
`;
const searchBox = searchForm.querySelector('#query');
const searchResults = searchForm.querySelector('#docket-search-results');
const searchEntryForResult = result => {
return `${result.title}`;
}
const displayResults = results => {
if (results.length == 0) {
searchResults.innerHTML = "No results
";
} else {
searchResults.innerHTML =
`${results.length} results
${results.map(searchEntryForResult).join('')}
`;
}
}
const searchIndex = await fetch(`${rootPath}search_index.json`)
.then(response => response.json());
const doSearch = query => {
// If the search is empty clean up.
if (query.trim().length == 0) {
searchResults.innerHTML = "";
return;
}
let terms = query.split(/\W+/)
.map(term => term.trim().toLowerCase())
.filter(term => term.length > 0);
let found = []
searchIndex.forEach(page => {
let score = 0;
terms.forEach(term => {
let termScore = page.terms[term];
if (termScore !== undefined) {
score += termScore;
}
});
if (score > 0) {
found.push({
score: score,
page: page,
});
}
});
// Order them by the score, descending.
found.sort((a, b) => b.score - a.score);
displayResults(found.map(f => f.page));
}
let timer = null;
searchBox.addEventListener('keyup', event => {
if (timer !== null) {
clearTimeout(timer);
}
timer = setTimeout(() => {
timer = null;
doSearch(searchBox.value);
}, 500);
});
searchForm.addEventListener('submit', event => {
event.preventDefault();
if (timer !== null) {
clearTimeout(timer);
timer = null;
}
doSearch(searchBox.value);
});
}
const uri = import.meta.url;
initialiseSearch(uri.substring(0, uri.lastIndexOf('/') + 1), '#docket-search')