Двойной ползунок фильтра
Часто требуется двойной ползунок для фильтра в интернет-магазине. Код ниже решает эту задачу
HTML
<div class="page">
<div class="container">
<div class="range">
<div class="range-slider">
<span class="range-selected"></span>
</div>
<div class="range-input">
<input type="range" class="min" min="0" max="1000" value="300" step="10">
<input type="range" class="max" min="0" max="1000" value="700" step="10">
</div>
<div class="range-price">
<label for="min">Min:</label>
<input type="number" name="min" class="min" value="300" step="10">
<label for="max">Max:</label>
<input type="number" name="max" class="max" value="700" step="10">
</div>
</div>
</div>
</div>CSS
.range-slider{
height: 5px;
position: relative;
background-color: #e1e9f6;
}
.range-selected{
height: 100%;
left: 30%;
right: 30%;
position: absolute;
border-radius: 5px;
background-color: #1b53c0;
transition: 200ms;
}
.range-input{
position: relative;
}
.range-input input{
position: absolute;
width: 100%;
height: 5px;
top: -6px;
background: none;
pointer-events: none;
-webkit-appearance: none;
-moz-appearance: none;
}
.range-input input::-webkit-slider-thumb {
height: 14px;
width: 14px;
border-radius: 50%;
border: 1px solid #1b53c0;
background-color: #1b53c0;
pointer-events: auto;
-webkit-appearance: none;
cursor: pointer;
}
.range-input input::-moz-slider-thumb {
height: 14px;
width: 14px;
border-radius: 50%;
border: 1px solid #1b53c0;
background-color: #1b53c0;
pointer-events: auto;
-moz-appearance: none;
cursor: pointer;
}
.range-price{
margin: 30px 0;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.range-price label{
margin-right: 5px;
}
.range-price input{
width: 70px;
padding: 5px;
}
.range-price input:first-of-type {
margin-right: 15px;
}JavaScript
let rangeMin = 100; // это минимальный диапазон для выбора
const range = document.querySelector(".range-selected"); // сам диапазон между двумя значениями (полоска)
const rangeInput = document.querySelectorAll(".range-input input"); // оба инпута для выбора
const rangePrice = document.querySelectorAll(".range-price input"); // оба инпута (окошка со значениями)
rangeInput.forEach((input) => {
// для каждого инпута выбора (range) делаем следующее:
input.addEventListener("input", (e) => {
// добавляем прослушиватель события 'input', то есть при взаимодействии
let minRange = parseInt(rangeInput[0].value); // кладем в переменную миним значение
let maxRange = parseInt(rangeInput[1].value); // кладем в переменную максим значение
if (maxRange - minRange < rangeMin) {
// если минДиапВыбора больше разницы значений обоих инпутов
if (e.target.className === "min") {
// если изменяемый элемент имеет класс 'min', то...
rangeInput[0].value = maxRange - rangeMin; // значеие минимального Инпута вычисляем: (значМаксИнпута - минДиапВыбора)
} else {
// в противном случае...
rangeInput[1].value = minRange + rangeMin; // значение максимального Инпута вычисляем: (значМинИнпута + минДиапВыбора)
}
} else {
// в противном случае
rangePrice[0].value = minRange; // значение минимального окошка инпута приравниваем к значМинИнпута
rangePrice[1].value = maxRange; // значение максимального окошка инпута приравниваем к значМаксИнпута
range.style.left = (minRange / rangeInput[0].max) * 100 + "%"; // выставляем левую сторону полосы
range.style.right = 100 - (maxRange / rangeInput[1].max) * 100 + "%"; // выставляем правую сторону полосы
}
});
});
rangePrice.forEach((input) => {
// для каждого окошка Price Input
input.addEventListener("input", (e) => { // добавляем слушатель событий Input (ввода числа)
let minPrice = parseInt(rangePrice[0].value); // переменная минЗначОкнаВвода
let maxPrice = parseInt(rangePrice[1].value); // переменная максЗначОкнаВвода
if (maxPrice - minPrice >= rangeMin && maxPrice <= rangeInput[1].max) { // если разница значений окон ввода меньше минДиапВыбора
if (e.target.className === "min") { // если данное окно имеет класс 'min'
rangeInput[0].value = minPrice; // то значение мин ползунка выставляем равное значению окна с классом 'min'
range.style.left = (minPrice / rangeInput[0].max) * 100 + "%"; // левую сторону полоски выставляем в соответствии
} else { // в противном случае
rangeInput[1].value = maxPrice; // значение макс ползунка выставляем равное значению окна с классом 'max'
range.style.right = 100 - (maxPrice / rangeInput[1].max) * 100 + "%"; // правую сторону полоски выставляем в соответствии
}
}
});
});