diff --git a/app/javascript/controllers/autocomplete_controller.js b/app/javascript/controllers/autocomplete_controller.js new file mode 100644 index 0000000..d6a0f5c --- /dev/null +++ b/app/javascript/controllers/autocomplete_controller.js @@ -0,0 +1,65 @@ +import { Controller } from "@hotwired/stimulus" + +export default class extends Controller { + static targets = ["input", "results", "item"] + + connect() { + // Schließt die Liste, wenn man irgendwo außerhalb hinklickt + this.closeHandler = (e) => { + if (!this.element.contains(e.target)) { + this.hideResults() + } + } + document.addEventListener("click", this.closeHandler) + } + + disconnect() { + document.removeEventListener("click", this.closeHandler) + } + + // Wird aufgerufen, wenn der Nutzer tippt (input-Event) + filter() { + const filterValue = this.inputTarget.value.toLowerCase().trim() + + if (filterValue === "") { + this.showAll() + return + } + + this.showResults() + let hasMatches = false + + this.itemTargets.forEach(item => { + const text = item.textContent.toLowerCase() + if (text.includes(filterValue)) { + item.classList.remove("hidden") + hasMatches = true + } else { + item.classList.add("hidden") + } + }) + + // Falls gar nichts gefunden wird, blenden wir die Liste aus + if (!hasMatches) this.hideResults() + } + + // Ein Klick auf einen Eintrag wählt ihn aus + select(event) { + const value = event.currentTarget.dataset.value + this.inputTarget.value = value + this.hideResults() + } + + showResults() { + this.resultsTarget.classList.remove("hidden") + } + + hideResults() { + this.resultsTarget.classList.add("hidden") + } + + showAll() { + this.showResults() + this.itemTargets.forEach(item => item.classList.remove("hidden")) + } +} diff --git a/app/views/items/_form.html.erb b/app/views/items/_form.html.erb index 2220d1b..5d039e8 100644 --- a/app/views/items/_form.html.erb +++ b/app/views/items/_form.html.erb @@ -88,7 +88,7 @@ Item.conditions.keys.map { |cond| [Item.human_attribute_name("conditions.#{cond}"), cond] }, {}, class: "py-2.5 px-3 block w-full border border-gray-300 rounded-lg text-sm bg-gray-50/50 focus:border-blue-500 focus:ring-blue-500 appearance-none pr-10" %> - +