added caching to search suggestions on client side
This commit is contained in:
parent
f7e6c34722
commit
2f65d04dda
1 changed files with 28 additions and 27 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
This script is responsible for fetching search suggestions when the user types in the search bar. It also shows and hides the search suggestions wrapper.
|
This script fetches and caches search suggestions to reduce server requests with an LRU cache.
|
||||||
*/
|
*/
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const searchInput = document.getElementById('search-input');
|
const searchInput = document.getElementById('search-input');
|
||||||
|
@ -7,14 +7,30 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
const resultsWrapper = document.querySelector('.autocomplete');
|
const resultsWrapper = document.querySelector('.autocomplete');
|
||||||
|
|
||||||
let suggestions = [];
|
let suggestions = [];
|
||||||
let currentIndex = -1; // Keep track of the currently selected suggestion
|
let currentIndex = -1;
|
||||||
|
const cacheLimit = 10000; // This should take about 3.6 MB of memory
|
||||||
|
const suggestionCache = new Map(); // Map to store suggestions with LRU capability
|
||||||
|
|
||||||
// Fetch suggestions from the server
|
// Fetch suggestions from server or cache
|
||||||
async function getSuggestions(query) {
|
async function getSuggestions(query) {
|
||||||
|
if (suggestionCache.has(query)) {
|
||||||
|
// Move the recently accessed item to the end of Map to mark it as most recently used
|
||||||
|
const cachedResult = suggestionCache.get(query);
|
||||||
|
suggestionCache.delete(query);
|
||||||
|
suggestionCache.set(query, cachedResult);
|
||||||
|
return cachedResult;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/suggestions?q=${encodeURIComponent(query)}`);
|
const response = await fetch(`/suggestions?q=${encodeURIComponent(query)}`);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data[1]; // Return only the array of suggestion strings
|
// Add result to cache and enforce cache limit
|
||||||
|
suggestionCache.set(query, data[1]);
|
||||||
|
if (suggestionCache.size > cacheLimit) {
|
||||||
|
// Remove the oldest (first) item in the Map
|
||||||
|
const firstKey = suggestionCache.keys().next().value;
|
||||||
|
suggestionCache.delete(firstKey);
|
||||||
|
}
|
||||||
|
return data[1];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching suggestions:', error);
|
console.error('Error fetching suggestions:', error);
|
||||||
return [];
|
return [];
|
||||||
|
@ -63,29 +79,20 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
const items = resultsWrapper.querySelectorAll('li');
|
const items = resultsWrapper.querySelectorAll('li');
|
||||||
if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'Tab') {
|
if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'Tab') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
if (items[currentIndex]) items[currentIndex].classList.remove('selected');
|
||||||
|
|
||||||
// Remove 'selected' class from the current item
|
currentIndex = event.key === 'ArrowUp'
|
||||||
if (items[currentIndex]) {
|
? (currentIndex > 0 ? currentIndex - 1 : items.length - 1)
|
||||||
items[currentIndex].classList.remove('selected');
|
: (currentIndex + 1) % items.length;
|
||||||
}
|
|
||||||
|
|
||||||
if (event.key === 'ArrowUp') {
|
|
||||||
currentIndex = (currentIndex > 0) ? currentIndex - 1 : items.length - 1;
|
|
||||||
} else {
|
|
||||||
currentIndex = (currentIndex + 1) % items.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add 'selected' class to the new item and update the input value
|
|
||||||
if (items[currentIndex]) {
|
if (items[currentIndex]) {
|
||||||
items[currentIndex].classList.add('selected');
|
items[currentIndex].classList.add('selected');
|
||||||
searchInput.value = items[currentIndex].textContent;
|
searchInput.value = items[currentIndex].textContent;
|
||||||
}
|
}
|
||||||
} else if (event.key === 'Enter') {
|
} else if (event.key === 'Enter' && currentIndex > -1 && items[currentIndex]) {
|
||||||
if (currentIndex > -1 && items[currentIndex]) {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
selectSuggestion(items[currentIndex]);
|
selectSuggestion(items[currentIndex]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Function to handle suggestion selection
|
// Function to handle suggestion selection
|
||||||
|
@ -94,14 +101,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
searchInput.value = query;
|
searchInput.value = query;
|
||||||
resultsWrapper.innerHTML = '';
|
resultsWrapper.innerHTML = '';
|
||||||
searchWrapper.classList.remove('wrapper-searching');
|
searchWrapper.classList.remove('wrapper-searching');
|
||||||
|
|
||||||
// Submit the form or navigate to search results
|
|
||||||
const form = searchInput.closest('form');
|
const form = searchInput.closest('form');
|
||||||
if (form) {
|
form ? form.submit() : window.location.href = `/search?q=${encodeURIComponent(query)}&t=web`;
|
||||||
form.submit();
|
|
||||||
} else {
|
|
||||||
window.location.href = `/search?q=${encodeURIComponent(query)}&t=web`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle clicks on search suggestions
|
// Handle clicks on search suggestions
|
||||||
|
|
Loading…
Add table
Reference in a new issue