[ACCEPTED]-JQuery Slider, how to make "step" size change-slider

Accepted answer
Score: 53

Not sure if you want the slider scale to 40 be in proportion to your values* but if 39 so, I provided a solution to this for someone 38 else who asked the same question. You can find my solution here. Basically 37 I make use of the slide event that gets triggered 36 when you move the slider to mimic the stepping, but 35 based off a custom array defining the steps. This 34 way it only allows you to "step" to 33 your predefined values, even if they're 32 not evenly spread.

*In other words if you 31 want your slider to look like this:

|----|----|----|----|----|----|----|
0   10   20  100  1000 2000 10000 20000

then 30 go with one of the other solutions here, but 29 if you want your slider to look like this 28 (diagram not to scale):

|--|--|-------|-----------|-----------|--------------------|--------------------|
0 10 20     100         1000        2000               10000                20000

Then the solution 27 I linked to may be more what you're after.


Edit: Ok, this 26 version of the script should work with dual 25 sliders:

$(function() {
    var values = [0, 500, 750, 1000, 1250, 1500, 2000, 2500, 75000, 100000, 150000, 200000, 250000, 300000, 350000, 400000, 500000, 1000000];
    var slider = $("#price-range").slider({
        orientation: 'horizontal',
        range: true,
        min: 0,
        max: 1000000,
        values: [0, 1000000],
        slide: function(event, ui) {
            var includeLeft = event.keyCode != $.ui.keyCode.RIGHT;
            var includeRight = event.keyCode != $.ui.keyCode.LEFT;
            var value = findNearest(includeLeft, includeRight, ui.value);
            if (ui.value == ui.values[0]) {
                slider.slider('values', 0, value);
            }
            else {
                slider.slider('values', 1, value);
            }
            $("#price-amount").html('$' + slider.slider('values', 0) + ' - $' + slider.slider('values', 1));
            return false;
        },
        change: function(event, ui) { 
            getHomeListings();
        }
    });
    function findNearest(includeLeft, includeRight, value) {
        var nearest = null;
        var diff = null;
        for (var i = 0; i < values.length; i++) {
            if ((includeLeft && values[i] <= value) || (includeRight && values[i] >= value)) {
                var newDiff = Math.abs(value - values[i]);
                if (diff == null || newDiff < diff) {
                    nearest = values[i];
                    diff = newDiff;
                }
            }
        }
        return nearest;
    }
});

Note that it looks a little funny 24 down the far left end, since the jumps are 23 so close together compared to the right 22 hand end, but you can see its stepping as 21 desired if you use your keyboard arrows 20 to move the slider. Only way to get around 19 that is to change your scale to not be quite 18 so drastically exponential.


Edit 2: Ok, if the spacing 17 is too exaggerated when you use the true 16 values, you could use a set of fake values 15 for the slider & then look up the real 14 value this corresponds to when you need 13 to use the real value (in a similar way 12 to what the other solutions here suggested). Here's 11 the code:

$(function() {
    var trueValues = [0, 500, 750, 1000, 1250, 1500, 2000, 2500, 75000, 100000, 150000, 200000, 250000, 300000, 350000, 400000, 500000, 1000000];
    var values =     [0,   1,   2,    3,    4,    5,    6,    7,    10,     15,     20,     25,     30,     40,     50,     60,     75,     100];
    var slider = $("#price-range").slider({
        orientation: 'horizontal',
        range: true,
        min: 0,
        max: 100,
        values: [0, 100],
        slide: function(event, ui) {
            var includeLeft = event.keyCode != $.ui.keyCode.RIGHT;
            var includeRight = event.keyCode != $.ui.keyCode.LEFT;
            var value = findNearest(includeLeft, includeRight, ui.value);
            if (ui.value == ui.values[0]) {
                slider.slider('values', 0, value);
            }
            else {
                slider.slider('values', 1, value);
            }
            $("#price-amount").html('$' + getRealValue(slider.slider('values', 0)) + ' - $' + getRealValue(slider.slider('values', 1)));
            return false;
        },
        change: function(event, ui) { 
            getHomeListings();
        }
    });
    function findNearest(includeLeft, includeRight, value) {
        var nearest = null;
        var diff = null;
        for (var i = 0; i < values.length; i++) {
            if ((includeLeft && values[i] <= value) || (includeRight && values[i] >= value)) {
                var newDiff = Math.abs(value - values[i]);
                if (diff == null || newDiff < diff) {
                    nearest = values[i];
                    diff = newDiff;
                }
            }
        }
        return nearest;
    }
    function getRealValue(sliderValue) {
        for (var i = 0; i < values.length; i++) {
            if (values[i] >= sliderValue) {
                return trueValues[i];
            }
        }
        return 0;
    }
});

You can fiddle with the numbers 10 in the values array (which represent the slider 9 stop points) until you get them spaced out 8 how you want. This way you can make it feel, from 7 the user's perspective, like it's sliding 6 proportionally to the values, but without 5 being as exaggerated. Obviously if your 4 true values are dynamically created, you 3 may need to come up with an algorithm to 2 generate the slider values instead of statically 1 defining them...

Score: 14

HTML:

<body>
   <p>
      Slider Value: <span id="val"></span><br/>
      Nonlinear Value: <span id="nlVal"></span><br/>
   </p>
   <div id="slider"></div>
</body>

JS:

    $(function() {
     var valMap = [0, 25,30,50,55,55,60,100];
     $("#slider").slider({
        // min: 0,
         max: valMap.length - 1,
         slide: function(event, ui) {
           $("#val").text(ui.value);
           $("#nlVal").text(valMap[ui.value]);
         }
     });
    });

0

Score: 7

One option for you is use a step size of 6 one and reference an array containing your 5 selected values. Start at 0, go up to 20, get 4 array[value_of_slider] to get your actual 3 value. I don't know sliders well enough 2 to tell you whether or not there is a way 1 to give it a custom set of values.

Score: 6

Based on the above answer and discussion 2 from @Seburdis, and using the names from 1 your example:

var prices_array = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 250, 500, 1000, 1500, 2000, 2500, 5000, 10000];

function imSliding(event,ui)
{
    //update the amount by fetching the value in the value_array at index ui.value
    $('#amount').val('$' + prices_arr[ui.value] + ' - $' + prices_arr[prices_arr.length - 1]); 
}

$('#slider-interval').slider({ min:0, max:values_arr.length - 1, slide: imSliding});
Score: 6

I think I can offer a better solution: The 6 idea is to keep an array with my real values 5 apart from the slider, then to set the step attribute 4 always to 1 and let the slider work with 3 the index of that array and then fetch the real 2 value from my real data array. Hope this 1 example Helps: http://jsfiddle.net/3B3tt/3/

Score: 4

Somebody posted this on the jQuery website. See:

http://forum.jquery.com/topic/non-linear-logarithmic-or-exponential-scale-for-slider

and

http://jsbin.com/ezema

It 2 is exactly what yo have, but way simpler 1 (like 1 line of code).

Score: 3

here's how i did mine. demo here - http://janpatricklara.com/web/extra/jQueryUISliderUnevenSteps.html

have 8 an array of your desired values

var amts=[50,100,150,200,225,250,300];

have the 7 slider increment from 0 to the length of 6 the array, with steps of 1. output the value 5 from the index of the array instead of using 4 the slider's actual value.

this way the increments 3 and steps are evenly distributed. after 2 that you can just grab the value of the 1 label or save it to a var.

$('#amtslider').slider({
    min:0,
    max:amts.length-1,
    step:1,
    value:0,
    change:function(event, ui){
        //alert(amts[$(this).slider("value")]);
        //alert($(this).slider("value"));
        $('#lbl_amt').val(amts[$(this).slider("value")]);
    },
    slide:function(event, ui){
        $('#lbl_amt').val(amts[$(this).slider("value")]);
    }
});
Score: 2

Here is my simple solution for a custom 11 (non consistent "step" size) dual-slider 10 (you can modify it to a single-slider if 9 the idea becomes clear) my slider is named 8 "slider-euro", the text-area is named amount-euro 7 as you can see in the code. The idea is 6 to have a slider from 0 to 100 and an array 5 ("realvalues") with 101 places. The slider-value 4 is understood as the place in that array. The 3 only thing is that you have to reference 2 the array when you get the slider values. Here 1 is my Example:

    $(function() {
    var realvalues = [0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 65000, 70000, 75000, 80000, 85000, 90000, 95000, 100000, 105000, 110000, 115000, 120000, 125000, 130000, 135000, 140000, 145000, 150000, 155000, 160000, 165000, 170000, 175000, 180000, 185000, 190000, 195000, 200000, 205000, 210000, 215000, 220000, 225000, 230000, 235000, 240000, 245000, 250000, 255000, 260000, 265000, 270000, 275000, 280000, 285000, 290000, 295000, 300000, 310000, 320000, 330000, 340000, 350000, 360000, 370000, 380000, 390000, 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000, 800000, 850000, 900000, 1000000, 1500000, 2000000];

    $( "#slider-euro" ).slider({
    range: true,
    min: 0,
    max: 100,
    step: 1,
    values: [ 25, 50 ],
    slide: function( event, ui ) {
    $( "#amount-euro" ).val( realvalues[ui.values[ 0 ]] + " € - " + realvalues[ui.values[ 1 ]] + " €");
    }
    });
    $( "#amount-euro" ).val( realvalues[$( "#slider-euro" ).slider( "values", 0 )] + " € - " + realvalues[$( "#slider-euro" ).slider( "values", 1 )]+" €" );
    });
Score: 1

if min and max value are the same, slider 1 value don't change

change this part

        if (ui.value == ui.values[0]) {
            slider.slider('values', 0, value);
        }
        else {
            slider.slider('values', 1, value);
        }

into

        if ( ui.values[0] == ui.values[1] ) {
            slider.slider('values', 0, value);
            slider.slider('values', 1, value);
        }else{
            if (ui.value == ui.values[0]) {
                slider.slider('values', 0, value);
            }else {
                slider.slider('values', 1, value);
            }
        }
Score: 1

I had to do something similar and even though 4 this is a late response, someone else may 3 happen on to this thread just as I did, and 2 find my solution useful. Here is the solution 1 I created:

http://jsfiddle.net/YDWdu/

So apparently, postings containing links to jsfiddle "must be accompanied by code".
OK - here ya go, stackoverflow... Some lovely "code" for you.
Score: 0

Just change the values.

$( "#price-range" ).slider({
        range: true,
        min: 1000,
        max: 300000000,
        /*step:1,*/
        values: [ 1000, 300000000 ],
        slide: function( event, ui ) {
            if(ui.values[0]<=100000 && ui.values[1]<=100000){
                $("#price-range").slider({step:10000});
            }else if(ui.values[0]<=300000 && ui.values[1]<=300000){
                $("#price-range").slider({step:25000});
            }else if(ui.values[0]<=1000000 && ui.values[1]<=1000000){
                $("#price-range").slider({step:50000});
            }else if(ui.values[0]<=2000000 && ui.values[1]<=2000000){
                $("#price-range").slider({step:100000});
            }else if(ui.values[0]<=5000000 && ui.values[1]<=5000000){
                $("#price-range").slider({step:250000});
            }else if(ui.values[0]<=10000000 && ui.values[1]<=10000000){
                $("#price-range").slider({step:500000});
            }else if(ui.values[0]<=20000000 && ui.values[1]<=20000000){
                $("#price-range").slider({step:1000000});
            }else if(ui.values[0]<=50000000 && ui.values[1]<=50000000){
                $("#price-range").slider({step:5000000});
            }else if(ui.values[0]<=50000000 && ui.values[1]<=50000000){
                $("#price-range").slider({step:10000000});
            }else if(ui.values[0]<=200000000 && ui.values[1]<=200000000){
                $("#price-range").slider({step:25000000});
            }else{
                $("#price-range").slider({step:100000000});
            }

            $("#mins").val( ui.values[0] );
            $("#maxs").val( ui.values[1] );

        }
    });

0

Score: 0

Further to @Broshi's jsfiddle above, here 2 is the code for a custom slider with range 1 disabled:

jQuery:

var myData = [1,2,3,4,5,6,7,8,9,10,20,30,40,50,60,70,80,90,100,200,300,400,500,600,700,800,900,1000,2000,3000,4000,5000,10000,20000,30000,50000,100000,200000,500000,1000000,20000000,30000000];
slider_config = {
        range: false,
        min: 0,
        max: myData.length - 1,
        step: 1,
        slide: function( event, ui ) {
            // Set the real value into the inputs
            console.log(ui);
            $('#value').val( myData[ ui.value ] );
        },
        create: function() {
            $(this).slider('value',0);
        }
    };

$("#slider").slider(slider_config);

HTML:

<input id="value" />
<div id="slider"></div>

More Related questions