-1

I need my three range sliders to share from a common "value pool." So if the max is 100, and slider-1 is set to 51. you should expect slider-2 and 3 to take from a shared pool of 49. The way I have it now, if you change slider 1, slider 2 and 3 are equal. This is not ideal!

How would you go about making it so I could set slider-1 to a value of "51" for example, and then set slider-2 to a value of "30" making slider-3 automatically "19".

And then from there, if I bump slider 3 with a value of "19" up to "20" for example, slider-2 changes to "29.5" and slider-1 changes to "50.5"

Here is a jsfiddle, hope my question makes sense:

https://jsfiddle.net/7ho3zfve/

Andrew Walsh
  • 35
  • 10
  • Do you have to always use the entire value pool or could you have a total of say 50? – CumminUp07 Jul 24 '17 at 18:02
  • Would be ideal, yes. But perhaps I could settle on not doing that. – Andrew Walsh Jul 24 '17 at 18:05
  • could the sliders have different max values or would they always be the same? – CumminUp07 Jul 24 '17 at 18:10
  • also, you have jquery tagged, does that mean you are using jquery or do you need it all in pure javascript – CumminUp07 Jul 24 '17 at 18:14
  • So you have three sliders and you want them to act as input devices for the parameters of some simple maths equation. Yes that's eminently possible. But you have a major issue to consider - namely that the calculation performed will depend on which slider is moved. With two sliders and a result field, it's simple. But with three sliders, things start getting complicated. – Roamer-1888 Jul 24 '17 at 18:20
  • if you are willing to use a library you can check this out, http://keith-wood.name/linkedsliders.html it does what you need it to do – CumminUp07 Jul 24 '17 at 18:38
  • Thanks @CumminUp07 I'll check that library out. I should be able to make that work! – Andrew Walsh Jul 24 '17 at 18:42

2 Answers2

0

There are a few things to note: first, you are really using redundant code. If you decide later to add more inputs, you're doing the same thing multiple times. Instead, use classes. You can have a single function or collection of functions that work on all inputs, as the behavior is going to be the same across them all.

Now, if I understand you correctly, you want a set max value to be respected, and any elements that have NOT yet been manually moved, to have their values set to an equal portion of the remaining max value? The code below will do that. It includes a draggable detector (basically, the sliders have a mousedown event that sets the isDragging, and the mousemove event checks that it is, in fact, dragging), which is when the remainder of the maxVal is split. The code is pretty heavily commented, it should get you most of the way to what you're looking for.

The one thing I haven't really worked on yet, and potentially a big pitfall, is that, when two of the three sliders have been manually set, you can still move the THIRD slider to the right. I'm guessing you'd want to catch that, but I haven't worked out that logic yet.

var maxVal = 1000,
  isDragging = false,
  fixedEls, flexEls;
/***
 * Tracking the dragging -- on mousedown, I set the isDragging
 *  to true, then I check that for the mousemove on this element.
 *  On mouseup, I reset the isDragging to false, thus ending the
 *  simulated drag event.
 ***/
$(".slide-control").on("mousemove", function() {
  if (isDragging) {
    // I want to keep two collections of sibling elements:
    //  those that have NOT been moved, and those that HAVE.
    //  I simply add the .slider-fixed to those that have,
    //  which are elements I don't want to be moveable later.
    fixedEls = $(this).siblings("input.slider-fixed");
    flexEls = $(this).siblings("input").not(".slider-fixed");
    // The subtotal I will be using is simply the current
    //  slider element plus any elements that have already had
    //  their .slider-fixed class set. The resulting value,
    //  subtracted from the above maxVal, will be the pool of
    //  values for any non-fixed sliders.
    var subtotal = parseInt($(this).val());
    fixedEls.each(function() {
      subtotal += parseInt($(this).val());
    });
    // The sharedVals is the remaining value, evenly split
    //   between all moveable elements.
    var sharedVals = (maxVal - subtotal) / flexEls.length;
    // Set the element's val to that sharedVal.
    flexEls.each(function() {
      $(this).val(sharedVals)
    })
    /***
     * The following lines simply output the values of each slider
     *  to the results pane. Not a necessity, more a debug thing.
     ***/
    $(".results").empty();
    $(this).parent().children("input").each(function() {

      var myHtml = "<p>Slider " + $(this).prop("id") + ": " + $(this).val() + "</p>"
      $(".results").append(myHtml);
    })

  }
}).on("mouseup", function() {
  // When the drag event has ended, set the toggle off.
  isDragging = false;
  // I don't want this particular slider affected by any other
  //  movements.
  $(this).addClass("slider-fixed");

}).on("mousedown", function() {
  isDragging = true;
});
.slide-control {
  display: block;
  margin-left: 20px;
}

.slider-fixed::before {
  margin-left: -20px;
  content: ">>";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="header">
  <h3>A slider control</h3>
  <h4>Note: &gt;&gt; beside a slider indicates that it won't be affected by any further movement of other sliders.</h4>
</div>

<input type="range" id="myRange" value="0" min="0" max="1000" class="slide-control">
<input type="range" id="myRange2" value="0" min="0" max="1000" class="slide-control">
<input type="range" id="myRange3" value="0" min="0" max="1000" class="slide-control">
<div class="results">

</div>
Snowmonkey
  • 3,716
  • 1
  • 16
  • 16
  • Also, take a look at https://stackoverflow.com/questions/9360246/jquery-ui-slider-combined-max-for-multiple-sliders-that-also-have-individual-m and specifically, there's a reference to http://jsfiddle.net/mikecruz/bAntY/ – Snowmonkey Jul 24 '17 at 19:21
0

Went with CumminUp07's library suggestion here:keith-wood.name/linkedsliders.html to accomplish this.

Thanks everyone for putting together some useful information and code on this thread.

Andrew Walsh
  • 35
  • 10
  • Consider including some relevant code from that page into your answer here. Because if that link ever breaks, this answer here will be useless. – NickyTheWrench Jul 24 '17 at 21:50