| const BASE_URL = "https://oevortex-webscout-api.hf.space"; |
| const searchForm = document.getElementById("search-form"); |
| const searchQueryInput = document.getElementById("search-query"); |
| const resultsContainer = document.getElementById("results"); |
| const suggestionsContainer = document.getElementById("suggestions"); |
| const loadingOverlay = document.querySelector('.loading-overlay'); |
| const noResultsMessage = document.getElementById('no-results'); |
| const loadingMoreIndicator = document.getElementById('loading-more'); |
| const aiResponseContainer = document.getElementById('ai-response'); |
|
|
| const INITIAL_RESULTS = 5; |
| const CACHED_RESULTS = 50; |
| const RESULTS_PER_PAGE = 5; |
|
|
| let allResultsFetched = false; |
| const seenUrls = new Set(); |
| let selectedSuggestionIndex = -1; |
| let suggestionRequestTimeout; |
| let cachedSearchResults = []; |
| const suggestionCache = {}; |
| let prefetchTimeout; |
| let allResults = []; |
| let startTime; |
|
|
| function debounce(func, delay) { |
| return function() { |
| clearTimeout(suggestionRequestTimeout); |
| suggestionRequestTimeout = setTimeout(() => { |
| func.apply(this, arguments); |
| }, delay); |
| }; |
| } |
|
|
| async function fetchSuggestions(query) { |
| if (suggestionCache[query]) { |
| return suggestionCache[query]; |
| } |
| try { |
| const response = await fetch(`${BASE_URL}/api/suggestions?q=${encodeURIComponent(query)}`); |
| if (response.ok) { |
| const suggestions = await response.json(); |
| suggestionCache[query] = suggestions; |
| return suggestions; |
| } else { |
| console.error("Error fetching suggestions:", response.status); |
| return []; |
| } |
| } catch (error) { |
| console.error("Error fetching suggestions:", error); |
| return []; |
| } |
| } |
|
|
| searchQueryInput.addEventListener("input", () => { |
| clearTimeout(prefetchTimeout); |
| const searchQuery = searchQueryInput.value.trim(); |
| if (searchQuery === "") { |
| suggestionsContainer.style.display = "none"; |
| return; |
| } |
| prefetchTimeout = setTimeout(async () => { |
| const suggestions = await fetchSuggestions(searchQuery); |
| displaySuggestions(suggestions); |
| }, 100); |
| }); |
|
|
| function displaySuggestions(suggestions) { |
| suggestionsContainer.innerHTML = ""; |
| if (suggestions.length === 0 || searchQueryInput.value.trim() === "") { |
| suggestionsContainer.style.display = "none"; |
| return; |
| } |
| const suggestionList = document.createElement("ul"); |
| suggestions.forEach((suggestion, index) => { |
| const listItem = document.createElement("li"); |
| listItem.textContent = suggestion.phrase; |
| listItem.addEventListener("click", () => { |
| searchQueryInput.value = suggestion.phrase; |
| suggestionsContainer.style.display = "none"; |
| performSearch(suggestion.phrase); |
| }); |
| listItem.addEventListener("focus", () => { |
| selectedSuggestionIndex = index; |
| updateSuggestionSelection(); |
| }); |
| suggestionList.appendChild(listItem); |
| }); |
| suggestionsContainer.appendChild(suggestionList); |
| suggestionsContainer.style.display = "block"; |
| } |
|
|
| function updateSuggestionSelection() { |
| const suggestionItems = suggestionsContainer.querySelectorAll("li"); |
| suggestionItems.forEach((item, index) => { |
| item.classList.toggle("selected", index === selectedSuggestionIndex); |
| }); |
| } |
|
|
| function showLoading() { |
| loadingOverlay.style.display = 'block'; |
| } |
|
|
| function hideLoading() { |
| loadingOverlay.style.display = 'none'; |
| } |
|
|
| async function performSearch(query) { |
| showLoading(); |
| aiResponseContainer.style.display = 'none'; |
| suggestionsContainer.style.display = "none"; |
| startTime = performance.now(); |
| seenUrls.clear(); |
| allResultsFetched = false; |
| resultsContainer.innerHTML = ''; |
| noResultsMessage.style.display = 'none'; |
| loadingMoreIndicator.classList.remove('active'); |
| speechSynthesis.cancel(); |
|
|
| const initialResults = await fetchResults(query, INITIAL_RESULTS); |
| displayResults(initialResults); |
| hideLoading(); |
|
|
| fetchResults(query, CACHED_RESULTS).then(cachedResults => { |
| cachedSearchResults = removeDuplicateResults(cachedResults); |
| allResults = allResults.concat(cachedSearchResults); |
| displayResults(cachedSearchResults.slice(INITIAL_RESULTS, RESULTS_PER_PAGE), true); |
| |
| if (cachedSearchResults.length > RESULTS_PER_PAGE) { |
| allResultsFetched = false; |
| loadingMoreIndicator.classList.add('active'); |
| } |
| }); |
|
|
| fetchAIResponse(query).then(aiResponse => { |
| displayAIResponse(aiResponse); |
| aiResponseContainer.style.display = 'block'; |
| }).catch(error => { |
| console.error("Error fetching AI response:", error); |
| }); |
|
|
| updateURLWithQuery(query); |
| } |
|
|
| async function fetchAIResponse(query) { |
| try { |
| const encodedQuery = encodeURIComponent(query); |
| const response = await fetch(`${BASE_URL}/api/ask_website?url=https://google.com/search?q=${encodedQuery}&question=Answer this question from google search result ${encodedQuery}&model=gpt-4o-mini`); |
| if (response.ok) { |
| const aiResponse = await response.json(); |
| return aiResponse; |
| } else { |
| console.error("Error fetching AI response from website:", response.status); |
| return null; |
| } |
| } catch (error) { |
| console.error("Error fetching AI response from website:", error); |
| return null; |
| } |
| } |
|
|
| function displayAIResponse(response) { |
| aiResponseContainer.innerHTML = ''; |
| if (response) { |
| const aiResultElement = document.createElement('div'); |
| aiResultElement.classList.add('ai-result'); |
| const aiHeading = document.createElement('h2'); |
| aiHeading.textContent = "AI Response"; |
| aiResultElement.appendChild(aiHeading); |
| const aiText = document.createElement('p'); |
| const decodedResponse = decodeHtml(response); |
| const msg = new SpeechSynthesisUtterance(decodedResponse); |
| speechSynthesis.speak(msg); |
| aiText.textContent = decodedResponse; |
| const pauseButton = document.createElement('button'); |
| pauseButton.id = 'pause'; |
| pauseButton.innerHTML = '<i class="fas fa-pause"></i>'; |
| const stopButton = document.createElement('button'); |
| stopButton.id = 'stop'; |
| stopButton.innerHTML = '<i class="fas fa-stop"></i>'; |
| let isPaused = false; |
| let isStoped = false; |
| pauseButton.addEventListener('click', () => { |
| if ('speechSynthesis' in window) { |
| if (isPaused) { |
| window.speechSynthesis.resume(); |
| isPaused = false; |
| stopButton.style.display = 'inline-block'; |
| pauseButton.innerHTML = '<i class="fas fa-pause"></i>'; |
| } else { |
| window.speechSynthesis.pause(); |
| isPaused = true; |
| stopButton.style.display = 'none'; |
| pauseButton.innerHTML = '<i class="fas fa-play"></i>'; |
| } |
| } |
| }); |
|
|
| stopButton.addEventListener('click', () => { |
| if ('speechSynthesis' in window) { |
| if (isStoped) { |
| speechSynthesis.speak(msg); |
| isPaused = false; |
| isStoped = false; |
| pauseButton.innerHTML = '<i class="fas fa-pause"></i>'; |
| pauseButton.style.display = 'inline-block'; |
| stopButton.innerHTML = '<i class="fas fa-stop"></i>'; |
| } else { |
| window.speechSynthesis.cancel(); |