(function () { var prefix = window.__PREFIX__ || "."; var input = document.getElementById("search-input"); var results = document.getElementById("search-results"); if (!input || !results) return; var index = null; var selectedIndex = -1; function loadIndex() { if (index !== null) return Promise.resolve(index); return fetch(prefix + "/static/search-index.json") .then(function (r) { return r.json(); }) .then(function (data) { index = data; return data; }) .catch(function (e) { console.error("search-index load failed", e); index = []; return index; }); } function score(entry, q) { var ql = q.toLowerCase(); if (entry.title.toLowerCase().indexOf(ql) !== -1) return 3; if (entry.tags.some(function (t) { return t.toLowerCase().indexOf(ql) !== -1; })) return 2; if (entry.ingredients.some(function (i) { return i.toLowerCase().indexOf(ql) !== -1; })) return 1; return 0; } function escapeHtml(s) { return s.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); } function render(matches) { if (matches.length === 0) { results.innerHTML = '
No recipes found
'; } else { results.innerHTML = matches.map(function (m) { var href = prefix + "/" + m.path; return '' + '
' + escapeHtml(m.title) + '
' + '
'; }).join(""); } results.classList.remove("hidden"); } function updateSearchSelection() { var items = results.querySelectorAll("a"); items.forEach(function (item, i) { if (i === selectedIndex) { item.classList.add("search-selected"); item.scrollIntoView({ block: "nearest" }); } else { item.classList.remove("search-selected"); } }); } var timeout; input.addEventListener("input", function () { clearTimeout(timeout); var q = this.value.trim(); selectedIndex = -1; if (q.length < 2) { results.classList.add("hidden"); return; } timeout = setTimeout(function () { loadIndex().then(function (idx) { var matches = idx .map(function (e) { return { e: e, s: score(e, q) }; }) .filter(function (x) { return x.s > 0; }) .sort(function (a, b) { return b.s - a.s; }) .slice(0, 20) .map(function (x) { return x.e; }); render(matches); }); }, 150); }); input.addEventListener("keydown", function (e) { var items = results.querySelectorAll("a"); if (items.length === 0 || results.classList.contains("hidden")) return; if (e.key === "ArrowDown") { e.preventDefault(); selectedIndex = Math.min(selectedIndex + 1, items.length - 1); updateSearchSelection(); } else if (e.key === "ArrowUp") { e.preventDefault(); selectedIndex = Math.max(selectedIndex - 1, -1); updateSearchSelection(); } else if (e.key === "Enter") { if (selectedIndex >= 0 && selectedIndex < items.length) { e.preventDefault(); items[selectedIndex].click(); } } }); document.addEventListener("click", function (e) { if (!input.contains(e.target) && !results.contains(e.target)) { results.classList.add("hidden"); selectedIndex = -1; } }); })();