0

I'm trying to create a form, where the user pick an answer from 0 to 100%; I've 25 questions. A the end, I add the result of each questions and I divide this by the number of questions, 25 in my case. So far, no problem; it works perfectly, I've the average I need.

But I've a problem, if the user decides to not answer at a question. If he answers at 20 questions, I divide by 20, no problem. But the result of my calculation is 'NaN' because some variable doesn't exist...

This solution works for me :

<input type="text" class="q" value="">
<input type="text" class="q" value="">
<input type="text" class="q" value="">

<input type="submit" class="send" value="send">

JS : 
$(".send").click(function() {
   let answeredCount = 0;
   var sum = 0;
  $('.q').each(function(){
    if(!isNaN(parseInt($(this).val()))){
    answeredCount++;
    }
    sum += Number($(this).val());
});
var result = parseInt(sum/answeredCount);
alert (result);
});

3 Answers3

1

The problem that you are encountering is that some of the values are blank, which means parseInt() will not work. What you want is to simply cast them to 0 if they are falsy.

Some improvements you can make is to actually use number as the input type, and also giving all the fields a common class so that you can sum them up using:

  1. a first-pass .filter() to only include input elements that has value
  2. the .map() + .get() jQuery methods, which returns an array of values (see more explanation here)
  3. the native .reduce() method that sums the array up

After the sum has been obtained, the average is simply obtained by dividing the sum with the number of input elements you have. See proof-of-concept below:

$(function() {
  $('.send').click(function() {
      // Get collection of non-empty inputs
      var $q = $('.q').filter(function() {
        return this.value;
      });
      
      // Get sum of all values
      var sum = $q.map(function() {
        var value = parseInt(this.value);
        return isNaN(value) ? 0 : value;
      }).get().reduce(function(val, cumulativeSum) {
        return val + cumulativeSum;
      }, 0);
      
      // Calculate average
      var average = sum / $q.length;
      console.log(average);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type='number' class="q" value=''>%
<input type='number' class="q" value=''>%
<input type='number' class="q" value=''>%

<input type="button" class='send' value="send">
Terry
  • 63,248
  • 15
  • 96
  • 118
  • Thanks a lot for your answer. But if an answer is blank, it's not exactly the same as if it was "0". That's my biggest issue here. beause in your snippet, if I try : blank - 100 - 100, the answer is 66,66%. I'd like to have 50% – Clémentine May 02 '18 at 16:08
  • @Clémentine Ah, if that's what you want, I have updated my answer to add an additional first-pass filter to only include input elements with non-empty values :) – Terry May 02 '18 at 19:38
0

This is how I would go about doing this, first I would give all the question inputs the same class like so:

<input type='text' class="question" value=''>
<input type='text' class="question" value=''>
<input type='text' class="question" value=''>
Etc...
<input type="submit" class='send' value="send">

Then when the user submits, change your function to be more dynamic, use .length of the collection returned by doing a query selector on class = question, this will get you the total number of questions, in case you ever add or delete questions. Then iterate each one of the collection and check for NaN value, if it is NaN, don't add it to the count of user answered questions, like so:

 $('.send').click(function(){
    const totalQuestions = $('.question').length;
    let answeredCount = 0;

    $('.question').each(function(){
        if(!isNaN(parseInt($(this).val()))){
              answeredCount++;
        }
    }

    //Divide answeredCount by the total questions * 1.0 
    //to get a floating point number, then multiply by 100 to get the percentage
    const result = (answeredCount / (totalQuestions * 1.0)) * 100; 
)};
Ryan Wilson
  • 10,223
  • 2
  • 21
  • 40
0

I worked on some jquery functions for above scenario. this may solve your problem. try this.

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
    $(document).ready(function(){
        var valueArray = $('.question').map(function() {
            return this.value;
        }).get();
        var temp = valueArray;
        function getSum(total, num) {
            if(num == ''){
                num = 0;
            }
            return parseInt(total) + parseInt(num);
        }
        var result = (temp.reduce(getSum))/ valueArray.length;
    });
</script>
</head>
<body>
    <input type='text' class="question" value='1'>
    <input type='text' class="question" value='2'>
    <input type='text' class="question" value='3'>
    <input type='text' class="question" value=''>
</body>
</html>
swathi_sri
  • 417
  • 4
  • 8
  • First, Thanks a lot for your help ! I think it's the same issue than Terry's answer : If an answer is blank, it's not exactly the same as if it was "0". That's my biggest issue here. – Clémentine May 02 '18 at 16:12