/*!
** \file
** \brief Javascript Klassen und Funktionen für die Online Sozialhilfe Berechnung.
*/ 

// --------------------------------------------------------------------
// Globale Variablen

var clrBorderError = "red";		//!< Farbe wenn eingabe nicht interpretiert werden konnte.
var clrBorderDefault;			//!< Standardrahmenfarbe (wird in onLoad gesetzt).

var oFieldIgn = null;			//!< Dieses Feld ignorgieren von writeNum / writeInt

var bShowAll  = false;			//!< In alle numerischen Felder auch Null ausgeben?

// --------------------------------------------------------------------
// Mehr oder weniger konstante Werte
// Beachte c Konvention: Arrays starten mit 0

var rgKg	= new Array();  //<! Kindergeld
var rgHzk	= new Array();  //<! Heizung (zweidimensional: 1. Heizungsart, 2: Anzahl Personen)
var rgRst	= new Array();	//<! Regelsätze (aus db).
var rgMbe   = new Array();	//<! Mehrbedarf Ernährung
var cAmpPausch	 = 0;		//<! Pauschale Arbeitsmitteln
var cKfzKmPausch = 0;		//<! Pauschale Fahrtkosten / KM
var cMaxKfzKm	 = 0;		//<! Maximale km-Anzahl für Fahrkostenberechnung mit KFZ.
var cFamFrei     = 0;		//<! Freibetrag pro Kindergeld.
var cMaxFamFrei  = 0;		//<! Maximale Anzahl Kinder für deren Kindergeld ein Freibetrag berechnet wird.


// --------------------------------------------------------------------
// Funktionen

/*!
** Zahl aus Eingabefeld auslesen.
**
** Deutsche Dezimaltrenner werden durch amerikanische ersetzt.
** Tausendertrennung führt vermutlich zu Fehlern.
** Ist das Eingabefeld nicht leer und gültig wird es auf
** mit Nachkommastellen formatiert.
*/ 
function readNum( oField )
{
	var r = 0;
	var s = "";
	var c = clrBorderDefault;
	
	if ( oField ) {
		s = oField.value.toString();
		s = s.replace( /,/g, '.' );
		s = s.replace( /\s/g, '' );
	}
	if ( s != "" ) {
		var f = parseFloat( s );
		if ( isNaN( f )  ) {
			c = clrBorderError;
		} else {
			r = f.round2();
			writeNum( oField, r, true );
		}
	}
	if ( oField && oField.style ) 
		oField.style.borderColor=c;
	return r;
}

/*!
** Prüfen ob das Feld bei der Ausgabe überprungen werden soll.
*/ 
function writeIgnore( oField )
{
	var result = oField == oFieldIgn;
	if ( !result && oField.style ) {
		result = oField.style.borderColor == clrBorderError;
	}
	
	return result;
}

/*!
** Zahl mit zwei Nachkommastellen und deutschem Deziamltrenner ausgeben.
*/
function writeNum( oField, number, writeNull )
{
	if ( !writeIgnore( oField ) ) {
		var s = "";
		if ( number != 0 || writeNull ) {
			var sign = number < 0;
			number = Math.abs(number);
			var nInt = Math.floor( number );
			var nDec = Math.round( number * 100 ) % 100;
			s = (sign ? '-' : '') + nInt.toString() + ',' + ("00" + nDec).right( 2 );
		}
		if ( oField.value != s )
			oField.value = s;
	}
}

function readInt( oField )
{
	var result = 0;
	var s = "";
	var c = clrBorderDefault;
	
	if ( oField ) {
		s = oField.value.toString();
		s = s.replace( /\s/g, '' );
	}
	
	if ( s != ""  ) {
		var v = parseInt( s );
		if ( isNaN( v ) ) {
			c = clrBorderError;
		} else {
			result = v;
		}
	}
	if ( oField && oField.style ) {
		if ( oField.style.borderColor != c )
			oField.style.borderColor = c;
	}
	return result;
}

function writeInt( oField, integer, writeNull )
{
	if ( !writeIgnore( oField ) ) {
		var s = "";
		if ( integer != 0 || writeNull ) {
			Math.floor( integer );
			s = integer.toString();
		}
		if ( oField.value != s )
			oField.value = s;
	}
}


/*!
** Randfarbe eines Checkbox Controls setzen.
**
** Kein IE Version znterstützt derzeit style.borderColor derzeit. 
** Daher in Funktion gepackt. Momentan wird die Hintergrundfarbe
** gesetzt.
*/ 
function setCheckBorder( oChk, bHighlight )
{
	if ( oChk && oChk.style ) {
		var c = bHighlight ? clrBorderError : clrBorderDefault;
		if ( oChk.style.backgroundColor != c ) {
//			oChk.style.borderColor = c;
			oChk.style.backgroundColor = c;
		}
	}
}


// --------------------------------------------------------------------
// Prototyp erweiterungen

/*!
** Runden auf zwei Nachkommastellen.
**
** Eigentlich Quatsch für floating point Arithmetik.
** Für unsere Zwecke aber gut genug.
*/ 
function Number_round2()
{
	return Math.round( this * 100 ) / 100;
}

/*!
** Zahl mit Prozentwert multiplizeren und auf 2 Nachkommastellen runden.
*/ 
function Number_percent( p )
{
	return Math.round( this * p ) / 100;
}

Number.prototype.percent = Number_percent;
Number.prototype.round2  = Number_round2;

/*!
** Erweiterung der Klasse String um die Methode right(...).
**
** \returns Die angegebene Zahl von Zeichen vom Ende des Strings.
*/ 
function String_right( count )
{
	var sResult;
	if ( this.length > count ) {
		sResult = this.substr( this.length - count );
	} else {
		sResult = this;
	}
	return sResult;
}

String.prototype.right = String_right;

// --------------------------------------------------------------------
// Klassendefinitionen.

/*!
** Klasse oder besser Struktur mit Angaben zum Regelsatz in einem Bundesland
*/
function Regelsatz()
{
	this.hv		= 0;	// Haushaltsvorstand
	this.ha0	= 0;	// Haushaltsangehörige 0 - 6
	this.ha0Ae	= 0;	// Haushaltsangehörige 0 - 6 von alleinerziehenden
	this.ha7	= 0;	// Haushaltsangehörige 7 - 13
	this.ha14	= 0;	// Haushaltsangehörige 14 - 17
	this.ha18	= 0;	// Haushaltsangehörige über 18
}

function MbErnaehrung()
{
	this.abs = 0;
	this.rel = 0;
}


/*!
** Klasse für den Bedarfsblock.
*/
/*!
** c'tor. Initialisiert alle Variablen. 
**
** Zur besseren Dokumentation werden hier alle berechneten Felder 
** erst mal auf 0 gesetzt. Die Berechung findet dann in der Methode
** calc() statt.
*/
function Bedarf( frm )
{
	// Eingabe Felder
	this.blnSel		= frm.bdBlnSel.value;
	this.aeFlg		= frm.bdHvAeFlg.checked;
	this.hvShwFlg	= frm.bdHvShwFlg.checked;
	this.hvEwuMgFlg	= frm.bdHvEwuMgFlg.checked;
	this.hvU65MgFlg	= frm.bdHvU65MgFlg.checked;
	this.ha0Ct		= readInt( frm.bdHa0Ct );
	this.ha7Ct		= readInt( frm.bdHa7Ct );
	this.ha14Ct		= readInt( frm.bdHa14Ct );
	this.ha14ShwFlg = frm.bdHa14ShwFlg.checked;
	this.ha18Ct		= readInt( frm.bdHa18Ct );
	this.ha18ShwFlg	= frm.bdHa18ShwFlg.checked;
	this.ha18EwuMgFlg	= frm.bdHa18EwuMgFlg.checked;
	this.ha18U65MgFlg	= frm.bdHa18U65MgFlg.checked;
	
	// Ausgabe Felder
	this.oRst       = null;
	this.hv         = 0;
	this.hvShw      = 0;
	this.hvEwuMg    = 0;
	this.hvU65Mg    = 0;
	this.ha0        = 0;
	this.ha7        = 0;
	this.ha14       = 0;
	this.ha14Shw    = 0;
	this.ha18       = 0;
	this.ha18Shw    = 0;
	this.ha18EwuMg  = 0;
	this.ha18U65Mg  = 0;
	
	this.sum = 0;
	
	// Methoden
	this.calc  = Bedarf_calc;
	this.check = Bedarf_check;
	this.dump  = Bedarf_dump;
}

function Bedarf_check( frm )
{
	setCheckBorder( frm.bdHvShwFlg,   this.hvShwFlg && this.hvU65MgFlg  );
	setCheckBorder( frm.bdHvU65MgFlg, this.hvShwFlg && this.hvU65MgFlg  );
	
	setCheckBorder( frm.bdHa18ShwFlg, this.ha18ShwFlg && this.ha18U65MgFlg  );
	setCheckBorder( frm.bdHa18U65MgFlg, this.ha18ShwFlg && this.ha18U65MgFlg  );
	
	return !( this.hvShwFlg   && this.hvU65MgFlg 
	       || this.ha18ShwFlg && this.ha18U65MgFlg );
}


/*!
** Auswertung der Eingaben und Berechnung der Ausgaben.
*/
function Bedarf_calc()
{
	this.oRst = rgRst[this.blnSel]
	
	this.hv   = this.oRst.hv;
	if ( this.aeFlg ) 
		this.ha0  = this.ha0Ct * this.oRst.ha0Ae; 
	else
		this.ha0  = this.ha0Ct * this.oRst.ha0; 
		
	this.ha7  = this.ha7Ct * this.oRst.ha7; 
	this.ha14 = this.ha14Ct * this.oRst.ha14; 
	this.ha18 = this.ha18Ct * this.oRst.ha18; 
	
	if ( this.hvShwFlg )
		this.hvShw = this.hv.percent(20);
	if ( this.hvEwuMgFlg )
		this.hvEwuMg = this.hv.percent(20);
	if ( this.hvU65MgFlg )
		this.hvU65Mg = this.hv.percent(20);

	if ( this.ha14ShwFlg )
		this.ha14Shw = this.ha14.percent(20);

	if ( this.ha18ShwFlg )
		this.ha18Shw = this.ha18.percent(20);
	if ( this.ha18EwuMgFlg )
		this.ha18EwuMg = this.ha18.percent(20);
	if ( this.ha18U65MgFlg )
		this.ha18U65Mg = this.ha18.percent(20);
		
	this.sum = this.hv + this.hvShw + this.hvEwuMg + this.hvU65Mg
	         + this.ha0 + this.ha7
	         + this.ha14 + this.ha14Shw
	         + this.ha18 + this.ha18Shw + this.ha18EwuMg + this.ha18U65Mg;
	         
}

/*!
** Ausgabe der berechneten Felder im Forumlar.
*/
function Bedarf_dump( frm )
{
	writeNum( frm.bdHv, this.hv, bShowAll );
	writeNum( frm.bdHvShw, this.hvShw, bShowAll );
	writeNum( frm.bdHvEwuMg, this.hvEwuMg, bShowAll );
	writeNum( frm.bdHvU65Mg, this.hvU65Mg, bShowAll );
	writeNum( frm.bdHa0, this.ha0, bShowAll );
	writeNum( frm.bdHa7, this.ha7, bShowAll );
//	writeNum( frm.bdHa14, this.ha14, bShowAll );
	writeNum( frm.bdHa14Shw, this.ha14 + this.ha14Shw, bShowAll );
//	writeNum( frm.bdHa18, this.ha18, bShowAll );
	writeNum( frm.bdHa18Shw, this.ha18 + this.ha18Shw, bShowAll );
	writeNum( frm.bdHa18EwuMg, this.ha18EwuMg, bShowAll );
	writeNum( frm.bdHa18U65Mg, this.ha18U65Mg, bShowAll );

	writeNum( frm.bd, this.sum, true );
}

/*!
** Klasse für den Block Mehrbedarf.
*/
function Mehrbedarf( frm )
{
	// Eingabe Felder
	this.kidU7Flg	= frm.mbKidU7Flg.checked;
	this.kid2U16Flg	= frm.mbKid2U16Flg.checked;
	this.kid4U16Flg	= frm.mbKid4U16Flg.checked;
	this.erngSel    = frm.mbErngSel.value;
	
	// Ausgabe Felder
	this.kidU7   = 0;
	this.kid2U16 = 0;
	this.kid4U16 = 0;
	this.erng    = 0;
	
	this.sum = 0;
	
	// Methoden
	this.calc = Mehrbedarf_calc;
	this.dump = Mehrbedarf_dump;
}

function Mehrbedarf_calc( oBd )
{
	if ( oBd.aeFlg ) {
		// Nur bei Alleinerziehenden: Maximalen Zuschlag bestimmen.
		if ( this.kid4U16Flg ) {
			this.kid4U16 = oBd.hv.percent( 60 );
			this.kidU7Flg = 0;
			this.kid2U16Flg = 0;
		} else if ( this.kidU7Flg ) {
			this.kidU7 = oBd.hv.percent( 40 );
			this.kid2U16Flg = 0;
		} else if ( this.kid2U16Flg ) {
			this.kid2U16 = oBd.hv.percent( 40 );
		}
	}
	var erngId = this.erngSel;
	if ( erngId != 0 ) {
		var mbe = rgMbe[erngId];
		
		if ( mbe.abs != null ) {
			this.erng = mbe.abs;
		} else if ( mbe.rel != null ) {
			this.erng = oBd.hv.percent( mbe.rel );
		}
	}
	
	this.sum = this.kidU7 + this.kid2U16 + this.kid4U16 + this.erng;
}

function Mehrbedarf_dump( frm )
{
	writeNum( frm.mbKidU16, this.kidU7, bShowAll );
	writeNum( frm.mbKid2U16, this.kid2U16, bShowAll );
	writeNum( frm.mbKid4U16, this.kid4U16, bShowAll );
	writeNum( frm.mbErng, this.erng, bShowAll );

	frm.mbKidU7Flg.checked = this.kidU7Flg;
	frm.mbKid2U16Flg.checked = this.kid2U16Flg;
	frm.mbKid4U16Flg.checked = this.kid4U16Flg;
	
	writeNum( frm.mb, this.sum, true );
}


/*!
** Klasse für den Block Versicherung / vs.
*/
function Versicherung( frm )
{
	// Eingabe Felder
	this.kvPv = readNum( frm.vsKvPv );
	
	// Ausgabe Felder
	this.sum = 0;
	
	// Methoden
	this.calc = Versicherung_calc;
	this.dump = Versicherung_dump;
}

function Versicherung_calc()
{
	this.sum = this.kvPv;
}

function Versicherung_dump( frm )
{
	writeNum( frm.vs, this.sum, true );
}


/*!
** Klasse für den Block Unterkunftskosten und Heizung / uk
*/
function Unterkunft( frm )
{
	// Eingabe Felder
	this.miete	= readNum( frm.ukMiete );
	this.stadt	= readNum( frm.ukStadt );
	this.hzkSel = frm.ukHzkSel.value;
	this.hzkB   = readNum( frm.ukHzkB );
	
	// Ausgabe Felder
	this.hzk = 0;
	
	this.sum = 0;
	
	// Methoden
	this.calc = Unterkunft_calc;
	this.dump = Unterkunft_dump;
}

function Unterkunft_calc( oBd )
{
	if ( this.hzkB == 0 && this.hzkSel != 0 ) {
		var rgWerte = rgHzk[this.hzkSel];
		var persCt	= oBd.ha0Ct  + oBd.ha7Ct
					+ oBd.ha14Ct + oBd.ha18Ct
					+ 1; // HV
		var index   = Math.min( persCt, rgWerte.length ) - 1;
		
		this.hzk = rgWerte[index];
	}
             
	this.sum = this.miete + this.stadt + this.hzk + this.hzkB;
}

function Unterkunft_dump( frm )
{
	writeNum( frm.ukHzk, this.hzk, bShowAll );
	writeNum( frm.uk, this.sum, true );
}


/*!
** Klasse für den Block Monatliches Einkommen / ne
*/
function Einkommen( frm )
{
	// Eingabe Felder
	this.lohn1 = readNum( frm.neLohn1 );
	this.lohn2 = readNum( frm.neLohn2 );
	// Kindergeld kann unter den Beziehnungsberechtigen aufgeteilt werden.
	// Daher kann die Eingabe auch frei sein. 
	oFieldIgn  = frm.neKidCt;
	this.kidCt = readNum( frm.neKidCt );   
	oFieldIgn  = null;
	this.kidB  = readNum( frm.neKidB );
	this.unth  = readNum( frm.neUnth );
	this.untv  = readNum( frm.neUntv );
	this.algh  = readNum( frm.neAlgh );
	this.aaEtc = readNum( frm.neAaEtc );
	this.kkg   = readNum( frm.neKkg );
	this.rente = readNum( frm.neRente );
	this.wohng = readNum( frm.neWohng );
	this.etc1  = readNum( frm.neEtc1 );

	// Ausgabe Felder
	this.kid    = 0;
	this.alghM  = 0;
	this.aaEtcM = 0;
	this.kkgM   = 0;
	this.sum    = 0;
	
	// Methoden
	this.calc = Einkommen_calc;
	this.dump = Einkommen_dump;
}

function Einkommen_calc()
{
	var i;
	// Berechnungsformel für Kindergeld macht nur in einfachen Fällen Sinn. 
	// Daher Kindergeld laut Beischeid den Vorzug geben.
	if ( this.kidB == 0 ) {
		var n = Math.min( this.kidCt, rgKg.length );
		for ( i = 0; i < n; ++i ) {
			this.kid+= rgKg[i];
		}
		if ( this.kidCt > rgKg.length ) {
			var kgDef = rgKg[rgKg.length-1];
			this.kid+= kgDef * ( this.kidCt - rgKg.length );
		}
	} 
	
	this.alghM  = Math.round( this.algh  * 36500 / ( 12 * 7 ) ) / 100;
	this.aaEtcM = Math.round( this.aaEtc * 36500 / ( 12 * 7 ) ) / 100;
//	this.alghM  = Math.round( this.algh  * 1300 / 3 ) / 100;
//	this.aaEtcM = Math.round( this.aaEtc * 1300 / 3 ) / 100;
	this.kkgM   = this.kkg * 30;
	
	this.sum = this.lohn1  + this.lohn2 + this.kid   + this.kidB
	         + this.unth   + this.untv  + this.alghM
	         + this.aaEtcM + this.kkgM   + this.rente 
	         + this.wohng  + this.etc1;
}

function Einkommen_dump( frm )
{
	writeNum( frm.neKid, this.kid, bShowAll );
	writeNum( frm.neAlghM, this.alghM );
	writeNum( frm.neAaEtcM, this.aaEtcM );
	writeNum( frm.neKkgM, this.kkgM );
	writeNum( frm.ne, this.sum, true );
}

/*!
** Klasse für den Einkommensbereinigung / be
*/
function Bereinigung( frm )
{
	// Eingabe Felder
	this.abmp1Flg	= frm.ebAbmp1Flg.checked;
	this.abmn1		= readNum( frm.ebAbmn1 );
	this.oepnv1		= readNum( frm.ebOepnv1 );
	this.kfz1Km		= readNum( frm.ebKfz1Km );
	this.bvb		= readNum( frm.ebBvb );
	this.etc        = readNum( frm.ebEtc );
	this.vsHr		= readNum( frm.ebVsHr );
	this.vsHpf		= readNum( frm.ebVsHpf );
	this.vsEtc		= readNum( frm.ebVsEtc );
	
	
	// Ausgabe Felder
	this.frei1 = 0;
	this.abmp1 = 0;
	this.kfz1 = 0;
	this.vs	= 0;
	this.famFrei = 0;
	
	this.sum = 0;
	
	// Methoden
	this.calc = Bereinigung_calc;
	this.dump = Bereinigung_dump;
}

function Bereinigung_calc( oBd, oNe )
{
	// Freibetrag Erwerbstätigkeit.
	// Nach jedem Rechenschritt muss auf zwei Nachkommastellen gerundet werden,
	// daher etwas umständlich.
	var gfb;      // Grundfreibetrag
	var fb2;      // Freibetrag des über den gfb hinausgehenden Erwerbeinkommens.
	var frMax;    // Maximaler Freibetrag.

	this.vs     = this.vsHr + this.vsHpf + this.vsEtc;

	this.famFrei = cFamFrei * Math.min( oNe.kidCt, cMaxFamFrei );

	// Arbeitsmittel und Fahrkosten nur berechnenen wenn Nettoeinkommen vorhanden.
	if ( oNe.lohn1 > 0 ) {
		// Arbeitsmittelpauschale nur berechnen wenn kein Einzelnachweis.
		if ( this.abmn1 == 0 ) {
			this.abmp1Flg = oNe.lohn1 != 0;
			this.abmp1 = this.abmp1Flg ? cAmpPausch : 0;
		} else {
			this.abmp1Flg = false;
		}

		// KM Pauschale Fahrtkosten auf 40km beschränken.
		this.kfz1Km = Math.min( this.kfz1Km,  cMaxKfzKm );
		this.kfz1   = this.kfz1Km * cKfzKmPausch;
	}

	
	if ( oNe.lohn1 > 0 ) {
		// Berechnung des Freibetrags. 
		// Laut Thorsten müssen zunächst gemäß § 76 einige Ausgabe abgezogen werden.
		//var netto = oNe.lohn1 - ( this.vs + this.famFrei + this.abmp1 + this.abmn1 + this.kfz1);
		// Laut Harald nicht:
		var netto = oNe.lohn1;
		
		if ( oBd.aeFlg ) {
			// Erwerbstätige trotz beschränktem Leistungsvermögens.
			// Hier: Alleinerziehende
			gfb  = oBd.hv.percent(30);
			fb2  = Math.max( netto - gfb, 0).percent( 25 );
			frMax = (oBd.hv * 2 / 3).round2();
		} else if ( oBd.hvEwuMgFlg || oBd.bdHvU65MgFlg ) {
			// Erwerbstätige Blinde und Schwerstsbehinderte mit Merkzeichen G.
			gfb = oBd.hv.percent(50);
			fb2 = Math.max( netto - gfb, 0).percent( 25 );
			frMax = oBd.hv;
		} else {
			// Freibetrag für "normale" Erwerbstätige
			gfb = oBd.hv.percent(25);
			fb2 = Math.max( netto - gfb, 0).percent( 15 );
			frMax = oBd.hv.percent(50);
		}
		this.frei1 = gfb + fb2;
		this.frei1 = Math.min( this.frei1, frMax );


		/*
		** Freibeträge deckeln mit Nettoeinkommen.
		*/
		
		// Erstmal alles das übers Einkommen hinausgehende vom Freibetrag abziehen.
		this.frei1 = Math.min( this.frei1, netto );
		if ( this.frei1 + this.abmp1 > netto ) {
			this.frei1-= Math.min( this.frei1, (this.frei1 + this.abmp1) - netto );
		}
		if ( this.frei1 + this.abmn1 > netto ) {
			this.frei1-= Math.min( this.frei1, (this.frei1 + this.abmn1) - netto );
		}
		if ( this.frei1 + this.oepnv1 > netto ) {
			this.frei1-= Math.min( this.frei1, (this.frei1 + this.oepnv1) - netto );
		}
		if ( this.frei1 + this.kfz1 > netto ) {
			this.frei1-= Math.min( this.frei1, (this.frei1 + this.kfz1) - netto );
		}
		
		// Immer noch drüber (eingabe fake)? 
		// Freibeträge für Kosten reduzieren.
		if ( this.frei1 + this.kfz1 > netto ) {
			this.kfz1-= Math.min( this.kfz1, (this.frei1 + this.kfz1) - netto );
		}
		if ( this.frei1 + this.oepnv1 > netto ) {
			this.oepnv1-= Math.min( this.oepnv1, (this.frei1 + this.oepnv1) - netto );
		}
		if ( this.frei1 + this.abmn1 > netto ) {
			this.abmn1-= Math.min( this.abmn1, (this.frei1 + this.abmn1) - netto );
		}
		if ( this.frei1 + this.abmp1 > netto ) {
			this.abmp1-= Math.min( this.abmp1, (this.frei1 + this.abmp1) - netto );
		}
	} else {
		this.abmp1Flg = false;
	}
	
	
	
	this.sum = this.frei1 + this.abmp1 + this.abmn1 + this.oepnv1 + this.kfz1
	         + this.bvb   + this.etc   + this.vs    + this.famFrei;
}

function Bereinigung_dump( frm )
{
	writeNum( frm.ebFrei1, this.frei1, bShowAll );
	frm.ebAbmp1Flg.checked = this.abmp1Flg;
	writeNum( frm.ebAbmp1, this.abmp1, bShowAll );
	writeNum( frm.ebAbmn1, this.abmn1, bShowAll );
	writeNum( frm.ebOepnv1, this.oepnv1, bShowAll );
	writeInt( frm.ebKfz1Km, this.kfz1Km, bShowAll );
	writeNum( frm.ebKfz1, this.kfz1, bShowAll );
	writeNum( frm.ebVs, this.vs, bShowAll );
	writeNum( frm.ebFamFrei, this.famFrei, bShowAll );

	writeNum( frm.eb, this.sum, true );
}

/*!
** Hier wird alles berechnet.
*/

function calc( frm )
{
	var oBd = new Bedarf( frm );
	var oMb = new Mehrbedarf( frm );
	var oVs = new Versicherung( frm );
	var oUk = new Unterkunft( frm );
	var oNe = new Einkommen( frm );
	var oEb = new Bereinigung( frm );
	var bdSum;
	var neSum;
	var anspr;
	var checkOk = true;
	
	oBd.calc();
	checkOk = oBd.check( frm ) && checkOk;
	oBd.dump( frm );
	
	oMb.calc( oBd );
	oMb.dump( frm );
	
	oVs.calc();
	oVs.dump( frm );
	
	oUk.calc( oBd );
	oUk.dump( frm );
	
	bdSum = oBd.sum + oMb.sum + oVs.sum + oUk.sum;
	writeNum( frm.sumBed, bdSum, true );
	
	oNe.calc();
	oNe.dump( frm );

	oEb.calc( oBd, oNe );
	oEb.dump( frm );
	
	neSum = oNe.sum - oEb.sum;
	if ( neSum < 0 ) neSum = 0;	
	writeNum( frm.sumNe, neSum, true );
	
	anspr = bdSum - neSum;
	if ( anspr < 0 ) anspr = 0;
	
	writeNum( frm.endBd, bdSum, true );
	writeNum( frm.endNe, neSum, true );
	writeNum( frm.end, anspr, true );
}


// --------------------------------------------------------------------
// Eventhandler 

function onSubmit( frm )
{
	calc( frm );
}

function onPrint( frm )
{
	var frm = document.input;
	document.input.action = "?print=1";
	frm.submit();
}

function onBlur( oField )
{
	calc( oField.form );
}

/*!
** Hilfe Fenster in den Vordergrund holen oder öffnen.
*/

var oWndHelp //!< Hilfefenster falls bereits geöffnet.;

function openHelp( sTopic )
{
	var href = "sb_hilfe.asp";
	
	if ( sTopic && sTopic.length > 0 ) {
		href+= "?topic=" + sTopic;
	}

	if ( !oWndHelp || oWndHelp.closed ) {
		var cx  = Math.max( screen.width  * 0.382, 100 );
		var cy  = Math.max( screen.height * 0.382, 100 );
		var args = "width=" + cx.toString();
		args+= ", height=" + cy.toString();
		args+= ", resizable=yes";
		args+= ", scrollbars=yes";
		//args+= ", location=yes";
		//args+= ", menubar=yes";
		//args+= ", toolbar=yes";
		//args+= ", status=yes";
		oWndHelp = window.open( href, "help", args );
	} else {
		oWndHelp.location.replace( href );
	}
	oWndHelp.focus();
}



/*!
** Debughilfe: Name aller Felder ausgeben.
*/
function onDumpNames( frm )
{
	frm.reset();
	
	var e = new Enumerator( frm.elements );
	
	while ( !e.atEnd() ) {
		var f = e.item();
		
		if ( f.type == "select-one" ) {
			f.options[0].text     = f.name;
			f.options[0].selected = true;
		} else if ( f.type == "text" ) {
			f.value = f.name;
			f.size  = 10;
		} else if ( f.type == "checkbox" || f.type == "radio" ) {
			var i = 0;
			var l = document.getElementsByTagName( "label" )[i];
			while ( l ) {
				if ( l.htmlFor == f.id )
					break;
				++i;
				l = document.getElementsByTagName( "label" )[i];
			}
			if ( l ) {
				var r = new RegExp( f.name );
				if ( l.innerText.search( r ) < 0 ) {
					l.innerHTML = "<i>" + f.name + "</i>" + " "+ l.innerText;
				}
			}
		}
		e.moveNext();
	}
}

