/*----------------------------------------------------
  入力チェック

  Atsushi Koyama
-----------------------------------------------------*/
var inputfields = new Array();
var errors = new Array(); 	// エラーメッセージを格納する配列
var msgs = new Array();		// メッセージ配列(最下部にデフォルトを記述してある)
var errorBgcolor		= "#ffddcc";

//////////////////// onsubmitに記述する場合 ///////////////////////
// フォームの入力チェック
function validateForm(form) {
	inputfields = new Array();
	errors      = new Array();

	initValidateForm(form);
	return validateData();
}
// 入力チェック対象のフォームを初期化
function initValidateForm(form) {
	var elements = form.elements;
	for(var i = 0; i < elements.length; i++) {

		var e = elements[i];
		if(e.type == 'hidden' || e.type == 'submit' || e.type == 'reset')
			continue;

		if(!e.validateText) {
			var atts = e.attributes;
			var obj = null;
			if(atts['alt']) {
				obj = atts['alt'];
				if(!obj || obj.value == 'null') continue;
			}
			else {
				if(!e.alt || e.alt == '') continue;
				obj = new Object();
				obj.value = e.alt;
			}
			e.validateText = obj.value;		// <-- 独自の属性
			e.fieldList = elements[e.name];	// <-- 独自の属性
			obj.value = null;
		}

		inputfields.push(e);
	}
}
//////////////////// onloadに記述する場合 ///////////////////////

// 入力チェック初期化
function initValidate(formname) {
	var form = document.forms[formname];
	if(!form) return;
	
	form.onsubmit = function() {return validateData();};
	
	initValidateForm(form);
}
// 入力チェック
function validateData() {
	var result = true;
	for(var i = 0; i < inputfields.length; i++) {
		var e = inputfields[i];
		var vlist = e.validateText.split('|');		// 'v1|v2| ... |vn'

		changeBgColor(e, null); // 元のの背景色に戻す

		if(e.disabled) continue;// 無効ならチェックしない
		
		for(var j = 0; j < vlist.length; j++) {
			var v = vlist[j].split(':');			// 'type:opt1:opt2: ... :optn'
			var re = true;
			
			if(v[0] == 'checked' && !isChecked(e, v[1]))
				break;
			switch(v[0]) {
				case 'require' :	re = checkRequire(e);			break;
				case 'len':			re = checkLength(e, v[1], v[2]);break;
				case 'minlen' :		re = checkMinLen(e, v[1]);		break;
				case 'maxlen' :		re = checkMaxLen(e, v[1]);		break;
				case 'minmax':		re = checkMinMax(e, v[1], v[2]);break;
				case 'min' :		re = checkMin(e, v[1]);			break;
				case 'max' :		re = checkMax(e, v[1]);			break;
				case 'maxselect':	re = checkMaxSelect(e, v[1]);	break;
				case 'minselect':	re = checkMinSelect(e, v[1]);	break;
				case 'digit' :		re = checkDigit(e);				break;
				case 'word' :		re = checkWord(e);				break;
				case 'ascii':		re = checkAscii(e);				break;
				case 'hankaku':		re = checkOneByteChar(e);		break;
				case 'mail':		re = checkMailAddr(e);			break;
				case 'phone':		re = checkPhoneNumber(e);		break;
				case 'zipcode':		re = checkZipCode(e);			break;
				case 'equal':		re = checkEqual(e, v[1]);		break;
				default:break;
			}
			if(!re) {
				result = false;
				break;
			}
		}
	}
	if(!result) {
		printErrorMessage();
		return false;
	}
	return true;
}
// 
function isChecked(e, fieldName) {
	var ee = e.form.elements[fieldName];
	return (!(!ee || !ee.checked));
}
// フィールド名から探す
function getInputfieldByName(fieldName) {
	for(var i = 0; i < inputfields.length; i++) {
		if(inputfields[i].name == fieldName) {
			return inputfields[i];
		}
	}
	return null;
}
// 必須入力チェック
function checkRequire(e) {
	switch(e.type) {
		case 'text':
		case 'password':
		case 'textarea':
			if(!isEmptyText(e)) return true;
			break;
		case 'select-one':
			if(!isEmptyText(e.options[e.selectedIndex])) return true;
			break;
		case 'select-multiple':
			if(countSelected(e) > 0) return true;
			break;
		case 'checkbox':
		case 'radio':
			for(var i = 0; i < e.fieldList.length; i++)
				if(e.fieldList[i].checked) return true;
			break;
		default:
			return true;
	}
	errorAdd(e, msgs['require'], e.title);
	return false;
}
// 文字数チェック
function checkLength(e, min, max) {
	if(!isValidTextField(e)) return true;
	if(e.value.length >= min && e.value.length <= max) return true;
	errorAdd(e, msgs['len'], e.title, min, max);
	return false;
}
// 最大文字数チェック
function checkMaxLen(e, n){
	if(!isValidTextField(e)) return true;
	if(e.value.length <= n) return true;
	errorAdd(e, msgs['maxlen'], e.title, n);
	return false;
}
// 最小文字数チェック
function checkMinLen(e, n){
	if(!isValidTextField(e)) return true;
	if(e.value.length >= n) return true;
	errorAdd(e, msgs['minlen'], e.title, n);
	return false;
}
// 最大値、最小値のチェック
function checkMinMax(e, min, max) {
	if(!isValidTextField(e)) return true;
	if(!checkDigit(e)) return false;
	if(parseFloat(e.value) >= parseFloat(min) &&
		parseFloat(e.value) <= parseFloat(max) ) return true;
	errorAdd(e, msgs['minmax'], e.title, min, max);
	return false;
}
// 最大値チェック
function checkMax(e, n){
	if(!isValidTextField(e)) return true;
	if(!checkDigit(e)) return false;
	if(parseFloat(e.value) <= parseFloat(n)) return true;
	errorAdd(e, msgs['max'], e.title, n);
	return false;
}
// 最小値チェック
function checkMin(e, n){
	if(!isValidTextField(e)) return true;
	if(!checkDigit(e)) return false;
	if(parseFloat(e.value) >= parseFloat(n)) return true;
	errorAdd(e, msgs['min'], e.title, n);
	return false;
}
// 数値であるかをチェック
function checkDigit(e){
	if(!isValidTextField(e)) return true;
	if(e.value.match(/^\d*$/)) return true;
	errorAdd(e, msgs['digit'], e.title);
	return false;
}
// 文字であるかをチェック
function checkWord(e){
	if(!isValidTextField(e)) return true;
	if(e.value.match(/^[a-zA-Z]*$/)) return true;
	errorAdd(e, msgs['word'], e.title);
	return false;
}
// 半角英数チェック
function checkOneByteChar(e) {
	if(!isValidTextField(e)) return true;
	if(e.value.match(/^[0-9a-zA-Z]*$/)) return true;
	errorAdd(e, msgs['hankaku'], e.title);
	return false;
}
// Ascii チェック
function checkAscii(e) {
	if(isAscii(e.value)) return true;
	errorAdd(e, msgs['ascii'], e.title);
	return false;
}
// 郵便番号入力で使用される文字
function checkZipCode(e) {
	if(!isValidTextField(e)) return true;
	if(isAscii(e.value) && e.value.match(/^\d+[\d\-]*\d+$/)) return true;
	errorAdd(e, msgs['zipcode'], e.title);
	return false;
}
// 電話番号入力で使用される文字
function checkPhoneNumber(e) {
	if(!isValidTextField(e)) return true;
	if(isAscii(e.value) && e.value.match(/^\d+[\d\-]*\d+$/)) return true;
	errorAdd(e, msgs['phone'], e.title);
	return false;
}
// メールアドレス入力で使用される文字
function checkMailAddr(e) {
	if(!isValidTextField(e)) return true;
	if(isAscii(e.value) && e.value.match(/^[^@\s]+@[a-zA-Z0-9\._\-]+$/)) return true;
	errorAdd(e, msgs['mail'], e.title);
	return false;
}
// 選択可能な最大数をチェック
function checkMaxSelect(e, n) {
	var count = countSelected(e);
	if(count == -1 || count <= n) return true;
	errorAdd(e, msgs['maxselect'], e.title, n);
	return false;
}
// 選択可能な最小数をチェック
function checkMinSelect(e, n) {
	var count = countSelected(e);
	if(count == -1 || count >= n) return true;
	errorAdd(e, msgs['minselect'], e.title, n);
	return false;
}
// 同じ値であるかをチェック
function checkEqual(e, fieldName) {
	var ee = getInputfieldByName(fieldName); // 比較対象のフィールドを取得
	if(!ee || e.value == ee.value) return true;
	errorAdd(e, msgs['equal'], e.title, ee.title);
	return false;
}
/*----------------------------------------------------
  エラーメッセージの操作

-----------------------------------------------------*/
// エラーコレクションにエラーメッセージを格納
function errorAdd(e, format) {
	for(var i = 2; i < arguments.length; i++)
		format = format.replace('%'+ (i - 1), arguments[i]);
	e.errorMessage = format; // <-- 独自の属性
	errors.push(e);
}
// エラーメッセージを表示
function printErrorMessage() {
	if(errors.length < 1) return;
	var message = msgs['title'] + '\n\n';
	for(var i=0; i<errors.length; ++i) {
		message += errors[i].errorMessage + '\n';
		changeBgColor(errors[i], errorBgcolor);
	}
	errors = new Array();
	alert(message);
}
// 背景色を変更
function changeBgColor(e, color) {
	// 背景色を色変更
	if(e.orgBgColor == undefined)
		e.orgBgColor = e.style.backgroundColor; // 元の背景色がある場合保存 <-- 独自の属性
	if(color == null)
		color = e.orgBgColor;					// 色が指定されていない場合、保存されている背景色にする
	e.style.backgroundColor = color;

	// 親が<label>である場合
	if(e.parentNode && e.parentNode['tagName']  == "LABEL") {
		changeBgColor(e.parentNode, color, 1);
	}
	// 同名の入力項目も背景色を変更
	if(e.fieldList && e.fieldList.length && arguments.length < 3) {
		for(var i = 0; i < e.fieldList.length; i++)
			changeBgColor(e.fieldList[i], color, 1);
	}
}

/*----------------------------------------------------
  その他

-----------------------------------------------------*/
// ASCII文字であるか?
function isAscii(str){
	for (var i=0; i<str.length; i++){
		code = str.charCodeAt(i);
		if(0x20 > code || 0x7e < code) return false;
	}
	return true;
}
// 有効な文字列フィールドか
function isValidTextField(e) {
	if(e.type != 'text' && e.type != 'password' && e.tagName != 'TEXTAREA') return false;
	if(!isEmptyText(e)) return true;
	return false;
}
// 空の文字列か?
function isEmptyText(e) {
	return (!e.value || trim(e.value) == "");
}
// 選択されている項目数を数える
function countSelected(e) {
	var count = 0;
	if(e.type == 'radio' || e.type == 'checkbox') {
		for(var i = 0; i < e.fieldList.length; i++)
			if(e.fieldList[i].checked)
				++count;
	}
	else if(e.type == 'select-multiple') {
		var count = 0;
		for(var i = 0; i < e.options.length; i++) {
			if(e.options[i].selected && !isEmptyText(e.options[i]))
				++count;
		}
	}
	else {
		return -1;
	}
	return count;
}
// 前後のスペース削除
function trim(str){
	while(
		str.charAt(0)==" "		|| 
		str.charAt(0)=="　"		|| 
		str.charAt(0) == "\n"	||
		str.charAt(0) == "\r")
	{
		str=str.substring(1,str.length);
	}
	while(
		str.charAt(str.length-1)==" "    || 
		str.charAt(str.length-1)=="　"   || 
		str.charAt(str.length-1) == "\n" ||
		str.charAt(str.length-1) == "\r" )
	{
		str=str.substring(0,str.length-1);
	}
	return str;
}
/*----------------------------------------------------
  デフォルトのエラーメッセージ

-----------------------------------------------------*/
// タイトル
msgs['title']		= "[ 入力確認 ]";

// 必須入力
msgs['require']		= "%1: 必須入力項目です。";

// 最大/最小文字数の指定
msgs['len']			= "%1: %2 以上、%3 以下の文字数で入力してください。";

// 最大文字数の指定
msgs['minlen']		= "%1: %2 以上の文字数で入力してください。";

// 最小文字数の指定
msgs['maxlen']		= "%1: %2 以下の文字数で入力してください。";

// 最大値/最小値の指定
msgs['minmax']		= "%1: %2 以上、%3 以下の数値を入力してください。";

// 最小値の指定
msgs['min']			= "%1: %2 以上の数値を入力してください。";

// 最大値の指定
msgs['max']			= "%1: %2 以下の数値を入力してください。" ;

// 選択可能最大数の指定
msgs['maxselect']	= "%1: %2 個以下の項目を選択してください。";

// 選択可能最小数の指定
msgs['minselect']	= "%1: %2 個以上の項目を選択してください。";

// 半角数値
msgs['digit']		= "%1: 半角数字を入力してください。";

// 半角英字
msgs['word']		= "%1: 半角英字を入力してください。";

// 半角英数
msgs['hankaku']		= "%1: 半角英数文字を入力してください。";

// 半角文字
msgs['ascii']		= "%1: 半角文字を入力してください。";
// メール
msgs['mail']		= "%1: 正しいメールアドレスであるか確認してください。";

// 電話番号
msgs['phone']		= "%1: 半角英数字または、- を入力してください。例）111-2222-3333";

// 郵便番号
msgs['zipcode']		= "%1: 半角英数字または、- を入力してください。例) 111-2222";

// 同じであるか
msgs['equal']		= "%1: [ %2 ]と同じ値を入力してください。";


