1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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();
|