Practice Set: Functions to Reduce Repetitive Code

by Rick Harraghy

HTML

<p>There is one exercise in this practice set.</p>
<p>In this exercise, you will take some of the repetitive code in this example and move it into a function that performs the same task. In your solution, you'll call your new function three times instead of having the code duplicated in three places. See the code comments for more guidance.  </p>
<p>Remember that code can be awfully difficult to debug in JSFiddle. If you get frustrated trying to find a bug as you write your solution, you may want to copy this example to a local version on your computer to work it out, then paste it back in to JSFiddle.</p>
    <p>
        <div id="doIt" class="button">Calculate Averages</div>
    </p>
   

<table border="1">
    <table border="1">
      <tbody>
          <tr>
              <th>Number 1</th> 
              <th>Number 2</th>
              <th>Number 3</th>
              <th>Row Average</th>
          </tr>
        <tr>
          <td><input value="23" class="row1" type="text"><br>
          </td>
          <td><input value="50" class="row1" type="text"><br>
          </td>
          <td><input value="74" class="row1" type="text"><br>
          </td>
          <td id="row1Average" class="avg"><br>
          </td>
        </tr>
        <tr>
          <td><input value="41" class="row2" type="text"><br>
          </td>
          <td><input value="16" class="row2" type="text"><br>
          </td>
          <td><input value="27" class="row2" type="text"><br>
          </td>
          <td id="row2Average" class="avg"><br>
          </td>
        </tr>
        <tr>
          <td><input value="90" class="row3" type="text"><br>
          </td>
          <td><input value="51" class="row3" type="text"><br>
          </td>
          <td><input value="55" class="row3" type="text"><br>
          </td>
          <td id="row3Average" class="avg"><br>
          </td>
        </tr>
      </tbody>
    </table>

CSS

.avg{
    width: 25%;
    font-weight: bold;
}
.button:hover{
    cursor:pointer;
}
.row1, .row2, .row3 {
    width: 5em;
}
.button {
    text-indent:0;
    border:1px solid #eda933;
    display:inline-block;
    color:#ffffff;
    font-family:Arial;
    font-size:15px;
    font-weight:bold;
    font-style:normal;
    height:65px;
    line-height:65px;
    padding: .5 em;
    text-decoration:none;
    text-align:center;
    text-shadow:1px 1px 0px #cd8a15;
    background-color:#f6b33d;
}

JavaScript

/* 
This code calculates the average of the values in each of three rows, using nearly identical code that's repeated in three places. You can improve it by creating a single function, and calling that function once for each row in the table. 

There's more than one way to do this. Your function may  accept an Array of HTMLInputElements and return the average of their values. 

Or it may accept a classname (for the text inputs) and an ID (where to write the output) and write to the page directly (returning nothing). 

There are other ways, too. The important thing about your solution is that it reduce the duplication of code we see here, and consolidate some of that functionality into a function.    
*/
document.getElementById("doIt").onclick = function(){
    //Number of rows
    var numRows = 3;
    
    // function to calculate the average of each of the three rows
    function avgRowValue(row, rowAverage)
    {
        var sum=0, value=0, count=0;
        
        // First we get an array of the input elements from the HTML 
        var rowInputs = document.getElementsByClassName(row);
        
        // Then we iterate over that array, and for each element...
        for(var i=0; i<rowInputs.length; i++)
        {
            // ...we get its value (parsed to an integer)
            value = parseInt(rowInputs[i].value);
            
            // ...and if that value isn't undefined or NaN, add
            // it to the sum, and increment the counter
            if (value)
            { 
                sum += value;
                count++;
            }
        } // end for loop
        
        // Now we calculate the average, and write to the last cell in the row
        var rowAvg = sum/count;
        document.getElementById(rowAverage).innerHTML = rowAvg; 
        
    } // end function avgRowValue
    
    //For each row, call function avgRowValue to calculate its average
    for(var j=1; j<=numRows; j++)
    {
        avgRowValue("row" + j, "row" +...