// 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 = '#004000' //green
var gColor = '#CB301F' //red
// var fColor = '#CB301F' // red

// var bColor = 'WHITE'  // '#FFFFFF'
// var fColor = 'PURPLE' // '#000080'


// 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
	  nperiods = 0;
       }

     }

  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)

   }

   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 = '2000';
   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+">");

   text = (text +"<FONT face=Arial COLOR="+gColor+"><B>Amortization Table</B></FONT>");

   text = (text +"<BR><BR><FONT face=Tahoma, Verdana style=font-size:10pt>The following table is based on the information entered in the calculator form.</FONT>");

   text = (text +"<BR><BR><FONT face=Tahoma, Verdana style=font-size:10pt COLOR="+fColor+"><b>Mortgage Amount:</B> </FONT>" +calcRound(Mortgage.Amount));

   text = (text +"<BR><FONT face=Tahoma, Verdana style=font-size:10pt COLOR="+fColor+"><b>Interest Rate:</B> </FONT>" + Mortgage.Rate + " %");

   text = (text +"<BR><FONT face=Tahoma, Verdana style=font-size:10pt COLOR="+fColor+"><b>Mortgage Length:</B> </FONT>" + Mortgage.Term + " Years");

   text = (text +"<BR><FONT face=Tahoma, Verdana style=font-size:10pt COLOR="+fColor+"><b>Payment Frequency:</B> </FONT>" + Mortgage.Frequency + "");

   text = (text +"<br><BR><CENTER><table border='1' width='100%' cellpadding='3' cellspacing='0' noshade>");

   text = (text +"<TR><TD ALIGN=CENTER BGCOLOR="+fColor+"><FONT face=Arial style=font-size:10pt COLOR="+bColor+"><B>Year</B></FONT></TD><TD ALIGN=RIGHT BGCOLOR="+fColor+"><FONT face=Arial style=font-size:10pt COLOR="+bColor+"><B>Interest&nbsp;</B></FONT></TD><TD ALIGN=RIGHT BGCOLOR="+fColor+"><FONT face=Arial style=font-size:10pt COLOR="+bColor+"><B>Principal&nbsp;</B></FONT></TD><TD ALIGN=RIGHT BGCOLOR="+fColor+"><FONT face=Arial style=font-size:10pt 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><FONT face=Tahoma, Verdana style=font-size:8pt>"+ oTable[q].Year +"</font></TD><TD ALIGN=RIGHT><FONT face=Tahoma, Verdana style=font-size:8pt>"+ oTable[q].Interest +"</FONT></TD><TD ALIGN=RIGHT><FONT face=Tahoma, Verdana style=font-size:8pt>"+ oTable[q].Principle +"</FONT></TD><TD ALIGN=RIGHT><FONT face=Tahoma, Verdana style=font-size:8pt>"+ oTable[q].Balance +"</FONT></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=300,directories=no,status=no,scrollbars=yes,resize=no,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();
}

function Round(N) {	// Round a number 2 decimal places
	return Math.round(N*100)/100;
}

function jumpBox(list) {
   location.href = list.options[list.selectedIndex].value
   }
function computeForm(form)  {
    var i = form.interest.value;
    if (i > 1.0) {i = form.interest.value / 100} else {i = form.interest.value};
    i /= 52;
   var ma = eval(form.moAdd.value);
   var prin = eval(form.principal.value);
   var pmts = eval(form.payments.value * 52);
   var count = 0;
       while(count < pmts) {
        newprin = prin + ma;
        prin = (newprin * i) + eval(prin + ma);
        count = count + 1;
      }

    form.fv.value = Round (prin);
		var totinv = eval(count * ma) + eval(form.principal.value);
    form.totalint.value = Round (eval(prin - totinv));
}

function clearForm(form)

{
    form.payments.value = "";
    form.interest.value = "";
    form.principal.value = "";
    form.moAdd.value = "";
}


// unhide