KingNish commited on
Commit
cbf0a6d
·
verified ·
1 Parent(s): 8d4bd9c

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +283 -292
templates/index.html CHANGED
@@ -140,364 +140,355 @@ const suggestionCache = {};
140
  let prefetchTimeout;
141
 
142
  function debounce(func, delay) {
143
- return function() {
144
- clearTimeout(suggestionRequestTimeout);
145
- suggestionRequestTimeout = setTimeout(() => {
146
- func.apply(this, arguments);
147
- }, delay);
148
- };
149
  }
150
-
151
  async function fetchSuggestions(query) {
152
- if (suggestionCache[query]) {
153
- return suggestionCache[query];
154
- }
155
- try {
156
- const response = await fetch(`${BASE_URL}/api/suggestions?q=${encodeURIComponent(query)}`);
157
- if (response.ok) {
158
- const suggestions = await response.json();
159
- suggestionCache[query] = suggestions;
160
- return suggestions;
161
- } else {
162
- console.error("Error fetching suggestions:", response.status);
163
- return [];
164
- }
165
- } catch (error) {
166
- console.error("Error fetching suggestions:", error);
167
- return [];
168
- }
169
  }
170
-
171
  // Event listeners for Intro Search
172
  searchQueryInput.addEventListener("input", () => {
173
- clearTimeout(prefetchTimeout);
174
- const searchQuery = searchQueryInput.value.trim();
175
- if (searchQuery === "") {
176
- suggestionsContainer.style.display = "none";
177
- return;
178
- }
179
- prefetchTimeout = setTimeout(async () => {
180
- const suggestions = await fetchSuggestions(searchQuery);
181
- displaySuggestions(suggestions);
182
- }, 100);
183
  });
184
-
185
  searchForm.addEventListener("submit", async (event) => {
186
- event.preventDefault();
187
- selectedSuggestionIndex = -1;
188
- const searchQuery = searchQueryInput.value;
189
- performSearch(searchQuery);
190
  });
191
-
192
  // Event listeners for Main Content Search
193
  mainSearchQueryInput.addEventListener("input", () => {
194
- clearTimeout(prefetchTimeout);
195
- const searchQuery = mainSearchQueryInput.value.trim();
196
- if (searchQuery === "") {
197
- mainSuggestionsContainer.style.display = "none";
198
- return;
199
- }
200
- prefetchTimeout = setTimeout(async () => {
201
- const suggestions = await fetchSuggestions(searchQuery);
202
- displaySuggestions(suggestions, mainSuggestionsContainer);
203
- }, 100);
204
  });
205
-
206
  mainSearchForm.addEventListener("submit", async (event) => {
207
- event.preventDefault();
208
- selectedSuggestionIndex = -1;
209
- const searchQuery = mainSearchQueryInput.value;
210
- performSearch(searchQuery);
211
  });
212
 
213
  function displaySuggestions(suggestions, container = suggestionsContainer) {
214
- container.innerHTML = "";
215
- if (suggestions.length === 0 || (searchQueryInput.value.trim() === "" && mainSearchQueryInput.value.trim() === "")) {
216
- container.style.display = "none";
217
- container.style.opacity = 0;
218
- return;
219
- }
220
- const suggestionList = document.createElement("ul");
221
- suggestions.forEach((suggestion, index) => {
222
- const listItem = document.createElement("li");
223
- listItem.textContent = suggestion.phrase;
224
- listItem.addEventListener("click", () => {
225
- if (container === suggestionsContainer) {
226
- searchQueryInput.value = suggestion.phrase;
227
- } else {
228
- mainSearchQueryInput.value = suggestion.phrase;
229
- }
230
- container.style.display = "none";
231
- container.style.opacity = 0;
232
- performSearch(suggestion.phrase);
233
- });
234
- listItem.addEventListener("focus", () => {
235
- selectedSuggestionIndex = index;
236
- updateSuggestionSelection(container);
237
- });
238
- suggestionList.appendChild(listItem);
239
- });
240
- container.appendChild(suggestionList);
241
- container.style.display = "block";
242
- container.style.opacity = 1;
243
  }
244
 
245
  function updateSuggestionSelection(container) {
246
- const suggestionItems = container.querySelectorAll("li");
247
- suggestionItems.forEach((item, index) => {
248
- item.classList.toggle("selected", index === selectedSuggestionIndex);
249
- });
250
- // Make sure the mainSuggestionsContainer is displayed when needed
251
- if (container === mainSuggestionsContainer && selectedSuggestionIndex !== -1) {
252
- mainSuggestionsContainer.style.display = "block";
253
- }
254
  }
255
 
256
  function showLoading() {
257
- loadingOverlay.style.display = 'block';
258
  }
259
 
260
  function hideLoading() {
261
- loadingOverlay.style.display = 'none';
262
  }
263
-
264
  let startTime;
265
  async function performSearch(query) {
266
- showLoading();
267
- seenUrls.clear();
268
- allResultsFetched = false;
269
- resultsContainer.innerHTML = '';
270
- noResultsMessage.style.display = 'none';
271
- loadingMoreIndicator.classList.remove('active');
272
- suggestionsContainer.style.display = 'none';
273
- mainSuggestionsContainer.style.display = 'none';
274
- startTime = performance.now();
275
- const initialResults = await fetchResults(query, INITIAL_RESULTS);
276
- updateURLWithQuery(query);
277
- displayResults(initialResults);
278
- hideLoading();
279
- if (initialResults.length > 0) {
280
- cachedSearchResults = await fetchResults(query, CACHED_RESULTS);
281
- cachedSearchResults = removeDuplicateResults(cachedSearchResults);
282
- } else {
283
- cachedSearchResults = [];
284
- }
285
- introPage.style.display = 'none';
286
- mainContent.style.display = 'flex';
287
  }
288
 
289
  function updateURLWithQuery(query) {
290
- const newURL = `${window.location.pathname}?query=${encodeURIComponent(query)}`;
291
- window.history.pushState({ path: newURL }, '', newURL);
 
 
292
  }
293
 
294
  function removeDuplicateResults(results) {
295
- const uniqueResults = [];
296
- const seen = new Set();
297
- for (const result of results) {
298
- if (!seen.has(result.href)) {
299
- seen.add(result.href);
300
- uniqueResults.push(result);
301
- }
302
- }
303
- return uniqueResults;
304
  }
305
-
306
  async function fetchResults(query, resultsPerPage) {
307
- const response = await fetch(`${BASE_URL}/api/search?q=${encodeURIComponent(query)}&max_results=${resultsPerPage}`);
308
- if (!response.ok) {
309
- displayError("An error occurred while fetching results.");
310
- hideLoading();
311
- return [];
312
- }
313
- const searchResults = await response.json();
314
- return searchResults;
315
  }
316
 
317
  function displayResults(results, append = false) {
318
- if (!append) {
319
- resultsContainer.innerHTML = '';
320
- }
321
- const newResults = results.filter(result => !seenUrls.has(result.href));
322
- newResults.forEach((result, index) => {
323
- seenUrls.add(result.href);
324
- const resultElement = document.createElement("div");
325
- resultElement.classList.add("result");
326
- const titleElement = document.createElement("h3");
327
- const titleLink = document.createElement("a");
328
- titleLink.href = result.href;
329
- titleLink.textContent = result.title;
330
- titleLink.target = "_blank";
331
- titleLink.rel = "noopener noreferrer";
332
- titleElement.appendChild(titleLink);
333
- const urlElement = document.createElement("div");
334
- urlElement.classList.add("url");
335
- const urlLink = document.createElement("a");
336
- urlLink.href = result.href;
337
- urlLink.textContent = result.href;
338
- urlLink.target = "_blank";
339
- urlLink.rel = "noopener noreferrer";
340
- urlElement.appendChild(urlLink);
341
- const descriptionElement = document.createElement("p");
342
- descriptionElement.textContent = result.body;
343
- resultElement.appendChild(titleElement);
344
- resultElement.appendChild(urlElement);
345
- resultElement.appendChild(descriptionElement);
346
- resultsContainer.appendChild(resultElement);
347
- setTimeout(() => {
348
- resultElement.classList.add("show");
349
- }, 100 * index);
350
- });
351
- noResultsMessage.style.display = resultsContainer.children.length === 0 ? 'block' : 'none';
352
- if (!append) {
353
- const endTime = performance.now();
354
- const timeTaken = (endTime - startTime).toFixed(2);
355
- document.getElementById('results-info').textContent = `About ${timeTaken} milliseconds`;
356
- }
357
  }
358
 
359
  function displayError(message) {
360
- resultsContainer.innerHTML = "";
361
- const errorElement = document.createElement("p");
362
- errorElement.textContent = message;
363
- errorElement.style.color = "red";
364
- resultsContainer.appendChild(errorElement);
365
  }
366
-
367
  searchQueryInput.addEventListener("input", debounce(async () => {
368
- selectedSuggestionIndex = -1;
369
- const searchQuery = searchQueryInput.value;
370
- if (searchQuery.trim() === "") {
371
- suggestionsContainer.style.display = "none";
372
- return;
373
- }
374
- const suggestions = await fetchSuggestions(searchQuery);
375
- displaySuggestions(suggestions);
376
  }));
377
-
378
  mainSearchQueryInput.addEventListener("input", debounce(async () => {
379
- selectedSuggestionIndex = -1;
380
- const searchQuery = mainSearchQueryInput.value;
381
- if (searchQuery.trim() === "") {
382
- mainSuggestionsContainer.style.display = "none";
383
- return;
384
- }
385
- const suggestions = await fetchSuggestions(searchQuery);
386
- displaySuggestions(suggestions, mainSuggestionsContainer);
387
  }));
388
-
389
  searchQueryInput.addEventListener("focus", () => {
390
- if (searchQueryInput.value.trim() !== "") {
391
- suggestionsContainer.style.display = "block";
392
- }
393
  });
394
  mainSearchQueryInput.addEventListener("focus", () => {
395
- if (mainSearchQueryInput.value.trim() !== "") {
396
- mainSuggestionsContainer.style.display = "block";
397
- }
398
  });
399
-
400
  document.addEventListener("click", (event) => {
401
- if (!searchForm.contains(event.target) && !mainSearchForm.contains(event.target)) {
402
- suggestionsContainer.style.display = "none";
403
- mainSuggestionsContainer.style.display = "none";
404
- }
405
  });
406
-
407
  searchQueryInput.addEventListener("keydown", async (event) => {
408
- if (event.key === "ArrowUp" || event.key === "ArrowDown") {
409
- event.preventDefault();
410
- const suggestionItems = suggestionsContainer.querySelectorAll("li");
411
- const numSuggestions = suggestionItems.length;
412
- if (event.key === "ArrowUp") {
413
- selectedSuggestionIndex = (selectedSuggestionIndex - 1 + numSuggestions) % numSuggestions;
414
- } else {
415
- selectedSuggestionIndex = (selectedSuggestionIndex + 1) % numSuggestions;
416
- }
417
- updateSuggestionSelection(suggestionsContainer);
418
- if (selectedSuggestionIndex !== -1 && suggestionItems[selectedSuggestionIndex]) {
419
- searchQueryInput.value = suggestionItems[selectedSuggestionIndex].textContent;
420
- suggestionItems[selectedSuggestionIndex].focus();
421
- }
422
- } else if (event.key === "Enter" && selectedSuggestionIndex !== -1) {
423
- event.preventDefault();
424
- const selectedSuggestion = suggestionsContainer.querySelectorAll("li")[selectedSuggestionIndex];
425
- if (selectedSuggestion) {
426
- searchQueryInput.value = selectedSuggestion.textContent;
427
- suggestionsContainer.style.display = "none";
428
- performSearch(searchQueryInput.value);
429
- }
430
- }
431
  });
432
  mainSearchQueryInput.addEventListener("keydown", async (event) => {
433
- if (event.key === "ArrowUp" || event.key === "ArrowDown") {
434
- event.preventDefault();
435
- const suggestionItems = mainSuggestionsContainer.querySelectorAll("li");
436
- const numSuggestions = suggestionItems.length;
437
- if (event.key === "ArrowUp") {
438
- selectedSuggestionIndex = (selectedSuggestionIndex - 1 + numSuggestions) % numSuggestions;
439
- } else {
440
- selectedSuggestionIndex = (selectedSuggestionIndex + 1) % numSuggestions;
441
- }
442
- updateSuggestionSelection(mainSuggestionsContainer);
443
- if (selectedSuggestionIndex !== -1 && suggestionItems[selectedSuggestionIndex]) {
444
- mainSearchQueryInput.value = suggestionItems[selectedSuggestionIndex].textContent;
445
- suggestionItems[selectedSuggestionIndex].focus();
446
- }
447
- } else if (event.key === "Enter" && selectedSuggestionIndex !== -1) {
448
- event.preventDefault();
449
- const selectedSuggestion = mainSuggestionsContainer.querySelectorAll("li")[selectedSuggestionIndex];
450
- if (selectedSuggestion) {
451
- mainSearchQueryInput.value = selectedSuggestion.textContent;
452
- mainSuggestionsContainer.style.display = "none";
453
- performSearch(mainSearchQueryInput.value);
454
- }
455
- }
456
  });
457
-
458
  searchForm.addEventListener("submit", async (event) => {
459
- event.preventDefault();
460
- selectedSuggestionIndex = -1;
461
- const searchQuery = searchQueryInput.value;
462
- performSearch(searchQuery);
463
  });
464
  mainSearchForm.addEventListener("submit", async (event) => {
465
- event.preventDefault();
466
- selectedSuggestionIndex = -1;
467
- const searchQuery = mainSearchQueryInput.value;
468
- performSearch(searchQuery);
469
  });
470
-
471
  window.addEventListener("scroll", () => {
472
- if (allResultsFetched || cachedSearchResults.length === 0) return;
473
- const { scrollTop, scrollHeight, clientHeight } = document.documentElement;
474
- if (scrollTop + clientHeight >= scrollHeight - 100 && !loadingMoreIndicator.classList.contains("active")) {
475
- loadingMoreIndicator.classList.add("active");
476
- const resultsToDisplay = cachedSearchResults.splice(0, RESULTS_PER_PAGE);
477
- if (resultsToDisplay.length > 0) {
478
- displayResults(resultsToDisplay, true);
479
- }
480
- if (cachedSearchResults.length === 0) {
481
- allResultsFetched = true;
482
- }
483
- loadingMoreIndicator.classList.remove("active");
484
- }
 
 
 
 
485
  });
486
 
487
  function getQueryParameter(name) {
488
- const urlParams = new URLSearchParams(window.location.search);
489
- return urlParams.get(name);
490
  }
491
-
492
  window.addEventListener('load', () => {
493
- const initialQuery = getQueryParameter('query');
494
- if (initialQuery) {
495
- mainSearchQueryInput.value = initialQuery;
496
- performSearch(initialQuery);
497
- } else {
498
- introPage.style.display = 'flex';
499
- mainContent.style.display = 'none';
500
- }
501
  });
502
  </script>
503
  </body>
 
140
  let prefetchTimeout;
141
 
142
  function debounce(func, delay) {
143
+ return function() {
144
+ clearTimeout(suggestionRequestTimeout);
145
+ suggestionRequestTimeout = setTimeout(() => {
146
+ func.apply(this, arguments);
147
+ }, delay);
148
+ };
149
  }
 
150
  async function fetchSuggestions(query) {
151
+ if (suggestionCache[query]) {
152
+ return suggestionCache[query];
153
+ }
154
+ try {
155
+ const response = await fetch(`${BASE_URL}/api/suggestions?q=${encodeURIComponent(query)}`);
156
+ if (response.ok) {
157
+ const suggestions = await response.json();
158
+ suggestionCache[query] = suggestions;
159
+ return suggestions;
160
+ } else {
161
+ console.error("Error fetching suggestions:", response.status);
162
+ return [];
163
+ }
164
+ } catch (error) {
165
+ console.error("Error fetching suggestions:", error);
166
+ return [];
167
+ }
168
  }
 
169
  // Event listeners for Intro Search
170
  searchQueryInput.addEventListener("input", () => {
171
+ clearTimeout(prefetchTimeout);
172
+ const searchQuery = searchQueryInput.value.trim();
173
+ if (searchQuery === "") {
174
+ suggestionsContainer.style.display = "none";
175
+ return;
176
+ }
177
+ prefetchTimeout = setTimeout(async () => {
178
+ const suggestions = await fetchSuggestions(searchQuery);
179
+ displaySuggestions(suggestions);
180
+ }, 100);
181
  });
 
182
  searchForm.addEventListener("submit", async (event) => {
183
+ event.preventDefault();
184
+ selectedSuggestionIndex = -1;
185
+ const searchQuery = searchQueryInput.value;
186
+ performSearch(searchQuery);
187
  });
 
188
  // Event listeners for Main Content Search
189
  mainSearchQueryInput.addEventListener("input", () => {
190
+ clearTimeout(prefetchTimeout);
191
+ const searchQuery = mainSearchQueryInput.value.trim();
192
+ if (searchQuery === "") {
193
+ mainSuggestionsContainer.style.display = "none";
194
+ return;
195
+ }
196
+ prefetchTimeout = setTimeout(async () => {
197
+ const suggestions = await fetchSuggestions(searchQuery);
198
+ displaySuggestions(suggestions, mainSuggestionsContainer);
199
+ }, 100);
200
  });
 
201
  mainSearchForm.addEventListener("submit", async (event) => {
202
+ event.preventDefault();
203
+ selectedSuggestionIndex = -1;
204
+ const searchQuery = mainSearchQueryInput.value;
205
+ performSearch(searchQuery);
206
  });
207
 
208
  function displaySuggestions(suggestions, container = suggestionsContainer) {
209
+ container.innerHTML = "";
210
+ if (suggestions.length === 0 || (searchQueryInput.value.trim() === "" && mainSearchQueryInput.value.trim() === "")) {
211
+ container.style.display = "none";
212
+ container.style.opacity = 0;
213
+ return;
214
+ }
215
+ const suggestionList = document.createElement("ul");
216
+ suggestions.forEach((suggestion, index) => {
217
+ const listItem = document.createElement("li");
218
+ listItem.textContent = suggestion.phrase;
219
+ listItem.addEventListener("click", () => {
220
+ if (container === suggestionsContainer) {
221
+ searchQueryInput.value = suggestion.phrase;
222
+ } else {
223
+ mainSearchQueryInput.value = suggestion.phrase;
224
+ }
225
+ container.style.display = "none";
226
+ container.style.opacity = 0;
227
+ performSearch(suggestion.phrase);
228
+ });
229
+ listItem.addEventListener("focus", () => {
230
+ selectedSuggestionIndex = index;
231
+ updateSuggestionSelection(container);
232
+ });
233
+ suggestionList.appendChild(listItem);
234
+ });
235
+ container.appendChild(suggestionList);
236
+ container.style.display = "block";
237
+ container.style.opacity = 1;
238
  }
239
 
240
  function updateSuggestionSelection(container) {
241
+ const suggestionItems = container.querySelectorAll("li");
242
+ suggestionItems.forEach((item, index) => {
243
+ item.classList.toggle("selected", index === selectedSuggestionIndex);
244
+ });
245
+ // Make sure the mainSuggestionsContainer is displayed when needed
246
+ if (container === mainSuggestionsContainer && selectedSuggestionIndex !== -1) {
247
+ mainSuggestionsContainer.style.display = "block";
248
+ }
249
  }
250
 
251
  function showLoading() {
252
+ loadingOverlay.style.display = 'block';
253
  }
254
 
255
  function hideLoading() {
256
+ loadingOverlay.style.display = 'none';
257
  }
 
258
  let startTime;
259
  async function performSearch(query) {
260
+ showLoading();
261
+ seenUrls.clear();
262
+ allResultsFetched = false;
263
+ resultsContainer.innerHTML = '';
264
+ noResultsMessage.style.display = 'none';
265
+ loadingMoreIndicator.classList.remove('active');
266
+ suggestionsContainer.style.display = 'none';
267
+ mainSuggestionsContainer.style.display = 'none';
268
+ startTime = performance.now(); // Start time calculation here
269
+ const initialResults = await fetchResults(query, INITIAL_RESULTS);
270
+ updateURLWithQuery(query);
271
+ displayResults(initialResults);
272
+ hideLoading();
273
+ if (initialResults.length > 0) {
274
+ cachedSearchResults = await fetchResults(query, CACHED_RESULTS);
275
+ cachedSearchResults = removeDuplicateResults(cachedSearchResults);
276
+ } else {
277
+ cachedSearchResults = [];
278
+ }
279
+ introPage.style.display = 'none';
280
+ mainContent.style.display = 'flex';
281
  }
282
 
283
  function updateURLWithQuery(query) {
284
+ const newURL = `${window.location.pathname}?query=${encodeURIComponent(query)}`;
285
+ window.history.pushState({
286
+ path: newURL
287
+ }, '', newURL);
288
  }
289
 
290
  function removeDuplicateResults(results) {
291
+ const uniqueResults = [];
292
+ const seen = new Set();
293
+ for (const result of results) {
294
+ if (!seen.has(result.href)) {
295
+ seen.add(result.href);
296
+ uniqueResults.push(result);
297
+ }
298
+ }
299
+ return uniqueResults;
300
  }
 
301
  async function fetchResults(query, resultsPerPage) {
302
+ const response = await fetch(`${BASE_URL}/api/search?q=${encodeURIComponent(query)}&max_results=${resultsPerPage}`);
303
+ if (!response.ok) {
304
+ displayError("An error occurred while fetching results.");
305
+ hideLoading();
306
+ return [];
307
+ }
308
+ const searchResults = await response.json();
309
+ return searchResults;
310
  }
311
 
312
  function displayResults(results, append = false) {
313
+ if (!append) {
314
+ resultsContainer.innerHTML = '';
315
+ }
316
+ const newResults = results.filter(result => !seenUrls.has(result.href));
317
+ newResults.forEach((result, index) => {
318
+ seenUrls.add(result.href);
319
+ const resultElement = document.createElement("div");
320
+ resultElement.classList.add("result");
321
+ const titleElement = document.createElement("h3");
322
+ const titleLink = document.createElement("a");
323
+ titleLink.href = result.href;
324
+ titleLink.textContent = result.title;
325
+ titleLink.target = "_blank";
326
+ titleLink.rel = "noopener noreferrer";
327
+ titleElement.appendChild(titleLink);
328
+ const urlElement = document.createElement("div");
329
+ urlElement.classList.add("url");
330
+ const urlLink = document.createElement("a");
331
+ urlLink.href = result.href;
332
+ urlLink.textContent = result.href;
333
+ urlLink.target = "_blank";
334
+ urlLink.rel = "noopener noreferrer";
335
+ urlElement.appendChild(urlLink);
336
+ const descriptionElement = document.createElement("p");
337
+ descriptionElement.textContent = result.body;
338
+ resultElement.appendChild(titleElement);
339
+ resultElement.appendChild(urlElement);
340
+ resultElement.appendChild(descriptionElement);
341
+ resultsContainer.appendChild(resultElement);
342
+ setTimeout(() => {
343
+ resultElement.classList.add("show");
344
+ }, 100 * index);
345
+ });
346
+ noResultsMessage.style.display = resultsContainer.children.length === 0 ? 'block' : 'none';
347
+ if (!append) {
348
+ const endTime = performance.now();
349
+ const timeTaken = (endTime / 2 - startTime).toFixed(2);
350
+ document.getElementById('results-info').textContent = `About ${timeTaken} milliseconds`;
351
+ }
352
  }
353
 
354
  function displayError(message) {
355
+ resultsContainer.innerHTML = "";
356
+ const errorElement = document.createElement("p");
357
+ errorElement.textContent = message;
358
+ errorElement.style.color = "red";
359
+ resultsContainer.appendChild(errorElement);
360
  }
 
361
  searchQueryInput.addEventListener("input", debounce(async () => {
362
+ selectedSuggestionIndex = -1;
363
+ const searchQuery = searchQueryInput.value;
364
+ if (searchQuery.trim() === "") {
365
+ suggestionsContainer.style.display = "none";
366
+ return;
367
+ }
368
+ const suggestions = await fetchSuggestions(searchQuery);
369
+ displaySuggestions(suggestions);
370
  }));
 
371
  mainSearchQueryInput.addEventListener("input", debounce(async () => {
372
+ selectedSuggestionIndex = -1;
373
+ const searchQuery = mainSearchQueryInput.value;
374
+ if (searchQuery.trim() === "") {
375
+ mainSuggestionsContainer.style.display = "none";
376
+ return;
377
+ }
378
+ const suggestions = await fetchSuggestions(searchQuery);
379
+ displaySuggestions(suggestions, mainSuggestionsContainer);
380
  }));
 
381
  searchQueryInput.addEventListener("focus", () => {
382
+ if (searchQueryInput.value.trim() !== "") {
383
+ suggestionsContainer.style.display = "block";
384
+ }
385
  });
386
  mainSearchQueryInput.addEventListener("focus", () => {
387
+ if (mainSearchQueryInput.value.trim() !== "") {
388
+ mainSuggestionsContainer.style.display = "block";
389
+ }
390
  });
 
391
  document.addEventListener("click", (event) => {
392
+ if (!searchForm.contains(event.target) && !mainSearchForm.contains(event.target)) {
393
+ suggestionsContainer.style.display = "none";
394
+ mainSuggestionsContainer.style.display = "none";
395
+ }
396
  });
 
397
  searchQueryInput.addEventListener("keydown", async (event) => {
398
+ if (event.key === "ArrowUp" || event.key === "ArrowDown") {
399
+ event.preventDefault();
400
+ const suggestionItems = suggestionsContainer.querySelectorAll("li");
401
+ const numSuggestions = suggestionItems.length;
402
+ if (event.key === "ArrowUp") {
403
+ selectedSuggestionIndex = (selectedSuggestionIndex - 1 + numSuggestions) % numSuggestions;
404
+ } else {
405
+ selectedSuggestionIndex = (selectedSuggestionIndex + 1) % numSuggestions;
406
+ }
407
+ updateSuggestionSelection(suggestionsContainer);
408
+ if (selectedSuggestionIndex !== -1 && suggestionItems[selectedSuggestionIndex]) {
409
+ searchQueryInput.value = suggestionItems[selectedSuggestionIndex].textContent;
410
+ suggestionItems[selectedSuggestionIndex].focus();
411
+ }
412
+ } else if (event.key === "Enter" && selectedSuggestionIndex !== -1) {
413
+ event.preventDefault();
414
+ const selectedSuggestion = suggestionsContainer.querySelectorAll("li")[selectedSuggestionIndex];
415
+ if (selectedSuggestion) {
416
+ searchQueryInput.value = selectedSuggestion.textContent;
417
+ suggestionsContainer.style.display = "none";
418
+ performSearch(searchQueryInput.value);
419
+ }
420
+ }
421
  });
422
  mainSearchQueryInput.addEventListener("keydown", async (event) => {
423
+ if (event.key === "ArrowUp" || event.key === "ArrowDown") {
424
+ event.preventDefault();
425
+ const suggestionItems = mainSuggestionsContainer.querySelectorAll("li");
426
+ const numSuggestions = suggestionItems.length;
427
+ if (event.key === "ArrowUp") {
428
+ selectedSuggestionIndex = (selectedSuggestionIndex - 1 + numSuggestions) % numSuggestions;
429
+ } else {
430
+ selectedSuggestionIndex = (selectedSuggestionIndex + 1) % numSuggestions;
431
+ }
432
+ updateSuggestionSelection(mainSuggestionsContainer);
433
+ if (selectedSuggestionIndex !== -1 && suggestionItems[selectedSuggestionIndex]) {
434
+ mainSearchQueryInput.value = suggestionItems[selectedSuggestionIndex].textContent;
435
+ suggestionItems[selectedSuggestionIndex].focus();
436
+ }
437
+ } else if (event.key === "Enter" && selectedSuggestionIndex !== -1) {
438
+ event.preventDefault();
439
+ const selectedSuggestion = mainSuggestionsContainer.querySelectorAll("li")[selectedSuggestionIndex];
440
+ if (selectedSuggestion) {
441
+ mainSearchQueryInput.value = selectedSuggestion.textContent;
442
+ mainSuggestionsContainer.style.display = "none";
443
+ performSearch(mainSearchQueryInput.value);
444
+ }
445
+ }
446
  });
 
447
  searchForm.addEventListener("submit", async (event) => {
448
+ event.preventDefault();
449
+ selectedSuggestionIndex = -1;
450
+ const searchQuery = searchQueryInput.value;
451
+ performSearch(searchQuery);
452
  });
453
  mainSearchForm.addEventListener("submit", async (event) => {
454
+ event.preventDefault();
455
+ selectedSuggestionIndex = -1;
456
+ const searchQuery = mainSearchQueryInput.value;
457
+ performSearch(searchQuery);
458
  });
 
459
  window.addEventListener("scroll", () => {
460
+ if (allResultsFetched || cachedSearchResults.length === 0) return;
461
+ const {
462
+ scrollTop,
463
+ scrollHeight,
464
+ clientHeight
465
+ } = document.documentElement;
466
+ if (scrollTop + clientHeight >= scrollHeight - 100 && !loadingMoreIndicator.classList.contains("active")) {
467
+ loadingMoreIndicator.classList.add("active");
468
+ const resultsToDisplay = cachedSearchResults.splice(0, RESULTS_PER_PAGE);
469
+ if (resultsToDisplay.length > 0) {
470
+ displayResults(resultsToDisplay, true);
471
+ }
472
+ if (cachedSearchResults.length === 0) {
473
+ allResultsFetched = true;
474
+ }
475
+ loadingMoreIndicator.classList.remove("active");
476
+ }
477
  });
478
 
479
  function getQueryParameter(name) {
480
+ const urlParams = new URLSearchParams(window.location.search);
481
+ return urlParams.get(name);
482
  }
 
483
  window.addEventListener('load', () => {
484
+ const initialQuery = getQueryParameter('query');
485
+ if (initialQuery) {
486
+ mainSearchQueryInput.value = initialQuery;
487
+ performSearch(initialQuery);
488
+ } else {
489
+ introPage.style.display = 'flex';
490
+ mainContent.style.display = 'none';
491
+ }
492
  });
493
  </script>
494
  </body>