diff --git a/bookwyrm/static/js/autocomplete.js b/bookwyrm/static/js/autocomplete.js new file mode 100644 index 000000000..0ba3e2172 --- /dev/null +++ b/bookwyrm/static/js/autocomplete.js @@ -0,0 +1,164 @@ +(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 trie = tries[input.getAttribute("data-autocomplete")]; + + let suggestions = getSuggestions(input.value, trie); + + const boxId = input.getAttribute("list"); + + // Create suggestion box, if needed + let suggestionsBox = document.getElementById(boxId); + + // Clear existing suggestions + suggestionsBox.innerHTML = ""; + + // Populate suggestions box + suggestions.forEach((suggestion) => { + const suggestionItem = document.createElement("option"); + + suggestionItem.textContent = suggestion; + suggestionsBox.appendChild(suggestionItem); + }); + } + + function getSuggestions(input, trie) { + // Follow the trie through the provided input + input.split("").forEach((letter) => { + if (!trie) { + return; + } + + trie = trie[letter]; + }); + + if (!trie) { + return []; + } + + return searchTrie(trie); + } + + function searchTrie(trie) { + const options = Object.values(trie); + + if (typeof trie == "string") { + return [trie]; + } + + return options + .map((option) => { + const newTrie = option; + + if (typeof newTrie == "string") { + return [newTrie]; + } + + return searchTrie(newTrie); + }) + .reduce((prev, next) => prev.concat(next)); + } + + document.querySelectorAll("[data-autocomplete]").forEach((input) => { + input.addEventListener("input", autocomplete); + }); +})(); + +const tries = {"mimetype": { + a: { + a: { + c: "AAC", + }, + z: { + w: "AZW", + }, + }, + d: { + a: { + i: { + s: { + y: "Daisy", + }, + }, + }, + }, + e: { + p: { + u: { + b: "ePub", + }, + }, + }, + f: { + l: { + a: { + c: "FLAC", + }, + }, + }, + h: { + t: { + m: { + l: "HTML", + }, + }, + }, + m: { + 4: { + a: "M4A", + b: "M4B", + }, + o: { + b: { + i: "MOBI", + }, + }, + p: { + 3: "MP3", + }, + }, + o: { + g: { + g: "OGG", + }, + }, + p: { + d: { + f: "PDF", + }, + l: { + a: { + i: { + n: { + t: { + e: { + x: { + t: "Plaintext", + }, + }, + }, + }, + }, + }, + }, + }, + }, +}; diff --git a/bookwyrm/templates/book/book.html b/bookwyrm/templates/book/book.html index c8c78e0e9..f6d9929dd 100644 --- a/bookwyrm/templates/book/book.html +++ b/bookwyrm/templates/book/book.html @@ -386,4 +386,5 @@ {% block scripts %} + {% endblock %} diff --git a/bookwyrm/templates/book/file_links/add_link_modal.html b/bookwyrm/templates/book/file_links/add_link_modal.html index fc8b90597..dfc222ee9 100644 --- a/bookwyrm/templates/book/file_links/add_link_modal.html +++ b/bookwyrm/templates/book/file_links/add_link_modal.html @@ -1,5 +1,6 @@ {% extends 'components/modal.html' %} {% load i18n %} +{% load static %} {% block modal-title %} {% trans "Add file link" %} @@ -26,7 +27,19 @@
- + + {% include 'snippets/form_errors.html' with errors_list=file_link_form.filetype.errors id="desc_filetype" %}
diff --git a/bookwyrm/templates/book/file_links/file_link_page.html b/bookwyrm/templates/book/file_links/file_link_page.html index 902057af2..00efe5089 100644 --- a/bookwyrm/templates/book/file_links/file_link_page.html +++ b/bookwyrm/templates/book/file_links/file_link_page.html @@ -1,5 +1,6 @@ {% extends 'layout.html' %} {% load i18n %} +{% load static %} {% block title %} {% trans "File Links" %} @@ -8,3 +9,7 @@ {% block content %} {% include "book/file_links/add_link_modal.html" with book=book active=True static=True id="file-link" %} {% endblock %} + +{% block scripts %} + +{% endblock %}