1
Fork 0
blog/search.md

104 lines
2.8 KiB
Markdown
Raw Normal View History

---
permalink: /search
title: Search
layout: simple.liquid
data:
route: search
---
<form>
<p><input id="searchbox" type="search" placeholder="Search fnordig" style="width: 60%"></p>
</form>
<div id="results"></div>
<script>
function debounce(func, wait, immediate) {
let timeout;
return function() {
let context = this, args = arguments;
let later = () => {
timeout = null;
if (!immediate) func.apply(context, args);
};
let callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
const htmlEscape = (s) => s.replace(
/>/g, '&gt;'
).replace(
/</g, '&lt;'
).replace(
/&/g, '&'
).replace(
/"/g, '&quot;'
).replace(
/'/g, '&#039;'
);
const highlight = (s) => htmlEscape(s).replace(
/b4de2a49c8/g, '<b>'
).replace(
/8c94a2ed4b/g, '</b>'
);
function permalink(link, ts) {
let d = ts.replace(/ ([-+]....)/, "$1").replace(/ /, "T");
let date = new Date(d);
return link.replace(/\{\{ *year *}}/, date.getFullYear().toString().padStart(4, '0')
).replace(/\{\{ *month *}}/, (date.getMonth() + 1).toString().padStart(2, '0')
).replace(/\{\{ *day *}}/, date.getDate().toString().padStart(2, '0'));
}
function datefmt(ts) {
let d = ts.replace(/ ([-+]....)/, "$1").replace(/ /, "T");
let date = new Date(d);
let year = date.getFullYear().toString().padStart(4, '0');
let month = (date.getMonth() + 1).toString().padStart(2, '0');
let day = date.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`;
}
// Prevent form submission
document.querySelector("form").onsubmit = (e) => e.preventDefault();
// Grab a reference to the <input type="search">
const searchbox = document.getElementById("searchbox");
2022-04-22 20:16:21 +00:00
// Used to avoid race-conditions
let requestInFlight = null;
searchbox.onkeyup = debounce(() => {
const q = searchbox.value;
if (!q) { return; }
// Construct the API URL, using encodeURIComponent() for the parameters
2022-04-22 20:16:21 +00:00
const url = `https://fnordig.de/_search?search=${encodeURIComponent(q)}`;
// Unique object used just for race-condition comparison
let currentRequest = {};
requestInFlight = currentRequest;
fetch(url).then(r => r.json()).then(d => {
if (requestInFlight !== currentRequest) {
// Avoid race conditions where a slow request returns
// after a faster one.
return;
}
let results = d.map(r => {
let link = permalink(r.permalink, r.published_date);
return `
<div class="result">
<h3><a href="${link}">${htmlEscape(r.title)}</a></h3>
<p><small>${datefmt(r.published_date)}</small></p>
<p>${highlight(r.snippet)}</p>
</div>
`
}).join("");
document.getElementById("results").innerHTML = results;
});
}, 100); // debounce every 100ms
</script>