
/* Validate.js, version 1.0.2
*  Package to validate various data :
*  isEqual
*  hasValidChars
*  isSimpleIP
*  isAlphaLatin
*  isNotEmpty
*  isIntegerInRange
*  isNum
*  isEMailAddr
*  isZipCode
*  isDate
*  isMD5
*  isURL
*  isGuid
*  isISBN
*  isSSN
*  isDecimal
*  isplatform
*  addRules
*  Apply
/*--------------------------------------------------------------------------*/
var Class = {
	create: function() {
		return function() {
			this.initialize.apply(this, arguments);
		}
	}
}

function getValue(s){
	if ($(s).getValue){
		return $(s).getValue();
	}else{
		//nothing available
		return '';
	}
}

var Validate = Class.create();
Validate.prototype = {
	/*--------------------------------------------------------------------------*/
	initialize:function(tipOptions){
		this.error_array = []
		this.rules_array = [];
		this.tipOptions = tipOptions;
		this.e = true;
	},
	/*--------------------------------------------------------------------------*/
	isEqual:function(string1, string2){
		if(string1 == string2) return true;
		else return false;
	},
	/*--------------------------------------------------------------------------*/
	hasValidChars:function(s, characters, caseSensitive){
		function valescapeSpecials(s){
			return s.replace(new RegExp("([\\\\-])", "g"), "\\$1");
		}
		return new RegExp("^[" + valescapeSpecials(characters) + "]+$",(!caseSensitive ? "i" : "")).test(s);
	},
	/*--------------------------------------------------------------------------*/
	isSimpleIP:function(ip){
		ipRegExp = /^(([0-2]*[0-9]+[0-9]+)\.([0-2]*[0-9]+[0-9]+)\.([0-2]*[0-9]+[0-9]+)\.([0-2]*[0-9]+[0-9]+))$/
		return ipRegExp.test(ip);
	},
	/*--------------------------------------------------------------------------*/
	isAlphaLatin:function(string){
		alphaRegExp = /^[0-9a-z]+$/i
		return alphaRegExp.test(string);
	},
	/*--------------------------------------------------------------------------*/
	isNotEmpty:function (string){
		return /\S/.test(string);
	},
	/*--------------------------------------------------------------------------*/
	isEmpty:function(s){
		return !/\S/.test(s);
	},
	/*--------------------------------------------------------------------------*/
	isIntegerInRange:function(n,Nmin,Nmax){
		var num = Number(n);
		if(isNaN(num)){
			return false;
		}
		if(num != Math.round(num)){
			return false;
		}
		return (num >= Nmin && num <= Nmax);
	},
	/*--------------------------------------------------------------------------*/
	isNum:function(number){
		numRegExp = /^[0-9]+$/
		return numRegExp.test(number);
	},
	/*--------------------------------------------------------------------------*/
	isEMailAddr:function(string){
		emailRegExp = /^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.([a-z]){2,4})$/
		return emailRegExp.test(string);
	},
	/*--------------------------------------------------------------------------*/
	isZipCode:function(zipcode,country){
		if(!zipcode) return false;
		
		if(!country){
			try{
				console.warn("Country not provided. Allowing any zip code format");
			}catch(e){
			}

			return true;
		}
		
		//is this a function?
		if (typeof(country) == 'function'){
			country = country();
		}
		
		switch(country){
			case'US': zpcRegExp = /^\d{5}$|^\d{5}-\d{4}$/; break;
			case'MA': zpcRegExp = /^\d{5}$/; break;
			case'CA': zpcRegExp = /^[A-Z]\d[A-Z] \d[A-Z]\d$/; break;
			case'DU': zpcRegExp = /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/; break;
			case'FR': zpcRegExp = /^\d{5}$/; break;
			case'MC':zpcRegExp = /^(MC-)\d{5}$/; break;
			default:
				try{
					console.warn("country " + country + " unknown, allowing any zipcode");
				}catch(e){
				}

				return true;
				break;
		}
		return zpcRegExp.test(zipcode);
	},
	/*--------------------------------------------------------------------------*/
	isDate:function(date,format){
		if(!date) return false;
		if(!format) format = 'FR';
		
		switch(format){
			case'FR': RegExpformat = /^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/([2][0]|[1][9])\d{2})$/; break;
			case'US': RegExpformat = /^([2][0]|[1][9])\d{2}\-([0]\d|[1][0-2])\-([0-2]\d|[3][0-1])$/; break;
			case'SHORTFR': RegExpformat = /^([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/\d{2}$/; break;
			case'SHORTUS': RegExpformat = /^\d{2}\-([0]\d|[1][0-2])\-([0-2]\d|[3][0-1])$/; break;
			case'dd MMM yyyy':RegExpformat = /^([0-2]\d|[3][0-1])\s(Jan(vier)?|F√©v(rier)?|Mars|Avr(il)?|Mai|Juin|Juil(let)?|Aout|Sep(tembre)?|Oct(obre)?|Nov(ember)?|Dec(embre)?)\s([2][0]|[1][19])\d{2}$/; break;
			case'MMM dd, yyyy':RegExpformat = /^(J(anuary|u(ne|ly))|February|Ma(rch|y)|A(pril|ugust)|(((Sept|Nov|Dec)em)|Octo)ber)\s([0-2]\d|[3][0-1])\,\s([2][0]|[1][9])\d{2}$/; break;
		}
		
		return RegExpformat.test(date);
	},
	/*--------------------------------------------------------------------------*/
	isMD5:function(string){
		if(!string) return false;
		md5RegExp = /^[a-f0-9]{32}$/;
		return md5RegExp.test(string);
	},
	/*--------------------------------------------------------------------------*/
	isURL:function(string){
		if(!string) return false;
		string = string.toLowerCase();
		urlRegExp = /^(((ht|f)tp(s?))\:\/\/)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/
		return urlRegExp.test(string);
	},
	/*--------------------------------------------------------------------------*/
	isGuid:function(guid){//guid format : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx or xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
		if(!guid) return false;
		GuidRegExp = /^[{|\(]?[0-9a-fA-F]{8}[-]?([0-9a-fA-F]{4}[-]?){3}[0-9a-fA-F]{12}[\)|}]?$/
		return GuidRegExp.test(guid);
	},
	/*--------------------------------------------------------------------------*/
	isISBN:function(number){
		if(!number) return false;
		ISBNRegExp = /ISBN\x20(?=.{13}$)\d{1,5}([- ])\d{1,7}\1\d{1,6}\1(\d|X)$/
		return ISBNRegExp.test(number);
	},
	/*--------------------------------------------------------------------------*/
	isSSN:function(number){//Social Security Number format : NNN-NN-NNNN
		if(!number) return false;
		ssnRegExp = /^\d{3}-\d{2}-\d{4}$/
		return ssnRegExp.test(number);
	},
	/*--------------------------------------------------------------------------*/
	isDecimal:function(number){// positive or negative decimal
		if(!number) return false;
		decimalRegExp = /^-?(0|[1-9]{1}\d{0,})(\.(\d{1}\d{0,}))?$/
		return decimalRegExp.test(number);
	},
	/*--------------------------------------------------------------------------*/
	isplatform:function(platform){
		//win, mac, nix
		if(!platform) return false;
		var os;
		winRegExp = /\win/i
		if(winRegExp.test(window.navigator.platform)) os = 'win';
		
		macRegExp = /\mac/i
		if(macRegExp.test(window.navigator.platform)) os = 'mac';
		
		nixRegExp = /\unix|\linux|\sun/i
		if(nixRegExp.test(window.navigator.platform)) os = 'nix';
		
		if(platform == os) return true;
		else return false;
	},
	/*--------------------------------------------------------------------------*/
	getValue:function(id){
		if ($(id).getValue){
			return $(id).getValue();
		}
	},
	/*--------------------------------------------------------------------------*/
	
	/*--------------------------------------------------------------------------*/
	addRules:function(rules,tipHookTarget){
		
		//check tooltip exists
		var tmpdiv = new Element('div').update(rules.defaultMessage);
		tmpdiv.id = rules.id + '_errormsg';
		
		if (!$(rules.id)){
			try{
				console.warn(rules.id + ' not available');
			}catch(e){
			}
		}else{
			//composite options
			tipOpts = this.tipOptions;
			if (!tipHookTarget){
			//	tipOpts.target = tipHookTarget;
			}else{
			//	tipOpts.target = rules.id;
			}
			
			if (rules.tipOptions){
				//override any specific tip options with those provided
				tipOpts = new Hash(tipOpts);
				tipOpts = tipOpts.merge(rules.tipOptions);
				
				//get a normallized obj
				tipOpts = tipOpts.toObject();
			}
			

			if (!rules.tipTargetID){
				//set specific tip target ID
				rules.tipTargetID = rules.id;
			}
			
			//create new tip
			new Tip(rules.tipTargetID, tmpdiv, tipOpts);
			
			//monitor for mouseover...
			$(rules.id).observe('change',function(e){
				this.Apply('prototip',Event.element(e).id);
			}.bind(this));
			
			this.rules_array.push(rules);
		}
	},
	/*--------------------------------------------------------------------------*/
	check:function(specificelement){
		this.error_array = [];
		this.e = true;
		for(var i=0;i<this.rules_array.length;i++){
			//is there a element requirement?
			//if so, only process that element
			if (specificelement){
				if (specificelement != this.rules_array[i].id){
					continue;
				}
			}
			
			switch(this.rules_array[i].option){
				/*--------------------------------------------------------------------------*/
				case'ValidChars':
					if(!this.hasValidChars(getValue(this.rules_array[i].id),this.rules_array[i].characters,false)){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				case'AlphaLatin':
					if (this.isAlphaLatin(getValue(this.rules_array[i].id))){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				case'isNotEmpty':
					if (!this.isNotEmpty(getValue(this.rules_array[i].id))){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
					break;
				/*--------------------------------------------------------------------------*/
				case'required':
					if (this.isEmpty(getValue(this.rules_array[i].id))){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				case'integerRange':
					if (!this.isIntegerInRange(getValue(this.rules_array[i].id),this.rules_array[i].Min,this.rules_array[i].Max)){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				case'Number':
					if (!this.isNum(getValue(this.rules_array[i].id))){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				case'email':
					if (!this.isEMailAddr(getValue(this.rules_array[i].id))){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				case'zipCode':
				case'isZipCode':
					if (!this.isZipCode(getValue(this.rules_array[i].id),this.rules_array[i].country)){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				case'date':
					if(!this.isDate(getValue(this.rules_array[i].id),this.rules_array[i].format)){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				case'url':
					if(!this.isURL(getValue(this.rules_array[i].id))){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				case'Decimal':
					if(!this.isDecimal(getValue(this.rules_array[i].id))){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				case'isEqual':
					if(!this.isEqual(getValue(this.rules_array[i].id),getValue(this.rules_array[i].to))){
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
				break;
				/*--------------------------------------------------------------------------*/
				/*--------------------------------------------------------------------------*/
				case'function':
					var vfunc = this.rules_array[i].valfunction;
					var funcresult = vfunc.call(
								$(this.rules_array[i].id),
								$(this.rules_array[i].id),
								getValue(this.rules_array[i].id),
								this.rules_array[i].defaultMessage
							);
							
					if (funcresult.hadError){
						this.rules_array[i].msg = funcresult.msg;
						this.rules_array[i].formattedValue = funcresult.formattedValue;
						this.error_array.push(this.rules_array[i]);
						this.e = false;
					}
					break;
					/*--------------------------------------------------------------------------*/
				default:
					//problem
					$(this.rules_array[i].id).setStyle({backgroundColor: 'red'});
					break;
			}
		}
	},
	/*--------------------------------------------------------------------------*/
	Apply:function(el,specificelement,successFunction){
		this.check(specificelement);
		if(this.e){
			if (!specificelement){
				Tips.hideAll();
				if (successFunction){
					successFunction();
				}
				return true;
			}else{
				if ($(specificelement)){
					//loop through all elements, find the correct one
					for(var i=0;i<this.rules_array.length;i++){
						if ($(specificelement).id == this.rules_array[i].id){
							$(this.rules_array[i].tipTargetID).prototip.hide();
						}					
					}
				}
				return true;
			}
			
		}else{
			
			if(!el){
				alert(this.error_array.toString().replace(/\,/gi,"\n"));
			}else if(el == 'prototip'){
				//display prototype tips
				firstError = '';
				
				for(var j=0;j<this.rules_array.length;j++){
					var hadErrorInItem = false;
					
					for(var i=0;i<this.error_array.length;i++){

						if (this.rules_array[j].id == this.error_array[i].id){
							
							//error
							hadErrorInItem = true;
							
							//update tooltip content
							$(this.error_array[i].tipTargetID).prototip.show();
							if (typeof(this.error_array[i].msg) != 'undefined'){
								if ($(this.error_array[i].id + '_errormsg')){
									$(this.error_array[i].id + '_errormsg').update(this.error_array[i].msg);
								}
							}else{
								if ($(this.error_array[i].id + '_errormsg')){
									$(this.error_array[i].id + '_errormsg').update(this.error_array[i].defaultMessage);
								}
							}
							
							//store first item
							if (firstError == ''){
								firstError = this.error_array[i].tipTargetID;
							}
						}else{
							//wrong item
						}
					}
					
					//if we didn't encounter an error, hide this item..
					if (!hadErrorInItem){
						//unless we're processing a specific item of course..
						if ((specificelement) && (specificelement != this.rules_array[j].id)){
							continue;
						}
						$(this.rules_array[j].tipTargetID).prototip.hide();
					}
				}
				
				if (firstError != ''){
					var belowBox = (($(firstError).cumulativeOffset().top) < (document.viewport.getScrollOffsets()[1]));
					var aboveBox = (($(firstError).cumulativeOffset().top) > (document.viewport.getScrollOffsets()[1] + document.viewport.getDimensions().height));
					
					if (aboveBox || belowBox){
						  new Effect.Tween(null, document.viewport.getScrollOffsets().top, $(firstError).cumulativeOffset().top, function(p){ scrollTo(0,p) });
					}
				}
			}else{
				document.getElementById(el).innerHTML = this.error_array.toString().replace(/\,/gi,"<br/>");
			}
			return false;
		}
	}
	/*--------------------------------------------------------------------------*/
}

/**prototip support */
