javascriptjqueryjquery-slider

jQuery No-Ui-Slider, how to lock multiple interconnected sliders to always sum 100?


I am using NoUiSlider in some pages which could have 3, 4 or 5 sliders (http://refreshless.com/nouislider/).

I need to set the sliders to have a total value which is constrained to 100, so that if I raise the value of a slider, the others should lower a little and vice-versa, but I really don't know how to do it.

Can anyone help me please? Thanks!

jQuery code:

$(".slider.tied").each(function() {
    var context = $(this).addClass("noUiSlider");
    var input = context.prev(".amount"); // the input containing the actual slider value
    var val = input.val();
    var min = input.data("min");
    var max = input.data("max");

    context.noUiSlider({
        range: [min, max],
        start: val,
        step: 1,
        handles: 1,
        slide: function() {
            var value = $(this).val();
            input.val(value);
        }
    });
});

Solution

  • A possible solution:

    var init = true;
    var elements = $(".multislider").children(".slider.tied").length;
    var MAX = 100;
    var initValue = (MAX / elements) >> 0;
    var InitMod = MAX % elements;
    
    $(".slider.tied").each(function() {
        var slidersTied = $(".slider.tied");
        var context = $(this);
    
        var input = context.prev(".amount");
        var val = input.data('answer');
        var min = input.data('min');
        var max = input.data('max');
        var range = 1;
        var proceed = false;
    
        $(this).empty().slider({
            value: val,
            min: min,
            max: max,
            range: range,
            animate: "slow",
            create: function(event, ui){
    
                if (InitMod > 0) {
                    $(this).slider('value', initValue + 1);
                    $(this).prev('.amount').val(initValue + 1);
                    InitMod = InitMod - 1;
                }
                else
                {
                    $(this).slider('value', initValue);
                    $(this).prev('.amount').val(initValue);
                }
    
            },
            slide: function(e, ui) {
    
                // Update display to current value
                $(this).prev('.amount').val(ui.value);
    
                var current = ($(this).index() / 2) >> 0;
                var total = 0;
                var counter = 0
    
                slidersTied.not(this).each(function() {
    
                    total += $(this).slider("option", "value");                
                    counter += 1;
                });
    
                total += ui.value;
    
                if (total != MAX){
                    proceed = true;
                }
    
                var missing = MAX - total;
                console.log("missing: " + missing);
    
                counter = 0;
    
                if(proceed) {
    
                    //load elements array
                    var elements = [];
    
                    slidersTied.each(function() {
                        elements[counter] = $(this);
                        counter += 1;
                    });
    
                    var endIndex = counter - 1;
                    counter = endIndex + 1;
    
                    while (missing != 0) {
    
                        console.log("current counter: " + counter);
                        do {
                            if (counter == 0) 
                            {
                                counter = endIndex;
                            }
                            else
                            {
                                counter = counter - 1;
                            }
                        } while(counter == current)
    
                        console.log("elemento attuale: " + counter);
    
                        var value = elements[counter].slider("option", "value");
                        var result = value + missing;
    
                        if (result >= 0) 
                        {
                            elements[counter].slider('value', result);
                            elements[counter].prev('.amount').val(result);
    
                            missing = 0;    
                        }
                        else
                        {
                            missing = result;
                            elements[counter].slider('value', 0);
                            elements[counter].prev('.amount').val(0);
                        }
    
                    }
    
                }
    
            }
        });
    });
    

    Here's a fiddle:

    http://jsfiddle.net/vuQz5/11/

    Take care of setting the value of MAX variable to desired value (the sum of all slider's value together...