128 lines
4.6 KiB
JavaScript
128 lines
4.6 KiB
JavaScript
function _codigoparallevar_enable_search_box(selector, options) {
|
|
const element = document.querySelector(selector);
|
|
if ('placeholder' in options) {
|
|
element.setAttribute('placeholder', options.placeholder);
|
|
}
|
|
|
|
// Prepare backdrop
|
|
const resultsBoxBackdrop = document.createElement('div');
|
|
resultsBoxBackdrop.setAttribute('class', 'results-box-container hidden');
|
|
const resultsBox = document.createElement('div');
|
|
resultsBox.setAttribute('class', 'results-box');
|
|
|
|
// Results box contents
|
|
const innerSearchBox = document.createElement('input');
|
|
innerSearchBox.setAttribute('type', 'text');
|
|
innerSearchBox.setAttribute('placeholder', element.getAttribute('placeholder'));
|
|
resultsBox.appendChild(innerSearchBox);
|
|
|
|
const resultsList = document.createElement('ul');
|
|
resultsBox.appendChild(resultsList);
|
|
|
|
const noResultsBox = document.createElement('div');
|
|
noResultsBox.setAttribute('class', 'no-results-box hidden');
|
|
noResultsBox.innerText = 'No results 🤷';
|
|
resultsBox.appendChild(noResultsBox);
|
|
|
|
resultsBoxBackdrop.appendChild(resultsBox);
|
|
document.body.appendChild(resultsBoxBackdrop);
|
|
|
|
// Popup cancellation
|
|
resultsBoxBackdrop.onclick = () => {
|
|
resultsBoxBackdrop.classList.add('hidden');
|
|
};
|
|
resultsBox.onclick = (ev) => {
|
|
ev.stopPropagation();
|
|
};
|
|
|
|
// Element triggers popup
|
|
element.onfocus = () => {
|
|
resultsBoxBackdrop.classList.remove('hidden');
|
|
innerSearchBox.focus();
|
|
|
|
const wasKeyDown = document.onkeydown;
|
|
document.onkeydown = (ev) => {
|
|
if (ev.key === 'Escape') {
|
|
resultsBoxBackdrop.classList.add('hidden');
|
|
document.onkeydown = wasKeyDown;
|
|
ev.stopPropagation();
|
|
}
|
|
};
|
|
};
|
|
|
|
const DEBOUNCE_TIME = 250; // Milliseconds
|
|
const MIN_LENGTH = 3;
|
|
const SEARCH_ENDPOINT = (window.location.host.startsWith('localhost')
|
|
? 'http://localhost:3001/api/search'
|
|
: 'https://api.codigoparallevar.com/api/search'
|
|
);
|
|
|
|
let debounceWaiter = null;
|
|
let currentQuery = null;
|
|
|
|
let lastVal = null;
|
|
const doQuery = () => {
|
|
const val = innerSearchBox.value.trim();
|
|
if ((val.length < MIN_LENGTH) || (val === lastVal)) {
|
|
return;
|
|
}
|
|
lastVal = val;
|
|
|
|
const uri = SEARCH_ENDPOINT + '?q=' + encodeURIComponent(val);
|
|
let query = fetch(uri);
|
|
currentQuery = query;
|
|
query
|
|
.then(res => res.json())
|
|
.then((body) => {
|
|
if (query !== currentQuery) {
|
|
console.log("Query out-raced 🤷");
|
|
return;
|
|
}
|
|
|
|
resultsList.innerHTML = '';
|
|
for (const list of [
|
|
body.results.notes.filter(n => n.is_todo !== "1"),
|
|
body.results.notes.filter(n => n.is_todo === "1"),
|
|
]){
|
|
for (const note of list) {
|
|
const resultCard = document.createElement('li');
|
|
|
|
const resultContents = document.createElement('a');
|
|
resultContents.setAttribute('href', './' + note.id + '.node.html');
|
|
|
|
const resultTitle = document.createElement('h2');
|
|
resultTitle.innerText = `${note.title} (${note.top_level_title})`;
|
|
if (note.is_todo === "1") {
|
|
resultTitle.setAttribute('class', 'is-todo');
|
|
}
|
|
else if (note.is_done === "1") {
|
|
resultTitle.setAttribute('class', 'is-done');
|
|
}
|
|
|
|
resultContents.appendChild(resultTitle);
|
|
resultCard.appendChild(resultContents);
|
|
resultsList.appendChild(resultCard);
|
|
}
|
|
}
|
|
if (body.results.notes.length == 0) {
|
|
noResultsBox.classList.remove('hidden');
|
|
}
|
|
else {
|
|
noResultsBox.classList.add('hidden');
|
|
}
|
|
});
|
|
};
|
|
element.removeAttribute('disabled');
|
|
|
|
innerSearchBox.onkeyup = (ev) => {
|
|
if (debounceWaiter !== null) {
|
|
clearTimeout(debounceWaiter);
|
|
}
|
|
debounceWaiter = setTimeout(doQuery, DEBOUNCE_TIME);
|
|
};
|
|
}
|
|
|
|
// // TODO: Remove this when dev is done
|
|
// _codigoparallevar_enable_search_box('#searchbox', {placeholder: 'Search...'})
|
|
// document.querySelector('#searchbox').focus()
|