var addEvent = function() {
	if (window.addEventListener) {
		return function(el, type, fn) {
			el.addEventListener(type, fn, false);
		};
	} else if (window.attachEvent) {
		return function(el, type, fn) {
			var f = function() {
				fn.call(el, window.event);
			};
			el.attachEvent('on' + type, f);
		};
	} else {
		return function(el, type, fn) {
			var of = el['on' + type];
			if (typeof of != 'function')
				el['on' + type] = fn.apply(this, arguments);
			else
				el['on' + type] = function() {of.apply(this, arguments); fn.apply(this, arguments);}
		};
	}
}();

function add_load_event(fn) {
	var of = window.onload;
	if(typeof window.onload != 'function') { window.onload = fn; return false; }
	window.onload = function() { of(); fn(); }
	return true;
}

function add_onchange_event(c, fn) {
	var of = c.onchange;
	if(typeof c.onchange != 'function') { c.onchange = fn; return false;}
	c.onchange = function() { of.apply(this, arguments); fn.apply(this, arguments); }
	return true;
}

function trim(s) { return s.replace(/(^\s*)|(\s*$)/g,''); }
String.prototype.trim = function(){ return trim(this); }

function get_value(lst) { return ((lst.selectedIndex >= 0) ? lst.options[lst.selectedIndex].value : null); }

function reset_options_ex(ctrl, flag) {
	if(!ctrl || !ctrl.options) return false;
	for (var i=0; i<ctrl.options.length; i++)
		ctrl.options[i].selected = flag;
	return true;
}
function reset_options(ctrl) { reset_options_ex(ctrl, false); }

function count_checked(ctrl) {
	if(!ctrl.length)
		return (ctrl.checked ? 1 : 0);
	for (var cnt=0, i=0; i<ctrl.length; i++)
		if(ctrl[i].checked) cnt ++;
	return cnt;
}

function set_checked(ctrl, val) {
	if(!ctrl.length)
		ctrl.checked = (ctrl.value == val || val == null);
	else {
		for (var i=0; i<ctrl.length; i++)
			ctrl[i].checked = (ctrl[i].value == val || val == null);
	}
}


function is_percentage(fld) { return (fld.value.match(/^[\d]{1,2}$/)); }
function is_number(fld) { return (fld.value.match(/^\d+$/)); }
function is_email(fld) { return fld.value.match(/^[a-z0-9\.\-\_]+@([a-z0-9\-]+\.)+[a-z]{2,4}$/i); }
function is_year(fld) { return fld.value.match(/^(18|19|20)[0-9]{2}$/); }
function is_telephone(fld) { return fld.value.match(/^[0-9 \.]{10,14}$/); }
function is_zip(fld) { return fld.value.match(/^[0-9]{5}$/); }
function is_date(fld) {
	var a = fld.value.split(/[\/\-\:]/), d = new Date(a[2], a[1]-1, a[0]);
	return (!isNaN(d) && a[2] > 0 && d.getYear()%100==a[2]%100 && d.getMonth()==a[1]-1 && d.getDate()==a[0]);
}


function form_init(f) {
	f.fc = new formChecker();
	// parcourir les éléments pour traiter les input[type=text]
	for (var c, i=0, l = f.elements.length; i < l; i++) {
		c = f.elements[i];
		switch(c.nodeName) {
			case 'INPUT':
				if(!(c.type=='text' || c.type=='radio' || c.type=='checkbox'))
					break;
			case 'SELECT':
			case 'TEXTAREA':
				add_onchange_event(c, form_onchange);
				break;
			default:
				/* ne fait rien */
		}
	}
	// ajouter un onsubmit
	f.onsubmit = form_onsubmit;
	// ajouter les labels
	setTimeout(function() { add_label_properties(f); }, 1);
}

/* fonctions pour gérer les évènements */
function form_onchange() {
	return this.form.fc.run(this.form, this);
}
function form_onsubmit() {
	return this.fc.run(this);
}

// add a label property to all input / select / textarea element
function add_label_properties(f) {
	// Collect all label elements in form, init vars
	if(typeof f.getElementsByTagName == 'undefined') return false;
	var label, elem, labels = f.getElementsByTagName("label");
	// Loop through labels retrieved
	for (var i=0; i<labels.length; i++) {
	// while (label = labels[i++])	{
		label = labels[i];
		// For Opera 6
		if(typeof label.htmlFor == 'undefined') return false;
		// Retrieve element
		elem = f.elements[label.htmlFor];
		if(typeof elem == 'undefined') { // No element found for label
			alert("No element found for label: " + label.htmlFor);
		} else if(typeof elem.label != 'undefined') { // label property already added
			continue;
		} else if(typeof elem.length != 'undefined' && elem.length > 1 && elem.nodeName != 'SELECT') { // For checkbox arrays and radio-button groups
			for (var j=0; j<elem.length; j++) {
				elem.item(j).label = label;
			}
		} else {
			// Regular label
			elem.label = label;
		}
	}
	return true;
}

// about class attributes
function hasClassName(el, className) {
	if(!el) return false;
	var regexp = new RegExp('(^|\\s)' + className + '($|\\s)', 'ig');
	return (el.className && el.className.search(regexp) != -1);
};
function addClassName(el, className) {
	if(!el || hasClassName(el, className)) return false;
	if(el.className && el.className!="")
		el.className += " " + className;
	else
		el.className = className;
	return true;
}
function removeClassName(el,className) {
	if(el && el.className && hasClassName(el, className)) {
		var regexp = new RegExp('(^|\\s)' + className + '($|\\s)', 'ig');
		el.className = el.className.replace(regexp,'');
	}
}

// objet formChecker
function formChecker() {
	this.err = "";
	this.ctrl = null;
	this.alert_type;
	this.hasInnerText = (document.getElementsByTagName("body")[0].innerText != undefined) ? true : false;
	// construit la chaîne d'erreur, garde le premier contrôle et modifie la présentation
	this.add_error = function(ctrl, err_msg) {
		var i, label = "", o = null;
		if(ctrl.length && ctrl.length > 0 && ctrl.nodeName != 'SELECT') {
			o = ctrl[0];
			for (i=0; i<ctrl.length; i++) {
				if(this.hasInnerText)
					label += (label=="") ? ctrl[i].label.innerText : " / " + ctrl[i].label.innerText;
				else
					label += (label=="") ? ctrl[i].label.textContent : " / " + ctrl[i].label.textContent;
			}
		} else {
			o = ctrl;
			if(this.hasInnerText)
				label = ctrl.label.innerText;
			else
				label = ctrl.label.textContent;
		}		
		if(!this.ctrl) this.ctrl = o;		
		if(err_msg)
			this.err += err_msg + '\n';
		else
			this.err += 'Vous devez préciser "'+ label + '" !\n';
		/* l'erreur est placée sur l'élément P conteneur
		if(o.parentNode && o.parentNode.nodeName=='P') {
			addClassName(o.parentNode, 'alerte');
		}*/
		addClassName(o, 'alerte');
		return false;
	}
	// supprime la présentation 'erreur'
	this.remove_error = function(ctrl) {
		if(!ctrl) return false;
		if(ctrl.length && ctrl.length > 0 && ctrl.nodeName!='SELECT')
			ctrl = ctrl[0];
		/*if(ctrl.parentNode && ctrl.parentNode.nodeName=='P')
			removeClassName(ctrl.parentNode,'alerte');
		*/
		removeClassName(ctrl,'alerte');
		return true;
	}
	this.is_needed = function(c) {
		if(!c || !c.label) return false;
		return hasClassName(c.label, 'oblig');
	}
	this.check_select = function(c) {
		if(!this.is_needed(c)) return false;
		if(c.selectedIndex==-1 || (c.selectedIndex == 0 && c.options[0].value==""))
			return this.add_error(c);
		return this.remove_error(c);
	}
	this.check_radio = function(c) {
		if(!this.is_needed(c)) return false;
		if(c && count_checked(c)==0)
			return this.add_error(c);
		return this.remove_error(c);
	}
	// pour les input type=text
	this.check_field = function(c, test) {
		if(!c) return false;
		if(!c.value.trim().length)
			test = !this.is_needed(c);
		if(!test)
			return this.add_error(c);
		return this.remove_error(c);
	}
	this.check_text = function(c) {
		if(c.className.match(/\byear\b/))
			return this.check_field(c, is_year(c));
		else if(c.className.match(/\bdate\b/))
			return this.check_field(c, is_date(c));
		else if(c.className.match(/\bemail\b/))
			return this.check_field(c, is_email(c));
		else if(c.className.match(/\bint\b/))
			return this.check_field(c, is_number(c));
		else if(c.className.match(/\bpercent\b/))
			return this.check_field(c, is_percent(c));
		else if(c.className.match(/\bzip\b/))
			return this.check_field(c, is_zip(c));
		else if(c.className.match(/\btelephone\b/))
			return this.check_field(c, is_telephone(c));
		return this.check_field(c, true);
	}
	// Attribue les contrôles aux différents champs du formulaire
	// en fonction de leur type
	this.check_control = function(c) {
		switch(c.nodeName) {
			case 'SELECT':
				this.check_select(c);
				break;
			case 'INPUT':
				switch(c.type) {
					case 'text':
					case 'password':
						this.check_text(c);
						break;
					case 'radio':
					case 'checkbox':
						this.check_radio(c);
						break;
					default: /* submit, hidden */
						break;
				}
				break;
			case 'TEXTAREA':
				this.check_text(c);
				break;
			default:
				/* ne fait rien */
		}
	}
	this.run = function(f, c) {
		this.err = "";
		this.ctrl = null;
		if(!f) return false;
		if(c && c != 'undefined') {
			this.check_control(c);
		} else {
			for (var i=0; i<f.elements.length; i++) {
				this.check_control (f.elements[i]);
			}
		}
		// check des doubles champs
		if(this.field_match.length) {
			for(var i=0; i<this.field_match.length; i++) {
				if(f[this.field_match[i][0]].value.trim().length && f[this.field_match[i][1]].value.trim().length && f[this.field_match[i][0]].value != f[this.field_match[i][1]].value) {
					this.add_error(f[this.field_match[i][1]], this.field_match[i][2]);
				}
			}
		}		
		// s'il y a des erreurs on ne valide pas le formulaire
		if(!this.err.length)
			return true;
		if(!c || c == 'undefined') {
			if(this.alert_type == 'alert')
				alert("Veuillez compléter les champs encadrés en rouge");
				// alert("Le formulaire n'est pas valide !\n" + this.err);
		}
		/*if(this.ctrl) {
			if(this.ctrl.select) this.ctrl.select();
			if(this.ctrl.focus) this.ctrl.focus();
		}*/
		return false;
	}
	this.field_match = [];
	// Les champs à tester deux à deux sont passés à form_field_match
	// ex: document.forms[0].fc.form_field_match(["email", "remail", "Vous devez confirmez l'email"]);
	this.form_field_match = function(arr) {
		if(!arr || arr.length < 2) return false;
		return this.field_match.push(arr);
	}
	this.set_alert_type = function(type) {
		if(!type) return false;
		return this.alert_type = type;
	}
}