// search from https://github.com/onweru/compose function initializeSearch(index) { const searchKeys = ['title', 'link', 'body', 'id']; const searchPageElement = elem('#searchpage'); const searchOptions = { ignoreLocation: true, findAllMatches: true, includeScore: true, shouldSort: true, keys: searchKeys, threshold: 0.0 }; index = new Fuse(index, searchOptions); function minQueryLen(query) { query = query.trim(); const queryIsFloat = parseFloat(query); const minimumQueryLength = queryIsFloat ? 1 : 2; return minimumQueryLength; } function searchResults(results=[], query="", passive = false) { let resultsFragment = new DocumentFragment(); let showResults = elem('.search_results'); if(passive) { showResults = searchPageElement; } emptyEl(showResults); const queryLen = query.length; const requiredQueryLen = minQueryLen(query); if(results.length && queryLen >= requiredQueryLen) { let resultsTitle = createEl('h3'); resultsTitle.className = 'search_title'; resultsTitle.innerText = quickLinks; if(passive) { resultsTitle.innerText = searchResultsLabel; } resultsFragment.appendChild(resultsTitle); if(!searchPageElement) { results = results.slice(0,8); } else { results = results.slice(0,12); } results.forEach(function(result){ let item = createEl('a'); item.href = `${result.link}?query=${query}`; item.className = 'search_result'; item.style.order = result.score; if(passive) { pushClass(item, 'passive'); let itemTitle = createEl('h3'); itemTitle.textContent = result.title; item.appendChild(itemTitle); let itemDescription = createEl('p'); // position of first search term instance let queryInstance = result.body.indexOf(query); itemDescription.textContent = `... ${result.body.substring(queryInstance, queryInstance + 200)} ...`; item.appendChild(itemDescription); } else { item.textContent = result.title; } resultsFragment.appendChild(item); }); } if(queryLen >= requiredQueryLen) { if (!results.length) { showResults.innerHTML = `${noMatchesFound}`; } } else { showResults.innerHTML = `` } showResults.appendChild(resultsFragment); } function search(searchTerm, passive = false) { if(searchTerm.length) { let rawResults = index.search(searchTerm); rawResults = rawResults.map(function(result){ const score = result.score; const resultItem = result.item; resultItem.score = (parseFloat(score) * 50).toFixed(0); return resultItem; }); passive ? searchResults(rawResults, searchTerm, true) : searchResults(rawResults, searchTerm); } else { passive ? searchResults([], "", true) : searchResults(); } } function liveSearch() { const searchField = elem(searchFieldClass); if (searchField) { searchField.addEventListener('input', function() { const searchTerm = searchField.value.trim().toLowerCase(); search(searchTerm); }); if(!searchPageElement) { searchField.addEventListener('search', function(){ const searchTerm = searchField.value.trim().toLowerCase(); if(searchTerm.length) { window.location.href = new URL(`search/?query=${searchTerm}`, rootURL).href; } }); } } } function findQuery(query = 'query') { const urlParams = new URLSearchParams(window.location.search); if(urlParams.has(query)){ let c = urlParams.get(query); return c; } return ""; } function passiveSearch() { if(searchPageElement) { const searchTerm = findQuery(); search(searchTerm, true); // search actively after search page has loaded const searchField = elem(searchFieldClass); if(searchField) { searchField.addEventListener('input', function() { const searchTerm = searchField.value.trim().toLowerCase(); search(searchTerm, true); wrapText(searchTerm, main); }); } } } function hasSearchResults() { const searchResults = elem('.results'); if(searchResults) { const body = searchResults.innerHTML.length; return [searchResults, body]; } return false } function clearSearchResults() { let searchResults = hasSearchResults(); if(searchResults) { searchResults = searchResults[0]; searchResults.innerHTML = ""; // clear search field const searchField = elem(searchFieldClass); searchField.value = ""; } } function onEscape(fn){ window.addEventListener('keydown', function(event){ if(event.code === "Escape") { fn(); } }); } let main = elem('main'); if(!main) { main = elem('.main'); } searchPageElement ? false : liveSearch(); passiveSearch(); wrapText(findQuery(), main); onEscape(clearSearchResults); window.addEventListener('click', function(event){ const target = event.target; const isSearch = target.closest(searchClass) || target.matches(searchClass); if(!isSearch && !searchPageElement) { clearSearchResults(); } }); } window.addEventListener('load', function() { fetch(new URL("index.json", rootURL).href) .then(response => response.json()) .then(function(data) { data = data.length ? data : []; initializeSearch(data); }) .catch((error) => console.error(error)); });