Home > Software engineering >  Changing automatically value on range fields
Changing automatically value on range fields

Time:03-12

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>

  • Related