Adjust the maximum and minimum values on a dual thumb slider

I have implemented a two thumb range slider to define the maximum and minimum values. However, I recently discovered that it is possible for the thumbs to cross over each other - the max value can exceed the min value and vice versa.

I am looking for a solution to prevent the min value from exceeding the max value and ensure that the max value does not go below the min value.

Despite conducting some research, I have not come across any useful JavaScript solutions for this issue. Is there any alternative option available that could help in resolving this matter?

const twoRangeSlider = (() => {
  const rangeCheck = (rangeInputs, rangeMinOutput, rangeMaxOutput) => {
    const rangeMin = rangeInputs[0].min ? rangeInputs[0].min : 0;
    const rangeMax = rangeInputs[0].max ? rangeInputs[0].max : 100;
    let rangeMinValue = parseFloat(rangeInputs[1].value);
    let rangeMaxValue = parseFloat(rangeInputs[0].value);

    rangeMinValue = Math.min(Math.max(rangeMinValue, rangeMin), rangeMaxValue);


    const rangeMinPercentage = Number(
      ((rangeMinValue - rangeMin) * 100) / (rangeMax - rangeMin));
    const rangeMaxPercentage = Number(
      ((rangeMaxValue - rangeMin) * 100) / (rangeMax - rangeMin));


    rangeInputs[0].style.background = `linear-gradient(to right, #000 ${rangeMaxPercentage}%, #c4c8ca ${rangeMaxPercentage}%)`;
    rangeInputs[1].style.background = `linear-gradient(to right,#c4c8ca ${rangeMinPercentage}%, transparent ${rangeMinPercentage}%)`;


  };

  const bindComponent = (item) => {
    const rangeInputs = item.querySelectorAll('.js-two-range-slider-input');
    const rangeMinOutput = item.querySelector('.js-two-range-slider-min-value');
    const rangeMaxOutput = item.querySelector('.js-two-range-slider-max-value');

    item.addEventListener("input", () => {
      rangeCheck(rangeInputs, rangeMinOutput, rangeMaxOutput);
    });

    rangeCheck(rangeInputs, rangeMinOutput, rangeMaxOutput);
  };

  const init = () => {
    const rootEl = document.getElementsByClassName("js-two-range-slider");
    [...rootEl].forEach((item) => bindComponent(item));
  };

  return {
    init
  };
})();

twoRangeSlider.init();
.two-range-slider {
  position: relative;
  height: 4px;
  width: 164px;
  margin-bottom: 50px;
}

.two-range-slider__input {
  position: absolute;
  left: 40%;
  top: 15px;
  box-shadow: 0;
  appearance: none;
  width: 60%;
  height: 3px;
  border-radius: 50px;
  background-color: #000;
  outline: 0;
}

.two-range-slider__value {
  padding: 0px 10px;
  color: #000;
  position: relative;
  top: 19px;
  outline: none;
  width: 50px;
  position: absolute;
  border: 1px solid #ccc;
  box-sizing: border-box;
}

.two-range-slider__input::-webkit-slider-thumb {
  z-index: 2;
  position: relative;
  -webkit-appearance: none;
  appearance: none;
  height: 13px;
  width: 13px;
  border-radius: 50%;
  background: #000;
  cursor: pointer;
}

.two-range-slider__input::-moz-range-thumb {
  z-index: 2;
  position: relative;
  appearance: none;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  border: 0;
  background: #FFFFFF;
  cursor: pointer;
}

.two-range-slider__output {
  display: inline-flex;
  flex-flow: row nowrap;
  justify-content: space-between;
  width: 140%;
  top: -15px;
  margin-left: 0px;
  color: #000;
  position: relative;
}

.range-slider__value {
  padding: 0px 10px;
  color: #000;
  outline: none;
  width: 50px;
}
<div class="two-range-slider js-two-range-slider">
  <input type="range" value="80" min="10" max="100" step="1" class="two-range-slider__input js-two-range-slider-input">
  <input type="range" value="30" min="10" max="100" step="1" class="two-range-slider__input js-two-range-slider-input">

  <div class="two-range-slider__output">
    <p class="minmax">Min</p><input class="two-range-slider__value js-two-range-slider-min-value" type="number" value="30" min="10" max="100" step="1"></input>
    <p class="maxmin">Max</p><input style="right: -5px;" class="two-range-slider__value js-two-range-slider-max-value" type="number" value="80" min="10" max="100" step="1"></input>
  </div>

</div>

Answer №1

I made some modifications to your example in order to better illustrate my point from the previous comment.

const rangeSlider = (() => {

  const bindComponent = (element) => {
    const rangeInputs = element.querySelectorAll('.js-range-slider-input');

    element.addEventListener("input", ({ target }) => {
      const [ right, left ] = rangeInputs;
      if (target == right) {
        left.value = Math.min(+right.value -1, +left.value);
      } else {
        right.value = Math.max(+left.value +1, +right.value);
      }

    });

  };

  const initialize = () => {
    const rootElement = document.getElementsByClassName("js-range-slider");
    [...rootElement].forEach((item) => bindComponent(item));
  };

  return {
    initialize
  };
})();

rangeSlider.initialize();
.range-slider {
  position: relative;
  height: 4px;
  width: 164px;
  margin-bottom: 50px;
}

.range-slider__input {
  position: absolute;
  left: 40%;
  top: 15px;
  box-shadow: 0;
  appearance: none;
  width: 60%;
  height: 3px;
  border-radius: 50px;
  background-color: #000;
  outline: 0;
}

.range-slider__value {
  padding: 0px 10px;
  color: #000;
  position: relative;
  top: 19px;
  outline: none;
  width: 50px;
  position: absolute;
  border: 1px solid #ccc;
  box-sizing: border-box;
}

.range-slider__input::-webkit-slider-thumb {
  z-index: 2;
  position: relative;
  -webkit-appearance: none;
  appearance: none;
  height: 13px;
  width: 13px;
  border-radius: 50%;
  background: #000;
  cursor: pointer;
}

.range-slider__input::-moz-range-thumb {
  z-index: 2;
  position: relative;
  appearance: none;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  border: 0;
  background: #FFFFFF;
  cursor: pointer;
}

.range-slider__output {
  display: inline-flex;
  flex-flow: row nowrap;
  justify-content: space-between;
  width: 140%;
  top: -15px;
  margin-left: 0px;
  color: #000;
  position: relative;
}

.range-slider__value {
  padding: 0px 10px;
  color: #000;
  outline: none;
  width: 50px;
}
<div class="range-slider js-range-slider">
  <input type="range" value="80" min="10" max="100" step="1" class="range-slider__input js-range-slider-input">
  <input type="range" value="30" min="10" max="100" step="1" class="range-slider__input js-range-slider-input">

  <div class="range-slider__output">
    <p class="minmax">Min</p><input class="range-slider__value js-range-slider-min-value" type="number" value="30" min="10" max="100" step="1">
    <p class="maxmin">Max</p><input style="right: -5px;" class="range-slider__value js-range-slider-max-value" type="number" value="80" min="10" max="100" step="1">
  </div>

</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to assign a default value to an Angular input field

My web page utilizes an Angular form to display user data fetched from a MongoDB database. The information includes the user's name, phone number, email, etc. I want the default value of the input field to be set as the placeholder text, allowing user ...

When you use the useState object in NextJS, the context object may appear to be empty

I've encountered an issue while trying to pass a context object in NextJS that uses data from a useState hook. Strangely, the state variable and setState functions are undefined when consumed. It's puzzling because substituting a simple variable ...

javascript Why isn't the initial click registering?

In my table, users can select certain rows by using checkboxes. I have implemented some JavaScript functionality that allows them to select each checkbox individually and also use a "Select All" option. Additionally, there is code written to enable the use ...

Expansive menu that stretches the full height of the webpage

I'm having difficulty making my side spry menu extend the full length of the webpage. I tried using this code: $("nav").css({ "height" : $("nav").height() }); but it still isn't working as expected. I just want the grey color, like ...

The absence of the 'Access-Control-Allow-Origin' header is reported even though it is actually present

I have been attempting to send a POST request from one website to my own site. Despite allowing CORS access explicitly, every time I try to make the actual POST request, I am faced with the No 'Access-Control-Allow-Origin' header is present on th ...

Executing two jQuery scripts simultaneously on one page

Struggling to use 2 jQuery objects simultaneously on the same page. Can't get them both working at once despite playing around with the code. I'm new to this, so any help would be greatly appreciated. The code in the head section looks like this ...

Vue - Additional loading may be required to manage the output of these loaders

Currently working with Vue and babel. I have a function that's been exported // Inside file a.js export async function get() { ... } I am trying to link this exported function to a static method of MyClass // Inside file b.js import myInterface fr ...

Making an HTTP request within a forEach function in Angular2

Encountering an issue while using the forEach function with HTTP requests. The _watchlistElements variable contains the following data: [{"xid":"DP_049908","name":"t10"},{"xid":"DP_928829","name":"t13"},{"xid":"DP_588690","name":"t14"},{"xid":"DP_891890" ...

Display a static partial on a webpage using AJAX in Rails 3

So, I have 2 follow/unfollow forms in my Rails code. Here's the first one: <%= form_tag( {:controller => 'profile', :action => 'unfollow_topic' }) do %> <%= hidden_field_tag :topic_id, @topic.id %> <button ...

Creating a dual style name within a single component using Styled Components

Need assistance with implementing this code using styled components or CSS for transitions. The code from style.css: .slide { opacity: 0; transition-duration: 1s ease; } .slide.active { opacity: 1; transition-duration: 1s; transform: scale(1.08 ...

The hierarchical structure in the DOM that mirrors an HTML table

While working on code to navigate the DOM for a table, I encountered an unexpected surprise. The DOM (specifically in FF) did not align with my initial expectations. Upon investigation, it appears that FF has automatically inserted a tbody along with sever ...

How can we enhance Backbone.sync() at the Model level to include additional parameters?

Currently, I am facing a challenge with overriding Backbone's sync() method for a Model. I have the function signature set up and it is triggered correctly, but I am unsure about what needs to be included in the function body in order for it to automa ...

When an AJAX request is made, it can either return an array or a single object, potentially leading to

My proficiency in Javascript is definitely lacking, and I've only just begun to understand it. I have set up an AJAX call to an API using the GET method. The JSON data returned by the API is pretty standard. If I don't include an ID, I receive ...

Sorting through mongoose information on the front end using EJS depending on a dropdown pick

Beginner embarking on my inaugural project here. I have developed 2 Mongoose schematics and models for managing categories and products. The products are nested within the corresponding categories model. Using Node and Express, I successfully sent all ca ...

What potential issues arise from utilizing useRef alongside useSelector?

Although I have the capability to access the store by using thunks and/or global stores, I avoid binding my component to the Redux store. This is because the component will be utilized with various stores both inside and outside of the project. The compone ...

What causes a horizontal line to form when a user enters white space?

I have written a piece of code which seems to be causing an issue when running it. Whenever I input empty spaces, it results in creating a horizontal line. import React, { Component } from 'react'; export default class App extends Component { co ...

Encountering an issue when attempting to downgrade React Native version from 0.51 to 0.45

My current project requires me to downgrade due to certain third-party packages not being updated for the latest version of react-native. Specifically, I am using Xcode 9.0. Despite my efforts to downgrade the react-native version, I encountered the follo ...

jQuery - Inserting Content at the End

As an example, I have the following chunk of HTML code: <div class="messageContainer"> <div class="message"> </div> </div> ---Here <div class="messageContainer"> <div class="message"> <here> :) &l ...

In my opinion, CSS3 transform translateZ can be likened to scaling in some way

There are instances where I believe that the translateZ and scale properties produce similar effects, akin to zooming in or out. I suspect there is a mathematical relationship between them. If I know the value of one, such as translateZ(-1000px), along wi ...

What is the best way to configure the default selected value order in a jQuery select2 remote select box?

After customizing the select2 plugin to display default selected values, I encountered a problem when editing sessions. While creating a session and selecting multiple speakers from the dropdown, they were displayed as selected. However, when editing anoth ...