PageSourceSearch

https://www.hofladenfinder.org/js/components/search/search.js

js hofladenfinder.org collected 2026-10-09 04:38:27 UTC 4,939 bytes, 128 lines download raw bytes

1import { Utils } from "./../../helper/utils.js";
2
3export class Search extends HTMLElement {
4
5    connectedCallback() {
6        this.render();
7    }
8
9    render() {
10        this.innerHTML = /* html */`
11
12        <div class="max-w-5xl mx-auto px-4 -mt-12 relative z-20">
13            <div class="bg-white p-3 md:p-6 rounded-2xl shadow-xl shadow-green-900/5 flex flex-col md:flex-row gap-3 border border-lime-50">
14                <div class="flex-1">
15                    <input type="text" id="product" placeholder="Was suchen Sie? (z.B. Honig)" class="w-full bg-slate-50 rounded-xl px-6 py-4 focus:bg-white focus:ring-2 focus:ring-slate-100 outline-none transition-all">
16                </div>
17                    <div class="flex-1 min-w-0">
18                        <div class="flex items-center w-full bg-slate-50 rounded-xl focus-within:bg-white focus-within:ring-2 focus-within:ring-slate-100 transition-all relative z-10">          
19                            <input type="text" id="zip-code-or-place" placeholder="PLZ oder Stadt" class="w-0 grow bg-transparent pl-6 pr-3 py-4 outline-none">
20                            <div class="h-6 w-px bg-slate-200 shrink-0"></div>
21                        </div>
22                    </div>
23                <button id="search-button" class="bg-orange-500 hover:bg-orange-600 text-white font-bold px-8 py-4 rounded-xl transition-all shadow-md active:scale-95">
24                    Finden
25                </button>
26            </div>
27        </div>`;
28
29        this.productInput = this.querySelector("#product");
30        this.zipCodeOrPlaceInput = this.querySelector("#zip-code-or-place");
31        this.searchButton = this.querySelector("#search-button");
32
33        this.place;
34
35        this.searchButton.addEventListener("click", async () => {
36            if (this.productInput.value.length >= 2 || this.zipCodeOrPlaceInput.value.length >= 2) {
37                this.dispatchEvent(new CustomEvent('new_search_requested', { bubbles: true, composed: false }));
38
39                window.umami?.track("'Search' button clicked", { product: this.productInput.value, zipCodeOrPlace: this.zipCodeOrPlaceInput.value });
40            }
41        });
42
43        this.productInput.addEventListener("keydown", async (e) => {
44            if (e.key === 'Enter') {
45                if (this.productInput.value.length >= 2 || this.zipCodeOrPlaceInput.value.length >= 2) {
46                    this.dispatchEvent(new CustomEvent('new_search_requested', { bubbles: true, composed: false }));
47                    this.productInput.blur();
48
49                    window.umami?.track("'Search' button clicked", { product: this.productInput.value, zipCodeOrPlace: this.zipCodeOrPlaceInput.value });
50                }
51            }
52        });
53
54        this.zipCodeOrPlaceInput.addEventListener("keydown", async (e) => {
55            if (e.key === 'Enter') {
56                if (this.productInput.value.length >= 2 || this.zipCodeOrPlaceInput.value.length >= 2) {
57                    this.dispatchEvent(new CustomEvent('new_search_requested', { bubbles: true, composed: false }));
58                    this.zipCodeOrPlaceInput.blur();
59
60                    window.umami?.track("'Search' button clicked", { product: this.productInput.value, zipCodeOrPlace: this.zipCodeOrPlaceInput.value });
61                }
62            }
63        });
64    }
65
66    show() {
67        this.hidden = false;
68    }
69
70    hide() {
71        this.hidden = true;
72    }
73
74    async search(pageNumber) {
75        if (pageNumber == undefined)
76            pageNumber = 1;
77
78        const product = this.productInput.value.trim();
79        const zipCodeOrPlace = this.zipCodeOrPlaceInput.value.trim();
80
81        const params = new URLSearchParams({
82            Product: product,
83            ZipCodeOrPlace: zipCodeOrPlace,
84            PageNumber: pageNumber
85        });
86
87        const response = await fetch(`/farmshop/search?${params}`);
88        const searchResult = await response.json();
89
90        if (!Utils.isNumber(zipCodeOrPlace))
91            this.place = zipCodeOrPlace;
92        else
93            this.place = undefined;
94
95        if (pageNumber == 1) {
96            this.dispatchEvent(new CustomEvent('search_result_received', {
97                detail: { searchResult },
98                bubbles: true,
99                composed: false
100            }));
101        }
102        else {
103            this.dispatchEvent(new CustomEvent('additional_search_result_received', {
104                detail: { searchResult },
105                bubbles: true,
106                composed: false
107            }));
108        }
109    }
110
111    setProduct(product) {
112        this.productInput.value = product;
113    }
114
115    setZipCodeOrPlace(zipCodeOrPlace) {
116        this.zipCodeOrPlaceInput.value = zipCodeOrPlace;
117    }
118
119    getProduct() {
120        return this.productInput.value;
121    }
122
123    getZipCodeOrPlace() {
124        return this.zipCodeOrPlaceInput.value;
125    }
126}
127
128customElements.define("wc-search", Search);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.