function validateCompleteForm(objForm,strErrorClass){
    return _validateInternal(objForm,strErrorClass,0);
};

function validateStandard(objForm,strErrorClass){
    return _validateInternal(objForm,strErrorClass,1);
};

function _validateInternal(form,strErrorClass,nErrorThrowType){
    var strErrorMessage="";var objFirstError=null;

    if(nErrorThrowType==0){
	strErrorMessage=(form.err)?form.err:_getLanguageText("err_form");
    };

    var fields=_GenerateFormFields(form);

    for(var i=0;i<fields.length;++i){
	var field=fields[i];
	field.ResetClass();
	if(!field.IsValid(fields)){
	    field.SetClass(strErrorClass);
	    if(nErrorThrowType==1){
		_throwError(field);
		return false;
	    }else{
		if(objFirstError==null){
		     objFirstError=field;
		}
		strErrorMessage=_handleError(field,strErrorMessage);
		bError=true;
	    }
	}
    };

    if(objFirstError!=null){
	alert(strErrorMessage);
	objFirstError.element.focus();
	return false;
    };


    return true;
};

function _getLanguageText(id){
    objTextsInternal=new _jsVal_Language();
    objTexts=null;
    try{
	objTexts=new jsVal_Language();
    }catch(ignored){};

    switch(id){
	case "err_form":strResult=(!objTexts||!objTexts.err_form)?objTextsInternal.err_form:objTexts.err_form;break;
	case "err_enter":strResult=(!objTexts||!objTexts.err_enter)?objTextsInternal.err_enter:objTexts.err_enter;break;
	case "err_select":strResult=(!objTexts||!objTexts.err_select)?objTextsInternal.err_select:objTexts.err_select;break;
    };

    return strResult;
};

function _GenerateFormFields(form){
    var arr=new Array();

    for(var i=0;i<form.length;++i){
	var element=form.elements[i];
	var index=_getElementIndex(arr,element);

	if(index==-1){
	    arr[arr.length]=new Field(element,form);
	}else{
	    arr[index].Merge(element)
	};
    };

    return arr;
};

function _getElementIndex(arr,element){
    var elementName=element.name.toLowerCase();

    for(var i=0;i<arr.length;++i){

	if(arr[i].element.name.toLowerCase()==elementName){
	    return i;
	};
    };

    return -1;
};

function _jsVal_Language(){
    this.err_form="Please enter/select values for the following fields:\n\n";
    this.err_select="Please select a valid \"%FIELDNAME%\"";
    this.err_enter="Please enter a valid \"%FIELDNAME%\"";
};

function Field(element,form){
    if(!element.oldClassName)element.oldClassName=element.className;
	this.type=element.type;
	this.element=element;
	this.exclude=element.exclude||element.getAttribute('exclude');
	this.err=element.err||element.getAttribute('err');
	this.required=_parseBoolean(element.required||element.getAttribute('required'));
	this.realname=element.realname||element.getAttribute('realname');
	this.elements=new Array();

	switch(this.type){
	    case "textarea":
	    case "password":
	    case "text":
		this.value=element.value;
		this.minLength=element.minlength||element.getAttribute('minlength');
		this.maxLength=element.maxlength||element.getAttribute('maxlength');
		this.regexp=this._getRegEx(element);
		this.minValue=element.minvalue||element.getAttribute('minvalue');
		this.maxValue=element.maxvalue||element.getAttribute('maxvalue');
		this.equals=element.equals||element.getAttribute('equals');
		this.callback=element.callback||element.getAttribute('callback');
	    break;
	    case "select-one":
	    case "select-multiple":
		this.values=new Array();
		for(var i=0;i<element.options.length;++i){
		    if(element.options[i].selected&&(!this.exclude||element.options[i].value!=this.exclude)){
			this.values[this.values.length]=element.options[i].value;
		    }
		}

		this.min=element.min||element.getAttribute('min');
		this.max=element.max||element.getAttribute('max');
		this.equals=element.equals||element.getAttribute('equals');
	    break;
	    case "checkbox":
		this.min=element.min||element.getAttribute('min');
		this.max=element.max||element.getAttribute('max');
	    case "radio":
		this.required=_parseBoolean(this.required||element.getAttribute('required'));
		this.values=new Array();

		if(element.checked){
		    this.values[0]=element.value;
		}
		this.elements[0]=element;
	    break;
	};
    };

    Field.prototype.Merge=function(element){
	var required=_parseBoolean(element.getAttribute('required'));
	if(required){
	    this.required=true;
	};

	if(!this.err){
	    this.err=element.getAttribute('err');
	};

	if(!this.equals){
	    this.equals=element.getAttribute('equals');
	};

	if(!this.callback){
	    this.callback=element.getAttribute('callback');
	};

	if(!this.realname){
	    this.realname=element.getAttribute('realname');
	};

	if(!this.max){
	    this.max=element.getAttribute('max');
	};

	if(!this.min){
	    this.min=element.getAttribute('min');
	};

	if(!this.regexp){
	    this.regexp=this._getRegEx(element);
	};

	if(element.checked){
	    this.values[this.values.length]=element.value;
	};

	this.elements[this.elements.length]=element;
    };

    Field.prototype.IsValid=function(arrFields){
	switch(this.type){
	    case "textarea":
	    case "password":
	    case "text":
		return this._ValidateText(arrFields);
	    case "select-one":
	    case "select-multiple":
	    case "radio":
	    case "checkbox":
		return this._ValidateGroup(arrFields);
	    default:
		return true;
	};
    };

    Field.prototype.SetClass=function(newClassName){
	if((this.elements)&&(this.elements.length>0)){
	    for(var i=0;i<this.elements.length;++i){
		this.elements[i].oldClassName=this.elements[i].className;
		this.elements[i].className=newClassName;
	    }
	}else{
	    this.element.oldClassName=this.element.className;
	    this.element.className=newClassName;
	};
    };

    Field.prototype.ResetClass=function(){
	if((this.type!="button")&&(this.type!="submit")&&(this.type!="reset")){
	    if((this.elements)&&(this.elements.length>0)){
		for(var i=0;i<this.elements.length;++i){
		    this.elements[i].className=this.elements[i].oldClassName;
		}
	    }else{
		this.element.className=this.element.oldClassName;
	    };
	};
    };

    Field.prototype._getRegEx=function(element){
	regex=element.regexp||element.getAttribute('regexp')
	if(regex==null)return null;
	retype=typeof(regex);
	if(retype.toUpperCase()=="FUNCTION")
	    return regex;
	else if((retype.toUpperCase()=="STRING")&&!(regex=="numeric")&&!(regex=="email")&&!(regex=="tel")&&!(regex=="pc")&&!(regex=="zip")&&!(regex=="integer")&&!(regex=="money")&&!(regex=="creditcard")&&!(regex=="postalzip"))
	{
	    nBegin=0;nEnd=regex.length-1;
	    if(regex.charAt(0)=="/")nBegin=1;
	    if(regex.charAt(regex.length-1)=="/")nEnd=regex.length-2;
	    return new RegExp(regex.slice(nBegin,nEnd));
	}
	else{
	    return regex;
	};
    };

    Field.prototype._ValidateText=function(arrFields){
	if(this.required&&!this.value){
	    return false;
	};

	if(this.value&&(this.minLength&&this.value.length<this.minLength)){
	    return false;
	};

	if(this.value&&(this.maxLength&&this.value.length>this.maxLength)){
	    return false;
	};

	if(this.regexp){
	    if(!_checkRegExp(this.regexp,this.value))
	    {
		if(!this.required&&this.value){
		    return false;
		}

		if(this.required){
		    return false;
		}
	    }
	    else
	    {
		return true;
	    };
	};

	if(this.callback){
	    nCurId=this.element.id?this.element.id:"";
	    nCurName=this.element.name?this.element.name:"";
	    eval("bResult = "+this.callback+"('"+nCurId+"', '"+nCurName+"', '"+this.value+"');");
	    if(bResult==false){
		return false;
	    };
	};

	if(this.equals){
	    for(var i=0;i<arrFields.length;++i){
		var field=arrFields[i];
		if((field.element.name==this.equals)||(field.element.id==this.equals)){
		    if(field.element.value!=this.value){
			return false;
		    };
		    break;
		};
	    };
	};

	if(this.required){
	    var fValue=parseFloat(this.value);
	    if((this.minValue||this.maxValue)&&isNaN(fValue)){
		return false;
	    };

	    if((this.minValue)&&(fValue<this.minValue)){
		return false;
	    };

	    if((this.maxValue)&&(fValue>this.maxValue)){
		return false
	    };
	};
	return true;
    };

    Field.prototype._ValidateGroup=function(arrFields){
	if(this.required&&this.values.length==0){
	    return false;
	};

	if(this.required&&this.min&&this.min>this.values.length){
	    return false;
	};

	if(this.required&&this.max&&this.max<this.values.length){
	    return false;
	};

	return true;
};

function _handleError(field,strErrorMessage){
    var obj=field.element;
    strNewMessage=strErrorMessage+((field.realname)?field.realname:((obj.id)?obj.id:obj.name))+"\n";
    return strNewMessage;
};

function _throwError(field){
    var obj=field.element;
    switch(field.type){
	case "text":
	case "password":
	case "textarea":
	    alert(_getError(field,"err_enter"));
	    try{
		obj.focus();
	    }
	    catch(ignore){}
	break;
	case "select-one":
	case "select-multiple":
	case "radio":
	case "checkbox":
	    alert(_getError(field,"err_select"));
	break;
    };
};

function _getError(field,str){
    var obj=field.element;
    strErrorTemp=(field.err)?field.err:_getLanguageText(str);
    idx=strErrorTemp.indexOf("\\n");
    while(idx>-1){
	strErrorTemp=strErrorTemp.replace("\\n","\n");
	idx=strErrorTemp.indexOf("\\n");
    };
    return strErrorTemp.replace("%FIELDNAME%",(field.realname)?field.realname:((obj.id)?obj.id:obj.name));
};

function _parseBoolean(value){
    return !(!value||value==0||value=="0"||value=="false");
};


function IsNumeric(sText)
{
    var ValidChars = "0123456789.";
    var IsNumber=true;
    var Char;

    for (i = 0; i < sText.length && IsNumber == true; i++) 
    { 
	Char = sText.charAt(i); 
	if (ValidChars.indexOf(Char) == -1) 
	{
	    IsNumber = false;
	}
    }

    return IsNumber;
}

function _checkRegExp(regx,value){
    switch(regx){
	case "numeric":
	    return IsNumeric(value);
	case "integer":
	    return((/^\d+$/).test(value));
	case "email":
	    return((/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,5})+$/).test(value));
	case "tel":
	    return((/^1?[\-]?\(?\d{3}\)?[\-]?\d{3}[\-]?\d{4}$/).test(value));
	case "pc":
	    return((/^[a-z]\d[a-z]?\d[a-z]\d$/i).test(value));
	case "zip":
	    return((/^\d{5}$/).test(value));
	case "money":
	    return((/^\d+([\.]\d\d)?$/).test(value));
	case "creditcard":
	    return(!isNaN(value));
	case "postalzip":
	    if(value.length==6||value.length==7)
		return((/^[a-zA-Z]\d[a-zA-Z] ?\d[a-zA-Z]\d$/).test(value));

	    if(value.length==5||value.length==10)
		return((/^\d{5}(\-\d{4})?$/).test(value));
	break;
	default:
	    return(regx.test(value));
    };
};