// JavaScript Document


	// Fonctions gerant l'affichage et les fonctionnalites d'un calendrier dans la page ----------------------------------------------------------
	// -------------------------------------------------------------------------------------------------------------------------------------------

	/* Liste des fonctions de l'objet Calendar : 
		Fonctions d'initialisation
			public	function init(referenceCalendar:Object)													// Initialisation de l'objet principal avec les donnees transmises et construction du calendrier vide
			private	function init_defaultObj():Object														// Initialisation de l'objet principal avec les donnees par defaut
			private	function addEventListener(event:String, function:Function)								// Creation d'un evenement
			private	function removeEventListener(event:String, function:Function)							// Suppression d'un evenement
		Fonctions d'appel public
			public	function display(tag:Object[facultatif], date:String[facultatif])						// Validation de la date passee en parametre et lancement de l'affichage du calendrier (si pas de date -> la date du jour)
 				->	autres parametres autorises : display(tag:Object[facultatif], year:Number[facultatif], month:Number[facultatif], day:Number[facultatif])
			public 	function hide()																		// Disparition du calendrier et nettoyage des donnees
			public	function change(sensYear:Number, sensMonth:Number)										// Changement de mois ou d'annee du calendrier
			public	function hover(display:Boolean, week:Number)											// Affichage et disparition du surlignage de la semaine survolee
			public	function send_date(year:Number, month:Number, day:Number)								// Envoi la date en cours au format demande et suppression du calendrier
		Fonctions de construction	
			private	function createCalendar_table():Boolean													// Creation des balises HTML pour le tableau vide du calendrier
			private	function createCalendar_popup():Boolean													// Creation des balises HTML pour le pop up contenant le tableau du calendrier
			private	function createCalendar_navigation(year:Number, month:Number)							// Creation des boutons de navigation dans le calendrier
			private	function createCalendar_day(textHiddenStart:String, day:Number, textHiddenEnd):Object	// Creation du lien d'un jour du calendrier avec les textes invisibles
		Fonctions de suppression
			private	function removeCalendar_navigation()													// Suppression des boutons de navigation
			private	function clear_table()																	// Suppression du contenu du calendrier
		Fonctions de remplissage
			private	function fillingup_calendar(tag:Object, year:Number, month:Number, day:Number)			// Remplissage du calendrier et du pop up avec la date choisie
			private	function fillingup_day(year:Number, month:Number, day:Number, week:Number, cell:Number, maxDay:Number, daySelected:Number)	// Remplissage d'une cellule du tableau
			private	function fillingup_week(cell:Number, week:Number)										// Remplissage d'une cellule du numero de la semaine
		Fonction d'outils
			private	function get_numberWeek(year:Number, month:Number, day:Number):Number					// Calcul du numero de la semaine contenant le jour demande
			private	function analyse_dateLimite(date:String):Object											// Analyse la validite des dates minimales et maximales
			private	function check_dateString(date:Array):Object											// Verification de la validite de la date demandee
			private	function convert_format_date(date:String):Object										// Lancement de la convertion d'une date d'une chaine de texte en tableau en fonction du format
			private	function convert_format_stringArray(date:String):Object									// Convertion d'une date d'une chaine de texte en tableau
			private	function is_leapyear(year:Number):Boolean												// Verification que l'annee transmise est bissextile ou pas
	*/	
	
	// Creation de l'objet calendrier
	var Calendar = function(){
		
		// Variables =========================================================================================================
			
			// Variables publiques -------------------------------------------------------------------------------------------
				
				this.months;											// Tableau contenant le nom des differents mois
				this.abbrMonths;										// Tableau contenant les abbreviations a utiliser pour les differents mois
				this.days;												// Tableau contenant le nom des differents jours
				this.abbrDays;											// Tableau contenant les abbreviations a utiliser pour les differents jours
				
				this.textSelected;										// Texte invisible precisant que le jour est selectione
				
				this.week;												// Mot "semaine"
				this.abbrWeek;											// Abbreviation du mot "semaine"
				this.titleWeek;											// Info-bulle du mot "semaine"
				
				this.linkclose;											// Intitule du bouton "fermer"
				
				this.titleMonthPrev;									// Info bulle du lien "mois precedent"
				this.titleYearPrev;										// Info bulle du lien "annee precedente"
				this.titleMonthNext;									// Info bulle du lien "mois suivant"
				this.titleYearNext;										// Info bulle du lien "annee suivante"
				
				this.srcMonthPrev;										// Adresse de l'image "mois precedent"
				this.srcYearPrev;										// Adresse de l'image "annee precedente"
				this.srcMonthNext;										// Adresse de l'image "mois suivant"
				this.srcYearNext;										// Adresse de l'image "annee suivante"
				
				this.altMonthPrev;										// Texte alternatif de l'image "mois precedent"
				this.altYearPrev;										// Texte alternatif de l'image "annee precedente"
				this.altMonthNext;										// Texte alternatif de l'image "mois suivant"
				this.altYearNext;										// Texte alternatif de l'image "annee suivante"
				
				this.mondayFirst;										// Indicateur d'affichage du lundi comme premier jour
				this.numberWeek;										// Affichage du numero de semaine
				
				this.mode;												// Mode d'affichage : popup
				this.format;											// Format d'affichage et de traitement des dates
				
				this.dateMin;											// Date minimale ne pouvant etre franchie
				this.dateMax;											// Date maximale ne pouvant etre franchie
				
				this.classMain;											// Classe a utiliser
				this.classShadow;										// Classe pour l'ombre portee
				this.classCalendar;										// Classe pour le calendrier
				this.classCalendarWeek;									// Classe pour le calendrier selectionnant des semaines
				this.classMonth;										// Classe pour l'abbreviation du mois dans l'entete
				this.classLinksPrev;									// Classe pour le bloc de liens mois et annees precedents
				this.classLinksNext;									// Classe pour le bloc de liens mois et annees suivants
				this.classClose;										// Classe pour le bloc conteneur du tableau
				this.classTable;										// Classe pour le bloc conteneur du tableau
				this.classWeek;											// Classe pour le numero de la semaine
				this.classWeekEnd;										// Classe pour le numero des jours de week end
				this.classSelected;										// Classe pour le numero du jour selectionne
				this.classHover;										// Classe pour la semaine survolee
				this.classHidden;										// Classe pour les textes caches
				
				this.marginLink;										// Marge laterale des liens de navigation
				
				
			// Variables privees ---------------------------------------------------------------------------------------------
			
				this.autorizeHidden;									// Autorisation de suppression du calendrier pour distinguer les clics hors et dans le calendrier
				
				var oMain				= new Object();					// Variable globale
				var oCalendar			= new Object();					// References des balises
				var dDate				= new Date();					// Variable de date
				var RefCalendar;										// Reference a l'objet calendrier
				var Html;												// Class HTMLManager
			
		// ===================================================================================================================
		// Fonctions d'initialisation ========================================================================================
		
			// Fonction initialisant les variables de l'objet calendrier avec les valeurs publiques transmises
			this.init = function(oRef){
				// Blocage du calendrier
				oMain.authorize						= false;
				// Verification de l'existance du calendrier
				if(oCalendar.target && typeof(oCalendar.target) != "undefined" && oCalendar.main && typeof(oCalendar.main) != "undefined") oCalendar.target.removeChild(oCalendar.main);
				// Sauvegarde de la reference a l'objet
				RefCalendar							= oRef;
				// Creation de l'objet par defaut
				oMain								= init_defaultObj();
				// Initialisation de l'objet conteneur de balises
				oCalendar							= new Object();
				// Variable gerant les dates
				dDate								= new Date();
				// Verification des variables de dates publiques
				if(this.months 				&& this.months.length 				== 12)		oMain.months 		= this.months;
				if(this.abbrMonths 			&& this.abbrMonths.length 			== 12)		oMain.abbrMonths	= this.abbrMonths;
				if(this.days 				&& this.days.length 				== 7) 		oMain.days 			= this.days;
				if(this.abbrDays 			&& this.abbrDays.length 			== 7)		oMain.abbrDays		= this.abbrDays;
				if(this.days 				&& this.days.length 				== 7) 		oMain.days 			= this.days;
				if(this.titleWeek			&& this.titleWeek.length 			> 0)		oMain.titleWeek		= this.titleWeek;
				if(this.abbrWeek			&& this.abbrWeek.length 			> 0)		oMain.abbrWeek		= this.abbrWeek;
				if(this.week				&& this.week.length 				> 0)		oMain.week			= this.week;
				if(this.textSelected		&& this.textSelected.length 		> 0)		oMain.textSelected	= this.textSelected;
				if(this.linkclose			&& this.linkclose.length 			> 0)		oMain.linkclose		= this.linkclose;
				if(String(this.numberWeek).toLowerCase() 						== "yes") 	oMain.numberWeek 	= true;
				if(String(this.mondayFirst).toLowerCase() 						== "yes") 	oMain.mondayFirst	= true;
				// Verification des variables d'identification
				if(this.mode				&& this.mode.length 				> 0)		oMain.mode	 		= this.mode;
				oMain.mode																			= String(oMain.mode).toLowerCase();
				if(String(this.selectionweek).toLowerCase()	 					== "yes") 	oMain.selectionweek	= true;
				// Verification des variables de format de date
				if(this.format				&& this.mode.format 				> 0)		oMain.format	 	= this.format;
				if(this.formatweek			&& this.mode.formatweek				> 0)		oMain.formatweek 	= this.formatweek;
				// Verification des variables de limitation
				if(this.dateMin				&& this.dateMin.length 				> 0)		oMain.dateMin		= this.dateMin;
				if(this.dateMax				&& this.dateMax.length 				> 0)		oMain.dateMax		= this.dateMax;
				// Sauvegarde des adresses des images
				oMain.srcMonthPrev					= this.srcMonthPrev;
				oMain.srcYearPrev					= this.srcYearPrev;
				oMain.srcMonthNext					= this.srcMonthNext;
				oMain.srcYearNext					= this.srcYearNext;
				// Sauvegarde des info bulles
				if(this.titleMonthPrev		&& this.titleMonthPrev.length 		>= 0) 		oMain.titleMonthPrev	= this.titleMonthPrev;
				if(this.titleYearPrev		&& this.titleYearPrev.length 		>= 0) 		oMain.titleYearPrev		= this.titleYearPrev;
				if(this.titleMonthNext		&& this.titleMonthNext.length 		>= 0) 		oMain.titleMonthNext	= this.titleMonthNext;
				if(this.titleYearNext		&& this.titleYearNext.length 		>= 0) 		oMain.titleYearNext		= this.titleYearNext;
				// Sauvegarde des textes alternatifs
				if(this.altMonthPrev		&& this.altMonthPrev.length 		>= 0) 		oMain.altMonthPrev		= this.altMonthPrev;
				if(this.altYearPrev			&& this.altYearPrev.length 			>= 0) 		oMain.altYearPrev		= this.altYearPrev;
				if(this.altMonthNext		&& this.altMonthNext.length 		>= 0) 		oMain.altMonthNext		= this.altMonthNext;
				if(this.altYearNext			&& this.altYearNext.length 			>= 0) 		oMain.altYearNext		= this.altYearNext;
				// Sauvegarde des classes
				if(this.classMain			&& this.classMain.length 			>= 0) 		oMain.classMain			= this.classMain;
				if(this.classCalendar		&& this.classCalendar.length 		>= 0) 		oMain.classCalendar		= this.classCalendar;
				if(this.classCalendarWeek	&& this.classCalendarWeek.length 	>= 0) 		oMain.classCalendarWeek	= this.classCalendarWeek;
				if(this.classShadow			&& this.classShadow.length 			>= 0) 		oMain.classShadow		= this.classShadow;
				if(this.classMonth			&& this.classMonth.length 			>= 0) 		oMain.classMonth		= this.classMonth;
				if(this.classLinksPrev		&& this.classLinksPrev.length 		>= 0) 		oMain.classLinksPrev	= this.classLinksPrev;
				if(this.classLinksNext		&& this.classLinksNext.length 		>= 0) 		oMain.classLinksNext	= this.classLinksNext;
				if(this.classClose			&& this.classClose.length 			>= 0) 		oMain.classClose		= this.classClose;
				if(this.classTable			&& this.classTable.length 			>= 0) 		oMain.classTable		= this.classTable;
				if(this.classWeek			&& this.classWeek.length 			>= 0) 		oMain.classWeek			= this.classWeek;
				if(this.classWeekEnd		&& this.classWeekEnd.length 		>= 0) 		oMain.classWeekEnd		= this.classWeekEnd;
				if(this.classSelected		&& this.classSelected.length 		>= 0) 		oMain.classSelected		= this.classSelected;
				if(this.classHover			&& this.classHover.length 			>= 0) 		oMain.classHover		= this.classHover;
				if(this.classHidden			&& this.classHidden.length 			>= 0) 		oMain.classHidden		= this.classHidden;
				if(!isNaN(this.marginLink))													oMain.marginLink		= this.marginLink;
				// Verification de la presence de l'objet HTMLManager pour la creation de tag HTML
				if(typeof(HtmlManager) != "undefined" && typeof(RefCalendar) != "undefined"){
					// Instanciation de la classe
					Html							= new HtmlManager();
					// Creation des balises
					var bOk							= false;
					// Convertion des dates minimales et maximales
					oMain.dateMin					= analyse_dateLimite(oMain.dateMin);
					oMain.dateMax					= analyse_dateLimite(oMain.dateMax);
					if(typeof(oMain.dateMin) == "object" && oMain.dateMin.ok){ if(isNaN(oMain.dateMin.month)){	oMain.dateMin.month = 1; 	} oMain.dateMin.day = 1;										}
					if(typeof(oMain.dateMax) == "object" && oMain.dateMax.ok){ if(isNaN(oMain.dateMin.month)){	oMain.dateMin.month = 12; 	} oMain.dateMax.day = oMain.numberdays[oMain.dateMax.month -1];	}
					// Creation du tableau du calendrier
					bOk								= createCalendar_table();
					if(bOk){
						bOk							= false;
						// Analyse le mode de creation demande
						if(oMain.mode == "popup"){
							// Creation du pop up englobant le tableau du calendrier
							bOk						= createCalendar_popup();
							// Autorisation d'utilisation des fonctions
							oCalendar.main			= oCalendar.popUp;
							if(bOk)oMain.authorize	= true;
						}else{
							// Autorisation d'utilisation des fonctions
							oCalendar.main			= oCalendar.table;
							oMain.authorize			= true;
						}
					}
				}
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction initialisant l'objet principal avec les valeurs par defaut
			function init_defaultObj(){
				var oObj					= new Object();
					oObj.authorize			= false;														// Autorisation globale pour les diverses fonctions
					// Variables de date
					oObj.Dates				= new Object();													// Objet sauvegardant la date affichee
					oObj.Dates.display		= new Object();
					oObj.Dates.display.ok	= false;	
					oObj.Dates.opened		= new Object();
					oObj.Dates.autoFormat	= false;														// Indicateur de formatage automatique de la date meme quand on n'a pas valide le choix
					// Variables du calendrier
					oObj.months				= new Array("January","February","March","April","May","June","July","August","September","October","November","December");	// Liste des noms de mois
					oObj.abbrMonths			= new Array("Jan","Feb","March","April","May","June","July","Aug","Sept","Oct","Nov","Dec");								// Liste des abbreviations des mois	
					oObj.days				= new Array("Sunday","Monday","Thuesday","Wednesday","Thurday","Friday","Saterday");										// Liste des initiales des jours
					oObj.abbrDays			= new Array("S","M","T","W","T","F","S");																					// Liste des initiales des jours
					oObj.numberdays			= new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);	// Nombre de jours par mois
					oObj.titleWeek			= "";															// Info bulle "Semaine"
					oObj.abbrWeek			= "week";														// Abbreviation "Semaine"
					oObj.week				= "week";														// Mot invisible "Semaine"
					oObj.linkclose			= "Close";														// Intitule du bouton "fermer"
					oObj.numberWeek			= false;														// Affichage du numero de la semaine
					oObj.mondayFirst		= false;														// Dimanche comme premier jour de la semaine
					oObj.format				= "DD/MM/YYYY";													// Format d'affichage des dates
					oObj.formatweek			= "Week {WW}: {Start} - {End}";									// Format d'affichage des dates lors de la selection par semaine
					oObj.textSelected		= "selected";													// Texte invisible precisant que le jour est selectionne
					// Variables de balisage
					oObj.mod				= "popup";														// Type de calendrier a afficher
					// Variables d'evenement
					oObj.selectionweek		= false;														// Autorisation de la selection d'une semaine
					// Variables de limitation de date
					oObj.dateMin			= "";															// Date minimale ne pouvant etre franchie
					oObj.dateMax			= "";															// Date maximale ne pouvant etre franchie
					// Variables de info bulles
					oObj.titleMonthPrev		= "";
					oObj.titleYearPrev		= "";
					oObj.titleMonthNext		= "";
					oObj.titleYearNext		= "";
					// Variables de textes alternatifs
					oObj.altMonthPrev		= "";
					oObj.altYearPrev		= "";
					oObj.altMonthNext		= "";
					oObj.altYearNext		= "";
					// Variables de classe css accessoire
					oObj.classMain			= "ep_calendar";												// classe pour le conteneur
					oObj.classShadow		= "ep_shadow";													// classe pour l'ombre portee
					oObj.classCalendar		= "ep_container";												// classe pour le calendrier
					oObj.classCalendarWeek	= "ep_containerweek";											// classe pour le conteneur selectionnant des semaines (classe ajoutee au conteneur principal
					oObj.classMonth			= "ep_title";													// classe pour l'abbreviation du mois dans l'entete
					oObj.classLinksPrev		= "ep_links_prev";												// classe pour le bloc de liens mois et années précédents
					oObj.classLinksNext		= "ep_links_next";												// classe pour le bloc de liens mois et années suivants
					oObj.classClose			= "ep_footer";													// classe pour le bloc conteneur du tableau
					oObj.classTable			= "ep_body";													// classe pour le bloc de pied du tableau
					oObj.classWeek			= "ep_week";													// classe pour le numero de la semaine
					oObj.classWeekEnd		= "ep_weekend";													// classe pour le numero des jours de week end
					oObj.classSelected		= "ep_selected";												// classe pour le numero du jour selectionne
					oObj.classHover			= "ep_hover";													// classe pour la semaine survolee
					oObj.classHidden		= "ep_hidden";													// classe pour les textes caches
					oObj.marginLink			= 0;															// Marge laterale des liens de navigation
					// Variables d'objets
					oObj.Calendars			= new Object();													// Stockage des balises par calendrier
					// Variables d'evenements
					oObj.Functions			= new Object();													// Stockage des fonctions liees aux evenements
					oObj.Functions.hidden	= new Object();													// Fonction de fermeture du calendrier
					oObj.Functions.hidden.e	= "click";
					oObj.Functions.hidden.f	= function(){RefCalendar.hide();};
					// Variables de touches du clavier
					oObj.key_shift			= false;														// Detection de l'etat de la touche shift
				return(oObj);
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction ajoutant un evenement
			function addEventListener(sEvent, fFunction){
				// Verification des parametres
				if(typeof(sEvent) == "string" && sEvent.length > 1 && typeof(fFunction) == "function"){
					// Ajout de l'evenement selon la nommenclature autorisee/comprise par le navigateur
					if (window.addEventListener){
						window.addEventListener(sEvent, fFunction, false);
					}else if(document.addEventListener) {
						document.addEventListener(sEvent, fFunction, false);
					}else if(document.attachEvent){
						var sEvent		= "on" + sEvent;
						document.attachEvent(sEvent, fFunction);
					}
				}
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction supprimant un evenement
			function removeEventListener(sEvent, fFunction){
				// Verification des parametres
				if(typeof(sEvent) == "string" && sEvent.length > 1 && typeof(fFunction) == "function"){
					// Ajout de l'evenement selon la nommenclature autorisee/comprise par le navigateur
					if (window.removeEventListener){
						window.removeEventListener(sEvent, fFunction, false);
					}else if(document.removeEventListener) {
						document.removeEventListener(sEvent, fFunction, false);
					}else if(window.detachEvent){
						document.detachEvent("on" + sEvent, fFunction);
					}
				}
			};
			
		// ===================================================================================================================
		// Fonctions d'appel publique ========================================================================================
		
			// Fonction affichant le calendrier
			this.display = function(){
				// Verification de l'autorisation de construction
				if(oMain.authorize){
					// Verification de l'existence d'un calendrier deja ouvert
					if(oMain.Dates.display.ok){
						RefCalendar.hide(true);
					}
					var aDate						= new Array();
					this.authorizehidden			= true;
					var oTag;
					var fTarget;
					var dateMin						= "";
					var dateMax						= "";
					// Analyse des variables transmises
					if(arguments.length == 1 && typeof(arguments[0]) == "object"){
						var oArg					= arguments[0];
						// Analyse des proprietes
							// Balise conteneur du calendrier
							if(typeof(oArg.tag) == "object") 	oTag	= oArg.tag;
							// Cible pour l'envoi du choix du calendrier
							if(typeof(oArg.fct) == "function") 	fTarget	= oArg.fct;
							// Date decoupee
							if(!isNaN(Number(oArg.year)))		aDate[0] = oArg.year;
							if(!isNaN(Number(oArg.month)))		aDate[1] = oArg.month;
							if(!isNaN(Number(oArg.day)))		aDate[2] = oArg.day;
							// Date formatee (string)
							if(typeof(oArg.date) == "string" && oArg.date.length > 0){  var a = convert_format_date(oArg.date); if(a.length == 3){ aDate = a; };}
							// Date minimum
							if(typeof(oArg.dateMin) == "string" && oArg.dateMin.length > 0) dateMin = oArg.dateMin;
							// Date maximum
							if(typeof(oArg.dateMax) == "string" && oArg.dateMax.length > 0) dateMax = oArg.dateMax;
					}else if(arguments.length > 1){
						var bTarget 				= false;
						var nLength					= arguments.length;
						for(var a = 0; a < nLength; a++){
							switch(typeof(arguments[a])){
								case "number":	aDate.push(arguments[a]);	break;							// Valeur de la date (ordre : annee, mois, jour)
								case "object": 	oTag 	= arguments[a];		break;							// Balise ou doit se construire le calendrier
								case "function":fTarget = arguments[a];		break;							// Balise ou doit se construire le calendrier
								case "string": 	var aValue 	= convert_format_stringArray(arguments[a]);		// Date formatee
												if(aValue.length == 3) aDate = aValue;	
												break;
							}
						}
					}
					// Verification des dates minimum et maximum
						if(dateMin.length > 1) dateMin	= analyse_dateLimite(dateMin);
						if(dateMax.length > 1) dateMax	= analyse_dateLimite(dateMax);
						if(typeof(dateMin) == "object" && dateMin.ok){ if(isNaN(dateMin.month)){	dateMin.month = 1; 	} dateMin.day = 1;									}
						if(typeof(dateMax) == "object" && dateMax.ok){ if(isNaN(dateMin.month)){	dateMin.month = 12; } dateMax.day = oMain.numberdays[dateMax.month -1];	}
					// Ajout de la fonction de suppression du calendrier lors d'un clic hors du calendrier
					if(typeof(oMain.Functions.hidden) == "object") addEventListener(oMain.Functions.hidden.e, oMain.Functions.hidden.f);
					// Verification de la valeur de la date par rapport aux dates limites
					oMain.Dates.opened				= check_dateString(aDate);
					oMain.Dates.opened.parentTag	= oTag;
					oMain.Dates.opened.sendTarget	= fTarget;
					if(dateMin.ok) oMain.Dates.opened.dateMin		= dateMin;
					if(dateMax.ok) oMain.Dates.opened.dateMax		= dateMax;
					// Sauvegarde des donnees
					oMain.Dates.display				= new Object();
					oMain.Dates.display.year		= oMain.Dates.opened.year;
					oMain.Dates.display.month		= oMain.Dates.opened.month;
					oMain.Dates.display.day			= oMain.Dates.opened.day;
					oMain.Dates.display.ok			= true;
					oMain.Dates.display.parentTag	= oMain.Dates.opened.parentTag;
					oMain.Dates.display.sendTarget	= oMain.Dates.opened.sendTarget;
					oMain.Dates.display.dateMin		= oMain.Dates.opened.dateMin;
					oMain.Dates.display.dateMax		= oMain.Dates.opened.dateMax;
					// Blocage de la fermeture automatique due au clic du lien pour l'ouverture du pop up
					oMain.Dates.firstClick			= true;
					// Remplissage du calendrier avec la date transmise
					fillingup_calendar(oMain.Dates.display.parentTag, oMain.Dates.display.year, oMain.Dates.display.month, oMain.Dates.display.day);
				}
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction suprimant le calendrier
			this.hide = function(bAuthorize){
				if(oMain.authorize && oMain.Dates.display.ok && ((this.authorizehidden && !oMain.Dates.firstClick) || bAuthorize) && typeof(oMain.Dates.display.parentTag) == "object"){
					// Mise a jour de la date transmise si la selection concerne des semaines et que la date envoyee est un jour
					if(oMain.selectionweek && oMain.Dates.autoFormat){
						// Identification de la semaine en cours d'apres le jour selectionne a l'ouverture
						var nW	= get_numberWeek(oMain.Dates.opened.year, oMain.Dates.opened.month, oMain.Dates.opened.day);
						// Identification du numero de la rangee de la semaine concernee
						var nCw	= nW - Number(oCalendar["value_week0"]);
						// Identification du premier jour de la semaine concernee
						var oDs	= getday_inWeek(true, nCw, oMain.Dates.opened.year, oMain.Dates.opened.month, nW);
						// Identification du dernier jour de la semaine concernee
						var oDe	= getday_inWeek(false, nCw, oMain.Dates.opened.year, oMain.Dates.opened.month, nW);
						// Envoi du reformatage de la date
						oMain.Dates.display.sendTarget(oDs, oDe);
					}
					// Suppression de l'evenement
					removeEventListener(oMain.Functions.hidden.e, oMain.Functions.hidden.f);
					// Supression de l'objet
					oMain.Dates.display.parentTag.removeChild(oCalendar.main);
					// Nettoyage des valeurs
					oMain.Dates.opened			= new Object();
					oMain.Dates.display			= new Object();
					oMain.Dates.display.ok		= false;
					oMain.Dates.autoFormat		= false;
				}else{
					oMain.Dates.firstClick		= false;
				}
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction changeant le mois ou l'annee du calendrier
			this.change = function(nSens_year, nSens_month){
				// Verification de l'autorisation de construction
				if(oMain.authorize && oMain.Dates.display.ok && ((!isNaN(nSens_year) && nSens_year != 0) || (!isNaN(nSens_month) && nSens_month != 0))){
					this.authorizehidden			= false;
					// Recuperation des valeurs de la date affichee
					var aDate						= new Array();
						aDate[0]					= oMain.Dates.display.year;
						aDate[1]					= oMain.Dates.display.month;
						aDate[2]					= 0;
					// Changement de valeur
					if(nSens_year != 0)	aDate[0]	+= nSens_year;
					if(nSens_month != 0)aDate[1]	+= nSens_month;
					// Verification de la date
					if(aDate[1] > 12){
						aDate[1]					= 1; 	
						aDate[0]++;	
					}else if(aDate[1] < 1){
						aDate[1]					= 12; 	
						aDate[0]--;
					}
					// Verification de la valeur de la date
					oMain.Dates.display				= check_dateString(aDate);
					oMain.Dates.display.ok			= true;
					oMain.Dates.display.parentTag	= oMain.Dates.opened.parentTag;
					oMain.Dates.display.sendTarget	= oMain.Dates.opened.sendTarget;
					oMain.Dates.display.dateMin		= oMain.Dates.opened.dateMin;
					oMain.Dates.display.dateMax		= oMain.Dates.opened.dateMax;
					// Verification du jour selectionne
					if(oMain.Dates.display.year == oMain.Dates.opened.year && oMain.Dates.display.month == oMain.Dates.opened.month){
						oMain.Dates.display.day		= oMain.Dates.opened.day;
					}
					// Remplissage du calendrier avec la date transmise
					fillingup_calendar("", oMain.Dates.display.year, oMain.Dates.display.month, oMain.Dates.display.day);
				}
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction affichant l'effet de survole sur les jours du calendrier
			this.hover = function(bDisplay, nWeek){
				if(oMain.authorize && oMain.Dates.display.ok){
					var oTag;
					// Nettoyage des semaines
					for(var t = 0; t < 6; t++){
						oTag		= oCalendar["tr_" + t];
						if(oTag && typeof(oTag) != "undefined") oTag.className = String(oTag.className).replace(" " + oMain.classHover, "").replace(oMain.classHover, "");
					}
					// Surlignage de la semaine
					if(bDisplay && !isNaN(nWeek) && nWeek >= 0 && nWeek < 6){
						oTag		= oCalendar["tr_" + nWeek];
						if(oTag && typeof(oTag) != "undefined") oTag.className = oMain.classHover + " " + oTag.className;
					}
				}
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction envoyant le jour choisi dans le calendrier
			this.send_date = function(nYear, nMonth, nDay, nWeek){
				if(oMain.authorize && oMain.Dates.display.ok){
					// Verification de la validite de la fonction d'envoi
					if(typeof(oMain.Dates.display.sendTarget) == "function"){
						// Recuperation du numero de la semaine concernee
						var w			= oCalendar["value_week" + nWeek];
						// Analyse du type de donnees a transmettre
						if(!oMain.selectionweek){
							// Envoi du jour choisi
							oMain.Dates.display.sendTarget({year:nYear, month:nMonth, day:nDay, week:w, selectedweek:false, formatday:oMain.format});
						}else{
							// Recuperation du premier jour de la semaine
							var oStart			= getday_inWeek(true, nWeek, oMain.Dates.display.year, oMain.Dates.display.month, w); //getTargetDay(1);
							// Recuperation du dernier jour de la semaine
							var oEnd			= getday_inWeek(false, nWeek, oMain.Dates.display.year, oMain.Dates.display.month, w);
							// Envoi de la semaine choisie
							oMain.Dates.display.sendTarget(oStart, oEnd);
						}
					}
					// Blocage du reformatage de la date
					oMain.Dates.autoFormat		= false;
					// Disparition du calendrier
					RefCalendar.hide(true);
				}
			};
		
		
		// ===================================================================================================================
		// Fonctions de construction de balises ==============================================================================
		
			// Fonction construisant les balises HTML du tableau du calendrier (vide)
			function createCalendar_table(){
				// Creation des balises
					var oTable								= Html.createNode("table", "");
				// Creation de l'entete
					// Creation des balises generales
					var oHead								= Html.createNode("thead", "");
					var oTr									= Html.createNode("tr", "");
					var oTr_head;
					var sId;
					var oTd;
					var oA;
					// Creation du titre "Semaine"
					if(oMain.numberWeek){
						oA									= Html.createNode("abbr", {"title":oMain.titleWeek}, oMain.abbrWeek);
						oTd									= Html.createNode("th", oA);
						oCalendar["th_week"]				= oTd;
						oCalendar["abbr_week"]				= oA;
						oTr.appendChild(oTd);
					}
					// Creation du nom des jours
					for(var d = 0; d < 7; d++){
						oA									= Html.createNode("abbr", {"title":oMain.days[d]}, oMain.abbrDays[d]);
						oTd									= Html.createNode("th", oA);
						oCalendar["th_" + d]				= oTd;
						oCalendar["abbr_" + d]				= oA;
						oTr.appendChild(oTd);
					}
					// Incrustation des balises
					oHead.appendChild(oTr);
					oTr_head								= oTr;
				// Creation du corps
					// Creation des balises generales
					var oBody								= Html.createNode("tbody", "");
					for(var t = 0; t < 6; t++){
						oTr									= Html.createNode("tr", "");
						oCalendar["tr_" + t]				= oTr;
						// Creation des numeros de semaine
						if(oMain.numberWeek){
							oTd								= Html.createNode("td", "");
							oTd.className					= oMain.classWeek;
							oCalendar["td_week_" + t]		= oTd;
							oTr.appendChild(oTd);
						}
						// Creation des dates des jours
						for(var c = 0; c < 7; c++){
							oTd								= Html.createNode("td", "");
							oCalendar["td_" + t + "_" + c]	= oTd;
							oTr.appendChild(oTd);
						}
						oBody.appendChild(oTr);
					}
				// Deplacement du dimanche	
					if(oMain.mondayFirst){
						// Deplacement dans l'entete
						if(oTr_head && oCalendar.th_0){
							// Suppression du noeud
							oTr_head.removeChild(oCalendar.th_0);
							// Creation du noeud en fin de liste
							oTr_head.appendChild(oCalendar.th_0);
						}
						// Deplacement dans le corps
						for(var t = 0; t < 6; t++){
							oTd								= oCalendar["td_" + t + "_0"];
							oTr								= oCalendar["tr_" + t];
							if(oTr && oTd){
								// Suppression du noeud
								oTr.removeChild(oTd);
								// Creation du noeud en fin de liste
								oTr.appendChild(oTd);
							}
						}
					}
				// Finition
					// Composition du tableau
					oTable.appendChild(oHead);
					oTable.appendChild(oBody);
					// Stockage de la balise principale
					oCalendar.table							= oTable;
					// Renvoi de l'autorisation de poursuite de la procedure
					return(true);
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction construisant les balises HTML du pop up contenant le tableau du calendrier (vide)
			function createCalendar_popup(){
				// Creation des balises
					// Creation des balises principales
					var oPopUp								= Html.createNode("div", 	{"className":oMain.classMain}, "");
					var oShadow								= Html.createNode("div", 	{"className":oMain.classShadow}, " ");
					var sClassContent						= (oMain.selectionweek)? oMain.classCalendar + " " + oMain.classCalendarWeek : oMain.classCalendar;
					var oContent							= Html.createNode("div", 	{"className":sClassContent}, "");
					// Creation des balises du nom du mois de l'entete
					var oTitle								= Html.createNode("div", 	{"className":oMain.classMonth, "title":""}, "-");
						oCalendar.month						= oTitle;
						oContent.appendChild(oTitle);
					// Creation des balises de liens precedents dans l'entete
					var oLinks								= Html.createNode("div", 	{"className":oMain.classLinksPrev}, "");
						oCalendar.linksprev					= oLinks;
						oCalendar.linksprevA				= new Array();
						// Stockage des liens
						oContent.appendChild(oLinks);
					// Creation des balises de liens suivants dans l'entete
						oLinks								= Html.createNode("div", 	{"className":oMain.classLinksNext}, "");
						oCalendar.linksnext					= oLinks;
						oCalendar.linksnextA				= new Array();
						// Stockage des liens
						oContent.appendChild(oLinks);
					// Integration du contenu
					var oBody								= Html.createNode("div", 	{"className":oMain.classTable}, "");
						oBody.appendChild(oCalendar.table);
						oContent.appendChild(oBody);
					// Creation des balises du pied de tableau
						oLinks								= Html.createNode("a", 		{"href":"#"}, oMain.linkclose);
						oLinks.onclick						= function(){ RefCalendar.hide(true); return(false); };
						oBody								= Html.createNode("div", 	{"className":oMain.classClose}, oLinks);
						oContent.appendChild(oBody);
				// Finition
					// Composition du pop up
					oPopUp.appendChild(oShadow);
					oPopUp.appendChild(oContent);
					oPopUp.onclick = function(){ return(false); };
					// Ajout des evenements de survole
					oPopUp.onmouseover						= function(){
						oMain.Dates.firstClick				= false;
						RefCalendar.authorizehidden			= false;
						this.style.opacity					= 1;
					}
					oPopUp.onmouseout						= function(){
						RefCalendar.authorizehidden			= true;
						this.style.opacity					= 0.2;
					}
					// Stockage de la balise principale
					oCalendar.popUp							= oPopUp;
					oCalendar.content						= oContent;
					oCalendar.shadow						= oShadow;
					// Renvoi de l'autorisation de poursuite de la procedure
					return(true);
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction construisant les balises HTML des liens de navigation
			function createCalendar_navigation(nYear, nMonth){
				// Identification des dates minimales et maximales
				var oDateMin							= new Object();
				if(oMain.Dates.display.dateMin && typeof(oMain.Dates.display.dateMin) == "object" && oMain.Dates.display.dateMin.ok){
					oDateMin							= oMain.Dates.display.dateMin;
				}else{
					oDateMin							= oMain.dateMin;
				}
				var oDateMax							= new Object();
				if(oMain.Dates.display.dateMax && typeof(oMain.Dates.display.dateMax) == "object" && oMain.Dates.display.dateMax.ok){
					oDateMax							= oMain.Dates.display.dateMax;
				}else{
					oDateMax							= oMain.dateMax;
				}
				// Creation des liens
				var oA;
				var oImg;
				var iImg;
				var nDecal								= 0;
				// Lien "annee precedente"
					if(nYear > oDateMin.year || !oDateMin.ok){
						// Creation du lien
						oA								= Html.createNode("a", 		{"href":"#", "title":oMain.titleYearPrev}, "");
						oImg							= Html.createNode("img", 	{"src":oMain.srcYearPrev, "alt":oMain.altYearPrev});
						oA.appendChild(oImg);
						oCalendar.linksprev.appendChild(oA);
						// Sauvegarde de l'information
						nDecal							= 0;
						oCalendar.linksprevA[0]			= oA;
						// Ajout de l'action
						oA.onclick						= function(){	RefCalendar.change(-1, 0);	return(false);	}
					}else{
						iImg							= new Image();
						iImg.src						= oMain.srcYearPrev;
						nDecal							= 0;
						if(!isNaN(iImg.width) && iImg.width > 0) nDecal = iImg.width + oMain.marginLink;
					}
				// Lien "mois precedent"
					if(nYear > oDateMin.year || (nYear == oDateMin.year && nMonth > oDateMin.month) || !oDateMin.ok){
						oA								= Html.createNode("a", 		{"href":"#", "title":oMain.titleMonthPrev}, "");
						oA.style.marginLeft				= nDecal + "px";
						oImg							= Html.createNode("img", 	{"src":oMain.srcMonthPrev, "alt":oMain.altMonthPrev});
						oA.appendChild(oImg);
						oCalendar.linksprev.appendChild(oA);
						// Sauvegarde de l'information
						oCalendar.linksprevA[1]			= oA;
						// Ajout de l'action
						oA.onclick						= function(){	RefCalendar.change(0, -1);	return(false);	}
					}
				// Lien "mois suivant"
					var bBtn							= false;
					if(nYear < oDateMax.year || (nYear == oDateMax.year && nMonth < oDateMax.month) || !oDateMax.ok){
						// Creation du lien
						oA								= Html.createNode("a", 		{"href":"#", "title":oMain.titleMonthNext}, "");
						oImg							= Html.createNode("img", 	{"src":oMain.srcMonthNext, "alt":oMain.altMonthNext});
						oA.appendChild(oImg);
						oCalendar.linksnext.appendChild(oA);
						// Sauvegarde de l'information
						nDecal							= 0;
						oCalendar.linksnextA[0]			= oA;
						bBtn							= true;
						// Ajout de l'action
						oA.onclick						= function(){	RefCalendar.change(0, 1);	return(false);	}
					}
				// Lien "annee suivante"
					if(nYear < oDateMax.year || !oDateMax.ok){
						// Creation du lien
						oA								= Html.createNode("a", 		{"href":"#", "title":oMain.titleYearNext}, "");
						oImg							= Html.createNode("img", 	{"src":oMain.srcYearNext, "alt":oMain.altYearNext});
						oA.appendChild(oImg);
						oCalendar.linksnext.appendChild(oA);
						// Sauvegarde de l'information
						oCalendar.linksnextA[1]			= oA;
						// Ajout de l'action
						oA.onclick						= function(){	RefCalendar.change(1, 0);	return(false);	}
					}else{
						iImg							= new Image();
						iImg.src						= oMain.srcYearNext;
						nDecal							= 0;
						if(!isNaN(iImg.width) && iImg.width > 0) nDecal = iImg.width + oMain.marginLink;
						if(bBtn) oCalendar.linksnextA[0].style.marginRight	= nDecal + "px";
					}
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction construisant les balises HTML des liens de jour
			function createCalendar_day(sStart, nDay, sEnd){
				// Creation du texte cache de debut
				var oSpan1				= Html.createNode("span", {"className":oMain.classHidden}, (sStart + " : "));
				// Creation du texte cache de fin
				var oSpan2				= Html.createNode("span", {"className":oMain.classHidden}, sEnd);
				// Creation du lien
				var oA					= Html.createNode("a", {"href":"#"}, oSpan1, String(nDay), oSpan2);
				// Renvoi du lien
				return(oA);
			};
			
			
		// ===================================================================================================================
		// Fonctions de suppression ==========================================================================================
		
			// Fonction supprimant les balises HTML des liens de navigation
			function removeCalendar_navigation(){
				var oTag;
				switch(oCalendar.linksprevA.length){
					case 2:		oTag							= oCalendar.linksprevA[0];
								if(oTag && typeof(oTag) != "undefined") 	oCalendar.linksprev.removeChild(oTag);
					case 1:		oTag							= oCalendar.linksprevA[1];
								if(oTag && typeof(oTag) != "undefined") 	oCalendar.linksprev.removeChild(oTag);	
								oCalendar.linksprev.innerHTML 	= "";
								break;
				}
				oCalendar.linksprevA	= new Array();
				switch(oCalendar.linksnextA.length){
					case 2:		oTag							= oCalendar.linksnextA[0];
								if(oTag && typeof(oTag) != "undefined") 	oCalendar.linksnext.removeChild(oTag);
					case 1:		oTag							= oCalendar.linksnextA[1];
								if(oTag && typeof(oTag) != "undefined") 	oCalendar.linksnext.removeChild(oTag);
								oCalendar.linksnext.innerHTML 	= "";
								break;
				}
				oCalendar.linksnextA	= new Array();
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction supprimant les balises HTML des liens du tableau
			function clear_table(){
				var oCell;
				var oLink;
				// Nettoyage du contenu du tableau
				for(var t = 0; t < 6; t++){
					// Suppression du contenu des cellules "semaine"
					oCell					= oCalendar["td_week_" + t];
					oLink					= oCalendar["a_week_" + t];
					if(oCell && typeof(oCell) != "undefined" && oLink && typeof(oLink) != "undefined"){ 	oCell.removeChild(oLink); oCell.innerHTML = ""; oCalendar["a_week_" + t] = ""; oCalendar["value_week_" + t] = false;	}
					// Suppression des classes de survoles
					oCell					= oCalendar["tr_" + t];
					if(oCell && typeof(oCell) != "undefined") 	oCell.className = "";
					// Suppression du contenu des cellules "jour"
					for(var c = 0; c < 7; c++){
						oCell				= oCalendar["td_" + t + "_" + c];
						oCell.className		= "";
						oLink				= oCalendar["a_" + t + "_" + c];
						if(oCell && typeof(oCell) != "undefined" && oLink && typeof(oLink) != "undefined"){ oCell.removeChild(oLink); oCell.innerHTML = ""; oCalendar["a_" + t + "_" + c] = ""; oCalendar["value_" + t + "_" + c] = false;	}
					}
				}
			};
			
			
		// ===================================================================================================================
		// Fonctions de remplissage ==========================================================================================
		
			// Fonction remplissant les balises du calendrier
			function fillingup_calendar(oTarget, nYear, nMonth, nDay){
				// Remplissage des balises du popup
					if(oMain.mode == "popup" && oCalendar.popUp && typeof(oCalendar.popUp) != "undefined"){
						// Nettoyage des boutons de navigation
						removeCalendar_navigation();
						// Ajout du nom du mois
						oCalendar.month.innerHTML		= oMain.abbrMonths[nMonth -1] + " " + nYear;
						oCalendar.month.title			= oMain.months[nMonth -1] + " " + nYear;
						// Ajout des boutons de navigation
						createCalendar_navigation(nYear, nMonth);
						// Affichage a 100%
						oCalendar.main.style.opacity	= 1;
					}
				// Remplissage des balises du tableau
					if(oCalendar.table && typeof(oCalendar.table) != "undefined"){
						// Nettoyage des cellules du calendrier
							clear_table();
						// Caracteristique de la date
							var dFirst		= new Date(nYear, nMonth -1, 1);
						// Duree du mois
							var nMax		= oMain.numberdays[(nMonth -1)];
							if(nMonth == 2 && is_leapyear(nYear)) nMax = 29;
						// Identification du numero de la premiere semaine
							var nWeek		= 0;
							if(oMain.numberWeek) nWeek	= get_numberWeek(nYear, nMonth, 1);
						// Identification du numero de la semaine selectionnee
							var nWeekSelect	= -1;
							if(oMain.selectionweek && nDay > 0){
								// Identification de la cellule
								nWeekSelect	= get_numberWeek(nYear, nMonth, nDay) - nWeek;
								nDay		= 0;
								// Ajout de la classe
								oCell					= oCalendar["tr_" + nWeekSelect];
								if(oCell && typeof(oCell) != "undefined") oCell.className = oMain.classSelected;
							}
						// Remplissage du contenu
							// Date des jours
							var t			= 0;
							var w			= -1;
							var c			= dFirst.getDay();
							var oLink;
							// Analyse de l'affichage des jours demandes
							if(oMain.mondayFirst){
								// Boucle de remplissage des jours du mois
								for(var d = 1; d <= nMax; d++){
									// Verification du nombre de semaines traitees
									if(t < 6){
										// Ciblage de la cellule de la semaine
										if(c >= 7) c 	= 0;
										// Traitement de la cellule (si aucun jour n'est selectionne, nDay = 0)
										fillingup_day(nYear, nMonth, d, t, c, nMax, nDay, nWeekSelect);
										// Ajout du numero de la semaine
										if(w != t){	fillingup_week(t, nWeek + t, nWeekSelect);	w = t;	}
										// Gestion du jour suivant
										if(c == 0) t++;
										c++;
									}
								}
							}else{
								// Boucle de remplissage des jours du mois
								for(var d = 1; d <= nMax; d++){
									// Verification du nombre de semaines traitees
									if(t < 6){
										// Ajout du numero de la semaine
										if(w != t){	fillingup_week(t, nWeek + t, nWeekSelect);	w = t;	}
										// Positionnement de la cellule
										if(c >= 7){	c = 0;	t++;	}
										// Traitement de la cellule
										fillingup_day(nYear, nMonth, d, t, c, nMax, nDay);
										// Gestion du jour suivant
										c++;
									}
								}
							}
					}
				// Incrustation dans la page
					if(oTarget && typeof(oTarget) != "undefined" && oCalendar.main && typeof(oCalendar.main) != "undefined"){
						// Dimensions de la fenetre
						var oWindow				= documentDimensions();
						// Integration
						oCalendar.target		= oTarget;
						oTarget.appendChild(oCalendar.main);
						// Calcul des dimensions du calendrier si le tableau est plus long que prevu
						if(oMain.mode == "popup" && oCalendar.popUp && oCalendar.table.offsetWidth > oCalendar.main.offsetWidth){
							// Suppression des contraintes de tailles définies
							oCalendar.popUp.style.width		= "auto";
							oCalendar.content.style.width	= "auto";
							// Etirement de l'ombre portee
							oCalendar.shadow.style.width	= oCalendar.main.offsetWidth + "px";
							// Pour IE, etirement de la zone de titre en deduisant la largeur des padding utilises en css
							if(oCalendar.month.currentStyle){
								var paddingL				= Number(String(oCalendar.month.currentStyle["paddingLeft"]).replace("px", ""));
								var paddingR				= Number(String(oCalendar.month.currentStyle["paddingRight"]).replace("px", ""));
								oCalendar.month.style.width	= (oCalendar.main.offsetWidth - (paddingL + paddingR)) + "px";
							}
						}
						// Calcul de la position absolue du calendrier
						var oPositionContainer	= getAbsoluteOffset(oTarget);
						var oPositionCalendar	= getAbsoluteOffset(oCalendar.main, oTarget);
						// Verification de la position
						if(!isNaN(oPositionContainer.top) && !isNaN(oPositionCalendar.top) && 
							(oPositionContainer.top + oPositionCalendar.top + oCalendar.main.offsetHeight)  >= oWindow.height){
							oCalendar.main.style.top	= (oWindow.height - oPositionContainer.top - oCalendar.main.offsetHeight -20) + "px";
						}
						if(!isNaN(oPositionContainer.left) && !isNaN(oPositionCalendar.left) && 
							(oPositionContainer.left + oPositionCalendar.left + oCalendar.main.offsetWidth)  >= oWindow.width){
							oCalendar.main.style.left	= (oWindow.width - oPositionContainer.left - oCalendar.main.offsetWidth -20) + "px";
						}
					}
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction remplissant les balises de "jour" du tableau
			function fillingup_day(nYear, nMonth, nDay, nWeek, nCell, nMax, nSelected){
				// Identification de la cellule
					var oCell									= oCalendar["td_" + nWeek + "_" + nCell];
					// Ajout du style pour la couleur des jours du week end
					if(nCell == 0 || nCell == 6) oCell.className = oMain.classWeekEnd;
				// Creation du texte cache de fin
					var sText									= "";
					// Identification du numero selectionne : ajout du texte invisible et de la classe CSS
					if(nDay == nSelected){
						sText									+= " " + oMain.textSelected;
						oCell.className							= oMain.classSelected;
					}
					// Choix de la ponctuation
					(nDay >= nMax)? sText += ". " : sText += ", ";
				// Creation du lien
					var oLink									= createCalendar_day(oMain.days[nCell], nDay, sText);
				// Action sur le lien	
					oLink.onclick								= function(){ RefCalendar.send_date(nYear, nMonth, nDay, nWeek);	return(false);	};
					oLink.onfocus	= oLink.onmouseover			= function(){ RefCalendar.hover(true, nWeek); 										};
					oLink.onblur	= oLink.onmouseout			= function(){ RefCalendar.hover(false, nCell); 										};
				// Integration du lien
					oCalendar["value_" + nWeek + "_" + nCell]	= nDay;
					oCalendar["a_" + nWeek + "_" + nCell]		= oLink;
					oCell.appendChild(oLink);
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction remplissant les balises de "semaine" du tableau
			function fillingup_week(nCell, nWeek, nSelected){
				// Identification de la cellule
				var oCell								= oCalendar["td_week_" + nCell];
				// Creation du texte cache de fin
					var sText							= ", ";
					// Identification du numero selectionne : ajout du texte invisible
					if(nCell == nSelected) sText		= " " + oMain.textSelected + ", ";
				// Creation du lien
				var oLink								= createCalendar_day(oMain.week, nWeek, sText);
				// Action de clic sur la semaine
				if(oMain.selectionweek){
					oLink.style.cursor					= "";
					oLink.onclick						= function(){ RefCalendar.send_date(0, 0 , 0, nCell);	return(false);	};
				}else{
					oLink.style.cursor					= "default";
					oLink.onclick						= function(){ return(false); 					};
				}
				// Action sur le lien	
					oLink.onfocus	= oLink.onmouseover	= function(){ RefCalendar.hover(true, nCell); 	};
					oLink.onblur	= oLink.onmouseout	= function(){ RefCalendar.hover(false, nCell); 	};
				// Integration du lien
					oCalendar["value_week" + nCell]		= nWeek;
					oCalendar["a_week_" + nCell]		= oLink;
					oCell.appendChild(oLink);
			};
			
			
		// ===================================================================================================================
		// Fonctions outils ==================================================================================================
		
			// Fonction renvoyant le numero de la semaine correspondant au mois transmis
			function get_numberWeek(nYear, nMonth, nDay){
				var nWeek										= Math.NaN;
				if(!isNaN(nYear) && !isNaN(nMonth) && !isNaN(nDay)){
					// Calcul du nombre de jour total entre le 01/01 et le jour donne
						var nFullDays								= 0;
						// Calcul des jours des mois precedents le mois donne
						for(m = 1; m < nMonth; m++){	nFullDays	+= oMain.numberdays[m -1];	}
						// Ajout d'un jour si l'annee est bissextile et que le mois de Fevrier est compris dans la liste
						if(is_leapyear(nYear) && nMonth > 2) nFullDays++;
						// Ajout du jour demande
						nFullDays									+= nDay;
					// Analyse de la position du premier Janvier dans la semaine
						var nNewYearDay								= 0;
						// Reference au premier jour de l'annee
						var dFirst									= new Date(nYear, 0, 1);
						nNewYearDay									= dFirst.getDay();
						// Repositionnement du jour si c'est un dimanche ( valeur egale a 7 au lieu de 0)
						if(nNewYearDay == 0) nNewYearDay			= 7;
					// Calcul du nombre de semaines
						// Calcul du nombre de jour de la premiere semaine a soustraire au nombre total
						nFullDays									-= (8 - nNewYearDay);
						// Ajout de la premiere semaine au compteur
						nWeek										= 1;
						// Comptabilisation du nombre de semaines completes
						nWeek										+= Math.floor(nFullDays/7);
						// Comptabilisation de la semaine entammee ou se trouve le jour demande
						if(nFullDays%7 != 0) nWeek++;
				}
				// Renvoi du resultat
				return(nWeek);
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction de recuperation de la date demandee
			function getday_inWeek(bStartDay, nCellWeek, year, month, week){
				// Ordre des jours dans la semaine
				var aD				= (oMain.mondayFirst)? [1, 2, 3, 4, 5, 6, 0] : [0, 1, 2, 3, 4, 5, 6];
				// Analyse du type de jour demande : premier ou dernier de la semaine
				var nSens			= (bStartDay)? 1 : -1;
				var nC				= (nSens > 0)? -1 : 7;
				// Identification du numero du jour demande
				var day				= false;
				while(!day && ((nSens > 0 && nC <= 7) || (nSens < 0 && nC >= 0))){
					nC				+= nSens;	
					day				= oCalendar["value_" + nCellWeek + "_" + aD[nC]];
				}
				// Verification de la position du jour choisi
				if((nSens > 0 && nC > 0) || (nSens < 0 && nC < 6)){
					// Mise a jour du mois et de l'annee (si besoin)
					if((nSens > 0 && month == 1) || (nSens < 0 && month == 12)){
						month		= (month == 1)? 12 : 1;
						yTarget		-= nSens;
					}else{
						month		-= nSens;
						var nMax	= 0;
					}
					// Numero du jour
					if(nSens > 0){
						// Duree du mois
						var nMax	= oMain.numberdays[(month -1)];
						if(month == 2 && is_leapyear(year)) nMax = 29;
						// Numero du jour
						day			= nMax - ((nC -1)*nSens);
					}else{
						// Numero du jour
						day			= 6 - nC;
					}
				}
				// Envoi du resultat
				return({day:day, month:month, year:year, week:week, selectedweek:true, formatday:oMain.format, formatweek:oMain.formatweek});
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction analysant les dates minimale et maximale
			function analyse_dateLimite(sDate){
				var oObj						= new Object();
					oObj.ok						= false;
				// Verification de la valeur transmise
				if(typeof(sDate) == "string" && sDate.length > 0){
					// Convertion de la date selon le format demande
					var aDate					= convert_format_stringArray(sDate);
					// Analyse du nombre de parametre transmis
					var nLength					= aDate.length;
					if(nLength >= 1){
						var nD					= aDate[0];
						if(!isNaN(nD)){
							oObj.ok				= true;
							oObj.year			= nD;
							nD					= aDate[1];
							if(!isNaN(nD)){
								oObj.month		= nD;
								nD				= aDate[2];
								if(!isNaN(nD)){
									oObj.day	= nD;
								}
							}
						}
					}
				}
				// Envoi du resultat
				return(oObj);
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction verifiant la valeur transmise pour la date a afficher
			function check_dateString(aDateAsked){
				var aDate					= new Array();
				// Verification de la date envoyee - si la date est fausse, assignation du jour actuel
					if(typeof(aDateAsked) != "object")	aDateAsked	= new Array();
					// Convertion des donnees
					switch(aDateAsked.length){
						case 3:	aDate[0]	= aDateAsked[0];
								aDate[1]	= aDateAsked[1];
								aDate[2]	= aDateAsked[2];		break;
						case 2:	aDate[0]	= aDateAsked[0];
								aDate[1]	= aDateAsked[1];
								aDate[2]	= 0;					break;
						case 1:	aDate[0]	= aDateAsked[0];
								aDate[1]	= dDate.getMonth() +1;	break;
								aDate[2]	= 0;					break;
						default:aDate[0]	= dDate.getFullYear();
								aDate[1]	= dDate.getMonth() +1;
								aDate[2]	= 0;
					}
					// Verification de l'annee contenue dans la date obtenue
					if(aDate[0] < 0)					aDate[0]	= dDate.getFullYear();
					// Verification du mois contenu dans la date obtenue
					if(aDate[1] < 1 || aDate[1] > 12) 	aDate[1]	= dDate.getMonth() +1;
					// Verification du jour contenu dans la date obtenue
					var nMax						= oMain.numberdays[aDate[1] -1];
					if(is_leapyear(aDate[0])) nMax	= 29;
					if(aDate[2] < 1 || aDate[2] > nMax) aDate[2]	= 0;
				// Verification de la date minimale
					if(typeof(oMain.dateMin) == "object" && oMain.dateMin.ok){
						if(aDate[0] < oMain.dateMin.year){
							aDate[0]		= oMain.dateMin.year;
							aDate[1]		= oMain.dateMin.month;
							aDate[2]		= 0;
						}else if(aDate[0] == oMain.dateMin.year && aDate[1] < oMain.dateMin.month){
							aDate[1]		= oMain.dateMin.month;
							aDate[2]		= 0;
						}else if(aDate[2] < 1){
							aDate[2]		= 0;
						}
					}
				// Verification de la date maximale
					if(typeof(oMain.dateMax) == "object" && oMain.dateMax.ok){
						if(aDate[0] > oMain.dateMax.year){
							aDate[0]		= oMain.dateMax.year;
							aDate[1]		= oMain.dateMax.month;
							aDate[2]		= 0;
						}else if(aDate[0] == oMain.dateMax.year && aDate[1] > oMain.dateMax.month){
							aDate[1]		= oMain.dateMax.month;
							aDate[2]		= 0;
						}else if(aDate[2] > oMain.numberdays[oMain.dateMax.month -1]){
							aDate[2]		= 0;
						}
					}
				// Sauvegarde de la date
				var oDate					= new Object();
					oDate.year				= aDate[0];
					oDate.month				= aDate[1];
					oDate.day				= aDate[2];
				// Renvoi de la date
					return(oDate);
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction convertissant la date transmise en valeurs utilisables
			function convert_format_date(sDate){
				// Analyse du type de format/donnees transmis lors de la selection par semaine
				if(oMain.selectionweek && sDate.length > oMain.format.length){
					// Initialisation des donnees de base
					var sFormat					= String(oMain.formatweek).toLowerCase();
						sDate					= String(sDate).toLowerCase();
					var nL;
					var nW						= 0;
					var bW						= false;
					// Recherche du numero de semaine dans le format
					var aCut					= sFormat.split("{ww}");
					if(aCut.length > 1){
						bW						= true;
						sDate					= sDate.replace(aCut[0], "");
						nL						= (isNaN(Number(sDate.substr(1, 1))))? 1 : 2;
						nW						= Number(sDate.substr(0, nL));
					}
					// Recherche de la date de debut
						sDate					= sDate.substr(nL);
						aCut					= String(aCut[1]).split("{start}");
						sDate					= sDate.replace(aCut[0], "");
					var dateStart				= sDate.substr(0, oMain.format.length);
					// Recherche de la date de fin
						sDate					= sDate.substr(oMain.format.length);
						aCut					= String(aCut[1]).split("{end}");
						sDate					= sDate.replace(aCut[0], "");
					var dateEnd					= sDate.substr(0, oMain.format.length);
					// Convertion des dates recuperees
						dateStart				= convert_format_stringArray(dateStart);
						dateEnd					= convert_format_stringArray(dateEnd);
					// Identification du numero de semaine
					var nWs						= (bW)? get_numberWeek(dateStart[0], dateStart[1], dateStart[2]) : 0;
					var nWe						= (bW)? get_numberWeek(dateEnd[0], dateEnd[1], dateEnd[2]) : 0;
					// Verification des dates transmises
					if(nW == nWs && nWs == nWe && 
					   ((dateStart[1] == 12 && dateStart[0] >= dateEnd[0] && dateStart[0] <= (dateEnd[0] +1)) || dateStart[0] == dateEnd[0])){
						var aDateConvert		= dateStart;
					}else{
						var aDateConvert		= new Array();
					}
				}else{
					// Traitement de la date fournie
					var aDateConvert			= convert_format_stringArray(sDate);
					// Verification de la date par semaine
					if(oMain.selectionweek){
						var oD					= check_dateString(aDateConvert);
						// Formatage automatique de la date meme sans validation
						oMain.Dates.autoFormat	= (oD.year == aDateConvert[0] && oD.month == aDateConvert[1] && oD.day == aDateConvert[2]);
					}
				}
				// Renvoi du resultat final
				return(aDateConvert);
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction convertissant une date en tableau
			function convert_format_stringArray(sDate){
				var nYear;
				var nMonth;
				var nDay;
				var aConvert	= new Array();
				// Analyse du format de la date
				var aFormat		= String(oMain.format).split("/");
				var aDate		= String(sDate).split("/");
				// Convertion de la date
				if(aFormat.length == aDate.length){
					// Recherche des annees
					switch("YYYY"){
						case aFormat[0]:	nYear	= Number(aDate[0]);	break;
						case aFormat[1]:	nYear	= Number(aDate[1]);	break;
						case aFormat[2]:	nYear	= Number(aDate[2]);	break;
					}
					// Recherche des mois
					switch("MM"){
						case aFormat[0]:	nMonth	= Number(aDate[0]);	break;
						case aFormat[1]:	nMonth	= Number(aDate[1]);	break;
						case aFormat[2]:	nMonth	= Number(aDate[2]);	break;
					}
					// Recherche des jours
					switch("DD"){
						case aFormat[0]:	nDay	= Number(aDate[0]);	break;
						case aFormat[1]:	nDay	= Number(aDate[1]);	break;
						case aFormat[2]:	nDay	= Number(aDate[2]);	break;
					}
					aConvert						= new Array(nYear, nMonth, nDay);
				}
				return(aConvert);
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Fonction identifiant si l'annee est bissextile ou non
			function is_leapyear(nYear){
				// Analyse de l'annee. Une annee est bissextile si elle est divisible par 4 mais pas par 100 sauf si elle est divisible par 400
				if((nYear%4 == 0 && nYear%100 != 0) || nYear%400 == 0){ return(true); }else{ return(false); }
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Calcul du positionnement de la balise dans la page
			function getAbsoluteOffset(oTag, oLimit){
				var nT						= 0;
				var nL						= 0;
				var nPass					= 0;
				if(oTag && typeof(oTag) == "object"){
					while(oTag && String(oTag.tagName).toUpperCase() != "HTML" && String(oTag.tagName).toUpperCase() != "BODY" && oTag != oLimit && nPass < 500){
						// Calcul des decallages
						nT					+= oTag.offsetTop;
						nL					+= oTag.offsetLeft;
						// Remplacement de la balise a analyser
						oTag				= oTag.offsetParent;
						nPass++;
					}
					return({top:nT, left:nL});
				}else{
					return({top:null, left:null});
				}
			};
			// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
			// Calcul des dimensions du contenu de la page
			function documentDimensions(){
				// Calcul des dimensions en fonction de l'interpretation des css par le navigateur
				if(document.compatMode){
					var w			= document.documentElement.scrollWidth;
					var h 			= document.documentElement.scrollHeight;
				}else{
					var w			= document.body.scrollWidth;
					var h			= document.body.scrollHeight;
				}
				// Verification de la demande de taille maximale : document/window
					// Recuperation de la dimension de la fenetre
					function windowDim(){
						// Calcul des dimensions en fonction du navigateur
						var w				= window.innerWidth;
						var h				= window.innerHeight;
						if(document.documentElement.clientWidth){
							w			= document.documentElement.clientWidth;
							h 			= document.documentElement.clientHeight;
						}else{
							w			= document.body.clientWidth;
							h			= document.body.clientHeight;
						}
						// Envoi de la hauteur
						return({width:w, height:h});
					};
					b				= windowDim();
					// Comparaison
					w				= Math.max(w, b.width);
					h				= Math.max(h, b.height);
				// Verification des valeurs
				if(isNaN(w)) w		= null;
				if(isNaN(h)) h		= null;	
				// Envoi des dimensions
				return({width:w, height:h});
			};
	};
	
