(function($){$.tools=$.tools||{version:'1.2.5'};var typeRe=/\[type=([a-z]+)\]/,numRe=/^-?[0-9]*(\.[0-9]+)?$/,dateInput=$.tools.dateinput,emailRe=/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,urlRe=/^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,v;v=$.tools.validator={conf:{grouped:false,effect:'default',errorClass:'invalid',inputEvent:null,errorInputEvent:'keyup',formEvent:'submit',lang:'en',message:'<div/>',messageAttr:'data-message',messageClass:'error',offset:[0,0],position:'center right',singleError:false,speed:'normal'},messages:{"*":{en:"Please correct this value"}},localize:function(lang,messages){$.each(messages,function(key,msg){v.messages[key]=v.messages[key]||{};v.messages[key][lang]=msg})},localizeFn:function(key,messages){v.messages[key]=v.messages[key]||{};$.extend(v.messages[key],messages)},fn:function(matcher,msg,fn){if($.isFunction(msg)){fn=msg}else{if(typeof msg=='string'){msg={en:msg}}this.messages[matcher.key||matcher]=msg}var test=typeRe.exec(matcher);if(test){matcher=isType(test[1])}fns.push([matcher,fn])},addEffect:function(name,showFn,closeFn){effects[name]=[showFn,closeFn]}};function getPosition(trigger,el,conf){var top=trigger.offset().top,left=trigger.offset().left,pos=conf.position.split(/,?\s+/),y=pos[0],x=pos[1];top-=el.outerHeight()-conf.offset[0];left+=trigger.outerWidth()+conf.offset[1];if(/iPad/i.test(navigator.userAgent)){top-=$(window).scrollTop()}var height=el.outerHeight()+trigger.outerHeight();if(y=='center'){top+=height/2}if(y=='bottom'){top+=height}var width=trigger.outerWidth();if(x=='center'){left-=(width+el.outerWidth())/2}if(x=='left'){left-=width}return{top:top,left:left}}function isType(type){function fn(){return this.getAttribute("type")==type}fn.key="[type="+type+"]";return fn}var fns=[],effects={'default':[function(errs){var conf=this.getConf();$.each(errs,function(i,err){var input=err.input;input.addClass(conf.errorClass);var msg=input.data("msg.el");if(!msg){msg=$(conf.message).addClass(conf.messageClass).appendTo(document.body);input.data("msg.el",msg)}msg.css({visibility:'hidden'}).find("p").remove();$.each(err.messages,function(i,m){$("<p/>").html(m).appendTo(msg)});if(msg.outerWidth()==msg.parent().width()){msg.add(msg.find("p")).css({display:'inline'})}var pos=getPosition(input,msg,conf);msg.css({visibility:'visible',position:'absolute',top:pos.top,left:pos.left}).fadeIn(conf.speed)})},function(inputs){var conf=this.getConf();inputs.removeClass(conf.errorClass).each(function(){var msg=$(this).data("msg.el");if(msg){msg.css({visibility:'hidden'})}})}]};$.each("email,url,number".split(","),function(i,key){$.expr[':'][key]=function(el){return el.getAttribute("type")===key}});$.fn.oninvalid=function(fn){return this[fn?"bind":"trigger"]("OI",fn)};v.fn(":email","Please enter a valid email address",function(el,v){return!v||emailRe.test(v)});v.fn(":url","Please enter a valid URL",function(el,v){return!v||urlRe.test(v)});v.fn(":number","Please enter a numeric value.",function(el,v){return numRe.test(v)});v.fn("[max]","Please enter a value smaller than $1",function(el,v){if(v===''||dateInput&&el.is(":date")){return true}var max=el.attr("max");return parseFloat(v)<=parseFloat(max)?true:[max]});v.fn("[min]","Please enter a value larger than $1",function(el,v){if(v===''||dateInput&&el.is(":date")){return true}var min=el.attr("min");return parseFloat(v)>=parseFloat(min)?true:[min]});v.fn("[required]","Please complete this mandatory field.",function(el,v){if(el.is(":checkbox")){return el.is(":checked")}return!!v});v.fn("[pattern]",function(el){var p=new RegExp("^"+el.attr("pattern")+"$");return p.test(el.val())});function Validator(inputs,form,conf){var self=this,fire=form.add(self);inputs=inputs.not(":button, :image, :reset, :submit");function pushMessage(to,matcher,returnValue){if(!conf.grouped&&to.length){return}var msg;if(returnValue===false||$.isArray(returnValue)){msg=v.messages[matcher.key||matcher]||v.messages["*"];msg=msg[conf.lang]||v.messages["*"].en;var matches=msg.match(/\$\d/g);if(matches&&$.isArray(returnValue)){$.each(matches,function(i){msg=msg.replace(this,returnValue[i])})}}else{msg=returnValue[conf.lang]||returnValue}to.push(msg)}$.extend(self,{getConf:function(){return conf},getForm:function(){return form},getInputs:function(){return inputs},reflow:function(){inputs.each(function(){var input=$(this),msg=input.data("msg.el");if(msg){var pos=getPosition(input,msg,conf);msg.css({top:pos.top,left:pos.left})}});return self},invalidate:function(errs,e){if(!e){var errors=[];$.each(errs,function(key,val){var input=inputs.filter("[name='"+key+"']");if(input.length){input.trigger("OI",[val]);errors.push({input:input,messages:[val]})}});errs=errors;e=$.Event()}e.type="onFail";fire.trigger(e,[errs]);if(!e.isDefaultPrevented()){effects[conf.effect][0].call(self,errs,e)}return self},reset:function(els){els=els||inputs;els.removeClass(conf.errorClass).each(function(){var msg=$(this).data("msg.el");if(msg){msg.remove();$(this).data("msg.el",null)}}).unbind(conf.errorInputEvent||'');return self},destroy:function(){form.unbind(conf.formEvent+".V").unbind("reset.V");inputs.unbind(conf.inputEvent+".V").unbind("change.V");return self.reset()},checkValidity:function(els,e){els=els||inputs;els=els.not(":disabled");if(!els.length){return true}e=e||$.Event();e.type="onBeforeValidate";fire.trigger(e,[els]);if(e.isDefaultPrevented()){return e.result}var errs=[];els.not(":radio:not(:checked)").each(function(){var msgs=[],el=$(this).data("messages",msgs),event=dateInput&&el.is(":date")?"onHide.v":conf.errorInputEvent+".v";el.unbind(event);$.each(fns,function(){var fn=this,match=fn[0];if(el.filter(match).length){var returnValue=fn[1].call(self,el,el.val());if(returnValue!==true){e.type="onBeforeFail";fire.trigger(e,[el,match]);if(e.isDefaultPrevented()){return false}var msg=el.attr(conf.messageAttr);if(msg){msgs=[msg];return false}else{pushMessage(msgs,match,returnValue)}}}});if(msgs.length){errs.push({input:el,messages:msgs});el.trigger("OI",[msgs]);if(conf.errorInputEvent){el.bind(event,function(e){self.checkValidity(el,e)})}}if(conf.singleError&&errs.length){return false}});var eff=effects[conf.effect];if(!eff){throw"Validator: cannot find effect \""+conf.effect+"\"";}if(errs.length){self.invalidate(errs,e);return false}else{eff[1].call(self,els,e);e.type="onSuccess";fire.trigger(e,[els]);els.unbind(conf.errorInputEvent+".v")}return true}});$.each("onBeforeValidate,onBeforeFail,onFail,onSuccess".split(","),function(i,name){if($.isFunction(conf[name])){$(self).bind(name,conf[name])}self[name]=function(fn){if(fn){$(self).bind(name,fn)}return self}});if(conf.formEvent){form.bind(conf.formEvent+".V",function(e){if(!self.checkValidity(null,e)){return e.preventDefault()}})}form.bind("reset.V",function(){self.reset()});if(inputs[0]&&inputs[0].validity){inputs.attr('novalidate','novalidate');inputs.each(function(){this.oninvalid=function(){return false}})}if(form[0]){form[0].checkValidity=self.checkValidity}if(conf.inputEvent){inputs.bind(conf.inputEvent+".V",function(e){self.checkValidity($(this),e)})}inputs.filter(":checkbox, select").filter("[required]").bind("change.V",function(e){var el=$(this);if(this.checked||(el.is("select")&&$(this).val())){effects[conf.effect][1].call(self,el,e)}});var radios=inputs.filter(":radio").change(function(e){self.checkValidity(radios,e)});$(window).resize(function(){self.reflow()})}$.fn.validator=function(conf){var instance=this.data("validator");if(instance){instance.destroy();this.removeData("validator")}conf=$.extend(true,{},v.conf,conf);if(this.is("form")){return this.each(function(){var form=$(this);instance=new Validator(form.find(":input"),form,conf);form.data("validator",instance)})}else{instance=new Validator(this,this.eq(0).closest("form"),conf);return this.data("validator",instance)}}})(jQuery);

