
<!-------
// initilize page variables
window.onerror=null
var bState = true;
var rec = 0;
var oTable = new Array();

// the colors for the amortization table... you will need to search and replace on these codes for the HTML form.
var bColor = '#FFFFFF' // white
var fColor = '#006600' // green

// names for the collections (used for form validation)
oReq = new Collection("AMOUNT","RATE","","","","")
oVal = new Collection("AMOUNT","RATE","","","","")
oTst = new Collection("N","N","","","","")

//============================================================================
// Gets called when the user pressed one of the buttons.
// oForm: 		form elements
// oBtn:  		the name of the button that was pressed
// return value:	did we make it through?
//============================================================================
function controller(oForm, oBtn) {
   while (bState) {
      if (!Required(oForm))
         break;
      if (!Validate(oForm))
         break;
      if (!Create())
         break;
      if (!SetValue(oForm))
         break;
      if (!Amortize(oForm, oBtn))
         break;
      if (bState) {
          bState = false
      }
   }
   bState = true
}

//============================================================================
// Check if a form element is required by comparing the all of the form
// elements against a collection of required form control names.
// oView: 		form elements
// oReq		required elements
// return value:	did it pass the test?
//============================================================================
function Required(oView) {
   for (i in oView ) {
      for (j in oReq) {
          if (i == oReq[j]) {      
             if (isMissing(oView[i])) {
               return(false)
             }
          }
      } 
  }
  return(true)
}

//============================================================================
// Check if a form control is required and missing
// oView: 		a form control
// Return value:	do we have a problem?
//============================================================================
function isMissing(oCtrl) {
   if (oCtrl.value == "") { 
      alert("You have left a required value blank. Please type a number");
      oCtrl.focus();
      oCtrl.select();
      return(true)
      }
   else
      { 
      return(false)
   }
}

//============================================================================
// Check if a form element inputs need to be a certain type by
// comparing all of the form elements against a collection of 
// form controls that need specific types of input data.
// oView: 		form elements
// oReq		required elements
// return value:	did it pass the test?
//============================================================================
function Validate(oView) {
   for (i in oView) {
      for (j in oVal) {
        if (i==oVal[j] && oTst[j]=="N") {      
           if (isTest(oView[i], oTst[j])) {
               return(false)
           }
        }
     }
  }
  return(true)
}

//============================================================================
// Check if a form control input is the right type
// oView: 		a form control
// Return value:	do we have a problem?
//============================================================================
function isTest(oCtrl, oTest) {
   if (oTest=="N" && !isNumber(oCtrl.value) ) {
      alert(oCtrl.value+" contains an invalid character. Please type a number");
      oCtrl.focus();
      oCtrl.select();
      return(true)
      }
      else
      { 
      return(false)
   }
}

//============================================================================
// Check if the result is a number
// input: 		a texbox value
// Return value:	true / false
//============================================================================
function isNumber(input) {
var result = ""
var nperiods = 0;
   for (var i=0;i<input.length;i++) {
      var ch = input.substring(i, i+1);
      if (!isNaN(parseInt(ch))) {
         result = result + ch
      } 
      if (ch==".") {
        nperiods++;
      }
      if (nperiods==1){
         result = result + ch  
      }
   }
   if (result == ""){
     return(false);
   }
return(true)
}

//============================================================================
// Make a string input into a number
// input: 		a texbox value
// Return value:	a number
//============================================================================
function makeNumber(input) {
var result = ""
var nperiods = 0;
   for (var i=0;i<input.length;i++) {
       var ch = input.substring(i, i+1);
       var flag = true;
       if (!isNaN(parseInt(ch))) {
          result = result + ch
       }           
       if (ch==".") {
         nperiods++;
       }
       if (nperiods==1){
          result = result + ch  
       }
     }
  return(result)
}

//============================================================================
// Create a default instance of the object
// parm1:	Amount	- required
// parm2:	Rate		- required
// parm3:   	Term		- required
// parm4:	Payment
// parm5:	Interest
// parm6:	Frequency	- required
// parm7:	Periods
// return value:	did we create the oebject?
//============================================================================
function Create() {
   Mortgage = new Loan(50000, 8, 30, 0, 0, "Monthly", 0 );
   return(true)
}

//============================================================================
// Set the properties of the object based on form inputs
// oView: 		form elements
// return value:	did it get and set the properties?
//============================================================================
function SetValue(oView) {
   // get the properties mapped from the form
   Mortgage.Amount = makeNumber(oView.AMOUNT.value);
   // works like a masked edit
   oView.AMOUNT.value = calcRound(Mortgage.Amount);
   Mortgage.Rate = makeNumber(oView.RATE.value);
   Mortgage.Term = get_selection(oView.YEARS);
   Mortgage.Frequency = get_selection(oView.FREQUENCY);
   // set the number of periods
   Mortgage.calcPeriods();
   // set the monthly payment
   Mortgage.calcPayment();
   // set the total interest due
   Mortgage.calcInterest();
   // update the form view
   Show()
   return(true)
}

//============================================================================
// Amortize is called at the end of the controler loop and checks to see
// if the amortize button was pushed
// oForm: 		form elements
// oBtn:  		the name of the button that was pressed
// return value:	did we select the Amortize button?
//============================================================================
function Amortize(oForm, oBtn) {
   if (oBtn.name == "cmdCalc") {
      return(false)
   }else{
/*
   if (confirm("An Amortization Table calculates the periodic payment breakdown for each specific category listed.")) {
*/
      // need to create the table before you can show it
      createRecords();
      // display the table
      showAmortize(oForm);
      return(true)
    }
  return(false)
}

//============================================================================
// create Records computes the values associated with the Amortzation of a Mortgage Loan and 
// adds those values to a record in the Amortization table container array
// return value:	did we calculate all values to display in the Amortization?
//============================================================================
function createRecords(){
   // re-init the record counter and container array
   rec = 0;
   oTable = new Array();
   // initialize variables
   var currInt = 0;
   var currPrin = 0;
   prevBalance = Mortgage.Amount;
   InterestRate = ( Mortgage.Rate /100) / Mortgage.Periods;
   MonthlyPayment = Mortgage.Payment;
   //currStart = '1997';
   currStart = get_selection(document.MORTGAGE.START);  
   // let the loops begin
   for(i=1;i<=30;i++) {
      for(j=1;j<=Mortgage.Periods;j++) {
         periodInt = prevBalance * InterestRate;
         periodPrin = MonthlyPayment - periodInt;
         currBal = prevBalance - periodPrin;
         currInt += periodInt;
         currPrin += periodPrin;
         prevBalance = currBal;
      }
      if( currBal <= 0 ){ 
         currBal = 0;
      }
      // set the parameters
      Year = currStart;
      Interest = calcRound(currInt);
      Principle = calcRound(currPrin);
      Balance = calcRound(currBal);
      // increment the container 
      rec++
      // add a record to the table
      addRecord(Year, Interest, Principle, Balance);
      // re-init the private variables
      currInt = 0;
      currPrin = 0;
      currStart = parseInt(currStart);
      currStart += 1;
      // are we done?
      if(currBal<=0) {
         return(true)
      }       
   }
   return (true)
}

//============================================================================
// Build a text string with a header, the table and a footer in HTML then
// diplay the table in a new window with only the menu active.
// oForm: 		form elements
// return value:	did we display the Amortization?
//============================================================================
function showAmortize(oForm) {

   // create the header

   text = ("<HEAD><TITLE>Amortization Table</TITLE></HEAD>");

   text = (text +"<BODY BGCOLOR =  "+bColor+"><BR>");

   text = (text +"<H2 ALIGN=CENTER><FONT FACE=ARIAL COLOR="+fColor+">Amortization Table</FONT></H2>");

   text = (text +"<UL><FONT FACE=ARIAL COLOR="+fColor+"> <b>Mortgage Amount:</b> </FONT>" +calcRound(Mortgage.Amount));

   text = (text +"<BR><FONT FACE=ARIAL COLOR="+fColor+">   <b>Interest Rate:</b> </FONT>" + Mortgage.Rate + " %");

   text = (text +"<BR><FONT FACE=ARIAL COLOR="+fColor+"> <b>Mortgage Length:</b> </FONT>" + Mortgage.Term + " Years");

   text = (text +"<BR><FONT FACE=ARIAL COLOR="+fColor+"> <b>Payment Frequency:</b> </FONT>" + Mortgage.Frequency + "  </UL>");

   text = (text +"<BR><CENTER><table border='1' width='100%' cellspacing='0' cellpadding='2' bordercolor='#003300'>");

   text = (text +"<TR><TD ALIGN=CENTER BGCOLOR="+fColor+"><FONT FACE=ARIAL COLOR="+bColor+"><B>Year</B></FONT></TD><TD ALIGN=RIGHT BGCOLOR="+fColor+"><FONT FACE=ARIAL COLOR="+bColor+"><B>Interest&nbsp;</B></FONT></TD><TD ALIGN=RIGHT BGCOLOR="+fColor+"><FONT FACE=ARIAL COLOR="+bColor+"><B>Principal&nbsp;</B></FONT></TD><TD ALIGN=RIGHT BGCOLOR="+fColor+"><FONT FACE=ARIAL COLOR="+bColor+"><B>Balance&nbsp;</B></FONT></TD></TR>\n");
     
   // create the Amortization table text by looping through a CONTAINER ARRAY 
   for (var q=1; q<oTable.length;q++) {

      text = (text +"<TR><TD ALIGN=CENTER>"+ oTable[q].Year +"</TD><TD ALIGN=RIGHT>"+ oTable[q].Interest +"&nbsp;</TD><TD ALIGN=RIGHT>"+ oTable[q].Principle +"&nbsp;</TD><TD ALIGN=RIGHT>"+ oTable[q].Balance +"&nbsp;</TD></TR>");

   }   

   // create the footer  
   text = (text +"</TABLE></CENTER>");

   // Create a new window to display the results
 oWindow=window.open("","displayWindow","toolbar=no,width=500,height=500,directories=no,status=no,scrollbars=yes,resize=yes,menubar=yes");

   oWindow.document.write(text);

   oWindow.document.close();

   return(true)

}


//============================================================================
// Collection Constructor, a custom object to act as an array but provide
// more flexibility in the future.
//============================================================================
function Collection(item1, item2, item3, item4, item5, item6) {
   this.item1 = item1;
   this.item2 = item2;
   this.item3 = item3;
   this.item4 = item4;
   this.item5 = item5;
   this.item6 = item6;
}

//============================================================================
// Loan Constructor, defines what the Loan object will look like
// and how it will behave. 
//============================================================================
function Loan(Amount, Rate, Term, Payment, Interest, Frequency, Periods ) {
   this.Amount = Amount;
   this.Rate = Rate;
   this.Term = Term;
   this.Payment = Payment;
   this.Interest = Interest;
   this.Frequency = Frequency;
   this.Periods = Periods;
   this.calcPeriods = calcPeriods;
   this.calcPayment = calcPayment;
   this.calcInterest = calcInterest;
}

//============================================================================
// Loan object method that calculates the monthly payment for a mortgage loan in the US
//============================================================================

function calcPayment() {
   this.Payment = (this.Amount*((this.Rate/(1200))/(1-(Math.pow(1+(this.Rate/(1200)),((this.Term*12)*-1))))));
  // handle bi-weekly 
  if ( this.Periods == 26 ){
      this.Payment = this.Payment / 2;
   }
}

//============================================================================
// Loan object method that calculates the interest portion of a loan
//============================================================================
function calcInterest() {
   this.Interest = ((this.Payment*(this.Term*this.Periods))-this.Amount);
}

//============================================================================
// Loan object method that translates a selection drop down to a value
//============================================================================
function calcPeriods() {
   if (this.Frequency=="Monthly") { this.Periods=12 } else { this.Periods=26 }
}

//============================================================================
// Loan object method that shows the calculated amounts
//============================================================================
function Show(oView) {
   document.MORTGAGE.PAYMENT.value = calcRound(Mortgage.Payment)
   document.MORTGAGE.INTEREST.value = calcRound(Mortgage.Interest)
}

//============================================================================
// oRecord Constructor, defines what the Amortzation record looks like 
//============================================================================
function oRecord(Year, Interest, Principle, Balance){
   this.Year = Year;
   this.Interest = Interest;
   this.Principle = Principle;
   this.Balance = Balance;
}

//============================================================================
// addRecord defines how a record gets added to the container array
//============================================================================
function addRecord(Year, Interest, Principle, Balance){
   oTable[rec] = new oRecord(Year, Interest, Principle, Balance);
}

//============================================================================
// select_item Constructor, used to retrive the selected item from the dropdown 
// control on a form.
// name: 		form element name
// value:  		the value of the options that was selected
// return value:	selected item
//============================================================================
function select_item(name, value) {  
   this.name = name;
   this.value = value;
}

//============================================================================
// Common routine to retrieve the selected value from the drop down object
// select_object:	a drop down from control
// return value:	the selected objects name
//============================================================================
function get_selection(select_object) {   
   contents = new select_item();
   for(var i=0;i<select_object.options.length;i++)
      if(select_object.options[i].selected == true) {
        contents.name = select_object.options[i].text;
        contents.value = select_object.options[i].value;
      }      
   return(contents.name)
}

//============================================================================
// Common routine for rounding that also formats the results into US currency
// num: 		a number
// return value:  result is rounded and formated for currency $999,999.00
//============================================================================
function calcRound(num) {
   result="$"+Math.floor(num)+"." ;
   n = result.length;
   if (num>1000 && num<999999) {  
     result="$"+result.substring(1,n-4)+","+result.substring(n-4,n);
   }
   if (num>1000000) {  
     result = "$"+result.substring(1,n-7)+","+result.substring(n-7,n-4)+","+result.substring(n-4,n);
   }
   var cents=100*(num-Math.floor(num))+0.5;
   result += Math.floor(cents/10);
   result += Math.floor(cents%10);
   return(result)
}


//============================================================================
// A page specific routine to set the initial state when the page is reloaded.
//============================================================================
function setfocus() {   
   document.MORTGAGE.AMOUNT.focus();
   document.MORTGAGE.AMOUNT.select();
}

// -->