4

I have 4 input fields and I need the total of all fields not to exceed 100. I want to set the max of the field being changed.

I have been trying to adjust values on keyup() and then difference the total of the other fields from the current and set the max. Seems to work for a bit then stop.

JSfiddle example

var $fieldA = $('#acf-field_55dc6669f5235');
var $fieldB = $('#acf-field_55dc6699f5236');
var $fieldC = $('#acf-field_55dc66d3f5237');
var $fieldD = $('#acf-field_55dc6713f5238');
var total;

function getTotal() {
   total = parseInt($fieldA.val()) + parseInt($fieldB.val()) +      parseInt($fieldC.val()) + parseInt($fieldD.val());
}
$fieldA.change(function () {
   $this = $(this);
   var input = parseInt($this.val());

   var otherFields = parseInt($fieldB.val()) + parseInt($fieldC.val()) + parseInt($fieldD.val());
   var max = 100 - otherFields;

   $this.attr("max", max);
});
$fieldB.change(function () {
   $this = $(this);
   var input = parseInt($this.val());

   var otherFields = parseInt($fieldA.val()) + parseInt($fieldC.val()) + parseInt($fieldD.val());
   var max = 100 - otherFields;

   $this.attr("max", max);
});
$fieldC.keyup(function () {
    $this = $(this);
    var input = parseInt($this.val());

    var otherFields = parseInt($fieldA.val()) + parseInt($fieldB.val()) + parseInt($fieldD.val());
    var max = 100 - otherFields;

    $this.attr("max", max);

});
$fieldD.change(function () {
   $this = $(this);
   var input = parseInt($this.val());

   var otherFields = parseInt($fieldA.val()) + parseInt($fieldB.val()) + parseInt($fieldC.val());
   var max = 100 - otherFields;

   $this.attr("max", max);
});
getTotal;
2
  • 3
    Seems to work for a bit then stop Can you explain more about this? Commented Sep 23, 2015 at 3:47
  • as @Lalji Tadhani mentioned in his answer , why fieldC has keyup when others have change. And reproduce the issue, so that we can fix it . Commented Sep 23, 2015 at 4:26

5 Answers 5

2

This is how I would do it, see comments in code for details:

$('.acf-is-appended').focus(function(){
   $(this).val('');  // clear the current input when it is focused
   var total = 0; // create a var to track the current total
   $('.acf-is-appended').each(function(){  // loop through each element
       total = total + Number($(this).val()); // add the current value to the running total
      $(this).attr('max', Number($(this).val())); // set each element's max to the currently held value
   });
   var remaining = 100 - total; // figure out how much is left before you hit 100
   $(this).attr('max', remaining); // set the max on the current element to match the remaining limit
});

// that will handle the stepper, note that the max wont prevent the user typing in a value higher than the limit
// if you want, you can also make it so typing in a greater value will default to the max value
$('.acf-is-appended').keyup(function(){
    if(Number($(this).val()) > Number($(this).attr('max'))){
        $(this).val($(this).attr('max'))
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="acf-field_55dc6669f5235" class="acf-is-appended" min="" max="100" step="any" name="acf[field_55dc6669f5235]" value="30" placeholder="" type="number">
</div>
<div class="acf-input-wrap">
  <input id="acf-field_55dc6699f5236" class="acf-is-appended" min="" max="100" step="any" name="acf[field_55dc6699f5236]" value="5" placeholder="" type="number">
</div>
<div class="acf-input-wrap">
  <input id="acf-field_55dc66d3f5237" class="acf-is-appended" min="" max="100" step="any" name="acf[field_55dc66d3f5237]" value="15" placeholder="" type="number">
</div>
<div class="acf-input-wrap">
  <input id="acf-field_55dc6713f5238" class="acf-is-appended" min="" max="100" step="any" name="acf[field_55dc6713f5238]" value="50" placeholder="" type="number">
</div>

Sign up to request clarification or add additional context in comments.

Comments

1

Try jQuery input and propertychange handler:

var acfs;

$(function() {
  acfs = $('input[type=text][id^=acf-field_55dc6669f523]'); //cache all once
  acfs.on('input propertychange', checkSum);
});

var max = 100;

var checkSum = function(e) {
  this.value = this.value.replace(/\D/g, ''); //only digits
  var sum = 0;
  var fn = function() {
    sum += +this.value || 0; // parse individual text-box value to int
  };
  acfs.each(fn);
  if (max < sum) // above limit
    this.value = ''; //erase input
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id='acf-field_55dc6669f5235' type='text' />
<input id='acf-field_55dc6669f5236' type='text' />
<input id='acf-field_55dc6669f5237' type='text' />
<input id='acf-field_55dc6669f5238' type='text' />

Comments

1

How about just this

$("input[type='number'].acf-is-appended").change(function () {
    $.each($("input[type='number'].acf-is-appended"), function (index, element) {
        var total = 0;
        $.each($("input[type='number'].acf-is-appended").not($(element)), function (innerIndex, innerElement) {
            total += parseInt($(innerElement).val());
        });
        if ($(element).val() > 100 - total) {
            alert("The total value for all inputs can not exceed 100");
            return false;
        } else {
            $(element).attr("max", 100 - total);
        }
    });
});

Fiddle Demo

Comments

0

Try utilizing input event , .get() , Array.prototype.map() , Array.prototype.reduce() , Math.max , Array.prototype.sort()


If total values of all input elements is greater than MAX : 100 , decrement value of input that has greatest value in collection of elements ; if event.target with input , change event is element with greatest value , decrement value of element with next greatest value

    var inputs = $("input[id^=acf]"),
        MAX = 100;
    inputs.on("input", function (e) {
        var input = inputs.get(),
            vals = input.map(function (el) {
                return Number(el.value)
            }),
            total = vals.reduce(function (a, b) {
                return a + b
            })
        , el = inputs.sort(function (a, b) {
            return a.value > b.value
        });

        if (total > MAX) {
            $(el).eq($(el[el.length - 1]).is(e.target) 
              ? el.length - 2 
              : el.length - 1)
             .val(function (i, val) {
                return Number(val) - (total % MAX)
            });
        }
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="acf-input-wrap">
  <input id="acf-field_55dc6669f5235" class="acf-is-appended" min="" max="100" step="any" name="acf[field_55dc6669f5235]" value="30" placeholder="" type="number">
</div>
<div class="acf-input-wrap">
  <input id="acf-field_55dc6699f5236" class="acf-is-appended" min="" max="100" step="any" name="acf[field_55dc6699f5236]" value="5" placeholder="" type="number">
</div>
<div class="acf-input-wrap">
  <input id="acf-field_55dc66d3f5237" class="acf-is-appended" min="" max="100" step="any" name="acf[field_55dc66d3f5237]" value="15" placeholder="" type="number">
</div>
<div class="acf-input-wrap">
  <input id="acf-field_55dc6713f5238" class="acf-is-appended" min="" max="100" step="any" name="acf[field_55dc6713f5238]" value="50" placeholder="" type="number">
</div>

jsfiddle https://jsfiddle.net/q478ujfr/9/

Comments

-1

Change $fieldC.keyup to $fieldC.change

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.