var fValidator=new Class({options:{msgContainerTag:"div",msgClass:"fValidator-msg",styleNeutral:{"background-color":"#ffc","border-color":"#cc0"},styleInvalid:{"background-color":"#fcc","border-color":"#c00"},styleValid:{"background-color":"#cfc","border-color":"#0c0"},required:{type:"required",re:/[^.*]/,msg:"This field is required."},alpha:{type:"alpha",re:/^[a-z ._-]+$/i,msg:"This field accepts alphabetic characters only."},alphanum:{type:"alphanum",re:/^[a-z0-9 ._-]+$/i,msg:"This field accepts alphanumeric characters only."},integer:{type:"integer",re:/^[-+]?\d+$/,msg:"Please enter a valid integer."},zipcode:{type:"zipcode",re:/^[0-9]{5}$/,msg:"Please enter a valid zip code."},real:{type:"real",re:/^[-+]?\d*\.?\d+$/,msg:"Please enter a valid number."},date:{type:"date",re:/^((((0[13578])|([13578])|(1[02]))[\/](([1-9])|([0-2][0-9])|(3[01])))|(((0[469])|([469])|(11))[\/](([1-9])|([0-2][0-9])|(30)))|((2|02)[\/](([1-9])|([0-2][0-9]))))[\/]\d{4}$|^\d{4}$/,msg:"Please enter a valid date (mm/dd/yyyy)."},email:{type:"email",re:/^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i,msg:"Please enter a valid email."},phone:{type:"phone",re:/^((\([0-9]{3}\) ?)|([0-9]{3}-))?[0-9]{3}-[0-9]{4}$/,msg:"Please enter a valid phone."},url:{type:"url",re:/^(http|https|ftp)\:\/\/[a-z0-9\-\.]+\.[a-z]{2,3}(:[a-z0-9]*)?\/?([a-z0-9\-\._\?\,\'\/\\\+&amp;%\$#\=~])*$/i,msg:"Please enter a valid url."},ssn:{type:"ssn",re:/^[0-9]{3}-[0-9]{2}-[0-9]{4}$/i,msg:"Please enter a valid social security number."},dollar:{type:"dollar",re:/^\${0,1}([0-9]{1,3}(\,[0-9]{3})*|([0-9]+))(\.[0-9]{2})?$/i,msg:"Please enter a valid dollar amount."},confirm:{type:"confirm",msg:"Confirm Password does not match original Password."},range:{type:"range",msg:"Please enter a value between [LOWER] and [UPPER]."},onValid:Class.empty,onInvalid:Class.empty},initialize:function(form,options){this.form=$(form);this.setOptions(options);this.fields=this.form.getElements("*[class^=fValidate]");this.validations=[];this.invalids=[];this.callbacks=[];this.messages=[];this.ranges=[];this.fields.each(function(element){if(!this._isChildType(element)){element.setStyles(this.options.styleNeutral)}element.cbErr=0;var callBacks="";callBacks=element.getProperty("class").match(/onError\[\'([^']+)\'\]/);if(callBacks){this.callbacks.push([element,callBacks[1]])}var messages="";messages=element.getProperty("class").match(/errorMessage\[\'([^']+)\'\]/);if(messages){this.messages.push([element,messages[1]])}var classes=element.getProperty("class").split(" ");classes.each(function(klass){if(klass.match(/^fValidate(\[.+\])$/)){var aFilters=eval(klass.match(/^fValidate(\[.+\])$/)[1]);for(var i=0;i<aFilters.length;i++){if(aFilters[i].match(/^range/)){range=aFilters[i].match(/range\[(-{0,1}[\d\,\.]+)\]\[(-{0,1}[\d\,\.]+)\]/);if(range){this.ranges.push({"Element":element,"Lower":range[1],"Upper":range[2]});this.register(element,this.options["range"])}}else{if(this.options[aFilters[i]]){this.register(element,this.options[aFilters[i]])}}if(aFilters[i].charAt(0)=="="){this.register(element,$extend(this.options.confirm,{idField:aFilters[i].substr(1)}))}}}}.bind(this))}.bind(this));this.form.addEvents({"submit":this._onSubmit.bind(this),"reset":this._onReset.bind(this)})},register:function(field,options){field=$(field);this.validations.push([field,options]);field.addEvent("blur",function(){this._validate(field,options)}.bind(this))},_isChildType:function(el){var elType=el.type.toLowerCase();if((elType=="radio")||(elType=="checkbox")){return true}return false},_validate:function(field,options){switch(options.type){case"confirm":if($(options.idField).getValue()==field.getValue()){this._msgRemove(field,options)}else{this._msgInject(field,options)}break;case"required":if(options.re.test(field.getValue())){this._msgRemove(field,options)}else{this._msgInject(field,options)}break;case"range":var found=false;tmp=this;this.ranges.each(function(e){if(e.Element==field&&!found){found=true;v=parseFloat(field.getValue().replace(/[^\d\.]/g,""));if(!isNaN(v)){upper=parseFloat(e.Upper);lower=parseFloat(e.Lower);tmpOptions=options;tmpOptions.msg=tmpOptions.msg.replace(/\[LOWER\]/,lower);tmpOptions.msg=tmpOptions.msg.replace(/\[UPPER\]/,upper);if(v<=upper&&v>=lower){tmp._msgRemove(field,tmpOptions)}else{tmp._msgInject(field,tmpOptions)}}}});break;default:if(field.getValue().length>0&&!options.re.test(field.getValue())){this._msgInject(field,options)}else{this._msgRemove(field,options)}}},_validateChild:function(child,options){var nlButtonGroup=this.form[child.getProperty("name")];if(!nlButtonGroup.length){nlButtonGroup=[nlButtonGroup]}var cbCheckeds=0;var isValid=true;for(var i=0;i<nlButtonGroup.length;i++){if(nlButtonGroup[i].checked){cbCheckeds++;if(!options.re.test(nlButtonGroup[i].getValue())){isValid=false;break}}}if(cbCheckeds==0&&options.type=="required"){isValid=false}if(isValid){this._msgRemove(child,options)}else{this._msgInject(child,options)}},_msgInject:function(owner,options){var hasCB=false;var callback="";this.callbacks.each(function(pair){if(pair[0]==owner&&!hasCB){hasCB=true;callback=pair[1]}});var hasMsg=false;var message="";this.messages.each(function(pair){if(pair[0]==owner&&!hasMsg){hasMsg=true;message=pair[1]}});if(hasCB&&window[callback]){window[callback](owner,options,false);if(!this.invalids.contains(owner.getProperty("id"))){this.invalids.push(owner.getProperty("id"))}}else{if(!$(owner.getProperty("id")+options.type+"_msg")){if(!hasMsg){message=options.msg}var msgContainer=new Element(this.options.msgContainerTag,{"id":owner.getProperty("id")+options.type+"_msg","class":this.options.msgClass}).setHTML(message).setStyle("opacity",0).injectAfter(owner).effect("opacity",{duration:500,transition:Fx.Transitions.linear}).start(0,1);owner.cbErr++;this._chkStatus(owner,options)}}},_msgRemove:function(owner,options,isReset){isReset=isReset||false;var hasCB=false;this.callbacks.each(function(pair){if(pair[0]==owner&&!hasCB){hasCB=true;callback=pair[1]}});if(hasCB&&window[callback]){window[callback](owner,options,true);if(this.invalids.contains(owner.getProperty("id"))){this.invalids.splice(this.invalids.indexOf(owner.getProperty("id")),1)}}else{if($(owner.getProperty("id")+options.type+"_msg")){var el=$(owner.getProperty("id")+options.type+"_msg");el.effect("opacity",{duration:500,transition:Fx.Transitions.linear,onComplete:function(){el.remove()}}).start(1,0);if(!isReset){owner.cbErr--;this._chkStatus(owner,options)}}}},_chkStatus:function(field,options){if(field.cbErr==0){field.effects({duration:500,transition:Fx.Transitions.linear}).start(this.options.styleValid);this.fireEvent("onValid",[field,options],50)}else{field.effects({duration:500,transition:Fx.Transitions.linear}).start(this.options.styleInvalid);this.fireEvent("onInvalid",[field,options],50)}},_onSubmit:function(event){event=new Event(event);var isValid=true;this.validations.each(function(array){if(!this.invalids.contains(array[0].id)){if(this._isChildType(array[0])){this._validateChild(array[0],array[1])}else{this._validate(array[0],array[1])}}if(array[0].cbErr>0){isValid=false}}.bind(this));if(this.invalids.length){isValid=false}if(!isValid){event.stop()}return isValid},_onReset:function(){this.validations.each(function(array){if(!this._isChildType(array[0])){array[0].setStyles(this.options.styleNeutral)}array[0].cbErr=0;this._msgRemove(array[0],array[1],true)}.bind(this))}});fValidator.implement(new Events);fValidator.implement(new Options)