2023-03-10 20:43:49 +01:00

162 lines
5.3 KiB
JavaScript

function initSliders() {
document.querySelectorAll('.double-slider').forEach(setupSlider);
}
function setupSlider(slider) {
const left_input = slider.querySelector('input.left');
const right_input = slider.querySelector('input.right');
const left_thumb = slider.querySelector('.left-thumb');
const right_thumb = slider.querySelector('.right-thumb');
left_thumb.onmousedown = event => {
selectLeft();
startDrag(event, left_thumb);
}
right_thumb.onmousedown = event => {
selectRight()
startDrag(event, right_thumb);
}
updateSlider(slider);
let x0 = 0;
let clientX0 = 0;
let input = null;
let effective_width = 0;
let slider_min_value = 0;
let slider_max_value = 0;
let slider_range = 0;
let thumb_min_value = 0;
let thumb_max_value = 0;
function selectRight() {
input = right_input;
thumb_min_value = Math.max(right_input.min, parseInt(left_input.value));
thumb_max_value = right_input.max;
}
function selectLeft() {
input = left_input;
thumb_min_value = left_input.min;
thumb_max_value = Math.min(left_input.max, parseInt(right_input.value));
}
function startDrag(event, thumb) {
event = event || window.event;
event.preventDefault();
clientX0 = event.clientX;
x0 = event.clientX - thumb.getBoundingClientRect().left + slider.getBoundingClientRect().left;
effective_width = slider.getBoundingClientRect().width - thumb.getBoundingClientRect().width;
slider_min_value = left_input.min;
slider_max_value = right_input.max;
slider_range = slider_max_value - slider_min_value;
document.onmouseup = endDrag;
document.onmousemove = drag;
}
function drag(event) {
event = event || window.event;
event.preventDefault();
let forceUpdate = false;
// calculate mouse position relative to slider
let new_thumb_x = event.clientX - x0;
new_thumb_x = Math.max(0, Math.min(effective_width, new_thumb_x));
// convert position into value
let progress = new_thumb_x / parseFloat(effective_width);
let value = Math.round(slider_min_value + (progress * slider_range));
// switch selected thumb if outside thumb value range
if (value < parseInt(left_input.value) && input === right_input) {
input.value = thumb_min_value;
selectLeft();
forceUpdate = true;
} else if (value > parseInt(right_input.value) && input === left_input) {
input.value = thumb_max_value;
selectRight();
forceUpdate = true;
}
// clamp value
value = Math.max(thumb_min_value, Math.min(thumb_max_value, value));
// apply changes
if (value !== parseInt(input.value)) {
changeValue(input, value);
forceUpdate = true;
}
// update gui if necessary
if (forceUpdate) {
updateSlider(slider);
}
}
function endDrag() {
document.onmouseup = null;
document.onmousemove = null;
}
}
function updateSlider(slider) {
const left_input = slider.querySelector('input.left');
const right_input = slider.querySelector('input.right');
const slider_min_value = left_input.min;
const slider_max_value = right_input.max;
const slider_range = slider_max_value - slider_min_value;
const left_max_value = left_input.max;
const right_min_value = right_input.min;
const left_thumb = slider.querySelector('.left-thumb');
const right_thumb = slider.querySelector('.right-thumb');
const bar = slider.querySelector('.bar');
const clampedLeft = Math.max(slider_min_value, Math.min(left_max_value, parseInt(left_input.value)));
const clampedRight = Math.max(Math.max(clampedLeft, right_min_value), Math.min(slider_max_value, parseInt(right_input.value)));
if (parseInt(left_input.value) !== clampedLeft) {
changeValue(left_input, clampedLeft);
}
if (parseInt(right_input.value) !== clampedRight) {
changeValue(right_input, clampedRight);
}
positionThumbInSlider(left_thumb, left_input.value - slider_min_value, slider_range);
positionThumbInSlider(right_thumb, right_input.value - slider_min_value, slider_range);
positionBarInSlider(bar, left_input.value - slider_min_value, right_input.value - slider_min_value, slider_range);
}
function positionThumbInSlider(thumb, position, range) {
let progress = position / parseFloat(range);
progress = Math.max(0, Math.min(1, progress));
thumb.style.left = 'calc(' + (100 * progress) + '% - ' + (progress) + 'em)';
}
function positionBarInSlider(bar, left, right, range) {
let leftProgress = left / parseFloat(range);
leftProgress = Math.max(0, Math.min(1, leftProgress));
let rightProgress = right / parseFloat(range);
rightProgress = Math.max(0, Math.min(1, rightProgress));
bar.style.left = 'calc(' + (100 * leftProgress) + '% - ' + (leftProgress) + 'em)';
bar.style.width = 'calc(' + (100 * (rightProgress - leftProgress)) + '% - ' + (rightProgress - leftProgress) + 'em)';
}
function changeValue(input, value) {
input.value = value;
let evt = document.createEvent('HTMLEvents');
evt.initEvent('change', false, true);
input.dispatchEvent(evt);
}