I would like to balance a user input of three input fields so that they will always sum up 100.
The initial state is: 100, 0, 0
, when the user enters let's say 50 in the second input, it should become: 50, 50, 0
. I am doing this in Vue but technically it is irrelevant for the question. I have tried:
adjustPercentage(changedValue) {
if (changedValue === 'input1') {
this.input2 = 100 - this.input1 - this.input3;
this.input3 = 100 - this.input1 - this.input2;
} else if (changedValue === 'input2') {
this.input1 = 100 - this.input2 - this.input3;
this.input3 = 100 - this.input1 - this.input2;
} else if (changedValue === 'input3') {
this.input1 = 100 - this.input2 - this.input3;
this.input2 = 100 - this.input1 - this.input3;
}
// Ensure the values are clamped to avoid negative percentages
if (this.input1 < 0) this.input1 = 0;
if (this.input2 < 0) this.input2 = 0;
if (this.input3 < 0) this.input3 = 0;
},
But I cannot get it to work properly, if I enter let's say a value in input 3 it is exceeding the total sum of 100.
Adjusting < 0
to 0
after you're calculating the other fields will cause the calulation to fail.
You'll need to set < 0
to 0
before the next input calculation.
Here an example with a helper function that we call after each line of your existing logics, this could ofc be improved.
const input1 = document.querySelector('input[name=input1]');
const input2 = document.querySelector('input[name=input2]');
const input3 = document.querySelector('input[name=input3]');
const noBelowZero = (input) => (input.value < 0) ? input.value = 0 : {};
const adjust = (event) => {
let name = event.target.name;
if (name === 'input1') {
input2.value = 100 - input1.value - input3.value; noBelowZero(input2);
input3.value = 100 - input1.value - input2.value; noBelowZero(input3)
} else if (name === 'input2') {
input1.value = 100 - input2.value - input3.value; noBelowZero(input1)
input3.value = 100 - input1.value - input2.value; noBelowZero(input3)
} else if (name === 'input3') {
input1.value = 100 - input2.value - input3.value; noBelowZero(input1)
input2.value = 100 - input1.value - input3.value; noBelowZero(input2)
}
}
[ input1, input2, input3 ].forEach(i => i.addEventListener('change', adjust));
<input name='input1' value=100 />
<input name='input2' value=0 />
<input name='input3' value=0 />