dprothero
dprothero

Reputation: 2722

HTML5 input type range - non-linear sequence?

I want to use a slider control to input a selection. The possible values are: 5000, 25000, 50000, 75000, and 100000. However, I cannot get the range input to limit to those choices. The closest thing I've got is this:

<datalist id="valid-options">
  <option>5000</option>
  <option>25000</option>
  <option>50000</option>
  <option>75000</option>
  <option>100000</option>
</datalist>
<input type="range" min="5000" max="100000" step="5000" list="valid-options" ng-model="selectedValue" />

You can see the full sample here: http://jsfiddle.net/au14Lv2t/1/

The problem with this solution is that it allows for invalid values like 10000, 15000, etc.

I'm looking for an AngularJS (or pure HTML5/JS/CSS) solution. I would prefer not to introduce jQuery.

Thanks!

Upvotes: 5

Views: 2785

Answers (3)

Chris Browne
Chris Browne

Reputation: 1612

Instead of trying to use the values directly, you can use a map that the range slider operates on - so your ng-model is something like myrangeIndex and when you bind your output element you use rangeValues[myrangeIndex] to get the value back out. Equally when you use the value elsewhere you will need to look it up first. If you know the list of elements might grow/shrink later on, you can use max="{{rangeValues.length}}" so that you only need to update the code in one place. If the values can be calculated from ordinal values, you can simply populate rangeValues when the controller is loaded, e.g. $scope.rangeValues = f(1,100); for any given f.

Upvotes: 1

Alper Cinar
Alper Cinar

Reputation: 861

you can search for the closest valid value and set the input value to that value for each value change event

var inputElement = document.getElementById('customRangeInput');

inputElement.oninput = setInput;
inputElement.onchange = setInput;   // IE fix

function setInput(){
    inputElement.value = closestValue(inputElement.value);
}

var validValues = [5000,25000,50000,75000,100000];
function closestValue(input)
{
    var differences = [];
    for (var i = 0; i < validValues.length; i++)    
        differences.push( Math.abs(validValues[i] - input));

    var index = indexOfSmallest(differences);
    return validValues[index];      
}

function indexOfSmallest(inputArray) {
    var lowest = 0;
    for (var i = 1; i < inputArray.length; i++) {
        if (inputArray[i] < inputArray[lowest]) lowest = i;
    }
    return lowest;
}

html should look like this

<input id="customRangeInput" type="range" min="5000" max="100000" step="5000" list="valid-options" ng-model="selectedValue" />Selected Value: {{ selectedValue }}</div>

Upvotes: 2

xploshioOn
xploshioOn

Reputation: 4115

you need to use property step, that let's you decide how much is every step, for your example, most values are in 25000 so make step="25000"

<input type="range" min="0" max="100000" step="25000">

and to solve the 5000 value... in your example your first value is 5000 what you do is that if you receive 0 that is your low value that is 5000... the other values increase in 25000... hope that helps.

and you don't need the datalist in this case.

Upvotes: 1

Related Questions