(function($){
	$.fn.form=function(o, extra) {
		if( typeof o == 'string' ) {
			if( o == 'submit') { o = extra; var submit=true; }
			else if( o.charAt(0) == '{' ) o = $.extend(extra, $.parseJSON(o));
		}
		else if ( typeof o == 'object' ) {
			if( typeof o.register == 'string' && o.register != '') {
				$.fn.form.types[o.register] = o; return this;
			}
		}
		
		o=$.extend({ form: this.is("form")? this : this.parents("form") }, o);
		if(!o.form.length) o.form = this.find("form");
		o = $.fn.form.define({	
			self: 			this,
			before: 		function(o) {},
			test: 			function(o) {return true;},
			after: 			function(o) {},
			success: 		false,
			error: 			false,
			errors: 		function(o) {},
			load: 			false,
			type: 			'default',
			validation:		false,
			validationItem: '.field',	
			infoClass:  	"info",
			errorClass: 	"error",
			validClass: 	"valid",
			extraUrl: 	 	"",
			ajax:	 		false,
			enhance: 		false,
			input:			this.is("input")? this : o.form.find("input:submit"),
			data:			"",
			url:			o.form.attr("action"),
			nofile:			!o.form.find("input:file").length
		}, o);	
		o.url += o.extraUrl;		
		
		if(submit) {
			if(o.load) o.load(o);
			$.fn.form.submit(o);
			return this;
		}
		
		if(o.liveValidation) $.fn.form.liveValidation(o);
		if(o.enhance) $.fn.form.enhance(o);
		if(o.autogrow) $.fn.form.autogrow(o);
		
		if(o.ajax || o.success || o.error) {
			//o.form.find('input').focus(function(){this.blur()});
			o.form.submit(function(e) {
				//if(o.liveValidation) { // && o.errors_count) {
					//o.errors(o);					
					//return false;
				//}
				//else {
					if(o.form.attr('target')) return true;
					$.fn.form.submit(o); return false; 
				//}
			});			
			o.input.click(function() {
				o.form.submit();
				return false;
			})
		}
		if(o.load) o.load(o);
		return this;
	};
	
	$.fn.form.types = {};
	$.fn.form.define = function(defaults, o, extra) {
		if(!o) o={};
		var type = $.fn.form.types[ o.type  ? o.type : defaults.type ];				
    	if( type ) {
    		var options = typeof type == 'function' ? type(o) : type;	
			defaults = $.extend(defaults, type);			
		}    	
    	return $.extend(defaults, o, extra);
    };   
	
	$.fn.delegate_form=function(o,f,id,ifr,old,c){
		//return this.form($.extend(o, { delegate: true });
	};
		
	$.fn.formSubmit = function(o) { this.form(o); $.fn.form.submit(o); return this; };
	$.fn.form.submit = function(o, c, old, ifr){
		o.form.find('input,textarea,select').each(function(){
			if(this.empty) this.value = '';
		});
		o.dataArray = o.form.serializeArray();
		if(o.input&&o.input.is(':submit')) o.dataArray.push({name: o.input.attr('name'), value: o.input.val()});

		if(!o.test(o)) return this;
		if( o.before(o) === false ) return this;
		if(!o.nofile){
			id='__uploadfile'+(new Date().getTime());
			ifr=$('<iframe id="'+id+'" name="'+id+'" src="about:blank"></iframe>').css({position:'absolute',left:-9000,top:0,zIndex:99999999}).appendTo("body");
			old = {target:o.form.attr('target'),action:o.form.attr('action'),encoding:o.form.attr('encoding'),enctype:o.form.attr('enctype'),method:o.form.attr('method')};
			o.form.attr({target:id,action:o.url,encoding:'multipart/form-data',enctype:'multipart/form-data',method:'POST'}).trigger('submit', { bypass: true });
			o.form.removeAttr('target');
			c=function(){
				var b=ifr.contents().find('body');
				if(!b.length)setTimeout(c,100);
				o.data=b.html();
				setTimeout(function(){
					ifr.remove().empty();
					ifr=null;
				},200);
				$.fn.form.after(o);
				o.form.attr(old);
			};
			setTimeout(function(){ifr.one('load',c);},10);
		}
		else{
			//$.post(o.url,o.dataArray,function(d){o.data=d;$.fn.submit.after(o);});			
			$.ajax({
				type: o.form.attr('method') ? o.form.attr('method') : 'POST',
        		dataType: 'html',
        		url: o.url, 
        		data: o.dataArray,        		
        		success: function(d, textStatus, XMLHttpRequest) {        
					o.data=d;$.fn.form.after(o);
        		},
        		error: function(xhr, ajaxOptions, thrownError) {          		
        			if(o.error) o.error(o, xhr, ajaxOptions, thrownError);
        			o.after(o);
        		}
			});
		}
	};
	$.fn.form.after = function(o){
		o.after(o);			
		if(o.validation) {
			o.form.find("."+o.errorClass).removeClass(o.errorClass).find("."+o.infoClass).html("");
			if(o.data.replace(/^\s+/g,'').replace(/\s+$/g,'').charAt(0)=="{") {		
				var data = window["eval"]("("+o.data+")");
				for(var i in data) {
					var name = i.replace(/\[/g,"\\[").replace(/\]/g,"\\]");
					o.form.find(name).addClass(o.errorClass).find("."+o.infoClass).html(data[i]);
				}			
				o.errors(o);
				
			}
			else o.success(o);		
		}
		else { 
			if(o.data.replace(/^\s+/g,'').replace(/\s+$/g,'').charAt(0)=="{") {	
				o.data = window["eval"]("("+o.data+")");
			}
			o.success(o);	
		}
	};

	$.fn.form.autogrow=function(o){	
		var selector = typeof o.autogrow == 'string'? o.autogrow : 'textarea';
		o.form.find(selector).each(function() {

			if(this.autogrow) return false;	
			this.autogrow = true;
			var self = $(this);
			
			if(!$.fn.form.autogrow.m)$.fn.form.autogrow.m=$('<div style="left:-9999px;top:0px;position:absolute;">').appendTo('body');
			
			if(o.width){
				var neg = parseInt(self.css("paddingLeft")) + parseInt(self.css("paddingRight"));
				$.fn.form.autogrow.m.width(o.width-neg).html(self.val().replace(/\n/g,'<br />&nbsp;'));
				o.height=parseInt($.fn.autogrow.m.height());
			}
			else {
				o.height=parseInt(self.height());
				if(o.height==0)o.height=parseInt(self.css('height'));			
				if(o.height==0)o.height=parseInt(this.offsetHeight);
			}
			self.css('overflow','hidden');
			$.fn.form.autogrow.g(o,self);
		});
		o.form.delegate(selector, "keyup", function(e){$.fn.form.autogrow.g(o,$(this));})
		return this;
	};
	$.fn.form.autogrow.g=$.browser.msie?function(o,t){			
		$.fn.form.autogrow.m.html(t.val().replace(/\n/g,'<br />&nbsp;'));
		t.height($.fn.form.autogrow.m.height()<=o.height?o.height:$.fn.form.autogrow.m.height());
	}:function(o,t){
		t.css('height','').height(t[0].scrollHeight<=o.height?o.height:t[0].scrollHeight);
	};
	$.fn.form.autogrow.m=null;$.fn.form.autogrow.h=null;
	
	$.fn.form.enhance = function(o) {	
		o.form.find('input:text, textarea, select').each(function() {
			$.fn.form.enhance.emptytest({ type : 'blur', input : $(this) });					
		});
		o.form.unbind('submit.enhance').bind('submit.enhance', $.fn.form.enhance.submit);
		o.form.find('input, textarea, select').unbind('.enhance');
		o.form.delegate('input:text, textarea, select', 'keyup.enhance', $.fn.form.enhance.emptytest);
		o.form.delegate('input:text, textarea, select', 'change.enhance', $.fn.form.enhance.emptytest);
		o.form.delegate('input:text, textarea, select', 'focus.enhance', $.fn.form.enhance.emptytest);
		o.form.delegate('input:text, textarea, select', 'blur.enhance', $.fn.form.enhance.emptytest);
		return this;	
	};
	
	$.fn.form.liveValidation = function(o) {	
		o.errors_count = 0;
		o.form.find('input[required],textarea[required],select[required]').each(function(opt, item, self, tiny) {
			self = $(this)	
			opt = self.attr('required')
			if( typeof(opt) == 'string' && opt != '' ) {
				//self.attr('title', self.attr('title').replace(title[0], '') )
				opt = opt.split(',')
				item = self.parents(o.validationItem)
				self[0].validation = {}
				for(var i in opt) {
					var options = opt[i].split(':')
					self[0].validation[options[0]] = options;	
				}
						
				self.bind('keyup.form.validation', function() { $.fn.form.liveValidate(o, self, item, self.val()); });
				self.bind('blur.form.validation', function() { $.fn.form.liveValidate(o, self, item, self.val()); });
				self.bind('change.form.validation', function() { $.fn.form.liveValidate(o, self, item, self.val()); });
				//self.bind('click.form.validation', function() { $.fn.form.liveValidate(o, self, item, self.val()); });				
				//if(self.val() != '' && !self[0].empty ) $.fn.form.liveValidate(o, self, item, self.val());
				
				setTimeout(function() {
					if( self.next().is('.mceEditor') ) {	
						
						tiny  = self.next().find('iframe').contents()
						
						if(self.val() == '' || self[0].empty ) {
							tiny.find('body').html('');
							self[0].empty = false;
						}
						
						tiny.bind('keyup.form.validation', function() { $.fn.form.liveValidate(o, self, item, self.tinymce().getContent()); });
						tiny.bind('blur.form.validation', function() { $.fn.form.liveValidate(o, self, item, self.tinymce().getContent()); });
						tiny.bind('change.form.validation', function() { $.fn.form.liveValidate(o, self, item, self.tinymce().getContent()); });
						//tiny.bind('click.form.validation', function() { $.fn.form.liveValidate(o, self, item, self.tinymce().getContent()); });
					}
				}, 1000);
			}
		});
	};
	$.fn.form.liveValidate = function(o, input, item, val, errors) {
		errors = false;
		item.removeClass(o.errorClass).removeClass(o.validClass).find("."+o.infoClass).html('');
		var empty = val == '' || input[0].empty
			
		if( input[0].validation['required'] && empty ) errors = 'Ce champ ne peut être vide.';
		
		else if (!empty ) {
			
		
			if(  input[0].validation['e-mail'] && !val.match(/^([a-zA-Z+0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/) ) 
				errors = 'Ce champ doit être un e-mail valide.';
			
			/*else if( input[0].validation['date'] && val.match(/[0-9]/) ) 
				if( input[0].validation['blocker'] ) input.val(  val.replace(/[0-9]/g, '') )
				else errors = 'Ce champ ne doit pas contenir de chiffres.';*/
			
			else if( input[0].validation['alphabetic'] && val.match(/[0-9]/) ) 
				if( input[0].validation['blocker'] ) input.val(  val.replace(/[0-9]/g, '') )
				else errors = 'Ce champ ne doit pas contenir de chiffres.';
			
			else if( input[0].validation['numeric'] && val.match(/[^0-9]/) ) 
				if( input[0].validation['blocker'] ) {
					var newval = parseInt(val.replace(/[^0-9]/, ''))
					input.val( isNaN( newval ) ? 0 : newval )
				}
				else errors = 'Ce champ doit être numérique.';
			
			else if( input[0].validation['datemin'] ) {					
				// Date FR				
				var day = val.substring(0,2);
				var month = val.substring(3,5);
				var year = val.substring(6,10);
				var date = new Date(month+'/'+day+'/'+year)				
				var datemin = input[0].validation['datemin'][1] ? new Date(input[0].validation['datemin'][1]).toLocaleString() : new Date()
				if( date < datemin ) errors = 'Cette date doit être supérieure à '+datemin.toLocaleString();
			}
			
			else if( input[0].validation['charmax'] && val.length > input[0].validation['charmax'][1] ) 
				if( input[0].validation['blocker'] ) input.val( val.substring(0, input[0].validation['charmax'][1] ) )
				else errors = 'Ce champ doit contenir '+input[0].validation['charmax'][1]+' caractères maximum.';
			
			else if( input[0].validation['charmin'] && val.length < input[0].validation['charmin'][1] ) 
				if( input[0].validation['blocker'] ) input.val( val.substring(0, input[0].validation['charmin'][1] ) )
				else errors = 'Ce champ doit contenir '+input[0].validation['charmin'][1]+' caractères minimum.';
			
			else if( input[0].validation['charfix'] && val.length != input[0].validation['charfix'][1] ) 
				if( input[0].validation['blocker'] ) input.val( val.substring(0, input[0].validation['charfix'][1] ) )
				else errors = 'Ce champ doit contenir '+input[0].validation['charfix'][1]+' caractères.';
			
			else if( input[0].validation['phone'] && 
					(!val.match(/^(01|02|03|04|05|06|08|09)[ \.\-]?[0-9]{2}[ \.\-]?[0-9]{2}[ \.\-]?[0-9]{2}[ \.\-]?[0-9]{2}$/) &&
					!val.match(/^(\(\+[0-9]{2}\))[ \.\-]?[0-9][ \.\-]?[0-9]{2}[ \.\-]?[0-9]{2}[ \.\-]?[0-9]{2}[ \.\-]?[0-9]{2}$/)) ) 
				if( input[0].validation['blocker'] ) input.val( val.substring(0, 10 ) )
				else errors = 'Ce champ doit être un numéro de téléphone valide.';
			
			else if( input[0].validation['zipcode'] && 
					(!val.match(/^[0-9]{5}$/)) ) 
				errors = 'Ce champ doit être un code postal valide.';
			
			else if( input[0].validation['unique'] ) {
				o.form.find(input[0].tagName).not(input).each(function() {
					if($(this).val() == val) errors = 'Ce champ doit être unique.';
				})
			}				
		}
		
		if(errors) { 
			if(!input[0].validation_error) {
				input[0].validation_error = true;
				o.errors_count += 1;
			}
			item.addClass(o.errorClass).find("."+o.infoClass).html(errors);
		}
		else if(!empty) {
			if(input[0].validation_error) {
				input[0].validation_error = false;
				o.errors_count -= 1;
			}
			item.addClass(o.validClass).find("."+o.infoClass).html('');	
		}
		
	}
	$.fn.form.enhance.emptytest = function(e) 
	{					
		e.input = e.input ? e.input : $(this);
		
		// try for IE8 bug (e.input[0] is None sometimes, fuck IE)
		try {
			e.input[0].empty = jQuery.trim(e.input.val()) == '' || (e.type.match(/focus|blur/) && e.input[0].empty);
		
			if( e.input[0].empty )
			{
				e.input.addClass('empty');			
				if(e.type.match(/^(blur|focusout)$/) && e.input.attr('title')) { $(e.target).trigger("form.field.prevalue"); e.input.val( e.input.attr('title') ); }
				else if(e.type.match(/^focus(in)?$/)) { $(e.target).trigger("form.field.empty"); e.input.val(''); }
			}
			else {
				$(e.target).trigger("form.field.filled");
				e.input.removeClass('empty');
			}
		} catch(e) {}
	}
	$.fn.form.enhance.submit = function() {
		$(this).find('input:text,textarea,select').each(function(){ if(this.empty) this.value = ''; });
	}
	$.fn.form({ 
		register : 'default'
	});
	
})(jQuery);


(function($){
	$.fn.form_error = function( data, o ) 
	{
		o = {	
			validationItem: '.field',	
			infoClass:  	"info",
			errorClass: 	"error",
			validClass: 	"valid",
			extraUrl: 	 	""
		};
		
		this
			.find( "." + o.errorClass )
			.removeClass( o.errorClass )
			.find( "."+o.infoClass )
			.html( "" );
		
		var result = null;
		
		if( typeof data == 'object' )
		{
			result = data;
		}
		else if( data.replace(/^\s+/g,'').replace(/\s+$/g,'').charAt(0)=="{" )
		{
			result = window[ "eval" ]( "(" + data + ")" );
		}		
		
		if( result )
		{
			for( var i in result ) 
			{
				var name = i.replace(/\[/g,"\\[").replace(/\]/g,"\\]");
				console.log( name )
				this
					.find( name )
					.addClass(o.errorClass)
					.find( "." + o.infoClass )
						.html( data[ i ] );
			}			
		}
		return this;
		
	};
	
})(jQuery);



