Merge pull request #1699 from bookwyrm-social/autocomplete

Autocomplete script
This commit is contained in:
Mouse Reeve 2022-01-12 17:09:34 -08:00 committed by GitHub
commit 7bb634b71f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 184 additions and 1 deletions

View file

@ -0,0 +1,164 @@
(function () {
"use strict";
/**
* Suggest a completion as a user types
*
* Use `data-autocomplete="<completions set identifier>"`on the input field.
* specifying the trie to be used for autocomplete
*
* @example
* <input
* type="input"
* data-autocomplete="mimetype"
* >
* @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",
},
},
},
},
},
},
},
},
},
};

View file

@ -386,4 +386,5 @@
{% block scripts %}
<script src="{% static "js/vendor/tabs.js" %}?v={{ js_cache }}"></script>
<script src="{% static "js/autocomplete.js" %}?v={{ js_cache }}"></script>
{% endblock %}

View file

@ -1,5 +1,6 @@
{% extends 'components/modal.html' %}
{% load i18n %}
{% load static %}
{% block modal-title %}
{% trans "Add file link" %}
@ -26,7 +27,19 @@
</div>
<div class="column is-one-fifth">
<label class="label" for="id_filetype">{% trans "File type:" %}</label>
<input type="text" name="filetype" maxlength="5" class="input" required="" id="id_filetype" value="{% firstof file_link_form.filetype.value "" %}" placeholder="PDF">
<input
type="text"
name="filetype"
maxlength="5"
class="input"
required=""
id="id_filetype"
value="{% firstof file_link_form.filetype.value '' %}"
placeholder="ePub"
list="mimetypes-list"
data-autocomplete="mimetype"
>
<datalist id="mimetypes-list"></datalist>
{% include 'snippets/form_errors.html' with errors_list=file_link_form.filetype.errors id="desc_filetype" %}
</div>
</div>

View file

@ -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 %}
<script src="{% static "js/autocomplete.js" %}?v={{ js_cache }}"></script>
{% endblock %}