diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-18 21:32:28 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-18 21:32:28 +0200 |
| commit | 992c36c6c7ce7e1e732866b3cd4fb8269a905875 (patch) | |
| tree | 15b7ae06b14341929e555ebc126f07d963213104 /web/frontend/ride-filters.ts | |
| parent | 51613971c1e25dedbc808c66b79d15111d250160 (diff) | |
Diffstat (limited to 'web/frontend/ride-filters.ts')
| -rw-r--r-- | web/frontend/ride-filters.ts | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/web/frontend/ride-filters.ts b/web/frontend/ride-filters.ts new file mode 100644 index 0000000..24c23e8 --- /dev/null +++ b/web/frontend/ride-filters.ts @@ -0,0 +1,49 @@ +import { requireElement } from "./dom.js"; +import { + formatRideFilterValue, + normalizeRideFilterRange, + type RideFilterRangeFormat, + type RideFilterRangeHandle, +} from "./ride-filters-logic.js"; + +const mountRangeFilter = (container: HTMLElement): void => { + const format = container.dataset.rangeFormat as RideFilterRangeFormat | undefined; + if (!format) throw new Error("Missing ride filter range format"); + const minInput = requireElement(container.querySelector<HTMLInputElement>("[data-range-min]"), "ride filter minimum input"); + const maxInput = requireElement(container.querySelector<HTMLInputElement>("[data-range-max]"), "ride filter maximum input"); + const track = requireElement(container.querySelector<HTMLElement>("[data-range-track]"), "ride filter range track"); + const group = requireElement(container.parentElement, "ride filter group"); + const minOutput = requireElement(group.querySelector<HTMLOutputElement>('[data-range-value="min"]'), "ride filter minimum output"); + const maxOutput = requireElement(group.querySelector<HTMLOutputElement>('[data-range-value="max"]'), "ride filter maximum output"); + const lowerBound = Number(minInput.min); + const upperBound = Number(minInput.max); + + const update = (changed?: RideFilterRangeHandle): void => { + const range = normalizeRideFilterRange(Number(minInput.value), Number(maxInput.value), changed ?? "min"); + minInput.value = String(range.min); + maxInput.value = String(range.max); + const span = Math.max(upperBound - lowerBound, 1); + const start = ((range.min - lowerBound) / span) * 100; + const end = ((range.max - lowerBound) / span) * 100; + track.style.setProperty("--range-start", `${start}%`); + track.style.setProperty("--range-end", `${end}%`); + const minLabel = formatRideFilterValue(format, range.min); + const maxLabel = formatRideFilterValue(format, range.max); + minOutput.value = minLabel; + maxOutput.value = maxLabel; + minOutput.textContent = minLabel; + maxOutput.textContent = maxLabel; + minInput.setAttribute("aria-valuetext", minLabel); + maxInput.setAttribute("aria-valuetext", maxLabel); + }; + + minInput.addEventListener("input", () => update("min")); + maxInput.addEventListener("input", () => update("max")); + update(); +}; + +export const mountRideFilters = (): void => { + document.querySelectorAll<HTMLElement>("[data-range-filter]").forEach(mountRangeFilter); +}; + +mountRideFilters(); |