Files
santeh-ray/static/js/catalog-price-slider.js
Azimkin 3d356c7d6a
All checks were successful
Build and Push Docker Image / build (push) Successful in 41s
feat: add price filter and dynamic slider to catalog
- Implemented JavaScript-based price slider for catalog filtering
- Updated catalog views to handle min/max price inputs and compute slider bounds
- Enhanced templates (`index.html`, `side-bar.html`) with filtering form and updated URLs
- Added CSS for price slider styling and form layout
- Introduced utility functions for URL building and price parsing
- Expanded tests for price filtering, sliders, and sidebar active states
- Updated context processor and header for dynamic navigation with price filters
2026-05-16 11:12:24 +02:00

62 lines
2.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
document.addEventListener('DOMContentLoaded', function () {
const priceFormatter = new Intl.NumberFormat('ru-RU', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
const formatQueryValue = function (value) {
return value.toFixed(2).replace(/\.?0+$/, '');
};
document.querySelectorAll('[data-price-slider]').forEach(function (slider) {
const minBound = Number.parseFloat(slider.dataset.minBound || '0');
const maxBound = Number.parseFloat(slider.dataset.maxBound || slider.dataset.minBound || '0');
const minRange = slider.querySelector('[data-price-range-min]');
const maxRange = slider.querySelector('[data-price-range-max]');
const minHidden = slider.querySelector('[data-price-hidden-min]');
const maxHidden = slider.querySelector('[data-price-hidden-max]');
const minLabel = slider.querySelector('[data-price-label-min]');
const maxLabel = slider.querySelector('[data-price-label-max]');
const trackFill = slider.querySelector('[data-price-track-fill]');
if (!minRange || !maxRange || !minHidden || !maxHidden || !minLabel || !maxLabel || !trackFill) {
return;
}
const updateSlider = function () {
const minValue = Number.parseFloat(minRange.value);
const maxValue = Number.parseFloat(maxRange.value);
const rangeSpan = maxBound - minBound;
const left = rangeSpan > 0 ? ((minValue - minBound) / rangeSpan) * 100 : 0;
const right = rangeSpan > 0 ? ((maxValue - minBound) / rangeSpan) * 100 : 100;
trackFill.style.left = left + '%';
trackFill.style.width = Math.max(right - left, 0) + '%';
minLabel.textContent = priceFormatter.format(minValue) + ' руб.';
maxLabel.textContent = priceFormatter.format(maxValue) + ' руб.';
minHidden.value = minValue <= minBound ? '' : formatQueryValue(minValue);
maxHidden.value = maxValue >= maxBound ? '' : formatQueryValue(maxValue);
};
minRange.addEventListener('input', function () {
if (Number.parseFloat(minRange.value) > Number.parseFloat(maxRange.value)) {
minRange.value = maxRange.value;
}
updateSlider();
});
maxRange.addEventListener('input', function () {
if (Number.parseFloat(maxRange.value) < Number.parseFloat(minRange.value)) {
maxRange.value = minRange.value;
}
updateSlider();
});
updateSlider();
});
});