Calculate inputs average I'm creating an online calculator to get the average grade of different tests my students take. I wonder if you see any problems in the following code or any way to improve it:



document.getElementById('calculator').addEventListener('click', function() {
  var physicsTests = document.getElementById('physics').getElementsByTagName('input'),
    historyTests = document.getElementById('history').getElementsByTagName('input'),
    physicsTestsCount = 0,
    historyTestsCount = 0,
    physicsAverage = document.getElementById('physicsAverage'),
    historyAverage = document.getElementById('historyAverage'),
    i;
  for (i = 0; i &lt; physicsTests.length; i++) {
    if (physicsTests[i].value) {
      physicsTestsCount++;
    }
    if (!physicsTestsCount) {
      physicsAverage.value = 'No assessment made!';
    } else {
      physicsAverage.value = (Number(physicsTests[0].value) + Number(physicsTests[1].value) + Number(physicsTests[2].value)) / physicsTestsCount;
    }
  }
  for (i = 0; i &lt; historyTests.length; i++) {
    if (historyTests[i].value) {
      historyTestsCount++;
    }
    if (!historyTestsCount) {
      historyAverage.value = 'No assessment made!';
    } else {
      historyAverage.value = (Number(historyTests[0].value) + Number(historyTests[1].value) + Number(historyTests[2].value)) / historyTestsCount;
    }
  }
});
&lt;form&gt;
  &lt;p id="physics"&gt;
    Physics:
    &lt;input type="number"&gt;
    &lt;input type="number"&gt;
    &lt;input type="number"&gt;
    &lt;output id="physicsAverage"&gt;&lt;/output&gt;
  &lt;/p&gt;
  &lt;p id="history"&gt;
    History:
    &lt;input type="number"&gt;
    &lt;input type="number"&gt;
    &lt;input type="number"&gt;
    &lt;output id="historyAverage"&gt;&lt;/output&gt;
  &lt;/p&gt;
  &lt;button type="button" id="calculator"&gt;Calculate&lt;/button&gt;
&lt;/form&gt;
type=number inputs can be error-prone because it's easy to mistakenly adjust a value with the mouse wheel.  Unless you specifically intend to enter grades with a mouse wheel, or have some other use for that interface, go with regular text fields.

You're testing the truth of element.value as a string and then adding it as a number.  It's good practice to be explicit about these kinds of conversions. 

It would be nice to generalize the code to handle any subject, without the use of hard-coding or copy-and-paste.  

We only need the subject name to put a label next to the inputs; the code doesn't need to know it at all.   The code snippet below uses the name=... attribute to label the inputs (via CSS) and class=subject to denote an average-eligible set of inputs.  The number of inputs is determined solely by the HTML.



document.getElementById('calculator').addEventListener('click', function() {
    Array.from( document.getElementsByClassName('subject') ).forEach(subject =&gt; {
        const scores=Array.from( subject.getElementsByTagName('input') ).map( e =&gt; ""+e.value.trim() ).filter( s =&gt; s.length ).map( n =&gt; parseFloat(n) ),
          output=subject.getElementsByTagName('output'),
          sum=scores.length ? scores.reduce((partial_sum, a) =&gt; partial_sum + a) : 0,
          average=scores.length ? ( sum / scores.length ).toFixed(2) : "No assessment made!"
      if (output.length) output[0].textContent = average;
  })
});
    
.subject::before {  text-transform: capitalize; content: attr(name) ": " }
.subject &gt; input { width:3em }
&lt;form&gt;
  &lt;p class=subject name=physics&gt;   &lt;input&gt; &lt;input&gt; &lt;input&gt; &lt;output/&gt;  &lt;/p&gt;
  &lt;p class=subject name=history&gt;   &lt;input&gt; &lt;input&gt; &lt;input&gt; &lt;output/&gt;  &lt;/p&gt;
  &lt;p class=subject name=chemistry&gt; &lt;input&gt; &lt;input&gt; &lt;input&gt; &lt;input&gt; &lt;output/&gt;  &lt;/p&gt;
  &lt;p class=subject name=algebra&gt;   &lt;input&gt; &lt;output/&gt;  &lt;/p&gt;
  &lt;button type=button id=calculator&gt;Calculate&lt;/button&gt;
&lt;/form&gt;