/**
 * livevalidation.js
 *
 * @author    MT312
 * @copyright 2008 MT312
 * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
 * @version   CVS: $Id:$
 * @link      http://www.mt312.com/
 * @see       prototype.js 1.6 (http://www.prototypejs.org/)
 */

var validator = {};
validator.register = function(def_list) {
	this.def_list = def_list;
	Event.observe(window, 'load', this.dispatch);
};
validator.dispatch = function() {
	var def_list = validator.def_list;
	if (def_list.length == 0 || !('id' in def_list[0])) {
		return false;
	}
	var inner = $(def_list[0].id);
	if (inner == null) {
		return false;
	}
	if (inner.tagName == 'SPAN') {
		inner = $(def_list[0].id + '0');
	}
	var form = inner.form;

	form.onkeydown = form.onmousedown = function(ev) {
		this.el = Event.element(ev || window.event);
	};
	form.onsubmit = function(ev) {
		var el = this.el;
		if (el.tagName != 'INPUT' || el.type != 'submit') {
			var elems = Form.getElements(this);
			elems[elems.indexOf(el) + 1].focus();
			return false;
		}
		var focused = false;
		el_list.each(function(el) {
			if (!el.validate(ev) && !focused) {
				focused = true;
				el.focus();
				Element.scrollTo(el.previousSibling);
			}
		});
		return !focused;
	};
	form.onreset = function() {
		el_list.each(function(el) {
			var err_el = el.previousSibling;
			var has_err = err_el && err_el.tagName == 'EM';
			if (has_err) {
				// el.style.backgroundColor = '';
				Element.remove(err_el);
			}
		});
		Element.scrollTo(this);
	};

	var getType = function(el) {
		var tag = el.tagName;
		if (tag == 'SPAN') {
			var nodes = $A(el.childNodes);
			var node = nodes.find(function(node) {
				return node.firstChild && node.firstChild.type;
			});
			if (node) {
				return node.firstChild.type == 'radio' ? 'R' : 'C';
			}
			return '';
		}
		return tag.charAt(0);
	};

	var el_list = [];
	def_list.each(function(def) {
		var el = $(def.id);
		if (el == null) return;

		Element.cleanWhitespace(el.parentNode);
		el_list.push(el);
		var class_name = getType(el) + '_Define';
		if (class_name in window) {
			var define = new window[class_name]();
			Object.extend(define, def);
		} else {
			var define = new Object();
			def = {};
		}

		if (!('form' in el)) {
			el.form = form;
		}
		define.el = el;
		el.def = def;
		el.define = define;
		el.validate = function(ev) {
			ev = ev || window.event;
			if (ev.keyCode == 9 || ev.keyCode == 13) {
				return true;
			}
			var err_el = this.previousSibling;
			var has_err = err_el && err_el.tagName == 'EM';
			for (var mem in def) {
				var name = mem + '_check';
				if (typeof define[name] == 'function') {
					var result = define[name]();
					if (result === null) break;
					if (result === true) continue;
					var msg = define[mem + '_error'] + '。';
					msg = msg.replace('{form}', define.name);
					if (!has_err) {
						err_el = document.createElement('em');
						this.parentNode.insertBefore(err_el, this);
					}
					err_el.className = 'error';
					err_el.innerHTML = msg;
					return false;
				}
			}
			if (has_err) {
				err_el.className = 'good';
				err_el.innerHTML = 'Good!';
			}
			return true;
		};

		if (el.tagName == 'SELECT') {
			Event.observe(el, 'change', el.validate);
		} else if (el.tagName == 'SPAN') {
			var nodes = $A(el.childNodes);
			nodes.each(function(node) {
				if (node.firstChild) {
					Event.observe(node.firstChild, 'click', function(ev) {return el.validate(ev);});
				}
			});
		} else {
			Event.observe(el, 'keyup', el.validate);
			// Event.observe(el, 'blur', el.validate);
		}
	});
	return true;
};
function Define()
{
	this.required = false;
	this.required_error = '{form}を入力して下さい';
	this.required_check = function() {
		if (this.required) {
			return $F(this.el) != '';
		} else if ($F(this.el) == '') {
			return null;
		}
		return true;
	};
	this.min = 0;
	this.min_error = '';
	this.min_check = function() {
		if (this.min_error == '') {
			this.min_error = '{form}は' + this.min + '文字以上にして下さい';
		}
		return $F(this.el).length >= this.min;
	};
	this.max = 2000;
	this.max_error = '';
	this.max_check = function() {
		if (this.max_error == '') {
			this.max_error = '{form}は' + this.max + '文字以内にして下さい';
		}
		return $F(this.el).length <= this.max;
	};
}
function T_Define()
{
	this.regexp_list = {
		mailaddress:   /^([a-z\d_]|\-|\.|\+)+@(([a-z\d_]|\-)+\.)+[a-z]{2,6}$/i,
		url: /^(https?|ftp):\/\/.+/,
		alphabet: /^[a-z]+$/i,
		number: /^\d+$/,
		alphanum: /^[a-z\d]+$/i,
		integer: /^[1-9]\d*$/,
		zipcode: /^\d{3}-\d{4}$/,
		zipcode_d: /^\d{7}$/,
		phone: /^0[1-9]\d{0,3}-\d{1,4}-\d{4}$/,
		phone_d: /^0[1-9]\d{8}$/,
		mbphone: /^0[7-9]0-\d{4}-\d{4}$/,
		mbphone_d: /^0[7-9]0\d{8}$/,
		katakana: /^[ア-ン　 ]+$/,
		hiragana: /^[あ-ん　 ]+$/
	};
	this.regexp = null;
	this.regexp_error = '{form}が正しくありません';
	this.regexp_check = function() {
		if (this.regexp in this.regexp_list) {
			return this.regexp_list[this.regexp].test($F(this.el));
		}
		return true;
	};
	this.repeat = false;
	this.repeat_error = '{form}が正しくありません';
	this.repeat_check = function() {
		var elems = Form.getElements(this.el.form);
		var n = elems.indexOf(this.el);
		return n > 0 && (elems[n - 1].value == this.el.value);
	};
}
function S_Define()
{
	this.required_error = '{form}を選択して下さい';
}
function R_Define()
{
	this.required_error = '{form}を選択して下さい';
	this.required_check = function() {
		if (this.required) {
			var list = this.el.form[this.el.def.id];
			if ('checked' in list) {
				return list.checked;
			}
			for (var i = 0, l = list.length; i < l; ++i) {
				if (list[i].checked) return true;
			}
			return false;
		}
		return true;
	};
	this.min_check = function() {
		if (this.min_error == '') {
			this.min_error = '{form}は' + this.min + '文字以上にして下さい';
		}
		var length = 0;
		var nodes = $A(this.el.childNodes);
		nodes.each(function(node) {
			if (node.firstChild && node.firstChild.checked) {
				length = $F(node.firstChild).length;
			}
		});
		return length >= this.min;
	};
}
function C_Define()
{
	this.required_error = '{form}を選択して下さい';
	this.required_check = function() {
		if (this.required) {
			var list = this.el.form[this.el.def.id + '[]'];
			if ('checked' in list) {
				return list.checked;
			}
			for (var i = 0, l = list.length; i < l; ++i) {
				if (list[i].checked) return true;
			}
			return false;
		}
		return true;
	};
	this.min_check = function() {
		if (this.min_error == '') {
			this.min_error = '{form}は' + this.min + '箇所以上選択して下さい';
		}
		var checks = 0;
		var nodes = $A(this.el.childNodes);
		nodes.each(function(node) {
			if (node.firstChild && node.firstChild.checked) {
				++checks;
			}
		});
		return checks >= this.min;
	};
}
function F_Define()
{
	this.required_error = '{form}を選択して下さい';
}
I_Define = T_Define;
I_Define.prototype = new Define();
T_Define.prototype = new Define();
R_Define.prototype = new Define();
S_Define.prototype = new Define();
C_Define.prototype = new Define();
F_Define.prototype = new Define();

