//Pentawave modification on 10/28/99
//JLH - added the following validation routine for the price, downpayment, tradein, and amount fields

if (window.focus) self.focus();
// check for IE3
var isIE3 = (navigator.appVersion.indexOf('MSIE 3') != -1);

// object definition
function validation(realName, formEltName, eltType, checkData, format) {
  this.realName = realName;
  this.formEltName = formEltName;
  this.eltType = eltType;
  this.checkData = checkData;
  this.format = format;
}

// create objects for validation here:

var price = new validation('Price', 'price', 'text', 'isValNumber(str)', '###,###.00 (up to $999,999)');
var downpayment = new validation('Down Payment', 'downpayment', 'text', 'isValNumber(str)', '###,###.00 (up to $999,999)');
var tradein = new validation('Trade-In Value', 'tradein', 'text', 'isValNumber(str)', '###,###.00 (up to $999,999)');
var amount = new validation('Amount Financed', 'amount', 'text', 'isValNumber(str)', '###,###.00 (up to $999,999)');

//validate all at once, or one error at a time (causes resubmit cycle)
var allAtOnce = true;

//set alerts for text and other fields
var beginRequestAlertForText = "Please include ";
var beginRequestAlertGeneric = "Please choose ";
var endRequestAlert = ".";
var beginInvalidAlert = " is an invalid ";
var endInvalidAlert = "!";
var beginFormatAlert = "  Use this format: ";

//field validation functions

function isValNumber(str) {
	var dollar = "";
	var newdoll = "";
	var sgn = str.indexOf("$")
	var dot = str.indexOf(".")
	var thous = str.indexOf(",")  
	var startpnt = 0
	if (sgn != -1) {
		startpnt = 1
		}
	dollar = str.slice(startpnt);
	if (dot != -1) {
		for (k=dot+1; k<dollar.length; k++) {
			if (dollar.charAt(k) == ".") { 
			newdoll = "invalid";
			}
		}
		if (newdoll == "invalid") {
		dollar = newdoll;
		} 
	}
	if (thous != -1) {
		newdoll = "";
		for (k=0; k<dollar.length; k++) {
			if (dollar.charAt(k) != ",") { 
			newdoll = newdoll + dollar.charAt(k);
			}
		}
		if (newdoll != "") {
		dollar = newdoll;
		} 
	}
	var dollarStringtoInt = parseFloat(dollar) ;
	var dollarConv = dollarStringtoInt.toString() ;
	if (dollarConv != "NaN" && (dollar.substring(dollar.length-1) != "0")) {
		if (dollarConv == "NaN" || (dollarConv.length < dollar.length))
		{ return false }
	}
	if ((dollarStringtoInt > 999999) || (dollarStringtoInt < 0))
	{ return false }
	else {
	 return true; 
	}
}

//  validation function (loop through elements, test those in array)
function validateForm(oForm) {
  var formEltName = "";
  var formObj = "";
  var str = "";
  var realName = "";
  var alertText = "";
  var firstMissingElt = null;
  var hardReturn = "\r\n";

	//set variables for fields to be evaluated
	var elts = new Array(price,downpayment,tradein,amount);
  for (i=0; i<elts.length; i++) 
  {
		formEltName = elts[i].formEltName;
		realName = elts[i].realName;
	for (j=0; j<oForm.length; j++) 
	{
	if (formEltName == (oForm[j].name.toLowerCase())) 
	{
			 test = "oForm[j]";
		 formObj = eval(test);
		 test2 = test + ".value";
		 if (elts[i].eltType == "text") {
		   str = formObj.value;
		   if (eval(elts[i].checkData)) continue;
		   if (str == "") {
			 if (allAtOnce) {
			   alertText += beginRequestAlertForText + realName + endRequestAlert + hardReturn;
			   if (firstMissingElt == null) {firstMissingElt = formObj};
			 } else {
			   alertText = beginRequestAlertForText + realName + endRequestAlert + hardReturn;
			   alert(alertText);
			 }
		   } else {
			 if (allAtOnce) {
			   alertText += str + beginInvalidAlert + realName + endInvalidAlert + hardReturn;
			 } else {
			   alertText = str + beginInvalidAlert + realName + endInvalidAlert + hardReturn;
			 }
			 if (elts[i].format != null) {
			   alertText += beginFormatAlert + elts[i].format + hardReturn;
			 }
			 if (allAtOnce) {
			   if (firstMissingElt == null) {firstMissingElt = formObj};
			 } else {
			   alert(alertText);
			 }
		   }
		 } else {
		   if (eval(elts[i].checkData)) continue;
		   if (allAtOnce) {
			 alertText += beginRequestAlertGeneric + realName + endRequestAlert + hardReturn;
			 if (firstMissingElt == null) {firstMissingElt = formObj};
		   } else {
			 alertText = beginRequestAlertGeneric + realName + endRequestAlert + hardReturn;
			 alert(alertText);
		   }
		 }
		if (!isIE3) {
			var goToObj = (allAtOnce) ? firstMissingElt : formObj;
			if (goToObj.select) goToObj.select();
			if (goToObj.focus) goToObj.focus();
		}
		 if (!allAtOnce) {return false};
	}
	}
  }
  if (allAtOnce) {
	if (alertText != "") {
	  alert(alertText);
	  return false;
	}
  } 
  return true; 
}

<!--
/* hide this code from non scriptable browsers

LOAN LOAN CALCULATOR
COPYRIGHT NOTICE                                                         
Copyright 1997, 1998 Steven D. Witkop  All Rights Reserved.
This Javascript "Loan calculator" Script  may be used and modified free of charge by anyone
so long as this copyright notice and the comments above remain intact.  By using this code you agree 
to indemnify Steven D. Witkop from any liability that might arise from it's use.   

Selling the code for this program without prior written consent is  expressly forbidden.  In other 
words, please ask first before you try and  make money off of my program.  

Obtain permission before redistributing this software over the Internet or in any other medium. 
In all cases copyright and header must remain intact

LANGUAGE: JavaScript 1.1 compliant

PATTERN: MVC

*/



// initilize page variables

window.onerror=null
var bState = true;
var rec = 0;
var oTable = new Array();

//JLH varible for rounding fix
var numFixAmt = 0;

// deactivated by Pentawave. Stylesheets used
// 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 = '#75A485' //purple
//var bimage = './images/bkgd2.jpg' //purple
// var fColor = '#75A485' // green

// var bColor = 'WHITE'  // '#FFFFFF' 
// var fColor = 'PURPLE' // '#75A485'


// 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) {
   //JLH added line below for validation function
   bState = validateForm(oForm);
   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 = ""
//JLH added variable for numeric return value
var jresult = 0;
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  
       }
     }
  //JLH fix: this function doesn't return a number, it returns a string
  jresult = parseFloat(result);
  //JLH fix2: if the result is not a number, return 0
	if (isNaN(jresult)) {
	jresult = 0;
	}
  //return(result)
  return(jresult)
}
//============================================================================
// 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) {
   //lines below customized by Pentawave, tsf 9/14/99
   Mortgage.Price =makeNumber(oView.PRICE.value);
	oView.PRICE.value= calcRound(Mortgage.Price);
   Mortgage.Downpayment = makeNumber(oView.DOWNPAYMENT.value);
    oView.DOWNPAYMENT.value=calcRound(Mortgage.Downpayment);
   Mortgage.Tradein = makeNumber(oView.TRADEIN.value);
    oView.TRADEIN.value=calcRound(Mortgage.Tradein)
   //end customizatiom
   
   //JLH added the following modified code from the original developer's SetValue function
   Mortgage.Amount = makeNumber(oView.AMOUNT.value);
   oView.AMOUNT.value = calcRound(Mortgage.Amount);
   
   Mortgage.Rate = parseFloat(oView.RATE.value);
   oView.RATE.value = Mortgage.Rate;
   
   //Mortgage.Term = makeNumber(oView.YEARS.value);
   Mortgage.Term = get_selection(oView.YEARS);
   Mortgage.Term = makeNumber(Mortgage.Term);

   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 shows the interest paid during each year of the term.")) {
      // 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;
   
  //CHANGED BY PENTAWAVE TO REFLECT CURRENT YEAR
  //currStart = get_selection(document.MORTGAGE.START);
   // currStart = '1999';
	//adjusted because getYear returns 2 digits prior to 2000;
   currStart = new Date();
   currStart = currStart.getYear();
   if(currStart==99){
      currStart=1999;
	  }


   // let the loops begin
   //JLH modified by developer
   //for(i=1;i<=10;i++) {
    for(i=1;i<=Mortgage.Term;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);
      Principal = calcRound(currPrin);
      Balance = calcRound(currBal);
      // increment the container 
      rec++
      // add a record to the table
      addRecord(Year, Interest, Principal, 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
   //JLH text remove session variable, add html tags = ("<HEAD><TITLE> Amortization Table</TITLE><LINK REL=STYLESHEET HREF='publisher_files/autochooser.css'></HEAD>");
   text = ("<HTML><HEAD><TITLE> Amortization Table</TITLE></HEAD>");
   text = (text +"<BODY><BR><BR>");
   //JLH session value will be lost: text = (text +"<H2 ALIGN=CENTER> Amortization Table</H2>");
   text = (text +"<H2 ALIGN='CENTER'> Amortization Table</H2>");
   text = (text +"<UL><FONT SIZE='-1'>The following table is based on the information entered in the calculator form.<BR>");
   text = (text +"Rounding may slightly affect the accuracy of some yearly totals.</FONT></UL>");
   text = (text +"<UL><FONT SIZE='+1'> Loan Amount: </FONT>" +calcRound(Mortgage.Amount));
   text = (text +"<BR><FONT SIZE='+1'> Interest Rate: </FONT>" + Mortgage.Rate + "%");
   text = (text +"<BR><FONT SIZE='+1'> Loan Length: </FONT>" + Mortgage.Term + " Years");
   text = (text +"<BR><FONT SIZE='+1'> Payment Frequency: </FONT>" + Mortgage.Frequency + "  </UL>");
   text = (text +"<BR><CENTER><table border='1' width='100%'>");
   text = (text +"<TR><TD ALIGN='CENTER'><B>Anniversary</B></FONT></TD><TD ALIGN='RIGHT'><B>Interest&nbsp;</B></TD><TD ALIGN='RIGHT'><B>Principal&nbsp;</B></TD><TD ALIGN='RIGHT'><B>Balance&nbsp;</B></TD></TR>\n");
   
   // create the Amortization table text by looping through a CONTAINER ARRAY 
   //PENTAWAVE added date to indicate year shown in table not calendar year
   dToday=new Date;
   //need to add 1 to month, Jan is 0?
   nMonth=dToday.getMonth()+1;

   strDate=nMonth + "/" + dToday.getDate() + "/";
    for (var q=1; q<oTable.length;q++) {
	  //PENTAWAVE corrected date for year 2000
	  strNextYear = oTable[q].Year + 1;
      if(strNextYear < 2000){strNextYear = strNextYear + 1900;}
	  //alert(strNextYear);
      text = (text +"<TR><TD ALIGN='CENTER'>"+ strDate + strNextYear +"</TD><TD ALIGN='RIGHT'>"+ oTable[q].Interest +"&nbsp;</TD><TD ALIGN='RIGHT'>"+ oTable[q].Principal +"&nbsp;</TD><TD ALIGN='RIGHT'>"+ oTable[q].Balance +"&nbsp;</TD></TR>");
   }
   // create the footer  
   //text = (text +"</TABLE></CENTER>");
   
   //JLH add button to close window -- and closing html tags
    text = text +"<TR><TD ALIGN='CENTER' colspan=4><a href='javascript:void(0);' onClick='javascript: window.close();'><img src=images/close.gif alt='Close Window' border='0'></a></TD></TR></TABLE></CENTER></BODY></HTML>"; 

   // Create a new window to display the results
   oWindow=window.open('','displayWindow','toolbar=no,width=500,height=400,directories=no,status=no,scrollbars=yes,resize=no,menubar=no');
   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() {
	//JLH following declaration was added by the original developer
     var reduce;
   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;
     //JLH following three lines were modified by the original developer
   	 reduce = this.Payment / 26;
     this.Payment = this.Payment / 2;
     this.Payment = this.Payment - reduce;
   }
}
//============================================================================
// 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, Principal, Balance){
   this.Year = Year;
   this.Interest = Interest;
   this.Principal = Principal;
   this.Balance = Balance;
}
//============================================================================
// addRecord defines how a record gets added to the container array
//============================================================================
function addRecord(Year, Interest, Principal, Balance){
   oTable[rec] = new oRecord(Year, Interest, Principal, 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);
   // handle special case - JLH this was added by the original developer
   n = result.length;
   if ( n - result.indexOf('.') > 3 ){
      result = "$"+result.substring(1,n-1);
   }     
   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();
}

//============================================================================
// Pentawave added function to populate amount financed form object from downpayment, 
// trade-in value and price
// JLH - added maxlength of 11 to price, downpayment, tradein, and amount fields
//============================================================================
function setAmount() {   
   //JLH initialize Mortgage value
   if (Create()){
	//JLH set intial price value in case of null
	if (document.MORTGAGE.PRICE.value=="") {
	document.MORTGAGE.PRICE.value = 0;
	}
	numSalesTax = makeNumber(document.MORTGAGE.SALESTAX.value);
	numPrice = makeNumber(document.MORTGAGE.PRICE.value);
	numDownPayment = makeNumber(document.MORTGAGE.DOWNPAYMENT.value);
	numTradeIn = makeNumber(document.MORTGAGE.TRADEIN.value);
   
	// JLH fix rounding problem
	//document.MORTGAGE.AMOUNT.value = (numPrice * (1 + (numSalesTax/100)))- numDownPayment - numTradeIn;
	numFixAmt = (numPrice + (numPrice*(numSalesTax/100)))- numDownPayment - numTradeIn;
	document.MORTGAGE.AMOUNT.value = calcRound(numFixAmt);
	Mortgage.Amount = numFixAmt;
   }
}

// unhide 
// -->
