/* 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. */ document.addEventListener('DOMContentLoaded', () => { const searchInput = document.getElementById('search-input'); const searchWrapper = document.querySelector('.wrapper, .wrapper-results'); const resultsWrapper = document.querySelector('.autocomplete'); let suggestions = []; let currentIndex = -1; // Keep track of the currently selected suggestion // Fetch suggestions from the server async function getSuggestions(query) { try { const response = await fetch(`/suggestions?q=${encodeURIComponent(query)}`); const data = await response.json(); return data[1]; // Return only the array of suggestion strings } catch (error) { console.error('Error fetching suggestions:', error); return []; } } // Function to render results function renderSuggestions(results) { if (!results || !results.length) { searchWrapper.classList.remove('wrapper-searching'); resultsWrapper.innerHTML = ''; return; } let content = ''; results.forEach((item, index) => { content += `
  • ${item}
  • `; }); resultsWrapper.innerHTML = ``; searchWrapper.classList.add('wrapper-searching'); } // Fetch suggestions when input is focused searchInput.addEventListener('focus', async () => { const query = searchInput.value.trim(); suggestions = await getSuggestions(query); renderSuggestions(suggestions); currentIndex = -1; }); // Handle input event searchInput.addEventListener('input', async () => { const query = searchInput.value.trim(); if (query.length > 0) { suggestions = await getSuggestions(query); } else { suggestions = []; } currentIndex = -1; // Reset index when new results come in renderSuggestions(suggestions); }); // Handle keydown events for navigation searchInput.addEventListener('keydown', (event) => { const items = resultsWrapper.querySelectorAll('li'); if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'Tab') { event.preventDefault(); // Remove 'selected' class from the current item if (items[currentIndex]) { items[currentIndex].classList.remove('selected'); } 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]) { items[currentIndex].classList.add('selected'); searchInput.value = items[currentIndex].textContent; } } else if (event.key === 'Enter') { if (currentIndex > -1 && items[currentIndex]) { event.preventDefault(); selectSuggestion(items[currentIndex]); } } }); // Function to handle suggestion selection function selectSuggestion(item) { const query = item.textContent; searchInput.value = query; resultsWrapper.innerHTML = ''; searchWrapper.classList.remove('wrapper-searching'); // Submit the form or navigate to search results const form = searchInput.closest('form'); if (form) { form.submit(); } else { window.location.href = `/search?q=${encodeURIComponent(query)}&t=web`; } } // Handle clicks on search suggestions resultsWrapper.addEventListener('click', (event) => { if (event.target.tagName === 'LI') { selectSuggestion(event.target); } }); // Close the suggestions when clicking outside document.addEventListener('click', (event) => { if (!searchWrapper.contains(event.target)) { searchWrapper.classList.remove('wrapper-searching'); resultsWrapper.innerHTML = ''; currentIndex = -1; } }); });