﻿~function(){
$.fn.form = function(settings){
	if ($(this).data('formsettings')) {
		$(this).data('form').setting(settings);
	} else {
		settings = settings || {};
		return this.each(function(){
			var $this = $(this), formFunc;
			if ($this.is('form')) {
				settings.method = $this.attr('method');
				settings.url    = $this.attr('action');
			}
			settings = $.extend({
				type       : 'ajax',
				validation : false
			}, settings);
			formFunc = new form(settings, $this);
			$this.data({'formsettings':true, 'form':formFunc}).bind('submit', function(){
				return formFunc.submit();
			});
		});
	}
}
	
function form(settings, object) {
	this._data = {};
	this.isSubmit = false;
	this.object = object;
	this.dataNode = $('<div/>').appendTo(object);
	this.settings = {
		onSubmit : function(){},
		onSubmited : function(){},
		onSubmitEnd : function(){}
	};
	this.setting(settings);
}
	
$.extend(form.prototype, {
	setting : function(settings){
		var This = this;
		$.extend(this.settings, settings);
		settings.data && this.data(settings.data);
		settings.validation && this.getControl().each(function(){
			if ($(this).data('vdt')) return;
			var $this = $(this).data('vdt', 1), name = $this.attr('name'), option;
			settings.validation[name] = option = settings.validation[name] || {};
			$.each(settings.fn || {}, function(key, fn){
				if (option[key] === undefined) option[key] = fn;
			});
			option.$tips = $('<span/>');
			option.$node = $this.attr('autoComplete', 'off');
			if (!option.key) option.key = name;
			if (option.same) {
				This.getControl(option.same.key).blur(function(){
					$this.blur();
				});
			}
			option.isBlur !== false && $this.is(':password,:text,textarea') && $this.blur(function(){
				if (option.server && $this.data('ov') != $this.val()) {
					option.server.ok = '';
					option.server.isSend = '';
				}
				This.validation.match($this.val(), option, This.data());
			}).focus(function(){
				$this.data('ov', $this.val());
				isFunction(option.tips) && option.tips.apply($this);
			});
			isFunction(option.run) && option.run.apply(option);
		}) && (this.validation = new validation(settings.validation));	
	},
	getControl : function(name){ return name ? this.object.find(':input[name='+name+']') : this.object.find(':input[name]'); },
	data : function(key, val){
		if (key === undefined || (val === undefined && !isObject(key))) {
			var data = {};
			this.getControl().each(function(){
				var $this = $(this), 
					name  = $this.attr('name'), val = ($this.val() || '').trim();
				if ($this.is(':checkbox')) {
					!data[name] && (data[name] = []);
					if ($this.is('[checked]')) {
						data[name].push(val);
					}
				} else if (!$this.is(':radio') || $this.is('[checked]')) {
					data[name] = val;
				} else if (!data[name]) {
					data[name] = '';
				}
			});
			$.extend(data, this._data);
			return key ? data[key] : data;
		} else if (val === undefined) {
			var This = this;
			return $.each(key, function(key, val){	This.data(key, val); }), This;
		} else {
			this._data[key] = val;
		}
	},
	submit : function(){
		if (!this.isSubmit) {
			var This = this, settings = This.settings, data;
			if (this.settings.validation && this.validation.matchAll(this.data()) === false) return false;
			if (this.settings.onSubmit.apply(this, [this.settings, this.object]) === false) return false;
			data = this.data();
			this.isSubmit = true;
			if (this.settings.type == 'ajax') {
				return v.ajax[this.settings.method || 'post'](this.settings.url, data, function(text){
					This.isSubmit = false;
					var response = jsonDecode(text);
					settings.onSubmited.apply(This, [response, text]);
					if (response) {
						callback(response.msg, response.data) !== false && settings.onSubmitEnd.apply(This, [response, text])
					} else {
						alert(text);
					}
				}),  false;
			} else if (this.settings.type == 'iframe') {
				var iframeName = v.util.randomName('iframe'), iframe = $('<div/>').appendTo('body').html('<iframe style="display:none" name="'+iframeName+'"></iframe>');
				iframe.find('iframe').bind('load', function(){
					This.isSubmit = false;
					var text = $(this).contents().find('body').html(), response = jsonDecode(text);
					settings.onSubmited.apply(This, [response, text]);
					if (response) {
						callback(response.msg, response.data) !== false && settings.onSubmitEnd.apply(This, [response, text])
					} else {
						alert(text);
					}
					setTimeout(function(){iframe.remove()}, 0);
				});
				this.object.attr('target', iframeName);
			}
			This.dataNode.html('');
			$.each(this._data, function(key, val){
				$('<input/>').hide().appendTo(This.dataNode).val(val).attr('name', key);
			});
		} else {
			return false;
		}
	}
});

window.validation = function(settings){
	this.settings = settings;
}

$.extend(validation, {
	regexp : {
		userName : /^[a-zA-Z][a-zA-Z0-9_]{5,15}$/,
		userPwd : /.{6,20}/,
		email : /^[a-z0-9-.]+@([a-z0-9-]+[.])+[a-z]{2,3}$/,
		notEmpty : /^.+$/,
		phone : /^([0-9]{3,4}([- ])?)?[0-9]{8}$/,
		mobile : /^((13)|(15)|(18))[0-9]{9}$/,
		moremobile : /^((13)|(15)|(18))[0-9]{9}(,((13)|(15)|(18))[0-9]{9}).$/,
		qq : /^[0-9]{5,11}$/,
		url : /^(http:\/\/)?(www\.)?.*?\.(com|cn|hk|tw|net|org|info)/,
		num : /^[0-9]+$/,
		code : /^[0-9]{6}$/,
		date : /^(\d{2}|\d{4})-([0-1][0-2]|0?\d)-[0-3]?\d$/
	}
});

$.extend(validation.prototype, {
	matchAll : function(data){
		var This = this;
		$.each(data, function(key, val){
			if (This.settings[key] && This.match(val, This.settings[key], data) === false) {
				return data = false;
			}
		});
		return data;
	},
	match : function(val, option, data){
		option.$tips && option.$tips.hide();
		if (!val) {//验证不能为空
			if (isFunction(option.empty)){
				option.empty.apply(option);
				return false;
			}
			return true;
		}
		if (option.len) {//验证长度
			if (isString(option.len)) option.len = [0, option.len];
			if (val.toString().length < option.len[0]) {
				return isFunction(option.error) && option.error.apply(option, [option.key+'的长度不能小于'+option.len]), false;
			}
			if (val.toString().length > option.len[0]) {
				return isFunction(option.error) && option.error.apply(option, [option.key+'的长度不能大于'+option.len]), false;
			}
		}
		if (option.regexp){
			if (isString(regexp)  && validation.regexp[regexp]) {
				regexp = validation.regexp[regexp];
			}
			if (!val.match(regexp)) {
				isFunction(option.error) && option.error.apply(option, [option.key+'格式不正确']);
				return false;
			}
		}
		if (option.same){
			if (data[option.same.key] && val != data[option.same.key]) {
				isFunction(option.same.error) && option.same.error.apply(option);
				return false;
			}
		}
		if (option.server){
			if (!option.server.ok && !option.server.isSend) {
				isFunction(option.server.tips) && option.server.tips.apply(option);
				v.ajax.server(option.server.url, {data:val}, function(response){
					option.server.isSend = true;
					if (response.status == 'ok') {
						option.server.ok = true;
						isFunction(option.ok) && option.ok.apply(option);
					} else {
						isFunction(option.server.error) && option.server.error.apply(option);
					}
				});
				return false;
			} else if (!option.server.ok) {
				isFunction(option.server.error) && option.server.error.apply(option);
				return false;
			}
		}
		
		isFunction(option.ok) && option.ok.apply(option);

		return true;
	}
});

}();
