//#17.0.1.0 WDRating.js
//VersionVI: 30F170056g
// Le seul support technique disponible pour cette librairie est
// accessible a travers le service "Assistance Directe".

// Manipulation d'un champ image (avec defilement ou vignette)
function WDRating(sAliasChamp, sAliasZR, sAliasAttribut)
{
	// Si on est pas dans l'init d'un protoype
	if (sAliasChamp)
	{
		// Appel le constructeur de la classe de base
		WDChampParametresHote.prototype.constructor.apply(this, arguments);

		this.m_clDragRating = new WDDragRating();
	}
};

// Declare l'heritage
WDRating.prototype = new WDChampParametresHote();
// Surcharge le constructeur qui a ete efface
WDRating.prototype.constructor = WDRating;

WDRating.prototype.ms_eRateEntier = 0;
WDRating.prototype.ms_eRateDemi = 1;
WDRating.prototype.ms_eRateReel = 2;
WDRating.prototype.ms_eEtoileSans = -1;
WDRating.prototype.ms_eEtoilePleine = 0;
WDRating.prototype.ms_eEtoileVide = 1;
WDRating.prototype.ms_eEtoileSelection = 2;
WDRating.prototype.ms_eEtoileGrise = 3;

// Declare les fonction une par une

// Initialisation :
WDRating.prototype.Init = function Init()
{
	// Appel de la methode de la classe de base
	WDChampParametresHote.prototype.Init.apply(this, arguments);

	this.m_clDragRating = new WDDragRating(this);

	this.__tabInitTousElements();
};

// Initialise un champ rating. Retourne le tableau de gestion
WDRating.prototype.__tabInitTousElements = function __tabInitTousElements()
{
	// Si on est dans une ZR AJAX : ne fait rien sur les champs
	if (!this.bGestionZR())
	{
		this.m_tabDescriptions = this.__tabInitElements(this.m_oHote);

		// Affiche le champ (non fait par le serveur)
		this.__MAJAfficheComplet();
	}
	else if (!this.oGetZRAjax())
	{
		// Recupere la collection des champs dans la ZR
		this.m_tabDescriptions = [];
		this.PourToutesLignesZR(this.__InitElementsZR);
	}
	else
	{
		this.m_tabDescriptions = [];
	}
};

WDRating.prototype.__InitElementsZR = function __InitElementsZR(nLigneAbsolueBase1)
{
	this.m_tabDescriptions[nLigneAbsolueBase1 - 1] = this.__tabInitElements(this.oGetElementByIdZRIndice(document, nLigneAbsolueBase1, this.ms_sSuffixeHote), nLigneAbsolueBase1);
	// Affiche le champ (non fait par le serveur)
	this.__MAJAfficheComplet(nLigneAbsolueBase1);
};

// Initialise un champ rating. Retourne le tableau de gestion
WDRating.prototype.__tabInitElements = function __tabInitElements(oConteneur, nIndiceZR)
{
	// Pas de conteneur possible pour les lignes invisibles
	var tabDescriptions;
	if (oConteneur)
	{
		tabDescriptions = [];

		// Liaison avec les div d'affichage (nombre de div)
		// Normalement tabDivs.length == this.m_oParametres.m_nNbEtoileMax * 2;
		var tabDivs = oConteneur.getElementsByTagName("div");
		var i;
		var nLimiteI = tabDivs.length;
		for (i = 0; i < nLimiteI; i++)
		{
			var oDiv = { m_oDiv: tabDivs[i] };
			tabDescriptions.push(oDiv);

			// Liaison sur le clic
			this.m_clDragRating.InitElement(oDiv, oDiv.m_oDiv, nIndiceZR);
		}
	}

	return tabDescriptions;
};

// Libere un champ rating
WDRating.prototype.__LibereTousElements = function __LibereTousElements()
{
	var i;
	var nLimiteI = this.m_tabDescriptions.length;
	for (i = 0; i < nLimiteI; i++)
	{
		this.__LibereElements(this.m_tabDescriptions[i]);
	}
	this.m_tabDescriptions = [];
};

WDRating.prototype.__LibereElementsZR = function __LibereElementsZR(nLigneAbsolueBase1, bDelete)
{
	var nLigne = nLigneAbsolueBase1 - 1;
	if (this.m_tabDescriptions[nLigne])
	{
		this.__LibereElements(this.m_tabDescriptions[nLigne]);
		if (bDelete)
		{
			delete this.m_tabDescriptions[nLigne];
		}
	}
};

// Libere un champ rating
WDRating.prototype.__LibereElements = function __LibereElements (tabDescriptions)
{
	var i;
	var nLimiteI = tabDescriptions.length;
	for (i = 0; i < nLimiteI; i++)
	{
		var oDiv = tabDescriptions[i];
		this.m_clDragRating.LibereElement(oDiv, oDiv.m_oDiv);
		oDiv.m_oDiv = null;
		delete oDiv.m_oDiv;
		tabDescriptions[i] = null;
	}
	tabDescriptions = [];
};

// Applique les parametres
WDRating.prototype._vAppliqueParametres = function _vAppliqueParametres()
{
	WDChampParametresHote.prototype._vAppliqueParametres.apply(this, arguments);

	// Affiche le champ
	this.__MAJAfficheComplet();
};

// Recupere la valeur
WDRating.prototype.GetValeur = function GetValeur(oEvent, sValeur, oChamp)
{
	// Appel de la methode de la classe de base et retour de son resultat
	return WDChampParametresHote.prototype.GetValeur.apply(this, [oEvent, this.m_oDonnees.m_dValeur, oChamp]);
};

// Ecriture de la valeur du champ en programmation
WDRating.prototype.SetValeur = function SetValeur(oEvent, sValeur, oChamp)
{
	// Appel de la methode de la classe de base (ignore la valeur retourne par l'implementation de la classe de base)
	WDChampParametresHote.prototype.SetValeur.apply(this, arguments);

	this.__SetValeur(parseFloat(sValeur));

	// Dans tous les cas : retourne la vraie valeur
	return this.m_oDonnees.m_dValeur;
};

// Recupere la valeur arrondie correctement
WDRating.prototype.__dArrondiSelection = function __dArrondiSelection(dValeurSelection, dValeurPrecedente)
{
	// Calcule la valeur reelle selon la position de la valeur actuelle et les options
	// Si on demande une valeur entiere, il faut arrondir
	switch (this.m_oParametres.m_eGranulariteValeur)
	{
	case this.ms_eRateEntier:
		// Si on demande une valeur entiere
		return Math.ceil(dValeurSelection);
		break;

	case this.ms_eRateDemi:
		// Si on demande une valeur a la moitie, il faut arrondir dans le bon sens
		if (dValeurSelection < dValeurPrecedente)
		{
			return Math.ceil(dValeurSelection * 2) / 2;
		}
		else if (dValeurSelection > dValeurPrecedente)
		{
			return Math.ceil(dValeurSelection * 2) / 2;
		}
		break;

	case this.ms_eRateReel:
		// Si on demande une valeur flotante, on ne change pas la valeur
		return dValeurSelection
	}
};

// Indique que la valeur a changer par une action de l'utilisateur (provoque un redessin)
WDRating.prototype.OnChange = function OnChange(oEvent, dValeurSelection, nIndiceZR)
{
	// Gere le cas de la ZR
	var dValeurPrecedente = this.oAppelSurLigneZR(nIndiceZR, this.__dGetValeur, []);
	dValeurSelection = this.__dArrondiSelection(dValeurSelection, dValeurPrecedente);

	// On force reelement la ligne de la ZR
	if (this.bGestionZR() && (nIndiceZR !== undefined))
	{
		this.SetZRValeur(oEvent, nIndiceZR);
	}

	// Rien si la valeur ne change pas
	if (dValeurSelection == dValeurPrecedente)
	{
		return;
	}

	// Fixe la valeur (provoque un redessin)
	this.__SetValeur(dValeurSelection, nIndiceZR);

	// Appel du PCode (qui appel le code serveur)
	this.RecuperePCode(this.ms_nEventNavChange)(oEvent);

	// Notifie la ZR
	var oZRAjax = this.oGetZRAjax();
	if (oZRAjax && oEvent)
	{
		oZRAjax.vOnValideLigneZRExterne(oEvent);
	}
};

// Fixe la valeur
WDRating.prototype.__SetValeur = function __SetValeur(dValeur, nIndiceZR)
{
	// Valide la valeur
	if (isNaN(dValeur))
		return;
	dValeur = Math.max(dValeur, this.m_oParametres.m_nNbEtoileMin);
	dValeur = Math.min(dValeur, this.m_oParametres.m_nNbEtoileMax);

	// Modifie la valeur dans les parametres
	this.m_oDonnees.m_dValeur = dValeur;

	// Gere le cas de la ZR
	// => Deja gere au niveau parent si besoin (OnChange)
	// (pas dans le cas de SetValeur car on n'est alors pas en ZR)
	// On utilise donc directement __MAJAfficheCompletInterne

	// Ecrit la valeur dans le champ formulaire
	// Meme dans le cas du parcours navigateur car il tient compte des bornes
	this._vSetValeurChampFormulaire(dValeur);

	// MAJ de l'affichage (prend en compte le changement possible de taille du champ externe)
	this.__MAJAfficheCompletInterne(dValeur, nIndiceZR);
};

// Trouve la valeur du champ selon l'indice de la ZR
// Modifie tabIndiceZRSav si besoin pour stocker nIndiceZRSav
WDRating.prototype.__dGetValeur = function __dGetValeur()
{
	if (this.bGestionZR())
	{
		this._vLiaisonHTML();
		if (this.m_oChampFormulaire)
		{
			return parseFloat(this.m_oChampFormulaire.value);
		}
	}
	else
	{
		return this.m_oDonnees.m_dValeur;
	}
	return undefined;
};

// Lit le flag lecture seule
WDRating.prototype.bLectureSeuleOuGriseExterne = function bLectureSeuleOuGriseExterne(nIndiceZR)
{
	return this.oAppelSurLigneZR(nIndiceZR, this._bLectureSeuleOuGrise, [], true);
};

// MAJ de l'affichage (prend en compte le changement possible de taille du champ externe)
WDRating.prototype.__MAJAfficheComplet = function __MAJAfficheComplet(nIndiceZR, dValeurSelection)
{
	this.oAppelSurLigneZR(nIndiceZR, this.__MAJAfficheCompletZR, arguments);
};
WDRating.prototype.__MAJAfficheCompletZR = function __MAJAfficheCompletZR(nIndiceZR, dValeurSelection)
{
	this.__MAJAfficheCompletInterne(this.__dGetValeur(), nIndiceZR, dValeurSelection);
};

WDRating.prototype.__MAJAfficheCompletInterne = function __MAJAfficheCompletInterne(dValeur, nIndiceZR, dValeurSelection)
{
	var tabDescriptions = this.tabGetDescriptions(nIndiceZR);
	// Dans une ligne de ZR invisible ou repliee, le champ n'est pas present
	if (tabDescriptions && (dValeur !== undefined))
	{
		// Supprime le div tertiaire s'il existe
		bHTMLVideDepuisVariable(this, "m_oDivTertiaire");

//		var bGrise = this.oAppelSurLigneZR(nIndiceZR, this._bGrise, [], true);
		var bGrise = this.oAppelSurLigneZR(nIndiceZR, this._bGrise, [], true);

		var nEtoile;
		var nLimiteEtoile = this.m_oParametres.m_nNbEtoileMax;
		for (nEtoile = 0; nEtoile < nLimiteEtoile; nEtoile++)
		{
			// Si la valeur de selection correspond a l'etoile courante
			var bSelection;
			var bDivTertiaire = false;
			if (dValeurSelection !== undefined)
			{
				dValeurSelection = this.__dArrondiSelection(dValeurSelection, dValeur);
				if (dValeurSelection < dValeur)
				{
					bSelection = (Math.floor(dValeurSelection) <= nEtoile) && (nEtoile < dValeur);
				}
				else if (dValeurSelection > dValeur)
				{
					bSelection = (Math.floor(dValeurSelection) > nEtoile) && (nEtoile >= Math.floor(dValeur));
				}
				else
				{
					bSelection = false;
				}
				if ((dValeur > nEtoile) && (dValeur < (nEtoile + 1)) && (dValeurSelection > nEtoile) && (dValeurSelection < (nEtoile + 1)))
				{
					bDivTertiaire = true;
				}
			}

			// Dessine chaque etoile
			this.__AfficheUnDivPrincipal(tabDescriptions, nEtoile, dValeur, bSelection, dValeurSelection, bGrise);
			this.__AfficheUnDivSecondaire(tabDescriptions, nEtoile, dValeur, bSelection, dValeurSelection, bGrise);

			// Si besoin, ajoute le troisieme div
			if (bDivTertiaire)
			{
				this.__AfficheUnDivTertiaire(tabDescriptions, nEtoile, dValeur, bSelection, dValeurSelection, bGrise);
			}
		}
	}
};

// Dessine un div principal (= celui affiche en cas de valeur entiere)
WDRating.prototype.__AfficheUnDivPrincipal = function __AfficheUnDivPrincipal(tabDescriptions, nEtoile, dValeur, bSelection, dValeurSelection, bGrise)
{
	var dLargeur;
	var eEtatEtoile;
	if ((dValeurSelection !== undefined) && (this.ms_eRateEntier != this.m_oParametres.m_eGranulariteValeur) && (dValeurSelection > nEtoile) && (dValeurSelection < (nEtoile + 1)))
	{
		if ((dValeur > nEtoile) && (dValeur < (nEtoile + 1)))
		{
			eEtatEtoile = this.ms_eEtoilePleine;
			dLargeur = Math.min(dValeur, dValeurSelection) - nEtoile;
		}
		else
		{
			dLargeur = dValeurSelection - nEtoile;
			eEtatEtoile = (dValeurSelection > dValeur) ? this.ms_eEtoileSelection : this.ms_eEtoilePleine;
		}
	}
	else if ((this.ms_eRateEntier != this.m_oParametres.m_eGranulariteValeur) && (dValeur > nEtoile) && (dValeur < (nEtoile + 1)))
	{
		dLargeur = dValeur - nEtoile;
		eEtatEtoile = (bSelection && (dValeurSelection < dValeur)) ? this.ms_eEtoileSelection : this.ms_eEtoilePleine;
	}
	else
	{
		dLargeur = 1.0;
		if (bSelection)
		{
			eEtatEtoile = this.ms_eEtoileSelection;
		}
		else if (dValeur > (nEtoile + 1))
		{
			eEtatEtoile = this.m_oParametres.m_bDessinValeurPrevAvec0 ? this.ms_eEtoileVide : this.ms_eEtoilePleine;
		}
		else if (dValeur == (nEtoile + 1))
		{
			eEtatEtoile = this.ms_eEtoilePleine;
		}
		else
		{
			eEtatEtoile = this.ms_eEtoileVide;
		}
	}
	this.__AfficheUnDiv(tabDescriptions, nEtoile, false, dLargeur, eEtatEtoile, dValeur, bGrise);
};

// Dessine un div secondaire (= celui affiche en cas de valeur non entiere sur l'etoile donnee)
WDRating.prototype.__AfficheUnDivSecondaire = function __AfficheUnDivSecondaire(tabDescriptions, nEtoile, dValeur, bSelection, dValeurSelection, bGrise)
{
	if (this.ms_eRateEntier != this.m_oParametres.m_eGranulariteValeur)
	{
		var bVisible;
		var eEtatEtoile;

		if ((dValeurSelection !== undefined) && (dValeurSelection > nEtoile) && (dValeurSelection < (nEtoile + 1)))
		{
			bVisible = true;
			if ((dValeur > nEtoile) && (dValeur < (nEtoile + 1)))
			{
				eEtatEtoile = this.ms_eEtoileVide;
				dValeur = Math.max(dValeur, dValeurSelection);
			}
			else
			{
				eEtatEtoile = (dValeurSelection > dValeur) ? this.ms_eEtoileVide : this.ms_eEtoileSelection;
				dValeur = dValeurSelection;
			}
		}
		else if ((dValeur > nEtoile) && (dValeur < (nEtoile + 1)))
		{
			// Affichee uniquement si on a une valeur non entiere sur la plage de l'etoile courante
			bVisible = true;
			eEtatEtoile = (bSelection && (dValeurSelection > dValeur)) ? this.ms_eEtoileSelection : this.ms_eEtoileVide;
		}
		else
		{
			// Masque l'etoile
			bVisible = false;
		}

		if (bVisible)
		{
			var dLargeur = 1.0 - (dValeur - nEtoile);
			this.__AfficheUnDiv(tabDescriptions, nEtoile, true, dLargeur, eEtatEtoile, dValeur, bGrise);
		}
		clWDUtil.SetDisplay(tabDescriptions[nEtoile * 2 + 1].m_oDiv, bVisible);
	}
};

// Dessine le div tertiaire (= celui affiche en cas de valeur non entiere sur l'etoile donnee et que l'on est en selection depuis la valeur courante !!)
WDRating.prototype.__AfficheUnDivTertiaire = function __AfficheUnDivTertiaire(tabDescriptions, nEtoile, dValeur, bSelection, dValeurSelection, bGrise)
{
	// Creation du div avant le div secondaire
	var oDivSecondaire = tabDescriptions[nEtoile * 2 + 1].m_oDiv;
	this.m_oDivTertiaire = oDivSecondaire.parentNode.insertBefore(oDivSecondaire.cloneNode(), oDivSecondaire);

	// Et l'affiche
	var dLargeur = Math.abs(dValeur - dValeurSelection);
	var dDebut = Math.min(dValeur, dValeurSelection) - nEtoile;
	if (clWDUtil.bRTL)
	{
		dDebut = 1.0 - (Math.max(dValeur, dValeurSelection) - nEtoile);
	}
	this.__AfficheUnDivInterne(this.m_oDivTertiaire, nEtoile, dLargeur, dDebut, this.ms_eEtoileSelection, dValeurSelection, bGrise, false);
};

// Place les caracteristiques d'un div
// dLargeur : ]0, 1] : largeur totale de l'etoile utilise
// nEtat : { 0, 1, 2 } : { Vide, plein, selection }
WDRating.prototype.__AfficheUnDiv = function __AfficheUnDiv(tabDescriptions, nEtoile, bDivSecondaire, dLargeur, eEtatEtoile, dValeur, bGrise)
{
	// dDebut : [0, 1[ : debut de l'affichage du div dans l'etoile (> 0 uniquement avec les etoiles secondaires)
	var dDebut = 0.0;
	if ((dLargeur != 1.0) && ((clWDUtil.bRTL && !bDivSecondaire) || (!clWDUtil.bRTL && bDivSecondaire)))
	{
		dDebut = 1.0 - dLargeur;
	}

	this.__AfficheUnDivInterne(tabDescriptions[nEtoile * 2 + (bDivSecondaire ? 1 : 0)].m_oDiv, nEtoile, dLargeur, dDebut, eEtatEtoile, dValeur, bGrise, bDivSecondaire)
};

// Place les caracteristiques d'un div
// dLargeur : ]0, 1] : largeur totale de l'etoile utilise
// dDebut : [0, 1[ : debut de l'affichage du div dans l'etoile
// nEtat : { 0, 1, 2 } : { Vide, plein, selection }
WDRating.prototype.__AfficheUnDivInterne = function __AfficheUnDivInterne(oDiv, nEtoile, dLargeur, dDebut, eEtatEtoile, dValeur, bGrise, bDivSecondaire)
{
	// Corrige l'etat en fonction de la disponibilite et de l'etat grise
	eEtatEtoile = this.__eCorrigeEtat(eEtatEtoile, bGrise);

	// Calcule la position reelle dans la planche
	var dPosition = eEtatEtoile;
	if (this.m_oParametres.m_bUnePlancheParValeur)
	{
		dPosition += nEtoile * this.m_oParametres.m_nNbEtatsImageEtoile;
	}
	// Si on a un offset de debut en tient compte
	dPosition += dDebut;
	// Puis convertit en coordonnees dans l'image de fond
	dPosition *= this.m_oParametres.m_oTailleUneEtoile.m_nX;

	// Si on est sous IE en mode quirks et que la largeur totale n'est pas un multiple de 2, la largueur va etre mal arrondie
	// Et un element passera a la ligne et ne sera donc pas affiche
	// Le calcul est complique : on test d'abord le cas simple de 50%
	if (bIEQuirks && bDivSecondaire && (dLargeur == 0.5) && (1 == (this.m_oParametres.m_oTailleUneEtoile.m_nX % 2)))
	{
		dLargeur = 0.499;
	}

	// Fixe les proprietes
	oDiv.style.width = parseInt(dLargeur * 100, 10) + "%";
	if (eEtatEtoile != this.ms_eEtoileSans)
	{
		oDiv.style.backgroundPosition = "-" + dPosition.toFixed(0) + "px center";
		oDiv.style.backgroundImage = "";
	}
	else
	{
		oDiv.style.backgroundImage = "none";
	}

	// Affiche la bulle
	var sBulle;
	if (this.m_oDonnees.m_tabBulles && (nEtoile < this.m_oDonnees.m_tabBulles.length))
	{
		sBulle = this.m_oDonnees.m_tabBulles[nEtoile].m_sBulle;
	}
	if (!sBulle || (sBulle.length == 0))
	{
		// Si on est sur une valeur non entiere et que l'on est sur la bulle en cours de modification, on prend la valeur affichee avec deux decimales
		sBulle = (nEtoile + 1) + "";
		if (dLargeur != 1.0)
		{
			sBulle = dValeur.toFixed(this.ms_eRateReel == this.m_oParametres.m_eGranulariteValeur ? 2 : 1);
		}
	}
	oDiv.title = sBulle;
};

// Corrige l'etat en fonction de la disponibilite et de l'etat grise
WDRating.prototype.__eCorrigeEtat = function __eCorrigeEtat (eEtatEtoile, bGrise)
{
	switch (eEtatEtoile)
	{
	default:
	case this.ms_eEtoilePleine:
		// Si besoin (et si disponible) applique l'etat grise
		if (bGrise && (this.ms_eEtoileGrise <= this.m_oParametres.m_nNbEtatsImageEtoile))
		{
			return this.ms_eEtoileGrise;
		}
		return this.ms_eEtoilePleine;

	case this.ms_eEtoileVide:
		// Si disponible applique l'etat
		if (this.ms_eEtoileGrise <= this.m_oParametres.m_nNbEtatsImageEtoile)
		{
			return this.ms_eEtoileVide;
		}
		// Sinon ne dessine rien
		return this.ms_eEtoileSans;

	case this.ms_eEtoileSelection:
		// Si disponible applique l'etat
		if (this.ms_eEtoileSelection <= this.m_oParametres.m_nNbEtatsImageEtoile)
		{
			return this.ms_eEtoileSelection;
		}
		// Sinon ne dessine une etoile pleine
		return this.ms_eEtoilePleine;
	}
};

// - Tous les champs : notifie que une ZRs a ete MAJ en AJAX (= ZR non AJAX mais avec les ZR horizontales)
WDRating.prototype._vOnZRAfficheAJAXInterne = function _vOnZRAfficheAJAXInterne()
{
	// Appel de la methode de la classe de base (qui normalement ne fait rien car on est une ZR donc pas dans une autre ZR)
	WDChampParametresHote.prototype._vOnZRAfficheAJAXInterne.apply(this, arguments);

	this.__tabInitTousElements();
};

// Methode appele directement
// - Champ dans une ZR : notifie le champ de l'affichage/suppression de la ligne
WDRating.prototype._vOnLigneZRAffiche = function _vOnLigneZRAffiche(nLigneAbsolueBase1, bSelectionne)
{
	// Appel de la methode de la classe de base
	WDChampParametresHote.prototype._vOnLigneZRAffiche.apply(this, arguments);

	this.__LibereElementsZR(nLigneAbsolueBase1, false);
	this.__InitElementsZR(nLigneAbsolueBase1);
};
WDRating.prototype._vOnLigneZRMasque = function _vOnLigneZRMasque(nLigneAbsolueBase1, bSelectionne, oEvent)
{
	this.__LibereElementsZR(nLigneAbsolueBase1, true);

	// Appel de la methode de la classe de base
	WDChampParametresHote.prototype._vOnLigneZRMasque.apply(this, arguments);
};

// Trouve la description de l'element
WDRating.prototype.tabGetDescriptions = function tabGetDescriptions(nIndiceZR)
{
	if (this.bGestionZR())
	{
		if (nIndiceZR === undefined)
		{
			nIndiceZR = this.nGetZRValeur();
		}
		return this.m_tabDescriptions[nIndiceZR - 1];
	}
	else
	{
		return this.m_tabDescriptions;
	}
};

//////////////////////////////////////////////////////////////////////////
// Le gestionnaire de clic sous forme de dragdrop pour le champ rating : permet la gestion de la surbrillance

// Constructeur
function WDDragRating(oChampRating)
{
	// Si on est pas dans l'init d'un protoype
	if (oChampRating !== undefined)
	{
		// Appel le constructeur de la classe de base
		WDDrag.prototype.constructor.apply(this, [0, 50]);

		// Sauve l'objet attache
		this.m_oChampRating = oChampRating;
	}
};

// Declare l'heritage
WDDragRating.prototype = new WDDrag();
// Surcharge le constructeur qui a ete efface
WDDragRating.prototype.constructor = WDDragRating;

// Gestion pour un element
WDDragRating.prototype.InitElement = function InitElement(oObjetSurDiv, oDiv, nIndiceZR)
{
	// Intercepte le mousedown sur le rendez-vous
	var oThis = this;
	oObjetSurDiv.m_fMouseDown = function(oEvent) { oThis.OnMouseDown.apply(oThis, [oEvent || event, nIndiceZR]); return oThis._bStopPropagation(oEvent); };
	HookOnXXX(oDiv, 'onmousedown', 'mousedown', oObjetSurDiv.m_fMouseDown);
};
WDDragRating.prototype.LibereElement = function LibereElement(oObjetSurDiv, oDiv)
{
	// Supprime l'evenement mousedown sur le rendez-vous
	UnhookOnXXX(oDiv, 'onmousedown', 'mousedown', oObjetSurDiv.m_fMouseDown);
	oObjetSurDiv.m_fMouseDown = null;
	delete oObjetSurDiv.m_fMouseDown;
};

// Appel lors du debut d'un clic pour le deplacement
// Pose les hooks
WDDragRating.prototype._vbOnMouseDown = function _vbOnMouseDown(oEvent, nIndiceZR)
{
	// Appel de la classe de base : sauve la position de la souris et place les hooks
	if (!WDDrag.prototype._vbOnMouseDown.apply(this, arguments))
	{
		return false;
	}

	// Interdit si le champ est en lecture seule
	if (this.m_oChampRating.bLectureSeuleOuGriseExterne(nIndiceZR))
	{
		return false;
	}

	// Premier dessin avec la valeur de selection
	this.m_nIndiceZR = nIndiceZR;
	this.__MAJAfficheComplet(oEvent);

	return true;
};

// Appel lors du deplacement de la souris
WDDragRating.prototype._vOnMouseMove = function _vOnMouseMove(oEvent)
{
	// Appel de la classe de base
	WDDrag.prototype._vOnMouseMove.apply(this, arguments);

	// Interdit si le champ est en lecture seule
	if (this.m_oChampRating.bLectureSeuleOuGriseExterne(this.m_nIndiceZR))
	{
		return;
	}

	// Dessin avec la valeur de selection
	this.__MAJAfficheComplet(oEvent);
};

// Appel lors du relachement de la souris
WDDragRating.prototype._vOnMouseUp = function _vOnMouseUp(oEvent)
{
	try
	{
		// Interdit si le champ est en lecture seule
		if (!this.m_oChampRating.bLectureSeuleOuGriseExterne(this.m_nIndiceZR))
		{
			// Sauve la valeur
			this.m_oChampRating.OnChange(oEvent, this.__dGetValeurSelection(oEvent), this.m_nIndiceZR);
		}
	}
	catch (e)
	{
		throw e;
	}
	finally
	{
		// Pour avoir une liberation complete
		// Appel de la classe de base
		WDDrag.prototype._vOnMouseUp.apply(this, arguments);

		// Pas de dessin final (fait par OnChange)
		if (this.m_nIndiceZR !== undefined)
		{
			delete this.m_nIndiceZR;
		}
	}
};

// MAJ de l'affichage
WDDragRating.prototype.__MAJAfficheComplet = function __MAJAfficheComplet(oEvent)
{
	// Dessin avec la valeur de selection
	this.m_oChampRating.__MAJAfficheComplet(this.m_nIndiceZR, this.__dGetValeurSelection(oEvent));
};

// Indique la valeur courante (uniquement si on est en selection)
// La valeur retournee est toujours brute, il faut la retraiter par l'appelant selon l'ancienne valeur
WDDragRating.prototype.__dGetValeurSelection = function __dGetValeurSelection(oEvent)
{
	var nX = oEvent.clientX;
	var nLargeurDiv = this.m_oChampRating.m_oParametres.m_oTailleUneEtoile.m_nX;
	var tabDescriptions = this.m_oChampRating.tabGetDescriptions(this.m_nIndiceZR);

	// Compare la valeur par rapport au div principaux
	var i;
	var nLimiteI = tabDescriptions.length / 2;
	for (i = 0; i < nLimiteI; i++)
	{
		var nEtoile = clWDUtil.bRTL ? nLimiteI - i - 1 : i;
		var oDiv = tabDescriptions[nEtoile * 2].m_oDiv;
		// Si on est en right-to-left il faut prendre le debut du div de fin s'il est visible
		if (clWDUtil.bRTL && clWDUtil.bEstDisplay(tabDescriptions[nEtoile * 2 + 1].m_oDiv, document))
		{
			oDiv = tabDescriptions[nEtoile * 2 + 1].m_oDiv
		}
		var nDifference = nX - _JCCP(oDiv.offsetLeft, oDiv, true, true);
		// Si on est en dessous c'est que l'on est :
		// - Entre deux div (on a deja teste la presence dans les div precedents)
		// - Avant le premier div (si on teste le premier div
		if (nDifference < 0)
		{
			// Donc on prend l'indice du div qui correspond a la valeur du div precedent
			return clWDUtil.bRTL ? (nEtoile + 1) : nEtoile;
		}
		else if (nDifference < nLargeurDiv)
		{
			// Si on est avant la fin du div : prend la position dans le div
			var dOffsetEtoile = nDifference / nLargeurDiv;
			if (clWDUtil.bRTL)
			{
				dOffsetEtoile = 1.0 - dOffsetEtoile;
			}
			return nEtoile + dOffsetEtoile;
		}
		// Sinon teste le div suivant
	}

	// Non trouve : on prend la valeur maximale
	return clWDUtil.bRTL ? 0 : this.m_oChampRating.m_oParametres.m_nNbEtoileMax;
};

