Increment number input with rules to steps

Viewed 675

I'm trying to create number input with counting rules, for example, I want to have first 5 increment steps to be 100 units (100 - 500) and once reaching 500 change increment steps to 500.

So it will be 100, 200, 300, 400, 500, 1000, 1500, 2000...

Here is what I have tried so far, something causes the 500 step attribute trigger only when reaching 600 instead 500.

$('input#grams_quantity').on( "change", function(){
    console.log('works');
    if($(this).val() > 400){
        $("#grams_quantity").attr('step', 500);
        console.log('500');
    } else {
        $("#grams_quantity").attr('step', 100);
        console.log('100');
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<input type="number" step="100" name="grams_quantity" class="grams_quantity" id="grams_quantity" value="100" min="100">

How can I set rules to number input increment steps correctly?

1 Answers

It is a bit tricky to get the wanted values, because the change happens before the event is called and then it needs to take action for the next click.

  1. Why does not simply changing the increment to 500 work?

    Because of the min value and a multiple of 500. By having min="100" and step="500", the next reachable value is 600.

    Solution: Change both values, min="0" and step="500".

  2. Why do wee need another condition? Why not simply check the value 500 for turning back to step="100"?

    • Solution for values greater than 500:

      • Adjust start to zero and step to 500.
      • Adjust value to at least 1000.
    • Solution for values smaller or equal than 500.

      • Adjust start to 100 and step to 500.
    • You need to cover user inputs as well and adust the values


EDIT: Added last in a closure for distinguish between arrow changing values and hand input values.

For example take an direct input of 600, this value is rounded to 500, but if the value is reached by up arrow pressing, you get 1000.

$('input#grams_quantity').on("change", function (last) {
    return function() {
        if (+$(this).val() > 500) {
            $("#grams_quantity").attr('step', 500);
            $("#grams_quantity").attr('min', 0);
            this.value = last === 500 && +this.value === 600
                ? 1000
                : Math.round(this.value / 500) * 500;
        } else {
            $("#grams_quantity").attr('step', 100);
            $("#grams_quantity").attr('min', 100);
            this.value = Math.max(100, Math.round(this.value / 100) * 100);
        }
        last = +this.value;
    };
}(0));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" step="100" name="grams_quantity" class="grams_quantity" id="grams_quantity" value="100" min="100">

Related