function Form( htmlElement )
{				
	// Connect object to element
	this.mElement = htmlElement;
	htmlElement.form = this;

	// Initialize properties
	this.mFieldLength = 0;
	this.mFields = new Object();
	this.mFieldList = new Array();
	var fieldElements = htmlElement.elements;
	var fieldElementsLength = fieldElements.length;
	var fieldElement = null;
	var fieldName = null;
	var field = null;
	var fieldType = null;
	for( var i=0; i < fieldElementsLength; i++ )
	{
		// Check whether field already exists
		fieldElement = fieldElements[i];
		fieldName = this.GetFieldName( fieldElement );
		if ( fieldName == null ) // Skip field is fieldname is not valid
			continue;
			
		field = this.mFields[ fieldName ];
		if ( field == null )
		{
			fieldType = fieldElement.getAttribute( 'binding' );
			if ( fieldType == null )
				fieldType = fieldElement.type;
				
			// Create new Formfield object and attach it to the element
			switch( fieldType )
			{
				case 'adviesblok':
					field = new AdviesblokField( fieldElement, this );
					break;
				case 'excelcalculation':
					field = new ExcelcalculationField( fieldElement, this );
					break;
				case 'formula':
					field = new FormulaField( fieldElement, this );
					break;
				case 'radio':
					field = new RadioField( fieldElement, this );
					break;
				default:
					field = new FormField( fieldElement, this );
					break;
			}

			this.mFields[ fieldName ] = field;
			this.mFieldList.push( field );
			this.mFieldLength++;
		}
		else if ( fieldElement.type == 'radio' )
		{
			// Only radio fields can have the same name
			fieldElement.field = field;
			
			// Create list of radio elements, push first element on list
			if ( field.mElements == null )
			{
				field.mElements = new Array();
				field.mElements.push( field.mElement );
			}
			field.mElements.push( fieldElement );
		}
		else
		{
			alert( 'FormFields cannot have the same name: ' + fieldElement.getAttribute( 'name' ) );
		}
	}
	
	// Hack to make paragraph conditional
	var paragraphList = document.getElementsByTagName( "SPAN" );
	var paragraphListLength = paragraphList.length;
	for( var i=0; i < paragraphListLength; i++ )
	{
		// Check whether field already exists
		fieldElement = paragraphList[i];
		fieldType = fieldElement.getAttribute( 'binding' );
		if ( fieldType == 'paragraph' )
		{
			fieldName = this.GetFieldName( fieldElement );
			if ( fieldName == null ) // Skip field is fieldname is not valid
				continue;

			field = new FormField( fieldElement, this );

			this.mFields[ fieldName ] = field;
			this.mFieldList.push( field );
			this.mFieldLength++;		
		}
	}
		
	// Set condition handlers and dependencies and hide the fields
	var targetField = null;
	for( var i=0; i < this.mFieldLength; i++ )
	{	
		field = this.mFieldList[ i ];
		// Set condition dependencies
		if ( field.mConditionField !== null )
		{
			targetField = this.GetField( field.mConditionField );
			if ( targetField != null )
			{
				targetField.AddListener( field );
				field.NotifyChange( field.mConditionField, targetField.GetValue() ); 
			}
		}
		
		// Set field dependencies
		if ( field.SetDependencies )
			field.SetDependencies();
	}			
}

// Method: GetField
Form.prototype.GetField = _Form_GetField;
function _Form_GetField( fieldName )
{
	if ( IsEmpty( fieldName ) )
		return null;

	return this.mFields[ fieldName.toLowerCase() ];
}

// Method: GetField
Form.prototype.GetFieldName = _Form_GetFieldName;
function _Form_GetFieldName( fieldElement )
{
	var name = fieldElement.getAttribute( 'name' );
	
	if( name != null && ( name.indexOf( 'PostedField[' ) == 0 || name.indexOf( 'Node_' ) == 0 ) )
		return name.substring( name.indexOf( '[' ) + 1, name.indexOf( ']' ) ).toLowerCase();
	else
		return null;
}

//-----------------------------------------------------------------------------------------------------
// Class: formfield
function FormField( htmlElement, formObject )
{
	// Initialize element
	if ( htmlElement != null )
		this.Initialize( htmlElement, formObject );
}

// Method: Initialize
FormField.prototype.Initialize = _FormField_Initialize;
function _FormField_Initialize( htmlElement, formObject )
{
	// Initialize properties
	this.mForm = formObject;
	this.mElement = htmlElement;

	var fieldType = htmlElement.getAttribute( 'binding' );
	if ( fieldType == null )
		fieldType = htmlElement.type;
	this.mType = fieldType;
	
	// Set reference in htmlElement to this field
	htmlElement.field = this;
	
	// Set name, label, etc
	var attributes = htmlElement.attributes;
	this.mName = this.mForm.GetFieldName( htmlElement );
	this.mId = attributes.getNamedItem( 'id' ).value; 
	this.mId = this.mId.substring( this.mId.indexOf( '[' ) + 1, this.mId.indexOf( ']' ) ); // extract id from FormField[id]

	if ( attributes.getNamedItem( 'label' ) )
		this.mLabel = attributes.getNamedItem( 'label' ).value;
	
	// Check required
	this.mRequired = false;	
	if ( IsTrue( attributes.getNamedItem( 'required' ) ) )
		this.mRequired = true;
		
	// Set enabled property
	this.mIsEnabled = true;

	// Check conditions
	if ( attributes.getNamedItem( 'condition' ) != null )
	{
		var condition = attributes.getNamedItem( 'condition' ).value;
		if ( ! IsEmpty( condition ) )
		{
			var equalPos = condition.indexOf( '=' );
			if ( equalPos > -1 )
			{
				var conditions = ParseQueryString( condition );
				for( var key in conditions )
				{
					if ( key == null )
						break;
					
					if ( conditions[ key ] == null )
						break;
					
					this.mConditionValues = conditions[ key ].split( '|' );
					this.mConditionField = key.toLowerCase();		 
				}
			}
		}
	}
}

// Method: AddListener 
FormField.prototype.AddListener = _FormField_AddListener;
function _FormField_AddListener( element ) 
{
	if ( this.mListeners == null )
		this.mListeners = new Array();

	this.mListeners.push( element );
}

// Method: Display
FormField.prototype.DisplayField = _FormField_DisplayField;
function _FormField_DisplayField()
{
	var htmlElement = document.getElementById( 'FieldContainer-' + this.mId );
	if ( htmlElement )
	{
		// Make lighter in backoffice mode
		if ( top.name != 'LynkxCanvas' )
			htmlElement.style.display = '';
		else
			htmlElement.disabled = false;
			
		this.mElement.disabled = false;
	}
}

// Method: GetValue
FormField.prototype.GetValue = _FormField_GetValue;
function _FormField_GetValue()
{
	return this.mElement.value;
}

// Method: Handle change Event
// If field is conditional, check condition values
FormField.prototype.NotifyChange = _FormField_NotifyChange;
function _FormField_NotifyChange( fieldName, fieldValue )
{
	// Check fieldName
	if ( this.mConditionField != fieldName )
		return;
		
	// Check condition values
	if ( this.mConditionValues == null )
		return;
	
	var boolConditionMet = false;
	if ( this.mConditionValues[ 0 ] == "not_empty" )
	{
		boolConditionMet = ! IsEmpty( fieldValue );
	}
	else
	{
		var length = this.mConditionValues.length;

		for( var i=0; i < length; i++ )
		{
			if ( this.mConditionValues[ i ] == fieldValue )
			{
				boolConditionMet = true;
				break;
			}
		}
	}
	
	// if no conditionvalue is found, disabled field
	if ( boolConditionMet )
	{
		if ( ! this.mIsEnabled )
		{
			this.mIsEnabled = true;
			this.DisplayField();
			this.OnChange();
		}
	}
	else
	{
		if ( this.mIsEnabled )
		{
			this.mIsEnabled = false;
			this.HideField();
			this.OnChange();
		}
	}
}

// Method: Hide
FormField.prototype.HideField = _FormField_HideField;
function _FormField_HideField()
{
	var htmlElement = document.getElementById( 'FieldContainer-' + this.mId );
	if ( htmlElement )
	{
		// Make lighter in backoffice mode
		if ( top.name != 'LynkxCanvas' )
			htmlElement.style.display = 'none';
		else
		{
			htmlElement.disabled = true;
		}
			
		this.mElement.disabled = true;
	}
}

// Method: get value on radio
FormField.prototype.SetDependency = _FormField_SetDependency;
function _FormField_SetDependency( fieldName )
{
	// Name check
	if ( IsEmpty ( fieldName ) )
		return;

	// Initialize publishers dictionary
	if ( this.mPublishers == null )
		this.mPublishers = new Object();
	
	// Only add dependency once
	fieldName = fieldName.toLowerCase();
	var targetField = this.mForm.GetField( fieldName );
	if ( this.mPublishers[ fieldName ] == null &&  targetField != null )
	{
		targetField.AddListener( this );
		this.mPublishers[ fieldName ] = targetField;
	}
}

// Method: OnChange Event
FormField.prototype.OnChange = _FormField_OnChange;
function _FormField_OnChange()
{
	if( this.mListeners == null )
		return;
		
	var length = this.mListeners.length;
	for ( var i=0; i < length; i++ )
	{
		this.mListeners[ i ].NotifyChange( this.mName, this.GetValue() );		
	}	
}

// Method: OnKeyUp
FormField.prototype.OnKeyDown = _FormField_OnKeyDown;
function _FormField_OnKeyDown( currentEvent )
{
	switch( currentEvent.keyCode )
	{
		case 13: // Fire onchange event if enter is pressed
			this.OnChange();
			break;
	}
	
	return true;
}


// Method: GetValue
FormField.prototype.SetValue = _FormField_SetValue;
function _FormField_SetValue( value )
{
	this.mElement.value = value;
}

// Specific FormFields --------------------------------------------------------

//-----------------------------------------------------------------

// Class: AdviesblokField 
function AdviesblokField( htmlElement, formObject )
{
	// Initialize field
	this.Initialize( htmlElement, formObject );
		
	// Initiaze properties
	this.mAdviesblokFields = new Object();
	this.mAdviesConditionField = htmlElement.getAttribute( 'adviesConditionField' ).toLowerCase();
	this.mTextElement = document.getElementById( 'FormField[' +this.mId + ']-text' );
		
	var adviesCondition = null;
	for( var i = 1; i < 11; i++ )
	{
		adviesCondition = htmlElement.getAttribute( 'condition' + i );
		if ( ! IsEmpty( adviesCondition ) )
			this.mAdviesblokFields[ adviesCondition ] = htmlElement.getAttribute( 'advies' + i );
	}
}

// Extend: Field
AdviesblokField.prototype = new FormField();
AdviesblokField.prototype.constructor = AdviesblokField;

// Method: GetNumberValueOf fieldName
AdviesblokField.prototype.SetDependencies = _AdviesblokField_SetDependencies;
function _AdviesblokField_SetDependencies()
{
	if ( this.mAdviesConditionField != '' )
		this.SetDependency( this.mAdviesConditionField );
}

// Method: GetNumberValueOf fieldName
AdviesblokField.prototype.GetNumberValueOf = _FormulaField_GetNumberValueOf;

// Method: GetNumberValueOf fieldName
AdviesblokField.prototype.GetValueOf = _FormulaField_GetValueOf;

// Method: Handle change Event
// If field is conditional, check condition values
AdviesblokField.prototype.NotifyChange = _AdviesblokField_NotifyChange;
AdviesblokField.prototype._base_NotifyChange = _FormField_NotifyChange;
function _AdviesblokField_NotifyChange( fieldName, fieldValue )
{
	// Execute base handle change
	this._base_NotifyChange( fieldName, fieldValue );
	if ( this.mAdviesConditionField != fieldName )
		return;
	
	var result = false;
	for( var condition in this.mAdviesblokFields )
	{
		if ( fieldValue == condition )
		{
			this.SetValue( this.mAdviesblokFields[ condition ] );
			return;
		}
		else if ( condition.substr(0,1) == '>' || condition.substr(0,1) == '<' || condition.substr(0,1) == '!' )
		{
			eval( 'result = ( ' + fieldValue + ' ' + condition + ' );' );
			if ( result == true )
			{
				this.SetValue( this.mAdviesblokFields[ condition ] );
				return;				
			}
		}
		else
		{
			var pos = condition.indexOf( '-' );
			if ( pos > 0 )
			{
				eval( 'result = ( ' + fieldValue + '>=' + condition.substr( 0, pos ) + ' && ' + fieldValue + ' <= ' + condition.substr( pos + 1 ) + ' );' );
				if ( result == true )
				{
					this.SetValue( this.mAdviesblokFields[ condition ] );
					return;				
				}
			}
		}
	}

	this.SetValue( '' );
}

// Method: GetValue
AdviesblokField.prototype.SetValue = _AdviesblokField_SetValue;
function _AdviesblokField_SetValue( value )
{
	this.mElement.value = value;
	this.mTextElement.innerHTML = value;
	this.OnChange();
}

/*----------------------------------------------------------------------------*/

// Class: CheckboxField 
function CheckboxField( htmlElement, formObject )
{
	this.Initialize( htmlElement, formObject );
}

// Extend: Field
CheckboxField.prototype = new FormField();
CheckboxField.prototype.constructor = CheckboxField;

// Method: get checkbox value
CheckboxField.prototype.GetValue = _CheckboxField_GetValue;
function _CheckboxField_GetValue()
{
	// Get value
	if ( this.checked == true )
		return '1';
	else
		return '0';
}

// Method: GetValue
CheckboxField.prototype.SetValue = _CheckboxField_SetValue;
function _CheckboxField_SetValue( value )
{
	this.checked = IsTrue( value );
}
// Class: FormulaField 
function FormulaField( htmlElement, formObject )
{
	// Initialize field
	this.Initialize( htmlElement, formObject );
		
	// Initialize properties
	this.mFormula = htmlElement.getAttribute( 'formula' );
	this.mNumberFormat = htmlElement.getAttribute( 'numberFormat' );
	var entries = htmlElement.getAttribute( 'entries' );
	if ( ! IsEmpty( entries ) )
		this.mEntries = UnpackCSV( entries );
	
}

//-------------------------------------------------------------------
// Class: ExcelcalculationField 
function ExcelcalculationField( htmlElement, formObject )
{
	// Initialize field
	this.Initialize( htmlElement, formObject );
		
	// Initialize properties
	this.mFile = htmlElement.getAttribute( 'excelfile' );
	this.mNumberFormat = htmlElement.getAttribute( 'numberFormat' );
	var entries = htmlElement.getAttribute( 'entries' );
	if ( ! IsEmpty( entries ) )
		this.mEntries = UnpackCSV( entries );
}


// Extend: Field
ExcelcalculationField.prototype = new FormField();
ExcelcalculationField.prototype.constructor = ExcelcalculationField;

// Method: GetNumberValueOf fieldName
ExcelcalculationField.prototype.SetDependencies = _ExcelcalculationField_SetDependencies;
function _ExcelcalculationField_SetDependencies( fieldName )
{
	if ( this.mEntries == null )
		return;
		
	var length = this.mEntries.length;
	var entry = null;
	for( var i = 0; i < length; i++ )
	{
		entry = this.mEntries[i][ 'formfield' ];
		this.SetDependency( entry );
	} 
}

// Method: Handle change Event
// If field is conditional, check condition values
ExcelcalculationField.prototype.NotifyChange = _ExcelcalculationField_NotifyChange;
ExcelcalculationField.prototype._base_NotifyChange = _FormField_NotifyChange;
function _ExcelcalculationField_NotifyChange( fieldName, fieldValue )
{
	// Execute base handle change
	this._base_NotifyChange( fieldName, fieldValue );

	if ( this.mPublishers && this.mPublishers[ fieldName ] != null )
	{
		var entries = '';
		var field = null;
		if ( this.mEntries != null )
		{
			var length = this.mEntries.length;
			for( var i = 0; i < length; i++ )
			{
				field = this.mForm.GetField( this.mEntries[i]['formfield'] );
				if ( field != null )
				{
					var value = field.GetValue();
					if ( IsEmpty( value ) )
						value = '0';
					entries += this.mEntries[i]['excelfield'] + '=' + encodeURIComponent( value.replace( /\./g , '' ).replace( /\,/g, '.' ) ) + '%26';
				}
			}
		}

		var result = HttpChannel.Request( 'Excelberekeningen/Calculate.lynkx?id=' + this.mId + '&entries=' + entries );
		if ( top.Popup != null && result.substr( 0,6 ) == '<html>' )
			top.Popup( result, 'html' );
		
		var results = ParseQueryString( result );
		var key = null;
		for( key in results )
		{
			this.mForm.GetField( key ).SetValue( results[ key ] );
		}			
	}
}

// Method: GetValue
ExcelcalculationField.prototype.SetValue = _ExcelcalculationField_SetValue;
function _ExcelcalculationField_SetValue( value )
{
	if ( value != null && value.toString() == 'NaN' )
		value = '';
	this.mElement.value = value;
	this.OnChange();
}

//-----------------------------------------------------------------
var veldRegex = new RegExp( "veld\\(([^\\)]+)\\)", "gi" );
var textRegex = new RegExp( "text\\(([^\\)]+)\\)", "gi" );

// Class: FormulaField 
function FormulaField( htmlElement, formObject )
{
	// Initialize field
	this.Initialize( htmlElement, formObject );
		
	// Initialize properties
	this.mFormula = htmlElement.getAttribute( 'formula' );
	this.mNumberFormat = htmlElement.getAttribute( 'numberFormat' );
	var entries = htmlElement.getAttribute( 'entries' );
	if ( ! IsEmpty( entries ) )
		this.mEntries = UnpackCSV( entries );
	
}

// Extend: Field
FormulaField.prototype = new FormField();
FormulaField.prototype.constructor = FormulaField;

// Method: GetNumberValueOf fieldName
FormulaField.prototype.SetDependencies = _FormulaField_SetDependencies;
function _FormulaField_SetDependencies( fieldName )
{
	if ( ! IsEmpty( this.mFormula ) )
	{
		// eval formula to get find the used fields
		try 
		{
			var formula = this.mFormula;
			var matches = formula.match( veldRegex );
			if ( matches != null )
			{
				var length = matches.length;
				for( var i=0; i < length; i++ )
				{
					eval( matches[ i ].replace( 'veld', 'this.SetDependency' ) );
				}
			}
			matches = formula.match( textRegex );
			if ( matches != null )
			{
				var length = matches.length;
				for( var i=0; i < length; i++ )
				{
					eval( matches[ i ].replace( 'text', 'this.SetDependency' ) );
				}
			}			
		}
		catch( e )
		{
			if ( top.user && top.user.mName == 'System' )
				alert( 'Er zit een fout bij veld [' +  this.mName + '] in deze formule: ' + this.mFormula );
		}
	}
}

// Method: GetNumberValueOf fieldName
FormulaField.prototype.GetNumberValueOf = _FormulaField_GetNumberValueOf
function _FormulaField_GetNumberValueOf( fieldName )
{
	var value = this.GetValueOf( fieldName );
	
	// Make english notation
	if ( ! IsEmpty( value ) )
		value =  parseFloat( value.replace( /\./g , '' ).replace( /\,/g, '.' ) );

	if ( IsEmpty( value ) || isNaN( value ) )
		value = 0;
	
	return value;
}

// Method: GetNumberValueOf fieldName
FormulaField.prototype.GetValueOf = _FormulaField_GetValueOf;
function _FormulaField_GetValueOf( fieldName )
{
	var targetField = this.mForm.GetField( fieldName );
	if ( targetField == null )
	{
		alert( 'Veld ' + fieldName + ' bestaat niet' );
		return null;
	}
	
	if ( targetField.mIsEnabled )
		return targetField.GetValue();
	else 
		return null;
}


// Method: Handle change Event
// If field is conditional, check condition values
FormulaField.prototype.NotifyChange = _FormulaField_NotifyChange;
FormulaField.prototype._base_NotifyChange = _FormField_NotifyChange;
function _FormulaField_NotifyChange( fieldName, fieldValue )
{
	// Execute base handle change
	this._base_NotifyChange( fieldName, fieldValue );

	if ( this.mPublishers && this.mPublishers[ fieldName ] != null )
	{
	
		var result = eval( this.mFormula.replace( /veld\(/g, 'this.GetNumberValueOf(' ).replace( /text\(/g, 'this.GetValueOf(' ) );
		
		// Format result
		switch( this.mNumberFormat )
		{
			case 'rounded':
				result = Math.round( result );
				break;
			case 'currencyNL':
				result = FormatCurrency( result, 'NL' );
				break;
			case 'currencyEN':
				result = FormatCurrency( result, 'EN' );
				break;
			case 'NL':
				result = result.toString().replace( /\./g, ',' );
				break;
			case 'EN':
			default:
				// do nothing
				break;				
		}

		this.SetValue( result );
	}
}

// Method: GetValue
FormulaField.prototype.SetValue = _FormulaField_SetValue;
function _FormulaField_SetValue( value )
{
	if ( value != null && value.toString() == 'NaN' )
		value = '';
	this.mElement.value = value;
	this.OnChange();
}

//-----------------------------------------------------------------------------------------------------
// Class: RadioField 
function RadioField( htmlElement, formObject )
{
	this.Initialize( htmlElement, formObject );
}

// Extend: Field
RadioField.prototype = new FormField();
RadioField.prototype.constructor = RadioField;

// Method: get value on radio
RadioField.prototype.GetValue = _RadioField_GetValue;
function _RadioField_GetValue()
{
   // Initialize found
   var found = false;
   
   // Get html element, get number of options
   var radioOptions = this.mElements;
   var length = radioOptions.length;

   // Loop over all select options
   var i;
   for ( i = 0; i < length; i++ ) 
   {
      if ( radioOptions[ i ].checked == true ) 
      {
         return radioOptions[ i ].value;
      }
   }
   
   // Else return empty string, because initialValue is also an empty string, if not set.
   return "";
}

// Method: get value on radio
RadioField.prototype.SetValue = _RadioField_SetValue;
function _RadioField_SetValue( value )
{
   // Initialize found
   var found = false;
   
   // Get html element, get number of options
   var radioOptions = this.mElements;
   var length = radioOptions.length;

   // Loop over all select options
   var i;
   for ( i = 0; i < length; i++ ) 
   {
      if ( radioOptions[ i ].value == value ) 
      {
         radioOptions[ i ].checked = true;
         break;
      }
   }   
}

// Helper functions -----------------------------------------------------------

function FormatCurrency( number )
{
	if ( isNaN( number ) )
		return number;
		
	// Format with 2 decimals
	number = Math.round( number * 100 )/100;
	var numberString = number.toString();
	switch( numberString.indexOf( '.' )  )
	{
		case -1:
			numberString += '.00';
			break;
		case ( numberString.length - 2 ):
			numberString += '0';
			break;
	}
	
	numberString = numberString.replace( '.', ',' );

	// Format with thousands separator
	if ( number >= 1000 )
	{
		var startPos = numberString.indexOf( ',' ) - 3;
		var newNumberString = numberString.substr( numberString.length - 6 );
		while( startPos > 3 )
		{
			newNumberString = numberString.substr( startPos - 3, 3 ) + '.' + newNumberString;
			startPos -= 3;	
		}
		numberString = numberString.substr( 0, startPos ) + '.' + newNumberString;
	}

	return numberString;
}

// Is Empty Check
function IsEmpty( input ) 
{
	return ( input == null || input == '' );
}

// Check if value represents true
function IsTrue( value )
{
	// Set value to lowercase
	if ( typeof( value ) == 'string' )
	{
		value = value.toLowerCase();
	}
	
	// Set value
	return ( value == true 
			|| value == '1' 
			|| value == 'true' 
			|| value == 'yes'
			|| value == 'on' );
} 

// Return the query string as an assosiative array
function ParseQueryString( queryString )
{
	// Initialize variables
	var parameters = new Array();

	// Null check
	if ( queryString == null )
		return parameters;
		
	// strip ? from querystring
	var pos = queryString.indexOf('?');
	if ( pos > -1 )
		queryString = queryString.substr(pos+1);
	
	// Replace + by spaces ( decodeURI does not do that )	
	queryString = queryString.replace( /\+/g, ' ' );

	// Get parameters
	var keyValuePairs = queryString.split( '&' );
	var equalPos = -1;
	var parameter;
	for ( var i in keyValuePairs )
	{
	   // Split on =
	   parameter = keyValuePairs[ i ];
	   equalPos = parameter.indexOf( '=' );
	   if ( equalPos > -1 )
	   	parameters[ decodeURIComponent( parameter.substr( 0, equalPos ) ) ] = decodeURIComponent( parameter.substr( equalPos + 1 ) );
	}
	
	// Return parameters
	return parameters;
}

// Function: trim
function Trim( value )
{
	// Remove all leading and trailing white space
	return TrimRight( TrimLeft( value ) );
}

// Trim leading and trailing comma's
trimCommasRegExp = new RegExp( "^,*|,*$"  ,"gm" );
function TrimCommas( string )
{
   return string.replace( trimCommasRegExp, '' );
}

// Function: left trim
function TrimLeft( value )
{
	// Remove all leading white space
	return value.rereplace( "^\\s+", "" );
}

// Function: right trim
function TrimRight( value )
{
	// Remove all trailing white space
	return value.rereplace( "\\s+$", "" );
}

// UnpackCSV
function UnpackCSV ( csv ) {
   
   // initializing variables
   var i = 0;
   var data = new Array();
   var heading = new Array();
   if ( csv.charAt(csv.length-1) != ';') csv = csv + ';';

   while ((x = csv.indexOf(';'))>-1) {
      
      var row = csv.substr(0,x) + ',';
      var csv = csv.substr(x+1);
      var j = 0;
      data[i] = new Array();
      while ((y = row.indexOf(','))>-1) {

         var cell = row.substr(0,y);
         var row = row.substr(y+1);
         j++;
         if ( i == 0 ) {
            heading[j] = unescape(cell);
         } else {
            data[i][heading[j]] = unescape(cell);
         }
      }
      i++;
   }
   return data; 
}

// Rekenfuncties
function CalculateTax( income, currentYear )
{
	// Check income
	income = parseInt( income );
	if ( isNaN( income ) )
		return null;
	
	if ( IsEmpty( currentYear ) )
		currentYear = (new Date()).getFullYear();
	
	var taxtariffs = TaxesNL[ currentYear ];
	if ( taxtariffs == null )
	{
		alert( "Geen belastingtarieven voor '" + currentYear + "'");
		return null;
	}
	
	var currentTariff;
	var totalTax = 0;
	for( var grens in taxtariffs )
	{
		currentTariff = taxtariffs[ grens ];
		if ( income > grens )
		{
			totalTax += (income - grens) * currentTariff / 100;
			income = grens;
		}
	}
	
	return parseInt( totalTax );
}

var TaxesNL = 
{
	2006: 
	{ 
		52228: 52.00,
		30631: 42.00, 
		17046: 41.45, 
			 0: 34.15
	},
	2007: 
	{ 
		53064: 52.00,
		31122: 42.00, 
		17319: 41.40, 
			 0: 33.65
	}

};

function CalculateForfait( houseValue, currentYear )
{
	// Check income
	houseValue = parseInt( houseValue );
	if ( isNaN( houseValue ) )
		return null;
	
	if ( IsEmpty( currentYear ) )
		currentYear = (new Date()).getFullYear();
	
	var tariffs = EigenWoningForfait[ currentYear ];
	if ( tariffs == null )
	{
		alert( "Geen eigenwoningforfait tarieven voor '" + currentYear + "'");
		return null;
	}
	var maxForfait = EigenWoningForfait[ 'Max' + currentYear ];
	if ( maxForfait == null )
		maxForfait = Number.MAX_VALUE;
	
	var currentTariff;
	var forfait = 0;
	for( var grens in tariffs )
	{
		currentTariff = tariffs[ grens ];
		if ( houseValue > grens )
		{
			forfait = houseValue * currentTariff / 100;
			break;
		}
	}
	
	// Put maximum on forfait
	if ( forfait > maxForfait )
		forfait = maxForfait;
		
	return parseInt( forfait );
}

var EigenWoningForfait = 
{
	Max2006: 8750,
	2006: 
	{ 
		75000: 0.60,
		50000: 0.45, 
		25000: 0.35, 
		12500: 0.20,
		    0: 0.00
	},
	Max2007: 9150,
	2007: 
	{ 
		75000: 0.55,
		50000: 0.40, 
		25000: 0.30, 
		12500: 0.20,
		    0: 0.00
	}
};

function CalculateNettomaandlasten( inkomen1, inkomen2, jaarRente, forfait, jaarPremie )
{
	// Check input
	if ( IsEmpty( inkomen1 ) )
		inkomen1 = 0;
	if ( IsEmpty( inkomen2 ) )
		inkomen2 = 0;
	if ( IsEmpty( jaarRente ) )
		jaarRente = 0;
	if ( IsEmpty( forfait ) )
		forfait = 0;
	if ( IsEmpty( jaarPremie ) )
		jaarPremie = 0;
		
	var aftrekbareKosten = jaarRente - forfait;
	var aftrek1 = 0;
	var aftrek2 = 0;
	var inkomensverschil = inkomen1 - inkomen2;
	if ( inkomensverschil >= aftrekbareKosten )
		aftrek1 = aftrekbareKosten;
	else if ( aftrekbareKosten > inkomensverschil )
		aftrek2 = aftrekbareKosten;
	else if ( inkomensverschil > 0 )
	{
		aftrek1 = aftrekbareKosten - inkomensverschil;
		aftrek2 = inkomensverschil;
	}
	else
	{
		aftrek2 = aftrekbareKosten - inkomensverschil;
		aftrek1 = inkomensverschil;
	}
	
	var taxVoor1 = CalculateTax( inkomen1 );
	var taxNa1 = CalculateTax( inkomen1 - aftrek1 );
	var taxVoor2 = CalculateTax( inkomen2 );
	var taxNa2 = CalculateTax( inkomen2 - aftrek2 );
	var belastingvoordeel = ( taxVoor1 + taxVoor2 - taxNa1 - taxNa2 );
	
	var nettoRente = jaarRente - belastingvoordeel;
	
	return ( nettoRente + jaarPremie ) / 12;
}

function CalculatePayment( futureValue, interest, period )
{
	var sumOfInterest = ( Math.pow( 1+interest, period ) - 1 ) / interest;
	
	return futureValue / sumOfInterest / 12;
}