/**
*   form.js
*   form validation purpose
*		@author Olaf Höft <olaf@edotz.de>
*/

/*==========================================================================
* script wide neede variables
* ==========================================================================*/
var debug = 1;
if(debug) {
	window.onerror = throwError;
}
function throwError(message,file,row) {
	error = "Fehlermeldung:\n"+message+"\n"+file+"\n"+row;
	alert(window.error);
	return true;
}
//different regular expressions
//see regExpr();
var num = /(\d)/;
var alpha = /[a-z_üöä\s\.-]/i;
var noalpha = /[^a-z_üöä\s\.-]/i;
var email = /^([_a-zA-Z0-9-]+)(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+\.([a-zA-Z-\.]+)$/;
//assign here get parameter in order to mark validation by javascript
var fieldValidated = "validated";
//default string for no value in elements
var strNoValue = "Bitte ausfuellen";
//assign here different javascript tags
var jscriptWrap = "<script type=\"text/javascript\">\n<!--:jscript://-->\n</script>\n";
//config array will be filled dynamically
//se setFormularConfig();
var elements = new Array();
var errorMsg = new Array();
var errorType = new Array();
var noValue = new Array();
var userFunc = new Array();

//standard error messages for above defined regualr expressions
errorMsg['alpha']= 'Keine Zahlen + Sonderzeichen';
errorMsg['alphanum'] = 'Namen und Nr. bitte angeben';
errorMsg['num']= 'Nur Zahlen erlaubt';
errorMsg['email']= 'kein gueltige email Adresse';

/**
*   creates new config array for different config fields
*   @param	string	config field eg. elements,errorMsg
*		@param	string 	form element name
*		@retun 	void
*/
function setNewConfigArray(conf,formName){
	eval(''+conf+'["'+formName+'"] = new Array();');
}
/**
*	sets dynamically form config made in script
*   @param	string	form element name
*	@param	array 	containing different configurations
*   @return boolean true on success, false on failure
*/
function setFormularConfig(formName,arrConf){
	var conf, tmp, field, arrFields, arrSplit, strUserFunc;
	if(!arrConf["elements"]){
		throwDebugMessage("config array is not specified");
   }else {
  		for(conf in arrConf){
    		setNewConfigArray(conf,formName);
    		//string operation assures string var
    		tmp = arrConf[conf]+"";
    		arrFields = tmp.split("#");
    		for(var i=0;i<arrFields.length;i++){
      			//string operation assures string var
      			tmp = arrFields[i]+"";
      			arrSplit = tmp.split(":");
      			if(arrSplit.length < 2) {
        			throwDebugMessage("wrong config statement "+tmp);
        			continue;
      			}
      			field = arrSplit[0];
      			switch(conf){
     				case "elements":
          				if(arrSplit.length <= 2){
            				elements[formName][field] = arrSplit[1];
          				}else {
          					arrSplit[0]="";
            				var strConf = arrSplit.join(":");
          					elements[formName][field] = strConf.substr(1,strConf.length);
          				}
        			break;
        			case "errorMsg":
          				errorMsg[formName][field] = arrSplit[1];
        			break;
        			case "errorType":
        				errorType[formName][field] = arrSplit[1];
        			break;
        			case "noValue":
        				noValue[formName][field] = arrSplit[1];
        			break;
        			case "userFunc":
          				userFunc[formName][field]= 1;
          				strUserFunc = "function "+field+"() {\n";
          				for(var j=1;j<arrSplit.length;j++){
             				strUserFunc += arrSplit[j]+";\n";
          				}
          				strUserFunc += "}";
          				arrSplit = jscriptWrap.split(":");
          				arrSplit[1] = strUserFunc;
          				document.write(arrSplit.join("\n"));
        			break;
    			}//switch
    		}//for
  		}//for
  }//else
  return;
}

/**
*   process no value handling
*   @param	string  element type eg. input,radio
*	@param	string  form element name
*   @return mixed
*/
function throwErrorMessage(type,fieldObj,msg){
	if(msg) {
  		switch(errorType[formName][type]){
			case "value":
      			setValue(type,fieldObj,msg);
      			setColor(type,fieldObj,"#FF0000");
			break;
    		case "alert":
      			alert(msg);
    		break;
    		default:
      			throwDebugMessage('No Error type specified for '+field);
    		break;
  		}
  	}
  	return;
}

/**
*  	Returns "no value" string assigned for form element
* 	if a "no value" string has been assigned than function takes default "no value" string
*   @param	string  form element name
*	@return string	"no value"
*/
function getNoValue(field) {
	if(!noValue.length && !noValue[formName]){
		return strNoValue;
  	}
  	return (!noValue[formName][field])?strNoValue:noValue[formName][field];
}

/**
*   Calls user defined function
*   @param	string  function name
*	@param	mixed 	form field value
*	@param	boolean
*/
function callUserFunc( func, value ){
	if(!userFunc.length && !userFunc[formName]){
    	return false;
  	}
  	if(!userFunc[formName][func]){
   		throwDebugMessage("Userfunc "+func+" does not exists");
    	return false;
  	}
  	return eval(''+func+'("'+value+'");');
}

/**
*   Applies global defined regular expression in different validation cases
*   @param	string  form element name
*		@param	mixed 	form element value
*   @return boolean true if validation is succesful, false if not
*/
function regExpr(field,value){
	var conf = elements[formName][field].split(":");
  	if(!conf[1]) {
   		return true;
  	}
  	switch(conf[1]){
		case "alpha":
      		if(!isNaN(value))
      		return false;
			if(num.exec(value) || noalpha.exec(value))
    		return false;
		break;
		case "alphanum":
			if(!isNaN(value))
				return false;
			if(!num.exec(value) || !alpha.exec(value) )
				return false;
    	break;
    	case "num":
			if(isNaN(value))
      		return false;
   		break;
    	case "email":
      		if(!email.test(value))
      		return false;
    	break;
    	default:
      		return callUserFunc( conf[1], value );
    	break;
	}
  	return true;
}

/**
*   Returns error messag assign in config array errorMsg
*   @param	string  form element name
*   @return string 	error message
*/
function getErrorMsg(field){
  	if(!errorMsg.length && !errorMsg[formName]){
    	return false;
  	}
  	var conf = elements[formName][field].split(":");
  	if(conf[1] && errorMsg[formName][conf[1]]){
		return errorMsg[formName][conf[1]];
  	}
  	if(errorMsg[formName][field]){
  		return errorMsg[formName][field];
  	}
  	return false;
}

/**
*   Checks whether one of a group of radio buttons has been clicked
*   @param	string  form radio element name
*   @return mixed 	value of form element radio if checked otherwise false
*/
function isChecked( group ){
    for(var i=0;i < group.length;i++){
    	if(group[i].checked == true){
      		return group[i].value;
    	}
  	}
  	return false;
}

/**
*   Returns value according form element type
*   @param	string  form element type
*   @param	object  form element object
*   @return mixed 	value of form element radio if set otherwise false
*/
function value2Type(type,fieldObj){
	switch(type){
  		case "input":
    		value = fieldObj.value;
    	break;
		case "checkbox":
    	case "radio":

            value = fieldObj.value;
      		if(!value) {
       			value = isChecked(fieldObj);
    		}else {
       			value = (fieldObj.checked)?value:false;
      		}
    	break;
  }
  return value;
}

/**
*   Sets font color if method "getElementById" is available
*   @param	string  form element type
*   @param	object  form element object
*   @param	string  hex font color
*   @return boolean
*/
function setColor(type,fieldObj,color){
  	if(!document.getElementById){
		return false;
  	}
  	switch(type){
    	case "input":
      		fieldObj.style.color = color;
    	break;
	}
  	return true;
}

/**
*   Sets form element value according element type
*   @param	string  form element type
*   @param	object  form element object
*   @param	mixed		form element value
*   @return void
*/
function setValue(type,fieldObj,value){
	if(!value)return false;
  	switch(type){
    	case "hidden":
    	case "input":
    		fieldObj.value = value;
    	break;
    	case "checkbox":
    	case "radio":
    	break;
  	}
  	return true;
}

/**
*   Returns form element type specified in config
*   @param	string  form element name
*   @return mixed 	form element type if specified otherwise false
*/
function getType(field) {
  	var pos = elements[formName][field].indexOf(":");
  	return (pos < 0)?elements[formName][field]:elements[formName][field].substr(0,pos);
}

/**
*   Returns form element object
*   @param	string  form element name
*   @return mixed 	form element object if specified otherwise false
*/
function getFieldObj(field) {
  	var f = document.forms[formName];
  	return (!f.elements[field])?false:f.elements[field];
}

/**
*   Check if form element value has been set taking into account possible error message
*   @param	string  form element name
*   @param	object  form element object
*   @return mixed 	form element value if set otherwise false
*/
function hasFilledOut(field,fieldObj){
  	var type = getType(field);
  	var value = value2Type(type,fieldObj);
  	//set no value
  	if(!value){
    	throwErrorMessage(type,fieldObj,getNoValue(field));
    	return false;
  	}
  	//if error type is value check error messages
  	if( errorType[formName][type] == "value") {
    	if( ( value == getNoValue(field) ) || ( value == getErrorMsg(field) ) )return false;
  	}
  	setColor(type,fieldObj,"#000000");
  	return value;
}

/**
*   main form validation function
*		iterates and validates specified form elements, calls form.submit() if validation was successful
*   @param	string  form name
*   @return boolean false
*/
function validate( fName ){
  	var valid = true,value;
  	if(!document.forms[fName]){
		throwDebugMessage("Formlar "+fName+" existiert nicht");
  	}
  	var f = document.forms[fName];
  	formName = fName;
  	var error = false;
  	var fields = f.elements;
  	for(var field in elements[formName]){
    	//if field is not set continue
    	if(!fields[field])continue;
    	//get field value
    	value = hasFilledOut(field,fields[field]);
    	if(!value) {
      		valid = false;
    	} else if(!regExpr(field,value) ){
    		var type = getType(field);
      		if(errorType[formName][type] !== "value"){
        		var msg = value;
      		}else {
        		var msg = getErrorMsg(field)
      			if(!msg) {
        			setColor(type,fields[field],"#FF0000");
        		}
      		}
      		throwErrorMessage(type,fields[field],msg);
      		valid = false;
    	}
    	if(!valid){
     		error = true;
    	}
    	valid = true;
	}
  	if(error){
    	return false;
  	}
  	if(fields[fieldValidated]){
    	setValue(fields[fieldValidated].type,fields[fieldValidated],1)
  	}
  	return true;
}


/**
*   Resets form
*		@return void
*/
function formReset(){
	if(!arguments[0]){
  		document.forms[0].reset();
  	}else {
    	document.forms[arguments[0]].reset();
  	}
}
/**
*   Alert debug message if flag has been set
*		@return void
*/
function throwDebugMessage(strMessage){
	if(!debug)return false;
  	alert(strMessage);
}

/**
* checkStatus
* checks radio button status and resets button if checked
* return void
*/
function checkStatus(butt){
 	if(butt.on == 0 || !butt.on){
  		butt.on = 1;
  		return;
 	}
 	butt.on = 0;
 	butt.checked = false;
}