// Comments:
// In this code,
// f.uXxx.value refers to the value of a form field which name is "Xxx"
// f.elements['Xxx'] does the same, but the field name may be dynamically generated.
// vwXxx refers to a value from the configuration document. It is provided as a javascript variable of the same name inside the Notes form.
// The vwXxx variables are read inside the page "web financial parameters.js"
// showXxx refers to a SPAN element that displays the value of a form field with the name f.uXxx

// ===== BEGIN namics functions =====
// Global variables
var f = document.finForm;	// the form for computation, the same on every step page
var mort = [ [0,0], [0,0], [0,0] ];  // internal array for mortgages: max 3 products, each has max 2 mortgages

// ----- BEGIN helper functions -----
// Mathematical Mod function
function Mod(a, b) 
{ 
	return a-Math.floor(a/b)*b;
}


// Mathematical Div function
function Div(a, b) 
{ 
	return Math.floor(a/b) 
}


// helper function for getFormattedAmount: reverse a number
function rev(num) 
{
	return num.split('').reverse().join('');
}

// helper function for sorting a numerical array
function Numsort(a,b)
{ 
	return a-b; 
}

// format a money amount (999999999,99) to the syntax 999'999'999,99
function getFormattedAmount(numTotal) 
{
	if ((!numTotal) || (numTotal == "") || isNaN(numTotal)) numTotal = 0;
	numTotal = Math.round(numTotal * 1);
	numTotal = "" + numTotal;
	numSplitted = numTotal.split('.');
	// behind decimal point
	numDec = numSplitted[1];
	if(numDec == "" || (isNaN(numDec)))
		numDec = ""; // 00
	else
		numDec = roundTo2Digits(numDec);

	// before decimal point
	num = numSplitted[0];		
	num = rev(num);
	num = num.replace(/(\d{3})/g, '$1\'');
	num = rev(num);
	if(num.charAt(0) == '\'') 
		num = num.substr(1);

	// format and return the result
	// return num + "," + numDec;
	return num
}


// Get the current value of a radio button (single or in a group)
function getRadioValue (radioButtonOrGroup) 
{
	var value = null;
	if (radioButtonOrGroup.length) 
	{ 
		// group 
		for (var b = 0; b < radioButtonOrGroup.length; b++)
		if (radioButtonOrGroup[b].checked)
			value = radioButtonOrGroup[b].value;
	}
	else if (radioButtonOrGroup.checked)
		value = radioButtonOrGroup.value;
	return value;
}


// Round a given number to two digits
function roundTo2Digits(ival)
{
	return (Math.round(ival*100)) / 100;
}


// Send a debugging message (e.g. show as window status)
function debugMsg(content)
{
	window.status=content;
}


// Populate an HTML form field with a number value (first we ensure it IS a number, then we set the value)
function setFieldToNumValue(fieldName, valueStr)
{
	fieldItem = f.elements[fieldName];
	// Does a field of this name exist?
	if(fieldItem)
	{
		fieldItem.value = valueStr * 1;
	}
	else
 		debugMsg("ERROR: Field "+fieldName+" does not exist: "+fieldItem);
}


// populate a computed field (a span) with a value
// We use the innerHTML function to dynamically put text inside a page.
function writeToID(idName, content)
{
  el = document.getElementById(idName);
  if(el)
  {
    el.innerHTML = content;
  }
}


// Check if a field's value is a number entry (is not empty and is a number)
function isValidNumber(numVal)
{
	return (!isNaN(numVal) && !(numVal == ""));
}

// ----- END helper functions -----


// ----- BEGIN lookup functions -----


// ------------------------------------------------------------
// getInterestRateForProduct
// (function for step/screen 1)
// Return the correct interest rate for a product page ID.
// The interest rate values are pulled from the global javascript variables that derive from the configuration documents.
// ------------------------------------------------------------
function getInterestRateForProduct(productId)
{
	switch(productId)
	{
		case "start1" : return [vwZinsStartHypo[0],vwZinsStartHypo[1]];
		case "start2" : return [vwZinsStartHypo[2],vwZinsStartHypo[3]];
		case "var" : return vwZinsVarHypo;
		case "fest1" : return vwZinsFestHypo[0];
		case "fest2" : return vwZinsFestHypo[1];
		case "fest3" : return vwZinsFestHypo[2];
		case "fest4" : return vwZinsFestHypo[3];
		case "fest5" : return vwZinsFestHypo[4];
		case "fest6" : return vwZinsFestHypo[5];
		case "fest7" : return vwZinsFestHypo[6];
		case "fest8" : return vwZinsFestHypo[7];
		case "fest9" : return vwZinsFestHypo[8];
		case "fest10" : return vwZinsFestHypo[9];
		case "fest11" : return vwZinsFestHypo[10];
		case "fest12" : return vwZinsFestHypo[11];
		case "fest13" : return vwZinsFestHypo[12];
		case "fest14" : return vwZinsFestHypo[13];
		case "fest15" : return vwZinsFestHypo[14];
		case "geldmitza13" : return vwZinsGeldHypoVar1Einstieg[0];
		case "geldmitza15" : return vwZinsGeldHypoVar1Einstieg[1];
		case "geldmitza18" : return vwZinsGeldHypoVar1Einstieg[2];
		case "geldmitza23" : return vwZinsGeldHypoVar2Einstieg[0];
		case "geldmitza25" : return vwZinsGeldHypoVar2Einstieg[1];
		case "geldmitza28" : return vwZinsGeldHypoVar2Einstieg[2];
		case "geldohneza" : return vwZinsGeldHypoOhneZA;
		case "zinssatzszenario" : return false; // we enter no interest rate for this product
	}
}


// ------------------------------------------------------------
// getMinimalProductAmount
// (function for step/screen 1)
// Some products only support minimal money amounts
// Get the minimal money amount from the configuration document and return it.
// ------------------------------------------------------------
function getMinimalProductAmount(productId)
{
	switch(productId)
	{
		case "start1" : return vwMinStartHypo[0];
		case "start2" : return vwMinStartHypo[1];
		case "var" : return vwMinVarHypo;
		case "fest1" : return vwMinFestHypo;
		case "fest2" : return vwMinFestHypo;
		case "fest3" : return vwMinFestHypo;
		case "fest4" : return vwMinFestHypo;
		case "fest5" : return vwMinFestHypo;
		case "fest6" : return vwMinFestHypo;
		case "fest7" : return vwMinFestHypo;
		case "fest8" : return vwMinFestHypo;
		case "fest9" : return vwMinFestHypo;
		case "fest10" : return vwMinFestHypo;
		case "fest11" : return vwMinFestHypo;
		case "fest12" : return vwMinFestHypo;
		case "fest13" : return vwMinFestHypo;
		case "fest14" : return vwMinFestHypo;
		case "fest15" : return vwMinFestHypo;
		case "geldmitza13" : return vwMinGeldHypoMitZA[0];
		case "geldmitza15" : return vwMinGeldHypoMitZA[0];
		case "geldmitza18" : return vwMinGeldHypoMitZA[0];
		case "geldmitza23" : return vwMinGeldHypoMitZA[1];
		case "geldmitza25" : return vwMinGeldHypoMitZA[1];
		case "geldmitza28" : return vwMinGeldHypoMitZA[1];
		case "geldohneza" : return vwMinGeldHypoOhneZA;
		case "zinssatzszenario" : return false;
	}
}


// ------------------------------------------------------------
// getInfoPageIdForProduct
// (function for step/screen 1)
// Get the document ID of the information page for a given product. 
// The IDs are stored in the configuration document and are provided as global Javascript variables.
// ------------------------------------------------------------
function getInfoPageIdForProduct(productId)
{
	switch(productId)
	{
		case "start1" : return vhPageIDStartHypo;
		case "start2" : return vhPageIDStartHypo;
		case "var" : return vhPageIDVarHypo;
		case "fest1" : return vhPageIDFestHypo;
		case "fest2" : return vhPageIDFestHypo;
		case "fest3" : return vhPageIDFestHypo;
		case "fest4" : return vhPageIDFestHypo;
		case "fest5" : return vhPageIDFestHypo;
		case "fest6" : return vhPageIDFestHypo;
		case "fest7" : return vhPageIDFestHypo;
		case "fest8" : return vhPageIDFestHypo;
		case "fest9" : return vhPageIDFestHypo;
		case "fest10" : return vhPageIDFestHypo;
		case "fest11" : return vhPageIDFestHypo;
		case "fest12" : return vhPageIDFestHypo;
		case "fest13" : return vhPageIDFestHypo;
		case "fest14" : return vhPageIDFestHypo;
		case "fest15" : return vhPageIDFestHypo;
		case "geldmitza13" : return vhPageIDGeldHypoMitZAV13;
		case "geldmitza15" : return vhPageIDGeldHypoMitZAV15;
		case "geldmitza18" : return vhPageIDGeldHypoMitZAV18;
		case "geldmitza23" : return vhPageIDGeldHypoMitZAV23;
		case "geldmitza25" : return vhPageIDGeldHypoMitZAV25;
		case "geldmitza28" : return vhPageIDGeldHypoMitZAV28;
		case "geldohneza" : return vhPageIDGeldHypoOhneZA;
		case "zinssatzszenario" : return vhPageIDZinsSatzSzenario;
	}
}


// ------------------------------------------------------------
// getInfoLinkTextForProduct
// (function for step/screen 1)
// Get the link text to be displayed for a given product. 
// The link texts are stored in the configuration document and are provided as global Javascript variables.
// ------------------------------------------------------------
function getInfoLinkTextForProduct(productId)
{
	switch(productId)
	{
		case "start1" : return vhStartHypoInfoLinkText;
		case "start2" : return vhStartHypoInfoLinkText;
		case "var" : return vhVarHypoInfoLinkText;
		case "fest1" : return vhFestHypoInfoLinkText;
		case "fest2" : return vhFestHypoInfoLinkText;
		case "fest3" : return vhFestHypoInfoLinkText;
		case "fest4" : return vhFestHypoInfoLinkText;
		case "fest5" : return vhFestHypoInfoLinkText;
		case "fest6" : return vhFestHypoInfoLinkText;
		case "fest7" : return vhFestHypoInfoLinkText;
		case "fest8" : return vhFestHypoInfoLinkText;
		case "fest9" : return vhFestHypoInfoLinkText;
		case "fest10" : return vhFestHypoInfoLinkText;
		case "fest11" : return vhFestHypoInfoLinkText;
		case "fest12" : return vhFestHypoInfoLinkText;
		case "fest13" : return vhFestHypoInfoLinkText;
		case "fest14" : return vhFestHypoInfoLinkText;
		case "fest15" : return vhFestHypoInfoLinkText;
		case "geldmitza13" : return vhGeldHypoMitZAV13InfoLinkText;
		case "geldmitza15" : return vhGeldHypoMitZAV15InfoLinkText;
		case "geldmitza18" : return vhGeldHypoMitZAV18InfoLinkText;
		case "geldmitza23" : return vhGeldHypoMitZAV23InfoLinkText;
		case "geldmitza25" : return vhGeldHypoMitZAV25InfoLinkText;
		case "geldmitza28" : return vhGeldHypoMitZAV28InfoLinkText;
		case "geldohneza" : return vhGeldHypoOhneZAInfoLinkText;
		case "zinssatzszenario" : return vhZinsSatzSzenarioInfoLinkText;
	}
}

// ----- END lookup functions -----

// ----- BEGIN field value checking functions -----


// ------------------------------------------------------------
// checkMinBankFin
// (function for step/screen 1)
// Check if the desired amount for the bank financing need exceeds the pre-defined minimum.
// If it does, function returns TRUE, if not, it throws an alert and returns FALSE.
// If the input value is not a valid number, FALSE is returned.
// The minimum is defined inside the configuration document.
// ------------------------------------------------------------
function checkMinBankFin()
{
  if(isValidNumber(f.uBankFin.value))
  {
    if( ((f.uBankFin.value * 1) < (vwMinBankFin* 1)) && f.uFinBedarf.value != "0" )
    {
      //alert('Die Bankfinanzierung muss mindestens CHF '+getFormattedAmount(vwMinBankFin)+' betragen. Unser Contact Center, Telefon +41 81 256 96 01 gibt Ihnen gerne weitere Auskünfte.');
      showHideElement("rowHideMinBankFin", true)
      showHideElement("showMinBankFin", true);
      return false;
    }
    else{
	showHideElement("showMinBankFin", false);
	 return true;
	}
  }
  else return false;
}


// ------------------------------------------------------------
// checkMinAmor
// (function for step/screen 2)
// Check if the desired amortisation value is below the limit defined in the configuration document.
// Returns TRUE if the value is valid, FALSE if it is too low or not a valid number.
// ------------------------------------------------------------
function checkMinAmor()
{
	allok = true;
	
	// change number formatting
	$("#uAmorBetrag").format({format:"#", locale:"ch"});
	
	amorLimit = (f.uBankFin.value / 100) * vwMinAmor;
     // calculate the valid minimal money amount for the amortization
	if( ((f.uAmorBetrag.value * 1) == 0) || (f.uAmorBetrag.value == "") ) {
		f.uAmorBetrag.value = amorLimit;
	}
	else if((f.uAmorBetrag.value * 1) < amorLimit)
	{
		//alert("Die Amortisation muss mindestens "+vwMinAmor+"% der Bankfinanzierung betragen, also mindestens CHF "+getFormattedAmount(amorLimit)+". Bitte geben Sie einen entsprechend höheren Wert ein.");
		showHideElement("showInfoBankFin", false);
		showHideElement("showInfoBankFinErr", true);
		//return false;
		allok = false
	}
	else{	
		showHideElement("showInfoBankFinErr", false);
		showHideElement("showInfoBankFin", true);
	}
	$("#uAmorBetrag").format({format:"#,###", locale:"ch"});
	//return true;
	return allok;
}


// ------------------------------------------------------------
// checkMinUnterhalt()
// Check if the maintenance expense value is below the limit defined in the configuration document.
// Returns TRUE if maintenance expense value is valid, FALSE if too low or not a number.
// Since the field is read only and is not submitted in IE, write a final field
// ------------------------------------------------------------
function checkMinUnterhalt()
{
	// change number formatting
	$("#uUnterhaltBetrag").format({format:"#", locale:"ch"});

	// CR August 2009: setzt den Betrag immer fix, ohne Änderungsmöglichkeit
	unterhaltLimit = (f.uFinBedarf.value / 100) * vwMinUnterhalt;
	unterhaltLimit = Math.round(unterhaltLimit);
	f.uUnterhaltBetrag.value = unterhaltLimit;
	f.uUnterhaltBetragFinal.value = unterhaltLimit;		
	$("#uUnterhaltBetrag").format({format:"#,###", locale:"ch"});
	$("#uUnterhaltBetrag").value=unterhaltLimit;
	return true;
	
	/*
    // calculate the valid minimal money amount for the maintenance
	if ( ((f.uUnterhaltBetrag.value * 1) == 0) || (f.uUnterhaltBetrag.value == "") ) {
		f.uUnterhaltBetrag.value = unterhaltLimit;
		f.uUnterhaltBetragFinal.value = unterhaltLimit;
	}
	else if((f.uUnterhaltBetrag.value * 1) < unterhaltLimit)
	{
		f.uUnterhaltBetrag.value = unterhaltLimit;
		f.uUnterhaltBetragFinal.value = unterhaltLimit;		
	}
	*/
	
}


// ----- END field value checking functions -----

// ----- BEGIN calculation functions -----

// ------------------------------------------------------------
// BankFin()
// (function for step/screen 1)
// Performs the recalculations that depend on the two input fields 
// "own capital" (Eigenkapital) and "funding requirement" (Finanzierungsbedarf)
// It refreshes the initial values of the fields "maintenance" (Unterhalt) and "amortization" (Amortisation), 
// and calculates the bank financing (Bankfinanzierung)
// Returns TRUE if the bank financing amount could successfully be computed, and FALSE if not.
// ------------------------------------------------------------
function recalcBankFin()
{
	f = document.finForm;
	allok = true; // return flag
	if(isValidNumber(f.uFinBedarf.value))
	{
		// if the finBedarf is ok, we can already compute the maintenance expenses
		// If the currently entered maintenance expense value is lower than the amount needed now, we will raise the new value to the needed amount.
		//if(f.uUnterhaltBetrag.value < (Math.round((f.uFinBedarf.value / 100) * vwVorgMinUnterhalt)))
		//{
		//	setFieldToNumValue("uUnterhaltBetrag", Math.round((f.uFinBedarf.value / 100) * vwVorgMinUnterhalt));
		//}
		// New: Don't check, if the amount is already high enough, always set the maintenance expenses to the exact value.
//2???		setFieldToNumValue("uUnterhaltBetrag", Math.round((f.uFinBedarf.value / 100) * vwVorgMinUnterhalt));

		//if uEigenMittel is empty set min Value
		if(!isValidNumber(f.uEigenMittel.value) || f.uEigenMittel.value == "0")
		{
			setFieldToNumValue("uEigenMittel", Math.round((f.uFinBedarf.value / 100) * vwVorgMinEM));
		}
		// compute the financing needs
		if(isValidNumber(f.uEigenMittel.value))
		{
			// test if the own capital ratio is sufficient
			if(f.uEigenMittel.value < Math.round(f.uFinBedarf.value * (vwMinEM / 100)))
			{
				// we don't have sufficiend own capital
				//alert('Das Eigenkapital muss mindestens '+vwMinEM+'% des Finanzierungsbedarfs betragen. Bitte geben Sie einen entsprechend höheren Betrag ein.');
				//f.uEigenMittel.focus();
				showHideElement("showEM", false);
				showHideElement("showEMFault", true);
				writeToID("showVwMinEMFault", vwMinEM);
				return false;
			}
			else
			{
				showHideElement("showEMFault", false);
				showHideElement("showEM", true);
			}
			bf = f.uFinBedarf.value - f.uEigenMittel.value;
			if (bf < 0) bf=0; // if we have more money than we need, the need for financing is of course exactly 0.
			if (bf == 0) {
				prozentBF = 0;
			}
			else {
				prozentBF = (bf*100)/(f.uFinBedarf.value *1);
			}			
			
			f.uBankFin.value = bf;
			writeToID("showBankFin",getFormattedAmount(f.uBankFin.value));
			writeToID("showBelehnung", Math.round(prozentBF));
			// after we computed the financial need, let's see if the amount is high enough so we offer service
			allok = checkMinBankFin();
			
			// compute the amortisation
			// If the currently entered amortization value is lower than the amount needed now, we will raise the new value to the needed amount.
			// if(f.uAmorBetrag.value < (Math.round((f.uBankFin.value / 100) * vwVorgMinAmor))) //roundTo2Digits
			// {
			//	setFieldToNumValue("uAmorBetrag", Math.round((f.uBankFin.value / 100) * vwVorgMinAmor)); //roundTo2Digits
			// }
			// New: Don't check, if the amount is already high enough, always set the amortization to the exact value.
//2???			setFieldToNumValue("uAmorBetrag", Math.round((f.uBankFin.value / 100) * vwVorgMinAmor)); //roundTo2Digits
		}
		else 
		{
			// if the own capital is not a value number, we return false
			allok = false;
		}		
	}
	else
	{
		// if the financial need is not a value number, we return false
		allok = false;
	}

	if(allok == false)
	{
		// If we cannot successfully compute the bank financing need, we print a placeholder.
		// writeToID("showBankFin","-");
		f.uBankFin.value = "";
	}

	return allok;
}


// ------------------------------------------------------------
// addOwnCapitalValues
// (function for step/screen 1)
// Compute the sum of the different own capital values
// (inside the Own Capital Dialog) and return those to
// the main page's own capital field.
// ------------------------------------------------------------
function addOwnCapitalValues()
{
	// Let's add our own capital fields
	// We only add those fields that contain valid numbers
	gg = 0;
	if(!isNaN(f.uEMBargeld.value)) gg += f.uEMBargeld.value * 1;
	if(!isNaN(f.uEMBauland.value)) gg += f.uEMBauland.value * 1;
	if(!isNaN(f.uEMEigen.value)) gg += f.uEMEigen.value * 1;
	if(!isNaN(f.uEMDarlehen.value)) gg += f.uEMDarlehen.value * 1;
	if(!isNaN(f.uEM23Saeule.value)) gg += f.uEM23Saeule.value * 1;
	// set the main document's Own Capital field to the new value
	f.uEigenMittel.value = gg;
	f.uEigenMittelSum.value = gg;
	// Compute the new bank financing amount
	recalcOK = recalcBankFin();
	// If the result was OK, let's hide this dialog layer.
	if (recalcOK) 
	{ 
		MM_showHideLayers('eigenmittel','','hide'); 
	}
	recalcOK = recalcAll();
}


// ------------------------------------------------------------
// showExplanation
// (function for step/screen 1)
// Show the product information page for a given page ID.
// ------------------------------------------------------------
function showExplanation(pageID)
{
  //window.open(document.finForm.tmpDBURL.value+"/vPageID/"+pageID,"_blank");
  //javascript:zoom(document.finForm.tmpDBURL.value+"/vContentBlank/"+pageID, '100', '100', '746', '500', 'yes')
  window.open("/web/"+pageID,"_blank");
}


// ------------------------------------------------------------
// showProductInfoLinks
// (function for step/screen 1)
// Shows the product information links for all the products
// ------------------------------------------------------------
function showProductInfoLinks()
{
	for(prodNr=1;prodNr<=3;++prodNr)
	{
		if(!(f.elements["uProdukt"+prodNr+"Typ"].value == ""))
		{

writeToID("InfoProd"+prodNr, getInfoLinkTextForProduct(f.elements["uProdukt"+prodNr+"Typ"].value))
		} else {
			writeToID("InfoProd"+prodNr, "")
		}
	}
}


// ------------------------------------------------------------
// changeProductType
// (function for step/screen 2)
// Event: the user changes the type of a product (i.e. chooses another value from a product type dropdown box)
// ------------------------------------------------------------
function changeProductType(prodNr, thisValue)
{
	f = document.finForm;
	// If the user chose the separator ("-----"), we treat this as an empty value.
	if(thisValue == "-")
	{
		thisValue = "";
		f.elements["uProdukt"+prodNr+"Typ"].value = thisValue;
	} 

	// if the user chose a disabled option (an option that is not available for the chosen object),
	// we will inform him, and reset the value
	if(disabledProducts[f.elements["uProdukt"+prodNr+"Typ"].value])
	{
		selectedObjType = f.ov_ObjektTyp.value;
		alert("Für den ausgewählten Objekttyp ("+selectedObjType+") steht die Start-Hypothek nicht zur Verfügung. Bitte wählen Sie ein anderes Produkt.");
		thisValue = "";
		f.elements["uProdukt"+prodNr+"Typ"].value = thisValue;	
	}
	
	// special for product "Zinssatzszenario": the user may edit the percentage field. Let's make it editable and reset its value to the variable mortgage.
	f.elements["uProd"+prodNr+"Hypo1Prozent"].value = getInterestRateForProduct("var");
	
	// If the product was set to "", also reset the product's amount to 0.	
	if(thisValue == "")
	{
		$("#errorTR_" + prodNr).hide();
		resetProductData(prodNr);
	}
	// recalculate according to our changes
	callRecalcAllStep2();
}


// ------------------------------------------------------------
// changeProductInterestRate
// (function for step/screen 2)
// Event: the user changes the interest rate for a product.
// NOTE: This only applies to the "Zinssatzszenario"
// ------------------------------------------------------------
function changeProductInterestRate(prodNr, thisValue)
{
	f = document.finForm;
	// replace Komma (",") values by decimal points
	thisValue = thisValue.replace(/\,/,".");
	f.elements["uProd"+prodNr+"Hypo1Prozent"].value = thisValue;

	if(isValidNumber(thisValue))
	{
		// The percentage value must be between 0 and 100, of course.
		if((thisValue >= 0) && (thisValue < 100))
		{
			callRecalcAllStep2();
		}
		else
		{
			alert("Der Zinssatz muss sich zwischen 0 und 100 liegen.");
			f.elements["uProd"+prodNr+"Hypo1Prozent"].value = "5";
			f.elements["uProd"+prodNr+"Hypo1Prozent"].focus();
		}
	}
	else
	{
		alert("Der Zinssatz muss eine Zahl zwischen 0 und 100 sein. Benutzen Sie bitte den Dezimalpunkt (.) und geben Sie nicht das Prozentzeichen (%) ein.");
		f.elements["uProd"+prodNr+"Hypo1Prozent"].value = "5";
		f.elements["uProd"+prodNr+"Hypo1Prozent"].focus();
	}
}


// ------------------------------------------------------------
// recalcHypoAmounts
// (function for step/screen 2)
// Calculate the mortgages for the products.
// According to the product choices and amount entries 
// the user has made for the three possible product entries,
// we calculate the mortgages per product.
// Returns TRUE if calculation was successful, 
// which is the case it the entered values were of currect format 
// and the amounts are higher than the minimum amounts.
// ------------------------------------------------------------
function recalcHypoAmounts()
{	
	allok = true; // return flag
	f = document.finForm;
	// get the financial need
	finBedarf = f.uFinBedarf.value;
	if (isValidNumber(finBedarf))
	{
		// calculate the maximal amount available for mortgages
		maxMortgValue = (finBedarf / 100) * vwProzHypo1;
		// if no values were entered, set them to 0
		prodBetrag = new Array();
		prodBetrag[1] = f.uProd1Betrag.value; if(prodBetrag[1] == "") prodBetrag[1]=0;
		prodBetrag[2] = f.uProd2Betrag.value; if(prodBetrag[2] == "") prodBetrag[2]=0;
		prodBetrag[3] = f.uProd3Betrag.value; if(prodBetrag[3] == "") prodBetrag[3]=0;

		// if values are entered, check if they are of the minimal amount specified
		for(prodNr=1;prodNr<=3;++prodNr)
		{
			if (prodBetrag[prodNr] > 0){
				prodTypeFieldName = "uProdukt"+prodNr+"Typ";
				prodMinimalAmount = getMinimalProductAmount(f.elements[prodTypeFieldName].value);
				if (prodBetrag[prodNr] < prodMinimalAmount){					
				
					//amaier: removed alert and added error spans instead (CR1619)
					//alert("Der Mindestbetrag für das Produkt "+prodNr+" beläuft sich auf CHF "+getFormattedAmount(prodMinimalAmount)+". Bitte geben Sie einen entsprechend höheren Betrag ein.");
					$("#ErrorMessage_"+prodNr).html("(Mindestbetrag: CHF "+getFormattedAmount(prodMinimalAmount)+")");
					$("#ErrorMessage_"+prodNr).show();
					$("#errorTR_"+prodNr).show();										
					allok = false;
				}else{
					$("#ErrorMessage_"+prodNr).css("display","none");
				}
			}
		}
		
		// computations for the start hypo product		
		prod1Type = f.uProdukt1Typ.value;
		if ((prod1Type=="start1") || (prod1Type=="start2"))
		{
			prodNr=1; // we only deal with product 1
			// automatically set the hypo value to the bank financing amount. As we cannot combine with another product, we must invest everything in this product.
			bankFin = f.elements["uBankFin"].value;
			f.elements["uProd"+prodNr+"Betrag"].value = bankFin;
			// make this field readonly
			
			// hide all other products and reset their values
			showHideProduct(2, false);
			showHideProduct(3, false);
			resetProductData(2);
			resetProductData(3);
			showHideElement("showProd"+prodNr+"Hypo2Comment", false); //Regelung mit var hypo kommt nicht zum tragen
			// mortgage 1 is the minimum of 70% of the financial need, and the bank financing amount
			m1 = Math.min(bankFin, maxMortgValue);
			m2 = bankFin - m1;
			f.elements["uProd"+prodNr+"Hypo1Anteil"].value = m1
			f.elements["uProd"+prodNr+"Hypo2Anteil"].value = m2			
			// compute half of the financial need with the first percentage value, and the rest (up to the mortgage 1 amount) with the second
			irProd = getInterestRateForProduct(prod1Type); // results in an array
			f.elements["uProd"+prodNr+"Hypo1Prozent"].value = irProd[0]+" bzw. "+irProd[1]; // we do not calculate with the value
			m1p1 = (bankFin / 2) * (irProd[0] / 100);
			m1p2 = (m1 - (bankFin / 2)) * (irProd[1] / 100);
			f.elements["uProd"+prodNr+"Hypo1Betrag"].value = m1p1 + m1p2;
			// if we have any amount left, open up a second mortgage and put the rest inside the second mortgage's second percentage
			prozHyp2 = irProd[1] + vwProzDiffHypo1zu2;
			f.elements["uProd"+prodNr+"Hypo2Prozent"].value = prozHyp2;
			m2p2 = m2 * (prozHyp2 / 100);
			f.elements["uProd"+prodNr+"Hypo2Betrag"].value = m2p2;
			mort[0][0] = m1;
			mort[0][1] = m2;
			
			//amaier: move to nirvana! - workaround for ie6... (CR1619)
			$(".dummyClass_2").css("position","absolute");
			$(".dummyClass_2").css("left","-6000px");
			$(".dummyClass_3").css("position","absolute");
			$(".dummyClass_3").css("left","-6000px");
			//be sure to hide errormessages of 2nd and 3rd product
			$("#ErrorMessage_2").css("display","none");
			$("#ErrorMessage_3").css("display","none");

		}
		else
		{
		
			//amaier: get back - workaround for ie6... (CR1619)
			$(".dummyClass_2").css("position","");
			$(".dummyClass_2").css("left","");
			$(".dummyClass_3").css("position","");
			$(".dummyClass_3").css("left","");
		
			// make sure products 2 and 3 are visible
			showHideProduct(2, true);
			showHideProduct(3, true);
			// computations for all other products	
			// feed the mortgages array
			mort = Array(Array(prodBetrag[1],0),Array(prodBetrag[2],0),Array(prodBetrag[3],0));
			restFirstMortg = maxMortgValue;
			for(prodNr=1;prodNr<=3;++prodNr)
			{
				if(prodBetrag[prodNr] == 0)
				{
					// the product amount is zero, so we ignore this product, not used at the moment.
					// resetProductData(prodNr);
				}
				else			
				{
					// a product amount was entered, so let's compute this product
					restFirstMortg = compute2Mortgages(restFirstMortg, prodNr)
				}
			}
		}
		populateComputedValues();
		showHideProductFields();
		showProductInfoLinks();
		
		return allok;
	}
	else
	{
		// if the finBedarf was not entered in a valid format, we cannot compute the mortgages.
		return false;
	}
		
	// ---------------------------------------
	// Inner Function compute2Mortgages:
	// for a given product, compute the needed mortgages. We may have one or two mortgages
	// per product, and we must take into account the total sum of first mortgages.
	// ---------------------------------------
	function compute2Mortgages(restM1, prodNr)
	{
	
		mort1productType="";
		
		// get the current product type
		prodTypeFieldName = "uProdukt"+prodNr+"Typ";
		prodTypeField = f.elements[prodTypeFieldName];
		if(!prodTypeField) { debugMsg("ERROR: product type field "+prodTypeFieldName+" does not exist."); }
		prodType = prodTypeField.value;
		// Get the interest rate for the variable mortgage (may always substitute the original product)
		varpercent = getInterestRateForProduct("var");
		// prodNr is the product number and runs from 1 to 3
		// Our index runs from 0 to 2, 
		arridx=prodNr - 1;
		// mort[a][b] is the (b-1). mortgage of the (a-1). product.
		// E.g., the 2nd mortgage of the 1st product is mort[0][1]
		// get the first mortgage input amount
		if (mort[arridx][0] == "") { mort[arridx][0] = 0; }

		// Get this product's interest rate		
		irProd = getInterestRateForProduct(prodType);
		// can we support this money amount with the desired product type, or do we have to take the variable mortgage instead?
		minProdMortgageAmount = getMinimalProductAmount(prodType);
		if(!(irProd == false ))
		{
			if((restM1 < minProdMortgageAmount)) //we have to switch to the variable mortgage
			{
				mort1productType = "var";
				//mort1percenttemp = irProd;
				mort1percent = varpercent;
				//set span for (Var Hypo)* 
				showHideElement("showProd"+prodNr+"Hypo1Comment", true);
			}
			else
			{
				mort1productType = prodType;
				mort1percent = irProd;	// interest rate for this product
				showHideElement("showProd"+prodNr+"Hypo1Comment", false);
			}
		}
		else
		{
			// we keep the old value. 
			// NOTE: This only applies for the "Zinssatzszenario" where we do not overwrite interest rate values
			mort1percent = f.elements["uProd"+prodNr+"Hypo1Prozent"].value;
			mort1productType = "zinssatzszenario";
			irProd = mort1percent;
		}

		// Compute all remaining mortgage fields and values.
		// For the "Zinssatzszenario" this means just setting the second mortgage to 0, for other products the calculations are made.
		mort2percent = 0; 			// default for 2nd mortgage percent value
		mort2productType = ""; 	// default for 2nd mortgage product id
				
		mort[arridx][1] = 0;
		if(mort[arridx][0] > restM1)
		{
			// we need two mortgages
			mort[arridx][1] = mort[arridx][0] - restM1;
			mort[arridx][0] = restM1;
			// can we support this money amount with the desired product type, or do we have to take the variable mortgage instead?
			minProdMortgageAmount = getMinimalProductAmount(prodType);
			if((minProdMortgageAmount == 0) || (mort[arridx][1] >= minProdMortgageAmount))
			{
				// we can keep this product
				mort2productType = prodType;
				// 2nd mortgage's interest rate is higher than the first (adaptable from configuration document)
				mort2percent = (irProd * 1) + (vwProzDiffHypo1zu2 * 1);
				// hide the informational text that the variable product has been chosen for the 2nd mortgage
				showHideElement("showProd"+prodNr+"Hypo2Comment", false);
			}
			else
			{
				// we have to switch to the variable mortgage
				mort2productType = "var";
				// 2nd mortgage's interest rate is higher than the first (adaptable from configuration document)
				mort2percent = (varpercent * 1) + (vwProzDiffHypo1zu2 * 1);
				// display the informational text that the variable product has been chosen for the 2nd mortgage
				showHideElement("showProd"+prodNr+"Hypo2Comment", true);
			}
		}
		else
		{
			// no second mortgage needed
		}

		// After we finished the product calculations, let's fill this product's form fields with the results.		
		f.elements["uProd"+prodNr+"Hypo1Prozent"].value = mort1percent;
		f.elements["uProd"+prodNr+"Hypo2Prozent"].value = mort2percent;
		f.elements["uProd"+prodNr+"Hypo1Anteil"].value = mort[arridx][0];
		f.elements["uProd"+prodNr+"Hypo2Anteil"].value = mort[arridx][1];
		mort1Amount = roundTo2Digits((mort[arridx][0] / 100) * mort1percent);
		mort2Amount = roundTo2Digits((mort[arridx][1] / 100) * mort2percent);
		f.elements["uProd"+prodNr+"Hypo1Betrag"].value = mort1Amount;
		f.elements["uProd"+prodNr+"Hypo2Betrag"].value = mort2Amount;
		f.elements["uProd"+prodNr+"Hypo1Type"].value = mort1productType;
		f.elements["uProd"+prodNr+"Hypo2Type"].value = mort2productType;
		
		restM1 = restM1 - mort[arridx][0];
		return restM1;
	} // func compute2Mortgages
	// ----- END inner functions -----		
return true;
}


// ------------------------------------------------------------
// recalcCost
// (function for step/screen 2)
// Recalculate the yearly and monthly cost ("Belastung").
// This function should only be called when calculations of the mortgage amounts has successfully finished.
// ------------------------------------------------------------
function recalcCost()
{
	// change number formatting
	$("#uAmorBetrag").format({format:"#", locale:"ch"});
	$("#uUnterhaltBetrag").format({format:"#", locale:"ch"});
	
	// calculate all mortgage1 and mortgage2 costs
	f.uAnnZinsBelastungHypo1.value = (Math.round(f.uProd1Hypo1Betrag.value * 1)) + (Math.round(f.uProd2Hypo1Betrag.value * 1)) + (Math.round(f.uProd3Hypo1Betrag.value *1));
	f.uAnnZinsBelastungHypo2.value = (Math.round(f.uProd1Hypo2Betrag.value * 1)) + (Math.round(f.uProd2Hypo2Betrag.value * 1)) + (Math.round(f.uProd3Hypo2Betrag.value *1));
	f.uAnnZinsBelastung.value = (f.uAnnZinsBelastungHypo1.value * 1) + (f.uAnnZinsBelastungHypo2.value * 1);
	f.uSummeHypo1Anteil.value = (f.uProd1Hypo1Anteil.value * 1) + (f.uProd2Hypo1Anteil.value * 1) + (f.uProd3Hypo1Anteil.value * 1);
	f.uSummeHypo2Anteil.value = (f.uProd1Hypo2Anteil.value * 1) + (f.uProd2Hypo2Anteil.value * 1) + (f.uProd3Hypo2Anteil.value * 1);

	// calculate the entire yearly and monthly cost
	yearlyCost = 0;
	if (isValidNumber(f.uAmorBetrag.value) && isValidNumber(f.uUnterhaltBetrag.value) && isValidNumber(f.uAnnZinsBelastung.value))
		yearlyCost = ((Math.round(f.uAmorBetrag.value * 1)) + (Math.round(f.uUnterhaltBetrag.value * 1)) + (f.uAnnZinsBelastung.value * 1));

	monthlyCost = yearlyCost / 12;
	f.uAnnBelastung.value = yearlyCost;
	f.uMtlBelastung.value = monthlyCost;	
}

// ------------------------------------------------------------
// calcFavourable
// (function for link "hier" step 2)
// Finds the lowest intrest rate, sets back all entered Information and calls callRecalcAllStep2(); with the 
//  product1 set to the found product and with the full financing need.
// ------------------------------------------------------------
function calcFavourable()
{
	if(f.uBankFin.value ==  "" | f.uBankFin.value ==  "-" | f.uBankFin.value ==  0)
	{
		alert("Bitte geben Sie erst den Finanzierungsbedarf und Ihre Eigenmittel an.")
	}
	else
	{
	//zunächst alle Produkte (eingaben vom Benutzer) löschen
	resetProductData(1);
	resetProductData(2);
	resetProductData(3);
	
	//be sure to hide errormessages of 2nd and 3rd product
	$("#ErrorMessage_2").css("display","none");
	$("#ErrorMessage_3").css("display","none");
	
	//array mit allen relevanten Zinssätzen
	marginArray = new Array(vwZinsVarHypo, vwZinsFestHypo[0], vwZinsFestHypo[1],vwZinsFestHypo[2],vwZinsFestHypo[3],vwZinsFestHypo[4],vwZinsFestHypo[5],vwZinsFestHypo[6],vwZinsFestHypo[7],vwZinsFestHypo[8],vwZinsFestHypo[9], vwZinsGeldHypoOhneZA, vwZinsGeldHypoVar1Einstieg[0], vwZinsGeldHypoVar2Einstieg[0], vwZinsStartHypo[0],  vwZinsStartHypo[2]);
	
	produktArray = new Array();
	produktArray[0] = new Array();
 	produktArray[0] [vwZinsVarHypo] = "var";
 	produktArray[0] [vwZinsFestHypo[0]] = "fest1";
 	produktArray[0] [vwZinsFestHypo[1]] = "fest2"; 	
 	produktArray[0] [vwZinsFestHypo[2]] = "fest3";
 	produktArray[0] [vwZinsFestHypo[3]] = "fest4";
 	produktArray[0] [vwZinsFestHypo[4]] = "fest5";
 	produktArray[0] [vwZinsFestHypo[5]] = "fest6";
 	produktArray[0] [vwZinsFestHypo[6]] = "fest7";
 	produktArray[0] [vwZinsFestHypo[7]] = "fest8";
 	produktArray[0] [vwZinsFestHypo[8]] = "fest9";
 	produktArray[0] [vwZinsFestHypo[9]] = "fest10";
 	produktArray[0] [vwZinsFestHypo[10]] = "fest11";
 	produktArray[0] [vwZinsFestHypo[11]] = "fest12"; 	
 	produktArray[0] [vwZinsFestHypo[12]] = "fest13";
 	produktArray[0] [vwZinsFestHypo[13]] = "fest14";
 	produktArray[0] [vwZinsFestHypo[14]] = "fest15";
 	produktArray[0] [vwZinsGeldHypoOhneZA] = "geldohneza";
	produktArray[0] [vwZinsGeldHypoVar1Einstieg[0]] = "geldmitza13";
	produktArray[0] [vwZinsGeldHypoVar2Einstieg[0]] = "geldmitza23";
	produktArray[0] [ vwZinsStartHypo[0]] = "start1";
	produktArray[0] [ vwZinsStartHypo[2]] = "start2";

	//niedrigsten Zinssatz ermitteln
	marginArray.sort(Numsort);
	
	//Produkt zu gefundenen Zinsatz ermitteln und setzen
	//wird bei dem gefundenen Produkt der Mindestberag nicht eingehalten wir die Variable Hypo gewählt
	if (getMinimalProductAmount(produktArray[0][marginArray[0]]) > f.uBankFin.value){
		f.uProdukt1Typ.value = "var";
	}else{
		f.uProdukt1Typ.value = produktArray[0][marginArray[0]];
	}
	
	f.uProd1Betrag.value = f.uBankFin.value;

	//mit neuen Produktdaten alles neu berechnen
	callRecalcAllStep2();
	//showHideElement("showFinancingTitle", false);	
	//showHideElement("showFinancingText", true);
	showHideElement("showCalcFavor", false);
	}
}

// ------------------------------------------------------------
// resetProductData
// (function for step/screen 1)
// Helper function: Set to 0 all data for a given product number
// ------------------------------------------------------------
function resetProductData(prodNr)
{
	// reset the HTML form fields...
	f.elements["uProdukt"+prodNr+"Typ"].value = "";
	f.elements["uProd"+prodNr+"Betrag"].value = 0;
	f.elements["uProd"+prodNr+"Hypo1Prozent"].value = 0;
	f.elements["uProd"+prodNr+"Hypo2Prozent"].value = 0;
	f.elements["uProd"+prodNr+"Hypo1Anteil"].value = 0;
	f.elements["uProd"+prodNr+"Hypo2Anteil"].value = 0;
	f.elements["uProd"+prodNr+"Hypo1Betrag"].value = 0;
	f.elements["uProd"+prodNr+"Hypo2Betrag"].value = 0;
	f.elements["uProd"+prodNr+"Hypo2Type"].value = "";
	// ... and the mortgages inner array
	mort[prodNr-1][0] = 0;
	mort[prodNr-1][1] = 0;
}


// ------------------------------------------------------------
// showHideProductFields
// (function for step/screen 1)
// hide all non-needed product fields
// ------------------------------------------------------------
function showHideProductFields()
{
	f = document.finForm;

	for(prodNr=1;prodNr<=3;++prodNr)
	{
		showHideElement("InputProd"+prodNr, !(f.elements["uProdukt"+prodNr+"Typ"].value == ""));
		for(hypNr=1;hypNr<=2;++hypNr)
		{
			showHideElement("LineProd"+prodNr+"Hypo"+hypNr, (mort[prodNr-1][hypNr-1]>0));
			setFieldToNumValue("uProd"+prodNr+"Hypo"+hypNr+"Anteil", mort[prodNr-1][hypNr-1]);
		}
		
		// for the "Zinssatzszenario", decide whether to show the input field or not
		productId = f.elements["uProdukt"+prodNr+"Typ"].value;
		showHideElement("maskProd"+prodNr+"Hypo1PercentInput", (productId == "zinssatzszenario"));
		showHideElement("showProd"+prodNr+"Hypo1Prozent", !(productId == "zinssatzszenario"));
	}
}


// ------------------------------------------------------------
// showHideElement
// (general function)
// Show or hide an HTML item. The HTML element must have an id attribute.
// Call with the element's id and true/false to show/hide the element.
// ------------------------------------------------------------
function showHideElement(elementName, mode)
{
	// grab the element by its id
	el = document.getElementById(elementName);
	// only treat elements that do exist
	if(el)
		if(mode == true)
			el.style.display = '';   
		else
			el.style.display = 'none';
}


// ------------------------------------------------------------
// populateComputedValues
// (function for step/screen 1)
// Populate all the display values (HTML SPANs) from their hidden fields
// for the bank financing, the product list and the cost fields.
// ------------------------------------------------------------
function populateComputedValues()
{
	f = document.finForm;
	// the financing fields (top)
      writeToID("showBankFin",getFormattedAmount(f.uBankFin.value));
	// populate the product fields
	for(prodNr=1;prodNr<=3;++prodNr)
		for(hypNr=1;hypNr<=2;++hypNr)
		{
		      writeToID("showProd"+prodNr+"Hypo"+hypNr+"Anteil", getFormattedAmount(f.elements["uProd"+prodNr+"Hypo"+hypNr+"Anteil"].value));
		      writeToID("showProd"+prodNr+"Hypo"+hypNr+"Prozent", f.elements["uProd"+prodNr+"Hypo"+hypNr+"Prozent"].value);
		      writeToID("showProd"+prodNr+"Hypo"+hypNr+"Betrag", getFormattedAmount(f.elements["uProd"+prodNr+"Hypo"+hypNr+"Betrag"].value));
		}
	// populate Cost fields
	writeToID("showAnnBelastung", getFormattedAmount(f.uAnnBelastung.value));
	writeToID("showMtlBelastung", getFormattedAmount(f.uMtlBelastung.value));
}


// ------------------------------------------------------------
// changeProductAmount
// Event: the user changes the amount for a given product
// (The parameters passed to this function are not used at this moment,
// but could be helpful if further actions shall be taken when the product
// amount changes. prodNr is the number of the product (1..3), thisValue
// is the newly entered value for the field.)
// ------------------------------------------------------------
function changeProductAmount(prodNr, thisValue)
{
	callRecalcAllStep2();
}


// ------------------------------------------------------------
// gotoStep
// Submit function when changing pages.
// When changing pages, we want to perform certain field checks etc., so we call those here.
// NOTE: stepId is the page to which the user wants to change. f.step.value, contrarily, is the currently active page.
// ------------------------------------------------------------
function gotoStep(stepId)
{
	f = document.finForm;

	// check the critical values of this step before continuing
	allok = true;
	switch(f.step.value)
	{
		case "1" :
			// change number formatting
			$(".numericT0").format({format:"#", locale:"ch"});
			allok = checkStep1();
			// change number formatting
			if (!allok) {
				$(".numericT0").format({format:"#,###", locale:"ch"});
			} else {
				$(".numericT0").format({format:"#", locale:"ch"});
			}
			break;
		case "2" : allok = checkStep2(); break;
		case "3" : allok = checkStep3(stepId); break;
		//case "4" : allok = checkStep4(); break;
	}
	
	// if everything is all right, let's move to the desired page
	if(allok)
	{
		f.step.value = stepId;
		f.submit();
	}
}


// ------------------------------------------------------------
// checkStep1
// (function for step/screen 1)
// Mandatory field integrity checks when leaving step 1 and moving to another.
// ------------------------------------------------------------
function checkStep1()
{
	allok = true;
	// Some sanity checks
	if(f.uFinBedarf.value == "" || !isValidNumber(f.uFinBedarf.value)) f.uFinBedarf.value = "0";
	if(f.uEigenMittel.value == "" || !isValidNumber(f.uEigenMittel.value)) f.uEigenMittel.value = "0";
	if(f.uTotalJahresEinkommen == "" || !isValidNumber(f.uTotalJahresEinkommen.value)) f.uTotalJahresEinkommen.value = "0";
	
	doCheckObjectType()
	
	if(f.uFinBedarf.value == "0"){
		f.uEigenMittel.value = "0";
		showHideElement("showFinBedarf", true);
		return false;
	}
	else{
		showHideElement("showFinBedarf", false);
	}

	if(f.uEigenMittel.value == "0"){
		showHideElement("showEM", false);
		showHideElement("showEMFault", true);
		return false;
	}
	else{
	showHideElement("showEigenmittel", false);}

	if (f.uTotalJahresEinkommen.value == "0"){
		//alert("Bitte geben Sie das jährliche Bruttoeinkommen ein.")
		showHideElement("showBruttoIncome", true);
		return false;
	}
	else{
	showHideElement("showBruttoIncome", false);}

	// check if entry for own capital has been made	
	if(f.ov_ImmoCode &&  f.uEigenMittel.value == "0")
	{
		showHideElement("showEM", false);
		showHideElement("showEMFault", true);
		return false;
      }
	
	allok = recalcAll();
	return allok;
}


// ------------------------------------------------------------
// checkStep2
// (function for step/screen 2)
// Mandatory field integrity checks when leaving step 2 and moving to another.
// ------------------------------------------------------------
function checkStep2()
{

	// change number formatting
	$(".numericT0").format({format:"#", locale:"ch"});

	allok = true;
	
	// calculate the sums of the product amounts
	sumProdAmounts = 0;
	if(isValidNumber(f.uProd1Betrag.value)) sumProdAmounts = (sumProdAmounts * 1) + (f.uProd1Betrag.value * 1);
	if(isValidNumber(f.uProd2Betrag.value)) sumProdAmounts = (sumProdAmounts * 1) + (f.uProd2Betrag.value * 1);
	if(isValidNumber(f.uProd3Betrag.value)) sumProdAmounts = (sumProdAmounts * 1) + (f.uProd3Betrag.value * 1);
	
	// check if our added product amounts add up exactly to the bank financing sum
	// check if too high...
	if ((sumProdAmounts * 1) > (f.uBankFin.value * 1)) 
	{
		sumDelta = (sumProdAmounts * 1) - (f.uBankFin.value * 1);
		showHideElement("showWrongTotal", true);
		allok = false;
	}
	// ... or too low.
	else if ((sumProdAmounts * 1) < (f.uBankFin.value * 1)  & sumProdAmounts > 0) 
	{
		sumDelta = (f.uBankFin.value * 1) - (sumProdAmounts * 1);
		showHideElement("showWrongTotal", true);
		allok = false;
	}
	else{
		allok = checkMinAmor();
	}
	if (allok) {
		allok = recalcHypoAmounts();
	}
	
	// change number formatting
	$(".numericT0").format({format:"#,###", locale:"ch"});

	return allok;
}


// ------------------------------------------------------------
// checkStep2
// (function for step/screen 2)
// Mandatory field integrity checks when leaving step 2 and moving to another.
// ------------------------------------------------------------
// 2???function checkStep2()
// 2???{
// 2???	allok = true;
// 2???	return allok;
// 2???}


// ------------------------------------------------------------
// checkStep3
// (function for step/screen 3)
// Mandatory field integrity checks when leaving step 3 and moving to another.
// NOTE: stepId is the page to which the user wants to change.
// ------------------------------------------------------------

function scrollTo(elementName, speed) {
	$('html,body').animate({
		scrollTop: $('#' + elementName).offset().top
		}, speed);
}//scrollTo

function showErrorMsg(itemname) {
	$('#' + itemname).css('display','inline');
	$('#' + itemname).parent().addClass('errortext');	
	scrollTo('formStart', 500);
}//showErrorMsg

function hideErrorMsg(itemname) {
	$('#' + itemname).css('display','none');
	$('#' + itemname).parent().removeClass('errortext');
}//hideErrorMsg

function isEmailValid(strEmailAddr) {
	if($('select#uKontaktWie').val()!='E-Mail'){
		if(strEmailAddr == "") return true;
	}
	var emailRegexp = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
	return emailRegexp.test(strEmailAddr);
}//isEmailValid

function checkStep3(stepId)
{
	// check if all mandatory fields in the contact form were filled out correctly
	allok = true;
	// Only when moving to the final screen, the address fields are mandatory
	if(stepId == "4"){
	
		var itemName = '';
		var requiredItemnames = $('#FormStep3RequiredFieldIDs').val().split(';');
	
		//hide all err spans
		for(var i=0; i<=requiredItemnames.length; i++){
			hideErrorMsg('err' + requiredItemnames[i]);			
		}
	
		//check form
		for(var i=0; i<=requiredItemnames.length; i++){
			itemName = requiredItemnames[i];
			if(itemName=="uEmail"){
				//email special
				if(!isEmailValid($('#' + itemName).val())) {
					showErrorMsg('err'+itemName); 
					return false;
				}
			} else {
				//normal fields
				if($('#' + itemName).val()==""){					
	  				showErrorMsg('err'+itemName); 
					return false;
				}
			}
		}//for			
	}

	return true;	

}


// ------------------------------------------------------------
// recalcAll
// (function for step/screen 1)
// Referring to the input fields in step 1, perform
// all calculations to fill computed fields and display SPANs.
// This function may be called under all circumstances, and
// will react accordingly to empty fields etc.
// ------------------------------------------------------------
function recalcAll()
{
	allok = true;

	// change number formatting for ie6/7 because of tabindex problem
	if ($.browser.msie && ($.browser.version.substr(0, 1) === '6' || $.browser.version.substr(0, 1) === '7')) {
	}
	else {
		$(".numericT0").format({format:"#", locale:"ch"});
	}
	
	// decide which of the context-sensitive variables to use
	f = document.finForm;
	selectedObjType = f.elements['ov_ObjektTyp'].options[f.elements['ov_ObjektTyp'].selectedIndex].text;
	if(selectedObjType == "Ferienwohnung")
	{
		vwMinEM = vwMinEMFeWo;
		vwVorgMinEM = vwVorgMinEMFeWo;
	}
	else
	{
		vwMinEM = vwMinEMStd;
		vwVorgMinEM = vwVorgMinEMStd;
	}

	//Check, if an object is selected
	// setTimeout("doCheckObjectType()", 100);
	doCheckObjectType();
	if (f.ov_ObjektTyp.options[0].selected == true || f.ov_ObjektTyp.options[1].selected == true){
		allok = false;
	}

	//Check, if object price is entered
	if (f.uFinBedarf.value != "0" && f.uFinBedarf.value != "") {
			showHideElement("showFinBedarf", false);
	}
	
	//Check, if income is entered
	if (f.uTotalJahresEinkommen.value != "0" && f.uTotalJahresEinkommen.value != "") {
			showHideElement("showBruttoIncome", false);
	}


	// recalculate the financing input data
	if (allok) {
		if(!recalcBankFin())
		{
			allok = false;
		}
	}

	// adapt the setting of min values and disabling of product items

	if (allok) {
		showHideElement("showGeneralFault", false);
	}
	else if (f.uFinBedarf.value == "" || f.uFinBedarf.value == "0" || f.uEigenMittel.value == "" || f.uEigenMittel.value == "0") {
		// showHideElement("showGeneralFault", true); -> not used anymore. delete everywhere? (mko)
	}

	// change number formatting
	if ($.browser.msie && ($.browser.version.substr(0, 1) === '6' || $.browser.version.substr(0, 1) === '7')) {
	}
	else {
		$(".numericT0").format({format:"#,###", locale:"ch"});
	}
	
	return allok;
}


// ------------------------------------------------------------
// callRecalcAllStep2
// Even after the last usable event (onMouseUp), in the MSIE, 
// a radiobutton's "this.value" still contains the radiobutton's old value.
// As we need the newly set value instead, we will "wait" until the value
// was set.
// ------------------------------------------------------------
function callRecalcAllStep2()
{
	setTimeout("recalcAllStep2()", 100);
}


// ------------------------------------------------------------
// recalcAllStep2
// (function for step/screen 2)
// Referring to the input fields in step 2, perform
// all calculations to fill computed fields and display SPANs.
// NOTE: For optimal performance on the MSIE browser,
// call function "callRecalcAllStep2" instead!
// ------------------------------------------------------------
function recalcAllStep2()
{
	// change number formatting
	$(".numericT0").format({format:"#", locale:"ch"});

	f = document.finForm;
	showTextFeWoVermietung = false;
	selectedObjType = f.ov_ObjektTyp.value;
	if(selectedObjType == "Ferienwohnung")
	{
		vwMinEM = vwMinEMFeWo;
		vwMinAmor = vwMinAmorFeWo;
		vwVorgMinAmor = vwVorgMinAmorFeWo;
		vwProzHypo1 = vwProzHypo1FeWo;
		writeToID("showMinAmorFeWoVermietung", vwMinAmorFeWoVermietung );
		showTextFeWoVermietung = true;
	}
	else
	{
		vwMinEM = vwMinEMStd;
		vwVorgMinEM = vwVorgMinEMStd;
		vwMinAmor = vwMinAmorStd;
		vwProzHypo1 = vwProzHypo1Std;
		vwVorgMinAmor = vwVorgMinAmorStd;
		showTextFeWoVermietung = false;
	}
	
	writeToID("showMinAmor", vwMinAmor );
	writeToID("showMinAmorErr", vwMinAmor );
	showHideElement("showFeWoRentalInfo", showTextFeWoVermietung);

	// checkMinAmor
	checkMinAmor()

	// checkMinUnterhalt
	checkMinUnterhalt()
	
	// recalculate the product display and minimal amounts
	if (recalcHypoAmounts())
	{
		// recalculate the cost
		recalcCost();
		// recalc computed fields
		populateComputedValues();
	}
	else
	{
		allok = false;
	}
	// show or hide the product fields
	showHideProductFields();
	
//allok???	
		
	writeToID("showProzEinkommensBelastung", f.uProzEinkommensBelastung.value);
	totalJEK = 0;
	if(isValidNumber(f.uTotalJahresEinkommen.value)) totalJEK = totalJEK + (f.uTotalJahresEinkommen.value * 1)
	writeToID("showTotalJahresEinkommen", getFormattedAmount(f.uTotalJahresEinkommen.value));

	// calculate the income cost ratio (kalkulatorische tragbarkeit)
	pEB = 0;
	f.uProzEinkommensBelastung.value = "";
	if(isValidNumber(f.uTotalJahresEinkommen.value) && isValidNumber(f.uAnnBelastung.value))
	{
		if((f.uTotalJahresEinkommen.value * 1) != 0)
		{
			bankFin = f.uBankFin.value * 1;
			kaufPreis = f.uFinBedarf.value * 1;
			belGW = (100 - vwMinEM) / 100;
			bel1H = Math.min(bankFin, (belGW * kaufPreis));
			bel1H = bel1H * vwKZSH1Std/100;
			bel2H = bankFin - Math.min(bankFin, (belGW * kaufPreis));
			bel2H = bel2H * vwKZSH2Std/100;

			pEB = bel1H + bel2H;
			pEB = pEB + (f.uAmorBetrag.value  * 1);
			pEB = pEB + (f.uUnterhaltBetrag.value  * 1);
			pEB = 100 * pEB / (f.uTotalJahresEinkommen.value  * 1);
			pEB = (Math.round(pEB*10)) / 10;
			f.uProzEinkommensBelastung.value = pEB;
			f.uProzEinkommensBelastungFinal.value = pEB;
		}
	}
	writeToID("showProzEinkommensBelastung", pEB);	
	
	// calculate the info textblocks
	if(isValidNumber(f.uTotalJahresEinkommen.value) && isValidNumber(f.uProzEinkommensBelastung.value))
	{
		// different percentage values will be taken for different incomes
		pBel = vwProzEKKleinerTragbLim; // default: we earn the lower value
		if((f.uTotalJahresEinkommen.value * 1) >= vwTragbLim)
			pBel = vwProzEKGroesserTragbLim; // we earn the higher value
		
		// can we afford the investment?
		// default: we can't
		pBelOK = false
		if(f.uProzEinkommensBelastung.value <= pBel)
			pBelOK = true
		if(pBelOK)
			f.uBelastungOK.value = 1;
		else
			f.uBelastungOK.value = 0;		
		
		// show the according text block
		showHideElement("showTextBelastung", true); //added 30.07.
		showHideElement("showTextBelastungOK", pBelOK);
		showHideElement("showTextBelastungNO", !pBelOK);
	}
	else
	{
		// as the values are not OK, let's not show any text block
		showHideElement("showTextBelastung", false); //added 30.07.
		showHideElement("showTextBelastungOK", false);
		showHideElement("showTextBelastungNO", false);
	}

	// change number formatting
	$(".numericT0").format({format:"#,###", locale:"ch"});
}

// ------------------------------------------------------------
// resetStep
// Resets all values in the specified step
// Call with the step to reset (1/2/3).
// ------------------------------------------------------------

function resetStep(stepId)
{
	f = document.finForm;
	switch(stepId)
	{
		case "1":
			f.uFinBedarf.value='0';
			f.uEigenMittel.value='0';
			f.uTotalJahresEinkommen.value='0';
			f.uBankFin.value='0';
			writeToID("showBankFin", '0');
			writeToID("showBelehnung", '0');
			f.ov_ObjektTyp.options[0].selected = true;
			recalcAll();
			showHideElement("showObjectChoosen", false);
			showHideElement("showMinBankFin", false);
			showHideElement("showGeneralFault", false);
			showHideElement("showBruttoIncome", false);	
			showHideElement("showEMFault", false);
			break;
		case "2":
			resetProductData(1);
			resetProductData(2);
			resetProductData(3);
			writeToID("showAnnBelastung", '0');
			writeToID("showMtlBelastung", '0');

			writeToID("InfoProd1", "");
			writeToID("InfoProd2", "");
			writeToID("InfoProd3", "");
			// recalculate Min Amor (Standard 1% of Finanzierung)
			amorLimit = (f.uBankFin.value / 100) * vwMinAmor;
			f.uAmorBetrag.value = amorLimit;
			recalcAllStep2();
			break;
		case "3":
			f.uAnrede.value='';
			f.uName.value='';
			f.uVorname.value='';
			f.uStrasse.value='';
			f.uOrt.value='';
			f.uTelefonPrivat.value='';
			f.uTelefonWork.value='';
			f.uEmail.value='';
			f.uBemerkungen.value='';
			f.uKontaktWie.options[0].selected=true;
			f.uKontaktTag.options[0].selected=true;
			f.uKontaktUhr.options[0].selected=true;			
			break;	
	}
}

// ------------------------------------------------------------
// showHideProduct
// (general function)
// calls showHideElement to Show or hide an HTML item. The HTML element must have an id attribute.
// Call with the element's id and true/false to show/hide the element.
// ------------------------------------------------------------

function showHideProduct(prodNr,mode)
{
	showHideElement("LineProd"+prodNr, mode);
	showHideElement("LineProd"+prodNr+"Hypo1", mode);
	showHideElement("LineProd"+prodNr+"Hypo2", mode);
}

//---------------------------------------------------------------------
// showProductInfo
// open the product information page for a product 
// number in a new window
//-------------------------------------------------------------------
function showProductInfo(prodNr)
{
	// what product do we have?
	productId = f.elements["uProdukt"+prodNr+"Typ"].value;
	prodPageId = getInfoPageIdForProduct(productId);
	if(!(prodPageId == false))
	{
		showExplanation(prodPageId)
	}
}


// ------------------------------------------------------------
// init
// This function is called when the page is initiated,
// regardless of the step/screen we enter.
// The call of init() is performed in the BODY tag's
// onLoad event, which is defined in the main notes form
// for this Notes Form field value.
// ------------------------------------------------------------
function init()
{
	f = document.finForm;
	switch (f.step.value)
	{
		case "1":
			recalcAll();
			showHideElement("showGeneralFault", false);
			showHideElement("showObjectChoosen", false);
			f.ov_ObjektTyp.focus();
			break;
		case "2":
			doCheckObjectType();
			recalcAllStep2();
			showHideElement("showInfoBankFinErr", false);
			scrollStart(500);
			break;
		case "3":
			scrollStart(500);
			break;
		case "4":
			scrollStart(500);
			break;
	}
}

// ------------------------------------------------------------
// performAction
// This function helps the submit action to pass
// further information about the action to perform
// when submitting a page. Ths field "actionId" is
// filled with a keyword that can then be caught
// in the webQuerySave agent.
// ------------------------------------------------------------
function performAction(actionId, step, stepid)
{
	switch (actionId)
	{
		case "makePdf": 
			allok = true;
			switch(step)
			{
				case 1 : allok = checkStep1(); break;
				case 2 : allok = checkStep2(); break;
				case 3 : allok = checkStep3(stepid); break;
			}
			if (allok)
			{
				f.submitAction.value=actionId;
				f.target="_blank";
				f.submit();
				f.target="";
				f.submitAction.value="";
			}
			break;
		case "clearImmo":
			f.submitAction.value=actionId;
			f.submit();
			f.submitAction.value="";
			break;
		case "doSend":
			f.submitAction.value=actionId;
			f.submit();
			f.submitAction.value="";
			break;
	}	
}


// ------------------------------------------------------------
// checkObjectType
// if ObjectType is "Ferienhaus", certain values
// may change. We do the changes here.
//
// This applies to page 1 and 2.
//
// This is a wrapper function to enable the
// script to catch the NEW selected value of a
// field.
// ------------------------------------------------------------
function doCheckObjectType()
{
	f = document.finForm;
	if (f.step.value == "1") {
		//Check, if an object is selected, otherwise show error text
		if (f.ov_ObjektTyp.options[0].selected == true || f.ov_ObjektTyp.options[1].selected == true){
			showHideElement("showObjectChoosen", true);
		}
		else{
			showHideElement("showObjectChoosen", false);
		}
		//Get the object name
		selectedObjType = f.elements['ov_ObjektTyp'].options[f.elements['ov_ObjektTyp'].selectedIndex].text;
	}
	else if (f.step.value == "2") {
		selectedObjType = f.ov_ObjektTyp.value;
	}
	if (selectedObjType == "Ferienwohnung")
	{
		// This is a "Ferienwohnung". Let's adapt all the fields and spans
		if (f.step.value == "1") {
			writeToID("showVwMinEM", vwMinEMFeWo);
		}
		else if (f.step.value == "2") {
			disableProduct("start1");
			disableProduct("start2");
		}
	}
	else
	{
		// This is not a "Ferienwohnung". Let's adapt all the fields and spans
		if (f.step.value == "1") {
			writeToID("showVwMinEM", vwMinEM);
		}
		else if (f.step.value == "2") {
			enableAllProducts();
		}
	}
}

var disabledProducts = new Object();

// disables the choice of a product from all product selections
function disableProduct(productname)
{
	// add the value to the disabled Products array
	disabledProducts[productname]="x";
	visualizeDisabledProducts();	
}

// undoes the disabling of products
function enableAllProducts()
{
	//reset the array of disabled products
	disabledProducts = new Object();
	visualizeDisabledProducts();
}

// visualize disabled products
function visualizeDisabledProducts()
{
	i=1;
	needRefresh=false;
	// re-adapt the look of the disabled options
	while(document.getElementsByName("uProdukt"+i+"Typ").length > 0)
	{
		selElem = document.getElementsByName("uProdukt"+i+"Typ")[0];
		for(j=0;j<selElem.options.length;++j)
		{
			if (disabledProducts[selElem.options[j].value]) 
			{
				selElem.options[j].style.color="#AAAAAA";
				selElem.options[j].disabled = "disabled";
				// check if these values are currently selected
				if(selElem.options[j].selected == true)
				{
					// if yes, set this product value to empty.
					selElem.options[j].selected = false;
					selElem.options[0].selected = true;
					resetProductData(i);
					populateComputedValues();
					needRefresh=true;
				}
			}
			else
			{
				selElem.options[j].style.color="";			
				selElem.options[j].disabled = "";
			}
		}
		++i;
	}
	// make sure the product fields are all consistent
	if(needRefresh == true)
	{
		callRecalcAllStep2();
	}
}

//berechnung weiterer varianten
function resetFinancing(){
	resetProductData(1);
	resetProductData(2);
	resetProductData(3);
	writeToID("showAnnBelastung", '0');
	writeToID("showMtlBelastung", '0');
	recalcAll();
	//showHideElement("showFinancingTitle", true);
	//showHideElement("showFinancingText", false);
	showHideElement("showCalcFavor", true);
}

// ===== END namics functions =====

