diff --git a/frontends/etiquette_flask/backend/endpoints/album_endpoints.py b/frontends/etiquette_flask/backend/endpoints/album_endpoints.py
index ebda1e3..cc58f41 100644
--- a/frontends/etiquette_flask/backend/endpoints/album_endpoints.py
+++ b/frontends/etiquette_flask/backend/endpoints/album_endpoints.py
@@ -1,8 +1,10 @@
import flask; from flask import request
+import time
import urllib.parse
import etiquette
+from .. import caching
from .. import common
from .. import decorators
from .. import jsonify
@@ -154,6 +156,13 @@ def post_album_edit(album_id):
# Album listings ###################################################################################
+@site.route('/all_albums.json')
+@caching.cached_endpoint(max_age=0)
+def get_all_album_names():
+ all_albums = {album.display_name: album.id for album in common.P.get_albums()}
+ response = {'updated': int(time.time()), 'albums': all_albums}
+ return jsonify.make_json_response(response)
+
def get_albums_core():
albums = list(common.P.get_root_albums())
albums.sort(key=lambda x: x.display_name.lower())
diff --git a/frontends/etiquette_flask/static/js/album_autocomplete.js b/frontends/etiquette_flask/static/js/album_autocomplete.js
new file mode 100644
index 0000000..74ce1ae
--- /dev/null
+++ b/frontends/etiquette_flask/static/js/album_autocomplete.js
@@ -0,0 +1,59 @@
+const album_autocomplete = {};
+
+album_autocomplete.albums = {};
+
+album_autocomplete.DATALIST_ID = "album_autocomplete_datalist";
+album_autocomplete.datalist = null;
+album_autocomplete.on_load_hooks = [];
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+album_autocomplete.init_datalist =
+function init_datalist()
+{
+ if (album_autocomplete.datalist)
+ {
+ return;
+ }
+ console.log("Init album_autocomplete datalist.");
+ const datalist = document.createElement("datalist");
+ datalist.id = album_autocomplete.DATALIST_ID;
+ document.body.appendChild(datalist);
+
+ const fragment = document.createDocumentFragment();
+ for (const album_name in album_autocomplete.albums)
+ {
+ const album_id = album_autocomplete.albums[album_name];
+ const option = document.createElement("option");
+ option.value = album_id;
+ option.innerText = album_name;
+ fragment.appendChild(option);
+ }
+ datalist.appendChild(fragment);
+ album_autocomplete.datalist = datalist;
+
+ for (const hook of album_autocomplete.on_load_hooks)
+ {
+ hook(datalist);
+ }
+}
+
+album_autocomplete.get_all_albums_callback =
+function get_all_albums_callback(response)
+{
+ if (response.meta.status !== 200)
+ {
+ console.error(response);
+ return;
+ }
+
+ album_autocomplete.albums = response.data.albums;
+ setTimeout(album_autocomplete.init_datalist, 0);
+}
+
+album_autocomplete.on_pageload =
+function on_pageload()
+{
+ setTimeout(api.albums.get_all_albums(album_autocomplete.get_all_albums_callback), 0);
+}
+document.addEventListener("DOMContentLoaded", album_autocomplete.on_pageload);
diff --git a/frontends/etiquette_flask/static/js/api.js b/frontends/etiquette_flask/static/js/api.js
index 1a795c0..ca77ebc 100644
--- a/frontends/etiquette_flask/static/js/api.js
+++ b/frontends/etiquette_flask/static/js/api.js
@@ -61,6 +61,13 @@ function _delete(album_id, callback)
common.post(url, null, callback);
}
+api.albums.get_all_albums =
+function get_all_albums(callback)
+{
+ const url = "/all_albums.json";
+ common.get(url, callback);
+}
+
api.albums.edit =
function edit(album_id, title, description, callback)
{
diff --git a/frontends/etiquette_flask/static/js/tag_autocomplete.js b/frontends/etiquette_flask/static/js/tag_autocomplete.js
index 46438d7..e3fc33f 100644
--- a/frontends/etiquette_flask/static/js/tag_autocomplete.js
+++ b/frontends/etiquette_flask/static/js/tag_autocomplete.js
@@ -4,26 +4,24 @@ tag_autocomplete.tags = new Set();
tag_autocomplete.synonyms = {};
tag_autocomplete.DATALIST_ID = "tag_autocomplete_datalist";
+tag_autocomplete.datalist = null;
+tag_autocomplete.on_load_hooks = [];
////////////////////////////////////////////////////////////////////////////////////////////////////
tag_autocomplete.init_datalist =
function init_datalist()
{
- console.log("Init datalist.");
- let datalist;
- datalist = document.getElementById(tag_autocomplete.DATALIST_ID);
- if (datalist)
+ if (tag_autocomplete.datalist)
{
return;
}
-
- datalist = document.createElement("datalist");
+ console.log("Init tag_autocomplete datalist.");
+ const datalist = document.createElement("datalist");
datalist.id = tag_autocomplete.DATALIST_ID;
document.body.appendChild(datalist);
const fragment = document.createDocumentFragment();
- common.delete_all_children(datalist);
for (const tag_name of tag_autocomplete.tags)
{
const option = document.createElement("option");
@@ -37,6 +35,12 @@ function init_datalist()
fragment.appendChild(option);
}
datalist.appendChild(fragment);
+ tag_autocomplete.datalist = datalist;
+
+ for (const hook of tag_autocomplete.on_load_hooks)
+ {
+ hook(datalist);
+ }
}
tag_autocomplete.normalize_tagname =
@@ -101,11 +105,7 @@ function resolve(tagname)
tag_autocomplete.get_all_tags_callback =
function get_all_tags_callback(response)
{
- if (response["meta"]["status"] == 304)
- {
- return;
- }
- if (response["meta"]["status"] != 200)
+ if (response.meta.status !== 200)
{
console.error(response);
return;
@@ -113,8 +113,7 @@ function get_all_tags_callback(response)
tag_autocomplete.tags = new Set(response.data.tags);
tag_autocomplete.synonyms = response.data.synonyms;
- setTimeout(() => tag_autocomplete.init_datalist(), 0);
- return tag_autocomplete.tagset;
+ setTimeout(tag_autocomplete.init_datalist, 0);
}
tag_autocomplete.on_pageload =
diff --git a/frontends/etiquette_flask/templates/album.html b/frontends/etiquette_flask/templates/album.html
index fdeda27..30cef80 100644
--- a/frontends/etiquette_flask/templates/album.html
+++ b/frontends/etiquette_flask/templates/album.html
@@ -141,6 +141,7 @@ const ALBUM_ID = undefined;
{% if theme %}{% endif %}
+
@@ -180,6 +181,7 @@ const ALBUM_ID = undefined;