Forms that Calculate


It is possible to build simple stand-alone applications using forms and JavaScript. These are of somewhat limited use on their own as JavaScript embedded in HTML pages depends on the services provided by a browser. For example JavaScript cannot maintain data by working with local files. (Of course there are good security reasons for this.) The scripted form below is an example of what you can do with a form and JavaScript. It provides a simple way to calculate your total savings if you invest a fixed amount every month for a given number of years. The form also provides some fictitious Guaranteed Investment Certificate interest rates with some conditions. Try it out:


Total Savings Calculator

(fixed interest and fixed monthly deposits)

Number of Years:
Monthly Deposit Amount:
GIC Type:

Total Savings:

There are at least three ways in which this form could be improved:

  1. If you enter a nonnumeric value in the year or monthly deposit fields the total savings are reported as NaN (Not a number). It would be better to explain what went wrong to the user when this happens. The normal way to do this is to check their input character by character - looking for and reporting illegal characters. It would also be helpful to allow the user to enter a dollar sign ($) and a decimal point in the monthly deposit field. If you allow a dollar sign it must be removed before the value is converted to a number.
  2. Similarly, entering bad data in the year field will produce NaN or an incorrect result. For example if a user enters -100 in the deposit field. Ideally, user data of this type would be caught and reported.
  3. The total savings are reported as numbers such as: 1091510.254092961 and really should be rounded to the nearest cent. For example it would be better to report: $1091510.25, or better still: $1,091,510.25.

Of course the form does not adjust for varrying inflation rates or give you the option to deposit different amounts over different periods of time. To keep the calculation and the form relatively simple we will just pretend there is no such thing as inflation and no other means of investing funds beyond fixed amount monthly deposits. Below is the complete source code for this example. The comments in the code provide an explanation of how it works.

<HTML>
<HEAD>
<TITLE>Total Value of Regular Monthly Deposits</TITLE>
<SCRIPT Language="JavaScript">
<!--


/**
 * Function that returns the selected value
 * after being passed a reference to a single choice
 * selection list.
 **/
function getSelectedValue(selectList){
   return selectList[selectList.selectedIndex].value
}


/**
 * Function to calculate the total savings based on fixed
 * monthly deposits.
 * This function does no testing of user data other than
 * to compare the minimum number of years a GIC requires
 * to the number of years entered. No checking is done
 * that properly formatted data has been entered!
 * Adding error checking is left as an exercise.
 * The formula used here is:
 * total = deposits * (((1 + monthly interest)^N*Y) - 1)/(monthly interest)
 * where N the number of deposits per year (in this case 12),
 *       Y the number of years
 *       monthly interest = (%yearly interest/100)/number of deposits per year
 *       ^ means to the power of
 * Here is the formula in JavaScript using the Math.pow(x,y) function
 * that raises x to the power of y:
 * total = deposits * (Math.pow((1 + monthlyInt),(depPerYear * years)) - 1)/(monthlyInt)
 *
 * Note: The GICType selection list values are in the format: "minYears,yearlyInterest"
 *       In other words the value contains a string with two separate pieces of data
 *       separated by a comma. To extract both pieces of data into separate variables,
 *       the comma is found and the substrings before and after it are extracted.
 **/
function calculateTotal(frm){
   var years      = frm.years.value
   var deposits   = frm.deposits.value
   var depPerYear = 12
   var GICType    = getSelectedValue(frm.GICType)
   var comma      = GICType.indexOf(",")             //Find comma location in string
   var minYears   = GICType.substring(0,comma)       //Extract substring before comma
   var interest   = GICType.substring(comma + 1)     //Extract substring after comma
   var monthlyInt = 0
   var total      = 0

   //Convert all values to integers or numbers
   years    = parseFloat(years)
   deposits = parseFloat(deposits)
   minYears = parseInt(minYears)
   interest = parseFloat(interest)/100


   if (minYears > years){
      frm.total.value = "Error"
      alert("The number of years must be equal \nto or more than GIC minimum.\n")
   }

   monthlyInt = interest/depPerYear

   total = deposits * (Math.pow((1 + monthlyInt),(depPerYear * years)) - 1)/(monthlyInt)
   frm.total.value = total
}

//-->
</SCRIPT>
</HEAD>

<BODY bgcolor="#FFFFFF">

<p> </p>
<H2>Total Savings Calculator</H2>
  <P>(fixed interest and fixed monthly deposits)</p>
<form method="post" action="">
  <table border="0" cellspacing="0" cellpadding="3">
    <tr>
      <td align="right">Number of Years:</td>
      <td><input type="text" name="years" size="4" maxlength="3"></td>
    </tr>
    <tr>
      <td align="right">Monthly Deposit Amount:</td>
      <td><input type="text" name="deposits" size="6" maxlength="5"></td>
    </tr>
    <tr>
      <td align="right">GIC Type:</td>
      <td>
        <SELECT name="GICType">
           <OPTION value="0,5">Grade A, No Fixed Term Certificate: 5%</OPTION>
           <OPTION value="2,6">Grade B, Minimum 2 Year Certificate: 6%</OPTION>
           <OPTION value="3,6.2">Grade B, Minimum 3 Year Certificate: 6.2%</OPTION>
           <OPTION value="5,7">Grade C, Minimum 5 Year Certificate: 7%</OPTION>
        </SELECT>
      </td>
    </tr>
    <tr>
      <td colspan="2" align="center">
          <input type="button" name="Button" value="Calculate Total Savings" onClick="calculateTotal(this.form)">
          <hr size="1" noshade>
      </td>
    </tr>
    <tr>
      <td align="right">Total Savings:</td>
      <td>
        <input type="text" name="total" size="30" maxlength="30">
      </td>
    </tr>
  </table>

</form>
<p> </p>

</BODY>
</HTML>