// accordion.js v2.0
//
// Copyright (c) 2007 stickmanlabs
// Author: Kevin P Miller | http://www.stickmanlabs.com
// 
// Accordion is freely distributable under the terms of an MIT-style license.
//
// I don't care what you think about the file size...
//   Be a pro: 
//	    http://www.thinkvitamin.com/features/webapps/serving-javascript-fast
//      http://rakaz.nl/item/make_your_pages_load_faster_by_combining_and_compressing_javascript_and_css_files
//

/*-----------------------------------------------------------------------------------------------*/

if (typeof Effect == 'undefined') 
	throw("accordion.js requires including script.aculo.us' effects.js library!");

var accordion = Class.create();
accordion.prototype = {

	//
	//  Setup the Variables
	//
	showAccordion : null,
	currentAccordion : null,
	duration : null,
	effects : [],
	animating : false,
	
	//  
	//  Initialize the accordions
	//
	initialize: function(container, options) {
	  if (!$(container)) {
	    throw(container+" doesn't exist!");
	    return false;
	  }
	  
		this.options = Object.extend({
			resizeSpeed : 8,
			classNames : {
				toggle : 'accordion_toggle',
				toggleActive : 'accordion_toggle_active',
				content : 'accordion_content'
			},
			defaultSize : {
				height : null,
				width : null
			},
			direction : 'vertical',
			onEvent : 'click'
		}, options || {});
		
		this.duration = ((11-this.options.resizeSpeed)*0.15);

		var accordions = $$('#'+container+' .'+this.options.classNames.toggle);
		accordions.each(function(accordion) {
			Event.observe(accordion, this.options.onEvent, this.activate.bind(this, accordion), false);
			if (this.options.onEvent == 'click') {
			  accordion.onclick = function() {return false;};
			}
			
			if (this.options.direction == 'horizontal') {
				var options = {width: '0px', display:'none'};
			} else {
				var options = {height: '0px', display:'none'};
			}
//			options.merge({display: 'none'});			
			
			this.currentAccordion = $(accordion.next(0)).setStyle(options);
		}.bind(this));
	},
	
	//
	//  Activate an accordion
	//
	activate : function(accordion) {
		if (this.animating) {
			return false;
		}
		
		this.effects = [];
	
		this.currentAccordion = $(accordion.next(0));
		this.currentAccordion.setStyle({
			display: 'block'
		});		
		
		this.currentAccordion.previous(0).addClassName(this.options.classNames.toggleActive);

		if (this.options.direction == 'horizontal') {
			this.scaling = $H({
				scaleX: true,
				scaleY: false
			});
		} else {
			this.scaling = $H({
				scaleX: false,
				scaleY: true
			});			
		}
			
		if (this.currentAccordion == this.showAccordion) {
		  this.deactivate();
		} else {
		  this._handleAccordion();
		}
	},
	// 
	// Deactivate an active accordion
	//
	deactivate : function() {
		var options = $H({
		  duration: this.duration,
			scaleContent: false,
			transition: Effect.Transitions.sinoidal,
			queue: {
				position: 'end', 
				scope: 'accordionAnimation'
			},
			scaleMode: { 
				originalHeight: this.options.defaultSize.height ? this.options.defaultSize.height : this.currentAccordion.scrollHeight,
				originalWidth: this.options.defaultSize.width ? this.options.defaultSize.width : this.currentAccordion.scrollWidth
			},
			afterFinish: function() {
				this.showAccordion.setStyle({
          height: 'auto',
					display: 'none'
				});				
				this.showAccordion = null;
				this.animating = false;
			}.bind(this)
		});    
//    options.merge(this.scaling);

    this.showAccordion.previous(0).removeClassName(this.options.classNames.toggleActive);
    
		new Effect.Scale(this.showAccordion, 0, options.update(this.scaling).toObject());
	},

  //
  // Handle the open/close actions of the accordion
  //
	_handleAccordion : function() {
		var options = $H({
			sync: true,
			scaleFrom: 0,
			scaleContent: false,
			transition: Effect.Transitions.sinoidal,
			scaleMode: { 
				originalHeight: this.options.defaultSize.height ? this.options.defaultSize.height : this.currentAccordion.scrollHeight,
				originalWidth: this.options.defaultSize.width ? this.options.defaultSize.width : this.currentAccordion.scrollWidth
			}
		});
		options.merge(this.scaling);
		
		this.effects.push(
			new Effect.Scale(this.currentAccordion, 100, options.update(this.scaling).toObject())
		);

		if (this.showAccordion) {
			this.showAccordion.previous(0).removeClassName(this.options.classNames.toggleActive);
			
			options = $H({
				sync: true,
				scaleContent: false,
				transition: Effect.Transitions.sinoidal
			});
			options.merge(this.scaling);
			
			this.effects.push(
				new Effect.Scale(this.showAccordion, 0, options.update(this.scaling).toObject())
			);				
		}
		
    new Effect.Parallel(this.effects, {
			duration: this.duration, 
			queue: {
				position: 'end', 
				scope: 'accordionAnimation'
			},
			beforeStart: function() {
				this.animating = true;
			}.bind(this),
			afterFinish: function() {
				if (this.showAccordion) {
					this.showAccordion.setStyle({
						display: 'none'
					});				
				}
				$(this.currentAccordion).setStyle({
				  height: 'auto'
				});
				this.showAccordion = this.currentAccordion;
				this.animating = false;
			}.bind(this)
		});
	}
}
//
// ===== Ajout d'une methode d'annulation des appels asynchrones
Ajax.Request.prototype.abort = function() {
    this.transport.onreadystatechange = Prototype.emptyFunction;
    this.transport.abort();
    Ajax.activeRequestCount--;
};
//
// ===== Debug
if (typeof print_r == 'undefined') {
	function print_r(a, n) {
		var s = "";
		if(!n) n = 0;
		var sEspace = "";
		for (var j = 0; j < n + 1; j++) sEspace += "    ";
		if (typeof(a) == 'object') {
	 		for (var item in a) {
	  			var value = a[item];
	  			if (typeof(value) == 'object') {
	   				s += sEspace+"'"+item+"' ...\n";
	   				s += print_r(value, n+1);
	  			} else {
	   				s += sEspace+"'"+item+"' => \""+value+"\"\n";
	  			}
	 		}
		} else {
	 		s = "==> "+a+" <== ("+typeof(a)+")";
		}
		return s;
	}
}
if (typeof ResizingTextArea == 'undefined') {
	/*  ResizeableTextarea for the Prototype JavaScript framework, version 0.2
	 *  (c) 2006 Bermi Ferrer <info -a-t bermi org>
	 *
	 *  ResizeableTextarea is freely distributable under the terms of an MIT-style license.
	 *
	 *  Requirements: Prototype JS framework http://prototypejs.org/
	 *  Ussage: Add this attribute to the textarea you want to resize 
	 *
	 *    onfocus="new ResizeableTextarea(this);"
	 *
	/*--------------------------------------------------------------------------*/
	var ResizingTextArea = Class.create();
	ResizingTextArea.prototype = {
	    defaultRows: 1,
	    initialize: function(field)
	    {
	        this.defaultRows = Math.max(field.rows, 1);
	        this.resizeNeeded = this.resizeNeeded.bindAsEventListener(this);
	        Event.observe(field, "click", this.resizeNeeded);
	        Event.observe(field, "keyup", this.resizeNeeded);
	    },
	    resizeNeeded: function(event)
	    {
	        var t = Event.element(event);
	        var lines = t.value.split('\n');
	        var newRows = lines.length;// + 1;
	        var oldRows = t.rows;
	        for (var i = 0; i <lines.length; i++)
	        {
	            var line = lines[i];
	            if (line.length>= t.cols) newRows += Math.floor(line.length / t.cols);
	        }
	        if (newRows> t.rows) t.rows = newRows;
	        if (newRows <t.rows) t.rows = Math.max(this.defaultRows, newRows);
	    }
	}
}
if (typeof popUp == 'undefined') {
	/**
	 * Function: popUp
	 * 
	 * Parameters:
	 *  - String url a appeler
	 *  - String id de la fenetre
	 *  - Number largeur
	 *  - Number hauteur
	 *  - Int 1 pour afficher la scrollbar, sinon 0
	 */	 	 	
	var popUp = function(sUrl, sId, nLargeur, nHauteur, nScrollBar) {
		var nX = (screen.availWidth) ? Math.round(screen.availWidth/2 - nLargeur/2) : 0;
	  	var nY = (screen.availHeight) ? Math.round(screen.availHeight/2 -nHauteur/2) : 0;
	  	var sOptions = 'width='+nLargeur+',height='+nHauteur+',left='+nX+',top='+nY+',scrollbars='+nScrollBar+',resizable=no';
	  	fenetreFocus = window.open(sUrl, sId, sOptions);
	  	try {
	  		if (fenetreFocus.window.focus) fenetreFocus.window.focus();
	  		return fenetreFocus;
		} catch(e) {} 
	};
}
if (typeof JSClient == 'undefined') {
	/**
	 * Object: JSClient
	 * Recuperation du "innerWidth" et "innerHeight" (initialisation automatique), 
	 * actualisation auto des valeurs lors du redimensionnement du client
	 * 
	 * 	Usage:
	 * 	 JSClient.nLARGEUR pour recuperer la largeur en Number
	 * 	 JSClient.nLARGEUR pour recuperer la hauteur en Number	 
	 */	 
	var JSClient = {INSTANCE:null};
	JSClient.initialise = function() {
		if (JSClient.INSTANCE == null) {
			JSClient.INSTANCE = this;
			JSClient.nLARGEUR = 0;
			JSClient.nHAUTEUR = 0;
			JSClient.actualiseDimensions();
			Event.observe(window, 'resize', function(event) { 
				JSClient.actualiseDimensions(); 
			});
		}
	};
	JSClient.actualiseDimensions = function() {
		if (typeof(window.innerWidth) == 'number') {
		    JSClient.nLARGEUR = window.innerWidth;
		    JSClient.nHAUTEUR = window.innerHeight;
		} else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
			// IE 6+ en 'standards compliant mode'
			JSClient.nLARGEUR = document.documentElement.clientWidth;
			JSClient.nHAUTEUR = document.documentElement.clientHeight;
		} else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
			// IE 4 compatible
			JSClient.nLARGEUR = document.body.clientWidth;
			JSClient.nHAUTEUR = document.body.clientHeight;
		}
	};
	JSClient.initialise();
}
if (typeof MEService == 'undefined') {
	/**
	 * Class: MEService
	 * Mode ajax des includes Master Edit
	 */	 	 	 	
	var MEService = {	
		_sURL:"",
		sAJAX_REQUEST:'Ajax.Request',
		sAJAX_UPDATER:'Ajax.Updater',
		/**
		 * Method: setURL
		 * 
		 * Parameters:
		 *  - String url du controleur
		 */		 		
		setURL:function(valeur) {
			this._sURL = valeur;
		},
		/**
		 * Method: appelle
		 * Effectue un Ajax.Request
		 * 
		 * Parameters:
		 *  - String classe
		 *  - String methode
		 *  - * parametres
		 *  - Ecouteurs de la reponse : surSucces, surErreur 		 		 		 		 		 
		 */		 		 		
		appelle:function(sClasse, sMethode, parametres, oEcouteur) {			
			var oParametres = {
				sClasse:sClasse, 
				sMethode:sMethode, 
				sType:MEService.sAJAX_REQUEST,
				sJson:Object.toJSON(parametres)
			};
			new Ajax.Request(this._sURL, {
				parameters:oParametres, 
				onComplete:function(event) {
					var reponse = (event.responseText.isJSON()) ? event.responseText.evalJSON() : event.responseText;
					if (typeof oEcouteur.surSucces == 'function') {
						oEcouteur.surSucces.apply(oEcouteur, [reponse]);
					}
				},
				onFailure:function(event) {
					Event.stop(event);
					if (typeof oEcouteur.surErreur == 'function') {
						oEcouteur.surErreur.apply(oEcouteur, [event]);
					}
				}
			})
		},
		/**
		 * Method: affiche
		 * Effectue un Ajax.Updater
		 * 
		 * Parameters:
		 *  - String id de l'element html de destination
		 *  - String classe
		 *  - String methode
		 *  - * parametres
		 *  - Ecouteurs de la reponse : surSucces	 		 		 		 		 		 		 
		 */
		affiche:function(sBoiteReponse, sClasse, sMethode, parametres, oEcouteur) {
			var oParametres = {
				sClasse:sClasse, 
				sMethode:sMethode, 
				sType:MEService.sAJAX_UPDATER,
				sJson:Object.toJSON(parametres)
			};
			new Ajax.Updater(sBoiteReponse, this._sURL, {
				evalScripts:true,
				parameters:oParametres, 
				onComplete:function(event) {
					if (typeof oEcouteur.surSucces == 'function') {
						oEcouteur.surSucces.apply(oEcouteur, [event.responseText]);
					}
				}
			});
		}
	};
}
if (typeof Fenetre == 'undefined') {
	/**
	 * Class: Fenetre
	 * Boites de dialogues modales
	 */	
	var Fenetre = {
		_aEcouteurs:[],
		_delegue:function(i) {
			if (typeof this._aEcouteurs[i].callback == 'function') this._aEcouteurs[i].callback();
		},
		_verifieHtml:function(s) {
			if (s.indexOf('<') != 0) {
				s = "<span>"+s+"</span>";
			}
			return s;
		},
		alerte:function(sTitre, sHtml, fCallbackFermeture) {
			Modalbox.show(this._verifieHtml(sHtml), {title:sTitre, afterHide:function() {
				if (typeof fCallbackFermeture == 'function') fCallbackFermeture();
			}});
		},
		/**
		 * Method: questionne
		 *
		 * Parametres:
		 *  - String question a poser
		 *  - Array de la forme 
		 * 	[ 
		 *		{
		 *			libelle:'libelle du bouton', 
		 *			callback:function() { alert('fonction invoquee lors du clic sur le bouton...'); }; 
		 *		}, 
		 *		... 
		 *	] 		  		 
		 */		 		 		 		
		questionne:function(sQuestion, aEcouteurs) {
			var sHtml = "";
			this._aEcouteurs = aEcouteurs || [];
			this._aEcouteurs.each(function(oEcouteur, i) {
					sHtml += "<input type=\"button\" value=\""+oEcouteur.libelle+"\" onclick=\"Fenetre._delegue("+i+");\" />&nbsp;";
			});
			sHtml = "<div style=\"text-align:center;\">"+sHtml+"</div>";
			Modalbox.show(sHtml, {evalScripts:true, title:sQuestion});
		}
	};
}
/**
 * =============================================
 * Class: Infobulle
 * Dependant de Prototype
 *  v 0.1
 * ============================================= 
 */ 
var Infobulle = Class.create();
Infobulle.prototype = {
	/**
	 * ====================================
	 * GROUP: Methodes publiques
	 * ====================================	 	 
	 *	 	
	 * Method: initialize
	 *
	 * Parameters:
 	 *  
	 */	 
	initialize: function() {
		if ($('__infobulle') == null) {
			this.MARGE_CURSEUR = 10;
			new Insertion.Top('body', "<div id='__infobulle' style='position:absolute; display:none;'></div>");
			$('__infobulle').setStyle({
				zIndex: 10001,
				position: 'absolute',
				backgroundColor: '#fff',
				margin: 0,
				padding: '5px',
				top: 0,
				left: 0,
				font: '11px Verdana, Arial, Geneva',
				border: '1px solid #ccc'
			});
		}
	},
	setStyle: function(o) {
		$('__infobulle').setStyle(o);
	},
	/**
	 * Method: affiche
	 *
	 * Parameters:
	 * 	- sHtml, String le contenu (html ou non) de l'infobulle	 	 
	 */	 	 	
	affiche: function(sHtml) {
		Event.stopObserving(document, 'mousemove', this._bouge.bindAsEventListener(this));
		Event.observe(document, 'mousemove', this._bouge.bindAsEventListener(this));
		$('__infobulle').update(sHtml);
		$('__infobulle').setStyle({position:'absolute', display:'inline'});
	},
	/**
	 * Method: masque
	 *  Masque l'infobulle	 
	 */	
	masque: function() {
		if ($('__infobulle') != null) {
			Event.stopObserving(document, 'mousemove', this._bouge.bindAsEventListener(this));
			$('__infobulle').setStyle({position:'absolute', display:'none'});
		}
	},
	/**
	 * ====================================
	 * GROUP: Methodes privees
	 * ====================================	 	 
	 *	 	
	 * Method: _bouge
	 *
	 * Parameters:
 	 *  MouseEvent e
	 */
	_bouge: function(e) {
		if ($('__infobulle') != null) {
			this.setStyle({
				top: Math.min(
					Event.pointerY(e) + this.MARGE_CURSEUR, 
					document.viewport.getHeight() + document.viewport.getScrollOffsets().top - $('__infobulle').getHeight()
				) + "px",
				left: Math.min(
					Event.pointerX(e) + this.MARGE_CURSEUR, 
					document.viewport.getWidth() + document.viewport.getScrollOffsets().left - $('__infobulle').getWidth()
				) + "px"
			});
		}
	}
};





/////////////////////////////////
// DEPRECIE (passage par soap pour retrocompatibilite pronight)
/////////////////////////////////
if (typeof JService == 'undefined') {
	/**
	 * Class: JService
	 * Utililisation du package jservice
	 */	 	 	 	
	var JService = {	
		_sServeur:"",
		/**
		 * Method: setServeur
		 * 
		 * Parameters:
		 *  - String url du serveur		 		 		 
		 */		 		
		setServeur:function(valeur) {
			this._sServeur = valeur;
		},
		/**
		 * Method: appelle
		 * Effectue un Ajax.Request
		 * 
		 * Parameters:
		 *  - String classe
		 *  - String methode
		 *  - * parametres
		 *  - Function de callback si succes
		 *  - Function de callback si erreur		 		 		 		 		 		 		 
		 */		 		 		
		appelle:function(sClasse, sMethode, parametres, fCallbackSucces, fCallbackErreur) {
			var oParametres = {
				sServeur:this._sServeur,
				sClasse:sClasse, 
				sMethode:sMethode, 
				sJson:Object.toJSON(parametres)
			};
			new Ajax.Request('site/httpservices/jservice.php', {
				parameters:oParametres, 
				onComplete:function(event) {
					var reponse = event.responseText.evalJSON();
					if (reponse.JService_erreur != undefined) {
						if (typeof fCallbackErreur == 'function') fCallbackErreur(reponse.JService_erreur);
					} else {
						if (typeof fCallbackSucces == 'function') fCallbackSucces(reponse);
					}
				}
			});
		},
		/**
		 * Method: affiche
		 * Effectue un Ajax.Updater
		 * 
		 * Parameters:
		 *  - String id de l'element html de destination
		 *  - String classe
		 *  - String methode
		 *  - * parametres
		 *  - Function de callback si succes	 		 		 		 		 		 		 
		 */
		affiche:function(sBoiteReponse, sClasse, sMethode, parametres, fCallbackSucces) {
			var oParametres = {
				sServeur:this._sServeur,
				sClasse:sClasse, 
				sMethode:sMethode, 
				sJson:Object.toJSON(parametres)
			};
			new Ajax.Updater(sBoiteReponse, 'site/httpservices/jservice.php', {
				evalScripts:true,
				parameters:oParametres, 
				onComplete:function(event) {
					if (typeof fCallbackSucces == 'function') fCallbackSucces(event.responseText);
				}
			});
		}
	};
}
/**
 * =======================================================================================
 *
 * Class: CompteurNumerique
 *  v 0.2
 */ 
var CompteurNumerique = Class.create();
CompteurNumerique.prototype = {
	/**
	 * ====================================
	 * GROUP: Methodes publiques
	 * ====================================	 	 
	 *	 	
	 * Method: initialize
	 *
	 * Parameters:
 	 *  - String sId, id du champ texte de qte	 
	 */	 	 	
	initialize: function(sId) {
		this.MIN = 1;
		this.MAX =  999;
		this.INCREMENT = 1;
		this.oChampNumerique = $(sId);
		if (this.oChampNumerique.value.length == 0) this.oChampNumerique.value = this.MIN;
		this.btPlus = $(sId+'_plus');
		this.btMoins = $(sId+'_moins');
		this.oChampNumerique.onkeyup = this.verifieSaisie.bind(this);
		this.btPlus.onclick = this.incremente.bind(this);
		this.btMoins.onclick = this.decremente.bind(this);
		
	},
	/**
	 * Method: incremente
	 *
	 *  Incrementation de la quantite	 
	 */	
	incremente: function() {
		if (parseInt(this.oChampNumerique.value) < this.MAX) {
			this.oChampNumerique.value = parseInt(this.oChampNumerique.value) + this.INCREMENT;
		}
	},
	/**
	 * Method: decremente
	 *
	 *  Decrementation de la quantite	 
	 */	
	decremente: function() {
		if (parseInt(this.oChampNumerique.value) > this.MIN) {
			this.oChampNumerique.value = parseInt(this.oChampNumerique.value) - this.INCREMENT;
		}
	},
	/**
	 * Method: verifieSaisie
	 *
	 *  Verification de la saisie, format numerique obligatoire	 
	 */
	verifieSaisie: function() {
		if (this.oChampNumerique.value.length == 0) {
			this.oChampNumerique.value = this.MIN;
		}
		if (!this.verifieEntier(this.oChampNumerique.value)) {
			this.oChampNumerique.value = this.MIN;
		}
	},
	/**
	 * Method: verifieEntier
	 *
	 *  Parameters:
	 *   type non connu valeur
	 *   
	 *  Returns:
	 * 	 Boolean, true si valeur est un entier 	  
	 */
	verifieEntier: function(valeur) {
		return !isNaN(Number(valeur));
	},
	/**
	 * ====================================
	 * GROUP: Setters
	 * ====================================	 	 
	 *	 	
	 * Method: changeIncrement
	 *
	 * Parameters:
 	 *  Int increment de base, si 6 alors 6,12,18,24,etc 
	 */
	changeIncrement: function(nIncrement) {
		this.INCREMENT = nIncrement;
	},
	/**
	 * Method: changeValeurMin
	 *
	 */	 	 	
	changeValeurMin: function(nMin) {
		this.MIN = nMin;
	},
	/**
	 * Method: changeValeur
	 *
	 */	
	changeValeur: function(nValeur) {
		this.oChampNumerique.value = nValeur;
	}
};
/**
 * =======================================================================================
 *
 * Class: Calendrier
 *  v 0.2 
 *   
 * =============================
 *  GROUP: Constantes
 * ============================= 
 * 
 * Var VERSION
 *  Version du Calendrier   
 */ 
Calendrier.VERSION = "0.2"; 
/**
 * Var: _INSTANCE
 *  Numero du calendrier en cours
 */ 
Calendrier._INSTANCE = 0;
/**
 * Var: aMoisFr
 *  Les mois en Francais
 */  
Date.aMoisFr = [
	'Janvier', 'Fevrier', 'Mars', 'Avril', 'Mai', 'Juin', 
	'Juillet', 'Aout', 'Septembre', 'Octobre', 'Novembre', 'Decembre'
];
/**
 * Var: aJoursFeries
 *  Les jours feries Francais
 */  
Date.aJoursFeries = [
	'01/01', '01/05', '08/05', '14/07', '15/08', '01/11', 
	'11/11', '25/12'
];
/**
 * ==================================
 * GROUP: Tools pour le Calendrier
 * ==================================
 * 
 * Method: renvoieJoursDansMois
 *  
 * Returns:
 *  Int le nombre de jour dans le mois (pour un objet de type date)
 */  
Date.prototype.renvoieJoursDansMois = function () {
	var dDateTmp = new Date(this.getFullYear(), this.getMonth(), 1);
	var nJours = 0;
	for (var i = 27; i <= 32; i++) {
		dDateTmp.setDate(i);
		if (dDateTmp.getMonth() != this.getMonth()) {
			nJours = i - 1;
			break;
		}
	}
	return nJours;
};
/**
 * Method: estFerie
 * 
 * Returns:   
 *  Boolean true si ferie (pour un objet de type date) 
 */ 
Date.prototype.estFerie = function (j, m) {
	for (var i = 0; i < Date.aJoursFeries.length; i++) {
		if (Date.aJoursFeries[i].substring(0, 2) == j && Date.aJoursFeries[i].substring(3, 5) == m)
			return true;
	}
	return false;
};
/**
 * Method: renvoiePremierJourDuMois
 * 
 * Returns:   
 *  Int premier jour du mois (pour un objet de type date) 
 */ 
Date.prototype.renvoiePremierJourDuMois = function () { // (ou 0 est dimanche)
	var dDateTmp = new Date(this.getFullYear(), this.getMonth(), 1);
	return (dDateTmp.getDay() == 0) ? 7 : dDateTmp.getDay();
};
/**
 * Method: combleDate
 * 
 * Returns:   
 *  String sur deux caracteres (pour un type nombre) 
 */ 
Number.prototype.combleDate = function () {
	return (this < 10) ? "0"+this : this;
};
/**
 * ==================================
 * Class: Calendrier
 * ==================================
 *  
 * Constructor: Calendrier 
 *  
 */ 
function Calendrier(oAction, oDate, oRestrictions) {
	this._nINSTANCE = ++Calendrier._INSTANCE;
	this._initialise(oAction, oDate, oRestrictions);
};
/**
 * Method: _initialise
 *  Init. du calendrier, a invoquer aussi avant une mise a jour de l'affichage
 *  Dans la fonction de callback, le parametre oEvent contient une representation 
 *  de l'objet date {annee:aaaa, mois:mm, jour:jj } et l'objet cible target  
 *  
 * Parameters:   
 *  oAction: Objet contenant Object scope et String callback
 *  oDate: Object contenant Number annee, Number mois (1 a 12), Number jour
 *  oRestrictions 
 */  
Calendrier.prototype._initialise = function(oAction, oDate, oRestrictions) {
	this._oAction 			= oAction;
	this._oDate 			= oDate;
	this._oRestrictions 	= (oRestrictions == undefined) ? {MIN:{}, MAX:{}} : oRestrictions;
	this._dDate 			= new Date(oDate.annee, oDate.mois-1, oDate.jour);
	this._nJours 			= this._dDate.renvoieJoursDansMois();
	this._nPremierJour 		= this._dDate.renvoiePremierJourDuMois();
	this._sCalque 			= null;
	this._sNomCalque 		= "";
	this._sHtml 			= "";
};
/**
 * Method: affiche
 *  Affichage du calendrier
 *  
 * Parameters:
 *  sNomCalque, String le nom du calque de destination   
 */ 
Calendrier.prototype.affiche = function(sNomCalque) {
	var _THIS_ = this;
	var aJours = [];
	var i = 0, j = 0, k = 0, l = 0, nMoisMin = 0, nMoisMax = 0, nAnneeMin = 0, nAnneeMax = 0;
	var bCliquable;
	if (this._oRestrictions.INTERDITS == undefined) { this._oRestrictions.INTERDITS = []; }
	// Borne des annees
	nAnneeMin = (this._oRestrictions.MIN.annee != undefined) ? this._oRestrictions.MIN.annee : new Date().getFullYear();
	nAnneeMax = (this._oRestrictions.MAX.annee != undefined) ? this._oRestrictions.MAX.annee : new Date().getFullYear() + 100;
	if (nAnneeMin > nAnneeMax) {
		nAnneeMin = new Date().getFullYear();
		nAnneeMax = new Date().getFullYear() + 100;
	}
	// Borne des mois
	nMoisMin = (this._oRestrictions.MIN.mois != undefined && this._dDate.getFullYear() == this._oRestrictions.MIN.annee) ? this._oRestrictions.MIN.mois-1 : 0;
	nMoisMax = (this._oRestrictions.MAX.mois != undefined && this._dDate.getFullYear() == this._oRestrictions.MAX.annee) ? this._oRestrictions.MAX.mois : Date.aMoisFr.length;
	if (nMoisMin > nMoisMax) {
		nMoisMin = 0;
		nMoisMax = Date.aMoisFr.length;
	}
	// !!!!!!!!  Cas particuliers  !!!!!!!!
	if (nMoisMin == this._oRestrictions.MIN.mois-1 && nMoisMin > this._dDate.getMonth()) {
		this._initialise(this._oAction, {annee:this._dDate.getFullYear(), mois:this._oRestrictions.MIN.mois, jour:1}, this._oRestrictions);
		this.affiche(sNomCalque);
	}
	if (nMoisMax == this._oRestrictions.MAX.mois && this._dDate.getMonth() > nMoisMax-1) {
		this._initialise(this._oAction, {annee:this._dDate.getFullYear(), mois:this._oRestrictions.MAX.mois, jour:1}, this._oRestrictions);
		this.affiche(sNomCalque);
	}
	//
	// Borne des jours
	if (this._oRestrictions.MIN.annee == this._dDate.getFullYear() && this._oRestrictions.MIN.mois-1 == this._dDate.getMonth() && this._oRestrictions.MIN.jour != undefined) {
		for (i = 1; i <= this._oRestrictions.MIN.jour; i++) {
			this._oRestrictions.INTERDITS.push({annee:this._dDate.getFullYear(), mois:this._dDate.getMonth(), jour:i});	
		}
	}
	if (this._oRestrictions.MAX.annee == this._dDate.getFullYear() && this._oRestrictions.MAX.mois-1 == this._dDate.getMonth() && this._oRestrictions.MAX.jour != undefined) {
		for (i = this._oRestrictions.MAX.jour+1; i <= this._nJours; i++) {
			this._oRestrictions.INTERDITS.push({annee:this._dDate.getFullYear(), mois:this._dDate.getMonth(), jour:i});
		}
	}
	//
	var nJours7 = this._nJours + this._nPremierJour - 1;
	while (nJours7%7 != 0 && nJours7 <= 50) nJours7++;
	this._sNomCalque = sNomCalque;
	this._sCalque = $(this._sNomCalque);
	this._sCalque.update("");
	this._sHtml = "";
	this._sHtml += "<table class=\"calendrierTableau\">\n"; 
	this._sHtml += "	<tr>\n";
	this._sHtml += "		<td colspan=\"7\" class=\"calendrierLigneFormulaire\">\n";
	this._sHtml += "			<select id=\"selectMois"+this._nINSTANCE+"\">\n";
	for (i = nMoisMin; i < nMoisMax; i++) {
		this._sHtml += "				<option value=\""+i+"\""+((this._dDate.getMonth() == i) ? " selected=\"selected\"" : "")+">"+Date.aMoisFr[i].substr(0, 3)+"</option>";
	}
	this._sHtml += "			</select>\n";
	this._sHtml += "			<select id=\"selectAnnee"+this._nINSTANCE+"\">\n";
	for (i = nAnneeMin; i <= nAnneeMax; i++) {
		this._sHtml += "				<option value=\""+i+"\""+((this._dDate.getFullYear() == i) ? " selected=\"selected\"" : "")+">"+i+"</option>";
	}
	this._sHtml += "			</select>&nbsp;\n";
	this._sHtml += "		</td>\n";
	this._sHtml += "	</tr>\n";
	this._sHtml += "	<tr>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Lu</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Ma</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Me</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Je</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Ve</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Sa</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Di</td>\n";
	this._sHtml += "	</tr>\n";
	for (var i = 1; i <= nJours7; i++) {
		if (i == 1 || (i-1) % 7 == 0) this._sHtml += "	<tr>\n";
		if(i >= this._nPremierJour && j < this._nJours) {
			k = ++j;
			this._sHtml += "		<td class=\"calendrierColonneJour\">\n"; 
			bCliquable = true;
			for (l = 0; l < this._oRestrictions.INTERDITS.length; l++) {
				if (this._oRestrictions.INTERDITS[l].annee == this._dDate.getFullYear() && this._oRestrictions.INTERDITS[l].mois == this._dDate.getMonth() && this._oRestrictions.INTERDITS[l].jour == k) {
					bCliquable = false;
					break;	
				}
			}
			if (bCliquable) {
				this._sHtml += "			<p><a class=\"calendrierLien\" id=\"jour_"+this._nINSTANCE+"_"+i+"\" href=\"javascript:void(0);\">"+k.combleDate()+"</a></p>";
				aJours.push({
					id:'jour_'+this._nINSTANCE+'_'+i, 
					oDate:{annee:this._oDate.annee, mois:this._oDate.mois.combleDate(), jour:k.combleDate()}
				});	
			} else {
				this._sHtml += "			<p class=\"jourInterdit\">"+k.combleDate()+"</p>";
			}
			this._sHtml += "		</td>\n";
			
		} else {
			this._sHtml += "		<td class=\"calendrierColonneJour\">&nbsp;</td>\n";
		}
		if (i % 7 == 0 || i == nJours7) 
			this._sHtml += "	</tr>\n";
	}
	this._sHtml += "</table>\n";
	this._sCalque.update(this._sHtml);
	for (i = 0; i < aJours.length; i++) {
		$(aJours[i].id).i = i;
		$(aJours[i].id).onclick = function() {
			var oArguments = aJours[this.i].oDate;
			oArguments.target = _THIS_;
			_THIS_._oAction.scope[_THIS_._oAction.callback](oArguments);
		};
	}
	$('selectMois'+this._nINSTANCE).onchange = function() {
		var sNomCalque = _THIS_._sNomCalque;
		var oDate = {annee:_THIS_._oDate.annee, mois:Number(this.value)+1, jour:1};
		_THIS_._initialise.apply(_THIS_, [_THIS_._oAction, oDate, _THIS_._oRestrictions]);
		_THIS_.affiche.apply(_THIS_, [sNomCalque]);
	};
	$('selectAnnee'+this._nINSTANCE).onchange = function() {
		var sNomCalque = _THIS_._sNomCalque;
		var oDate = {annee:this.value, mois:_THIS_._oDate.mois, jour:1};
		_THIS_._initialise.apply(_THIS_, [_THIS_._oAction, oDate, _THIS_._oRestrictions]);
		_THIS_.affiche.apply(_THIS_, [sNomCalque]);
	};	
};
/**
 * ==================================
 * GROUP: Specialisation du calendrier
 * ==================================
 *  
 * Method: Calendrier 
 *  A appeler a partir de l'evenement oEvent.target
 */
Calendrier.prototype.ferme = function() {
	this._sCalque.hide();
};
/**
 * Method: toggle
 *  Meme fonctionnement que toggle de prototype (afficher/masquer n fois)
 */  
Calendrier.prototype.toggle = function(sCalque) {
	this.affiche(sCalque);
	$(sCalque).toggle();
}

