aboutsummaryrefslogtreecommitdiff
path: root/static
diff options
context:
space:
mode:
authorArjun Satarkar <me@arjunsatarkar.net>2023-08-04 20:02:00 +0000
committerArjun Satarkar <me@arjunsatarkar.net>2023-08-04 20:03:29 +0000
commitb42091406ba4f4abe8591a793e2334d38613aaf5 (patch)
tree6b1e30d7a42cb41cff2ef50887b6010516152329 /static
parent8f5488436b90d85969abb8bdcbb0ecf14d8936bd (diff)
downloadtagrss-main.tar
tagrss-main.tar.gz
tagrss-main.zip
Make tag input nicer with JS (if enabled)HEADmain
Diffstat (limited to 'static')
-rw-r--r--static/scripts/auto_refresh.js1
-rw-r--r--static/scripts/dynamic_input.js84
-rw-r--r--static/styles/main.css5
3 files changed, 88 insertions, 2 deletions
diff --git a/static/scripts/auto_refresh.js b/static/scripts/auto_refresh.js
index 5e7223e..fd94497 100644
--- a/static/scripts/auto_refresh.js
+++ b/static/scripts/auto_refresh.js
@@ -1,3 +1,4 @@
+"use strict";
(() => {
const onFrontPage = () => {
const searchParams = new URLSearchParams(window.location.search);
diff --git a/static/scripts/dynamic_input.js b/static/scripts/dynamic_input.js
new file mode 100644
index 0000000..df1c8fe
--- /dev/null
+++ b/static/scripts/dynamic_input.js
@@ -0,0 +1,84 @@
+"use strict";
+(() => {
+ const outerContainer = document.querySelector("div.tag-input-container");
+ const rawInput = document.createElement("input");
+ const name = outerContainer.querySelector("span#tags-input-name-span").innerText;
+ rawInput.setAttribute("type", "hidden");
+ rawInput.setAttribute("name", name);
+ outerContainer.appendChild(rawInput);
+
+ function parseSpaceSeparatedTags(inp) {
+ const tags = new Set();
+ let tag = ""
+ let escaped = false;
+ for (const c of inp) {
+ switch (c) {
+ case "\\":
+ if (!escaped) {
+ escaped = true;
+ continue;
+ }
+ case " ":
+ if (!escaped) {
+ tags.add(tag);
+ tag = "";
+ continue;
+ }
+ }
+ escaped = false;
+ tag += c;
+ }
+ if (tag) {
+ tags.add(tag);
+ }
+ return Array.from(tags).sort((a, b) => a.localeCompare(b));
+ }
+
+ const dynamicInputContainer = document.createElement("span");
+
+ function createDynamicInput() {
+ const dynamicInput = document.createElement("input");
+ dynamicInput.setAttribute("class", "dynamic-tag-input");
+ // So autocomplete will work
+ dynamicInput.setAttribute("name", "dynamic_tag_input");
+ dynamicInput.addEventListener("input", handleInput);
+ return dynamicInput;
+ };
+
+ function handleInput(e) {
+ const sources = document.querySelectorAll("input.dynamic-tag-input");
+ const lastDynamicInput = sources[sources.length - 1];
+ if (e.currentTarget === lastDynamicInput && e.currentTarget.value) {
+ dynamicInputContainer.appendChild(createDynamicInput());
+ } else if (e.currentTarget === sources[sources.length - 2] && !e.currentTarget.value) {
+ dynamicInputContainer.removeChild(lastDynamicInput);
+ }
+ let serialised = "";
+ for (const [i, source] of sources.entries()) {
+ const tag = source.value;
+ if (!tag) { continue; }
+ if (i > 0) {
+ serialised += " ";
+ }
+ serialised += tag.replaceAll("\\", "\\\\").replaceAll(" ", "\\ ");
+ }
+ rawInput.value = serialised;
+ };
+
+ const firstDynamicInput = createDynamicInput();
+ firstDynamicInput.setAttribute("id", "tags-input");
+ dynamicInputContainer.appendChild(firstDynamicInput);
+
+ const initialValue = outerContainer.querySelector("span#tags-input-initial-value-span").innerText;
+ if (initialValue) {
+ const tags = parseSpaceSeparatedTags(initialValue);
+ let input = dynamicInputContainer.querySelector("input.dynamic-tag-input:last-of-type");
+ for (const tag of tags) {
+ input.value = tag;
+ input = createDynamicInput();
+ dynamicInputContainer.appendChild(input);
+ }
+ }
+
+ outerContainer.appendChild(dynamicInputContainer);
+})();
diff --git a/static/styles/main.css b/static/styles/main.css
index f6c6a27..1bc1709 100644
--- a/static/styles/main.css
+++ b/static/styles/main.css
@@ -57,11 +57,12 @@ span.tag {
display: table-row;
}
- div.side-by-side-help-container>* {
+ div.side-by-side-help-container>label,
+ div.side-by-side-help-container input {
display: table-cell;
}
- div.side-by-side-help-container>.hover-help:focus::after {
+ div.side-by-side-help-container .hover-help:focus::after {
content: attr(title);
font-size: small;
padding-left: 0.2em;