/*
入力フォーム自動チェッカスクリプト（簡易版）
2011-01-17 Y.hagi
バージョン：0.01  2011-01-17
バージョン：0.02  2011-10-13 バグ修正

バージョン：0.03  2011/10/26 エラーメッセージ要素の追加位置変更機能の追加

バージョン：0.04  2011/10/26 メールアドレス有効性チェックの追加　バグ修正
バージョン：0.05  2011/10/26 電話番号(numeric)有効性チェックの追加　

注意点：
　多くのjavascriptを読み込みしている場合、当該スクリプトで
　入力チェックロジックを含む前に、submitを押されるケースがあるので、
　なるたけ早いタイミングで読み込みさせること。

usage　：文字コードを読み込み元htmlと合わせる
　　　　:　チェック対象inputタグその他へ、class名'required'を記述
　　　　:※selectを使用する場合は、未選択として「選択してください」を
　　　　　optionに追加
　　　　：フォームの送信にinput submitボタンを使用

対象：inputタグのタイプ
　　　・text
　　　・password
　　　・file
　　　・checkbox
　　　・radio
　　　selectタグ
　　　textareaタグ

　エラーとなるケース
・input
　　text    :空文字、未記入
　　password:空文字、未記入
　　file    :空文字、未記入
　　checkbox:未チェック
　　radio   :未チェック
・select    :「選択してください」選択時
・textarea  :空文字、未記入

*/

var msIE6 = 'MSIE 6.0';
var msIE7 = 'MSIE 7.0';
var msIE8 = 'MSIE 8.0';
var msFirefox = 'Firefox';
var msOpera = 'Opera';
var msSafari = 'Safari';
var msChrome = 'Chrome'

/*
数値チェック対象クラス名
*/
var chkNumeric = "numeric";

/*
メールアドレスチェック対象クラス名
*/
var chkMailaddr = "email";


/*
 エラーメッセージ表示エレメントを、前に入れるか後ろに入れるか選択
 true: 前
 false: 後
*/

var insertPosition = false;

/*
入力必須とする項目へ記入するクラス名
*/
var inputRequre = 'required';

/*
エラーとなるタグのクラスに追加されるクラス名
*/
var errClassname = 'error';

/*
エラーとなるタグの前に挿入されるエラーメッセージのクラス名
*/
var errMesgClassname = 'errormsg';

/*
エラーとなるタグの前に挿入されるエラーメッセージのタグ名
*/
var errMesgWrapTag = 'div';

/*
テキスト項目についての、エラーメッセージ表記
*/
var inputTextErrStr = '記入してください。';

/*
パスワード項目についての、エラーメッセージ表記
*/
var inputPwdErrStr = '記入してください。';

//ファイル項目についての、エラーメッセージ表記
var inputFileErrStr = '記入してください。';

//コンボボックス項目についての、エラーメッセージ表記
var inputCBoxErrStr = 'チェックしてください。';

//ラジオボタン項目についての、エラーメッセージ表記
var inputRadioErrStr = 'どれか選択してください。';

//選択項目についての、エラーメッセージ表記
var inputSelectErrStr = 'どれか選択してください。';

//テキストエリアについての、エラーメッセージ表記
var inputTAreaErrStr = '記入してください。';

//入力項目について、エラーと判断するパラメータ
var inputTextErrParam = '';
var inputPwdErrParam = '';
var inputFileErrParam = '';

//チェックボックスとラジオをはあんまり意味ないかな。。。
var inputCBoxErrParam = false;
var inputRadioErrParam= false;

var inputSelectErrParam = '選択してください';
var inputTAreaErrParam = '';

function insertAfter(newNode, node){
	node.parentNode.insertBefore(newNode, node.nextSibling);
}

// 当該elementの直親になるform elementを取得
function parentFormElem(wantParentElem){

  var parents = wantParentElem.parentNode;

  if(parents){
    if(parents.nodeName == 'FORM'){
//      return parents;
    }else if(parents.nodeName == 'BODY'){
//      return null;
    }else{
      parents = parentFormElem(parents);
    }
  }
  return parents;
}

function chkExistClassName( chkExistClassNameElem ,className){
  var chkExistClassNameFlg = false;
  var classNameArray = new Array();

  var broType = IE67orNot();
  if(broType){
    var attrStr = chkExistClassNameElem.getAttribute('className');
  }else{
    var attrStr = chkExistClassNameElem.getAttribute('class');
  }

	if(attrStr){
		classNameArray = attrStr.split(' ');

		for(var i = 0;i < classNameArray.length; i++){
			if(classNameArray[i] == className){
				chkExistClassNameFlg = true;
				break;
			}
		}
	}
	return chkExistClassNameFlg;
}

function isNumeric(num){
    if (num.match(/[^0-9]/g)) {
        return false;
    }
    return true;
}

//エレメントのタイプ別に、エラーであるかどうか判定を行う。
function errParameter(errParameterElem, errParam){

	var paramFlg = false;
	
	if (errParameterElem.getAttribute('type') == 'text'){
		if(errParameterElem.value == errParam){
			paramFlg = true;
    	}else{

			var elemValue  = errParameterElem.value;
			if( chkExistClassName( errParameterElem , chkMailaddr ) ){

				if(!elemValue.match(/^[_a-zA-Z0-9-]+([\.\+_a-zA-Z0-9-]+)*@[a-zA-Z0-9]([_a-zA-Z0-9-])*(\.[_a-zA-Z0-9-]+)*(\.[_a-zA-Z0-9-]{2,})+$/i)){
					paramFlg = true;
				}

			}else if( chkExistClassName( errParameterElem , chkNumeric ) ){
				var char1 = new Array("１","２","３","４","５","６","７","８","９","０");
				var char2 = new Array(1,2,3,4,5,6,7,8,9,0);
				while(elemValue.match(/[０-９]/)){ 
					for(count = 0; count < char1.length; count++){
						elemValue = elemValue.replace(char1[count], char2[count]);
					}
				}
				errParameterElem.value = elemValue;
				if(!isNumeric(errParameterElem.value)){
					paramFlg = true;
				}
			}

		}
	}else if(errParameterElem.getAttribute('type') =='password'){
		if(errParameterElem.value == errParam){
			paramFlg = true;
		}
	}else if(errParameterElem.getAttribute('type') =='file'){
    	if(errParameterElem.value == errParam){
			paramFlg = true;
		}
	}else if(errParameterElem.getAttribute('type') =='checkbox'){
		if(errParameterElem.checked == errParam){
			paramFlg = true;
		}
	}else if(errParameterElem.getAttribute('type') =='radio'){
		var elemName = errParameterElem.name;
		var parentForm = parentFormElem(errParameterElem);

		var chekedFlg = false;
    
		if(parentForm){
			var formRadioList = parentForm.getElementsByTagName('input');
			for(var i = 0; i < formRadioList.length;i++){
				if(formRadioList[i].getAttribute('type') == 'radio' && formRadioList[i].name == elemName){
					if(formRadioList[i].checked){
						chekedFlg = true;
						break;
					}
				}
			}
		}
		if(!chekedFlg){
			paramFlg = true;
		}
	}else if(errParameterElem.nodeName =='SELECT'){
		var selopt = errParameterElem.options;

		if(selopt){
			var broType = IE67orNot();
			if(broType){
				var seltext = selopt.item(errParameterElem.selectedIndex).text;
			}else{
				var seltext = selopt.item(errParameterElem.selectedIndex).value;
			}

			if( seltext == errParam ){
				paramFlg = true;
			}

		}else{
			paramFlg = true;
		}

	}else if(errParameterElem.nodeName =='TEXTAREA'){

		if(errParameterElem.value == errParam){
			paramFlg = true;
		}

	}else{
		paramFlg = true;
	}
	return paramFlg;
}


//当該elementへクラス名の追加
function insertClassName( insertClassNameElem, className){

  var classNameArray = new Array();

  var broType = IE67orNot();
  if(broType){
    var attrStr = insertClassNameElem.getAttribute('className');
  }else{
    var attrStr = insertClassNameElem.getAttribute('class');
  }
/*
  try{
    var attrStr = insertClassNameElem.getAttribute('class');
  }catch(e){
    var attrStr = insertClassNameElem.getAttribute('className');
  }
*/

  if(attrStr){
    classNameArray = attrStr.split(' ');
    classNameArray.push(className);

    var newClassNames = '';
 
    for(var i = 0;i < classNameArray.length ;i++){
      newClassNames += classNameArray[i] + ' ';
    }
    if(newClassNames){
      newClassNames = newClassNames.substring(0,newClassNames.length -1);
    }
  }else{
    var newClassNames = className;
  }

  var broType = IE67orNot();
  if(broType){
    insertClassNameElem.setAttribute('className',newClassNames);
  }else{
    insertClassNameElem.setAttribute('class',newClassNames);
  }
/*
  try{
    insertClassNameElem.setAttribute('class',newClassNames);
  }catch(e){
    insertClassNameElem.setAttribute('className',newClassNames);
  }
*/

}

//当該elementからへクラス名の除外
function removeClassName( removeClassNameElem, className){

  var classNameArray = new Array();

  var broType = IE67orNot();
  if(broType){
    var attrStr = removeClassNameElem.getAttribute('className');
  }else{
    var attrStr = removeClassNameElem.getAttribute('class');
  }

/*
  try{
    var attrStr = removeClassNameElem.getAttribute('class');
  }catch(e){
    var attrStr = removeClassNameElem.getAttribute('className');
  }
*/

  if(attrStr){

    classNameArray = attrStr.split(' ');

    for(var i = 0;i < classNameArray.length; i++){
      if(classNameArray[i] == className){
        classNameArray.splice( i, 1);
        i--;
//        break;
      }
    }

    var newClassNames = '';
    for(var j = 0;j < classNameArray.length ;j++){
      newClassNames += classNameArray[j] + ' ';
    }
    if(newClassNames){
      newClassNames = newClassNames.substring(0,newClassNames.length -1);
    }

    var broType = IE67orNot();
    if(broType){
      removeClassNameElem.setAttribute('className',newClassNames);
    }else{
      removeClassNameElem.setAttribute('class',newClassNames);
    }
/*
    try{
      removeClassNameElem.setAttribute('class',newClassNames);
    }catch(e){
      removeClassNameElem.setAttribute('className',newClassNames);
    }
*/
  }
}

function thisClassNameExist(elem, className){

  var broType = IE67orNot();
  if(broType){
    var classnameLists = elem.getAttribute('className');
  }else{
    var classnameLists = elem.getAttribute('class');
  }
/*
  try{
    var classnameLists = elem.getAttribute('class');
  }catch(e){
    var classnameLists = elem.getAttribute('className');
  }
*/
  return classnameLists.indexOf(className,0);

}

//エラーメッセージ表示エレメントを削除
function removeErrMesgElem(errElem){
  var parentElem = errElem.parentNode;
	if(insertPosition){
		var msgElem = errElem.previousSibling;
	}else{
		var msgElem = errElem.nextSibling;
	}

  if(msgElem){
    if(msgElem.nodeName == errMesgWrapTag.toUpperCase()){
      if(thisClassNameExist(msgElem,errMesgClassname) != -1){
        parentElem.removeChild(msgElem);
      }
    }
  }
}

//エラーメッセージ表示エレメントの挿入
function insertErrMesgElem(errElem, errMesgStr){

  var parentElem = errElem.parentNode;

  var errMsgElem = document.createElement(errMesgWrapTag); 

  var broType = IE67orNot();
  if(broType){
    errMsgElem.setAttribute('className',errMesgClassname);
  }else{
    errMsgElem.setAttribute('class',errMesgClassname);
  }

/*
  try{
    errMsgElem.setAttribute('class',errMesgClassname);
  }catch(e){
    errMsgElem.setAttribute('className',errMesgClassname);
  }
*/

//  insertClassName(errMsgElem, errMesgClassname);

  errMsgElem.innerHTML = errMesgStr;

	if(insertPosition){
		parentElem.insertBefore(errMsgElem,errElem);
	}else{
	 	insertAfter (errMsgElem , errElem );
	}

/*
  insertAfter(errElem ,errMsgElem, errElem );
*/
}

//エラーチェック処理の初期を行いつつ、問題があればエラー処理を行う。
function inputCheckElem(inputCheckElemTag, mesgstr, errParam){

  removeClassName(inputCheckElemTag, errClassname);
  removeErrMesgElem(inputCheckElemTag);

  if(errParameter(inputCheckElemTag, errParam)){
    insertClassName(inputCheckElemTag,errClassname);
    insertErrMesgElem(inputCheckElemTag, mesgstr);
	return false;
  }else{
	return true;
  }
}

//入力タイプが「テキスト」専用入力チェック
function inputTextCheck(inputTextCheckelem){
  return inputCheckElem(inputTextCheckelem, inputTextErrStr, inputTextErrParam);
}

//入力タイプが「パスワード」専用入力チェック
function inputPwdCheck(inputPwdCheckelem){
  return inputCheckElem(inputPwdCheckelem, inputPwdErrStr, inputPwdErrParam);
}

//入力タイプが「ファイル」専用入力チェック
function inputFileCheck(inputFileCheckelem){
  return inputCheckElem(inputFileCheckelem, inputFileErrStr, inputFileErrParam);
}

//入力タイプが「チェックボックス」専用入力チェック
function inputCBoxCheck(inputCBoxCheckelem){
  return inputCheckElem(inputCBoxCheckelem, inputCBoxErrStr, inputCBoxErrParam);
}

//入力タイプが「ラジオボタン」専用入力チェック
function inputRadioCheck(inputRadioCheckelem){
  return inputCheckElem(inputRadioCheckelem, inputRadioErrStr, inputRadioErrParam);
}

//入力タイプが「選択」専用入力チェック
function inputSelectCheck(inputSelectCheckelem){
  return inputCheckElem(inputSelectCheckelem, inputSelectErrStr, inputSelectErrParam);
}

//入力タイプが「テキストエリア」専用入力チェック
function inputTAreaCheck(inputTAreaCheckelem){
  return inputCheckElem(inputTAreaCheckelem, inputTAreaErrStr, inputTAreaErrParam);
}

/*
function setCssStyle(setCssStyleElem,str){

  var cssStr = getCssStyles(setCssStyleElem);

  try{
    setCssStyleElem.getAttribute('style') = cssStr + str;
  }catch(e){
    setCssStyleElem.style.cssText = cssStr + str;
  }
}

function getCssStyles(getStylesElem){

  try{
    return getStylesElem.getAttribute('style');
  }catch(e){
    return getStylesElem.style.cssText;
  }
}
*/

//同一フォーム内のinput項目類についての判定ロジック分岐
var elemValidCheck = function(checkElem){

  var validFlg = true;

  if(checkElem.nodeName == 'INPUT'){
    if(checkElem.getAttribute('type') == 'text'){
      validFlg = inputTextCheck(checkElem);
    }else if(checkElem.getAttribute('type') =='password'){
      validFlg = inputPwdCheck(checkElem);
    }else if(checkElem.getAttribute('type') =='file'){
      validFlg = inputFileCheck(checkElem);
    }else if(checkElem.getAttribute('type') =='checkbox'){
      validFlg = inputCBoxCheck(checkElem);
    }else if(checkElem.getAttribute('type') =='radio'){
      validFlg = inputRadioCheck(checkElem);
    }else{
      validFlg = false;
    }

  }else if(checkElem.nodeName == 'SELECT'){
    validFlg = inputSelectCheck(checkElem);
  }else if(checkElem.nodeName == 'TEXTAREA'){
    validFlg = inputTAreaCheck(checkElem);
  }else{
    validFlg = false;
  }
  return validFlg;
}

//当該フォーム内のsubmitボタンへ、クリックイベントの追加
function setSubmitbtn(elem, Addr){

  var inps = elem.getElementsByTagName('input');
  if(inps){
    for(var i = 0;i < inps.length ; i++){
      if(inps[i].getAttribute('type') == 'submit'){
        inps[i].onclick = function(){

          var chekerlabelAdds = getInputList(this);
          var ErrCheckFlg = true;
          for(var j = 0;j < chekerlabelAdds.length; j++){
			if(!elemValidCheck(chekerlabelAdds[j])){
				ErrCheckFlg = false;
			}
          }

          if(ErrCheckFlg){
             parentFormElem().submit();
          }
          return false;
        };
      }
    }
  }
}



 // チェック対象elementリストを取得
function yetRadioInsert(eleArrays, radioElem){

  var radioFlg = false;
  for(var i = 0;i < eleArrays.length;i++){
    if(eleArrays[i].name == radioElem.name){
      radioFlg = true;
      break;
    }
  }
  return radioFlg;
}

function firstRadio(elem){
  var parentForm = parentFormElem(elem);
  var inptags  = parentForm.getElementsByTagName('input');
  
  var retEelem;

  for(var i= 0;i < inptags.length  ;i++){
    
    if(inptags[i].getAttribute('type') == 'radio'){
      if(inptags[i].name == elem.name){
        retEelem = inptags[i];
        break;
      }
    }
  }
  return retEelem;
}

// チェック対象elementリストを取得
function getInputList(submitElem){
   var eleInputArray = new Array();
   var parentForm  = parentFormElem(submitElem);
   var myFormInputs = getElementsByClassName(parentForm, inputRequre);

   for(var i = 0;i < myFormInputs.length; i++){
     if(chkInputTypes(myFormInputs[i])){

       if(myFormInputs[i].getAttribute('type') == 'radio'){
         if( !yetRadioInsert(eleInputArray , myFormInputs[i])){

//同form内の同名radioの先頭を、pushする。
           var radiotag= firstRadio(myFormInputs[i]); 
           if(radiotag){
             eleInputArray.push(radiotag);
           }else{
             eleInputArray.push(myFormInputs[i]);
           }
         }

       }else{
         eleInputArray.push(myFormInputs[i]);
       }
     }
   }
   return eleInputArray;
}



// 当該elementが、チェック対象であるかどうか確認
function chkInputTypes(chkInputTypeselem){

  var checkInputTypeFlg;
  if(chkInputTypeselem.nodeName == 'INPUT'){
    if(chkInputTypeselem.getAttribute('type') == 'text'){
      checkInputTypeFlg = true;
    }else if(chkInputTypeselem.getAttribute('type') == 'password'){
      checkInputTypeFlg = true;
    }else if(chkInputTypeselem.getAttribute('type') == 'file'){
      checkInputTypeFlg = true;
    }else if(chkInputTypeselem.getAttribute('type') == 'checkbox'){
      checkInputTypeFlg = true;
    }else if(chkInputTypeselem.getAttribute('type') == 'radio'){
      checkInputTypeFlg = true;
    }

  }else if(chkInputTypeselem.nodeName == 'SELECT'){
    checkInputTypeFlg = true;
  }else if(chkInputTypeselem.nodeName == 'TEXTAREA'){
    checkInputTypeFlg = true;
  }

  return checkInputTypeFlg;
}

// ページ内から「required」設定済みinputのformを取得。

function targetForms(){
  var targetElem = new Array();
  var formElems = document.getElementsByTagName('form');
  var formElem;

  if(formElems){
    for(var i= 0 ;i < formElems.length;i++){
      var reqInputs = getElementsByClassName(formElems[i],'required');
      for(var j = 0;j < reqInputs.length; j++){
        if(chkInputTypes(reqInputs[j])){
  

          formElem = formElems[i];
          targetElem.push(formElem);
          break;
        }
      }

    }
  }
  return targetElem;
}


// メイン関数。
// ページ内から「required」設定済みinputのformを取得し、
// 当該formのsubmitへチェッカ処理を追加する。
var inputCheckFunc = function(){
  var formArray = targetForms();
  for(var i = 0;i < formArray.length;i++){
    var actAddr =  formArray[i].getAttribute('action');
    setSubmitbtn(formArray[i], actAddr);
  }
};


// 指定関数を、ページonload時に実行する(登録済み既存関数を残したまま)
function addLoadEvent(func)
{	
	var oldonload = window.onload;
	if (typeof window.onload != 'function'){
    	window.onload = func;
	} else {
		window.onload = function(){
		oldonload();
		func();
		}
	}

}

// 指定elementの指定イベントに対して関数の登録
function addListener(elem, eventType, func, cap)
{
    if(elem.addEventListener)
    {
        elem.addEventListener(eventType, func, cap);
    }
    else if(elem.attachEvent)
    {
        elem.attachEvent('on' + eventType, func);
    }
}

// 指定クラス名のelementnodeを返す。
function getElementsByClassName(elem,classname){

  var targElem = new Array();

  if(elem){
    var tags = elem.getElementsByTagName('*');
  }else{
    var tags = document.getElementsByTagName('*');
  }

  for(var i = 0;i < tags.length;i++){
    var tmpElem = tags[i];
    var broType = IE67orNot();
    if(broType){
      var attrString = tmpElem.getAttribute('className');
    }else{
      var attrString = tmpElem.getAttribute('class');
    }

/*
    try{
      var attrString = tmpElem.getAttribute('class');
    }catch(e){
      var attrString = tmpElem.getAttribute('className');
    }
*/
    if(attrString){
      var attrArray = attrString.split(' ');
      if(attrArray){
        for(var j = 0;j < attrArray.length; j++){
          if(attrArray[j] == classname){
            targElem.push(tags[i]);
            break;
          }
        }
      }
    }
  }
  return targElem;
}

function IE67orNot(){

   var idFlg = false;
   var btype = broserSelect();
  if(btype == msIE6){
    idFlg = true;
  }else if(btype == msIE7){
    idFlg = true;
  }
  return idFlg;
}

function broserSelect(){

  var Btype='';
if(navigator.userAgent.indexOf('Opera') != -1){ // 文字列に「Opera」が含まれている場合
  Btype = msOpera;
}
else if(navigator.userAgent.indexOf('MSIE 6.0') != -1){ // 文字列に「MSIE」が含まれている場合

  Btype = msIE6;

}
else if(navigator.userAgent.indexOf('MSIE 7.0') != -1){ // 文字列に「MSIE」が含まれている場合
  Btype = msIE7;

}
else if(navigator.userAgent.indexOf('MSIE 8.0') != -1){ // 文字列に「MSIE」が含まれている場合
  Btype = msIE8;
}
else if(navigator.userAgent.indexOf('Firefox') != -1){ // 文字列に「Firefox」が含まれている場合
  Btype = msFirefox;

}
else if(navigator.userAgent.indexOf('Chrome') != -1){ // 文字列に「Chrome」が含まれている場合
  Btype = msChrome;

}
else if(navigator.userAgent.indexOf('Safari') != -1){ // 文字列に「Safari」が含まれている場合
  Btype = msSafari;
}
else{

}
  return Btype;

}


// 当該スクリプトの実行
addLoadEvent(inputCheckFunc);


