Reputation: 43
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.
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;
Upvotes: 4
Views: 2768
Reputation: 1
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/
Upvotes: 0
Reputation: 9947
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);
}
});
});
Upvotes: 1
Reputation: 19571
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>
Upvotes: 2
Reputation:
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' />
Upvotes: 1