/* 
 * popasp_check 1.0 
 * Copyright (c) popasp
 * Date: 2017-1-22
 * LastModify: 2020-5-3
 * 表单验证
*/  
var popasp_check = function(validate,objForm,mode) {
	var VALUE_VALIDATE = 2;  	//表单值不为空则验证
	var MUST_VALIDATE = 1;  	//必须验证
	var EXISTS_VALIDATE = 0;  	//表单存在字段则验证
	var error = new Array(); 	//错误信息
	var reg,patchValidate;		//正则,patchValidate是否批处理验证
	var alertMsg;				//是否弹出错误信息，默认为弹出，后台用check_alertMsg设置
	var returnMsg;				//是否弹出错误信息，默认不返回，后台用check_returnMsg设置
	//对于layui的验证，可以采用 POPASP_CHECK.check_alertMsg = false; POPASP_CHECK.check_returnMsg = true;
	var dReg = {
			/*正则*/
			'require' :  /[^(^\s*)|(\s*$)]/,	    
			'email' : /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
			'url' : /^https?:\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/,
			'currency' : /^\d+(\.\d+)?$/,	
			'number' : /^\d+$/,
			'integer' : /^[-\+]?\d+$/,			
			'phone' : /^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/,
			'mobile' : /^((\(\d{3}\))|(\d{3}\-))?1[345789]\d{9}$/,
			'tel': /^(\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$/,
			'call':/^(^(0[0-9]{2,3}\-)?([2-9][0-9]{6,7})+(\-[0-9]{1,4})?$)|(^(1[358]\d{9})$)/,		   
			'zip' : /^\d{6}$/,
			'qq' : /^[1-9][0-9]{4,}$/,
			'ip'  : /((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)/,
			'plusint': /^[+]?\d+$/,
			'minusint': /^[-]\d+$/,
			'plusdecimal' : /^[+]?\d+(\.\d+)?$/,
			'minusdecimal' : /^[-]\d+(\.\d+)?$/,
			'double' : /^[-\+]?\d+(\.\d+)?$/,
			'english' : /^[A-Za-z]+$/,
			'chinese' :  /^[\u0391-\uFFE5]+$/,
			'db_id' :  /^[1-9]\d*$/
	};
	
	mode = ( mode==null ) ? 3 : POPASP_CHECK.check_mode;
	objForm = ( objForm==null ) ? document.forms[0] : objForm;
	validate = ( validate!=null ) ? validate : POPASP_CHECK.check_validate;
	patchValidate = POPASP_CHECK.check_patchValidate;
	alertMsg = POPASP_CHECK.check_alertMsg === false ? false: true ;
	returnMsg = POPASP_CHECK.check_returnMsg === true ? true: false;
	return handle();
	
	function classof(o){
		if (null===o) return null;
		if (undefined===o) return undefined;
		return Object.prototype.toString.call(o).slice(8,-1);
	}
	
	//array(验证字段,验证规则,错误提示,[验证条件,附加规则,验证时间])
	function handle(  ){
		var i,cnt,ret,cnt2,row;
		var bValidate;
		ret = true;
		if(classof( validate ) != "Array" || validate.length < 1 ) {//如果不是数组，或者数组为空则返回true
			return true;
		} 
		
		cnt = validate.length;
		for( i=0;i<cnt;i++ ){	//循环数组中的每个数组
			//验证因子定义格式
			//[field,rule,message,condition,type,when,params]
			//判断是否需要执行验证		
			bValidate = false;
			row = validate[i];
			cnt2 = row.length;

			//如果row[5]不存在，为true，否则row[5]==3或者row[5]==mode时才验证
			if( cnt2<6 ) {			
				bValidate = true;
			}else if(  (3==row[5] || mode==row[5]) ) {
				
				bValidate = true;
			} 


			if(!bValidate) {
				continue;				
			} 

			if(classof( row ) != "Array") {	//如果不是数组则返回true
				continue;
			} 
							
			if( cnt2 < 3 ){	//前三项是必须的
				showMsg( "自动验证的每条数组不能少于三项" );
				if ( returnMsg ) {
					return "自动验证的每条数组不能少于三项" ;					
				} else {
					return false;
				}				
			}
			
			if ( cnt2 < 4 ) {	//默认为存在就验证
				row[3] = EXISTS_VALIDATE;
			}
			
			if ( cnt2 < 5 ) {
				row[4] = "regex";	//默认采用正则验证
			}
		
			
			//判断验证条件
			switch( row[3] ){
				case MUST_VALIDATE:		//1 必须验证					
					if ( objForm[row[0]] === undefined ) {
						ret = false;
						error.push( "前后台设计不一致，必须验证的字段 "+ row[0] + " 在表单中不存在!" );
					}
					if( getValue( objForm,row[0] ) ===undefined) {
						ret = false;
						error.push( row[2] );
					} else {
						ret = validationField( objForm,row );
					}
					break;
				case VALUE_VALIDATE:	//2 值不为空的时候才验证
					if ( objForm[row[0]] === undefined ) {	//不存在返回true
						ret = true;
						break;
					} 
					
					if( getValue( objForm,row[0] ) != '' ) {
						ret = validationField( objForm,row );
					}
					break;
				default:	//0 默认表单存在该字段就验证
					if ( objForm[row[0]] === undefined ) {	//不存在返回true
						ret = true;
						break;
					} 
					ret = validationField( objForm,row );				
			}

			if ( !patchValidate && error.length> 0 ) {
				showMsg( error );
				if ( returnMsg ) {
					return error;
				} else {
					return false;
				}				
			}
		}
		
		if ( error.length > 0 ) {
			showMsg( error );
			if ( returnMsg ) {
				return error;
			} else {
				return false;
			}			
		}
		return true;
	}
	
	//获取表单值
	function getValue( form,field ) {		
		//if ( typeof(jQuery) !== "undefined" ) {
		//	ret  = jQuery( form ).find( "[name='" + field + "']" ).val();
		//} else{
			var ret;
			var obj =  form[field];
			if( classof( obj ).slice( -4 ).toLowerCase() != "list" ) {	//只有一个			
				switch( obj.tagName.toLowerCase() ) {
					case "input" :	//input标签
						switch( obj.type.toLowerCase() ){
							case "radio":		//radio					
							case "checkbox":	//checkbox
								if( obj.checked ) {
									ret = obj.value;
								}
							default:
								ret = obj.value;
						}
						break;
					case "textarea","select":
						ret = obj.value;
						break;
					default:
						ret = obj.value;
				}
				return ret;
			} else {
				var ret = new Array();
				var j = -1;
				for ( var i = 0 ; i< obj.length; i++ ) {
					switch( obj[i].tagName.toLowerCase() ) {
						case "input" :	//input标签
							switch( obj[i].type.toLowerCase() ){
								case "radio":		//radio					
								case "checkbox":	//checkbox
									if( obj[i].checked ) {
										ret[++j] = obj[i].value;
									}
									break;
								default:
									ret[++j] = obj[i].value;
							}
							break;
						case "textarea":
						case "select":
							ret[++j] = obj[i].value;
							break;
						default:
							ret[++j] = obj[i].value;
					}
				}
				return ret.length > 0 ? ret : undefined;
			}
		//}
	}

	function showMsg( arg ) {
		var msg;
		if(alertMsg) {
			if( classof( arg ) == 'Array' ) {
				msg = arg.join( "\n" );
			} else {
				msg = arg;				
			}
			if ( layui ) {
				layui.use('layer', function(){
					var layer = layui.layer;
					layer.msg( msg, {icon: 5});
				});
				
			}else {
				window.alert( msg );
			}			
		}
	}
	
	
	function validationField( form ,row ) {
		if( !validationFieldItem( form,row ) ) {
			error.push( row[2] );
			if ( !patchValidate ){
				return false;
			}			
		}
		return true;
	}
	
	//根据验证因子验证字段
	function validationFieldItem( form ,row ) {
		row[4] = row[4].toLowerCase();

		switch( row[4] ) {
			case 'function':case 'callback':case 'unique':case 'exists':
				//暂不支持的验证方法
				return true;
			case 'confirm' :
				return (getValue( form, row[0] ) == getValue( form,row[1] ) );
			case 'notconfirm' :
				return !validationFieldItem( form,row );
			default:
				if( row[4] == "ke_length" ) {
					return Check( KE.html( 'textarea[name="' + row[0] + '"]' ) , row[1] , 'length' );
				} else if( row[4] == "ue_length" ) {
					if( row.length > 5 ) {
						//getAllHtml取html内容，getContentTxt取文本内容
						return Check( UE.getEditor(row[6]).getAllHtml() , row[1] , 'length' );
					} else {
						return Check( UE.getEditor(row[0]).getAllHtml() , row[1] , 'length' );
					}					
				} else {
					return Check( getValue( form,row[0] ) , row[1] , row[4] );
				}
		}
	}
	
	//验证数据 支持 in notin between notbetween equal(eq) iequal(ieq) notequal(neq) length date regex expire ip_allow ip_deny,verify,notempty,ip
	function Check(value,rule,mode ) {
		
		switch( mode ) {
			case 'ip_allow': case'ip_deny':
				//暂不支持的方法
				return true;
			case 'in':	//此时的rule为range
				if(classof( rule ) == 'String' ) {
					rule = rule.split(',');
				}
				if ( classof( rule ) == 'Array' ) {
					if ( rule.indexOf( value.toString() ) < 0 ) {
						return false;
					} else {
						return true;
					}					
				}
				return false;
			case 'notin': case 'not in': case '_in':
				return !Check( value,rule,'in' );
			case 'between':	//验证是否在某个范围
				if ( classof( rule ) != 'Array' ) {
					rule = rule.split(',');
				}
				var min =  parseFloat( rule[0].trim() );
				min = isNaN( min ) ? 0 : min;
				var max =  parseFloat( rule[1].trim() );
				max = isNaN( max ) ? 0 : max;
				
				return (value>=min && value<=max);
			case "notbetween": case "not between": case "_between":
				return !Check( value,rule,'between' );
			case 'eq': case 'equal':
				return ( value == rule );
			case "ieq": case "iequal":
				return Check( value.toLowerCase(),rule.toLowerCase() , 'eq' );
			case "neq": case "notequal": case "_eq":
				return !Check( value,rule,'eq' );
			case "_ieq":
				return !Check(value,rule,"ieq" ) ;
			case "length":
				var len = value.length;
				if ( classof( rule )!='Array' ) {
					rule = rule.split(',');
				}
				if(rule.length > 1){
					return ( len>=parseFloat( rule[0].trim() ) && len<=parseFloat( rule[1].trim() ) );
				} else {
					return ( len == rule[0] );
				}
				break;
			case 'date':
				return !( (new Date( value )).toString() == 'Invalid Date');
			case 'expire':
				if ( classof( rule ) != 'Array' ) {
					rule = rule.split(',');
				}
				var min =  new Date( min.trim() );
				var max =  new Date( max.trim() );
				value = new Date( value );
				return ( value>=min && value<=max ) ;
			case 'notempty':
				return (value.trim()!='' && value!= null);
			default:
				return regex( value,rule );
		}	
	
	}
	
	
	//正则验证
	function regex( value,rule ) {
		var pattern;
		if( dReg[ rule.toLowerCase() ] !==undefined  ) {
			pattern = dReg[ rule.toLowerCase() ];
		} else{
			pattern = rule;
		}		

		try{			
			if ( reg === undefined ) {
				reg = new RegExp( pattern );			
			} else {
				reg.compile( pattern );
			}
			if ( classof(value) == "Array" ) {
				for( var i = 0 ; i < value.length ; i++ ) {
					if ( !reg.test( value[i].toString() ) ) {
						return false;
					}
				}
				return true;
			} else {				
				return reg.test( value.toString() );
			}			
		} catch ( err ) {
			showMsg( err.message );
			return true;
		}
	}
	
	String.prototype.trim = String.prototype.trim || function() {
		if (!this) return this;		//空字符串不做处理
		return this.replace(/^\s+|\s+$/g,'');	//使用正则表达式进行空格替换
	}
};