/**
* 	@fileoverview ce fichier contient l'ensemble des modules autodeclares, necessite mootools.js (1.1 ou 1.2)
	@author FullSIX Tech - Equipe DFO
	@version 1.0
*/

/**
    @object Module,
    @description 
        Module est un objet facilitant la creation et l'execution de script s'appuyant sur des elements du DOM html
        en n'executant que les scripts necessaires au fonctionnement de la page.
        
        Le principe: 
			Pour cela, il suffit d'enregister une class et un selecteur via la methode Module.register("nomDeLaClasse", "selecteur");
			Au chargement, si un element correspond au selecteur, la classe correspondante sera instancie avec cet element en parametre
			Execute au domready.
			
			
	@use 
		
		Module.register("maClasse", "selecteur", [args1, args2]);
		C'est a dire que pour chaque element de $$("selecteur"),
		on instancie la class maClasse, en lui passant l'element courant en 1er parametre, et un ou des argument(s) en second.
		
		
		Pour la creation de module il suffit de creer une class et de l'enregistrer via la methode Module.register
		var maClass = new Class({
			initialize: function (elm, args){
				this.doStuff();
			},
			
			doStuff: function (){
				console.log(elm, args);
			}
		});
		Module.register("maClass", "a.lien");
		// affichera au domready autant de console qu'il y a de <a class="lien"> dans la page
		
	@param : 	maClasse {String}: le nom de la Class a instancier
	@param : 	selecteur {String}: 
				pour des questions de performance, preferez les selecteurs simples type  div.block ou #monId,
				un selecteur interne permet de parcourir le DOM le moins possible.
				
				Dans le cas contraire, le DOM se parcouru completement pour chaque module ($$(selecteur))
	@param : 	args, argument(s) a passer au constructeur
	@return behavior        
*/

Module = {
	modules: [],
	lines: [],
	selectorTag: {},
	ids: {},
	resizeListener: function (block){
		if(!block) return;
		block = $(block);
		if(block.hasClass('noresize')) return;
		
		
		// si le blockToggle possede des lines
		var childLine = block.getElements('.line');
		childLine.each(function (line){
			Module.LineResizer(line, false);
		})
		
		// si le block est contenu dans une line
		var line = $(block).getParent(".line");
		if(line) {
			$(document.documentElement).addClass('beforeResize');
			Module.clearResize(line);
			var body = $(block).getParent(".body") || $(block).getParent(".unit") ;
			body.style[CONF.heightStyle] = "";
			Module.LineResizer(line, true);
		}
	},
	
	clearResize: function(line){
		var bodies = line.getElements(".body").concat(line.getElements('.unit')).filter(function(a,b){return a.getParent(".line") == line});;
		bodies.each(
			function(el){
				el.style[CONF.heightStyle] = "";
			}
		);
		var parentLine = line.getParent('.line');
		if(parentLine) Module.clearResize(parentLine);
		
	},

	resizeNotifier:	
		Notifier.register(this, "onLayoutChanged", function(args){
			Module.resizeListener(args);
		}),
	
	register: function (sClass, sSelector, aArgs){
		// si le selecteur est du type tag.class
		
		if(sSelector.match(/^[a-zA-z]*\.[a-zA-Z]*$/)){
			var sp = sSelector.split('.');
			if(!Module.selectorTag[sp[0]]) Module.selectorTag[sp[0]] = {};
			if(!Module.selectorTag[sp[0]][sp[1]]) Module.selectorTag[sp[0]][sp[1]] = [];
			Module.selectorTag[sp[0]][sp[1]].push([sClass, aArgs]);
		}
		// si le selecteur est du type #id
		else if(sSelector.match(/^#[a-zA-z]KKKKKKK*$/)){
			if(!Module.ids[sSelector]) Module.ids[sSelector] = [];
			Module.ids[sSelector].push([sClass, aArgs]);
		}
		else {
			Module.modules.push([sClass, sSelector, aArgs]);
		}
	},
	launch: function (){
		//capabilities.init();
		// selecteur simple tag.class ou #id
		for(var tag in Module.selectorTag){
			var tagColl = document.getElementsByTagName(tag);
			var i=0, l=tagColl.length,elm,id;
			for(;i<l;i++){
				elm = tagColl[i];
				id = "#"+elm.id;
				if(id != "#" && Module.ids[id]){
					var j=0, m=Module.ids[id].length;
					for(;j<m;j++){
						new window[Module.ids[id][j]](elm);
					}
				}
				
				if(elm.className != ""){
					for(var klass in Module.selectorTag[tag]){
						if(elm.className.match(new RegExp("\\b"+klass+"\\b"))){
							var m,n=Module.selectorTag[tag][klass].length;
							for(m=0;m<n;m++){
								new window[Module.selectorTag[tag][klass][m][0]](elm, Module.selectorTag[tag][klass][m][1]);
							}
						}
					}
				}
			}
		}
		// selecteur complexe $$(selecteur)
		var i=0, l=Module.modules.length, module, elms, elm;
		for(;i<l;i++){
			module = Module.modules[i];
			elms = $$(module[1]);
			for(var j=0, m=elms.length;j<m;j++){
				elm = elms[j];
				new window[module[0]](elm);
			}
		}

	}
}

Notifier.register(Module, 'onLayoutChanged', Module.resizeListener);
/* Lancement des modules */
$(window).addEvent("domready", function (){Module.launch();})


var Modules = function(){
	if(Modules.prototype.check(arguments[0].required)) return new Class(arguments[0]);
	else return function (){};
}

Modules.prototype.check = function(aRequired){
	var ok = true;
	for(var i =0, l=aRequired.length;i<l;i++){
		if(aRequired && !Browser.Features[aRequired[i]]) {
			ok = false;
			break;
		}
	}
	return ok;
}


/** @function LinePusher
	@description permet d'utiliser le systeme de module pour enregistrer les <line> en vu de Module.LineResizer
*/
var LinePusher = new Class({
	initialize: function (line){
		if(!$(line).hasClass("noresize")) {
			Module.lines.push(line);
		}
		
	}
});
Module.register("LinePusher", "div.line");
/** @function Module.LineResizer 
	@description permet l'alignement en hauteur des <div class="line"> 
	@use 
			Le respect de cette structure html minimal est indispensable pour l'execution du script.
			En effet le script compare la hauteur d'un <unit> par rapport a une <line> et applique la difference sur le dernier <body>.
			L'application de la class="noresize" sur l'une des 3 <div>, empechera le resize de cette element.
			
			<div class="line">
				<div class="unit">
					<div class="body"></div>
				</div>
			</div>
			
			Toutefois, en l'abscence de <div class="body">, le resize s'effectura sur <div class="unit"> 
			ATTENTION: peut engendrer des problemes graphiques.
			
			Executee sur le onload de la page, pour que l'ensemble des medias soit charge.
			
	@param line {element} option
	@param bubbleResize {boolean} option permettant de provoquer le resize des line parente de la line courante
			Cette fonction peut etre appellee independament des modules, 
				en lui passant la <div class="line"> en 1er parametre, 
	@todo repartir la hauteur manquante sur les differents <body> d'un <unit>
	@return behavior 
*/
Module.LineResizer = function (line, bubbleResize){
	if(line && (line.hasClass("noresize") || line.offsetHeight == 0))  return Module.AfterResize();
	else if(line) {
		manualMode = true;
		Module.lines = [line];
	}
	else if(Module.lines.length == 0) Module.lines = $$('div.line').filter(function(a, b){return !a.hasClass("noresize")});
	
	function doResize (elm, size){
		
			elm.style[CONF.heightStyle] =  Math.ceil(size) + "px";
		
	}
	
	for(var i = Module.lines.length-1; i>=0; i--){
		var line = Module.lines[i];
		var height = line.offsetHeight;
		var units = line.getElements(".unit").filter(function(a, b){
			var pLine = a.getParent(".line");
			return pLine == line && !pLine.hasClass("noresize") && pLine.offsetHeight != 0;
		});
		
		for(var j=0,l=units.length;j<l;j++){
			var el = units[j];
			var body = el.getElements(".body").filter(function(a, b){return a.getParent(".unit") == el && !a.hasClass("noresize");}).getLast();
			// si pas de .body, le .unit est resize
			if(!body) body = el;
			var oriH = body.getStyle("height").toInt();
			var h2apply = line.clientHeight - el.clientHeight;
		
			doResize(body, oriH + h2apply);
		}
	}
	
	if(bubbleResize){
		var parentLine = line.getParent('.line');
		if(parentLine) Module.LineResizer(parentLine, true);
	}
	else Module.AfterResize();
}
/** @function Module.AfterResize 
	@description function servant de callback a Module.LineResizer.
*/ 
Module.AfterResize = function (){
	// beforeResize: class sur <body> permettant de masquer les elements ne rentrant pas en compte du resize
	// body.beforeResize .maClasse {display:none;}
	document.documentElement.className = document.documentElement.className.replace(/\bbeforeResize\b/g, "");
	Notifier.fireEvent("onLayoutChanged");
}
/* Lancement du resize, attendre le onload pour les images */
window.addEvent('load', function (){Module.LineResizer();});
window.addEvent('load', function (){
	setTimeout(function (){
		$(document.documentElement).removeClass('beforeLoading')
	}, 50);
});

/** @class Side 
	@description injecte la structure html permetant la realisation d'ombre portee 
	@use 
			l'utilisation de la structure block/blockInside est indispensable pour l'execution du script.
			
			<div class="block">
				<div class="blockInside"></div>
			</div>
			
			En effet, le script va injecter la structure des coins entre les 2 <div>
			
			html apres l'execution du script:
			
			<div class="block">
				<span class="sideL"></span>
				<span class="sideR"></span>
				<span class="sideT"></span>
				<div class="blockInside"></div>
				<span class="sideB"></span>
			</div>
			
			le skin des side est gere via CSS, ce reporter a la section /* blockShadow * de default.css
			
	@return behavior
*/
var Side = new Class({
	initialize: function (block){
		var sideL = new Element("span", {"class":"sideL"});
		var sideR = new Element("span", {"class":"sideR"});
		var sideT = new Element("span", {"class":"sideT"});
		sideT.injectTop(block);
		sideR.injectTop(block);
		sideL.injectTop(block);
		
		var sideB = new Element("span", {"class":"sideB"});
		sideB.injectBottom(block);
	}
})
/** @class Corner 
	@description injecte la structure html permetant la realisation de coin arrondi 
	@use 
			l'utilisation de la structure block/blockInside est indispensable pour l'execution du script.
			
			<div class="block">
				<div class="blockInside"></div>
			</div>
			
			En effet, le script va injecter la structure des coins entre les 2 <div>
			
			html apres l'execution du script:
			
			<div class="block">
				<span class="topCorners"><span class="tl"></span><span class="tr"></span></span>
				<div class="blockInside"></div>
				<span class="bottomCorners"><span class="bl"></span><span class="br"></span></span>
			</div>
			
			le skin des coins est gere via CSS, ce reporter a la section /* corners * de default.css
			
	@return behavior
*/
var Corner = new Class({
	initialize: function (block){
		var topC = new Element("span", {"class":"topCorners", html:'<span class="tl"></span><span class="tr"></span>'});
		topC.injectTop(block);
		var bottomC = new Element("span", {"class":"bottomCorners", html:'<span class="bl"></span><span class="br"></span>'});
		bottomC.injectBottom(block);
	}
})
// Side avant Corner
// Decommenter si la sructure n'est pas dans le html de depart
// Module.register("Side", "div.blockShadow");
// Module.register("Corner", "div.block");


/** @class InputAutoclean 
	@description ajoute un comportement 'intelligent' a un <input type="text">
	@use 
			<input type="text" value="votre email" />
			
			L'input se videra au clic, si la value est egale a  la value par defaut
			L'input se remplira au blur avec la value par defaut, si la value est vide
	@return behavior
*/
var InputAutoclean = new Class({
	initialize: function (el){
		$(el).addEvents({
			focus: function (){
				if(this.value == this.defaultValue) this.value = "";
			},
			blur: function (){
				//if(this.value == "") this.value = this.defaultValue;
				if(this.value.replace(/^\s+/g,'').replace(/\s+$/g,'') == "") this.value = this.defaultValue;
			}
		})
	}
})
Module.register("InputAutoclean", "input.autoclean");

/** @class fakeSelect 
	@description permet de simuler un select a l'aide d'un <span> et d'un <ul>
	@use 
			<div class="fakeSelect">
				<span>Mes liens</span>
				<ul class="hidden">
					<li><a href="#">google.fr</a></li>
					<li><a href="#">yahoo.com</a></li>
					<li><a href="#lien4">deezer.com</a></li>
				</ul>
			</div>
			Le clic ou le survol du <span>, affiche le <ul>
	@return behavior 
*/
var fakeSelect = new Class({
	initialize: function (block){
		block = $(block);
		// detection du context overflow
		var modeOverflow = false;
		block.getParents().each(function(parent){
			if (parent.getStyle('overflow') == 'hidden') modeOverflow = true;
		})
		// si dans un  context overflow:hidden, on clone le node, on masque celui d'origine, et on positionne le clone sur le block d'origine
		if(modeOverflow){
			var clone = block.clone(true);
			this.block = block;
			this.clone = clone;
			block.setStyle('visibility', 'hidden');
			$(document.body).adopt(clone);
			Notifier.register(this, "onLayoutChanged", function (){
				this.positionateBlock();
			});
			this.positionateBlock(clone, block);
			block = clone;
		}
		
	
		
		
		// on recupere le span
		this.handler = $(block).getElement("span.fakeSelectHandler");
		// on recupere le u
		this.ul = block.getElement("ul");
		// on le masque
		if(!this.ul.hasClass("hidden")) this.ul.addClass('hidden');
		// events
		this.handler.addEvents({
			"click" : function (e){e.stop();this.toggle();}.bind(this),
			"mouseover" : function (e){}.bind(this),
			"mouseout" : function (e){}.bind(this)
		})
	},
	show: function (){
		//this.positionate();
		this.handler.addClass('open');
		this.ul.removeClass('hidden');
		document.body.addEvent('click', function (){
			this.hide();
		}.bind(this))
	},
	hide: function (){
		this.handler.removeClass('open');
		this.ul.addClass('hidden');
	},
	toggle: function (){this.ul.hasClass('hidden') ? this.show() : this.hide();},
	positionateBlock: function (){
		clone = this.clone;
		block = this.block;
		var c = block.getCoordinates();
		clone.setStyle("left", c.left);
		clone.setStyle("top", c.top);
		clone.setStyle("position", "absolute");
	},
	
	positionate: function (){
		var c = this.handler.getCoordinates();
		this.ul.setStyle("left", c.left);
		this.ul.setStyle("top", c.top + c.height);
	},
	
	bodyEvent: function (){
		this.hide();
		document.body.removeEvent('click', this.bodyEvent)
	}
	
});
Module.register("fakeSelect", "div.fakeSelect");

/** @class blockClickable 
	@description permet de rendre un conteneur entierement cliquable, reproduisant le clic sur son 1er lien enfant.
	@use 
			<div class="blockClickable">
				<p>Lorem ipsum....</p>
				<a href="monsite.com" target="_blank">En savoir plus</a>
				<p>... dolor sic amet</p>
			</div>
			
			L'ensemble de la <div class="blockClickable"> est maintenant cliquable et mene vers monsite.com dans une nouvelle fenetre
	@return behavior 
*/
var blockClickable = new Class({
	initialize: function (block, sClass){
		block = $(block);
		var lien = block.getElement("a");
		if(!lien) return;
		block.style.cursor = 'pointer';
		var klass = sClass || "hover";
		block.addEvents({
			"click" : function (e){
						e.stop();
						var target = lien.getAttribute("target") || "_self";
						window.open(lien.href, target);
					},
			"mouseover" : function (e){e.stop();this.addClass(klass)},
			"mouseout" : function (e){e.stop();this.removeClass(klass)}
		})
	}
});
Module.register("blockClickable", "div.blockClickable");
Module.register("blockClickable", "div.blockOffreSpeciale");
Module.register("blockClickable", "div.blockExcluWeb");

/** @class blockTabs 
	@description gere un systeme de bloc a onglet.
	@use 
			<div class="blockTabs">
				<ul class="tabs onglets3">
					<li class="first"></li>
					<li class=""></li>
					<li class="last"></li>
				</ul>
				<div class="tabCtn"></div>
				<div class="tabCtn tabCurrent"></div>
				<div class="tabCtn"></div>
			</div>
			
			Le nombre de <li> doit correspondre au class="tabCtn".
			Chaque click de <li> declenchera l'ouverture d'un element possedant la class="tabCtn".
			Le premier <li> ouvre le 1er class="tabCtn" ...
			
	@option si <div class="blockTabs blockTabsHover"> le comportement se declenche au mouseover.
	@return behavior 
*/
var blockTabs = new Class({
	initialize: function (block){
		var event = $(block).hasClass('blockTabsHover') ? "mouseover" : "click";
		this.block = block;
		//get handler
		this.lis = $(block).getElements('ul.tabs li');
		// get togglelable 
		this.ctns = block.getElements('.tabCtn');
		// check if OK
		if(this.lis.length != this.ctns.length || this.lis.length == 0 || this.ctns.length == 0)
			return 
			//throw('Le nombre de <li> dans <ul class="tabs"> doit correspondre au nombre de d\'elements possedant la class="tabCtn" au sein du blockTabs');
		
		// evts
		var i=0, l=this.lis.length, li, tabCtn, _self=this;
		for(;i<l;i++){
			
			li = $(this.lis[i]);
			tabCtn = $(this.ctns[i])
			if(li.className.match(/\bcurrent[a-zA-Z]*/g)){
				_self.currentIndex = i;
			}
			li.addEvent(event, function (index){
				return function (e){
					if(e.type == "click") e.stop();
					_self.toggleTo(index);
				}
			}(i))
		}
		//
		this.toggleTo(this.currentIndex)
		
	},
	
	toggleTo: function (index){
		// close the current
		this.ctns[this.currentIndex].removeClass('tabCurrent');
		this.lis[this.currentIndex].className = this.lis[this.currentIndex].className.replace(/\bcurrent[a-zA-Z]*/g, "");
		//
		this.currentIndex = index;
		// show the new current
		this.ctns[this.currentIndex].addClass('tabCurrent');
		var li = this.lis[this.currentIndex];
		var classToApply = 
			li.hasClass('first') ?
				"current currentFirst" :
					li.hasClass("last") ?
						"current currentLast" :
						"current";
		this.lis[this.currentIndex].addClass(classToApply);
		
	}
});
Module.register("blockTabs", "div.blockTabs");
Module.register("blockTabs", "ul.blockTabs");


/** @class blockToggle 
	@description gere un systeme de bloc ouvert/ferme
	@use 
		le ou les boutons declencheurs possede(nt) la class="toggleHandler"
		le ou les conteneurs a afficher/masquer possede(nt) la class="toggleCtn"
		en css, la class="toggleClose" amene un display:none
		et la class="toggleHandler" est en display:none si js est desactive
		
		2 modes de fonctionnement:
		
			avec un seul bouton:
					
				<div class="blockToggle">
					<a href="#" class="toggleHandler" >Voir les mentions legales</a>
					<script type="text/javascript">
						var altText = 'Masquer les mentions legales';
					</script>
					<div class="toggleCtn toggleClose">...</div>
					<div class="toggleCtn toggleOpen">...</div>
				</div>
				
				Le clic sur le bouton inverse les classes toggleOpen et toggleClose,
				et le texte du bouton deviendra le texte declare dans la balise <script> (le nom de la variable n'a aucun impact),
				le 2eme clic remettra le contenu comme au chargement de la page.
				
				Le choix de mettre le texte dans une balise <script> est dicte par des raisons d'accessibilite. 
				Sans JS, il n'existe qu'un seul lien inutile dans la page, qui est masque
			
			avec deux boutons:
				
				<div class="blockToggle">
					<a href="#" class="toggleHandler toggleOpen" >Voir les mentions legales</a>
					<a href="#" class="toggleHandler toggleClose" >Masquer les mentions legales</a>
					<div class="toggleCtn toggleClose">...</div>
				</div>
				
				Le clic sur le bouton inversent les classes toggleOpen et toggleClose.
				
		Un event est fired pour permettre le resize de la line parent si elle existe.
		
		@return behavior 
*/
var blockToggle = new Class({
	required: ["css"],
	
	initialize: function (block){
		block = this.block = $(block);
		this.handlers = block.getElements(".toggleHandler");
		this.toggleCtn = block.getElements(".toggleCtn");
		var _self = this;
		// recuperation du text alternatif si il n'y a qu'un lien et une balise script
		this.altText = this.handlers.length == 1 && block.getElement('script') ? block.getElement('script').innerHTML.split('=')[1].replace(/'|"|;/g, "") : null;
		var i=0, l=this.handlers.length, hand;
		for(;i<l;i++){
			hand = $(this.handlers[i]);
			hand.addEvent("click", function(e){
					_self.toggle();
					e.stop();
			})
		}
		
		
		
	},
	
	toggle: function (){
		switch(true){
			case this.handlers.length == 1:
				if(this.altText != null){
					var alt = this.altText;
					this.altText = this.handlers[0].innerHTML;
					this.handlers[0].innerHTML = alt;
				}
				break;
			default :
				this.handlers.each(function (el){
					if(el.hasClass("toggleOpen")){
						$(el).removeClass("toggleOpen");
						$(el).addClass("toggleClose");
					}
					else if(el.hasClass("toggleClose")){
						$(el).removeClass("toggleClose");
						$(el).addClass("toggleOpen");
					}
				})
				break;
		}

		this.toggleCtn.each(function (el){
			$(el).toggleClass("toggleClose");
			$(el).toggleClass("toggleOpen");
		})
		Notifier.fireEvent("onLayoutChanged", this.block);
		
	}
	
});
Module.register("blockToggle", "div.blockToggle");


/** */
var navTop = new Class({
	required: ["css", "img"],

	initialize: function (ul){
		this.ul = ul;
		this.fstLi = ul.getChildren();
		this.current = this.fstLi.filter(function(a){return a.hasClass('current')}).getLast();
		//console.log(this.current);
		var _self = this;
		this.fstLi.each(function (li){
			li.addEvents({
				"click": function (){},
				"mouseover": function (){
					this.addClass("open");
					_self.current.removeClass('current');
					Cufon.refresh("#navTop span.sm", "#navTop span.lg");
				},
				"mouseout": function (){
					this.removeClass("open");
					//_self.current.addClass('current');
					Cufon.refresh("#navTop span.sm", "#navTop span.lg");
				
				}
			});
			li.getElement("a").addEvents({
				focus: function (){
					li.addClass("open");
					_self.current.removeClass('current');
					Cufon.refresh("#navTop span.sm", "#navTop span.lg");
				},
				blur: function (){
					li.removeClass("open");
					//_self.current.addClass('current');
					Cufon.refresh("#navTop span.sm", "#navTop span.lg");
				
				}
			});
			var c = li.getCoordinates();
			var ul = li.getElement('ul');
			if(ul){
				//ul.offsetWidth < li.offsetWidth ? ul.style.width = li.offsetWidth + "px" : "";
			}
		})
	},
	
	show: function (){}
});
Module.register("navTop", "#navTop");


/** @class skinCheckableInput 
	@description gere une liste d'input type checkbox/radio skinne
	@param className {string} par defaut isChecked
	@use 
		les labels possedent la class="checkbox" completee par la class="isChecked" lorsque l'input est en etat checked
		les inputs contenu dans la liste sont en visibility:hidden (avec hasJS )et les labels sont places par dessus
		les labels ont en background l'image de la checkbox non cochee avec la class="checkbox" et le background est remplace par la checkbox cochee avec la class="check"
		le javascript verifie si les inputs sont de type checkbox ou radio et adapte leur comportement en fonction
		
		il existe 2 types de checkbox / radio skines, les petits boutons amenes avec la classe checkboxList et les plus gros amenes avec la classe checkboxListBig
		
				type radio :
					<label for="myId"><input type="radio" name="myName" id="myId" .../>mon label</label>
					<label for="myId2"><input type="radio" name="myName" id="myId2" .../>mon label 2</label>
				
				type checkbox :
					<label for="myId"><input type="checkbox" name="myName" id="myId" .../>mon label</label>
					<label for="myId2"><input type="checkbox" name="myName2" id="myId2" .../>mon label 2</label>
		
		@return behavior 
*/
var skinCheckableInput = new Class({
	initialize: function(label, className){
		this.label = $(label);
		
		
		var For = this.label.getProperty("for");
		var input = $(For);
		if(input.disabled) {
			this.label.addClass('disabled');
			return;
		}
		input.addEvent('click', function(){
			if($type(this.onclick) == "function"){
				this.onclick();
			} 
		})
		var className = !className ? "isChecked" : className;
		// 
		
		if(input.checked) this.label.addClass(className);
		else this.label.removeClass(className);
		
		this.label.addEvent("click", function(e){
			// si input type="radio"
			
			if(input.getProperty("type") == "radio"){
				e.stop();
				var name = input.getProperty("name");
				var inputs = this.getParent("form").getElements("input[name="+name+"]")
				
				// si l'element est deja checked
				if (this.hasClass(className)) {
					this.removeClass(className);
					input.checked = false;
				} 
				// sinon
				else {
					inputs.each(function(inp){
						var lab = $(getLabel(inp));
						if(lab.hasClass(className)) lab.removeClass(className);
						inp.checked = false;
					});
					this.addClass(className);
					input.checked = true;
				}
			// si input type="checkbox"
			} else if(input.getProperty("type") == "checkbox"){
				
				
				e.stop();
				
				// si l'element est deja checked
				if(this.hasClass(className)){
					this.removeClass(className);
					input.checked = false;
				}
				// sinon
				else{
					this.addClass(className);
					input.checked = true;
				}
			}
			input.fireEvent("click");
		});
	}
});
//Module.register("skinCheckableInput", "label.skinCheckable");

Module.register("skinCheckableInput", "label.checkbox", "check");

/** Slider */
var F6Slider = new Class({
	initialize: function(slider,args){
		slider = $(slider);
		this.ul = slider.getElement("ul");
		this.aLis = this.ul.getElements("li");
		this.liSize = this.aLis.getSize();
		
		this.linkImgZoom = slider.getElement("div.bigImg").getElement("a.imgZoom");
		
		//on calcule la taille totale d'un li (marges comprises) puis la taille de tous les li mis bout a bout
		//et on applique cette valeur a la propriete "width" du ul
		var totalW = this.aLis[0].offsetWidth + this.aLis[0].getStyle("marginLeft").toInt() + this.aLis[0].getStyle("marginRight").toInt();
		this.ulWidth = Browser.Engine.trident && Browser.Engine.version == 4 ? totalW*this.aLis.length+3 : totalW*this.aLis.length;
		this.ul.setStyle("width", this.ulWidth);
		
		//on calcul la taille du masque en fonction du nombre de li a afficher passe en parametre
		//et on applique cette valeur a la propriete "width" du masque
		this.maskSlider = slider.getElement("div.maskSlider");
		var maskSize = Browser.Engine.trident && Browser.Engine.version == 4 ? args[0]*totalW+3 : args[0]*totalW;
		this.maskSlider.setStyle("width",maskSize);
		this.maskSlider.setStyle("marginLeft","auto");
		this.maskSlider.setStyle("marginRight","auto");
		
		//on calcule la marge maximum que pourra avoir le ul afin de ne pas la depasser
		var maxMarginL = 0 - (this.ulWidth - maskSize);
		
		this.slidePrev = slider.getElement("a.btnPrev");
		this.slideNext = slider.getElement("a.btnNext");
		
		//a l'ouverture de la page on cache les boutons prev et next
		this.slidePrev.addClass("inactive");
		this.slideNext.addClass("inactive");
		
		//on recupere le nom de la miniature
		var src = "/img/mobiles/";
		var small = "SMALL";
		var medium = "MEDIUM";
		var large = "LARGE";
		
		var smallImgArray = new Array();
		var mediumImgArray = new Array();
		var largeImgArray = new Array();
		
		
		var myArray = args[1] == "MEDIUM" ? mediumImgArray : largeImgArray;
		
		
		this.aLis.each(function(li,i){
			var thumb = li.getElement("img");
			var srcThumb = thumb.getProperty("src");
			var thumbName = srcThumb.substring(srcThumb.lastIndexOf("/")+1);
			var prefixeImg = thumbName.substring(0, thumbName.length-11);
			var suffixeImg = thumbName.substring(thumbName.lastIndexOf("_"));
			smallImgArray.push(src+prefixeImg+small+suffixeImg);
			mediumImgArray.push(src+prefixeImg+medium+suffixeImg);
			largeImgArray.push(src+prefixeImg+large+suffixeImg);
			
			li.addEvent("mouseover", function(e){
				slider.getElement("div.bigImg").getElement("img").setProperty("src",myArray[i]);
				
				if(_self.linkImgZoom != null){
					_self.linkImgZoom.setProperty("href", myArray[i]);
					_self.linkImgZoom.setProperty("index", i);
				}
				
				li.getAllPrevious("li").removeClass("current");
				li.getAllNext("li").removeClass("current");
				li.addClass("current");
			});
		});
		
		var myImagesMedium = new Asset.image(mediumImgArray);
		var myImagesLarge = new Asset.image(largeImgArray);
		
		
		var _self = this;
		
		//si la taille du ul est inferieur a la taille du masque, on laisse les bouton prev et next caches
		if(this.ulWidth < maskSize)
		{
			this.slidePrev.addClass("inactive");
			this.slideNext.addClass("inactive");
		}
		//si la taille du ul est superieur a la taille du masque
		//et la marge gauche est egale a 0 on cache uniquement le bouton next
		else if(this.ulWidth > maskSize && this.ul.getStyle("marginLeft") == "0px")
		{
			this.slideNext.removeClass("inactive");
		}
		
		
		//au click sur le bouton prev : slide vers la gauche
		this.slidePrev.addEvent("click", function(e){
			e.stop();
			if(_self.locked) return;
			var actualMarginL = _self.ul.getStyle("marginLeft").toInt();
			var setMarginL = actualMarginL + totalW;
			if(setMarginL > 0){
				_self.slidePrev.addClass("inactive");
			}else{
				if(_self.slideNext.hasClass("inactive")) _self.slideNext.removeClass("inactive");
				_self.slide(_self.ul,setMarginL,maxMarginL,_self.slidePrev);
			}
			return false;
		});
		
		
		//au click sur le bouton next : slide vers la droite
		this.slideNext.addEvent("click", function(e){
			e.stop();
			if(_self.locked) return;
			var actualMarginL = _self.ul.getStyle("marginLeft").toInt();
			var setMarginL = actualMarginL - totalW;
			if(setMarginL < maxMarginL){
				_self.slideNext.addClass("inactive");
			}else{
				//_self.ul.setStyle("marginLeft",setMarginL+"px");
				if(_self.slidePrev.hasClass("inactive")) _self.slidePrev.removeClass("inactive");
				_self.slide(_self.ul,setMarginL,maxMarginL,_self.slideNext);
			}
			return false;
		});
		
		
		if(this.linkImgZoom != null){
			this.linkImgZoom.addEvent("click", function(e){
				e.stop();
				var url = this.href.replace(/MEDIUM/, "LARGE");
				var mobileSlider = $('mobileSlider');
				mobileSlider.getElement("div.bigImg").getElement("img").setProperty("src",url);
				new fogManager().open('mobileSlider');
			});
		}
	},
	
	
	slide: function(element, value, maxMarginL, slideArrow){
		var _self = this;
		var myFx = new Fx.Tween(element, {
			onComplete: function(){
				_self.locked = false;
				if(element.getStyle("marginLeft") == maxMarginL+"px" || element.getStyle("marginLeft") == "0px")
				{
					$(slideArrow).addClass("inactive");
				}
			},
			onStart: function(){
				_self.locked = true;
			}
		});
		myFx.start("marginLeft", value+"px");
	}
});

Module.register("F6Slider","div.slider", ["4", "MEDIUM"]);
Module.register("F6Slider","div.sliderLarge", ["4", "LARGE"]);


var validateForm = new Class({
	initialize: function (form, options){
		new FormValidator.Inline(form, {
			onElementValidate: function(isValid, field, className, warn){
				var label = $(getLabel(field));
				if(label)
					isValid ?
						label.removeClass("validation-failed") :
						label.addClass("validation-failed");
			},
			onElementFail: function (){trace(arguments)},
			scrollToErrorsOnSubmit: false,
			evaluateOnSubmit: true,
			evaluateFieldsOnBlur: true,
			evaluateFieldsOnChange: true,
			serial: false
		});
	}
});
Module.register("validateForm", "form.toValidate");

var validateForm2 = new Class({
	initialize: function (form, options){
		new FormValidator.Inline(form, {
			onElementValidate: function(isValid, field, className, warn){
				var label = $(getLabel(field));
				if(label)
					isValid ?
						label.removeClass("validation-failed") :
						label.addClass("validation-failed");
			},
			onElementFail: function (){trace(arguments)},
			scrollToErrorsOnSubmit: false,
			evaluateOnSubmit: true,
			evaluateFieldsOnBlur: false,
			evaluateFieldsOnChange: false,
			serial: false
		});
	}
});
Module.register("validateForm2", "form.toValidateOnEnd");


var validateFormLayer = new Class({
	initialize: function (form, options){
		if(!$('errorLayer')){
			var html = [
			'<div class="blockInside doubleGradientDark">',
			'<div class="head redHead">',
			'<a href="#" class="layerClose">X</a>',
			'</div>',
			'<div class="body" id="errorLayerCtn"></div>',
			'<div class="foot txtC">',
			'<a href="#" class="layerClose btn btnRedSmall"><span>FERMER</span></a>',
			'</div>',
			'</div>'
			].join('');
			new Element('div', {id:"errorLayer", "class":"hidden layer", html: html}).inject(document.body);
		}
		
		new FormValidator.Inline(form, {
			onFormValidate: function(passed, form, event) {
				if (passed) {
					// here goes ajax submit
				}
				else {
					new fogManager("errorLayer", options);
				}
			},
			serial: true,
			scrollToErrorsOnSubmit: false
		});
	}
});
Module.register("validateFormLayer", "form.toValidateLayer", {duration:100, styles:{backgroundColor:"000"}});

/**
 * Module de validation de formulaire avec affichage d'une infobulle (tooltip) au dessus du formulaire en regroupant 
 * tous les messages d'erreur. Attention , le label des champs doit être indiqué sur le title.
 * ex : <input type="text" value="email" title="Adresse e-mail" class="input100px required" />
 * Cette classe servira à identifier le champ dans le message d'erreur.
 *  
 */
var validateFormTips = new Class({
	initialize: function (form, options){
		// in FormValidator.js
		var errorMessagesPool = [];
		var formTip = new TipsFix(form, {
			fixed : true,
			className : 'errorToolTip',
			positionFrom : $(form).getElement("input[type='text']")
		});
		new FormValidator(form, {
			evaluateFieldsOnBlur : false,
			ignoreHidden:false,
			onFormValidate: function(passed, form, event) {
				if (passed) {
					formTip.hide();
					// here goes ajax submit
				}
				else {
					formTip.text = errorMessagesPool.filter(function(obj, index, array){
						for (var i=0; i<array.length; i++) {
							if(array[i]!=obj && array[i].field == obj.field && array[i].msg == obj.msg)
								return false;
							return true;
						}
					}).map(function(obj){
						var title = obj.field.getAttribute('title') ? obj.field.getAttribute('title') + ' : ' : '';
						return  title + obj.msg;
					}).join('<br>\n');
					formTip.show();
					
					
					
					var closer = new Element("span", {"class":"closeTip"});
					closer.addEvent("click", function (e){
						this.hide();
						e.target.dispose();
					}.bind(formTip));
					if(!formTip.container.getElement(".closeTip")) closer.inject(formTip.container, "top");
					errorMessagesPool = [];
					event.preventDefault();
				}
			},
			
			onElementValidate: function(isValid, field, className, warn){
				var label = $(getLabel(field));
				if(label)
					isValid ?
						label.removeClass("validation-failed") :
						label.addClass("validation-failed");
			},
				
			onElementPass: function (field){/* si controle OK*/
				//field.set('title', "");
			},
			onElementFail: function (field, validatorsFailed){/* si controle KO*/
				errorMessagesPool.push({
					field: field,
					msg: FormValidator.getValidator(validatorsFailed[0]).getError(field)
				});
			},
			scrollToErrorsOnSubmit: false
		});
	}
});
Module.register("validateFormTips", "form.toValidateTips");


/**
 * Module pour autoBalancer les valeurs d'un select avec un autre. 
 * Ce module n'est seulement utilisé que dans les select adultes/enfants
 * @params par CSS : 
 * autoBalance-max:N	N est le nombre max possible qu'on peut obtenir en additionnant les values des 2 selects 
 * 
 * Exemple : 
 * <div class="autoBalanceSelect autoBalance-max:6">
		<select>
			<option>1</option>
			<option>2</option>
		</select>
		<select> 
			<option>0</option>
			<option>1</option>
			<option>2</option>
		</select>
	</div>

 */
var AutoBalanceSelect = new Class({
	max : 6,
	optionsSaved:false,
	initialize: function (container){
		this.container = $(container);
		
		var maxStr = this.container.className.match(/autoBalance\-max\:(\d)+/);
		if (maxStr.length>2) this.max = maxStr[1];
		
		this.selects = $(container).getElements('select');
		this.selects.each(function(select){
			$(select).addEvent('change', this.selectChangeHandler.bind(this));
		},this)
	},
	
	saveOptions : function() {
		this.selects.each(function(select){
			var oldI = select.selectedIndex;
			select.savedOptions = [];
			while(select.options.length>0)
				select.savedOptions.push($(select.options[0]).dispose());
			select.savedOptions.each(function(option){select.adopt(option)});
			select.selectedIndex = oldI;
		}, this)
		this.optionsSaved=true;
	},
	
	selectChangeHandler : function(e) {
		if(!this.optionsSaved) this.saveOptions();
		var e = new Event(e);
		var value = e.target.value*1;
		
		var maxSelVal = this.max-value;
		this.selects.each(function(select){
			
			if(select != e.target) {
				var oldIndex = select.selectedIndex;
				while(select.firstChild)
					select.removeChild(select.firstChild);
				var option,i=0;
				do {
					var option = select.savedOptions[i];
					if (option) {
						select.adopt(option);
					}
					i++;
				} while(option && option.value<maxSelVal)
				select.selectedIndex = oldIndex;
			}
		},this)
	}
});
Module.register("AutoBalanceSelect", "div.autoBalanceSelect");

/* SCROLL */
var scrollToAnchor = new Class({
	initialize: function(anchor){
		this.anchor = $(anchor);
		this.link = this.anchor.getProperty("href");
		this.hrefToID = this.link.substring(1);
		
		var _self = this;
		
		this.anchor.addEvent("click", function(e){
			_self.scrollTo(_self.hrefToID);
			return false;
		});
	},
	
	scrollTo: function(toElement){
		var myScroll = new Fx.Scroll(document.body).toElement(toElement);
	}
});
Module.register("scrollToAnchor", "a.scrollAnchor")


/* carrousel */
var Carrousel = new Class({
	initialize: function(carrousel){
		this.carrousel = $(carrousel);
		this.aLis = this.carrousel.getElement("ul").getElements("li");
		this.anchor = this.aLis.getElement("a");
		this.img = this.anchor.getElement("img.mobile");
		this.legende = this.carrousel.getElement("div.legende");
		this.cursor = this.legende.getElement("div.curseur");
		
		this.carrousel.getParent(".line").adopt(new Element('div', {"id": "iphoneSeparator"}));
		$("iphoneSeparator").setStyle("left", this.carrousel.getParent(".line").getFirst().offsetWidth + 8);
		
		var _self = this;
		
		this.anchor.addEvent("mouseover", function(e){
			var position = this.getProperty("class").substring(4);
			var imgAlt= this.getElement("img.mobile").getProperty("alt");
			var telName = imgAlt.substring(0,imgAlt.lastIndexOf("|")+1);
			var telPrice = imgAlt.substring(imgAlt.lastIndexOf("|")+1)
			if(position < 65){
				_self.cursor.setStyle("backgroundImage","url(/css/skin/curseur_carrousel_dark.png)");
			}else{
				_self.cursor.setStyle("backgroundImage","url(/css/skin/curseur_carrousel.png)");
			}
			_self.cursor.setStyle("backgroundPosition",position+"px top");
			_self.legende.getElement("div.telName").set("html",telName);
			_self.legende.getElement("div.telPrice").set("html",telPrice);
		});
	}
});
Module.register("Carrousel", "div.carrousel");


/* tipbox générique */
/* 	
	caution :
		this script is using an extended version of mootools Tips plugin which can be found in object.js file
	remember !!! 
		the Mootools Tips can be used width the couples : a/title or _otherTag_/rel
	
	generated HTML :
	<div class="options.className"> //the className you pass in options will be assigned here.
	    <div class="tip-top"></div> //useful for styling

	    <div class="tip">

	        <div class="tip-title"></div>

	        <div class="tip-text"></div>

	    </div>

	    <div class="tip-bottom"></div> //useful for styling
	</div>
	
*/
var AllTips = new Class({
	initialize: function(elm){
		var MyBrowser = Browser.detect();
		var optionalClass = 'globTipBox';
		var optionalOffset = {'x': -16, 'y': -30};
		if (document.documentElement.getAttribute('dir')=='rtl'){
			if (MyBrowser.name=="trident" && (MyBrowser.version==5 || MyBrowser.version==4) && !(document.querySelectorAll)){
				optionalOffset = {'x': -36, 'y': -30};
			}else{
				optionalOffset = {'x': -18, 'y': -30};
			}
		}
		if (!!elm.className.match(/\btipBoxDown\b/)){
			optionalClass = 'globTipBox globTipBoxDown';
			optionalOffset = {'x': -16, 'y': 10};
		}
		var myTip = new CustomTip(elm, {
			className : optionalClass,
			offset : optionalOffset
		});
	}
	
});
Module.register("AllTips", "*.tipBox");


/* simple toggler */
/*
	HTML example
		<div class="toggler">
			<a href="#" class="handler">Link</a>
			<div class="togglerOpenCtt">
				Toggleing Ctt
			</div>
		</div>	
*/
var SimpleToggler = new Class({
	initialize: function(elm){
		var handlers = $(elm).getElements('.handler');
		var toggler = new Toggler(elm, handlers,'open');
	}
});
//launch toggle on a simple toggler
Module.register("SimpleToggler", "div.toggler");


var FaqToggler = new Class({
	initialize: function(elm){
		var handlers = $(elm).getElements('.question a');
		var toggler = new Toggler(elm, handlers,'faqOpen');
	}
});
//launch toggle on block faq
Module.register("FaqToggler", "div.faq");


var CartRMC = new Class({
	initialize: function(elm){
		var handlers = $(elm).getElements('.handler');
		var toggler = new Toggler(elm, handlers,'ct_village_rmc_open');
	}	
});
//launch toggle on block faq
Module.register("CartRMC", "div.ct_village_rmc");





var AutomaticTodayDate = new Class({
   initialize : function(elm) {
       var z = this.zeroFill;
       var d = new Date();
       var mask = elm.getAttribute('value');
       d.setDate(d.getDate()+1);
	   var day = z(d.getDate());

       
       var month = z(d.getMonth()+1);
       var year = d.getFullYear();
		
		
       if(elm.value.match(/mm|dd|yyyy/i)) {
           elm.value = mask.replace(/dd/i,day ).replace(/mm/i,month).replace(/yyyy/i,year);
       }
   },

   zeroFill : function(num) {
       if(num<10)
           return '0'+num;
       return num;
   }
})
Module.register("AutomaticTodayDate", 'input.automaticTodayDate')



/* inputAllChecking */

var InputAllChecking = new Class({
	initialize: function(elm){

		var _this = this;
		this.leadInput = elm.getElement('input.all');
		this.allInputs = elm.getElements('input');
		this.allInputs.erase(this.leadInput);
		this.leadInput.addEvent('click', function(e){
			_this.toggleInputs()
		})
		this.allInputs.each(function(el){
			el.addEvent('click', function(e){
				_this.leadInput.checked = false;
			})
		})
		this.toggleInputs();
	},
	toggleInputs : function(){
		if(this.leadInput.checked){
			this.allInputs.each(function(el){
				el.checked = true;
			})
		}else{
			this.allInputs.each(function(el){
				el.checked = false;
			})
		}
	}
	
});
//launch inputAllChecking
Module.register("InputAllChecking", "*.inputAllChecking");




/* TwoBrosSelects */

var TwoBrosSelects = new Class({
	initialize: function(elm){
		var _this = this;
		//recupération des selects
		this.first = elm.getElement('.firstBrosSelects');
		this.second = elm.getElement('.secondBrosSelects');
		//recupération de la liste du premier select
		this.list = this.first.getChildren().clone();
		
		//ajout d'evenements
		this.first.addEvent('change', this.change.bind(this));
		
		
	},
	change : function(){
		if(this.first.selectedIndex == 0)
			return;
		
			
		this.second.getChildren().each(function(el){
			this.second.removeChild(el); 
		}.bind(this))
		//creation de la string
		this.list.each(function(el){
			//si non séléctionné
			if (el.value !=  this.first.options[this.first.selectedIndex].value){
				this.second.appendChild(el);
			}
		}.bind(this));
		this.second.selectedIndex = 0;
	}
	
});
//launch twoBrosSelects
Module.register("TwoBrosSelects", "*.twoBrosSelects");


// http://clubmed.tibo.f6.fr/?dir=rtl charge la page avec les params rtl
if(getQueryString("dir") == "rtl") switchDirection();
