skip to Main Content

I’m trying to make a count voter with percentage but the first click doesn’t register and makes the percentages NaN.

This is my code:

var pikaClick = 0;
var nineClick = 0;
var pikaPercent;
var ninePercent;


function getTotal() {
  tClicks.innerHTML = parseInt(vPika.innerHTML) + parseInt(vNine.innerHTML);
  pikaPercent = parseInt(vPika.innerHTML) / parseInt(tClicks.innerHTML) * 100;
  vPika.innerHTML = pikaClick + " (" + pikaPercent.toFixed(2) + "%)";
  ninePercent = parseInt(vNine.innerHTML) / parseInt(tClicks.innerHTML) * 100;
  vNine.innerHTML = nineClick + " (" + ninePercent.toFixed(2) + "%)";
}

pika.onclick = function() {
  pikaClick++;
  getTotal();
}

nine.onclick = function() {
  nineClick++;
  getTotal();
}
<div>
  <p> Pikachu Total Clicks : <span id="vPika"> 0 (0.00%) </span> </p>
  <img id="pika" src="https://img.pokemondb.net/sprites/ultra-sun-ultra-moon/normal/pikachu-f.png" />
</div>
<div>
  <p> NineTails Total Clicks : <span id="vNine"> 0 (0.00%) </span> </p>
  <img id="nine" src="https://img.pokemondb.net/sprites/black-white/shiny/ninetales.png" />
</div>
<p> Overall Total Clicks : <span id="tClicks">  0 </span> </p>

Why does it do this and how do I fix it?

2

Answers


  1. Since you already have variables storing all the counts, just use those instead of parsing the innerHTML of the elements in which you are displaying those counts.

    (Additionally, it is better to set textContent instead of innerHTML since you don’t actually have to add new elements.)

    function getTotal(){
        const total = pikaClick + nineClick;
        tClicks.textContent = total;
        pikaPercent = pikaClick / total * 100;
        vPika.textContent = pikaClick + " (" + pikaPercent.toFixed(2) + "%)";
        ninePercent = nineClick / total * 100;
        vNine.textContent = nineClick + " (" + ninePercent.toFixed(2) + "%)";
    }
    

    You are getting NaN because you set tClicks.innerHTML by using the values of vPika.innerHTML and vNine.innerHTML but before vPika and vNine are updated, so you end up dividing by 0 initially.

    Login or Signup to reply.
  2. NaN means “Not a number”. This can happen in certain circumstances:

    1. When you are parsing something that is not a number
    2. When you perform an invalid/undefined math operation, like dividing zero by zero, for example.

    In your code, the NaN comes from an invalid math operation (0/0).

    Let’s look at it step by step.

    1. You click at Pikachu
    2. pikaClick is increased and is now one
    3. getTotal is called
    4. The percentages are calculated based on the text representing the current number of clicks.
    5. If you look closely, you’ll notice that only the internal variables were increased, but the text is not yet updated at the time the percentages are calculated. Therefore, the values being used for your percentage calculation are still "zero".
    6. It tries to divide zero by zero, and you get NaN
    7. Similarly, the total count is incorrect because it’s fetching the numbers from the text before they are updated.

    One way to fix would be to try reordering some of the statements to ensure they get up to date information.

    However, you can fix the problem and make your program simpler by simply using the internal variables themselves (instead of fetching information from the HTML).

    Besides, you should generally avoid using innerHTML, as it can become a source for XSS vulnerabilities.

    Here is an example code that fixes the problem:

    <div>
        <p> Pikachu Total Clicks : <span id="vPika"> 0 (0.00%) </span> </p>
        <img id="pika" src="https://img.pokemondb.net/sprites/ultra-sun-ultra-moon/normal/pikachu-f.png"/>
    </div>
    <div>
        <p> NineTails Total Clicks : <span id="vNine"> 0 (0.00%) </span> </p>
        <img id="nine" src="https://img.pokemondb.net/sprites/black-white/shiny/ninetales.png"/>             
    </div>
    <p> Overall Total Clicks : <span id="tClicks">  0 </span> </p>
    
    <script>
        var pikaClick = 0;
        var nineClick = 0;
        var pikaPercent;
        var ninePercent;
    
        
        function getTotal(){
            var tClickCount = pikaClick + nineClick
            tClicks.innerHTML = tClickCount;
            pikaPercent = pikaClick / tClickCount * 100;
            vPika.innerHTML = pikaClick + " (" + pikaPercent.toFixed(2) + "%)";
            ninePercent = nineClick / tClickCount * 100;
            vNine.innerHTML = nineClick + " (" + ninePercent.toFixed(2) + "%)";
        }
    
        pika.onclick = function() {
            pikaClick++;
            getTotal();
        }
        
        nine.onclick = function() {
            nineClick++;
            getTotal();
        }
    </script>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search