/*  Miya Validator 0.1 (2007-11-16)
 *  (c) 2007 Goonoo Kim
 *
 *  Miya Validator is under the terms of a GPL(General Public License).
 */

/**
 * constructor
 * @return void
 */
var MiyaValidator = function(form) {
    this.form = MiyaValidator.getFormElement(form);
    if (!this.form) return false;

    this.conditions = [];
    this.groupConditions = [];
    this.errorCondition = null;
    this.errorGroupCondition = null;
    this.errorType = null;
};
/**
 * format check map (point function name)
 */
MiyaValidator.FORMAT_MAP = {
    email      : "MiyaFormat.email",
    hangul     : "MiyaFormat.hangul",
    engonly    : "MiyaFormat.engonly",
    number     : "MiyaFormat.number",
    residentno : "MiyaFormat.residentno",
    jumin      : "MiyaFormat.jumin",
    foreignerno: "MiyaFormat.foreignerno",
    bizno      : "MiyaFormat.bizno",
    phone      : "MiyaFormat.phone",
    homephone  : "MiyaFormat.homephone",
    handphone  : "MiyaFormat.handphone",
    isdate     : "MiyaFormat.isdate",
    zip        : "MiyaFormat.zip"
};
/**
 * message pattern to replace with getErrorMessage method
 *  {label} - name of form control
 *  {message} - invalid message
 */
MiyaValidator.ERROR_MESSAGE_PATTERN = "[{label}] {message}";
/**
 * message preset for MiyaValidator
 */
MiyaValidator.ERROR_MESSAGE = {
    /* for element */
    required   : "반드시 입력하셔야 하는 사항입니다.",
    requiredstring : "반드시 {required}(으)로 입력하셔야 하는 사항입니다.",
    match      : "입력된 내용이 일치하지 않습니다.",
    invalid    : "입력된 내용이 올바르지 않습니다.",
    minbyte    : "입력된 내용의 길이가 {minbyte}Byte 이상이어야 합니다.",
    maxbyte    : "입력된 내용의 길이가 {maxbyte}Byte를 초과할 수 없습니다.",
    mincheck   : "{mincheck}개의 항목 이상으로 선택하세요.",
    maxcheck   : "{maxcheck}개의 항목 이하로 선택하세요.",
    minselect  : "{minselect}개의 항목 이상으로 선택하세요.",
    maxselect  : "{maxselect}개의 항목 이하로 선택하세요.",
    imageonly  : "이미지 파일만 첨부 할 수 있습니다.",

    /* for group */
    requiremin : "{requiremin}개 이상의 항목이 입력되어야 합니다.",
    requiremax : "{requiremax}개 이하의 항목이 입력되어야 합니다.",

    /* for format */
    email      : "이메일 형식이 올바르지 않습니다.",
    hangul     : "반드시 한글로 입력하셔야 합니다.",
    engonly    : "영문으로만 입력하셔야 합니다.",
    number     : "숫자로만 입력하셔야 합니다.",
    residentno : "주민등록번호 형식이 올바르지 않습니다.",
    jumin      : "주민등록번호 형식이 올바르지 않습니다.",
    foreignerno: "외국인등록번호 형식이 올바르지 않습니다.",
    bizno      : "사업자등록번호 형식이 올바르지 않습니다.",
    phone      : "전화번호 형식이 올바르지 않습니다.",
    homephone  : "유선 전화번호 형식이 올바르지 않습니다.",
    handphone  : "핸드폰번호 형식이 올바르지 않습니다.",
    isdate     : "날짜 형식이 올바르지 않습니다.",
    zip        : "우편번호 형식이 올바르지 않습니다."
};

MiyaValidator.prototype.add=function(targetElement,targetOptions,targetLabel){var condition=new MiyaCondition(targetElement,targetOptions,targetLabel,this.form);if(condition)this.addCondition(condition);return condition};MiyaValidator.prototype.addCondition=function(condition){if(condition)this.conditions[this.conditions.length]=condition};MiyaValidator.prototype.addGroup=function(targetConditions,targetOptions,targetLabel){var groupCondition=new MiyaGroupCondition(targetConditions,targetOptions,targetLabel);if(groupCondition)this.addGroupCondition(groupCondition);return groupCondition};MiyaValidator.prototype.addGroupCondition=function(groupCondition){if(groupCondition)this.groupConditions[this.groupConditions.length]=groupCondition};MiyaValidator.prototype.validate=function(){var isFailed=false;for(var i=0,l=this.conditions.length;i<l;i++){isFailed=!this.validateCondition(this.conditions[i]);if(isFailed)return false};for(var i=0,l=this.groupConditions.length;i<l;i++){isFailed=!this.validateGroup(this.groupConditions[i]);if(isFailed)return false};return true};MiyaValidator.prototype.validateGroup=function(groupCondition){var conditions=groupCondition.conditions;var optionsObj=groupCondition.optionsObj;var requiremin=optionsObj.requiremin?parseInt(optionsObj.requiremin,10):0;if(requiremin>0){var countValid=0;var firstInvalidCondition=null;for(var i=0,l=conditions.length;i<l;i++){if(this.validateCondition(conditions[i])){countValid++;if(countValid>=requiremin)break}else{if(!firstInvalidCondition){firstInvalidCondition=conditions[i]};if(this.errorType!="required"){return false}}};if(countValid<requiremin)return this.raiseGroupError(groupCondition,firstInvalidCondition,"requiremin")};var requiremax=optionsObj.requiremax?parseInt(optionsObj.requiremax,10):0;if(requiremax>0){var countValid=0;var firstInvalidCondition=null;for(var i=0,l=conditions.length;i<l;i++){if(this.validateCondition(conditions[i])){countValid++;if(countValid>=requiremax)break}else{if(!firstInvalidCondition){firstInvalidCondition=conditions[i]};if(this.errorType!="required"){return false}}};if(countValid<requiremax)return this.raiseGroupError(groupCondition,firstInvalidCondition,"requiremax")};return true};MiyaValidator.prototype.validateCondition=function(condition){var element=condition.element;var optionsObj=condition.optionsObj;var value=MiyaValidator.getValue(element);if(!MiyaValidator.isActiveFormControl(element))return true;var type=MiyaValidator.getElementType(element);if(!type)return true;var useifvalid=optionsObj.useifvalid||null;var useifinvalid=optionsObj.useifinvalid||null;if(useifvalid){if(!this.validateCondition(useifvalid))return true};if(useifinvalid){if(this.validateCondition(useifvalid))return true};var isEmpty=MiyaValidator.isEmptyElement(element,type);var required=optionsObj.required||null;if(required&&isEmpty){return this.raiseError(condition,"required")}else if(typeof required=="string"&&required!=value){return this.raiseError(condition,"requiredstring")};var minbyte=parseInt(optionsObj.minbyte,10)||null;var maxbyte=parseInt(optionsObj.maxbyte,10)||null;if((minbyte>0||maxbyte>0)&&!isEmpty){if(type==MiyaValidator.TEXT||type==MiyaValidator.HIDDEN){var valueByte=value.length;for(i=0;i<value.length;i++){if(value.charCodeAt(i)>128)valueByte++};if(minbyte>0&&valueByte<minbyte)return this.raiseError(condition,"minbyte");if(maxbyte>0&&valueByte>maxbyte)return this.raiseError(condition,"maxbyte")}};var match=optionsObj.match||null;if(match){if(type!=MiyaValidator.FILE){var matchElement=MiyaValidator.getElement(match,this.form);if(matchElement&&value!=MiyaValidator.getValue(matchElement))return this.raiseError(condition,"match")}};var option=optionsObj.option||null;if(option&&!isEmpty){if(type!=MiyaValidator.FILE&&MiyaValidator.FORMAT_MAP[option]){var formatFunction=eval(MiyaValidator.FORMAT_MAP[option]);var formatResult;var span=parseInt(optionsObj.span,10)||null;var glue=optionsObj.glue||"";var _options=option.split(/\s/);for(var i=0;i<_options.length;i++){var format=MiyaValidator.FORMAT_MAP[_options[i]];if(span&&typeof value!="object"){var spanedValue=value;var _elementForSpan=element;for(var j=1;j<span;j++){_elementForSpan=MiyaValidator.getNextElement(_elementForSpan);if(_elementForSpan){if(typeof glue=="object"&&glue.length+1==span){spanedValue+=glue[j-1]+MiyaValidator.getValue(_elementForSpan)}else{spanedValue+=glue+MiyaValidator.getValue(_elementForSpan)}}};formatResult=formatFunction(element,spanedValue)}else{formatResult=formatFunction(element,value)};if(typeof formatResult=="string")return this.raiseError(condition,formatResult)}}};var pattern=optionsObj.pattern||null;if(pattern&&!isEmpty){if(type!=MiyaValidator.FILE){patternRegExp=new RegExp(pattern);if(typeof value=="object"){for(var i=0;i<value.length;i++){if(!patternRegExp.test(value[i])){return this.raiseError(condition,"invalid")}}}else if(!patternRegExp.test(value)){return this.raiseError(condition,"invalid")}}};var mincheck=parseInt(optionsObj.mincheck,10)||null;var maxcheck=parseInt(optionsObj.maxcheck,10)||null;if(mincheck>0||maxcheck>0){if(type==MiyaValidator.CHECK){if(mincheck>0&&value.length<mincheck)return this.raiseError(condition,"mincheck");if(maxcheck>0&&value.length>maxcheck)return this.raiseError(condition,"maxcheck")}};var minselect=parseInt(optionsObj.minselect,10)||null;var maxselect=parseInt(optionsObj.maxselect,10)||null;if(minselect>0||maxselect>0){if(type==MiyaValidator.MULTI_SELECT){if(minselect>0&&value.length<minselect)return this.raiseError(condition,"minselect");if(maxselect>0&&value.length>maxselect)return this.raiseError(condition,"maxselect")}};var imageonly=optionsObj.imageonly||null;if(imageonly){if(type==MiyaValidator.FILE){var dotIndex=value.lastIndexOf(".");var ext=value.substr(dotIndex+1).toLowerCase();if(ext!="jpg"&&ext!="jpeg"&&ext!="gif"&&ext!="png")return this.raiseError(condition,"imageonly")}};return true};MiyaValidator.prototype.raiseError=function(condition,errorType){this.errorCondition=condition;this.errorType=errorType;return false};MiyaValidator.prototype.raiseGroupError=function(groupCondition,firstInvalidCondition,errorType){this.errorGroupCondition=groupCondition;this.errorCondition=firstInvalidCondition;this.errorType=errorType;return false};MiyaValidator.prototype.getErrorElement=function(){return this.errorCondition?this.errorCondition.element:null};MiyaValidator.prototype.getErrorMessage=function(errorMessagePattern){if(!this.errorCondition||!this.errorType)return null;if(this.errorGroupCondition){var optionsObj=this.errorGroupCondition.optionsObj;var label=this.errorGroupCondition.label}else{var optionsObj=this.errorCondition.optionsObj;var label=this.errorCondition.label};var typeMessage=MiyaValidator.ERROR_MESSAGE[this.errorType]||this.errorType;var message=optionsObj.message||typeMessage;var dynamicPattern=/\{([a-z0-9_]+)\}/i;if(dynamicPattern.test(message)==true){while(dynamicPattern.exec(message)){if(RegExp.$1&&optionsObj[RegExp.$1]){message=message.replace(dynamicPattern,optionsObj[RegExp.$1])}else{break}}};var messagePattern=errorMessagePattern?errorMessagePattern:MiyaValidator.ERROR_MESSAGE_PATTERN;var errorMessage=messagePattern.replace(/{label}/,label);var errorMessage=errorMessage.replace(/{message}/,message);return errorMessage};MiyaValidator.isActiveFormControl=function(element){return element.tagName&&element.tagName.match(/^input|select|textarea$/i)&&!element.disabled};MiyaValidator.isEmptyElement=function(element){var value=MiyaValidator.getValue(element);return!value};MiyaValidator.getFormElement=function(form){if(form.tagName)return form;else if(document.getElementById&&document.getElementById(form))return document.getElementById(form);else if(document.forms&&document.forms[form])return document.forms[form];else return false};MiyaValidator.getElement=function(element,elementForm){if(element.tagName){return element}else if(elementForm&&elementForm.elements&&elementForm.elements[element]){if(!elementForm.elements[element].tagName&&elementForm.elements[element].length)return elementForm.elements[element][0];else return elementForm.elements[element]}else if(document.getElementById&&document.getElementById(element)){return document.getElementById(element)}else{return false}};MiyaValidator.getElementType=function(element){if(!element.tagName)return false;var tagName=element.tagName.toLowerCase();var type=element.type;var multiple=element.multiple;if(tagName=="textarea"||(tagName=="input"&&(type=="text"||type=="password")))return MiyaValidator.TEXT;else if(tagName=="select"&&multiple)return MiyaValidator.MULTI_SELECT;else if(tagName=="select")return MiyaValidator.SELECT;else if(tagName=="input"&&type=="checkbox")return MiyaValidator.CHECK;else if(tagName=="input"&&type=="radio")return MiyaValidator.RADIO;else if(tagName=="input"&&type=="file")return MiyaValidator.FILE;else if(tagName=="input"&&type=="hidden")return MiyaValidator.HIDDEN;else return false};MiyaValidator.getValue=function(element){var type=MiyaValidator.getElementType(element);switch(type){case MiyaValidator.TEXT:case MiyaValidator.HIDDEN:case MiyaValidator.FILE:return element.value;break;case MiyaValidator.SELECT:for(var i=0,l=element.options.length;i<l;i++){if(element.options[i].selected){return element.options[i].value}};break;case MiyaValidator.MULTI_SELECT:var values=[];for(var i=0,l=element.options.length;i<l;i++){if(element.options[i].selected){values[values.length]=element.options[i].value}};return values.length>0?values:null;break;case MiyaValidator.CHECK:if(element.form&&element.name){var checkElements=element.form.elements[element.name];var values=[];if(checkElements.length){for(var i=0;i<checkElements.length;i++){if(checkElements[i].checked==true)values[values.length]=checkElements[i].value}}else{if(checkElements.checked==true)values[values.length]=checkElements.value};return values.length>0?values:null};break;case MiyaValidator.RADIO:if(element.form&&element.name){var checkElements=element.form.elements[element.name];if(checkElements.length){for(var i=0;i<checkElements.length;i++){if(checkElements[i].checked==true)return checkElements[i].value}}else{if(checkElements.checked==true)return checkElements.value}};break};return null};MiyaValidator.getNextElement=function(element){if(element.form){var form=element.form;for(var i=0;i<form.elements.length;i++){if(form.elements[i]==element){var count=i;while(++count<form.elements.length&&MiyaValidator.isActiveFormControl(form.elements[count])){return form.elements[count]}}}}else if(element.nextSibling){var _nextElement=element;while(_nextElement=element.nextSibling){if(MiyaValidator.isActiveFormControl(_nextElement))return _nextElement}};return null};var MiyaCondition=function(targetElement,targetOptions,targetLabel,targetForm){var element=MiyaValidator.getElement(targetElement,targetForm);if(!MiyaValidator.isActiveFormControl(element))return false;this.element=element;this.optionsObj=targetOptions||{};this.label=targetLabel||MiyaCondition.getHTMLLabel(element)};MiyaCondition.prototype.addOption=function(key,val){this.optionsObj[key]=val};MiyaCondition.prototype.removeOption=function(key){this.optionsObj[key]=null};MiyaCondition.prototype.getOption=function(key){return this.optionsObj[key]?this.optionsObj[key]:null};MiyaCondition.getHTMLLabel=function(element){var currentLabel="";if(document.getElementsByTagName){var currentLabelElement;labelLoop:for(var i=0,l=document.getElementsByTagName("label").length;i<l;i++){var labelElement=document.getElementsByTagName("label")[i];var labelChilds=labelElement.childNodes;if(labelElement.htmlFor&&labelElement.htmlFor==element.id){currentLabelElement=labelElement;break labelLoop};for(var _i=0,_l=labelChilds.length;_i<_l;_i++){if(labelChilds[_i]==element){currentLabelElement=labelElement;break labelLoop}}};if(currentLabelElement){var labelChilds=currentLabelElement.childNodes;for(var i=0,l=labelChilds.length;i<l;i++){if(!labelChilds[i].tagName)currentLabel+=labelChilds[i].nodeValue.replace(/^\s+/,"").replace(/\s+$/,"")}}};if(!currentLabel){if(element.title)currentLabel=element.title;else if(element.id)currentLabel=element.id;else if(element.name)currentLabel=element.name;else currentLabel="noname"};return currentLabel};var MiyaGroupCondition=function(targetConditions,targetOptions,targetLabel){this.conditions=targetConditions||[];this.optionsObj=targetOptions||{};if(targetLabel){this.label=targetLabel}else{this.label="";for(var i=0,l=this.conditions.length;i<l;i++){this.label+=this.label?", ":"";this.label+=this.conditions[i].label}}};MiyaGroupCondition.prototype.addCondition=function(condition){var index=this.conditions.length;this.conditions[index]=condition;return index};MiyaGroupCondition.prototype.getCondition=function(index){return this.conditions[index]?this.conditions[index]:null};MiyaGroupCondition.prototype.removeCondition=function(index){var len=this.conditions.length;if(this.conditions[index]){var flag=false;for(var i=0;i<len;i++){if(i==index)flag=true;if(flag==true&&i+1<len){this.conditions[i]=this.conditions[i+1]}};this.conditions.length=len-1}};var MiyaFormat={};MiyaFormat.email=function(el,value){var value=value?value:el.value;var pattern=/^[_a-zA-Z0-9-\.]+@[\.a-zA-Z0-9-]+\.[a-zA-Z]+$/;return pattern.test(value)?true:"email"};MiyaFormat.hangul=function(el,value){var value=value?value:el.value;var pattern=/^[가-힣]+$/;return pattern.test(value)?true:"hangul"};MiyaFormat.engonly=function(el,value){var value=value?value:el.value;var pattern=/^[a-zA-Z]+$/;return pattern.test(value)?true:"engonly"};MiyaFormat.number=function(el,value){var value=value?value:el.value;var pattern=/^[0-9]+$/;return pattern.test(value)?true:"number"};MiyaFormat.residentno=function(el,value){var pattern=/^(\d{6})-?(\d{5}(\d{1})\d{1})$/;var num=value?value:el.value;if(!pattern.test(num))return"invalid";num=RegExp.$1+RegExp.$2;if(RegExp.$3==7||RegExp.$3==8||RegExp.$4==9)if((num[7]*10+num[8])%2)return"residentno";var sum=0;var last=num.charCodeAt(12)-0x30;var bases="234567892345";for(var i=0;i<12;i++){if(isNaN(num.substring(i,i+1)))return"residentno";sum+=(num.charCodeAt(i)-0x30)*(bases.charCodeAt(i)-0x30)};var mod=sum%11;if(RegExp.$3==7||RegExp.$3==8||RegExp.$4==9)return(11-mod+2)%10==last?true:"residentno";else return(11-mod)%10==last?true:"residentno"};MiyaFormat.jumin=function(el,value){var pattern=/^([0-9]{6})-?([0-9]{7})$/;var num=value?value:el.value;if(!pattern.test(num))return"jumin";num=RegExp.$1+RegExp.$2;var sum=0;var last=num.charCodeAt(12)-0x30;var bases="234567892345";for(var i=0;i<12;i++){if(isNaN(num.substring(i,i+1)))return"jumin";sum+=(num.charCodeAt(i)-0x30)*(bases.charCodeAt(i)-0x30)};var mod=sum%11;return(11-mod)%10==last?true:"jumin"};MiyaFormat.foreignerno=function(el,value){var pattern=/^(\d{6})-?(\d{5}[7-9]\d{1})$/;var num=value?value:el.value;if(!pattern.test(num))return"foreignerno";num=RegExp.$1+RegExp.$2;if((num[7]*10+num[8])%2)return"foreignerno";var sum=0;var last=num.charCodeAt(12)-0x30;var bases="234567892345";for(var i=0;i<12;i++){if(isNaN(num.substring(i,i+1)))return"foreignerno";sum+=(num.charCodeAt(i)-0x30)*(bases.charCodeAt(i)-0x30)};var mod=sum%11;return(11-mod+2)%10==last?true:"foreignerno"};MiyaFormat.bizno=function(el,value){var pattern=/([0-9]{3})-?([0-9]{2})-?([0-9]{5})/;var num=value?value:el.value;if(!pattern.test(num))return"bizno";num=RegExp.$1+RegExp.$2+RegExp.$3;var cVal=0;for(var i=0;i<8;i++){var cKeyNum=parseInt(((_tmp=i%3)==0)?1:(_tmp==1)?3:7);cVal+=(parseFloat(num.substring(i,i+1))*cKeyNum)%10};var li_temp=parseFloat(num.substring(i,i+1))*5+"0";cVal+=parseFloat(li_temp.substring(0,1))+parseFloat(li_temp.substring(1,2));return parseInt(num.substring(9,10))==10-(cVal%10)%10?true:"bizno"};MiyaFormat.phone=function(el,value){var pattern=/^(0[2-8][0-5]?|01[01346-9])-?([1-9]{1}[0-9]{2,3})-?([0-9]{4})$/;var pattern15xx=/^(1544|1566|1577|1588|1644|1688)-?([0-9]{4})$/;var num=value?value:el.value;return pattern.test(num)||pattern15xx.test(num)?true:"phone"};MiyaFormat.homephone=function(el,value){var pattern=/^(0[2-8][0-5]?)-?([1-9]{1}[0-9]{2,3})-?([0-9]{4})$/;var pattern15xx=/^(1544|1566|1577|1588|1644|1688)-?([0-9]{4})$/;var num=value?value:el.value;return pattern.test(num)||pattern15xx.test(num)?true:"homephone"};MiyaFormat.handphone=function(el,value){var pattern=/^(01[01346-9])-?([1-9]{1}[0-9]{2,3})-?([0-9]{4})$/;var num=value?value:el.value;return pattern.test(num)?true:"handphone"};MiyaFormat.isdate=function(el,value){var value=value?value:el.value;var pattern=/^[12][0-9]{3}\-[01]?[0-9]\-[0-3]?[0-9]$/;return pattern.test(value)?true:"isdate"};MiyaFormat.zip=function(el,value){var value=value?value:el.value;var pattern=/^[0-9]{3}\-[0-9]{3}$/;return pattern.test(value)?true:"zip"};
