I have three range fields with a total percentage of 100. The idea is for those three fields to communicate with each other and has a total value of 100%. That's working fine.
While you drag the range field, the label value is increasing/decreasing for that specific field but not for the other two.
The result should be that while you increase/decrease one range field, the other two increase/decrease their label value as well.
Here is a jsfiddle, and once you see it, you will see the issue.
const els1 = Array.from(document.querySelectorAll('.pp-ranges'));
const total1 = 100;
const values1 = new Array(els1.length).fill(40);
els1.forEach((el, i) => el.value = values1[i].toFixed(3.3));
const handleChange1 = e => {
const changedIndex = els1.indexOf(e.target);
const newValue = e.target.value;
values1[changedIndex] = newValue;
const otherIndexes1 = new Array(els1.length)
.fill(0)
.map((_, i) => i)
.filter((_, i) => i !== changedIndex);
const otherSum1 = otherIndexes1.map(i => values1[i])
.reduce((a, c) => a c);
if (otherSum1 === 0) {
otherIndexes1.forEach(i => values1[i] = (total1 - newValue) / (values1.length - 1));
} else {
const f = (total1 - newValue) / otherSum1;
otherIndexes1.forEach(i => values1[i] *= f);
}
els1.forEach((el, i) => el.value = values1[i].toFixed(2));
}
els1.forEach(el => el.addEventListener('input', handleChange1));
document.querySelector("#ppBearInputId").addEventListener("input", function (e) {
document.querySelector(".pp-label-beer-range").textContent = e.currentTarget.value;
})
document.querySelector("#ppVineInputId").addEventListener("input", function (e) {
document.querySelector(".pp-label-vine-range").textContent = e.currentTarget.value;
})
document.querySelector("#ppStrongInputId").addEventListener("input", function (e) {
document.querySelector(".pp-label-strong-range").textContent = e.currentTarget.value;
})
<div >
Pivo<input id="ppBearInputId" type="range" name="ppBearInputName" value="40" min="1" max="100"/><label for="ppBearInputId">40</label>%
</div>
<div >
Vino<input id="ppVineInputId" type="range" name="ppVineInputName" value="35" min="1" max="100"/><label for="ppVineInputId">35</label>%
</div>
<div >
Žestina<input id="ppStrongInputId" type="range" name="ppStrongInputName" value="25" min="1" max="100"/><label for="ppStrongInputId">25</label>%
</div>
CodePudding user response:
The most direct solution is to select the label closest to each input range and set its value to the same thing as the input range:
els1.forEach((el, i) => {
el.value = values1[i].toFixed(2);
el.parentNode.querySelector("label").textContent = el.value;
});
Now there are some rounding errors to consider, but it's not quite clear how that should be resolved to match your specifications, so I'll leave that open as a separate issue.
const els1 = Array.from(document.querySelectorAll('.pp-ranges'));
const total1 = 100;
const values1 = new Array(els1.length).fill(40);
els1.forEach((el, i) => el.value = values1[i].toFixed(3.3));
const handleChange1 = e => {
const changedIndex = els1.indexOf(e.target);
const newValue = e.target.value;
values1[changedIndex] = newValue;
const otherIndexes1 = Array(els1.length)
.fill(0)
.map((_, i) => i)
.filter((_, i) => i !== changedIndex);
const otherSum1 = otherIndexes1.map(i => values1[i])
.reduce((a, c) => a c);
if (otherSum1 === 0) {
otherIndexes1.forEach(i => values1[i] = (total1 - newValue) / (values1.length - 1));
} else {
const f = (total1 - newValue) / otherSum1;
otherIndexes1.forEach(i => values1[i] *= f);
}
els1.forEach((el, i) => {
el.value = values1[i].toFixed(2);
el.parentNode.querySelector("label").textContent = el.value;
});
}
els1.forEach(el => el.addEventListener('input', handleChange1));
document.querySelector("#ppBearInputId").addEventListener("input", function (e) {
document.querySelector(".pp-label-beer-range").textContent = e.currentTarget.value;
})
document.querySelector("#ppVineInputId").addEventListener("input", function (e) {
document.querySelector(".pp-label-vine-range").textContent = e.currentTarget.value;
})
document.querySelector("#ppStrongInputId").addEventListener("input", function (e) {
document.querySelector(".pp-label-strong-range").textContent = e.currentTarget.value;
})
<div >
Pivo<input id="ppBearInputId" type="range" name="ppBearInputName" value="40" min="1" max="100"/><label for="ppBearInputId">40</label>%
</div>
<div >
Vino<input id="ppVineInputId" type="range" name="ppVineInputName" value="35" min="1" max="100"/><label for="ppVineInputId">35</label>%
</div>
<div >
Žestina<input id="ppStrongInputId" type="range" name="ppStrongInputName" value="25" min="1" max="100"/><label for="ppStrongInputId">25</label>%
</div>