<div class="range_container js-range-slider js-filter" data-range-slider-id="slider1" data-type="range-slider" data-title="Air flow range">
    <div class="switchers js-switchers">
        <div class="switchers__title">Airflow range</div>
        <div class="switchers__list">
            <label for="radio-1" class="switchers__label">
                <input id="radio-1" value="radio-1" type="radio" name="radio" class="switchers__input" checked data-type="radio" data-max-beyond="110" data-step-increments="[10,20,50,100,200,500,1000]" data-steps="[0,70,250,500,2000,5000,15000,50000]">
                <span>m/h</span>
            </label>
            <label for="radio-2" class="switchers__label">
                <input id="radio-2" value="radio-2" type="radio" name="radio" class="switchers__input" data-type="radio" data-step-increments="[0.002,0.005,0.015,0.03,0.05,0.1,0.25]" data-steps="[0,0.02,0.07,0.14,0.56,1.39,4.17,13.89]">
                <span>m/s</span>
            </label>
            <label for="radio-3" class="switchers__label">
                <input id="radio-3" value="radio-3" type="radio" name="radio" class="switchers__input" data-type="radio" data-max-beyond="140" data-step-increments="[5,10,10,50,50,100,200]" data-steps="[0,20,70,150,550,1400,4100,13900]">
                <span>l/s</span>
            </label>
        </div>
    </div>
    <div class="sliders_control">
        <input class="input" type="range" />
    </div>
    <div class="form_control">
        <div class="form_control_container">
            <output class="form_control_container__time__input input-label"></output>
        </div>
    </div>
</div>
<div class="range_container js-range-slider js-filter" {{{ getattributes attr }}}>
    {{> @switchers this }}
    <div class="sliders_control">
        <input class="input" type="range"/>
    </div>
    <div class="form_control">
        <div class="form_control_container">
            <output class="form_control_container__time__input input-label"></output>
        </div>
    </div>
</div>
{
  "attr": {
    "data-range-slider-id": "slider1",
    "data-type": "range-slider",
    "data-title": "Air flow range"
  },
  "radios": [
    {
      "name": "radio",
      "disabled": false,
      "checked": true,
      "label": "m/h",
      "value": "radio-1",
      "type": "radio",
      "attr": {
        "data-type": "radio",
        "data-max-beyond": "110",
        "data-step-increments": "[10,20,50,100,200,500,1000]",
        "data-steps": "[0,70,250,500,2000,5000,15000,50000]"
      }
    },
    {
      "name": "radio",
      "disabled": false,
      "checked": false,
      "label": "m/s",
      "value": "radio-2",
      "type": "radio",
      "attr": {
        "data-type": "radio",
        "data-step-increments": "[0.002,0.005,0.015,0.03,0.05,0.1,0.25]",
        "data-steps": "[0,0.02,0.07,0.14,0.56,1.39,4.17,13.89]"
      }
    },
    {
      "name": "radio",
      "disabled": false,
      "checked": false,
      "label": "l/s",
      "value": "radio-3",
      "type": "radio",
      "attr": {
        "data-type": "radio",
        "data-max-beyond": "140",
        "data-step-increments": "[5,10,10,50,50,100,200]",
        "data-steps": "[0,20,70,150,550,1400,4100,13900]"
      }
    }
  ]
}
  • Content:
    import { lerpExt } from '../../functions/lerp';
    
    class RangeSlider {
        constructor(el) {
            this.step = 0.001;
            this.wrapper = el;
            this.input = el.querySelector('.input');
            this.inputLabel = el.querySelector('.input-label');
            this.formControl = el.querySelector('.form_control');
            this.reset();
            this.input.addEventListener('change', this.handleInputChange.bind(this));
            this.input.addEventListener('input', this.handleInputChange.bind(this));
            el.addEventListener('reset', this.reset.bind(this));
        };
    
        set isDirty(value) {
            this.input.setAttribute('isDirty', value);
        }
    
        get isDirty() {
            return this.input.getAttribute('isDirty') === 'true';
        }
    
        reset (e) {
            this.input.min = 0;
            this.input.max = 1;
            this.input.step = this.step;
            this.input.value = 1;
            this.isDirty = false;
            this.render(this.input, '#D1D2D2', '#277D32');
            this.renderLabels(this.input);
        }
    
        handleInputChange(event) {
            this.isDirty = true;
            this.render(this.input, '#D1D2D2', '#277D32');
            this.renderLabels(this.input);
        }
    
        render(input, sliderColor, rangeColor) {
            const rangeDistance = input.max - input.min;
            const rangePosition = input.value;
            input.style.background = `linear-gradient(
            to right,
            ${rangeColor} 0%,
            ${rangeColor} calc(${(rangePosition) / (rangeDistance) * 100}%), 
            ${sliderColor} calc(${(rangePosition) / (rangeDistance) * 100}%), 
            ${sliderColor} 100%)`;
        }
    
        renderLabels(input, precision = 3) {
            let stepIncrements;
            let steps;
            try {
                stepIncrements = JSON.parse(this.wrapper.dataset.stepIncrements);
                steps = JSON.parse(this.wrapper.dataset.steps);
            } catch (e) {
                console.error('invalid JSON');
            }
            if (!stepIncrements || !steps) {
                return;
            }
            // The most left value on range(units)
            const minValue = steps[0];
            // The most right value on range(units)
            const maxValue = steps[steps.length - 1];
            // Interval width for single step(0-1)
            const stepInterval = 1 / stepIncrements.length;
    
            const stepIndex = Math.floor(input.value / stepInterval); // Index of handle interval
    
            const startValue = steps[stepIndex]; // Start value of handle interval(units)
            const endValue = steps[stepIndex + 1] || steps[stepIndex]; // End value of handle interval(units)
    
            // Handle multiplication value(units)
            const stepIncrement = stepIncrements[stepIndex] || stepIncrements[stepIncrements.length - 1];
    
            let multValue = lerpExt(startValue, endValue, (input.value - stepIndex * stepInterval) / stepInterval, stepIncrement, precision);
            multValue = Math.min(multValue, maxValue);
            input.dataset.realValue = multValue;
    
            this.dispatchChange(minValue, maxValue, multValue);
    
            this.inputLabel.textContent = multValue === maxValue ? `${multValue}+` : multValue;
    
            const accordionContent = this.inputLabel.closest('.accordion__content');
            if (accordionContent) {
                accordionContent.style.display = 'block';
            }
            const labelContainer = this.inputLabel.parentNode;
            const labelHalfWidth = labelContainer.offsetWidth / 2;
            const formControlWidth = this.formControl.offsetWidth;
            const labelOffset = Math.min(Math.max(this.input.value * formControlWidth, labelHalfWidth), formControlWidth - labelHalfWidth);
            labelContainer.style.left = `${labelOffset}px`;
    
            if (accordionContent) {
                accordionContent.style.display = '';
            }
        }
    
        dispatchChange(min, max, input) {
            if (this.isDirty) {
                this.wrapper.dispatchEvent(new CustomEvent('change', { detail:{
                    min, max, input, isDirty: this.isDirty
                } }));
            }
        }
    }
    
    export default RangeSlider;
    
  • URL: /components/raw/range-slider/RangeSlider.js
  • Filesystem Path: src/components/range-slider/RangeSlider.js
  • Size: 4 KB
  • Content:
    import RangeSlider from './RangeSlider';
    
    const els = document.querySelectorAll('.js-range-slider');
    
    for (let el of els) {
        new RangeSlider(el);
    }
    
  • URL: /components/raw/range-slider/index.js
  • Filesystem Path: src/components/range-slider/index.js
  • Size: 151 Bytes
  • Content:
    .range_container {
        display: flex;
        flex-direction: column;
        margin: 8px 0px;
    }
      
    .sliders_control {
        position: relative;
        min-height: 7px;
    }
    
    .form_control {
        position: relative;
        display: flex;
        justify-content: space-between;
        font-size: 14px;
        line-height: 20px;
        color: #635a5a;
        height: 36px;
    }
    
    .form_control_container {
        position: absolute;
        top: 0;
        transform: translateX(-50%);
        padding: 8px;
        background: $color-green-pale;
    }
      
    input[type=range]::-webkit-slider-thumb {
        -webkit-appearance: none;
        pointer-events: all;
        width: 12px;
        height: 12px;
        background-color: $color-green-dark;
        border-radius: 50%;
        cursor: grab;
        z-index: 2;
        position: relative;
        border: none;
    
        &:focus {
            outline: none;
        }
    }
      
    input[type=range]::-moz-range-thumb {
        -webkit-appearance: none;
        pointer-events: all;
        width: 12px;
        height: 12px;
        background-color: $color-green-dark;
        border-radius: 50%;
        cursor: grab;
        z-index: 2;
        position: relative;
        border: none;
    
        &:focus {
           outline: none;
        }
    }
      
    input[type=range]::-webkit-slider-thumb:hover {
        border: 2px solid $color-green-dark;
        background: $color-green-pale;
        cursor: grab;
        width: 14px;
        height: 14px;
    }
    
    input[type=range]::-moz-range-thumb:hover {
        border: 2px solid $color-green-dark;
        background: $color-green-pale;
        cursor: grab;
        width: 8px;
        height: 8px;
    }
    
    input[type=range]::-webkit-slider-thumb:active {
        cursor: grabbing;
        border: 3px solid $color-green-dark;
    }
    
    input[type=range]::-moz-range-thumb:active {
        cursor: grabbing;
        border: 3px solid $color-green-dark;
        width: 8px;
        height: 8px;
    }
    
    input[type="range"] {
        -webkit-appearance: none; 
        appearance: none;
        height: 2px;
        width: 100%;
        position: absolute;
        background-color: $color-green-dark;
        pointer-events: none;
    
        &:focus {
            outline: 0;
        }
    }
    
    input[type="range"]:focus-visible::-webkit-slider-thumb {
        outline: 2px solid #000;
        background: $color-green-pale;
    }
    
    input[type="range"]:focus-visible::-moz-range-thumb {
        outline: 2px solid $color-black;
        background: $color-green-pale;
    }
    
    
  • URL: /components/raw/range-slider/range-slider.scss
  • Filesystem Path: src/components/range-slider/range-slider.scss
  • Size: 2.2 KB

No notes defined.