﻿/*
Script: Class.Binds.js
	Automagically binds specified methods in a class to the instance of the class.

	License:
		MIT-style license.

	Authors:
		Aaron Newton
*/

Class.Mutators.Binds = function(binds){
    return binds;
};

Class.Mutators.initialize = function(initialize){
	return function(){
		$splat(this.Binds).each(function(name){
			var original = this[name];
			if (original) this[name] = original.bind(this);
		}, this);
		return initialize.apply(this, arguments);
	};
};

/*
Script: Element.Forms.js
	Extends the Element native object to include methods useful in managing inputs.

	License:
		MIT-style license.

	Authors:
		Aaron Newton

*/

Element.implement({

	tidy: function(){
		this.set('value', this.get('value').tidy());
	},

	getTextInRange: function(start, end){
		return this.get('value').substring(start, end);
	},

	getSelectedText: function(){
		if (this.setSelectionRange) return this.getTextInRange(this.getSelectionStart(), this.getSelectionEnd());
		return document.selection.createRange().text;
	},

	getSelectedRange: function() {
		if ($defined(this.selectionStart)) return {start: this.selectionStart, end: this.selectionEnd};
		var pos = {start: 0, end: 0};
		var range = this.getDocument().selection.createRange();
		if (!range || range.parentElement() != this) return pos;
		var dup = range.duplicate();
		if (this.type == 'text') {
			pos.start = 0 - dup.moveStart('character', -100000);
			pos.end = pos.start + range.text.length;
		} else {
			var value = this.get('value');
			var offset = value.length - value.match(/[\n\r]*$/)[0].length;
			dup.moveToElementText(this);
			dup.setEndPoint('StartToEnd', range);
			pos.end = offset - dup.text.length;
			dup.setEndPoint('StartToStart', range);
			pos.start = offset - dup.text.length;
		}
		return pos;
	},

	getSelectionStart: function(){
		return this.getSelectedRange().start;
	},

	getSelectionEnd: function(){
		return this.getSelectedRange().end;
	},

	setCaretPosition: function(pos){
		if (pos == 'end') pos = this.get('value').length;
		this.selectRange(pos, pos);
		return this;
	},

	getCaretPosition: function(){
		return this.getSelectedRange().start;
	},

	selectRange: function(start, end){
		if (this.setSelectionRange) {
			this.focus();
			this.setSelectionRange(start, end);
		} else {
			var value = this.get('value');
			var diff = value.substr(start, end - start).replace(/\r/g, '').length;
			start = value.substr(0, start).replace(/\r/g, '').length;
			var range = this.createTextRange();
			range.collapse(true);
			range.moveEnd('character', start + diff);
			range.moveStart('character', start);
			range.select();
		}
		return this;
	},

	insertAtCursor: function(value, select){
		var pos = this.getSelectedRange();
		var text = this.get('value');
		this.set('value', text.substring(0, pos.start) + value + text.substring(pos.end, text.length));
		if ($pick(select, true)) this.selectRange(pos.start, pos.start + value.length);
		else this.setCaretPosition(pos.start + value.length);
		return this;
	},

	insertAroundCursor: function(options, select){
		options = $extend({
			before: '',
			defaultMiddle: '',
			after: ''
		}, options);
		var value = this.getSelectedText() || options.defaultMiddle;
		var pos = this.getSelectedRange();
		var text = this.get('value');
		if (pos.start == pos.end){
			this.set('value', text.substring(0, pos.start) + options.before + value + options.after + text.substring(pos.end, text.length));
			this.selectRange(pos.start + options.before.length, pos.end + options.before.length + value.length);
		} else {
			var current = text.substring(pos.start, pos.end);
			this.set('value', text.substring(0, pos.start) + options.before + current + options.after + text.substring(pos.end, text.length));
			var selStart = pos.start + options.before.length;
			if ($pick(select, true)) this.selectRange(selStart, selStart + current.length);
			else this.setCaretPosition(selStart + text.length);
		}
		return this;
	}

});

/*
Script: FormValidator.js
	A css-class based form validation system.

	License:
		MIT-style license.

	Authors:
		Aaron Newton
*/
var InputValidator = new Class({

	Implements: [Options],

	options: {
		errorMsg: 'Validation failed.',
		test: function(field){return true;}
	},

	initialize: function(className, options){
		this.setOptions(options);
		this.className = className;
	},

	test: function(field, props){
		//trace(this.getProps(field))
		if (document.id(field)) return this.options.test(document.id(field), props||this.getProps(field));
		else return false;
	},

	getError: function(field, props){
		var err = this.options.errorMsg;
		if ($type(err) == 'function') err = err(document.id(field), props||this.getProps(field));
		return err;
	},

	getProps: function(field){
		if (!document.id(field)) return {};
		return field.get('validatorProps');
	}

});

Element.Properties.validatorProps = {

	set: function(props){
		return this.eliminate('validatorProps').store('validatorProps', props);
	},

	get: function(props){
		if (props) this.set(props);
		if (this.retrieve('validatorProps')) return this.retrieve('validatorProps');
		if (this.getProperty('validatorProps')){
			try {
				this.store('validatorProps', JSON.decode(this.getProperty('validatorProps')));
			}catch(e){
				return {};
			}
		} else {
			var vals = this.get('class').split(' ').filter(function(cls){
				return cls.test(':');
			});
			if (!vals.length){
				this.store('validatorProps', {});
			} else {
				props = {};
				vals.each(function(cls){
					var split = cls.split(':');
					if (split[1]) {
						try {
							props[split[0]] = JSON.decode(split[1]);
						} catch(e) {}
					}
				});
				this.store('validatorProps', props);
			}
		}
		return this.retrieve('validatorProps');
	}

};

var FormValidator = new Class({

	Implements:[Options, Events],

	Binds: ['onSubmit'],

	options: {/*
		onFormValidate: $empty(isValid, form, event),
		onElementValidate: $empty(isValid, field, className, warn),
		onElementPass: $empty(field),
		onElementFail: $empty(field, validatorsFailed) */
		fieldSelectors: 'input, select, textarea',
		ignoreHidden: true,
		useTitles: false,
		evaluateOnSubmit: true,
		evaluateFieldsOnBlur: true,
		evaluateFieldsOnChange: true,
		serial: true,
		stopOnFailure: true,
		warningPrefix: function(){
			return FormValidator.getMsg('warningPrefix') || '';
		},
		errorPrefix: function(){
			return FormValidator.getMsg('errorPrefix') || '';
		}
	},

	initialize: function(form, options){
		this.setOptions(options);
		this.element = document.id(form);
		this.element.store('validator', this);
		this.warningPrefix = $lambda(this.options.warningPrefix)();
		this.errorPrefix = $lambda(this.options.errorPrefix)();
		if (this.options.evaluateOnSubmit) this.element.addEvent('submit', this.onSubmit);
		if (this.options.evaluateFieldsOnBlur || this.options.evaluateFieldsOnChange) this.watchFields(this.getFields());
	},

	toElement: function(){
		return this.element;
	},

	getFields: function(){
		return (this.fields = this.element.getElements(this.options.fieldSelectors));
	},

	watchFields: function(fields){
		fields.each(function(el){
			if (this.options.evaluateFieldsOnBlur)
				el.addEvent('blur', this.validationMonitor.pass([el, false], this));
			if (this.options.evaluateFieldsOnChange)
				el.addEvent('change', this.validationMonitor.pass([el, true], this));
		}, this);
	},

	validationMonitor: function(){
		$clear(this.timer);
		this.timer = this.validateField.delay(50, this, arguments);
	},

	onSubmit: function(event){
		if (!this.validate(event) && event) event.preventDefault();
		else this.reset();
	},

	reset: function(){
		this.getFields().each(this.resetField, this);
		return this;
	},

	validate: function(event){
		var result = this.getFields().map(function(field){
			return this.validateField(field, true);
		}, this).every(function(v){return v;});
		
		
		// modification pour d'integrer dans mooFW
		//Notifier.fireEvent('onFormValidate', result, this.element, event);
		this.fireEvent('formValidate', [result, this.element, event]);
		Notifier.fireEvent("onLayoutChanged", event.target);
		if (this.options.stopOnFailure && !result && event) event.preventDefault();
		return result;
	},

	validateField: function(field, force){
		if (this.paused) return true;
		field = document.id(field);
		var passed = !field.hasClass('validation-failed');
		var failed, warned;
		if (this.options.serial && !force){
			failed = this.element.getElement('.validation-failed');
			warned = this.element.getElement('.warning');
		}
		if (field && (!failed || force || field.hasClass('validation-failed') || (failed && !this.options.serial))){
			var validators = field.className.split(' ').some(function(cn){
				return this.getValidator(cn);
			}, this);
			var validatorsFailed = [];
			field.className.split(' ').each(function(className){
				if (className && !this.test(className, field)) validatorsFailed.include(className);
			}, this);
			passed = validatorsFailed.length === 0;
			if (validators && !field.hasClass('warnOnly')){
				if (passed){
					field.addClass('validation-passed').removeClass('validation-failed');
					this.fireEvent('elementPass', field);
				} else {
					field.addClass('validation-failed').removeClass('validation-passed');
					this.fireEvent('elementFail', [field, validatorsFailed]);
				}
			}
			if (!warned){
				var warnings = field.className.split(' ').some(function(cn){
					if (cn.test('^warn-') || field.hasClass('warnOnly'))
						return this.getValidator(cn.replace(/^warn-/,''));
					else return null;
				}, this);
				field.removeClass('warning');
				var warnResult = field.className.split(' ').map(function(cn){
					if (cn.test('^warn-') || field.hasClass('warnOnly'))
						return this.test(cn.replace(/^warn-/,''), field, true);
					else return null;
				}, this);
			}
		}
		return passed;
	},

	test: function(className, field, warn){
		var validator = this.getValidator(className);
		field = document.id(field);
		if (field.hasClass('ignoreValidation')) return true;
		warn = $pick(warn, false);
		if (field.hasClass('warnOnly')) warn = true;
		var isValid = validator ? validator.test(field) : true;
		if (validator && this.isVisible(field)) this.fireEvent('elementValidate', [isValid, field, className, warn]);
		if (warn) return true;
		return isValid;
	},

	isVisible : function(field){
		if (!this.options.ignoreHidden) return true;
		while(field != document.body){
			if (document.id(field).getStyle('display') == 'none') return false;
			field = field.getParent();
		}
		return true;
	},

	resetField: function(field){
		field = document.id(field);
		if (field){
			field.className.split(' ').each(function(className){
				if (className.test('^warn-')) className = className.replace(/^warn-/, '');
				field.removeClass('validation-failed');
				field.removeClass('warning');
				field.removeClass('validation-passed');
			}, this);
		}
		return this;
	},

	stop: function(){
		this.paused = true;
		return this;
	},

	start: function(){
		this.paused = false;
		return this;
	},

	ignoreField: function(field, warn){
		field = document.id(field);
		if (field){
			this.enforceField(field);
			if (warn) field.addClass('warnOnly');
			else field.addClass('ignoreValidation');
		}
		return this;
	},

	enforceField: function(field){
		field = document.id(field);
		if (field) field.removeClass('warnOnly').removeClass('ignoreValidation');
		return this;
	}
	
});

FormValidator.getMsg = function(key, field, props){
	var msg = "";
	//var lng = $(document.documentElement).get('lang') || $(document.body).get('lang');	// sur body pour cas sur iframe (pas la main sur <html>)
	if(key){
		switch(true){
			case props && props.msgType && FormValidatorMessage[props.msgType] && FormValidatorMessage[props.msgType].length != "" :
				//msg = FormValidatorMessage[lng][props.msgType];
				msg = FormValidatorMessage[props.msgType];
				break;
			case field && field.name && FormValidatorMessage[field.name] && FormValidatorMessage[field.name].length > 1:
				//msg = FormValidatorMessage[lng][field.name];
				msg = FormValidatorMessage[field.name];
				break;
			default:
				//msg = FormValidatorMessage[lng][key];
				msg = FormValidatorMessage[key];
				break;
		}
	}
	else {
		//msg = FormValidatorMessage[$(document.documentElement).get('lang')];
		msg = FormValidatorMessage;
	}
	return msg;
};

FormValidator.adders = {

	validators:{},

	add : function(className, options){
		this.validators[className] = new InputValidator(className, options);
		//if this is a class (this method is used by instances of FormValidator and the FormValidator namespace)
		//extend these validators into it
		//this allows validators to be global and/or per instance
		if (!this.initialize){
			this.implement({
				validators: this.validators
			});
		}
	},

	addAllThese : function(validators){
		$A(validators).each(function(validator){
			this.add(validator[0], validator[1]);
		}, this);
	},

	getValidator: function(className){
		return this.validators[className.split(':')[0]];
	}

};

$extend(FormValidator, FormValidator.adders);

FormValidator.implement(FormValidator.adders);

FormValidator.add('IsEmpty', {

	errorMsg: false,
	test: function(element){
		if (element.type == 'select-one' || element.type == 'select')
			return !(element.selectedIndex > 0 && element.options[element.selectedIndex].value != '');
		else
			return ((element.get('value') == null) || (element.get('value').length == 0));
	}

});

FormValidator.addAllThese([

	['required', {
		errorMsg: function(){
			return FormValidator.getMsg('required');
		},
		test: function(element){
			return !FormValidator.getValidator('IsEmpty').test(element);
		}
	}],
	
	['requiredDuree', {
		errorMsg: function(){
			return FormValidator.getMsg('requiredDuree');
		},
		test: function(element){
			
			return !FormValidator.getValidator('IsEmpty').test(element);
		}
	}],

	

	['minLength', {
		errorMsg: function(element, props){
			if ($type(props.minLength))
				return FormValidator.getMsg('minLength').substitute({minLength:props.minLength,length:element.get('value').length });
			else return '';
		},
		test: function(element, props){
			//trace(props)
			if ($type(props.minLength)) return (element.get('value').length >= $pick(props.minLength, 0));
			else return true;
		}
	}],

	['maxLength', {
		errorMsg: function(element, props){
			//props is {maxLength:10}
			if ($type(props.maxLength))
				return FormValidator.getMsg('maxLength').substitute({maxLength:props.maxLength,length:element.get('value').length });
			else return '';
		},
		test: function(element, props){
			//if the value is <= than the maxLength value, element passes test
			return (element.get('value').length <= $pick(props.maxLength, 10000));
		}
	}],

	['validate-beginNotSpace', {
		errorMsg: function(){
			return FormValidator.getMsg('required');
		},
		test: function(element){
			return !FormValidator.getValidator('IsEmpty').test(element) && !(/^[ ]/).test(element.get('value'));
		}
	}],
	
	['validate-integer', {
		errorMsg: FormValidator.getMsg.pass('integer'),
		test: function(element){
			return FormValidator.getValidator('IsEmpty').test(element) || (/^(-?[1-9]\d*|0)$/).test(element.get('value'));
		}
	}],

	['validate-numeric', {
		errorMsg: FormValidator.getMsg.pass('numeric'),
		test: function(element){
			return FormValidator.getValidator('IsEmpty').test(element) ||
				(/^-?(?:0$0(?=\d*\.)|[1-9]|0)\d*(\.\d+)?$/).test(element.get('value'));
		}
	}],

	['validate-digits', {
		errorMsg: FormValidator.getMsg.pass('digits'),
		test: function(element){
			return FormValidator.getValidator('IsEmpty').test(element) || (/^[\d() .:\-\+#]+$/.test(element.get('value')));
		}
	}],

	['validate-alpha', {
		errorMsg: FormValidator.getMsg.pass('alpha'),
		test: function(element){
			return FormValidator.getValidator('IsEmpty').test(element) ||  (/^[a-zA-Z]+$/).test(element.get('value'));
		}
	}],

	['validate-alphanum', {
		errorMsg: FormValidator.getMsg.pass('alphanum'),
		test: function(element){
			return FormValidator.getValidator('IsEmpty').test(element) || !(/\W/).test(element.get('value'));
		}
	}],

	['validate-date', {
		errorMsg: function(element, props){
			/* if (Date.parse){
				var format = props.dateFormat || '%x';
				return FormValidator.getMsg('dateSuchAs').substitute({date: new Date().format(format)});
			} else {
				return FormValidator.getMsg('dateInFormatMDY');
			} */
			return FormValidator.getMsg('dateInFormat');
		},
		test: function(element, props){
			if( /0{3}/.test(element.get('value')) && !/2000/.test(element.get('value')) ) return false;
			if (FormValidator.getValidator('IsEmpty').test(element)) return true;
			
			return DomUtils.checkDateFormat(element.get('value'), dateInFormat);

/* 			if (Date.parse){
				var format = props.dateFormat || '%x';
				d = Date.parse(element.get('value'));
				var formatted = d.format(format);
				var toReturn = !isNaN(d);
		 		
//				if (formatted != 'invalid date') 
//				{
//					element.set('value', formatted);
//					var currentYear = new Date().getFullYear();
//					var requestedYear = formatted.split("/")[2];
//					if( requestedYear < currentYear - 150 ) toReturn = false;
//				}
				return toReturn;
 			} else {
				var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
				if (!regex.test(element.get('value'))) return false;
				d = new Date(element.get('value').replace(regex, '$1/$2/$3'));
				return (parseInt(RegExp.$1, 10) == (1 + d.getMonth())) &&
					(parseInt(RegExp.$2, 10) == d.getDate()) &&
					(parseInt(RegExp.$3, 10) == d.getFullYear());
			} 
*/
 		}
	}],

	['validate-date-issue-passport', {
		errorMsg: function(element, props){
			return FormValidator.getMsg('dateIssuePassport');
		},
		test: function(element, props){
			if( /0{3}/.test(element.get('value')) && !/2000/.test(element.get('value')) ) return false;
			if (FormValidator.getValidator('IsEmpty').test(element)) return true;
			
			return DomUtils.checkDateFormat(element.get('value'), dateInFormat);
 		}
	}],
	
	['validate-date-issue-passport2', {
		errorMsg: function(element, props){
			return FormValidator.getMsg('dateIssuePassport2');
		},
		test: function(element, props){
			if(!FormValidator.getValidator('IsEmpty').test(element)) {//test si la date d'emission du passeport est inférieure ou égale à la date du jour
				var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
				if(dateInFormat == 'yyyy/MM/dd') {
					d = new Date(element.get('value').replace(regex, '$3/$1/$2'));
				} else if(dateInFormat == 'MM/dd/yyyy') {
					d = new Date(element.get('value').replace(regex, '$1/$2/$3'));
				} else {
					d = new Date(element.get('value').replace(regex, '$2/$1/$3'));
				}
				var today = new Date(); today.setHours(0,0,0,0);
				return d.getTime()<=today.getTime();
			} else {
				return true;
			}
 		}
	}],
	
	['validate-date-expiry-passport', {
		errorMsg: function(element, props){
			return FormValidator.getMsg('dateExpiryPassport');
		},
		test: function(element, props){
			if( /0{3}/.test(element.get('value')) && !/2000/.test(element.get('value')) ) return false;
			if (FormValidator.getValidator('IsEmpty').test(element)) return true;
			
			return DomUtils.checkDateFormat(element.get('value'), dateInFormat);
 		}
	}],
	
	['validate-date-expiry-passport2', {//test si la date d'expiration du passeport est supérieure à la date d'emission du passeport et à la date du jour
		errorMsg: function(element, props){
			return FormValidator.getMsg('dateExpiryPassport2');
		},
		test: function(element, props){
			if(!FormValidator.getValidator('IsEmpty').test(element)) {
				var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
				var elementName = element.name;
				var elementId = element.id;
				var dateIssue = '';
				
				if (elementId.length > 'eborders_dateexpiration'.length) {
					
					var suffix = elementId.substring('eborders_dateexpiration'.length);
					var accordionId = 'eborders_dateemission'+suffix;
					dateIssue = document.getElementById(accordionId).value;
				}
				else {
					dateIssue = document.getElementById('eborders_dateemission').value;
				}
				var d1 = null;
				if(dateInFormat == 'yyyy/MM/dd') {
					d = new Date(element.get('value').replace(regex, '$3/$1/$2'));
					if(dateIssue != null && dateIssue != ''){
						d1 = new Date(dateIssue.replace(regex, '$3/$1/$2'));
					}
				} else if(dateInFormat == 'MM/dd/yyyy') {
					d = new Date(element.get('value').replace(regex, '$1/$2/$3'));
					if(dateIssue != null && dateIssue != ''){
						d1 = new Date(dateIssue.replace(regex, '$1/$2/$3'));
					}
				} else {
					d = new Date(element.get('value').replace(regex, '$2/$1/$3'));
					if(dateIssue != null && dateIssue != ''){
						d1 = new Date(dateIssue.replace(regex, '$2/$1/$3'));
					}
				}
				var today = new Date(); today.setHours(0,0,0,0);
				if(d1 != null) {
					var bool1 = d.getTime()>d1.getTime();
					var bool2 = d.getTime()>today.getTime();
					if(bool1 && bool2) {
						return true;
					} else {
						return false;
					}
				} else {
					return d.getTime()>today.getTime();
				}
			} else {
				return true;
			}
 		}
	}],
	
	['validate-booking-number', {
		errorMsg: FormValidator.getMsg.pass('InvalidBookingNumber'),
		test: function(element){
			return FormValidator.getValidator('IsEmpty').test(element) || 
				(/^-?(?:0$0(?=\d*\.)|[1-9]|0)\d*(\.\d+)?$/).test(element.get('value'));
				
		}
	}],
	
	['validate-email', {
		errorMsg: FormValidator.getMsg.pass('email'),
		test: function(element){
			return FormValidator.getValidator('IsEmpty').test(element) || (/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i).test(element.get('value'));
		}
	}],
	
	

	['validate-url', {
		errorMsg: FormValidator.getMsg.pass('url'),
		test: function(element){
			return FormValidator.getValidator('IsEmpty').test(element) || (/^(https?|ftp|rmtp|mms):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i).test(element.get('value'));
		}
	}],

	['validate-one-required', {
		errorMsg: FormValidator.getMsg.pass('oneRequired'),
		test: function(element, props){
			var p = document.id(props['validate-one-required']) || element.parentNode;
			return p.getElements('input').some(function(el){
				if (['checkbox', 'radio'].contains(el.get('type'))) return el.get('checked');
				return el.get('value');
			});
		}
	}],

	['maxChecked', {
		errorMsg: function (element, props){
			return FormValidator.getMsg('maxChecked').substitute({maxChecked:props.maxChecked});
		},
		test: function(element, props){
			var areChecked = $(element.form).getElements("input[name="+element.name+"]").filter(function (elm){
				return elm.checked
			});
			return areChecked.length <= props.maxChecked;
		}
	}],
	
	['minChecked', {
		errorMsg: function (element, props){
			var l = $(element.form).getElements("input[name="+element.name+"]").filter(function (elm){
				return elm.checked;
			}).length;
			return FormValidator.getMsg('minChecked').substitute({minChecked:props.minChecked, length:l});
		},
		test: function(element, props){
			var areChecked = $(element.form).getElements("input[name="+element.name+"]").filter(function (elm){
				return elm.checked;
			});
			return areChecked.length >= props.minChecked;
		}
	}],
	
	['minCheckedBrochure', {
		errorMsg: function (element, props){
			var l = $(element.form).getElements("input[name="+element.name+"]").filter(function (elm){
				return elm.checked;
			}).length;
			return FormValidator.getMsg('minCheckedBrochure').substitute({minCheckedBrochure:props.minCheckedBrochure, length:l});
		},
		test: function(element, props){
			var areChecked = $(element.form).getElements("input[name="+element.name+"]").filter(function (elm){
				return elm.checked;
			});
			return areChecked.length >= props.minCheckedBrochure;
		}
	}],
	
	['validate-match', {
		errorMsg: function(element, props){
			return FormValidator.getMsg('match').substitute({matchName: props.matchName || document.id(props.matchInput).get('name')});
		},
		test: function(element, props){
			var eleVal = element.get('value');
			var matchVal = document.id(props.matchInput) && document.id(props.matchInput).get('value');
			return eleVal && matchVal ? eleVal == matchVal : true;
		}
	}],

	['validate-custom-required', {
		errorMsg: function(){
			return FormValidator.getMsg('required');
		},
		test: function(element, props){
			return element.get('value') != props.emptyValue;
		}
	}],
	
	/* Post codes legend */
	/*
	"N" : NUM
	"A" : ALPHA
	"S" : SPACE
	"R" : RANDOM (NUM or ALPHA)
	example for 75015 : validate-zip-code-NNNNN
	example for 987 DC : validate-zip-code-NNNSAA
	*/
	['validate-zip-code-NNNNN', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeNNNNN');
		},
		test: function(element, props){
			return /^[0-9]{5}$/.test(element.get('value'));
		}
	}],
	['validate-zip-code-NNNN', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeNNNN');
		},
		test: function(element, props){
			return /^[0-9]{4}$/.test(element.get('value'));
		}
	}],
	['validate-zip-code-RRRRR', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeRRRRR');
		},
		test: function(element, props){
			return /^[a-zA-Z0-9\-]{5}$/.test(element.get('value'));
		}
	}],
	['validate-zip-code-RRRR', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeRRRR');
		},
		test: function(element, props){
			return /^[a-zA-Z0-9\-]{4}$/.test(element.get('value'));
		}
	}],
	['validate-zip-code-RNNNRRRR', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeRNNNRRRR');
		},
		test: function(element, props){
			return /^[a-zA-Z0-9\-]{1}[0-9]{3}[a-zA-Z0-9\-]{4}$/.test(element.get('value'));
		}
	}],
	['validate-zip-code-NNNNNRNNN', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeNNNNNRNNN');
		},
		test: function(element, props){
			return /^[0-9]{5}[a-zA-Z0-9\-]{1}[0-9]{3}$/.test(element.get('value'));
		}
	}],
	['validate-zip-code-NNNRNNN', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeNNNRNNN');
		},
		test: function(element, props){
			return /^[0-9]{3}[a-zA-Z0-9\-]{1}[0-9]{3}$/.test(element.get('value'));
		}
	}],
	['validate-zip-code-ANABNAN', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeANABNAN');
		},
		test: function(element, props){
			return /^[a-zA-Z]{1}[0-9]{1}[a-zA-Z]{1}[\s]{1}[0-9]{1}[a-zA-Z]{1}[0-9]{1}$/.test(element.get('value'));
		}
	}],
	['validate-zip-code-NNNNNRRRRRR', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeNNNNNRRRRRR');
		},
		test: function(element, props){
			return /^[0-9]{5}[a-zA-Z0-9\-]{0,6}$/.test(element.get('value'));
		}
	}],
	['validate-zip-code-NNNNSAA', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeNNNNSAA');
		},
		test: function(element, props){
			return /^[0-9]{4}[\s]{1}[a-zA-Z]{2}$/.test(element.get('value'));
		}
	}],
	['validate-zip-code-RRRRRRRRRR', {
		errorMsg: function(){
			return FormValidator.getMsg('zipCodeRRRRRRRRRR');
		},
		test: function(element, props){
			return /^}[a-zA-Z0-9\-]{10}$/.test(element.get('value'));
		}
	}],
	
	
	['validate-phone-simple', {
		errorMsg: function(element, props){
			return FormValidator.getMsg('phoneSimple', element, props);
		},
		test: function(element, props){
			if(element.get('value')!=""){
				return /^\d/.test(element.get('value'));
			}else{
				return true;
			}
		}
	}],
	
	['validate-numcm-email', {
		errorMsg : function(element, props) {
			if (element.value == 'e-mail ou n°GM'){ // hack
				return FormValidator.getMsg('numcm-email2', element, props);
			}else{
				return FormValidator.getMsg('numcm-email', element, props);
			}
		},
		test : function(element, props) {
			var val = element.get('value');
			return (/^\d{1,9}$/.test(val) || (/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i).test(val));
		}
	}],
	
	['validate-numcm', {
		errorMsg: function(){
			return FormValidator.getMsg('numcm');
		},
		test: function(element, props){
			return /^[0-9]{1,9}$/.test(element.get('value'));
		}
	}],
	
	['validate-numcmGM', {
		errorMsg: function(){
			return FormValidator.getMsg('numcm');
		},
		test: function(element, props){
			if(element.get('value').length == 0){
				return true;
			}else{
				return /^[0-9]{9}$/.test(element.get('value'));
			}
		}
	}],
	
	['validate-checkboxgroup', {
		errorMsg: function(){
			return FormValidator.getMsg('cochegeenfants');
		},
		test: function(element, props){ //:'encadrementEnfantContainer'
			if (element.checked){
				var checks = $(props.group).getElements('input[type=checkbox]');
				bool = false;
				checks.each(function(elm){
					if (elm.checked == true)
						bool = true;	
				});
			}else{
				bool = true;	
			}
				
			return bool; ///^[0-9]{9}$/.test(element.get('value'));
		}
	}],
	
	['validate-radioschecked', {
		errorMsg: function(element, props){ 
//			return (props.radioscheckedMsg || FormValidator.getMsg('radioschecked')).replace(/_/g,' ');
			return FormValidator.getMsg('radioscheckedMsg');
		},
		test: function(element, props){
			var n = element.name;
			var radiosChecked = $(element.form).getElements('input[name=' + element.name + ']').some(function(radio){
				return !!radio.checked
			});
			
			return radiosChecked;
		}
	}],
	
	['validate-searchField', {
		errorMsg: function(){
			return FormValidator.getMsg('searchField');
		},
		test: function(element, props){
			if (element.get('value') != 'Ex : Punta Cana'){			
			return element.get('value') != props.emptyValue;
			}
		}
	}],
	
	['validate-select', {
		errorMsg: function(){
			return FormValidator.getMsg('required');
		},
		test: function(element, props){
			if ((element.get('value') != 'Sélection') || (element.get('value') != '-') || (element.get('value') != '--')){	
				return element.get('value') != '';
			}
		}
	}],
	
	
	['validate-eborders-cgu', {
		errorMsg: function(){
			return FormValidator.getMsg('cgu-required');
		},
		test: function(element, props){
			return (element.checked == true);
		
		}
	}],
	
	['validate-datedepart', { //test si la date entrée est supérieure à la date du jour
		errorMsg: function(){
			return FormValidator.getMsg('datedepart');
		},
		test: function(element, props){
			//validate-datedepart
			var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
			if (!regex.test(element.get('value'))) return false;
			if (dateInFormat == 'MM/dd/yyyy') {
				d = new Date(element.get('value').replace(regex, '$1/$2/$3'));
			} else {
				d = new Date(element.get('value').replace(regex, '$2/$1/$3'));
			}
			var today = new Date(); today.setHours(0,0,0,0);
			return d.getTime()>today.getTime();
		}
	}],
	
	['validate-birthdate', { //test si la date entrée est inférieure à la date du jour
		errorMsg: function(){
			return FormValidator.getMsg('naissance');
		},
		test: function(element, props){
			//validate-datenaissance
			var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
			if (!regex.test(element.get('value'))) return false;
			if (dateInFormat == 'MM/dd/yyyy') {
				d = new Date(element.get('value').replace(regex, '$1/$2/$3'));
			} else {
				d = new Date(element.get('value').replace(regex, '$2/$1/$3'));
			}
			var today = new Date(); today.setHours(0,0,0,0);
			return d.getTime()<today.getTime();
		}
	}],
	
	['validate-birthdate-notempty', { //test si la date entrée est inférieure à la date du jour
		errorMsg: function(){
			return FormValidator.getMsg('naissance');
		},
		test: function(element, props){
			//validate-datenaissance
			if(!FormValidator.getValidator('IsEmpty').test(element)){
				var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
				if (!regex.test(element.get('value'))) return false;
				if (dateInFormat == 'MM/dd/yyyy') {
					d = new Date(element.get('value').replace(regex, '$1/$2/$3'));
				} else {
					d = new Date(element.get('value').replace(regex, '$2/$1/$3'));
				}
				var today = new Date(); today.setHours(0,0,0,0);
				return d.getTime()<today.getTime();
			}else{
				return true;
			}
		}
	}],
	
	['requiredIfOtherEmpty', {
	      errorMsg: function (element, props){
	          return FormValidator.getMsg('requiredIfOtherEmpty',element, props).substitute();
	      },
	      test: function(element, props){
	          var $tmp = [element];
	          if(props.requiredIfOtherEmpty.test(/|/)){
	              var elms = props.requiredIfOtherEmpty.split("|");
	              elms.each(function (el){
	                  $tmp.push($(el));
	              })
	          }
	          else {
	              $tmp.push(props.requiredIfOtherEmpty)
	          }
	          var bool = false;
	          for(var i=0, l=$tmp.length, linkElm;i<l;i++){
	              linkElm = $tmp[i];
	              switch(linkElm.tagName){
	                  case "SELECT":
	                      if(linkElm.selectedIndex != 0 || linkElm.value != "" ) bool = true;
	                      break;
	                  case "INPUT":
	                      if(linkElm.value != linkElm.defaultValue) bool = true;
	                      break;
	              }
	          }
	          return bool;
	      }
	  }],
	  
	  ['validate-minlength-phone', {
			errorMsg: function(){
				var msg = FormValidator.getMsg('minlengthPhone');
				msg = msg.replace('$$',phoneSize)
		  		return msg;
			},
			test: function(element, props){
				var bool = false;
				if(!FormValidator.getValidator('IsEmpty').test(element)){				
					var valid = /^\d/.test(element.get('value'));
					if(valid) {
						var num = element.get('value');
						num = num.replace(' ','');
						var length = num.length;
						if(phoneSize != null && phoneSize !='' ) {
							if(length == phoneSize) {
								bool = true;
							}
						}
					} else {
						bool = true;
					}
				} else {
					bool = true;
				}
				return bool;
	 		}
	  }],

	  ['validate-atleast-onenumber', {
			errorMsg: function(){
		  		return FormValidator.getMsg('atLeastOneNumber');
			},
			test: function(element, props){
				var bool = false;
				if(!FormValidator.getValidator('IsEmpty').test(element)){
					var value = element.get('value');
					for(var i = 0; i < value.length; i++) {
						var chr = value.charAt(i); 
						if(chr==undefined){
							if(i==value.length-1) {
								bool = true;
							}
						} else {
							var valid = /^[0-9]{1}$/.test(chr);
							if(valid) {
								bool = true;
								break;
							}
						}
					}
				} else {
					bool = true;
				}
				return bool;
	 		}
	  }],


	  ['validate-name', {
		errorMsg: FormValidator.getMsg.pass('alpha'),
		test: function(element){
			return FormValidator.getValidator('IsEmpty').test(element) ||  (/^([a-zA-Z_éèàêâùïüë|\-|\'|\s])+$/).test(element.get('value'));
		}
	}]

]);


Element.Properties.validator = {

	set: function(options){
		var validator = this.retrieve('validator');
		if (validator) validator.setOptions(options);
		return this.store('validator:options');
	},

	get: function(options){
		if (options || !this.retrieve('validator')){
			if (options || !this.retrieve('validator:options')) this.set('validator', options);
			this.store('validator', new FormValidator(this, this.retrieve('validator:options')));
		}
		return this.retrieve('validator');
	}

};

Element.implement({

	validate: function(options){
		this.set('validator', options);
		return this.get('validator', options).validate();
	}

});


/*
Script: FormValidator.Inline.js
	Extends FormValidator to add inline messages.

	License:
		MIT-style license.

	Authors:
		Aaron Newton
*/

FormValidator.Inline = new Class({

	Extends: FormValidator,

	options: {
		scrollToErrorsOnSubmit: true,
		scrollFxOptions: {
			transition: 'quad:out',
			offset: {
				y: -20
			}
		}
	},

	initialize: function(form, options){
		this.parent(form, options);
		this.addEvent('onElementValidate', function(isValid, field, className, warn){
			var validator = this.getValidator(className);
			if (!isValid && validator.getError(field)){
				if (warn) field.addClass('warning');
				var advice = this.makeAdvice(className, field, validator.getError(field), warn);
				this.insertAdvice(advice, field);
				this.showAdvice(className, field);
			} else {
				this.hideAdvice(className, field);
			}
		});
	},

	makeAdvice: function(className, field, error, warn){
		var errorMsg = (warn)?this.warningPrefix:this.errorPrefix;
			errorMsg += (this.options.useTitles) ? field.title || error:error;
		var cssClass = (warn) ? 'warning-advice' : 'validation-advice';
		var advice = this.getAdvice(className, field);
		if(advice) {
			advice = advice.clone(true, true).set('html', errorMsg).replaces(advice);
		} else {
			advice = new Element('div', {
				html: errorMsg,
				styles: { display: 'none' },
				id: 'advice-' + className + '-' + this.getFieldId(field)
			}).addClass(cssClass);
		}
		field.store('advice-' + className, advice);
		return advice;
	},

	getFieldId : function(field){
		return field.id ? field.id : field.id = 'input_' + field.name;
	},

	showAdvice: function(className, field){
		var advice = this.getAdvice(className, field);
		if (advice && !field.retrieve(this.getPropName(className))
				&& (advice.getStyle('display') == 'none'
				|| advice.getStyle('visiblity') == 'hidden'
				|| advice.getStyle('opacity') == 0)){
			field.store(this.getPropName(className), true);
			if (advice.reveal) advice.reveal();
			else advice.setStyle('display', 'block');
		}

	},

	hideAdvice: function(className, field){
		var advice = this.getAdvice(className, field);
		if (advice && field.retrieve(this.getPropName(className))){
			field.store(this.getPropName(className), false);
			//if Fx.Reveal.js is present, transition the advice out
			if (advice.dissolve) advice.dissolve();
			else advice.setStyle('display', 'none');
		}
	},

	getPropName: function(className){
		return 'advice' + className;
	},

	resetField: function(field){
		field = document.id(field);
		if (!field) return this;
		this.parent(field);
		field.className.split(' ').each(function(className){
			this.hideAdvice(className, field);
		}, this);
		return this;
	},

	getAllAdviceMessages: function(field, force){
		var advice = [];
		if (field.hasClass('ignoreValidation') && !force) return advice;
		var validators = field.className.split(' ').some(function(cn){
			var warner = cn.test('^warn-') || field.hasClass('warnOnly');
			if (warner) cn = cn.replace(/^warn-/, '');
			var validator = this.getValidator(cn);
			if (!validator) return;
			advice.push({
				message: validator.getError(field),
				warnOnly: warner,
				passed: validator.test(),
				validator: validator
			});
		}, this);
		return advice;
	},

	getAdvice: function(className, field){
		return field.retrieve('advice-' + className);
	},

	insertAdvice: function(advice, field){
		//Check for error position prop
		var props = field.get('validatorProps');
		//Build advice
		if (!props.msgPos || !document.id(props.msgPos)){
			if(field.type.toLowerCase() == 'radio') field.getParent().adopt(advice);
			else advice.inject(document.id(field), 'after');
		} else {
			document.id(props.msgPos).grab(advice);
		}
	},

	validateField: function(field, force){
		var result = this.parent(field, force);
		if (this.options.scrollToErrorsOnSubmit && !result){
			var failed = document.id(this).getElement('.validation-failed');
			var par = document.id(this).getParent();
			while (par != document.body && par.getScrollSize().y == par.getSize().y){
				par = par.getParent();
			}
			var fx = par.retrieve('fvScroller');
			if (!fx && window.Fx && Fx.Scroll){
				fx = new Fx.Scroll(par, this.options.scrollFxOptions);
				par.store('fvScroller', fx);
			}
			if (failed){
				if (fx) fx.toElement(failed);
				else par.scrollTo(par.getScroll().x, failed.getPosition(par).y - 20);
			}
		}
		return result;
	}

});
