two-sides-slider

by Vladymyr Shevchuk

HTML

<div class="container">
  <div id="start-value" class="value">0$</div>

  <div class="slider">
    <div id="field" class="field">
      <div id="fill-left" class="fill left">&nbsp;</div>
      <div id="control-left" class="js-control-left control left">&nbsp;</div>
      <div id="fill-right" class="fill right">&nbsp;</div>
      <div id="control-right" class="js-control-right control right">&nbsp;</div>
    </div>
  </div>

  <div id="end-value" class="value">4000$</div>
</div>

CSS

.container {
  outline: 1px dotted grey;
  width: 300px;
  height: 300px;
  margin: auto;
  display: flex;
  align-items: center;
  flex-direction: row;
}

.value {
  width: 100px;
  text-align: center;
}

.slider {
  width: 100%;
  height: 5px;
  position: relative;
}

.field {
  width: 100%;
  height: 100%;
  background: #109CF2;
  position: absolute;
  user-select: none;
}

.control {
  border: 1px solid grey;
  box-sizing: border-box;
  width: 5px;
  height: 16px;
  background: white;
  position: absolute;
  margin: auto;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  user-select: none;
}

.control:active {
  border-color: #8b8b8b;
  background: #eaeaea;
}

.fill {
  background: #eaeaea;
  opacity: .5;
  width: 5px;
  height: 100%;
  position: absolute;
}

.left {
  left: 0px;
}

.right {
  right: 0px;
}

JavaScript

const $field = document.getElementById('field');
const $fillLeft = document.getElementById('fill-left');
const $fillRight = document.getElementById('fill-right');
const $start = document.getElementById('start-value');
const $end = document.getElementById('end-value');
const $controlLeft = document.getElementById('control-left');
const $controlRight = document.getElementById('control-right');

const step = getSliderStep();
const { end: initEndValue } = getBoundariesValues();

$field.addEventListener('mousedown', event => {
  const { target: control } = event;

  if (control.classList.contains('js-control-left')) {
    const boundary = getBoundary();
    const { left } = $field.getBoundingClientRect();
    const { offsetLeft } = control;
    const shift = event.pageX - left - pageXOffset;

    document.onmousemove = mouseMoveEvent => {
      const move = offsetLeft + (mouseMoveEvent.pageX - left - shift);

      if (move >= 0 && move <= boundary + offsetLeft) {
        const { end } = getBoundariesValues();
        const value = move * step;
        const newBoundary = value > end ? end : value;

        control.style.left = move + 'px';
        $fillLeft.style.width = move + 'px';

        changeBoundariesValues({start: newBoundary})
      }
    };

    clearEventListeners();
  }

  if (control.classList.contains('js-control-right')) {
    const boundary = getBoundary();
    const { right, width } = $field.getBoundingClientRect();
    const { offsetLeft } = control;
    const shift = right - event.pageX + pageXOffset;

    document.onmousemove = mouseMoveEvent => {
      const rightPadding = width - offsetLeft - control.getBoundingClientRect().width;
      const move = rightPadding + right - mouseMoveEvent.pageX - shift;

      if (move >= 0 && move <= boundary + rightPadding) {
        const { start } = getBoundariesValues();
        const value = initEndValue - move * step;
        const newBoundary = value < start ? start : value;

        control.style.right =...