/**
 * Title : frm.js
 * Description : 입력값의 검증
 *
 * @Author gggl.ko / kojaepil@easymedia.net
 * @Create 2008-04-04
 * @Update
 */

/*
 * 2008-04-04
 */
 /*

1. 메시지를 검수항목별로 지정가능	 ex) required="aaa" number="bbb"
2. 메시지 대신 함수실행가능함. ex)required="window.close();"
3. 개별개체 검사가능 ex)<input type="text" name="" value="" required="aaa" number="bbb" onchange="validate(this)">
4. fail = 검증실패시 실행
5. chk = 검증시마다 실행
6. success = 성공시에 실행
7. 동일 폼내의 email2 와 합쳐서 검증 / implode="email2"
8. delete 검증실패시 값지움
9. focus="개체" 검증실패후 해당개체에 포커스
10. nofocus 검증실패후 포커스 이동없음
11. diplaySkip 있고, 해당개체 display 가 none 인경우, 해당개체검증 스킵
12. requiredSkip 빈값인경우는 검증하지 않고 넘어감

2008-12-02
13. trueSkip - trueSkip="조건" = 조건이 참이면 나머지 attribute 실행하지 않음.
*/

var G_cfrmMsg; //외부설정 확인 메시지 변수

/**
*
* @param Form Object
* @return boolean
*/
function validate(frm,cfrmMsg) {

		if (cfrmMsg != undefined && cfrmMsg != "") {
				if (confirm(cfrmMsg) == false) {
						return false;
				}
		}
		try {
						
		var checker = new FrmChk(frm);
		return checker.go();
						} catch (e) {
								alert(e);
				}

}

// ------------------------------------------- // 입력값 검증 prototype ------------------------------------------------------------------------

FrmChk = function(frm) {

	// validate 타입
	this.validate = Array("required", "passChk","equal", "notEqual","minbyte","maxbyte","email","phone","ext", "idChk", "number","nameChk", "tel","SiteChk", "OfficeNum");

    //define error message
	this.DE_errMsg = {
	   common			: "입력하신 내용이 규칙에 어긋납니다.\n규칙에 어긋나는 내용을 바로잡아주세요."
	   ,required			: "값이 입력되지 않았습니다."
	  , equal				: "입력값이 일치하지 않습니다."
	  , invalid				: "입력값이 형식에 벗어납니다."
	  , minbyte			: "입력값의 길이가 {minbyte}자(영문기준) 이상이어야 합니다."
	  , email				: "이메일 입력값이 올바르지 않습니다."
	  , maxbyte			: "입력값의 길이가 {maxbyte}자(영문기준)를 초과할 수 없습니다."
	  , ext					: "첨부한 파일은 {ext} 타입이여야 합니다."
	  , idChk				: "아이디 입력값이 올바르지 않습니다. (대소문자+숫자 , 6~12자 사이여야 합니다.)"
	  , passChk			: "패스워드 입력값이 올바르지 않습니다.(대소문자+숫자 , 8~12자 사이여야 합니다.)"
	  , number			: "숫자만 입력할 수 있습니다."
	  , notEqual			: "입력값이 일치합니다."
	}

	this.value;
	this.chkPrototype;
	this.errMsg;
	this.form = frm;		//검증호출시 파라미터로 받은 검증개체를 셋팅			- naming 을 this.form 으로 가져감으로써, 내부,외부 싱크
	this.obj = {
		Rtype : ""	// 검증개체 type
		,Rvalue : "" // 검증개체 value
	};

	// 에러여부 플래그
	this.err = false;

	// 현재 검사 타입
	this.chkPrototype = "";

	// 현재 검사 타입 값
	this.chkAttVal = "";

	// 추가로 뿌려줄 메시지 기본 메시지 \n\n - 형식
	this.addErrMsg = "";

}

FrmChk.prototype.go = function() {

	// 폼이 아닐경우 개별개체설정
	if (this.form == null || this.form.tagName.toLowerCase() != "form") {
		var i2 = 1;
	} else {
		var i2 = this.form.elements.length;
	}

	for (var i = 0; i < i2; i++) {

				// 검사 개체 초기화
				this.init(i);

				// skip
				if ( this.obj.name == "" || this.obj == null || this.obj.tagName.toLowerCase() == "fieldset" || this.obj .tagName.toLowerCase() == "object") continue;

				// disabled 인경우와, diplaySkip이 있고, 해당개체  display=none 인경우, skip
				if (this.obj.disabled == true || (this.obj.getAttribute("diplaySkip") != null && this.obj.style.display == "none")) continue;

				// requiredSkip 속성 존재하고, 빈값인 경우는 skip
				if (this.obj.getAttribute("requiredSkip") != null && this.obj.value == "") continue;
				
				// falseSkip 속성 존재하고 falseSkip 의 값을 eval 로 실행해서 false 일경우 skip				
				if (this.obj.getAttribute("trueSkip") != null && eval(this.obj.getAttribute("trueSkip")) == true) continue;						
				var sucessChk = false;

				//
				// validate
				//
				for (var j=0; j < this.validate.length; j++) {

						// init
						var chk = this.chk_init(this.validate[j]);

						// 파일인경우는 무조건 검사
						if (chk == false || (this.obj.Rtype == "file" && this.validate[j] == "ext")) {
								if (eval("this."+this.validate[j]+"()") == false) {
										try { 
												this.errExec();
										} catch(e) {
										}
										return false;
								}
						}
				}

				//개별 오브젝트 true
				// success  어트리뷰트가 있는경우, 실행한다. - 파일인 경우는 값이 있는경우만

				if ((this.obj.Rtype == "file" && this.obj.Rvalue != "") || this.obj.Rtype != "file") {
						if (this.obj.getAttribute("success")) {
								try {
										eval(this.obj.getAttribute("success"));
								} catch (e) {
										alert(e.message);
								}
						}
				}
	}

	return true;		//운영모드
	//return false;	//개발모드
}


/**
* 개체별 초기화
*
*/
FrmChk.prototype.init = function (i) {

		// 변수초기화
		this.errMsg = "";

		// 폼인지 단일개체인지 구분하여 할당
		if (this.form.tagName.toLowerCase() == "form") {
				this.obj = this.form.elements[i];
		} else {
				this.obj = this.form;
		}

				
		// trim 어트리뷰트가 있는경우, 실행한다.
		if (this.obj.getAttribute("trim") != null) {
				this.obj.value = this.obj.value.replace(/(^[ \f\n\r\t]*)|([ \f\n\r\t]*$)/g, "");
		}

		// exec 어트리뷰트가 있는경우, 실행한다.
		if (this.obj.getAttribute("exec") != null && this.obj.getAttribute("exec") != "") {										
				eval(this.obj.getAttribute("exec").split("this.value").join("this.obj.value"));				
		}

		// 기본설정
		if (this.obj.type == "radio" || this.obj.type == "checkbox") {
				this.obj.Rtype = "check";
		} else if (this.obj.type == "file") {
				this.obj.Rtype  = "file";
		} else if (this.obj.tagName == "select") {
				this.obj.Rtype  = "select";
		} else {
				this.obj.Rtype  = "text";
		}

		// 타입에 따른 값 할당
		this.obj.Rvalue = "";

			switch (this.obj.Rtype) {
						case "file": case "text":
									this.obj.Rvalue = this.obj.value;
						break;
						case "select":
									if (this.obj[this.obj.selectedIndex].value == null || this.obj[this.obj.selectedIndex].value == "") {
										this.obj.Rvalue = "";
									} else {
										this.obj.Rvalue = this.obj[this.obj.selectedIndex].value;
									}
						break;
						case "check":
									//개별단일개체가 아닌, 복수일수도 있으므로, 해당 이름으로 개체 재설정함
									var elCheck = this.form.elements[this.obj.name];

									if (typeof elCheck != "undefined") {
										if (isNaN(elCheck.length) == true) {
												if (elCheck.checked == true) {
														this.obj.Rvalue = this.obj.value;
												}

										} else {
												for (var j = 0; j < elCheck.length; j++) {
													try {
															if (elCheck[j].checked == true) {

																	if (this.obj.Rvalue == "") {
																			this.obj.Rvalue = elCheck[j].value;
																	} else {
																			this.obj.Rvalue = this.obj.Rvalue + "," + elCheck[j].value;
																	}
															}

													}catch (e){
															alert(e.message);
													}

												}

										}
									}
						break;
			}
}

/**
* 에러모드 실행 - 외국사이트등의 구축시 메시지 alert 가 아닌 메시지 print 고려하여 별도의 prototype으로 생성함.
*
* @param
* @return private
*/
FrmChk.prototype.errExec = function () {

						// false 어트리뷰트가 있는경우, 실행한다.
						if (this.obj.getAttribute("fail")) {
								try {
										eval(this.obj.getAttribute("fail"));
								} catch (e) {
										alert(e.message);
								}
						}

						this.setErrMsg();

						if (this.errMsg != "") {
								alert(this.errMsg);
						}

						if (this.obj.getAttribute("delete") != null) {
										this.obj.value = "";
						}

						if (this.obj.getAttribute("select") != null) {
							this.obj.select();
						}

							//nofoucs 인경우, 포커스 없음. focus 있는경우 해당 지정
							if (this.obj.getAttribute("nofocus") == null || this.obj.Rtype != "hidden") {
								try	 {
										eval(this.obj.getAttribute("focus")+".focus();");
								} catch (e) {
										try {
												this.obj.focus();
										} catch (e) {
										}
								}
							} else {
								this.obj.focus();
							}

}

/**
* 에러메시지 할당
*
* @param
* @return private
*/
FrmChk.prototype.setErrMsg = function () {

					var pattern = /\{([a-zA-Z0-9_]+)\}/i;

					if (this.obj.getAttribute(this.chkPrototype) !=  null) {

										// 에러메시지 및 실제 속성값부여
										var Arr = this.obj.getAttribute(this.chkPrototype).split(":",2);

										if (Arr[1] != undefined) {
												this.errMsg  = Arr[1];
										} else {

												// 두가지 타입으로 나뉜다. 1. minbyte="4" or require="zz"
												if (this.chkPrototype == "minbyte" || this.chkPrototype == "ext") {

														this.errMsg = this.DE_errMsg[this.chkPrototype];

												} else {

														if (this.obj.getAttribute(this.chkPrototype) != "") {
																		this.errMsg = this.obj.getAttribute(this.chkPrototype);
														} else {
																		this.errMsg = this.DE_errMsg[this.chkPrototype];
														}

												}
										}


					} else {
							this.errMsg = this.DE_errMsg[this.chkPrototype];
					}

						// 함수일 경우 해당 함수를 실행해준다.
						try {
								// eval 적용중 alert 인경우는 skip
								if (this.errMsg.substr(0,5) != "alert") {
										this.errMsg =eval(this.errMsg);
								}

						} catch (e) {
								this.errMsg = this.errMsg;
						}

						// 추가 메시지가 있을경우
						if (this.addErrMsg != "") {
								this.errMsg = this.errMsg + "\n\n- "+ this.addErrMsg + "\n ";
						}
}

/**
* 검증기능 전 초기화 (검증 타입별로)
*
* @param
* @return private
*/
FrmChk.prototype.chk_init = function(t) {

		this.errMsg = "";
		this.chkAttVal = "";

		this.chkPrototype = t;

		if (this.obj.getAttribute(t) == null) {
				return true;
		}	else {

				if (this.obj.getAttribute(t) !=  null) {

						// 에러메시지 및 실제 속성값부여
						var Arr = this.obj.getAttribute(t).split(":",2);

						if (Arr[1] != undefined) {
								this.chkAttVal  = Arr[0];
						} else {
								this.chkAttVal  = this.obj.getAttribute(this.chkPrototype);
						}

						// 함수일경우 실행하기 차후에, eval 에 대한 전체적인 기능 필요
						// eval 로 접근할 경우, 전역으로 접근해야함. 내부접근이 아님
						try {
								this.chkAttVal = eval(this.chkAttVal);
						} catch (e) {
						}
				}

				return false;
		}
}

// ------------------------------------------- // 입력값 검증 prototype ------------------------------------------------------------------------

/**
* required 검증 (빈값체크)
* @param
* @return boolean
*/
FrmChk.prototype.required = function() {

								if (this.obj.Rvalue == "") {
										return false;
								} else {
										return true ;
								}

}


/**
* equal 검증 (같은지 안같은지)
* @param
* @return boolean
*/
FrmChk.prototype.equal = function() {

				if (this.obj.Rvalue != this.chkAttVal) {
						return false;
				} else {
						return true ;
				}
}


/**
* notEqual 검증 (같은지 안같은지)
* @param
* @return boolean
*/
FrmChk.prototype.notEqual = function() {

				if (this.obj.Rvalue == this.chkAttVal) {
						return false;
				} else {
						return true ;
				}
}


/**
* 최소값
* @param
* @return boolean
*/
FrmChk.prototype.minbyte = function() {

				var len = this.chkAttVal;

				if (isNaN(len) ==  true) {
						return false;
				}


				if (this.obj.Rvalue.length < len) {
						return false;
				}
}

/**
* 최대값
* @param
* @return boolean
*/
FrmChk.prototype.maxbyte = function() {

				var len = this.chkAttVal;

				if (isNaN(len) ==  true) {
						return false;
				}

				if (this.obj.Rvalue.length > len) {
						return false;
				}
}


/**
* 핸드폰
* @param
* @return boolean
*/
FrmChk.prototype.phone = function() {

				var pattern = /^([0]{1}[0-9]{1,2})-?([1-9]{1}[0-9]{2,3})-?([0-9]{4})$/;

				if (pattern.exec(this.obj.Rvalue)) {
						if(RegExp.$1 == "011" || RegExp.$1 == "016" || RegExp.$1 == "017" || RegExp.$1 == "018" || RegExp.$1 == "010" || RegExp.$1 == "019") {
							return true;
						} else {
							return false;
						}
				} else {
						return false;
				}
}

/**
* 전화번호
* @param
* @return boolean
*/
FrmChk.prototype.tel = function() {

				var pattern = /^[0-9]{2,4}-?[0-9]{3,4}-?[0-9]{4}$/;

				if (pattern.exec(this.obj.Rvalue)) {
							return true;
				} else {
						return false;
				}
}

/**
* 사업자 등록번호
* @param
* @return boolean
*/
FrmChk.prototype.OfficeNum = function() {

				var pattern = /^[0-9]{3}-?[0-9]{2}-?[0-9]{5}$/;

				if (pattern.exec(this.obj.Rvalue)) {
							return true;
				} else {
						return false;
				}
}

/**
* 영어만 입력하게끔
* @param
* @return boolean
*/
FrmChk.prototype.SiteChk = function() {

				var pattern = /^[a-zA-Z0-9-\.\_]+$/;

				if (pattern.exec(this.obj.Rvalue)) {
							return true;
				} else {
						return false;
				}
}


/**
* 숫자만입력 체크
* @param
* @return boolean
*/
FrmChk.prototype.number = function() {

				var pattern = /[^0-9]/g;

				if (pattern.exec(this.obj.Rvalue)) {
						return false;
				} else {
						return true;
				}
}


FrmChk.prototype.email = function() {

				var val = this.obj.Rvalue;

				if (this.obj.getAttribute("implode") != "") {

						var addV = this.obj.getAttribute("implode");

						if (addV != null && eval("this.form."+addV) != undefined && eval("this.form."+addV).value) {
								val = this.obj.Rvalue + "@" + eval("this.form."+addV).value;
						}
				}

				var pattern = /^[_a-zA-Z0-9-\.\_]+@[\.a-zA-Z0-9-]+\.[a-zA-Z]+$/;
				return (pattern.test(val)) ? true : false;
}

/**
* 파일타입체크
* @param
* @return boolean
*/
FrmChk.prototype.ext = function() {

				/* ----------------------------------------------------------------- */
				var notExt = Array("php","jsp","asp","exe", "js","html","htm","rb");

				this.obj.Rvalue = this.obj.Rvalue.toLowerCase();

				for (var i=0; i<notExt.length ;i++ ) {

						if (this.obj.Rvalue.toLowerCase().indexOf("."+notExt[i]) != -1) {
								return false;
								break;
						}
				}

				if (this.obj.Rvalue == "" || this.chkAttVal == "") {
						//규약조건을 벗어난 true 이므로

						return true;
				} else {

						/* ----------------------------------------------------------------- */

						var execExtArr;

						var exts = {
								"img" : Array("bmp","jpg","jpeg","gif","scr","jp2","png","wmf","pic","swf")
								,"aud" : Array("wma","mp2","mp3","wav","mid","cda","asx","ogg")
								,"mov" : Array("avi","mpg","mpeg","asf","wmv","flv","mov","m3u")
								,"doc" : Array("txt","doc","hwp","pdf","htm","html","ppt","gul","url","xml")
						}
						
						if (this.chkAttVal == "_image") {
								execExtArr = exts['img'];
						} else if (this.chkAttVal == "_audio") {
								execExtArr = exts['aud'];
						} else if (this.chkAttVal == "_movie") {
								execExtArr = exts['mov'];
						} else if (this.chkAttVal == "_document") {
								execExtArr = exts['doc'];
						} else if(this.chkAttVal != undefined && this.chkAttVal != "") {
								alert(this.chkAttVal);
								execExtArr = this.chkAttVal.split(",");
						}
						
						for (var j=0;j < execExtArr.length; j++) {
							if (this.obj.Rvalue.indexOf("."+execExtArr[j]) != -1 ) {
								return true;
								break;
							}
						}

						return false;
				}

				return true;
}

/**
* 아이디 체크
* @param
* @return boolean
*/
FrmChk.prototype.idChk = function() {

			var pattern = /^[a-zA-Z]{1}[a-zA-Z0-9_]{5,12}$/;

			if (pattern.test(this.obj.Rvalue) == true) {
				return true;
			} else {
				return false;
			}
}

/**
* 이름 입력 체크
* @param
* @return boolean
*/
FrmChk.prototype.nameChk = function() {

			var pattern = /^[가-힣]+$/;

			if (pattern.test(this.obj.Rvalue) == true) {
				return true;
			} else {
				return false;
			}
}

/**
* 패스워드 체크
* @param
* @return boolean
*/
FrmChk.prototype.passChk = function() {

			var pws = this.obj.Rvalue;

			//공백은 사용할 수 없습니다.
			if (pws.indexOf(' ') > -1) {
						this.addErrMsg = "공백은 사용할 수 없습니다.";
						return false;
			}

			// 3개이상 반복된 문자는 비밀번호로 사용하실수없습니다
			if(this.repeat_check(pws,3) != "") {
						this.addErrMsg = "3개이상 반복된 문자는 비밀번호로 사용하실 수 없습니다";
						return false;
			}

			// 3개이상 연속된 문자는 비밀번호로 사용하실수없습니다.
			if(this.sequence_check(pws,3) > 0) {
						this.addErrMsg = "3개이상 반복된 문자는 비밀번호로 사용하실 수 없습니다";
						return false;
			}

			// 비밀번호는 영문자와 숫자의 혼합만 사용가능합니다.
			if (!this.isAlphaAndNumber(pws))	{
						this.addErrMsg = "비밀번호는 영문과 숫자의 혼합 문자만 사용 가능합니다.";
						return false;
			}

			if (pws.length < 6) {
				this.addErrMsg = "6자 이하 문자열은 비밀번호로 사용하실 수 없습니다";
				return false;
			}

			if (pws.length >12)	{
				this.addErrMsg = "12자 이상 문자열은 비밀번호로 사용하실 수 없습니다";
				return false;
			}


			if(this.chkAttVal != undefined && this.chkAttVal != null && this.chkAttVal != "" && pws.indexOf(this.chkAttVal.substr(0, 4)) >= 0) {
				this.addErrMsg = "아이디와 유사한 비밀번호는 사용하실 수 없습니다.";
				return false;
			}

				return true;
}
			// ------------------------------------------------------------------------------------------------------------------------------

FrmChk.prototype.repeat_check = function(str, num) {
			var cnt = str.length;
			var repeat = "";
			var R=1;

			for(var i=0; i<cnt; i++) {
			tmp = str.substr(i, 1);
			key = tmp;
			if(key == repeat) { R++; }
			else { R=1; repeat = key; }
			if(R >= num) { return repeat; }
			}
			return "";
}


FrmChk.prototype.sequence_check = function(str, num) {
			var cnt = str.length;
			var repeat = 0;
			var R=1;

			for(var i=0; i<cnt; i++) {
			asc = str.charCodeAt(i);
			key = asc;
			if(key == repeat + 1) { R++; repeat = key; }
			else { R=1; repeat = key; }
			if(R >= num) { return repeat; }
			}
			return 0;
}

FrmChk.prototype.isAlphaAndNumber = function(val) {
			var isAlpha = false;
			var isNumber = false;
			var arr = val.split("");
			val = val.toLowerCase();

			for(var i=0; i < val.length; i++) {
				if ('a' <= val.charAt(i) &&val.charAt(i) <= 'z' ) {
					isAlpha = true;
				}

				if ('0' <= val.charAt(i) && val.charAt(i) <= '9' ) {
					isNumber = true;
				}
			}

			if (isAlpha && isNumber) {
				return true;
			} else {
				return false;
			}
}