//initialization function, to invoke from the documen.ready function
var focusFormFieldId;
var lockScreenMode = true;

function initGeneral() {
	if( lockScreenMode ) {
		$( "[class~=lockScreen],[onclick*=document.location.href],a[href^=http]" ).click( 
			function( event ) {
				if( !( $( this ).hasClass( "dontLockScreen" ) ) && !( $( this ).attr( "target" ) == "_blank" ) ) {
					disableAllButtons( this );
					lockScreen();
				}
				
				return( true );
			} 
		);

		$( window ).unload( 
			function() {
				unlockScreen();
				
				return( true );
			}
		);
	}
	
	$( "input:text, input:password, input:radio, input:checkbox, textarea" ).addClass( "idle" )
	.focus( 
		function() {
			$( this ).addClass( "active" ).removeClass( "idle" );
		}
	)
	.blur(
		function() {
			$( this ).removeClass( "active" ).addClass( "idle" );
		}
	);

	$( "input.error, textarea.error, select.error" )
	.focus( 
		function() {
			var id = "#" + this.id + "Error";

			if( !( id == focusFormFieldId ) ) {
				if( focusFormFieldId ) {
					$( focusFormFieldId ).hide();
				}
								
				focusFormFieldId = id;
				
				$( id ).show();
			}
		}
	)
	.each(
		function() {
			var id = "#" + this.id + "Error";
			$( id ).hide();			
		}
	);
	
	if( lockScreenMode ) {
		$( "form" ).submit(
			function( event ) {
				event.preventDefault();			
				disableAllButtons( $( this ).find( "input:submit" ).first().get(0) );
				lockScreen();
				resetLabelValues();

				this.submit();
				
				return( false );
			}
		);
	}
}

//make all input buttons, submit buttons and links look enabled by removing the "disabled" class 
var skipDisableElement;

function enableAllButtons() {
	$( "input:button, input:submit, a" ).each(
		function() {
			if( skipDisableElement ) {
				if( skipDisableElement == this ) {
					$( this ).removeClass( "clicked" );
				}
				else {
					$( this ).removeClass( "disabled" );
				}
			}
			else {
				$( this ).removeClass( "disabled" );
			}
		}
	);

	skipDisableElement = null;
	
	$( "#nonClickable" ).hide();			
}

//make all input buttons, submit buttons and links look disabled by adding the "disabled" class 
//one element can be passed on which will be skipped
//for instance the button that's being pressed
function disableAllButtons( skipElement ) {
	if( skipElement && !skipDisableElement ) {
		skipDisableElement = skipElement;
	}
	
	$( "input:button, input:submit, a" ).each( 
		function() {
			if( skipDisableElement ) {
				if( skipDisableElement == this ) {
					$( this ).addClass( "clicked" );
				}
				else {
					$( this ).addClass( "disabled" );
				}
			}
			else {
				$( this ).addClass( "disabled" );
			}
		}
	);
}

//locks the screen by showing a window sized container "nonClickable" which is on top of all elements
function lockScreen() {
	$( "#nonClickable" ).css( "width", $( window ).width() );
	$( "#nonClickable" ).css( "height", $( window ).height() );
	$( "#nonClickable" ).show();
}

//unlocks the screen by removing the "nonClickable" element
function unlockScreen() {
	$( "#nonClickable" ).hide();
	
	enableAllButtons();
}

//make an element look disabled by setting its disabled attribute to empty/false, and remove the "disabled" class
function enableElement( elementId ) {
	$( "#" + elementId ).each( 
		function() {
			$( this ).attr( "disabled", "" );
			$( this ).removeClass( "disabled" );
		}
	);	
}

//make an element look disabled by setting its disabled attribute to true, and add the "disabled" class
function disableElement( elementId ) {
	$( "#" + elementId ).each( 
		function() {
			$( this ).attr( "disabled", "true" );
			$( this ).addClass( "disabled" );
		}
	);			
}

//same as enableElement, except this function will enable all element within the parentId
function enableElementsWithin( parentId ) {
	$( "#" + parentId ).find( "*" ).each( 
		function() {			
			$( this ).attr( "disabled", "" );
			$( this ).removeClass( "disabled" );
		}
	);
}

//same as enableElement, except this function will disable all element within the parentId
function disableElementsWithin( parentId ) {
	$( "#" + parentId ).find( "*" ).each( 
		function() {
			$( this ).addClass( "disabled" );
			$( this ).attr( "disabled", "true" );
		}
	);
}

//returns a jquery selector for a form element, using its form name and element name
function getFormFieldSelector( formName, fieldName, visibleRequired ) {
	if( visibleRequired ) {
		var select = "form[name='" + formName + "'] input:visible[name='" + fieldName + "']";
		select += ", form[name='" + formName + "'] select:visible[name='" + fieldName + "']";
		select += ", form[name='" + formName + "'] textarea:visible[name='" + fieldName + "']";
	}
	else {
		var select = "form[name='" + formName + "'] input[name='" + fieldName + "']";
		select += ", form[name='" + formName + "'] select[name='" + fieldName + "']";
		select += ", form[name='" + formName + "'] textarea[name='" + fieldName + "']";
	}
	
	return( select );
}

//enable a form field: check its disabled property, remove "disabled" class and attempt to find (and enable) a related label 
//the latter will look for a label element having a "for" attribute pointing to the field ID we're enabling
function enableFormField( formName, fieldName ) {
	var select = getFormFieldSelector( formName, fieldName, false );
	
	$( "" + select ).each( 
		function() {			
			var id = $( this ).attr( "id" );

			if( id ) {
				enableElement( id );
				
				//enable the related label field
				$( "label:[for=" + id + "]" ).each( 
					function () {
						$( this ).removeClass( "disabled" );
					}
				);
			}
			else {
				$( this ).attr( "disabled", "" );
			}
		}
	);	
}

//disable a form field: check its disabled property, add "disabled" class and attempt to find (and disable) a related label 
//the latter will look for a label element having a "for" attribute pointing to the field we're disabling
function disableFormField( formName, fieldName ) {
	var select = getFormFieldSelector( formName, fieldName, false );
	
	$( "" + select ).each( 
		function() {			
			var id = $( this ).attr( "id" );

			if( id ) {
				disableElement( id );

				//enable the related label field
				$( "label:[for=" + id + "]" ).each( 
					function() {
						$( this ).addClass( "disabled" );
					}
				);
			}
			else {
				$( this ).attr( "disabled", "true" );
			}
		}
	);	
}

//set the action element value of a form
function setFormAction( formName, action ) {
	$( "form:[name=" + formName + "]" ).attr( "action", action );
}

//set an input field to a value, using its form name and input field name
function setFormValue( formName, fieldName, fieldValue ) {
	var select = getFormFieldSelector( formName, fieldName, false );
	
	$( "" + select ).each(
		function() {
			$( this ).attr( "value", fieldValue );
		}
	);
}

//check a form input field by its form name and field name
//can be used for checkboxes
function checkFormField( formName, fieldName ) {
	var select = getFormFieldSelector( formName, fieldName, false );
	
	$( "" + select ).each(
		function() {
			$( this ).attr( "checked", "true" );
		}
	);
}

//uncheck a form input field by its form name and field name
//can be used for checkboxes
function uncheckFormField( formName, fieldName ) {
	var select = getFormFieldSelector( formName, fieldName, false );
	
	$( "" + select ).each(
		function() {
			$( this ).attr( "checked", "" );
		}
	);
}

//focus a form field by its form name and input field name
//checks if the field has a focus function and checks if the field is an array (like a group of radio buttons)
//the latter will set focus to the first element
//after focusing the field the select() function is also invoked
function focusFormField( formName, fieldName ) {
	var select = getFormFieldSelector( formName, fieldName, true );
	
	$( "" + select ).each(
		function( index ) {
			if( index == 0 ) {
				$( this ).focus();
				$( this ).select(); 
			}
		}
	);
}

//set focus to the field input, select or textarea field of a form
function focusFirstFormField( formName ) {
	var fieldName = $( "form:[name=" + formName + "] :input:visible:enabled:first").attr( "name" );
	if( fieldName ) {
		focusFormField( formName, fieldName );
	}
}

//global value needed for the label values system
var labelValues = [];

//adds a label value to a text input field
//this function implements focus and blur events of the input element; if the element is focussed then the label is hidden, if the element is out of focus then the label is displayed (only if the element value isn't filled in yet)
//labelValue is the label to display
//defaultValue is an empty string by default, which represents the value that is considered to be the default value of that field
//when the form submits the resetLabelValues() function should be called
function addLabelValue( inputElementId, labelValue, defaultValue ) {
	//if omitted then set default value to an empty string
	if( !( defaultValue ) ) {
		defaultValue = "";
	}

	//assemble the information into an array and add it to the global labelValues
	var info = [];
	info[ "labelValue" ] = labelValue;
	info[ "defaultValue" ] = defaultValue;
	
	labelValues[ inputElementId ] = info;	
	
	//add onfocus and onblur events to the element
	$( "#" + inputElementId )
	.focus( 
		function() {
			if( labelValues[ this.id ] ) {
				var info = labelValues[ this.id ];
				var labelValue = info[ "labelValue" ];
				var defaultValue = info[ "defaultValue" ];
				
				var currentValue = this.value;

				if ( currentValue == labelValue ) {
					this.value = defaultValue;
					
					if( this.createTextRange ) {
						var range = this.createTextRange();
						range.collapse( false );
						range.select();
					}
				}
				
				$( this ).removeClass( "labelValue" );
			}
		}
	)
	.blur(
		function() {
			if( labelValues[ this.id ] ) {
				var info = labelValues[ this.id ];
				var labelValue = info[ "labelValue" ];
				var defaultValue = info[ "defaultValue" ];
				
				var currentValue = this.value;

				if ( currentValue == defaultValue ) {
					this.value = labelValue;
					
					$( this ).addClass( "labelValue" );
				}
			}
		}
	)
	.trigger( "blur" );
	
}

//when submitting a form this function should be called
//it runs through all label values and removed the label value if it's being displayed
function resetLabelValues() {
	for( inputElementId in labelValues ) {
		$( "#" + inputElementId ).each(
			function() { 		
				var id = $( this ).attr( "id" );
				
				var info = labelValues[ id ];
				var labelValue = info[ "labelValue" ];
				var defaultValue = info[ "defaultValue" ];
				
				var currentValue = $( this ).attr( "value" );
				
				if ( currentValue == labelValue ) {
					$( this ).attr( "value", defaultValue );
				}
			}
		);		
	}
}

//when unfocussing an input text field (onblur event), its value will be set to a label value if its value equals the default value: @see clearInputField()
function resetInputField( inputElement, labelValue, defaultValue ) {
	if( !( defaultValue ) ) {
		defaultValue = "";
	}

	var currentValue = inputElement.value;
	
	if ( currentValue == defaultValue ) {
		inputElement.value = labelValue;
	}
}

//submit a form by its form name
//use skipElement parameter to pass an element which should be skipped when disabling all buttons and links
function submitForm( formName, skipElement ) {
	if( skipElement ) {
		if( !( skipDisableElement ) ) {
			skipDisableElement = skipElement;
		}
	}
	
	$( "form:[name=" + formName + "]" ).trigger( "submit" );
}

//submit a form by its ID
//use skipElement parameter to pass an element which should be skipped when disabling all buttons and links
function submitFormById( formId, skipElement ) {
	if( skipElement ) {
		if( !( skipDisableElement ) ) {
			skipDisableElement = skipElement;
		}
	}
	
	$( "#" + formName ).trigger( "submit" );
}

//clicks a button when the return key is pressed
//this can be used for input text field's onkeypress eventl; when the user presses enter while editing the text field, the clickId element will be clicked
//for instance the clickId could be attached to a form submit button
//this function uses jQuery's trigger( "click" ) function to click the element that's attached to clickId
function clickOnEnter( event, clickId ) {
	var keycode;
	
	if( window.event ) {
		keycode = window.event.keyCode;
	}
	else if ( event ) {
		keycode = event.which;
	}
	else {
		return( true );
	}

	if( keycode == 13 ) {
		if( clickId ) {
			$( "#" + clickId ).trigger( "click" );
		}

		return( false );
	}
	else {
		return( true );
	}
	
}

//format a price value to a localized price value
//the parameters decimalChar, thousandsChar and roundedNumberChar can be used to format the price to a local price
//the decimals can be used to round the price to a number of decimals
//this function uses javascript's Number object to round the price value
//when specified, roundedNumberChar will only be added if the price is a rounded value already, or if the price value has only zero's as decimals (for instance: 5.00 or 5 will be formatted to 5,-)
function formatPrice( price, decimals, decimalChar, thousandsChar, roundedNumberChar ) {
	if( decimals === false ) {
		decimals = 2;
	}
	
	var result = price.toFixed( decimals );

	if( !( decimalChar == undefined ) && !( decimalChar === false ) ) {
		result = result.replace( /\./g, decimalChar );
	}
	else {
		decimalChar = ".";
	}

	if( !( thousandsChar == undefined ) && !( thousandsChar === false ) ) {
		var pricePart = result;
		
		var priceDecimal = result.split( decimalChar );
		var decimalPart = "";
		
		if( priceDecimal.length == 2 ) {
			pricePart = priceDecimal[ 0 ];
			decimalPart = priceDecimal[ 1 ];
		}

		var newResult = "";
		var thousandsCount = 0;
		for( var i = pricePart.length; i > 0; i-- ) {
			var priceChar = pricePart[ i - 1 ];
			
			if( thousandsCount == 3 ) {
				newResult = thousandsChar + newResult;				
				thousandsCount = 0;
			}
			
			thousandsCount++;

			newResult = priceChar + newResult;
		}

		result = newResult;
		if( !( decimalPart == "" ) ) {
			result += decimalChar + decimalPart;
		}
	}
	
	if( !( roundedNumberChar == undefined ) && !( roundedNumberChar === false ) ) {
		var priceDecimal = result.split( decimalChar );

		if( priceDecimal.length >= 2 ) {
			decimalPart = Number( priceDecimal[ priceDecimal.length - 1 ] );

			if( decimalPart == 0 ) {
				result = "";
				
				for( var i = 0; i < priceDecimal.length - 1; i++ ) {
					result += priceDecimal[ i ];
				}
				
				result += decimalChar + roundedNumberChar;
			}		
		}
		else {
			result = priceDecimal[ 0 ] + decimalChar + roundedNumberChar;
		}
	}
	
	return( result );
}
