/* Form validator
 * author: ALTAIR
 * last modified: 2008.06.06, lvass
 * version: 1.8
 * Changelog:
 * 1.9:
 * - reactivated minlength feature for text fields
 * 1.8:
 * - skip validating disabled fields
 * 1.7:
 * - fixed select handling: detect correctly the option.value and return option.text if value doesn't exists 
 * 1.6:
 * - added support to nullValue // a default value of a field that if we consider as null value
 * 1.5:
 * - added back formName function for backward compatibility
 * 1.4:
 * - added select validation
 * - added conditional required option
 * 1.3: 
 * - fix when Prototype library is used (array traversal with for( i in array) constructs)
 * - fix to protect against wrong config (alert instead of JS error)
 * 1.2: 
 * - added Checkbox validation
 */


var validHash = new Array() ;
var _formName ; //private variable
var errorMessages = new Array()
var errorMessage = '' ;
var errorReqFields = '' ;
var reqGroups = new Array() ;
var rgChecked = new Array() ;
var focused = false ;

function setFormName( name )
{
	_formName = name ;
}

//old name of the above function for backward compatibility
this.formName = this.setFormName;


function setErrorMessage( key, message )
{
	errorMessages[key.toLowerCase()] = message ;
}

function validField( field, confHash )
{
	this.validHash[field] = confHash ;
	
	if ( confHash['reqgroup'] )
	{
		if ( !reqGroups[confHash['reqgroup']] )
		{
			reqGroups[confHash['reqgroup']] = new Array() ;
		}
		
		reqGroups[confHash['reqgroup']][field] = confHash['text'] ;
		rgChecked[confHash['reqgroup']] = false ;
	}
}

function resetRGChecked()
{
	for ( var key in rgChecked )
	{
		if(typeof rgChecked[key] == 'function') continue; // patch of array traversal against Prototype library 
		rgChecked[key] = false ;
	}
}

function setFocus( fieldName )
{
	var field = document.forms[this._formName].elements[fieldName];
        if(isRadio(field)) field = field[0]; // radio
	if ( !focused )
	{	
		field.focus();
		focused = true ;
	}	
}

function valid( field )
{
	var fieldHash = this.validHash[field] ;
	var fieldName = fieldHash['text'] ;
	var value ;
	var form = document.forms[this._formName] ;
	var object = form.elements[String( field )] ;
	var validType = fieldHash['type'].toLowerCase() ;
	
	if(object.disabled === true) return true; // skip validation of disabled fields

//	alert( this._formName ) ;
	
//	alert( field + '(' + object.name + ':' + object.type + ') = ' + object.value  ) ;
	
	if(!object) { alert('Hibás config: ' + field); return false; }

	value = getValue(field);

	// field is empty, though required
	if ( value.length == 0 && fieldHash['required'] && fieldHash['required'] === true )
	{
		errorReqFields += " - " + fieldName + "\n" ; 
//		errorMessage += errorMessages['required'].replace( /\$1/, fieldName ) + "\n" ;
		setFocus( field ) ;
		return false ;
	}
	// field is empty though required if linked field is not empty
	else if( value.length == 0 && fieldHash['required'] && getValue(fieldHash['required']) ) {
		errorReqFields += " - " + fieldName + "\n" ; 
//		errorMessage += errorMessages['required'].replace( /\$1/, fieldName ) + "\n" ;
		setFocus( field ) ;
		return false ;
	}
	// field is empty and is part of a required group
	else if ( value.length == 0 && fieldHash['reqgroup'] && !rgChecked[fieldHash['reqgroup']] )
	{
		var tmpObject ;
		var tmpValue ;
		var ret = false ;
		var fieldNames = '' ;
		var firstField = '' ;
		
		for ( var key in reqGroups[fieldHash['reqgroup']] )
		{
			if(typeof reqGroups[key] == 'function') continue; // patch of array traversal against Prototype library 

			if ( fieldNames.length > 0 )
			{
				fieldNames += ', ' + reqGroups[fieldHash['reqgroup']][key] ;
			}
			else
			{
				fieldNames = reqGroups[fieldHash['reqgroup']][key] ;
			}
			
			if ( firstField.length == 0 )
			{
				firstField = key ;
			}
			
			tmpObject = form.elements[key] ;

			if(!tmpObject) { alert('Hibás config: ' + key); return false; }

			tmpValue = getValue(key);
		
			ret = ret || ( tmpValue.length > 0 ) ;		
		}
		
		rgChecked[fieldHash['reqgroup']] = true ;
		
		if ( !ret )
		{
			errorMessage += errorMessages['reqgroup'].replace( /\$1/, fieldNames ) + "\n" ;
			setFocus( firstField ) ;
			return false ;
		}
	}
	
	// ===[csak akkor validalunk, ha irt is bele valamit]===============
	if ( value.length > 0 )
	{
		switch ( validType )
		{
			// ===[PHONE]=====================================================
			case 'phone':
				var regexp = /^[\(\)\-\/ 0-9]*$/ ;
				
				var ret = value.match( regexp ) ;			
				
				if ( ret == null || ret.length == 0 )
				{
					errorMessage += errorMessages['phone'].replace( /\$1/, fieldName ) + "\n" ;
					setFocus( field ) ;
					return false ;
				}
			break ;
			
			// ===[EMAIL]=====================================================
			case 'email':
				var regexp = /^\w+([\.\_\-]?\w+)*\@\w+([\.\_\-\w]*)(\.\w{2,})$/ ;
				
				var ret = value.match( regexp ) ;

				if ( ret == null || ret.length == 0 )
				{
					errorMessage += errorMessages['email'].replace( /\$1/, fieldName ) + "\n" ;
					setFocus( field ) ;
					return false ;
				}
			break ;
			
			// ===[TEXT/DEFAULT]==============================================
			case 'text':
			default:
				if ( fieldHash['minlength'] && value.length < fieldHash['minlength'] )
				{
					errorMessage = errorMessages['minlength'].replace( /\$1/, fieldName ) ;
					errorMessage = errorMessage.replace( /\$2/, fieldHash['minlength'] ) ;
					//alert( 'A(z) ' + fieldName + ' mezőnek legalább ' + fieldHash['minlength'] + ' hosszúnak kell legyen!' ) ;
					setFocus( field ) ;
					return false ;
				}
			break ;
		}
	}
	
	return true ;
}

function isRadio(o) {
	if (typeof o == 'object' && o[0] && o[0].tagName == 'INPUT' && o[0].type == 'radio') {   //o[0] exists for selects too, but are OPTIONs //o[0] exists for selects too, but are OPTIONs
		return true;
	}
	return false;
}


function getValue(field) {

	var form = document.forms[this._formName] ;
	var object = form.elements[String (field)];
	var fieldHash = this.validHash[field] ;
	var value = null;
	if(isRadio(object)) object.type = 'radio';
	switch ( object.type )
	{
		case 'select':
		case 'select-one':
			value = optionValue(object.options[object.selectedIndex]);
			break;

		case 'checkbox':
			value = object.checked ? 'checked' : '';
			break;

	        case 'radio':
			value = ''; // default
			for(var i=0;i<object.length;i++) {
			   if(object[i].checked) {
			      value = object[i].value;
			      break;
			   }
			}
			break;

		case 'hidden':
		case 'password':
		case 'text':
		default:
			value = object.value ;
		break ;
	}

	//field contains a value that we consider no to be a value
	if(fieldHash['nullValue'] && value == fieldHash['nullValue']) value = '';
	return value;
}

function optionValue(opt) {
   var value;
   try { // for IE
    if(opt.attributes['value'].specified) value =opt.attributes['value'];
   } catch(e) {
   
    try { // for FF, Opera
       value = 'value' in opt ;
    } catch(e) {}
   };
   // FIXME: SAFARI???

  return value ? opt.value : opt.text;
}


function validate()
{
	var key ;
	var ret = true ;
	
	focused = false ;
	resetRGChecked() ;		
	errorMessage = '' ;	
	errorReqFields = '' ;	
	
	for ( key in this.validHash )
	{
		if(typeof this.validHash[key] == 'function') continue; // patch of array traversal against Prototype library 
		ret = valid( key ) && ret ;
	}
	
	if ( errorReqFields.length > 0 )
	{
		errorMessage = errorMessages['required'] + "\n" + errorReqFields + "\n" + errorMessage ;
	}
	
	if ( errorMessage.length > 0 )
	{
		alert( "\n" + errorMessage ) ;
	}
	
	return ret ;
}
