diff --git a/public/index.html b/public/index.html index a9a38a4..57ea98a 100644 --- a/public/index.html +++ b/public/index.html @@ -31,6 +31,7 @@ +
diff --git a/public/js/smartforms.js b/public/js/smartforms.js index ed34255..2bc4aa9 100644 --- a/public/js/smartforms.js +++ b/public/js/smartforms.js @@ -1,8 +1,7 @@ function smarten_forms() { - const forms = document.body.querySelectorAll("form[data-smart]:not([data-smartened])"); + const forms = document?.body?.querySelectorAll("form[data-smart]:not([data-smartened])") ?? []; for (const form of forms) { async function on_submit(event) { - debugger; event.preventDefault(); form.disabled = true; form.__submitted_at = new Date(); diff --git a/public/js/textareaenhancements.js b/public/js/textareaenhancements.js new file mode 100644 index 0000000..0fcf435 --- /dev/null +++ b/public/js/textareaenhancements.js @@ -0,0 +1,31 @@ +function enhance_textareas() { + const textareas = document.body.querySelectorAll("textarea:not([data-enhanced])"); + for (const textarea of textareas) { + const max_length_attr = textarea.getAttribute("maxlength"); + if (/^\d+$/.test(max_length_attr)) { + const max_length = parseInt(max_length_attr, 10); + + function on_updated() { + const counters = this.parentElement.querySelectorAll( + `[data-limit-counter-for="${this.name}"]`, + ); + for (const counter of counters) { + counter.innerHTML = `${this.value.length} / ${max_length}`; + } + } + + textarea.addEventListener("keyup", on_updated); + textarea.addEventListener("paste", on_updated); + textarea.addEventListener("blur", on_updated); + on_updated.call(textarea); + } + + textarea.dataset.enhanced = true; + } +} + +const textarea_enhancement_observer = new MutationObserver(enhance_textareas); +textarea_enhancement_observer.observe(document, { + childList: true, + subtree: true, +}); diff --git a/public/tabs/blurbs/blurbs.html b/public/tabs/blurbs/blurbs.html index 1ccb159..444e547 100644 --- a/public/tabs/blurbs/blurbs.html +++ b/public/tabs/blurbs/blurbs.html @@ -1,6 +1,8 @@