// @ts-check import { qs } from './modules/query.js'; import { raiseEvent } from './modules/events.js'; import { contains, sanitise, explode } from './modules/string.js'; var haystack = []; var needles = []; var currentQuery = null; var ready = false; var scrolled = false; /** * Performs the search * @param {string} s * @returns */ function search(s) { needles = []; // Clean the input var cleanQuery = sanitise(s); if (currentQuery === cleanQuery) { return; } raiseEvent('searched', { search: s }); currentQuery = cleanQuery; var queryTerms = explode(currentQuery); for (var i = 0; i < haystack.length; i++) { var item = haystack[i]; item.score = 0; var title = sanitise(item.title); var category = sanitise(item.category); var tags = sanitise(item.tags); for (var j = 0; j < queryTerms.length; j++) { var term = queryTerms[j]; if (contains(title, term)) { item.score = item.score + 10; } if (contains(category, term)) { item.score = item.score + 5; } if (contains(tags, term)) { item.score = item.score + 5; } } if (item.score > 0) { needles.push(item); } } needles.sort(function (a, b){ return b.score - a.score; }); var results = qs('#site-search-results'); if (results == null) { throw new Error('Cannot find #site-search-results'); } var ol = document.createElement('ol'); ol.className = 'site-search-results'; var limit = Math.min(needles.length, 12) for (var i = 0; i < limit; i++) { var needle = needles[i]; var a = document.createElement('a'); a.innerHTML = needle.title; a.href = needle.url; var li = document.createElement('li'); li.appendChild(a); ol.appendChild(li); } var h2 = document.createElement('h2'); h2.innerHTML = needles.length === 0 ? results.dataset.emptytitle || 'No Results' : results.dataset.title || 'Results'; results.innerHTML = ''; results.appendChild(h2); results.appendChild(ol); } var debounceTimer; function debounceSearch() { var input = /** @type {HTMLInputElement} */(qs('#site-search-query')); if (input == null) { throw new Error('Cannot find #site-search-query'); } var s = input.value; window.clearTimeout(debounceTimer); debounceTimer = window.setTimeout(function () { if (ready) { search(s); } }, 400); } fetch('/search.json') .then(function (response) { return response.json(); }) .then(function (data) { haystack = data; ready = true; var siteSearch = qs('#site-search'); var siteSearchQuery = qs('#site-search-query'); if (siteSearch == null || siteSearchQuery == null) { throw new Error('Cannot find #site-search or #site-search-query'); } siteSearch.addEventListener('submit', function (e) { e.preventDefault(); debounceSearch(); return false; }); siteSearchQuery.addEventListener('keyup', function (e) { e.preventDefault(); if (!scrolled) { scrolled = true; this.scrollIntoView(true); } debounceSearch(); return false; }); console.log('Search ready'); });