//#14.00Aa WDCalendrier.JS
//VersionVI: 30F140026t
// Le seul support technique disponible pour cette librairie est
// accessible a travers le service "Assistance Directe".

// Manipulation d'un champ calendrier
function WDCalendrier (sAliasChamp, sAliasZR, sAliasAttribut)
{
	// L'alias du champ et de l'eventuel champ de saisie associe
	this.m_sAliasChamp = sAliasChamp;
	// La ZR eventuelle qui contient le champ si la propriete ..Valeur est liee a un attribut (sAliasChamp est alors l'alias de cet attribut)
	if (sAliasZR)
	{
		this.m_sAliasZR = sAliasZR;
		this.m_sAliasAttribut = sAliasAttribut;
	}
}

WDCalendrier.prototype =
{
	//	m_sAliasChamp:			"",
	//	m_sAliasChampSaisie:	"",
	//	m_oChampSaisie:			null,		// Champ de saisie pour le calendrier affiché
	//	m_fPCodeSelectionJour:	null,
	//	m_fPCodeAffichageMois:	null,
	//	m_clObjetSaisie:		null,
	//	m_nTimeoutFocus:		null,
	sSuffixeJour: "_JOUR",
	sSuffixeMois: "_MOIS",
	sActionPrecedent: "CALENDRIERPREC",
	sActionSuivant: "CALENDRIERSUIV",
	sActionAujourdhui: "CALENDRIERAUJO",

	// Initialisation :
	// - clObjetSaisie : Objet de manipulation de l'eventuel champ de saisie associe au champ
	Init: function(clObjetSaisie)
	{
		// Sauve le champ de saisie associe
		if (clObjetSaisie)
		{
			this.m_clObjetSaisie = clObjetSaisie;

			// Et cree l'objet popup automatique
			this.m_oPopupAutomatique = new WDPopupAutomatique(this);
		}
	},

	// Evenement avant l'affectation en AJAX du contenu du calendrier
	PreAffecteHTML: function(bDepuisAJAX)
	{
		// Si la popup existe (la classe gere en interne le cas de la popup affichee)
		if (this.m_oPopupAutomatique)
		{
			this.m_oPopupAutomatique.PreAffecteHTML(bDepuisAJAX);
		}
	},

	// Evenement apres l'affectation en AJAX du contenu du calendrier
	PostAffecteHTML: function(bDepuisAJAX)
	{
		// Si la popup existe
		if (this.m_oPopupAutomatique)
		{
			this.m_oPopupAutomatique.PostAffecteHTML(bDepuisAJAX);
		}
	},
	
	// Indique si on doit utiliser la gestion dans une ZR
	bGestionZR_SansPopup:function()
	{
		// Dans une ZR et sans champ de saisie
		return (this.m_sAliasZR && !this.m_clObjetSaisie);
	},
	
	// Indique si on doit utiliser la gestion des popup dans une ZR
	bGestionZR_AvecPopup:function()
	{
		// Dans une ZR et sans champ de saisie
		return (this.m_sAliasZR && this.m_clObjetSaisie);
	},

	// Récupère le champ dans le HTML
	// La liaison n'est plus statique car les éléments dans les ZRs changent
	oGetElementHTMLValeur: function()
	{
		// Si la valeur du champ n'est pas lie a un attribut de zone repetee
		if (!this.bGestionZR_SansPopup())
		{
			return document.getElementsByName(this.m_sAliasChamp + this.sSuffixeJour)[0];
		}
		else
		{
			var nIndiceZR = parseInt(document.getElementsByName(this.m_sAliasZR)[0].value);
//			var nDebut = parseInt(document.getElementsByName(this.m_sAliasZR + "_DEB")[0].value);

			// Recupere la collection des champs dans la ZR
			// ATTENTION, le champ est SANS suffixe pour ne pas casser le placement des valeurs dans le moteur
//			return document.getElementsByName("_" + (nIndiceZR + nDebut - 1) + "_" + this.m_sAliasAttribut)[0];
			return document.getElementsByName("_" + nIndiceZR + "_" + this.m_sAliasAttribut)[0];
		}
	},

	// Récupère le champ dans le HTML
	oGetElementHTMLMois: function()
	{
		// Si la valeur du champ n'est pas lie a un attribut de zone repetee
		// Ou si on est dans une popup d'un champ de saisie d'une ZR
		if (!this.bGestionZR_SansPopup())
		{
			return document.getElementsByName(this.m_sAliasChamp + this.sSuffixeMois)[0];
		}
		else
		{
			var nIndiceZR = parseInt(document.getElementsByName(this.m_sAliasZR)[0].value);
//			var nDebut = parseInt(document.getElementsByName(this.m_sAliasZR + "_DEB")[0].value);

			// Recupere la collection des champs dans la ZR
//			return document.getElementsByName("_" + (nIndiceZR + nDebut - 1) + "_" + this.m_sAliasAttribut + this.sSuffixeMois)[0];
			return document.getElementsByName("_" + nIndiceZR + "_" + this.m_sAliasAttribut + this.sSuffixeMois)[0];
		}
	},

	// Récupère le champ dans le HTML
	// La liaison n'est plus statique car les éléments dans les ZRs changent
	oGetElementHTMLPopup: function()
	{
//		// Si la valeur du champ n'est pas lie a un attribut de zone repetee
//		if (!this.m_sAliasZR)
//		{
		return _JGE(this.m_sAliasChamp, document, true, true);
//		}
//		else
//		{
//			var nIndiceZR = parseInt(document.getElementsByName(this.m_sAliasZR)[0].value);
////			var nDebut = parseInt(document.getElementsByName(this.m_sAliasZR + "_DEB")[0].value);
//			
//			// Recupere la collection des champs dans la ZR
////			return _JGE("_" + (nIndiceZR + nDebut - 1) + "_" + this.m_sAliasAttribut, document, true, true);
//			return _JGE("_" + nIndiceZR + "_" + this.m_sAliasAttribut, document, true, true);
//		}
	},

	// Definition du PCode de selection de jour navigateur
	CodeSelectionJour: function(pFonctionSelection)
	{
		this.m_fPCodeSelectionJour = pFonctionSelection;
	},

	// Definition du PCode d'affichage de mois navigateur
	CodeAffichageMois: function(pFonctionAffichage)
	{
		this.m_fPCodeAffichageMois = pFonctionAffichage;
	},

	// Selection du jour depuis un clic dans la cellule mais AUTOUR du lien
	OnJourClick: function(oEvent, sDate, sActionMoteur)
	{
		// Filtre les clics qui sont sur la zone du lien
		var oSource;
		if (bIE)
		{
			oSource = oEvent.srcElement;
		}
		else
		{
			oSource = oEvent.explicitOriginalTarget;
		}
		if (oSource && ((oSource.tagName + "").toUpperCase() == "TD"))
		{
			return this.OnJour(oEvent, sDate, sActionMoteur);
		}
	},

	// Selection du jour
	OnJour: function(oEvent, sDate, sActionMoteur)
	{
		// Récupère le champ contenant la valeur
		var oChampvaleur = this.oGetElementHTMLValeur();

		// Sauve l'ancienne valeur
		var sOldDate = oChampvaleur.value;

		// Ecrit la date dans la valeur du champ
		oChampvaleur.value = sDate;
		// Appel le PCode de selection s'il existe
		var bRes = this.m_fPCodeSelectionJour(oEvent, sActionMoteur);
		if (bRes !== false)
		{
			// Valide la valeur dans le champ de saisie si on en a un
			if (this.m_oPopupAutomatique)
			{
				// Transmet la valeur et les indications au champ de saisie
				this.m_clObjetSaisie.OnChangeCalendrier(oEvent, oChampvaleur.value, this.m_oChampSaisie);

				// Et se masque
				this.m_oPopupAutomatique.Masque(undefined, false);
			}

			// Pas de return XXX : casse les HREFs
			//			return bRes;
			return;
		}
		// Restaure l'ancienne valeur en cas d'annulation
		oChampvaleur.value = sOldDate;
	},

	OnAujourdhui: function()
	{
		// Pas de return XXX : casse les HREFs
		// Calcule la date du jour avec DateSys
		//		return this.OnJour(undefined, _DS(), this.sActionAujourdhui);
		this.OnJour(undefined, _DS(), this.sActionAujourdhui);
	},

	// Change le mois courant
	OnChangeMois: function(nOffset, sActionMoteur)
	{
		// Récupère le champ contenant la valeur
		var oChampMois = this.oGetElementHTMLMois();

		// Sauve l'ancienne valeur
		var sOldDate = oChampMois.value;
		// Conversion de la date en chaine en objet Date
		var oMois = _WMD(sOldDate);

		// Modifie le mois
		var nMois = oMois.getMonth();
		nMois += nOffset;

		// Normalise le mois
		var nOffsetAnnee = 0;
		while (nMois < 0)
		{
			nOffsetAnnee--;
			nMois += 12;
		}
		while (nMois > 11)
		{
			nOffsetAnnee++;
			nMois -= 12;
		}

		// Defini le mois et forcant le debut du mois
		oMois.setMonth(nMois, 1);
		// Force l'annee si besoin
		if (nOffsetAnnee != 0)
		{
			oMois.setYear(oMois.getYear() + nOffsetAnnee);
		}

		// Convertit la valeur en chaine WL ecrite dans le champ cache
		oChampMois.value = _JDTW(oMois);
		// Appel le PCode de selection s'il existe
		var bRes = this.m_fPCodeAffichageMois(undefined, sActionMoteur);
		if (bRes !== false)
		{
			// Pas de return XXX : casse les HREFs
			//			return bRes;
			return;
		}
		// Restaure l'ancienne valeur en cas d'annulation
		oChampMois.value = sOldDate;
	},

	OnNext: function()
	{
		// Demande le mois precedent
		// Pas de return XXX : casse les HREFs
		//		return this.OnChangeMois(+1, this.sActionSuivant);
		this.OnChangeMois(+1, this.sActionSuivant);
	},

	OnPrev: function()
	{
		// Demande le mois suivant
		// Pas de return XXX : casse les HREFs
		//		return this.OnChangeMois(-1, this.sActionPrecedent);
		this.OnChangeMois(-1, this.sActionPrecedent);
	},

	// Gestion du champ calendrier dans un champ de saisie

	// Notification (par le champ de saisie) que son contenu a changer
	OnChangeSaisie: function(oEvent, sValeur, oChampSaisie)
	{
		// Si on est dans une zone répétée, redessine le champ calendrier avec le mois de la ligne courante
		if (this.bGestionZR_AvecPopup())
		{
			// On bloque la MAJ (elle sera de toutes façons faite par l'ouverture de la popup
			// Sauf si on ets justement dans cette ouveture
			if (!this.m_bDansAffiche)
			{
				return;
			}
			else
			{
				this.m_sValeurPopupZR = oChampSaisie.value;
			}
		}
	
		if (!this.m_oChampSaisie || (this.m_oChampSaisie != oChampSaisie))
		{
			this.m_oChampSaisie = oChampSaisie;
		}

		// Appele la methode interne avec la valeur
		this.OnJour(oEvent, sValeur);
	},

	// Notification de que champ doit etre affiche
	// Le champ aussi que le format d'affichage sont transmit pour memorisation
	Affiche: function(oEvent, oChampSaisie)
	{
		// Si on est dans une zone répétée, redessine le champ calendrier avec le mois de la ligne courante
		if (this.bGestionZR_AvecPopup())
		{
			// Ne pas le faire si la valeur du champ calendrier est DEJA a jour pour ne pas faire une double MAJ si la valeur viens d'etre modifie juste avant l'ouverture
			// Note : oChampSaisie.value contient la valeur FORMATEE du champ. C'est ce que l'on sauve dans this.m_sValeurPopupZR
			if (this.m_sValeurPopupZR != oChampSaisie.value)
			{
				// En supprimant le bloquage dans OnChangeSaisie
				this.m_bDansAffiche = true;
				this.m_clObjetSaisie.MAJContenuCalendrier(oEvent, oChampSaisie);
				delete this.m_bDansAffiche;
			}
		}

		// Trouve le champ a afficher
		var oElement = this.oGetElementHTMLPopup();

		this.m_oPopupAutomatique.Affiche(oEvent, oElement, oChampSaisie);
	},

	// Notification de que champ doit etre affiche
	// Le champ aussi que le format d'affichage sont transmit pour memorisation
	AfficheInterne: function(oEvent, oElement, oChampSaisie)
	{
		// Memorise le champ precis (pour les ZR) sur lequel on est
		this.m_oChampSaisie = oChampSaisie;

		var oCibleAlign = oChampSaisie;
		// Deplace le champ selon la position du champ qui a recu le clic
		// Le champ calendrier popup est place pour que le bord droit soit aligne avec le bord droit du bouton
		// - Trouve le bouton source
		if (!oCibleAlign)
		{
			oCibleAlign = bIE ? oEvent.srcElement : oEvent.target;
		}

		// Decale le champ
		var nGauche = _JCCP(oCibleAlign.offsetLeft, oCibleAlign, true, true) + oCibleAlign.offsetWidth - parseInt(oElement.style.width);
		if (nGauche < 0)
		{
			nGauche = 0;
		}
		SetStyleLeft(oElement.style, _JCCP(nGauche, oElement, true, false), 0);
		oElement.style.top = _JCCP(_JCCP(oCibleAlign.offsetTop, oCibleAlign, false, true), oElement, false, false) + oCibleAlign.offsetHeight;
	},

	// Notification de que champ doit etre masquer
	MasqueInterne: function(oEvent, bLostFocus)
	{
		// Si on a perdu le focus, il faut forcer le redessin du champ
		// Sauf si on est dans une ZR car alors le redessin à été fait ne ouverture donc il est inutile (et déclenche une MAJ abusive du champ de saisie)
		if (bLostFocus && this.m_oChampSaisie && !this.m_sAliasZR)
		{
			this.m_clObjetSaisie.OnChange(oEvent, this.m_oChampSaisie);
		}

		// Detruit les valeur memorisee sur le champ de saisie
		delete this.m_oChampSaisie;
	}
}

