ArtsAutosBooksBusinessEducationEntertainmentFamilyFashionFoodGamesGenderHealthHolidaysHomeHubPagesPersonal FinancePetsPoliticsReligionSportsTechnologyTravel

How to Create a Loan Amortization Calculator Using HTML and JavaScript

Updated on November 11, 2015

Published: October 30, 2011

Edited: 12 May 2015


JavaScript: HTML on Steroids
JavaScript: HTML on Steroids

So you have learned a little about HTML and JavaScript. Now you would like to accomplish something useful. If you make payments on any kind of loan or are thinking of taking one out then a javascript loan amortization calculator may fit your needs quite nicely.

This final JavaScript tutorial in the installment of tutorials puts together disciplines learned in many of Dumbledore's previous tutorials and leads an aspiring programmer on the quest to develop a functioning loan amortization calculator.

Unlike Dumbledore's other HTML and JavaScript tutorials that simply include snippets of the elements under study, this module will present the entire set of source code components, both HTML and JavaScript necessary to build the amortization calculator.

HTML Input Table

The only component of the amortization calculator that users directly interact with is the HTML input table. This table provides a HTML form where the user may enter the data used to calculate the characteristics of the loan's terms and perform the amortization. The operations are then completed when the user clicks on the button labeled Commit.

The following code module presents the entire HTML file for the amortization program:

HTML Table Code

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

  <head>
    <title>Amortization Calculator</title>
    <style>
      body {background-color:white; font-family: Arial, Helvetica, sans-serif}
      h2 {color:blue; letter-spacing: 1em; font-size: 1.5em; text-align: center}
      input {color:blue; margin-left: 15px}
      td {text-align:center; background-color:yellow}
    </style>

    <script type="text/javascript" src="amort.js"></script>

  </head>

  <body>

    <center>
      <div id="mainForm">
        <form id="form1" name="form1">
          <table>
            <tr><td> Your name</td>
              <td><input id="name" name="name" size="35" /></td>
            </tr>
            <tr><td> Loan Amount</td>
              <td><input id="amount" name="amount" size="8" /></td>
            </tr>
            <tr><td> Interest Rate</td>
              <td><input id="rate" name="rate" size="5" /></td>
            </tr>
            <tr><td> Number of Payments</td>
              <td><input id="numPay" name="numPay" size="5" /></td>
            </tr>
            <tr><td></td>
              <!-- Clicking the Commit button invokes the commitData() function in the <script> section above -->
              <td><input type="button" onclick="commitData()" value="Commit" /></td>
            </tr>
          </table>
        </form>
      </div>
    </center>
  </body>
</html>

Separate HTML and JavaScript

The HTML code presented above represents all the HTML coding necessary for the Amortization Program. Since HTML is only used by the program to generate the input for the program and display the results of the amortization, Dumbledore separated the HTML and JavaScript code.

The JavaScript component is contained in a separate file named amort.js and the following line of code included in the header portion of the HTML code above illustrates how to refer to the external JavaScript file from the HTML code:

 <script type="text/javascript" src="amort.js"></script>

Amortization: JavaScript By The Numbers

As stated earlier, Dumbledore included the JavaScript code for the amortization program in a separate file. This serves a couple of purposes: first, separating the HTML and JavaScript isolates the presentation of data from the program logic; second, the JavaScript does not show up in the source-code for the HTML document.

The modules that follow present each of the JavaScript functions and explain what goes on within the function modules. The individual modules are presented as code snippets and the entire JavaScript file is included at the end of the tutorial. The first of these modules is the commitData() function:

The commitData() Function

The commitData() function is the control or dispatch module for the program. This is the function that the user calls by pressing the button labeled Commit in the HTML form and specified in the <input> element of the HTML code. There are a number of housekeeping routines initiated by this function, the first of which is to create a table on a new page and echo the data that the user supplied. The module is displayed below:

function commitData() {
  // Declair and initialize the variables
  var loanName=document.form1.name.value;
  var loanAmount=document.form1.amount.value;			
  var intRate=document.form1.rate.value; 			
  var numPay=document.form1.numPay.value;
  // Render the display tables to echo the user input
  renderEchoInput();  
  	
  // Render the amortization table, this table displays the number of
  // rows specified by the number of payments input by the user in the numPay field.
  renderAmortizationTable(numPay);
  
  // Echo the input in the display table using the displayTableField() function
  displayTableField("flname",loanName);
  displayTableField("lamount",loanAmount);
  displayTableField("irate",intRate);
  displayTableField("numPmt",numPay);
  //Calculate and display the monthly payment amount
  var monPmt=calcMonthly(loanAmount,numPay,intRate);
  displayTableField("monPmt",monPmt);
  // Call the amortization routine
  amortizePmts(loanAmount,intRate,numPay,monPmt);
  return;
}

The commitData() function is a dispatcher module, which simply means that this function calls other functions to perform the actions necessary for the program to generate the desired results, in this case the loan amortization.

This function begins by declaring and initializing the variables necessary to retrieve the user's data from the HTML form.

The function then calls the functions that echo the user's input back so the user may see what was entered, this is the renderEchoInput() function. Next, the function to render the amortization table is called, which is the renderAmortizationTable() function.

The displayData() function is called four times to echo back the data the user entered and finally the functions to calculate the terms of the loan and perform the amortization are called.

The functions called by the commitData() function comprise the meat of the program and the remainder of this hub explains each of those functions.

Render the Table to Echo Input

function renderEchoTable(){
  document.write("<table>");
  document.write("<tr><td><table id='datTab'>");
  document.write("<tr><td id='namLab'>Borrower Name: </td><td id='flname'></td></tr>");
  document.write("<tr><td id='amtLab'>Loan Amount: </td><td id='lamount'></td></tr>");
  document.write("<tr><td id='intLab'>Interest Rate: </td><td id='irate'></td></tr>");
  document.write("<tr><td id='numLab'>Number of Payments:   </td><td id='numPmt'></td></tr>");
  document.write("<tr><td id='monLab'>Monthly Payment: </td><td id='monPmt'></td></tr>");
  document.write("</table></td>");
}

The purpose of the renderEchoTable() function is to simply create the table that will display back the information entered by the user for verification. The commitData() function calls this function exactly one time.

You may notice that the function simply contains a number of document.write statements and that those statements seem to contain HTML code. If you noticed this, you are correct. JavaScript may contain HTML code. This is a useful characteristic when the programmer wishes to create HTML elements after the initial web page loads. This is exactly what the author wished to accomplish with this function. The function createss an empty table, which the program will later populate with data.

After creating the echo table, the amortization table is created as determined by the number of payments that the user entered:

Amortization Program output  with Table Headings
Amortization Program output with Table Headings

Render the Amortization Table

Like the renderEchoTable() function above, the renderAmortizationTable() function displays an empty table that the program will later populate. The major difference in the functionality of the two modules is that this table varies in length according to a value entered by the user.

This variation is accomplished using a looping structure, which is dependent on the numPay parameter supplied by the calling routine.

One innovative method included in this function is using the tagNam variable to create dynamic id's for the <td> elements within the code. These id's are used by the getElementById() function later in the program so they must be unique. An alternative to the dynamic id's would have been to hard code an HTML table representing the maximum length of a loan, say 30 years or 360 payments but this would entail creating 360 static rows in the HTML table. This would have been a tedious exercise in codingcoding. However, in some cases the tedious method may someimes be easier than figuring out the alternative. Which method to apply isd up to the coder developing the program.

function renderAmortizationTable(numPay) {
  document.write("<td><table border="+"1"+" id='pmtTab'><tr   style='background-color:DeepSkyBlue'><td id='numHead'>Payment Number</td><td id='oldBal'>Previous Balance</td><td id='pt'>Payment</td><td id='oil'>Interest Paid</td><td id='newBal'>New Balance</td><td id='til'>Total Interest</td></tr>");
  var tagNam;
  for(var i=1;i<=numPay;i++) {
    loopNum=i;
    tagNam="n"+loopNum.toString(10);
    document.write("<tr style='background-color:LightSkyBlue'><td id=tagNam>"+i+"</td>");
    tagNam="b"+loopNum.toString(10);
    document.write("<td id="+tagNam+"></td>");
    tagNam="p"+loopNum.toString(10);
    document.write("<td id="+tagNam+"></td>")  
    tagNam="oi"+loopNum.toString(10);
    document.write("<td id="+tagNam+"></td>");
    tagNam="nb"+loopNum.toString(10);
    document.write("<td id="+tagNam+"></td>");
    tagNam="ti"+loopNum.toString(10);
    document.write("<td id="+tagNam+"></td></tr>");
  }
  // This statement outside the loop completes the table
  document.write("</table></td></tr></table>");
}

Amortize Payments

The amortizePmts() function performs the steps to amortize the loan. These steps include calculating the current interest due on the loan, subtracting that interest from the amount of the monthly payment, then subtracting the resulting amount from the old balance. The result of this final subtraction then becomes the new balance for the loan. These operations repeat for as many payments are included in the terms of the loan and the final result is the loan amortization.

function amortizePmts(loanAmount,intRate,numPay,monPmt) {
  var oldBalance=loanAmount;
  var newBalance=loanAmount;				
  intRate=(intRate/100)/12;				
  var monthly=monPmt;
  var owedInterest=0;
  var totalInterestPd=0;
  var tagNam;
  var dispInt
  // The for loop performs the amortization
  for(var i=1;i<=numPay;i++) {
    var loopNum=i;
    owedInterest=newBalance*intRate;
    dispInt=twoDecimal(owedInterest);
    totalInterestPd=totalInterestPd+owedInterest;
    // Test for the final payment
    if (i<numPay) {
      monthly=twoDecimal(monPmt-dispInt);
      oldBalance=newBalance;
      newBalance=twoDecimal(oldBalance-monthly);
    }
    else {
      monthly=(oldBalance-monthly)+owedInterest;
      oldBalance=newBalance;
      newBalance=0;
      monthly=twoDecimal(monthly);
    }
    tagNam="b"+loopNum.toString(10);
    displayTableField(tagNam,oldBalance);
    tagNam="p"+loopNum.toString(10);
    displayTableField(tagNam,monthly);
    tagNam="oi"+loopNum.toString(10);
    displayTableField(tagNam,dispInt);
    tagNam="nb"+loopNum.toString(10);
    displayTableField(tagNam,newBalance);
    tagNam="ti"+loopNum.toString(10);
    displayTableField(tagNam,twoDecimal(totalInterestPd));
  }
  return;
}
Amortization output reflecting input data
Amortization output reflecting input data

Display a Table Field

The displayTableField() function is the shortest function in the program and was created as an early demonstration of the benefits of modularization. The two attributes included in the definition of the function are passed to the function when it is invoked and this short routine actually eliminates quite a bit of redundant coding by shortening the lengths of the lines used to display a table field if the function were not a separate module.

function displayTableField(eleId,eleDat) {
  document.getElementById(eleId).innerHTML=eleDat;
  return;
}

Are tutorials worthwhile

Did you view Dumbledore's other tutorials?

See results

Calculate the Monthly Payment

A standard accounting function forms the basis for the function used to calculate the monthly payment. This function uses the amount of the loan, the interest rate, and the number of payments to determine what the monthly payment would be for the given terms of the loan. The payment is calculated one time then echoed back to the user and finally used by the amortization routine to specify the state of the loan after each payment is made.

function calcMonthly(principal,numPay,intRate) {
  var monthly;
  var intRate=(intRate/100)/12;
  var principal;
  // The accounting formula to calculate the monthly payment is
  //	M = P * ((I + 1)^N) * I / (((I + 1)^N)-1)
  // The following code  transforms the accounting formula into JavaScript to calculate the monthly payment
  monthly=(principal*(Math.pow((1+intRate),numPay))*intRate/(Math.pow((1+intRate),numPay)-1));
  return twoDecimal(monthly);
}

Convert a Format to Two-Decimal

When interest rates are calculated they generally extend out to quite a few decimal places. This floating point number then influences monetary calculations so the number of decimal places may become quite large.

The twoDecimal() function converts a floating point number to one limited to two decimal places. This function is necessary to convert the output to a more readable form and ensure that the output in fact fits in the table fields..

function twoDecimal(chgVar) {
  var chgVar;
  var twoDec=chgVar.toFixed(2);
  return twoDec;
}

Was this hub informational?

The author appreciates all comments.

Disclaimer

Note: The code contained in this hub contains some minor errors, which are left to the learner to discover and correct as an exercise. Therefore, no warranty, implied or otherwise, is supplied as a guarantee for this code. The program was created and presented as a learning exercise.

The Complete amort.js file

function commitData() {
  // Declair and initialize the variables
  var eleId;
  var eleDat;
  var loanName=document.form1.name.value;
  var loanAmount=document.form1.amount.value;			
  var intRate=document.form1.rate.value; 			
  var numPay=document.form1.numPay.value;
  var loopNum;
  var tagNum;
  var tagNam;
  // Render the display tables to echo the user input
  document.write("<table>");
  document.write("<tr><td><table id='datTab'>");
  document.write("<tr><td id='namLab'>Borrower Name: </td><td id='flname'></td></tr>");
  document.write("<tr><td id='amtLab'>Loan Amount: </td><td id='lamount'></td></tr>");
  document.write("<tr><td id='intLab'>Interest Rate: </td><td id='irate'></td></tr>");
  document.write("<tr><td id='numLab'>Number of Payments:   </td><td id='numPmt'></td></tr>");
  document.write("<tr><td id='monLab'>Monthly Payment: </td><td id='monPmt'></td></tr>");
  document.write("</table></td>");		
  // Render the amortization table, this table displays the number of
  // rows specified by the number of payments input by the user in the numPay field.
  document.write("<td><table border="+"1"+" id='pmtTab'><tr style='background-color:DeepSkyBlue'><td id='numHead'>Payment Number</td><td id='oldBal'>Previous Balance</td><td id='pt'>Payment</td><td id='oil'>Interest Paid</td><td id='newBal'>New Balance</td><td id='til'>Total Interest</td></tr>");
  for(var i=1;i<=numPay;i++) {
    loopNum=i;
    tagNam="n"+loopNum.toString(10);
    document.write("<tr style='background-color:LightSkyBlue'><td id=tagNam>"+i+"</td>");
    tagNam="b"+loopNum.toString(10);
    document.write("<td id="+tagNam+"></td>");
    tagNam="p"+loopNum.toString(10);
    document.write("<td id="+tagNam+"></td>")  
    tagNam="oi"+loopNum.toString(10);
    document.write("<td id="+tagNam+"></td>");
    tagNam="nb"+loopNum.toString(10);
    document.write("<td id="+tagNam+"></td>");
    tagNam="ti"+loopNum.toString(10);
    document.write("<td id="+tagNam+"></td></tr>");
  }
  // This statement outside the loop completes the table
  document.write("</table></td></tr></table>");
  // Echo the input in the display table using the displayTableField() function
  displayTableField("flname",loanName);
  displayTableField("lamount",loanAmount);
  displayTableField("irate",intRate);
  displayTableField("numPmt",numPay);
  //Calculate and display the monthly payment amount
  var monPmt=calcMonthly(loanAmount,numPay,intRate);
  displayTableField("monPmt",monPmt);
  // Call the amortization routine
  amortizePmts(loanAmount,intRate,numPay,monPmt);
  return;
}

function amortizePmts(loanAmount,intRate,numPay,monPmt) {
  var oldBalance=loanAmount;
  var newBalance=loanAmount;				
  intRate=(intRate/100)/12;				
  var monthly=monPmt;
  var owedInterest=0;
  var totalInterestPd=0;
  var tagNam;
  var dispInt
  // The for loop performs the amortization
  for(var i=1;i<=numPay;i++) {
    var loopNum=i;
    owedInterest=newBalance*intRate;
    dispInt=twoDecimal(owedInterest);
    totalInterestPd=totalInterestPd+owedInterest;
    // Test for the final payment
    if (i<numPay) {
      monthly=twoDecimal(monPmt-dispInt);
      oldBalance=newBalance;
      newBalance=twoDecimal(oldBalance-monthly);
    }
    else {
      monthly=(oldBalance-monthly)+owedInterest;
      oldBalance=newBalance;
      newBalance=0;
      monthly=twoDecimal(monthly);
    }
    tagNam="b"+loopNum.toString(10);
    displayTableField(tagNam,oldBalance);
    tagNam="p"+loopNum.toString(10);
    displayTableField(tagNam,monthly);
    tagNam="oi"+loopNum.toString(10);
    displayTableField(tagNam,dispInt);
    tagNam="nb"+loopNum.toString(10);
    displayTableField(tagNam,newBalance);
    tagNam="ti"+loopNum.toString(10);
    displayTableField(tagNam,twoDecimal(totalInterestPd));
  }
  return;
}

function displayTableField(eleId,eleDat) {
  document.getElementById(eleId).innerHTML=eleDat;
  return;
}

function calcMonthly(principal,numPay,intRate) {
  var monthly;
  var intRate=(intRate/100)/12;
  var principal;
  // The accounting formula to calculate the monthly payment is
  //	M = P * ((I + 1)^N) * I / (((I + 1)^N)-1)
  // The following code  transforms this accounting formula into JavaScript to calculate the monthly payment
  monthly=(principal*(Math.pow((1+intRate),numPay))*intRate/(Math.pow((1+intRate),numPay)-1));
  return twoDecimal(monthly);
}

function twoDecimal(chgVar) {
  var chgVar;
  var twoDec=chgVar.toFixed(2);
  return twoDec;
}

Comments

    0 of 8192 characters used
    Post Comment

    • profile image

      eli 

      13 months ago

      if i want to open the table in another page ? in blank page..

      and not like in here in the same page..

      how can i do that ?

    • JustMike profile image

      JustMike 

      2 years ago

      this is just what i was looking for. Thank you.

    • profile image

      OllyDbg 

      2 years ago

      Thank you so much!

    • Dumbledore profile imageAUTHOR

      This Old Guy 

      6 years ago from Somewhere in Ohio

      Boss,

      You can use the isnumeric keyword to validate a required field that must be numeric. If the test passes, then data was entered into the field.

      You can validate the value using the following:

      if (number

    • profile image

      Boss 

      6 years ago

      Can you help me out with validation as a required field, Must be a Number Field, Number must be greater than 0.

      Thank You.

    • profile image

      Patel 

      6 years ago

      Amazing

    • Dumbledore profile imageAUTHOR

      This Old Guy 

      7 years ago from Somewhere in Ohio

      I'm glad I could help you, YellowOC1.

    • YellowOC1 profile image

      YellowOC1 

      7 years ago

      Nice tips, helped me out in working this new project

    • BABYCHICOSREVEIWS profile image

      BABYCHICOSREVEIWS 

      7 years ago from Fort Pierce Florida

      I thought I knew it all, amazing review. Thank you

    working

    This website uses cookies

    As a user in the EEA, your approval is needed on a few things. To provide a better website experience, hubpages.com uses cookies (and other similar technologies) and may collect, process, and share personal data. Please choose which areas of our service you consent to our doing so.

    For more information on managing or withdrawing consents and how we handle data, visit our Privacy Policy at: https://hubpages.com/privacy-policy#gdpr

    Show Details
    Necessary
    HubPages Device IDThis is used to identify particular browsers or devices when the access the service, and is used for security reasons.
    LoginThis is necessary to sign in to the HubPages Service.
    Google RecaptchaThis is used to prevent bots and spam. (Privacy Policy)
    AkismetThis is used to detect comment spam. (Privacy Policy)
    HubPages Google AnalyticsThis is used to provide data on traffic to our website, all personally identifyable data is anonymized. (Privacy Policy)
    HubPages Traffic PixelThis is used to collect data on traffic to articles and other pages on our site. Unless you are signed in to a HubPages account, all personally identifiable information is anonymized.
    Amazon Web ServicesThis is a cloud services platform that we used to host our service. (Privacy Policy)
    CloudflareThis is a cloud CDN service that we use to efficiently deliver files required for our service to operate such as javascript, cascading style sheets, images, and videos. (Privacy Policy)
    Google Hosted LibrariesJavascript software libraries such as jQuery are loaded at endpoints on the googleapis.com or gstatic.com domains, for performance and efficiency reasons. (Privacy Policy)
    Features
    Google Custom SearchThis is feature allows you to search the site. (Privacy Policy)
    Google MapsSome articles have Google Maps embedded in them. (Privacy Policy)
    Google ChartsThis is used to display charts and graphs on articles and the author center. (Privacy Policy)
    Google AdSense Host APIThis service allows you to sign up for or associate a Google AdSense account with HubPages, so that you can earn money from ads on your articles. No data is shared unless you engage with this feature. (Privacy Policy)
    Google YouTubeSome articles have YouTube videos embedded in them. (Privacy Policy)
    VimeoSome articles have Vimeo videos embedded in them. (Privacy Policy)
    PaypalThis is used for a registered author who enrolls in the HubPages Earnings program and requests to be paid via PayPal. No data is shared with Paypal unless you engage with this feature. (Privacy Policy)
    Facebook LoginYou can use this to streamline signing up for, or signing in to your Hubpages account. No data is shared with Facebook unless you engage with this feature. (Privacy Policy)
    MavenThis supports the Maven widget and search functionality. (Privacy Policy)
    Marketing
    Google AdSenseThis is an ad network. (Privacy Policy)
    Google DoubleClickGoogle provides ad serving technology and runs an ad network. (Privacy Policy)
    Index ExchangeThis is an ad network. (Privacy Policy)
    SovrnThis is an ad network. (Privacy Policy)
    Facebook AdsThis is an ad network. (Privacy Policy)
    Amazon Unified Ad MarketplaceThis is an ad network. (Privacy Policy)
    AppNexusThis is an ad network. (Privacy Policy)
    OpenxThis is an ad network. (Privacy Policy)
    Rubicon ProjectThis is an ad network. (Privacy Policy)
    TripleLiftThis is an ad network. (Privacy Policy)
    Say MediaWe partner with Say Media to deliver ad campaigns on our sites. (Privacy Policy)
    Remarketing PixelsWe may use remarketing pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to advertise the HubPages Service to people that have visited our sites.
    Conversion Tracking PixelsWe may use conversion tracking pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to identify when an advertisement has successfully resulted in the desired action, such as signing up for the HubPages Service or publishing an article on the HubPages Service.
    Statistics
    Author Google AnalyticsThis is used to provide traffic data and reports to the authors of articles on the HubPages Service. (Privacy Policy)
    ComscoreComScore is a media measurement and analytics company providing marketing data and analytics to enterprises, media and advertising agencies, and publishers. Non-consent will result in ComScore only processing obfuscated personal data. (Privacy Policy)
    Amazon Tracking PixelSome articles display amazon products as part of the Amazon Affiliate program, this pixel provides traffic statistics for those products (Privacy Policy)