From e2d1c987b544e538f2dcdfe7ba897b792b1b7711 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 27 Dec 2021 12:41:27 -0800 Subject: [PATCH] Adds autocomplete scrip --- bookwyrm/static/js/autocomplete.js | 104 +++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 bookwyrm/static/js/autocomplete.js diff --git a/bookwyrm/static/js/autocomplete.js b/bookwyrm/static/js/autocomplete.js new file mode 100644 index 00000000..f7594807 --- /dev/null +++ b/bookwyrm/static/js/autocomplete.js @@ -0,0 +1,104 @@ +(function() { + 'use strict'; + + /** + * Suggest a completion as a user types + * + * Use `data-autocomplete=""`on the input field. + * specifying the trie to be used for autocomplete + * + * @example + * + * @param {Event} event + * @return {undefined} + */ + function autocomplete(event) { + const input = event.target; + + // Get suggestions + let suggestions = getSuggestions(input.value, mimetypeTrie); + + const boxId = input.id + "_suggestions"; + + // Create suggestion box, if needed + let suggestionsBox = document.getElementById(boxId); + + if (!suggestionsBox) { + suggestionsBox = document.createElement("ul"); + suggestionsBox.id = boxId; + suggestionsBox.classList.add("autocomplete-suggestions", "box"); + + input.insertAdjacentElement("afterend", suggestionsBox); + } + + // Clear existing suggestions + suggestionsBox.innerHTML = ""; + + // Populate suggestions box + suggestions.forEach(suggestion => { + const suggestionItem = document.createElement("li"); + + suggestionItem.textContent = suggestion; + suggestionsBox.appendChild(suggestionItem); + }); + } + + function getSuggestions(input, trie) { + // Follow the trie through the provided input + input.split("").forEach(letter => { + trie = trie[letter]; + + if (!trie) { + return; + } + }); + + if (!trie) { + return []; + } + + return searchTrie(input, trie); + } + + function searchTrie(output, trie) { + const options = Object.keys(trie); + + if (!options.length) { + return [output]; + } + + return options.map(option => { + const newTrie = trie[option]; + + if (!newTrie) { + return; + } + + return searchTrie(output + option, trie[option]); + }).reduce((prev, next) => prev.concat(next)); + } + + document + .querySelectorAll('[data-autocomplete]') + .forEach(input => { + input.addEventListener('input', autocomplete); + }); +})(); + +const mimetypeTrie = { + "p": { + "d": { + "f": { + "": {}, + "x": {}, + }, + }, + "n": { + "g": {} + }, + } +}; +