ehristoforu
commited on
Commit
•
322d8d3
1
Parent(s):
881407a
Create scripts.js
Browse files- scripts.js +208 -0
scripts.js
ADDED
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const BASE_URL = "https://oevortex-webscout-api.hf.space";
|
2 |
+
const searchForm = document.getElementById("search-form");
|
3 |
+
const searchQueryInput = document.getElementById("search-query");
|
4 |
+
const resultsContainer = document.getElementById("results");
|
5 |
+
const suggestionsContainer = document.getElementById("suggestions");
|
6 |
+
const loadingOverlay = document.querySelector('.loading-overlay');
|
7 |
+
const noResultsMessage = document.getElementById('no-results');
|
8 |
+
const loadingMoreIndicator = document.getElementById('loading-more');
|
9 |
+
const aiResponseContainer = document.getElementById('ai-response');
|
10 |
+
|
11 |
+
const INITIAL_RESULTS = 5;
|
12 |
+
const CACHED_RESULTS = 50;
|
13 |
+
const RESULTS_PER_PAGE = 5;
|
14 |
+
|
15 |
+
let allResultsFetched = false;
|
16 |
+
const seenUrls = new Set();
|
17 |
+
let selectedSuggestionIndex = -1;
|
18 |
+
let suggestionRequestTimeout;
|
19 |
+
let cachedSearchResults = [];
|
20 |
+
const suggestionCache = {};
|
21 |
+
let prefetchTimeout;
|
22 |
+
let allResults = [];
|
23 |
+
let startTime;
|
24 |
+
|
25 |
+
function debounce(func, delay) {
|
26 |
+
return function() {
|
27 |
+
clearTimeout(suggestionRequestTimeout);
|
28 |
+
suggestionRequestTimeout = setTimeout(() => {
|
29 |
+
func.apply(this, arguments);
|
30 |
+
}, delay);
|
31 |
+
};
|
32 |
+
}
|
33 |
+
|
34 |
+
async function fetchSuggestions(query) {
|
35 |
+
if (suggestionCache[query]) {
|
36 |
+
return suggestionCache[query];
|
37 |
+
}
|
38 |
+
try {
|
39 |
+
const response = await fetch(`${BASE_URL}/api/suggestions?q=${encodeURIComponent(query)}`);
|
40 |
+
if (response.ok) {
|
41 |
+
const suggestions = await response.json();
|
42 |
+
suggestionCache[query] = suggestions;
|
43 |
+
return suggestions;
|
44 |
+
} else {
|
45 |
+
console.error("Error fetching suggestions:", response.status);
|
46 |
+
return [];
|
47 |
+
}
|
48 |
+
} catch (error) {
|
49 |
+
console.error("Error fetching suggestions:", error);
|
50 |
+
return [];
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
searchQueryInput.addEventListener("input", () => {
|
55 |
+
clearTimeout(prefetchTimeout);
|
56 |
+
const searchQuery = searchQueryInput.value.trim();
|
57 |
+
if (searchQuery === "") {
|
58 |
+
suggestionsContainer.style.display = "none";
|
59 |
+
return;
|
60 |
+
}
|
61 |
+
prefetchTimeout = setTimeout(async () => {
|
62 |
+
const suggestions = await fetchSuggestions(searchQuery);
|
63 |
+
displaySuggestions(suggestions);
|
64 |
+
}, 100);
|
65 |
+
});
|
66 |
+
|
67 |
+
function displaySuggestions(suggestions) {
|
68 |
+
suggestionsContainer.innerHTML = "";
|
69 |
+
if (suggestions.length === 0 || searchQueryInput.value.trim() === "") {
|
70 |
+
suggestionsContainer.style.display = "none";
|
71 |
+
return;
|
72 |
+
}
|
73 |
+
const suggestionList = document.createElement("ul");
|
74 |
+
suggestions.forEach((suggestion, index) => {
|
75 |
+
const listItem = document.createElement("li");
|
76 |
+
listItem.textContent = suggestion.phrase;
|
77 |
+
listItem.addEventListener("click", () => {
|
78 |
+
searchQueryInput.value = suggestion.phrase;
|
79 |
+
suggestionsContainer.style.display = "none";
|
80 |
+
performSearch(suggestion.phrase);
|
81 |
+
});
|
82 |
+
listItem.addEventListener("focus", () => {
|
83 |
+
selectedSuggestionIndex = index;
|
84 |
+
updateSuggestionSelection();
|
85 |
+
});
|
86 |
+
suggestionList.appendChild(listItem);
|
87 |
+
});
|
88 |
+
suggestionsContainer.appendChild(suggestionList);
|
89 |
+
suggestionsContainer.style.display = "block";
|
90 |
+
}
|
91 |
+
|
92 |
+
function updateSuggestionSelection() {
|
93 |
+
const suggestionItems = suggestionsContainer.querySelectorAll("li");
|
94 |
+
suggestionItems.forEach((item, index) => {
|
95 |
+
item.classList.toggle("selected", index === selectedSuggestionIndex);
|
96 |
+
});
|
97 |
+
}
|
98 |
+
|
99 |
+
function showLoading() {
|
100 |
+
loadingOverlay.style.display = 'block';
|
101 |
+
}
|
102 |
+
|
103 |
+
function hideLoading() {
|
104 |
+
loadingOverlay.style.display = 'none';
|
105 |
+
}
|
106 |
+
|
107 |
+
async function performSearch(query) {
|
108 |
+
showLoading();
|
109 |
+
aiResponseContainer.style.display = 'none';
|
110 |
+
suggestionsContainer.style.display = "none";
|
111 |
+
startTime = performance.now();
|
112 |
+
seenUrls.clear();
|
113 |
+
allResultsFetched = false;
|
114 |
+
resultsContainer.innerHTML = '';
|
115 |
+
noResultsMessage.style.display = 'none';
|
116 |
+
loadingMoreIndicator.classList.remove('active');
|
117 |
+
speechSynthesis.cancel();
|
118 |
+
|
119 |
+
const initialResults = await fetchResults(query, INITIAL_RESULTS);
|
120 |
+
displayResults(initialResults);
|
121 |
+
hideLoading();
|
122 |
+
|
123 |
+
fetchResults(query, CACHED_RESULTS).then(cachedResults => {
|
124 |
+
cachedSearchResults = removeDuplicateResults(cachedResults);
|
125 |
+
allResults = allResults.concat(cachedSearchResults);
|
126 |
+
displayResults(cachedSearchResults.slice(INITIAL_RESULTS, RESULTS_PER_PAGE), true);
|
127 |
+
|
128 |
+
if (cachedSearchResults.length > RESULTS_PER_PAGE) {
|
129 |
+
allResultsFetched = false;
|
130 |
+
loadingMoreIndicator.classList.add('active');
|
131 |
+
}
|
132 |
+
});
|
133 |
+
|
134 |
+
fetchAIResponse(query).then(aiResponse => {
|
135 |
+
displayAIResponse(aiResponse);
|
136 |
+
aiResponseContainer.style.display = 'block';
|
137 |
+
}).catch(error => {
|
138 |
+
console.error("Error fetching AI response:", error);
|
139 |
+
});
|
140 |
+
|
141 |
+
updateURLWithQuery(query);
|
142 |
+
}
|
143 |
+
|
144 |
+
async function fetchAIResponse(query) {
|
145 |
+
try {
|
146 |
+
const encodedQuery = encodeURIComponent(query);
|
147 |
+
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`);
|
148 |
+
if (response.ok) {
|
149 |
+
const aiResponse = await response.json();
|
150 |
+
return aiResponse;
|
151 |
+
} else {
|
152 |
+
console.error("Error fetching AI response from website:", response.status);
|
153 |
+
return null;
|
154 |
+
}
|
155 |
+
} catch (error) {
|
156 |
+
console.error("Error fetching AI response from website:", error);
|
157 |
+
return null;
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
function displayAIResponse(response) {
|
162 |
+
aiResponseContainer.innerHTML = '';
|
163 |
+
if (response) {
|
164 |
+
const aiResultElement = document.createElement('div');
|
165 |
+
aiResultElement.classList.add('ai-result');
|
166 |
+
const aiHeading = document.createElement('h2');
|
167 |
+
aiHeading.textContent = "AI Response";
|
168 |
+
aiResultElement.appendChild(aiHeading);
|
169 |
+
const aiText = document.createElement('p');
|
170 |
+
const decodedResponse = decodeHtml(response);
|
171 |
+
const msg = new SpeechSynthesisUtterance(decodedResponse);
|
172 |
+
speechSynthesis.speak(msg);
|
173 |
+
aiText.textContent = decodedResponse;
|
174 |
+
const pauseButton = document.createElement('button');
|
175 |
+
pauseButton.id = 'pause';
|
176 |
+
pauseButton.innerHTML = '<i class="fas fa-pause"></i>';
|
177 |
+
const stopButton = document.createElement('button');
|
178 |
+
stopButton.id = 'stop';
|
179 |
+
stopButton.innerHTML = '<i class="fas fa-stop"></i>';
|
180 |
+
let isPaused = false;
|
181 |
+
let isStoped = false;
|
182 |
+
pauseButton.addEventListener('click', () => {
|
183 |
+
if ('speechSynthesis' in window) {
|
184 |
+
if (isPaused) {
|
185 |
+
window.speechSynthesis.resume();
|
186 |
+
isPaused = false;
|
187 |
+
stopButton.style.display = 'inline-block';
|
188 |
+
pauseButton.innerHTML = '<i class="fas fa-pause"></i>';
|
189 |
+
} else {
|
190 |
+
window.speechSynthesis.pause();
|
191 |
+
isPaused = true;
|
192 |
+
stopButton.style.display = 'none';
|
193 |
+
pauseButton.innerHTML = '<i class="fas fa-play"></i>';
|
194 |
+
}
|
195 |
+
}
|
196 |
+
});
|
197 |
+
|
198 |
+
stopButton.addEventListener('click', () => {
|
199 |
+
if ('speechSynthesis' in window) {
|
200 |
+
if (isStoped) {
|
201 |
+
speechSynthesis.speak(msg);
|
202 |
+
isPaused = false;
|
203 |
+
isStoped = false;
|
204 |
+
pauseButton.innerHTML = '<i class="fas fa-pause"></i>';
|
205 |
+
pauseButton.style.display = 'inline-block';
|
206 |
+
stopButton.innerHTML = '<i class="fas fa-stop"></i>';
|
207 |
+
} else {
|
208 |
+
window.speechSynthesis.cancel();
|