JSFiddle - React, Tailwind, and code Playground

by blesh

HTML

<div class="range-slider" id="foo" data-min="0" data-max="200">
    <div class="range-slider-caret range-slider-min" data-name="minVal" style="left: 0%;"></div>
    <div class="range-slider-caret range-slider-max" data-name="maxVal" style="left: 100%;"></div>
</div>

<div class="range-slider" data-min="0" data-max="200">
    <div class="range-slider-caret range-slider-min" data-name="minVal" style="left: 0%;"></div>
    <div class="range-slider-caret range-slider-max" data-name="maxVal" style="left: 100%;"></div>
</div>
<p>Min:
    <input id="minVal" type="text" />
    <br/>Max:
    <input id="maxVal" type="text" />
</p>

CSS

.range-slider {
    display: inline-block;
    position: relative;
    width: 400px;
    height: 10px;
    margin: 5px 10px 5px 10px;
    background: #ccc;
    border: 1px solid #999;
}
.range-slider-caret {
    top: 0;
    left: 0;
    width: 10px;
    height: 20px;
    position: absolute;
    margin-top: -6px;
    margin-left: -6px;
    border: 1px solid #999;
    background: #ccc;
}
.range-slider-min {
    margin-left: -12px;
}
.range-slider-max {
    margin-left: 0;
}

JavaScript

//RANGE SLIDER

(function (window, $) {
    var movingCaret,
    movingSlider;

    function caretMouseDown(e) {
        movingCaret = $(this);
        movingSlider = movingCaret.parent();
        $('html').one('mouseup', sliderDocMouseUp)
            .on('mousemove', sliderMouseMove);
    }

    function sliderDocMouseUp(e) {
        $('html').off('mousemove', sliderMouseMove);
        movingCaret = movingSlider = null;
    }

    function constrain(min, max, val) {
        return Math.min(max, Math.max(min, val));
    }

    function sliderMouseMove(e) {
        if (movingCaret) {
            var sw = movingSlider.width(),
                sliderPos = movingSlider.position(),
                x = e.clientX - sliderPos.left,
                l = constrain(0, 100, x / sw * 100);
            movingCaret.css('left', l + '%');

            movingCaret.nextAll('.range-slider-caret').each(function () {
                var sib = $(this),
                    sibLeft = sib.position().left;
                if (x > sibLeft) {
                    sib.css('left', l + '%');
                }
            });
            movingCaret.prevAll('.range-slider-caret').each(function () {
                var sib = $(this),
                    sibLeft = sib.position().left;
                if (x < sibLeft) {
                    sib.css('left', l + '%');
                }
            });

            sendValueUpdates(movingSlider);
        }
    }

    function sendValueUpdates(slider) {
        setTimeout(function () {
            var carets = slider.children('.range-slider-caret'),
                values = {},
                sw = slider.width();
            carets.each(function () {
                var caret = $(this),
                    name = caret.data('name'),
                    min = parseFloat(slider.data('min')) || 0,
                    max = parseFloat(slider.data('max')) || 100,
                    range = max - min,
                    leftPerc = caret.position().left /...