/**
 * @author denisdeng 
 * emmail dexibe@gmail.com || denisdeng@jobkoo.com
 * $Version: 2009.11.2. 1.0
 * @requires: jquery-1.3.2.min.js
 			  global.js
			  tip.js
 *
 * If an options Object is provided, the following attributes are supported:
 * 		param errorClass[String] The className of error;
 * 		param successClass[String] The className of success;
 * 		param tipClass[String] The className of tip;
 * 		param rules[json] The rule is used to validate;
 * 		param watchField[Boolean] Whether to live watch the field;
 * 		param onError[function] The function is used to handle all error infomation;
 * 		param onSubmit[function] The function is to submit the form by yourself;
 * 		eg. $("#reg").Validate({
				rules:rules
 			})
 */
(function($) {
$.Validate = {
		required:function(value){
			return this.getLength(value) > 0;
		},	
		minlength: function(value, param) {
			return this.getRealLength(value) >= param;
		},
		maxlength: function(value, param) {
			return this.getRealLength(value) <= param;
		},
		email: function(value) {
			return /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d)|(([a-z]|\d)([a-z]|\d|-|\.|_|~)*([a-z]|\d)))\.)+(([a-z])|(([a-z])([a-z]|\d|-|\.|_|~)*([a-z])))\.?$/i.test(value);
		},
		mobile: function(value){
			return /^\d{8,12}$/i.test(value);
			//return /\d+/i.test(value);
		},
		phone: function(value){
			//return /^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/i.test(value);
			return /\d+/i.test(value);
		},
		datestr: function(value){
			//return /^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/i.test(value);
			return /\d{4}\-\d{1,2}\-\d{1,2}/i.test(value);
		},
		range: function( value, param ) {
			var val = value.length;
			return ( val >= param[0] && val <= param[1] );
		},
		domain: function(value){
			var regex = /^((([a-z]|\d)|(([a-z]|\d])([a-z]|\d|-|\.|_|~|)*([a-z]|\d)))\.)+(([a-z])|(([a-z])([a-z]|\d|-|\.|_|~)*([a-z])))\.?$/i.test(value);			
			var findd = $.inArray(value,findKooConfig.domain) 
			return regex&&findd;
		},		
		url: function(value) {
			return /(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
		},
		equalTo: function(value, param) {
			return value == $(param).val();
		},
		isCn:function(value){
			var lst = /[u00-uFF]/;
			return !lst.test(value);
		},
		getLength:function(value){
			value = $.trim(value);
			var length = 0;
			var self = this;
			$.each(value,function(i,v){
								  		if(self.isCn(value.charAt(i)) == true)
											length += 2;
										else
											length += 1;
								  })
			return length;
		},
		getRealLength:function(value){
			value = $.trim(value);	  
			return value.length;
		},		
		subString:function(value,length){
			var r = /[^\x00-\xff]/g;
			if(value.replace(r,'mm').length <= length){
				return value;	
			}else{
				var m = Math.floor(length/2);
				for(var i = m;i<value.length;i++){
					if(value.substr(0,i).replace(r,'mm').length >= length){
						return value.substr(0,i);
					}
				}
			}
		},
		isEmpty:function(value){
			return value == 0 || value == '';
		},
		isInt:function (value,type){
			var rt = '';
			if(type=="0+"){
				rt = "^\\d+$";
			}else if(type=="+"){
				rt = "^\\d*[1-9]\\d*$";
			}else if(type=="-0"){
				rt = "^((-\\d+)|(0+))$";
			}else if(type=="-"){
				rt = "^-\\d*[1-9]\\d*$";
			}else{
				rt  = "^-?\\d+$";
			}
			var reg = new RegExp(rt,'i');
			return reg.test(value);
		},
		getValueByGroup:function(name){
			return $('input[name="'+name+'"]:checked').val() || '';
		},
		request: function (name) {
			var reg = new RegExp("(^|\\?|&)"+ name +"=([^&]*)(\\s|&|$)", "i");
			if (reg.test(location.href))
			return unescape(RegExp.$2.replace(/\+/g, " "));
			return "";
		},
		compare:function(){
			//取得显示错误信息的方式boolean;
			var len = arguments.length;
			var info = arguments[len -1];//取得选项为空的错误提示信息;
			if(len > 1){
				var args = Array.prototype.slice.call(arguments);
				args.shift();
			};
			var diff = parseInt(arguments[0].end,10) - parseInt(arguments[0].begin,10);
			if(diff < 0){
				//error(arguments[0].tip);
				$.Validate.hideInfo(info,'success');
				$.Validate.showInfo(info,arguments[0].tip,'error');
				return false;				
			}else if(diff == 0){
				if(len > 1){
					return $.Validate.compare.apply(this,args);
				}else{
					$.Validate.hideInfo(info,'error');
					$.Validate.showInfo(info,'success','success');
					return true;
				};
			}else{
				//success();
				$.Validate.hideInfo(info,'error');
				$.Validate.showInfo(info,'success','success');
				return true;
			}
		},
		showInfo:function(obj,tip,tipClass){
				var wrap = obj.next('.adaptiveWrap');
				if(wrap.size() == 1){
					wrap.remove();
				}
				/*var w = $(obj).outerWidth() < 240 ? 240 : $(obj).outerWidth();
				if($.browser.msie&&($.browser.version == "7.0")){
					w +=50;	
				};*/
				obj.addClass(tipClass + "_obj");
				var corner = $("<p class='con'>"+tip+"</p>");
				var wrap = $("<div class='adaptiveWrap'></div>");
				var tip = $("<div></div>").addClass(tipClass);
				tip.append(corner);
				wrap.append(tip);
				wrap.insertAfter(obj);
		},
		hideInfo:function(obj,infoClass){
			if(obj.next('.adaptiveWrap').html() !== null){
				obj.next('.adaptiveWrap').remove();
			};
			if(obj.hasClass(infoClass + "_obj")){
				obj.removeClass(infoClass + "_obj");
			}
		},
		elements:function(rules,context){
			var elements = [];
			var aStr = [];
			$.each(rules,function(key,value){
								  		var obj = {};
										//alert($.Validate.rules[value]);
										if($.Validate.rules[value] !== undefined){
											var rule = $.Validate.rules[value];
											if($("."+ value,context).size() !== 0 && $("."+ value,context).not(':disabled').is(':visible')){
												obj.name = 	$("."+ value,context);
												if(rule.tip){
													obj.tip = rule.tip;
												};
												if(rule.func && $.isFunction(rule.func)){
													obj.func = rule.func;
												};
												if(rule.infoPos !== 'undefined' && typeof rule.infoPos == 'string'){
													obj.infoPos = $(rule.infoPos);
												};
												obj.isWatch = rule.isWatch;
												elements.push(obj);
											}
										}else{
											//alert("className 为" + value +"的对象不存在！");	
										}
								  })
			return elements;
		},
		showAllerror:function(errors){
			var wrapper = $("<ul></ul>");
			$.each(errors,function(i,v){
								   		var li = $("<li></li>").append(v);
										wrapper.append(li);
								   })
			return wrapper;
		},
		ajaxValidate:function(aRequest,func){
			/*
			@param:aRequest 需要ajax验证的数组;
			@param:valid 需要ajax验证的数组;
			aRequest = [
						{
							keys:{
									name:'one',
									age:'32'
								},
							obj:$('code'),
							url:'/sgs',
							error:'错误提示！',
							isShowError:true,
							infoPos:null
						},
						{
							data:{"name":'244'},
							url:'http://www.g.cn',
							error:'错误提示！'
						}
			];*/	
			var len = aRequest.length;
			var aKeys = [];
			$.each(aRequest[0].keys,function(key,val){
					if(typeof val == 'string'){
						aKeys.push(key + "=" + val);
					}else{
						aKeys.push(key + "=" + $(val).val());
					}
			});
			function doAjax(){
				var isError = typeof aRequest[0].isShowError !== 'undefined' ? aRequest[0].isShowError : true;
				$.ajax({
						url:aRequest[0].url,
						data:aKeys.join('&'),
						type:'post',
						cache:false,
						dataType:'json',
						success:function(msg){
							var infoPos = typeof aRequest[0].infoPos !== 'undefined' ? $(aRequest[0].infoPos) : $(aRequest[0].obj);
							var error = typeof msg.message !== 'undefined' ? msg.message : aRequest[0].error;
							if(msg.status == 1){
								if(len > 1){
									aRequest.shift();
									return $.Validate.ajaxValidate.call(null,aRequest,func);
								}else{
									if($.isFunction(func)){
										func();
									}
								}
								$.Validate.hideInfo(infoPos,'error');
								return true;
							}else{
								if(isError){
									$.Validate.showInfo(infoPos,error,'error');
								}
								return false;
							}
						},
						error:function(){
							//alert("请检查服务器连接!");
						}
					})	
			}
			if(typeof aRequest[0].func !== 'undefined' && $.isFunction(aRequest[0].func)){
				var isAjax = aRequest[0].func();
				if(isAjax){
					doAjax();
				}else{
					return true;	
				}
			}else{
				doAjax();	
			}
		},
		ajaxValidateField:function(obj,watchField){
			var aKeys = [];
			function doAjax(){
					var isError = typeof obj.isShowError !== 'undefined' ? obj.isShowError : true;
					$.ajax({
							url:obj.url,
							data:aKeys.join('&'),
							type:'post',
							cache:false,
							dataType:'json',
							success:function(msg){
								var infoPos = typeof obj.infoPos !== 'undefined' ? $(obj.infoPos) : $(obj.obj);
								var error = typeof msg.message !== 'undefined' ? msg.message : obj.error;
								if(msg.status == 1){
									$.Validate.hideInfo(infoPos,'error');
									return true;
								}else{
									if(isError){
										$.Validate.showInfo(infoPos,error,'error');
									}
									return false;
								}
							},
							error:function(){
								alert("请检查服务器连接!");
							}
						})	
			};
			function doValidate(){
				if(typeof obj.func !== 'undefined' && $.isFunction(obj.func)){
					var isAjax = obj.func();
					if(isAjax){
						doAjax();
					}else{
						return true;	
					}
				}else{
					doAjax();	
				}
			};
			var isWatch = typeof obj.isWatch == 'undefined' ? watchField : obj.isWatch;
			if(isWatch){
				$(obj.obj).bind('blur',function(){
						//在鼠标失去焦点时获取数据;
						$.each(obj.keys,function(key,val){
								if(typeof val == 'string'){
									aKeys.push(key + "=" + val);
								}else{
									aKeys.push(key + "=" + $(val).val());
								}
						});
						doValidate();							
				})	
			}
		},
		compareDate:function(obj){
			var defult = {
							begin:obj.begin,
							end:obj.end,
							format:obj.format || 'y-m-d h:m'
			};
			var aDateBegin = splitDate(defult.begin,defult.format);
			var aDateEnd = [];
			if(typeof defult.end !== 'undefined'){
				var aDateEnd = splitDate(defult.end,defult.format);
			}else{
				var current = new Date();
				aDateEnd.push(current.getFullYear(),current.getMonth() + 1,current.getDate());
			}
			var timersBegin = getDateSeconds.apply(null,aDateBegin);
			var timersEnd = getDateSeconds.apply(null,aDateEnd);
			//将月份转换成毫秒数
			function getDateSeconds(y,m,d){		
				var date = new Date(y,m - 1,d);
				return date.getTime(); 
			}
			//格式化日期
			function splitDate(date,format){
				var aDate = [];
				switch(format){
					case 'y/m/d':
						 aDate = date.split('/');
						break;
					default: // 'y-m-d h:m'
						 aDate = date.split('-');
				}
				return aDate;
			};
			return parseInt(timersEnd) > parseInt(timersBegin);
		},
		addRule:function(rule){
				// obj = {
							//name:{
										//tip:'提示信息',
										//func:function(){}
								//},
				//	}
				$.each(rule,function(key,value){
						if($.Validate.rules[key] == null ){
							$.Validate.rules[key] = value;
						}else{
							//alert('该规则已经存在。');
						}
				})
		}
}
$.Validate.rules = {
	userName:{
				func:function(value){
				 if(!$.Validate.required(value)){
					return  '格式不正确，请重输！';
				 }else{
					return true
				 }
			}
	},
	password:{
				func:function(value){
				 if(!$.Validate.required(value) || value.length <6 || value.length>16){
						return '密码格式不正确，长度限制6-16位，请重输！';
					}else{
						return true;
					}
			}
	},
	confirmPassword:{
				func:function(value){
				if(!$.Validate.required(value)){
						return '密码格式不正确，请重输！';
				}else{
					 if(!$.Validate.equalTo(value,"input.password")){
						return '与密码不一致，请重输！';
					 }else{
						return true
					 }
				}
			}
	},
	url:{
		func:function(value){
				if(!$.Validate.required(value)){
						return '请输入网络地址！';
				}else{
					 if(!$.Validate.url(value)){
						return '网络地址格式不正确！';
					 }else{
						return true
					 }
				}
			}	
	},
	email:{	
			func:function(value){
				 if(!$.Validate.required(value)){
						return '邮件地址不能为空。';
				 }else if(!$.Validate.email(value)){
						return '邮箱格式不正确，请重输！';
				 }else{
						return true;
				 }
			 }
	},
	isIdCardNo:{
		func:function(value){   
				value = value.toUpperCase();  
				//身份证号码为15位或者18位，15位时全为数字，18位前17位为数字，最后一位是校验位，可能为数字或字符X。   
				if(!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(value))){ 
					return '输入的身份证号长度不对，或者号码不符合规定！\n15位号码应全为数字，18位号码末位可以为数字或X。'; 
				}else{
					return true; 
				}
		}
	}
}
$.fn.Validate = function(options){
	var defaults = {
			errorClass:"error",
			successClass:"success",	
			tipClass:"tip",
			rules:[],
			specialRule:null,
			errorContanier:'',
			watchField:false,
			//checkFormBtn:'',
			selfValidate:null,
			ajaxValidObj:null,
			//checkFormFunc:null,			
			onError:null,
			btnSubmit:null,
			isShowSuccessTip:false,
			onSubmit:null
		}
	return this.each(function(){
			if(options) settings = $.extend(defaults, options);
			var form = $(this);
			var action = form.attr("action");
			var elements = $.Validate.elements(settings.rules,$(this));
			var btnSubmit = settings.btnSubmit == null ? $('.btnSubmit',$(this)) : settings.btnSubmit;
			var isSubmit;
			if(elements.length >0){
			$.each(elements,function(key,json){
							var infoPos = json.infoPos || $(json.name);//定义错误显示的目标位置；
							$(json.name).bind("doCheck",function(){
													var error = json.func($.trim($(this).val()));
													var $this = $(this);
													//隐藏错误信息和成功信息提示
													$.Validate.hideInfo(infoPos,settings.tipClass);
													$.Validate.hideInfo(infoPos,settings.successClass);
													if(typeof error == 'string'){
															$(this).data('error',error);
															//失去焦点的事件处理函数
															//if($(this).val() !== ''){
															//如果没有自定义处理错误信息函数，则显示错误信息;
															if(!$.isFunction(settings.onError)){
																$.Validate.showInfo(infoPos,error,settings.errorClass);
															}
															//}
													}else{
															//alert(typeof error)
															//alert(error.ajaxUrl)
															if($(this).data('error')){
																$(this).removeData('error');
															}
													};
										 })
							//输入框失去焦点时检查输入内容
							var isWatch = typeof json.isWatch == 'undefined' ? settings.watchField : json.isWatch;
							if(isWatch){
								$(json.name).bind('blur',function(){
															var obj = $(json.name);
															setTimeout(function(){
																					if(!isSubmit) {
																						obj.trigger("doCheck");
																					}
																					isSubmit = false;
																				},100);
															
												});
							};
							$(json.name).bind('blur',function(){
															$.Validate.hideInfo(infoPos,settings.tipClass);
												});
							//输入框获得焦点时显示输入提示
							$(json.name).bind('focus',function(){
										//获得焦点时隐藏错误信息提示和成功信息提示，同时显示输入提示
											$.Validate.hideInfo(infoPos,settings.errorClass);
											//$.Validate.hideInfo($(this),settings.errorClass);
											//$.Validate.hideInfo($(this),settings.successClass);
											//$.Validate.showInfo($(this),json.tip,settings.tipClass);
											if(settings.isShowSuccessTip && infoPos.next().hasClass(settings.successClass)){
												infoPos.next().show();
											};
											if(infoPos.next().hasClass(settings.errorClass)){
												infoPos.next().show();
												//$.Validate.hideInfo(infoPos,settings.tipClass);
											}else if($(this).val() == ''){
												if(json.tip){
													$.Validate.showInfo(infoPos,json.tip,settings.tipClass);
												};
											};
										});
			});
			}
			//为表单绑定提交处理函数;
			//$(this).bind("doSubmit",
			function doSubmit(){
						var isValid = true;
						var errors = [];
						$.each(elements,function(key,json){
													var infoPos = json.infoPos || $(json.name);
													$(json.name).trigger("doCheck");
													var error = $(json.name).data('error');
													//判断是否有error;
													if(error){
														errors.push(error);
													}
											  });
						//自定义错误信息处理函数
						if($.isFunction(settings.onError) && errors.length > 0){
							if($(settings.errorContanier).html() !== null){
									$(settings.errorContanier).empty();
							}
							var allError = $.Validate.showAllerror(errors);
							settings.onError(allError);
						};
						if(settings.specialRule !== null){
							for(key in settings.specialRule){
								if(!settings.specialRule[key]()){
									isValid = false;
									continue;
								}
							}
						};
						return errors.length == 0 && isValid;
			};
			//给ajax验证绑定blur事件;
			if(settings.ajaxValidObj !== null && $.isArray(settings.ajaxValidObj) && settings.watchField){
					$.each(settings.ajaxValidObj,function(key,val){
						$.Validate.ajaxValidateField(val,settings.watchField);						 
					})
			}
			//定义提交动作触发事件
			//var btnSubmit = settings.btnSubmit == null ? $('input[type="submit"]',$(this)) : $(settings.btnSubmit);
			btnSubmit.bind('click',function(e){
										isSubmit = true;
										var isPass = doSubmit();
										var btnSubmit = $(this);
										//默认的提交方式;
										function doAjaxSubmit(){
											if($.isFunction(settings.onSubmit)){
												settings.onSubmit(isPass,form,btnSubmit);
											}else{
												if(isPass){
													form.submit();	
												}
											}	
										}
										if(settings.ajaxValidObj !== null && $.isArray(settings.ajaxValidObj)){
											if(isPass){
												$.Validate.ajaxValidate(settings.ajaxValidObj,doAjaxSubmit);
											}
										}else{
											doAjaxSubmit();	
										}
										e.preventDefault();
									 });
			//表单提交到不同的地址
			/*
				{
					"btn-1":{
								func:function(){},
								url:'',
								tip:
					},
					"btn-2":{
								func:function(){},
								url:''
					}
				}
			*/
			if(settings.selfValidate !== '' && $.isPlainObject(settings.selfValidate)){
				$.each(settings.selfValidate,function(key,json){
											 	$(key).removeClass('btnSubmit').bind('click',function(e){
														var valid = doSubmit();
														//自定义提交表单;
														function submitBySelf(){
															//如果有处理函数,则用处理函数处理表单														
															if(json.func && $.isFunction(json.func)){
																json.func(valid,form);	
															};
															//如果有url地址,则改变action
															if(json.url!== '' && typeof json.url == "string"){
																//无提示文字直接提交表单
																if(valid){
																	form.attr("action",json.url).submit();
																};
															}	
														}
														if(settings.ajaxValidObj !== null && $.isArray(settings.ajaxValidObj)){
															if(valid){
																$.Validate.ajaxValidate(settings.ajaxValidObj,submitBySelf);
															}
														}else{
															submitBySelf()
														}
														e.preventDefault();
												})
											 })	
			};
		  });
}


})(jQuery)
