diff --git a/app/static/js/autocomplete.js b/app/static/js/autocomplete.js
index 702ebc4..87d0c42 100644
--- a/app/static/js/autocomplete.js
+++ b/app/static/js/autocomplete.js
@@ -1,4 +1,9 @@
-const handleUserInput = searchBar => {
+let searchInput;
+let currentFocus;
+let originalSearch;
+let autocompleteResults;
+
+const handleUserInput = () => {
let xhrRequest = new XMLHttpRequest();
xhrRequest.open("POST", "autocomplete");
xhrRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
@@ -9,118 +14,119 @@ const handleUserInput = searchBar => {
}
// Fill autocomplete with fetched results
- let autocompleteResults = JSON.parse(xhrRequest.responseText);
- autocomplete(searchBar, autocompleteResults[1]);
+ autocompleteResults = JSON.parse(xhrRequest.responseText)[1];
+ updateAutocompleteList();
};
- xhrRequest.send('q=' + searchBar.value);
+ xhrRequest.send('q=' + searchInput.value);
};
-const autocomplete = (searchInput, autocompleteResults) => {
- let currentFocus;
- let originalSearch;
-
- searchInput.addEventListener("input", function () {
- let autocompleteList, autocompleteItem, i, val = this.value;
- closeAllLists();
-
- if (!val || !autocompleteResults) {
- return false;
+const closeAllLists = el => {
+ // Close all autocomplete suggestions
+ let suggestions = document.getElementsByClassName("autocomplete-items");
+ for (let i = 0; i < suggestions.length; i++) {
+ if (el !== suggestions[i] && el !== searchInput) {
+ suggestions[i].parentNode.removeChild(suggestions[i]);
}
+ }
+};
- currentFocus = -1;
- autocompleteList = document.createElement("div");
- autocompleteList.setAttribute("id", this.id + "-autocomplete-list");
- autocompleteList.setAttribute("class", "autocomplete-items");
- this.parentNode.appendChild(autocompleteList);
+const removeActive = suggestion => {
+ // Remove "autocomplete-active" class from previously active suggestion
+ for (let i = 0; i < suggestion.length; i++) {
+ suggestion[i].classList.remove("autocomplete-active");
+ }
+};
- for (i = 0; i < autocompleteResults.length; i++) {
- if (autocompleteResults[i].substr(0, val.length).toUpperCase() === val.toUpperCase()) {
- autocompleteItem = document.createElement("div");
- autocompleteItem.innerHTML = "" + autocompleteResults[i].substr(0, val.length) + "";
- autocompleteItem.innerHTML += autocompleteResults[i].substr(val.length);
- autocompleteItem.innerHTML += "";
- autocompleteItem.addEventListener("click", function () {
- searchInput.value = this.getElementsByTagName("input")[0].value;
- closeAllLists();
- document.getElementById("search-form").submit();
- });
- autocompleteList.appendChild(autocompleteItem);
- }
- }
- });
-
- searchInput.addEventListener("keydown", function (e) {
- let suggestion = document.getElementById(this.id + "-autocomplete-list");
- if (suggestion) suggestion = suggestion.getElementsByTagName("div");
- if (e.keyCode === 40) { // down
- e.preventDefault();
- currentFocus++;
- addActive(suggestion);
- } else if (e.keyCode === 38) { //up
- e.preventDefault();
- currentFocus--;
- addActive(suggestion);
- } else if (e.keyCode === 13) { // enter
- e.preventDefault();
- if (currentFocus > -1) {
- if (suggestion) suggestion[currentFocus].click();
- }
+const addActive = (suggestion) => {
+ // Handle navigation outside of suggestion list
+ if (!suggestion || !suggestion[currentFocus]) {
+ if (currentFocus >= suggestion.length) {
+ // Move selection back to the beginning
+ currentFocus = 0;
+ } else if (currentFocus < 0) {
+ // Retrieve original search and remove active suggestion selection
+ currentFocus = -1;
+ searchInput.value = originalSearch;
+ removeActive(suggestion);
+ return;
} else {
- originalSearch = document.getElementById("search-bar").value;
+ return;
}
- });
+ }
- const addActive = suggestion => {
- let searchBar = document.getElementById("search-bar");
+ removeActive(suggestion);
+ suggestion[currentFocus].classList.add("autocomplete-active");
- // Handle navigation outside of suggestion list
- if (!suggestion || !suggestion[currentFocus]) {
- if (currentFocus >= suggestion.length) {
- // Move selection back to the beginning
- currentFocus = 0;
- } else if (currentFocus < 0) {
- // Retrieve original search and remove active suggestion selection
- currentFocus = -1;
- searchBar.value = originalSearch;
- removeActive(suggestion);
- return;
- } else {
- return;
- }
+ // Autofill search bar with suggestion content (minus the "bang name" if using a bang operator)
+ let searchContent = suggestion[currentFocus].textContent;
+ if (searchContent.indexOf('(') > 0) {
+ searchInput.value = searchContent.substring(0, searchContent.indexOf('('));
+ } else {
+ searchInput.value = searchContent;
+ }
+
+ searchInput.focus();
+};
+
+const autocompleteInput = (e) => {
+ // Handle navigation between autocomplete suggestions
+ let suggestion = document.getElementById(this.id + "-autocomplete-list");
+ if (suggestion) suggestion = suggestion.getElementsByTagName("div");
+ if (e.keyCode === 40) { // down
+ e.preventDefault();
+ currentFocus++;
+ addActive(suggestion);
+ } else if (e.keyCode === 38) { //up
+ e.preventDefault();
+ currentFocus--;
+ addActive(suggestion);
+ } else if (e.keyCode === 13) { // enter
+ e.preventDefault();
+ if (currentFocus > -1) {
+ if (suggestion) suggestion[currentFocus].click();
}
+ } else {
+ originalSearch = searchInput.value;
+ }
+};
- removeActive(suggestion);
- suggestion[currentFocus].classList.add("autocomplete-active");
+const updateAutocompleteList = () => {
+ let autocompleteList, autocompleteItem, i;
+ let val = originalSearch;
+ closeAllLists();
- // Autofill search bar with suggestion content (minus the "bang name" if using a bang operator)
- let searchContent = suggestion[currentFocus].textContent;
- if (searchContent.indexOf('(') > 0) {
- searchBar.value = searchContent.substring(0, searchContent.indexOf('('));
- } else {
- searchBar.value = searchContent;
+ if (!val || !autocompleteResults) {
+ return false;
+ }
+
+ currentFocus = -1;
+ autocompleteList = document.createElement("div");
+ autocompleteList.setAttribute("id", this.id + "-autocomplete-list");
+ autocompleteList.setAttribute("class", "autocomplete-items");
+ searchInput.parentNode.appendChild(autocompleteList);
+
+ for (i = 0; i < autocompleteResults.length; i++) {
+ if (autocompleteResults[i].substr(0, val.length).toUpperCase() === val.toUpperCase()) {
+ autocompleteItem = document.createElement("div");
+ autocompleteItem.innerHTML = "" + autocompleteResults[i].substr(0, val.length) + "";
+ autocompleteItem.innerHTML += autocompleteResults[i].substr(val.length);
+ autocompleteItem.innerHTML += "";
+ autocompleteItem.addEventListener("click", function () {
+ searchInput.value = this.getElementsByTagName("input")[0].value;
+ closeAllLists();
+ document.getElementById("search-form").submit();
+ });
+ autocompleteList.appendChild(autocompleteItem);
}
+ }
+};
- searchBar.focus();
- };
+document.addEventListener("DOMContentLoaded", function() {
+ searchInput = document.getElementById("search-bar");
+ searchInput.addEventListener("keydown", (event) => autocompleteInput(event));
- const removeActive = suggestion => {
- for (let i = 0; i < suggestion.length; i++) {
- suggestion[i].classList.remove("autocomplete-active");
- }
- };
-
- const closeAllLists = el => {
- let suggestions = document.getElementsByClassName("autocomplete-items");
- for (let i = 0; i < suggestions.length; i++) {
- if (el !== suggestions[i] && el !== searchInput) {
- suggestions[i].parentNode.removeChild(suggestions[i]);
- }
- }
- };
-
- // Close lists and search when user selects a suggestion
document.addEventListener("click", function (e) {
closeAllLists(e.target);
});
-};
+});
\ No newline at end of file
diff --git a/app/static/js/controller.js b/app/static/js/controller.js
index 05b68ec..9f05e16 100644
--- a/app/static/js/controller.js
+++ b/app/static/js/controller.js
@@ -2,6 +2,8 @@ const setupSearchLayout = () => {
// Setup search field
const searchBar = document.getElementById("search-bar");
const searchBtn = document.getElementById("search-submit");
+ const arrowKeys = [37, 38, 39, 40];
+ let searchValue = searchBar.value;
// Automatically focus on search field
searchBar.focus();
@@ -11,8 +13,9 @@ const setupSearchLayout = () => {
if (event.keyCode === 13) {
event.preventDefault();
searchBtn.click();
- } else {
- handleUserInput(searchBar);
+ } else if (searchBar.value !== searchValue && !arrowKeys.includes(event.keyCode)) {
+ searchValue = searchBar.value;
+ handleUserInput();
}
});
};