// JavaScript Document
// Author : Christophe Iaïchouchen AKA saturnino
// Thanks : jquery tutorial


(function($) {
    
    /*
    Validation Singleton
    */
    var Validation = function() {
        
       
		var REGEX_BLANK = /^\s*$/;
		var REGEX_DAY = /^(0?[1-9]|[1-2][0-9]|3[01])$/;
		var REGEX_MONTH = /^(0?[1-9]|1[0-2])$/;
		var REGEX_MAIL = /^([a-zA-Z0-9_-])+([.]?[a-zA-Z0-9_-]{1,})*@([a-zA-Z0-9-_]{2,}[.])+[a-zA-Z]{2,4}$/;
		// Les multiples groupes vont nous découper l'ID tout seuls...
		var REGEX_TYPED_FIELD = /_(Int|Dbl|Date|Mail|Disclaimer|Tel)(_([0-9.]+))?(_([0-9.]+))?$/;
		var REGEX_YEAR = /^[0-9]{2,4}$/;
	
		var MSG_BLANK = ' est vide.';
		var MSG_NOT_A_MAIL = ' n\'est pas un mail valide.';
		var MSG_NOT_A_DATE = ' n\'est pas une date.';
		var MSG_NOT_A_DOUBLE = ' n\'est pas un nombre.';
		var MSG_NOT_AN_INTEGER = ' n\'est pas un nombre entier.';
		var MSG_TOO_LOW = ' est trop petit(e).';
		var MSG_TOO_HIGH = ' est trop grand(e).';	
		
		
		var rules = {
            
		    disclaimer : {
               check: function(value) {
                   //alert(value);
                   if (value == disclaimer)
							return false;        
                   return true;
               },
               msg : "Ce champs est obligatoire."
            },
			email : {
               check: function(value) {
                   
                   if (!value.match(/^([a-zA-Z0-9_-])+([.]?[a-zA-Z0-9_-]{1,})*@([a-zA-Z0-9-_]{2,}[.])+[a-zA-Z]{2,4}$/))
							return false;        
                   return true;
               },
               msg : "Entrez une adresse valide."
            },
			date : {
               check: function(value) {
                   
                  	var comps = value.split('/');
					if (3 != comps.length || !comps[0].match(/^(0?[1-9]|[1-2][0-9]|3[01])$/) ||
						!comps[1].match(/^(0?[1-9]|1[0-2])$/) ||
						!comps[2].match(/^[0-9]{2,4}$/))
						return false;
					return true;
               },
               msg : "Entrez une date valide."
            },
            url : {

               check : function(value) {

                   if(value)
                       return testPattern(value,"https?://(.+\.)+.{2,4}(/.*)?");
                   return true;
               },
               msg : "Entrez une URL valide."
            },
			tel : {

               check : function(value) {

                   try {
						val = parseInt(value, 10);
						if (String(val) != value)
							throw val;
						} catch (e) {
							return false;
						}
                   return true;
               },
               msg : "Entrez téléphone valide."
            },
            required : {
                
               check: function(value) {
					var REGEX = /^\s*$/;
					//alert('check '+value.match(REGEX));
                   if(!value.match(REGEX))
                       return true;
                   else
                       return false;
               },
               msg : "Ce champs est obligatoire."
            },
			groupRequired : {
                
               check: function(value, groupName) {
					var REGEX = /^\s*$/;
                   if(!value.match(REGEX))
                       return true;
                   else
                       return false;
               },
               msg : "Ce champs est obligatoire."
            },
			typed : {
                
               check: function(value) {
				  alert('check typed '+value);
				     // Valeurs par défaut pour les bornes
					min = min || Number.NEGATIVE_INFINITY;
					max = max || Number.POSITIVE_INFINITY;
					var val;
					if ('Int' == type) {
						try {
							val = parseInt(value, 10);
						if (String(val) != value)
							throw val;
						} catch (e) {
							return MSG_NOT_AN_INTEGER;
						}
					}
					if ('Mail' == type) {
						if (!value.match(REGEX_MAIL))
							return MSG_NOT_A_MAIL;        
					}
					if ('Disclaimer' == type) {
						/*
						alert(value);	
						return MSG_NOT_A_MAIL;       
						*/
					}
					if ('Dbl' == type) {
						try {
							val = parseFloat(value);
						if (String(val) != value)
							throw val;
						} catch (e) {
							return MSG_NOT_A_DOUBLE;
						}
					}
					if ('Int' == type || 'Dbl' == type) {
						if (val < min)
							return MSG_TOO_LOW;
						if (val > max)
							return MSG_TOO_HIGH;
					}
					if ('Date' == type) {
						var comps = value.split('/');
						if (3 != comps.length || !comps[0].match(REGEX_DAY) ||
							!comps[1].match(REGEX_MONTH) ||
							!comps[2].match(REGEX_YEAR))
							return MSG_NOT_A_DATE;
					}
					return null;
               },
               msg : "Ce champs est typé."

            },
			ok : {
                
               check: function(value) {                   
                       return true;
                  
               },
               msg : "OK."
            }
        }
        var testPattern = function(value, pattern) {

            var regExp = new RegExp("^"+pattern+"$","");
            return regExp.test(value);
        }
        return {
            
            addRule : function(name, rule) {

                rules[name] = rule;
            },
            getRule : function(name) {
                if ( name.match(/_Req/) ) {// champs obligatoire
					return rules['required'];
				}else{
					return rules['ok'];
				}
            },
			getTypedRule : function(name) {				
				
				var match = name.match(/_(Int|Dbl|Date|Mail|Url|Disclaimer|Tel)(_([0-9.]+))?(_([0-9.]+))?$/);				
				
				if (match) {
					var type = match[1];	
					
					if ('Mail' == type) {
						return rules['email'];
					}
					if ('Date' == type) {
						return rules['date'];					
					}
					if ('Url' == type) {						
						return rules['url'];						
					}					
					if ('Disclaimer' == type) {
						return rules['disclaimer'];					
					}
					if ('Tel' == type) {
						return rules['tel'];					
					}
					
					
					return rules['ok'];
				}				
				
				return rules['ok'];
			 }
			,
			getGroupRule : function(name) {
                var match 				= name.match(/_(Int|Dbl|Date|Mail|Url|Tel)(_([0-9.]+))?(_([0-9.]+))?$/);
				var tab 				= name.split('_');
				var index 				= tab[tab.length-1];
				var REGEX_EMPTY_FIELD 	= /^\s*$/;
				var value;
				var cpt					= 0;
				var nb_filled_fields	= 0;
				
				//est-ce que tous champs sont vides?
				$('#reqGroup_GName_'+index).find(":input[type!='submit'],:input[type!='image'], textarea").each(function() {					 
					
					value = $(this).val();
					
					if(!value.match(REGEX_EMPTY_FIELD))
						nb_filled_fields++;
				});
			
				if(nb_filled_fields>0)
				{
					if ( name.match(/_ReqGroup/) ) {// champs obligatoire
						return rules['required'];						
					}else{
						return rules['ok'];
					}
				}else{
					return rules['ok'];
				}
            },
			getGroupTypedRule : function(name) {

				var match 				= name.match(/_(Int|Dbl|Date|Mail|Url|Tel)(_([0-9.]+))?(_([0-9.]+))?$/);
				var tab 				= name.split('_');
				var index 				= tab[tab.length-1];
				var REGEX_EMPTY_FIELD 	= /^\s*$/;
				var value;
				var cpt					= 0;
				var nb_filled_fields	= 0;
				
				//est-ce que tous champs sont vides?
				$('#reqGroup_GName_'+index).find(":input[type!='submit'],:input[type!='image'], textarea").each(function() {					 
					
					value = $(this).val();
					
					if(!value.match(REGEX_EMPTY_FIELD))
						nb_filled_fields++;
				});
			
				if(nb_filled_fields>0)
				{
					return $.Validation.getTypedRule(name);
				}else{
					return rules['ok'];
				}
			}
        }
    }
    
    /* 
    Form factory 
    */
    var Form = function(form) {
        
        var fields = [];
		var REGEX_AUTO_FIELD = /^[^_]+(_Req|_ReqGroup)?(_(Int|Dbl|Date|Mail|Url|Disclaimer|Tel|ReqGroup|GName)(_[0-9.]+){0,2})?$/;
		
		var disclaimer = 'Votre note doit se conformer à la législation en vigueur en France. Sont interdits :\n'; 

		disclaimer += '- l\'incitation à la haine raciale et à la discrimination\n'; 
		disclaimer += '- la négation des crimes contre l\'humanité et l\'apologie de crimes de guerre\n'; 
		disclaimer += '- la diffamation, ce qui porte atteinte à l\'honneur d\'une personne\n'; 
		disclaimer += '- l\'incitation au piratage informatique.\n\n'; 

		disclaimer += 'De plus, nos modérateurs se réservent le droit de supprimer un commentaire si celui-ci est jugé...\n'; 
		disclaimer += '... trop agressif\n'; 
		disclaimer += '... grossier\n'; 
		disclaimer += '... hors sujet\n\n'; 

		disclaimer += 'Toute allusion sexiste, homophobe ou raciste sera également effacée,\n'; 
		disclaimer += 'tout comme les messages publicitaires, les messages contenant des coordonnées privées, '; 
		disclaimer += 'une adresse internet, une adresse postale ou e-mail.';
			
		var rb		=	[];

        form.find(":input[type!='submit'],:input[type!='image'], textarea").each(function() {
			
			var id 		= 	$(this).attr("id");			
			var match 	= 	id.match(/_(Int|Dbl|Date|Mail|Url|Disclaimer|Tel)(_([0-9.]+))?(_([0-9.]+))?$/);			
			
			if(match){
								
				var type = match[1];		
				if ('Disclaimer' == type) {
					if($(this).val() =='')						
						$(this).attr("value", disclaimer); 	
				
					$(this).bind("click",function() {
						if( $(this).val() == disclaimer)
							$(this).attr("value", ''); 	
					});
				}
			}			

			if(id.match(REGEX_AUTO_FIELD)){
				fields.push(new Field(this));	
			}  
			
			if ( id.match(/_ReqGroup/) ) {// champs obligatoire groupé
				fields.push(new Field(this));				
			}  
			
			if($(this).attr("type") == "radio"){
				var name	= $(this).attr("name");
				if(!rb[name]){
					rb[name] = true;
					fields.push(new Field(this));	
				}
			}

        });
        this.fields = fields;
		
		this.beenSubmitted = false;	
		
		

    }
    Form.prototype = {
		
		getBeenSubmitted : function() {			
            
			return this.beenSubmitted;
        },
		setBeenSubmitted : function( status ) {			
            
			this.beenSubmitted = status;
        },
        validate : function() {			
            
			for(field in this.fields) { 
				var type = this.fields[field].field.attr('type');
				var name = this.fields[field].field.attr('name');
				if(type != "radio")
					this.fields[field].validate();	

            }
        },
        isValid : function() {
            //alert('isValid');
            for(field in this.fields) {
				
				var type = this.fields[field].field.attr('type');
				var name = this.fields[field].field.attr('name');
				
				if(type == "radio" || type == "checkbox"){
					//alert('**ISVALIDE** '+name+'=>'+!$("input[name="+name+"]:checked").val());					
					if(!$("input[name="+name+"]:checked").val())
					{
						alert('Veuillez valider le consentement !');
						return false;
					}
						
				}else{
					if(!this.fields[field].valid) {            
						this.fields[field].field.focus();
						return false;
					}
				}                
            }
            return true;
        },
		// pre-submit callback 
		showRequest : function (formData, jqForm, options) { 
			// formData is an array; here we use $.param to convert it to a string to display it 
			// but the form plugin does this for you automatically when it submits the data 
			var queryString = jQuery.param(formData); 
		 
			// jqForm is a jQuery object encapsulating the form element.  To access the 
			// DOM element for the form do this: 
			// var formElement = jqForm[0]; 
		 
			//alert('About to submit: \n\n' + queryString); 
		 
			// here we could return false to prevent the form from being submitted; 
			// returning anything other than false will allow the form submit to continue 
			return true; 
		},		 
		// post-submit callback 
		showResponse : function (responseText, statusText)  { 
			// for normal html responses, the first argument to the success callback 
			// is the XMLHttpRequest object's responseText property 
		 
			// if the ajaxSubmit method was passed an Options Object with the dataType 
			// property set to 'xml' then the first argument to the success callback 
			// is the XMLHttpRequest object's responseXML property 
		 
			// if the ajaxSubmit method was passed an Options Object with the dataType 
			// property set to 'json' then the first argument to the success callback 
			// is the json data object returned by the server 
			/*
			alert( $(this).attr('id')+' status: ' + statusText + '\n\nresponseText: \n' + responseText + 
				'\n\nThe output div should have already been updated with the responseText.'); 
			*/
					
			var output = $(this);
			var formID = output.parent().attr('id');
			var captchaUrl = $('#'+formID+'Captcha').attr('src');		
			$('#'+formID+'Captcha').attr('src', captchaUrl+'&amp;r='+Math.random() );


			output.css('display','block');
			if(output.attr('class') == 'entry')
			{
				$.scrollTo( '#container', { speed:500} ); 
				$(output).html(responseText)  
					.hide()  
					.fadeIn(1500, function() {  
					//$('#output').append("<img id='checkmark' src='images/check.png' />"); 
				  });  
			}else{
				$.scrollTo( $(this), { speed:1000} ); 
				//$(this).effect("highlight", {}, 3000);	
				$(this).hide()  
					.fadeIn(1500, function() {  
					//$('#output').append("<img id='checkmark' src='images/check.png' />"); 
				  });  
			}
			
			
			
			var validator = $.data($("div").get(0), 'validator');
			validator.setBeenSubmitted(false);
			
				  
		} 
    }
    
    /* 
    Field factory 
    */
    var Field = function(field) {
        this.field = $(field);
        this.valid = false;
        this.attach("change");
    }
    Field.prototype = {
        
        attach : function(event) {
        
            var obj = this;
            if(event == "change") {
                obj.field.bind("change",function() {
                    return obj.validate();
                });
            }
            if(event == "keyup") {
                obj.field.bind("keyup",function(e) {
                    return obj.validate();
                });
            }
			
        },
        validate : function() {
            
            var obj = this,
                field = obj.field,
                errorClass = "errorlist",
                errorlist = $(document.createElement("ul")).addClass(errorClass),
				types = field.attr("id"),
                container = field.parent(),
                errors = []; 
				isGroupField = ( types.match(/_GName/) )? true : false;
				
				//alert(isGroupField);
            
            field.next(".errorlist").remove();
			
			//alert(types);
			// Champ requis ?
			var rule = $.Validation.getRule(types);
			if(!rule.check(field.val()) && isGroupField === false) {
				container.addClass("error");
				errors.push(rule.msg);
			}
			
			// Champ typé ?
			rule = $.Validation.getTypedRule(types);
			if(!rule.check(field.val()) && isGroupField === false) {
				container.addClass("error");
				errors.push(rule.msg);
			}
			
			// Champ typé groupé?
			if(isGroupField)
			{
			//	alert('Champ typé groupé '+types);
				
				rule = $.Validation.getGroupRule(types);
				if(!rule.check(field.val()) && isGroupField) {
					container.addClass("error");
					errors.push(rule.msg);
				}				
				
				rule = $.Validation.getGroupTypedRule(types);
				if(!rule.check(field.val()) && isGroupField) {
					container.addClass("error");
					errors.push(rule.msg);
				}
			}
			
			
			
            if(errors.length) {

                obj.field.unbind("keyup")
                obj.attach("keyup");
                field.after(errorlist.empty());
                for(error in errors) {
                
                    errorlist.append("<li>"+ errors[error] +"</li>");        
                }
                obj.valid = false;
            } 
            else {
                errorlist.remove();
                container.removeClass("error");
                obj.valid = true;
            }
        }
    }
    
    /* 
    Validation extends jQuery prototype
    */
    $.extend($.fn, {
        
        validation : function() {
            var validator = new Form($(this));
            $.data($(this)[0], 'validator', validator);				

            $(this).bind("submit", function(e) {
                validator.validate();	
				
				var ajaxForm 	= ($('#'+$(this).attr('id')+'AjaxForm').attr('value') == 'true')? true : false;				
				
			
				if( document.getElementById($(this).attr('id')+'Output') )
				{
					var output 		= '#'+$(this).attr('id')+'Output';	
					$(output).empty();
				}
				
				
                if(!validator.isValid()) {
                    e.preventDefault();
                }else if( !ajaxForm ) {
	                   return true;
                }else{				
					
					var clearForm 	= ($('#'+$(this).attr('id')+'ClearForm').attr('value') == 'true')? true : false;
					
					
				
					if($(this).attr('id') == 'gameForm')
						output = '.entry';
					
					// prevent double submit.
					if( !validator.getBeenSubmitted()){
						validator.setBeenSubmitted(true);
					}else{		
						e.preventDefault();					
						return false;
					}
					
					
					
					// we store validator datas to change beensubmitted after succes.
					$.data($("div").get(0), 'validator', validator);
					
					var options = { 
						target			:  output,   // target element(s) to be updated with server response 
						beforeSubmit	:  validator.showRequest,  // pre-submit callback 
						success			:  validator.showResponse,  // post-submit callback 
				 
						// other available options: 
						//url:       url         // override for form's 'action' attribute 
						//type:      type        // 'get' or 'post', override for form's 'method' attribute 
						//dataType:  null        // 'xml', 'script', or 'json' (expected server response type) 
						clearForm: clearForm     // clear all form fields after successful submit 
						//resetForm: clearForm           // reset the form after successful submit // desactive le formulaire
				 
						// $.ajax options can be used here too, for example: 
						//timeout:   3000 
					}; 
					 // inside event callbacks 'this' is the DOM element so we first 
					// wrap it in a jQuery object and then invoke ajaxSubmit 
					$(this).ajaxSubmit(options); 
			 
					// !!! Important !!! 
					// always return false to prevent standard browser submit and page navigation 
					//return false; 
					
					e.preventDefault();					
					return false;
				}
            });
        },
        validate : function() {
            //alert('validate');
            var validator = $.data($(this)[0], 'validator');
            validator.validate();
            return validator.isValid();
            
        }
    });
    $.Validation = new Validation();
	
	
	
})(jQuery);
		
		