Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Changing automatically value on range fields

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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 class="pp-fields pp-m-tb-10 pp-inline-flex">
    Pivo<input id="ppBearInputId" type="range" class="pp-ranges" name="ppBearInputName" value="40" min="1" max="100"/><label class="pp-label-beer-range" for="ppBearInputId">40</label>%
</div>
<div class="pp-fields pp-m-tb-10 pp-inline-flex">
    Vino<input id="ppVineInputId" type="range" class="pp-ranges" name="ppVineInputName" value="35" min="1" max="100"/><label class="pp-label-vine-range" for="ppVineInputId">35</label>%
</div>
<div class="pp-fields pp-m-tb-10 pp-inline-flex">
    Žestina<input id="ppStrongInputId" type="range" class="pp-ranges" name="ppStrongInputName" value="25" min="1" max="100"/><label class="pp-label-strong-range" for="ppStrongInputId">25</label>%
</div>

>Solution :

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 class="pp-fields pp-m-tb-10 pp-inline-flex">
    Pivo<input id="ppBearInputId" type="range" class="pp-ranges" name="ppBearInputName" value="40" min="1" max="100"/><label class="pp-label-beer-range" for="ppBearInputId">40</label>%
</div>
<div class="pp-fields pp-m-tb-10 pp-inline-flex">
    Vino<input id="ppVineInputId" type="range" class="pp-ranges" name="ppVineInputName" value="35" min="1" max="100"/><label class="pp-label-vine-range" for="ppVineInputId">35</label>%
</div>
<div class="pp-fields pp-m-tb-10 pp-inline-flex">
    Žestina<input id="ppStrongInputId" type="range" class="pp-ranges" name="ppStrongInputName" value="25" min="1" max="100"/><label class="pp-label-strong-range" for="ppStrongInputId">25</label>%
</div>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading