javascriptjqueryhtmljquery-uijquery-ui-slider

How can I restrict the range of a jQuery UI slider?


I have created a jQuery UI slider, which has its range set to true and has two handles at 0 and 4. I want to restrict the range of these handles to a maximum of 4. This means when user slides one of the handles and the position of other makes the range go beyond 4 then the other handle should slide to keep the range as 4 but if it the range is less than 4 then it shouldn't slide.

This means if ui.values[0] is equal to 0 and user slides the other handle to say 10, then this handle should slide to 6 along with it. But, if ui.values[0] is equal to 2 and the user slides the other handle to 4, then it should remain where it is.

Some example sets of values are :

  1. 1 to 5
  2. 0 to 4
  3. 0 to 2
  4. 16 to 19

I've created a JSFiddle to try on this: https://jsfiddle.net/j4hd760f/

Code from JSFiddle as a snippet:

$('.slider').slider({
    range: true,
    values: [0, 4],
    slide: function (ev, ui) {
        var ui1 = ui.values[0];
        var ui2 = ui.values[1];
        $('.slider').not(this).each(function () {
            total += $(this).slider('value');
        })
        $('#total').text(ui1 + " " + ui2);
    }
});
.slider {
    margin: 16px;
    width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css">
<div id="slider1" class="slider"></div>
<div id="total"></div>


Solution

  • There is no specific setting within jQuery UI Sliders to directly accomplish what you desire. Thus, you will need have code which does so in the slide handler.

    The code below will accomplish what you desire. However, I changed the maximum permitted difference to be 20 instead of 4, because 4 is just not visible on a 200 pixel wide slider. You can easily change this maximum difference by setting sliderMaxDifference. If you really want 4, another snippet is included near the end of this answer.

    var sliderMaxDifference = 20;
    var timeout;
    $('.slider').slider({
        range: true,
        values: [0, 4],
        slide: function (ev, ui) {
            var movedValue = ui.value;
            //ui.handleIndex does not exist in this version of jQuery UI
            //Determine which slider moved
            var handleIndex = 1;
            if(ui.handle.nextSibling && ui.handle.nextSibling.nodeName === 'A'){
                handleIndex = 0;
            }
            var unmovedValue = ui.values[1 - handleIndex];
            //Compute the new value for the unmoved slider
            unmovedValue = Math.max(unmovedValue,movedValue - sliderMaxDifference);
            unmovedValue = Math.min(unmovedValue,movedValue + sliderMaxDifference);
            //Set the following slider value
            $(this).slider('values',1 - handleIndex, unmovedValue);
            //$(this).slider('values') will not yet reflect the new values
            //var newValues=$(this).slider('values');
            var newValues=[]
            newValues[handleIndex] = movedValue;
            newValues[1 - handleIndex] = unmovedValue;
            $('#total').text(newValues[0] + "-->" + newValues[1] 
                             + ' Difference=' + (newValues[1]-newValues[0]));
        }
    });
    .slider {
        margin: 16px;
        width: 200px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
    <link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css">
    <div id="slider1" class="slider"></div>
    <div id="total"></div>

    It should be noted that the jQuery UI slider does not permit the lower slider to become larger than the higher slider. This results in some UI confusion when the sliders are equal. You have to move the slider which you most recently moved back off of the other slider in order to grab the other slider to move it.

    I removed your code:

    $('.slider').not(this).each(function () {
        total += $(this).slider('value');
    })
    

    Because, it appeared to do nothing (total was never declared, or otherwise used).

    If you really wanted it with a difference of 4, then you can try the following snippet (only changed: var sliderMaxDifference = 4;):

    var sliderMaxDifference = 4;
    var timeout;
    $('.slider').slider({
        range: true,
        values: [0, 4],
        slide: function (ev, ui) {
            var movedValue = ui.value;
            //ui.handleIndex does not exist in this version of jQuery UI
            //Determine which slider moved
            var handleIndex = 1;
            if(ui.handle.nextSibling && ui.handle.nextSibling.nodeName === 'A'){
                handleIndex = 0;
            }
            var unmovedValue = ui.values[1 - handleIndex];
            //Compute the new value for the unmoved slider
            unmovedValue = Math.max(unmovedValue,movedValue - sliderMaxDifference);
            unmovedValue = Math.min(unmovedValue,movedValue + sliderMaxDifference);
            //Set the following slider value
            $(this).slider('values',1 - handleIndex, unmovedValue);
            //$(this).slider('values') will not yet reflect the new values
            //var newValues=$(this).slider('values');
            var newValues=[]
            newValues[handleIndex] = movedValue;
            newValues[1 - handleIndex] = unmovedValue;
            $('#total').text(newValues[0] + "-->" + newValues[1] 
                             + ' Difference=' + (newValues[1]-newValues[0]));
        }
    });
    .slider {
        margin: 16px;
        width: 200px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
    <link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css">
    <div id="slider1" class="slider"></div>
    <div id="total"></div>

    A more generic solution would use an attribute on the slider to store the difference permitted for that particular slider.