PageSourceSearch

https://zapateriasilmos.es/assets/store/controllers/filter_search_controller

js zapateriasilmos.es collected 2026-10-04 23:17:30 UTC 3,737 bytes, 86 lines download raw bytes

1import { Controller } from "@hotwired/stimulus"
2
3// Vertical accordion filter: inline search + clear-all per filter group
4export default class extends Controller {
5    static targets = ["searchInput", "option", "clearBtn"]
6    static values = { filterName: String }
7
8    connect() {
9        this.toggleClearBtn()
10    }
11
12    // Search/filter option rows client-side (no server request)
13    search(event) {
14        const query = event.currentTarget.value.toLowerCase().trim()
15        this.optionTargets.forEach(option => {
16            const text = option.querySelector("label")?.textContent?.toLowerCase() || ""
17            option.classList.toggle("d-none", query.length > 0 && !text.includes(query))
18        })
19    }
20
21    // Called on each checkbox change — show/hide the "Borrar" button
22    toggleClearBtn() {
23        const hasChecked = this.element.querySelectorAll("input.filter-inputs:checked, input.filter-inputs-mobile:checked").length > 0
24        const isHorizontal = Boolean(this.element.closest('.horizontal-filter-container'))
25
26        if (this.hasClearBtnTarget) {
27            this.clearBtnTargets.forEach(btn => {
28                if (isHorizontal) {
29                    btn.classList.remove("d-none")
30                    btn.disabled = !hasChecked
31                    btn.setAttribute("aria-disabled", (!hasChecked).toString())
32                } else {
33                    btn.classList.toggle("d-none", !hasChecked)
34                    btn.disabled = false
35                    btn.removeAttribute("aria-disabled")
36                }
37            })
38        }
39    }
40
41    // Deselect all checkboxes in this filter group and update the badge counter
42    clearAll(event) {
43        event.preventDefault()
44
45        this.element.querySelectorAll("input.filter-inputs, input.filter-inputs-mobile").forEach(input => {
46            input.checked = false
47        })
48
49        // Hide the local badge counter (avoid duplicate IDs between desktop/mobile)
50        const counter = this.element.closest('.accordion-item, .dropdown')?.querySelector(`#${this.filterNameValue}_filter_counter`) ||
51            this.element.closest('form')?.querySelector(`#${this.filterNameValue}_filter_counter`) ||
52            document.getElementById(`${this.filterNameValue}_filter_counter`)
53        if (counter) {
54            counter.textContent = "0"
55            counter.classList.add("d-none")
56        }
57
58        // Enable the submit button so the user can apply the cleared selection.
59        // Use this.element scope first to avoid matching the sibling desktop/mobile
60        // panel when both turbo frames coexist in the DOM.
61        const submitBtn = this.element.querySelector(`#submit_${this.filterNameValue}_mobile, #submit_${this.filterNameValue}`) ||
62            document.getElementById(`submit_${this.filterNameValue}_mobile`) ||
63            document.getElementById(`submit_${this.filterNameValue}`)
64        if (submitBtn) submitBtn.disabled = false
65
66        // Hide the clear button itself
67        if (this.hasClearBtnTarget) {
68            const isHorizontal = Boolean(this.element.closest('.horizontal-filter-container'))
69            this.clearBtnTargets.forEach(btn => {
70                if (isHorizontal) {
71                    btn.classList.remove("d-none")
72                    btn.disabled = true
73                    btn.setAttribute("aria-disabled", "true")
74                } else {
75                    btn.classList.add("d-none")
76                }
77            })
78        }
79
80        // Clear the search input if present and restore all hidden options
81        if (this.hasSearchInputTarget) {
82            this.searchInputTarget.value = ""
83            this.optionTargets.forEach(option => option.classList.remove("d-none"))
84        }
85    }
86};

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.