Home > front end >  Strange button behaviour, values not passing correctly and arithmetic incorrect
Strange button behaviour, values not passing correctly and arithmetic incorrect

Time:12-21

On this page:

https://maxview.co.uk/data-usage-calculator-button-input/

Password: Liva

I have managed to get some strange button behaviour, mainly:

  • It takes 3 button clicks to display any output in GB
  • The output is not correct according to the values assigned for the buttons and also isn't consistent

I've tried several re-jigs of the code, moving variables into global scope.

I think it's something to do with the almost duplicate document.querySelectors I have but not entirely sure to be honest as I have tried removing them, moving them around and didn't work.

Here is the HTML and Javscript (I've left the styling as don't think it's relevant):

Huge thanks if anyone can spot the error.

<h1>Data Usage Calculator</h1>
<p id="total_data_usage"></p>
<p id="total_monthly_data_usage"></p>

<form>

  <h2>Select number of hours per day for streaming in SD:</h2>

  <button type="button"  id="sdnever" name="sd_streaming_hours" value="0">Never</button>
  <button type="button"  id="sdone_hour" name="sd_streaming_hours" value="1">1 hour</button>
  <button type="button"  id="sdtwo_hours" name="sd_streaming_hours" value="2">2 hours</button>
  <button type="button"  id="sdthree_hours" name="sd_streaming_hours" value="3">3 hours</button>
  <button type="button"  id="sdfive_hours" name="sd_streaming_hours" value="5">5 hours</button>
  <button type="button"  id="sdeight_hours" name="sd_streaming_hours" value="8">8 hours</button>

  <h2>Select number of hours per day for streaming in HD:</h2>

  <button type="button"  id="hdnever" name="hd_streaming_hours" value="0">Never</button>
  <button type="button"  id="hdone_hour" name="hd_streaming_hours" value="1">1 hour</button>
  <button type="button"  id="hdtwo_hours" name="hd_streaming_hours" value="2">2 hours</button>
  <button type="button"  id="hdthree_hours" name="hd_streaming_hours" value="3">3 hours</button>
  <button type="button"  id="hdfive_hours" name="hd_streaming_hours" value="5">5 hours</button>
  <button type="button"  id="hdeight_hours" name="hd_streaming_hours" value="8">8 hours</button>

</form>

<script>

  // SD streaming button listeners

  document.getElementById("sdnever").addEventListener("click", updateResult);
  document.getElementById("sdone_hour").addEventListener("click", updateResult);
  document.getElementById("sdtwo_hours").addEventListener("click", updateResult);
  document.getElementById("sdthree_hours").addEventListener("click", updateResult);
  document.getElementById("sdfive_hours").addEventListener("click", updateResult);
  document.getElementById("sdeight_hours").addEventListener("click", updateResult);

  const sdStreamButtons = document.querySelectorAll('button[name="sd_streaming_hours"]');

  sdStreamButtons.forEach(button => {
    button.addEventListener('click', function () {
      // Deselect all sdStreamButtons
      sdStreamButtons.forEach(btn => btn.classList.remove('selected'));
      // Select this button
      this.classList.add('selected');
    });
  });

  document.getElementById("hdnever").addEventListener("click", updateResult);
  document.getElementById("hdone_hour").addEventListener("click", updateResult);
  document.getElementById("hdtwo_hours").addEventListener("click", updateResult);
  document.getElementById("hdthree_hours").addEventListener("click", updateResult);
  document.getElementById("hdfive_hours").addEventListener("click", updateResult);
  document.getElementById("hdeight_hours").addEventListener("click", updateResult);

  const hdStreamButtons = document.querySelectorAll('button[name="hd_streaming_hours"]');

  hdStreamButtons.forEach(button => {
    button.addEventListener('click', function () {
      // Deselect all sdStreamButtons
      hdStreamButtons.forEach(btn => btn.classList.remove('selected'));
      // Select this button
      this.classList.add('selected');
    });
  });

  var totalDataUsage;
  //var totalMonthlyDataUsage;
  //var sdStreamButtonValue;
  //var hdStreamButtonValue;

  function updateResult() {
  // Get selected sd streaming hours button
  const sdSelectedButton = document.querySelector('button[name="sd_streaming_hours"].selected');
  // Calculate sd data usage based on selected button value
  const sdDataUsage = parseInt(sdSelectedButton.value) * 0.1;

  // Get selected hd streaming hours button
  const hdSelectedButton = document.querySelector('button[name="hd_streaming_hours"].selected');
  // Calculate hd data usage based on selected button value
  const hdDataUsage = parseInt(hdSelectedButton.value) * 0.3;

  // Calculate total data usage
  const totalDataUsage = sdDataUsage   hdDataUsage;
  // Update total data usage element text
  document.getElementById("total_data_usage").textContent = totalDataUsage   "GB";

}

</script>

CodePudding user response:

The issue is you are calling the updateResult() for each button. There is no need to call it because you are assigned events for 'hdStreamButtons' and 'sdStreamButtons'. You need to call the function after you assigned the class 'selected' for the buttons.

Please check this.

.btn.selected {
    background-color: black;
    color: white;
}
<h1>Data Usage Calculator</h1>
<p id="total_data_usage"></p>
<p id="total_monthly_data_usage"></p>

<form>

  <h2>Select number of hours per day for streaming in SD:</h2>

  <button type="button"  id="sdnever" name="sd_streaming_hours" value="0">Never</button>
  <button type="button"  id="sdone_hour" name="sd_streaming_hours" value="1">1 hour</button>
  <button type="button"  id="sdtwo_hours" name="sd_streaming_hours" value="2">2 hours</button>
  <button type="button"  id="sdthree_hours" name="sd_streaming_hours" value="3">3 hours</button>
  <button type="button"  id="sdfive_hours" name="sd_streaming_hours" value="5">5 hours</button>
  <button type="button"  id="sdeight_hours" name="sd_streaming_hours" value="8">8 hours</button>

  <h2>Select number of hours per day for streaming in HD:</h2>

  <button type="button"  id="hdnever" name="hd_streaming_hours" value="0">Never</button>
  <button type="button"  id="hdone_hour" name="hd_streaming_hours" value="1">1 hour</button>
  <button type="button"  id="hdtwo_hours" name="hd_streaming_hours" value="2">2 hours</button>
  <button type="button"  id="hdthree_hours" name="hd_streaming_hours" value="3">3 hours</button>
  <button type="button"  id="hdfive_hours" name="hd_streaming_hours" value="5">5 hours</button>
  <button type="button"  id="hdeight_hours" name="hd_streaming_hours" value="8">8 hours</button>

</form>

<script>
  const sdStreamButtons = document.querySelectorAll('button[name="sd_streaming_hours"]');
  sdStreamButtons.forEach(button => {
    button.addEventListener('click', function () {
      // Deselect all sdStreamButtons
      sdStreamButtons.forEach(btn => btn.classList.remove('selected'));
      // Select this button
      this.classList.add('selected');
      updateResult();
    });
  });

  const hdStreamButtons = document.querySelectorAll('button[name="hd_streaming_hours"]');
  hdStreamButtons.forEach(button => {
    button.addEventListener('click', function () {
      // Deselect all sdStreamButtons
      hdStreamButtons.forEach(btn => btn.classList.remove('selected'));
      // Select this button
      this.classList.add('selected');
      updateResult();
    });
  });

  var totalDataUsage;
  function updateResult() {
  // Get selected sd streaming hours button
  const sdSelectedButton = document.querySelector('button[name="sd_streaming_hours"].selected');
  // Calculate sd data usage based on selected button value
  const sdDataUsage = parseInt(sdSelectedButton.value) * 0.1;

  // Get selected hd streaming hours button
  const hdSelectedButton = document.querySelector('button[name="hd_streaming_hours"].selected');
  // Calculate hd data usage based on selected button value
  const hdDataUsage = parseInt(hdSelectedButton.value) * 0.3;

  // Calculate total data usage
  const totalDataUsage = sdDataUsage   hdDataUsage;
  // Update total data usage element text
  document.getElementById("total_data_usage").textContent = totalDataUsage   "GB";

}

document.getElementById("sdnever").classList.add('selected');
document.getElementById("hdnever").classList.add('selected');
</script>

CodePudding user response:

You don't have to create a click handler twice if its going to do the same thing.

Here I'm creating an array of the totals.

Then I'm attaching a click handler to the body and checking to see if a btn was clicked. Then I'm getting the element's name and using that to remove any selected buttons and then using it in a switch to determine the decimal. I then take that value and add it to the array. Then I simply add the values of the array and output, all in one function.

let totals = {
  "sd_streaming_hours": 0,
  "hd_streaming_hours": 0
};

document.body.addEventListener("click", (e) => {
  const el = e.target;
  if (el.classList.contains("btn")) {
    const name = el.name;
    
     const selected = document.querySelector(".selected[name="   name   "]");
    if (selected) {
      selected.classList.remove("selected")
    }
    el.classList.add("selected")
    let val = parseInt(el.value);
   switch (name) {
      case "sd_streaming_hours":
        val = val * 0.1;
        break;
      case "hd_streaming_hours":
        val = val * 0.3;
        break;
    }
    totals[name] = val

    document.getElementById("total_data_usage").textContent = (totals["sd_streaming_hours"]   totals["hd_streaming_hours"])   "GB";
  }
});
.selected{color:red}
<h1>Data Usage Calculator</h1>
<p id="total_data_usage"></p>
<p id="total_monthly_data_usage"></p>

<form>

  <h2>Select number of hours per day for streaming in SD:</h2>

  <button type="button"  id="sdnever" name="sd_streaming_hours" value="0">Never</button>
  <button type="button"  id="sdone_hour" name="sd_streaming_hours" value="1">1 hour</button>
  <button type="button"  id="sdtwo_hours" name="sd_streaming_hours" value="2">2 hours</button>
  <button type="button"  id="sdthree_hours" name="sd_streaming_hours" value="3">3 hours</button>
  <button type="button"  id="sdfive_hours" name="sd_streaming_hours" value="5">5 hours</button>
  <button type="button"  id="sdeight_hours" name="sd_streaming_hours" value="8">8 hours</button>

  <h2>Select number of hours per day for streaming in HD:</h2>

  <button type="button"  id="hdnever" name="hd_streaming_hours" value="0">Never</button>
  <button type="button"  id="hdone_hour" name="hd_streaming_hours" value="1">1 hour</button>
  <button type="button"  id="hdtwo_hours" name="hd_streaming_hours" value="2">2 hours</button>
  <button type="button"  id="hdthree_hours" name="hd_streaming_hours" value="3">3 hours</button>
  <button type="button"  id="hdfive_hours" name="hd_streaming_hours" value="5">5 hours</button>
  <button type="button"  id="hdeight_hours" name="hd_streaming_hours" value="8">8 hours</button>

</form>

  • Related