//#17.0.1.0 WDDrag.js
//VersionVI: 30F170078n
// Le seul support technique disponible pour cette librairie est
// accessible a travers le service "Assistance Directe".

// Gestion commune du drag-drop
function WDDragBase (bPasInitPrototype)
{
	// Si on est pas dans l'init d'un protoype
	if (bPasInitPrototype)
	{
	}
};

// Stop la propagation si demande
WDDragBase.prototype._bStopPropagation = function _bStopPropagation(oEvent)
{
	return clWDUtil.bStopPropagationCond(oEvent, this._vbStopPropagation());
};

// Par defaut stoppe la propagation
WDDragBase.prototype._vbStopPropagation = clWDUtil.m_pfVide;

// Recupere une position depuis un evenement
WDDragBase.prototype._nGetPosXEvent = function _nGetPosXEvent(oEvent)
{
	if (bTouch)
	{
		switch (oEvent.type)
		{
			case "touchend":
			case "touchcancel":
				break;
			default:
				this.m_nLastPosX = oEvent.touches.item(0).clientX;
				break;
		}
		return this.m_nLastPosX;
	}
	else
	{
		return oEvent.clientX;
	}
};
WDDragBase.prototype._nGetPosYEvent = function _nGetPosYEvent(oEvent)
{
	if (bTouch)
	{
		switch (oEvent.type)
		{
			case "touchend":
			case "touchcancel":
				break;
			default:
				this.m_nLastPosY = oEvent.touches.item(0).clientY;
				break;
		}
		return this.m_nLastPosY;
	}
	else
	{
		return oEvent.clientY;
	}
};

// Manipulation d'un element par Drag-Drop
function WDDrag(nDelaiAvantDeplacement, nDelaiEntreDeplacement)
{
	// Si on est vraiment dans la construction d'un objet
	if (nDelaiAvantDeplacement !== undefined)
	{
		// Appel le constructeur de la classe de base
		WDDragBase.prototype.constructor.apply(this, [true]);

		// Cree les fonctions de rappel
		var oThis = this;
		this.m_fMouseDown = function(oEvent) { return oThis.bOnMouseDown(oEvent || event) ? oThis._bStopPropagation(oEvent) : true; };
		this.m_fMouseMove = function(oEvent) { oThis.OnMouseMove(oEvent || event); return oThis._bStopPropagation(oEvent); };
		this.m_fMouseUp = function(oEvent) { oThis.OnMouseUp(oEvent || event); return oThis._bStopPropagation(oEvent); };
		// Ne fonctionne que avec IE. On stoppe toujours la selection en cas de dragdrop sur un element cible
		this.m_fSelectStart = function(oEvent) { return oThis._bStopPropagation(oEvent || event); };

		this.m_nDelaiAvantDeplacement = nDelaiAvantDeplacement;
		this.m_nDelaiEntreDeplacement = nDelaiEntreDeplacement;
	}
};

// Declare l'heritage
WDDrag.prototype = new WDDragBase();
// Surcharge le constructeur qui a ete efface
WDDrag.prototype.constructor = WDDrag;

WDDrag.prototype.ms_eDragDrop = 0;
WDDrag.prototype.ms_eDragRedimDebut = 1;
WDDrag.prototype.ms_eDragRedimFin = 2;
// + Droite + Gauche + Coins si besoin
WDDrag.prototype.ms_sMouseDown = (bTouch ? "touchstart" : "mousedown");
WDDrag.prototype.ms_sMouseMove = (bTouch ? "touchmove" : "mousemove");
WDDrag.prototype.ms_sMouseUp = (bTouch ? "touchend" : "mouseup");

// Liberation
WDDrag.prototype.Libere = function Libere()
{
	this.m_fMouseDown = null;
	delete this.m_fMouseDown;
	this.m_fMouseMove = null;
	delete this.m_fMouseMove;
	this.m_fMouseUp = null;
	delete this.m_fMouseUp;
	this.m_fSelectStart = null;
	delete this.m_fSelectStart;
};

// Place un hook sur mousedown/touchstart
WDDrag.prototype._AttacheDetacheMouseDown = function _AttacheDetacheMouseDown(bAttache, oElement, fFonction)
{
	// Il faut la phase de capture pour les tablettes
	clWDUtil.AttacheDetacheEvent(bAttache, oElement, this.ms_sMouseDown, fFonction, bTouch);
};

// Indique si on est presentement en drag-drop
WDDrag.prototype.bEnDrag = function bEnDrag()
{
	return undefined !== this.nGetPosX();
};

// Recupere les positions
WDDrag.prototype.nGetPosX = function nGetPosX()
{
	return this.m_nPosX;
};
WDDrag.prototype.nGetPosY = function nGetPosY()
{
	return this.m_nPosY;
};

WDDrag.prototype._oGetOriginalTarget = function _oGetOriginalTarget(oEvent)
{
	if (!bTouch)
	{
		return clWDUtil.oGetOriginalTarget(oEvent);
	}
	else
	{
		return document.elementFromPoint(this._nGetPosXEvent(oEvent), this._nGetPosYEvent(oEvent));
	}
};

// Recupere la variation de la position
WDDrag.prototype.nGetOffsetPosX = function nGetOffsetPosX(oEvent)
{
	var nOffsetPosX = this._nGetPosXEvent(oEvent) - this.nGetPosX();
	// Prend en compte le mode ltr/rtl
	return (clWDUtil.bRTL ? -nOffsetPosX : nOffsetPosX);
};
WDDrag.prototype.nGetOffsetPosY = function nGetOffsetPosY(oEvent)
{
	return this._nGetPosYEvent(oEvent) - this.nGetPosY();
};

// Appel lors du debut d'un click pour le redimensionnement
// Pose les hooks
WDDrag.prototype.bOnMouseDown = function bOnMouseDown(oEvent)
{
	// Uniquement sur le bouton gauche
	if (!clWDUtil.bValideBouton(oEvent))
	{
		return false;
	}

	// Appel de la methode surchargee
	if (this._vbOnMouseDown.apply(this, arguments))
	{
		return !bTouch;
	}
	else
	{
		return false;
	}
};

// Appel lors du debut d'un click pour le redimensionnement
// Pose les hooks
WDDrag.prototype._vbOnMouseDown = function _vbOnMouseDown(oEvent)
{
	// Sauve la position souris (et initialise m_nLastPosX/m_nLastPosY);
	this.m_nPosX = this._nGetPosXEvent(oEvent);
	this.m_nPosY = this._nGetPosYEvent(oEvent);

	// Intercepte les evenements sur le document
	if (!this.m_bHookPoses)
	{
		this.m_bHookPoses = true;
		clWDUtil.AttacheDetacheEvent(true, document, this.ms_sMouseMove, this.m_fMouseMove, bTouch);
		clWDUtil.AttacheDetacheEvent(true, document, this.ms_sMouseUp, this.m_fMouseUp, bTouch);
		if (bIE)//bIEQuirks ?
		{
			clWDUtil.AttacheDetacheEvent(true, document, "selectstart", this.m_fSelectStart, bTouch);
		}
		if (bTouch)
		{
			clWDUtil.AttacheDetacheEvent(true, document, "touchcancel", this.m_fMouseUp, bTouch);
		}
	}

	// Memorise pour le premier deplacement
	this.m_nDateMouseDown = (new Date()).getTime();

	return true;
};

// Appel lors du deplacement de la souris
WDDrag.prototype.OnMouseMove = function OnMouseMove(oEvent)
{
	// Si le bouton de la souris n'est plus enfonce (cas bizarre)
	// Annule le deplacement
	if (!clWDUtil.bValideBouton(oEvent))
	{
		this.OnMouseUp(oEvent);
		return;
	}

	// Si on demande un delai avant de lancer le deplacement
	var nMaintenant = (new Date()).getTime();
	if (this.m_nDelaiAvantDeplacement > 0)
	{
		if (this.m_nDateMouseDown)
		{
			if ((nMaintenant - this.m_nDateMouseDown) < this.m_nDelaiAvantDeplacement)
			{
				return;
			}
			else
			{
				delete this.m_nDateMouseDown;
			}
		}
	}

	// Si on demande un delai entre deux deplacement
	if (this.m_nDelaiEntreDeplacement > 0)
	{
		if (this.m_nDateMouseMove && ((nMaintenant - this.m_nDateMouseMove) < this.m_nDelaiEntreDeplacement))
		{
			return;
		}
		// On memorise pour le du rafraichissement
		this.m_nDateMouseMove = nMaintenant;
	}

	// Appel de la methode surchargee
	this._vOnMouseMove.apply(this, arguments);
};

// Appel lors du deplacement de la souris
WDDrag.prototype._vOnMouseMove = function _vOnMouseMove(oEvent)
{
	// Rien
};

// Appel lors du relachement de la souris
// Restaure les fonctions hookees
WDDrag.prototype.OnMouseUp = function OnMouseUp(oEvent)
{
	// Appel de la methode surchargee
	this._vOnMouseUp.apply(this, arguments);
};

// Appel lors du relachement de la souris
// Restaure les fonctions hookees
WDDrag.prototype._vOnMouseUp = function _vOnMouseUp(oEvent)
{
	// Restaure les hook du document
	if (this.m_bHookPoses)
	{
		if (bTouch)
		{
			clWDUtil.AttacheDetacheEvent(false, document, "touchcancel", this.m_fMouseUp, bTouch);
		}
		if (bIE)//bIEQuirks ?
		{
			clWDUtil.AttacheDetacheEvent(false, document, "selectstart", this.m_fSelectStart, bTouch);
		}
		clWDUtil.AttacheDetacheEvent(false, document, this.ms_sMouseUp, this.m_fMouseUp, bTouch);
		clWDUtil.AttacheDetacheEvent(false, document, this.ms_sMouseMove, this.m_fMouseMove, bTouch);
		delete this.m_bHookPoses;
	}

	// Vire la limitation du rafriachissement
	if (this.m_nDateMouseMove !== undefined)
	{
		delete this.m_nDateMouseMove;
	}
	if (this.m_nDateMouseDown !== undefined)
	{
		delete this.m_nDateMouseDown;
	}

	// Vire la position souris
	delete this.m_nPosY;
	delete this.m_nPosX;
};

// Gestion du drag+drop HTML 5 (+ drag+drop natif)
// Ne fait pas de gestion de sources/cibles multiples
function WDDnDNatif(nSource, nCible, oElement, nOperationDefaut)
{
	// Si on est pas dans l'init d'un protoype
	if (nSource !== undefined)
	{
		// Appel le constructeur de la classe de base
		WDDragBase.prototype.constructor.apply(this, [true]);

		// Cree les fonctions de rappel
		var oThis = this;
		if (0 < nSource)
		{
			this.m_nSource = nSource;
//			this.m_fDragStart = function(oEvent) { oThis._OnDnDEvenement(oEvent || event, oThis._OnDragStart); return oThis._bStopPropagation(oEvent); };
			this.m_fDragStart = function(oEvent) { oThis._OnDnDEvenement(oEvent || event, oThis._OnDragStart); };
			this.m_fDragEnd = function(oEvent) { oThis._OnDnDEvenement(oEvent || event, oThis._OnDragEnd); return oThis._bStopPropagation(oEvent); };
		}
		if (0 < nCible)
		{
			this.m_nCible = nCible;
			this.m_fDragEnter = function(oEvent) { oThis._OnDnDEvenement(oEvent || event, oThis._OnDragEnter); return oThis._bStopPropagation(oEvent); };
			this.m_fDragOver = function(oEvent) { oThis._OnDnDEvenement(oEvent || event, oThis._OnDragOver); return oThis._bStopPropagation(oEvent); };
			this.m_fDragExit = function(oEvent) { oThis._OnDnDEvenement(oEvent || event, oThis._OnDragExit); return oThis._bStopPropagation(oEvent); };
			this.m_fDrop = function(oEvent) { oThis._OnDnDEvenement(oEvent || event, oThis._OnDrop); return oThis._bStopPropagation(oEvent); };
		}
		// Par defaut accepte la copie
		this.m_nOperationDefaut = ((nOperationDefaut !== undefined) ? nOperationDefaut : this.ms_nOperationCopie);

		// Si on un element HTML : liaison
		if (oElement)
		{
			this._InitElement(oElement);
		}
	}
};

// Declare l'heritage
WDDnDNatif.prototype = new WDDragBase();
// Surcharge le constructeur qui a ete efface
WDDnDNatif.prototype.constructor = WDDnDNatif;

// Valeur de l'operation
// ms_nOperationDejaFait : pour la version par programmation qui indique que c'est deja fait par DNDAccepte et DNDCurseur
WDDnDNatif.prototype.ms_nOperationDejaFait = -1;
WDDnDNatif.prototype.ms_nOperationSans = 0;
WDDnDNatif.prototype.ms_nOperationCopie = 1;
WDDnDNatif.prototype.ms_nOperationDeplacement = 2;
WDDnDNatif.prototype.ms_nOperationLien = 4;
// Selon la combinaison de this.ms_nOperationXxx
WDDnDNatif.prototype.ms_tabEffectAllowed = ["none", "copy", "move", "copyMove", "link", "copyLink", "linkMove", "all"];
// copy > move > link
WDDnDNatif.prototype.ms_tabDropEffect = ["none", "copy", "move", "copy", "link", "copy", "Move", "copy"];

// Indice des operation (correspond aux parametres de DnDEvenements)
WDDnDNatif.prototype.ms_nDnDDebutGlisser = 5;
WDDnDNatif.prototype.ms_nDnDEntreeChamp = 2;
WDDnDNatif.prototype.ms_nDnDFinGlisser = 6;
WDDnDNatif.prototype.ms_nDnDLacher = 4;
WDDnDNatif.prototype.ms_nDnDSortieChamp = 3;
WDDnDNatif.prototype.ms_nDnDSurvol = 1;
// Type generaux de donnees
WDDnDNatif.prototype.ms_tabTypes = ["text/plain", "text/uri-list"];

// Association a un element HTML
WDDnDNatif.prototype._InitElement = function _InitElement(oElement)
{
	// Si on est source
	if (0 < this.m_nSource)
	{
		// Ajoute l'attribut draggable : comportement different selon les elements
		switch (clWDUtil.sGetTagName(oElement))
		{
		case "input":
			// Rien sur les "input" (bloque la saisie selon les navigateurs + le champ le gere nativement)
			break;
		case "select":
			// L'applique sur les options
			this._InitElementTab(oElement.getElementsByTagName("option"));
			break;
		default:
			oElement.setAttribute("draggable", "true", 0);
			break;
		}
		HookOnXXX(oElement, 'ondragstart', 'dragstart', this.m_fDragStart);
		HookOnXXX(oElement, 'ondragend', 'dragend', this.m_fDragEnd);
	}
	// Si on est cible
	if (0 < this.m_nCible)
	{
		HookOnXXX(oElement, 'ondragenter', 'dragenter', this.m_fDragEnter);
		HookOnXXX(oElement, 'ondragover', 'dragover', this.m_fDragOver);
		HookOnXXX(oElement, 'ondragexit', 'dragexit', this.m_fDragExit);
		HookOnXXX(oElement, 'ondrop', 'drop', this.m_fDrop);
	}
};
WDDnDNatif.prototype._InitElementTab = function _InitElementTab(tabElement)
{
	var i;
	var nLimiteI = tabElement.length;
	for (i = 0; i < nLimiteI; i++)
	{
		this._InitElement(tabElement[i]);
	}
};

// Liberation
WDDnDNatif.prototype._LibereElement = function _LibereElement(oElement)
{
	// Si on est cible
	if (0 < this.m_nCible)
	{
		UnhookOnXXX(oElement, 'ondrop', 'drop', this.m_fDrop);
		UnhookOnXXX(oElement, 'ondragexit', 'dragexit', this.m_fDragExit);
		UnhookOnXXX(oElement, 'ondragover', 'dragover', this.m_fDragOver);
		UnhookOnXXX(oElement, 'ondragenter', 'dragenter', this.m_fDragEnter);
	}
	// Si on est source
	if (0 < this.m_nSource)
	{
		UnhookOnXXX(oElement, 'ondragend', 'dragend', this.m_fDragEnd);
		UnhookOnXXX(oElement, 'ondragstart', 'dragstart', this.m_fDragStart);
		// Supprime l'attribut draggable : comportement different selon les elements
		switch (clWDUtil.sGetTagName(oElement))
		{
		case "input":
			// Rien sur les "input" (bloque la saisie selon les navigateurs + le champ le gere nativement)
			break;
		case "select":
			// L'applique sur les options
			this._LibereElementTab(oElement.getElementsByTagName("option"));
			break;
		default:
			oElement.removeAttribute("draggable", 0);
			break;
		}
	}
};
WDDnDNatif.prototype._LibereElementTab = function _LibereElementTab(tabElement)
{
	var i;
	var nLimiteI = tabElement.length;
	for (i = 0; i < nLimiteI; i++)
	{
		this._LibereElement(tabElement[i]);
	}
};

//////////////////////////////////////////////////////////////////////////
// Gestion des evenements

// Encapsulation des evenements
WDDnDNatif.prototype._OnDnDEvenement = function _OnDnDEvenement(oEvent, fFonction)
{
	try
	{
		// Pas besoin de pile, normalement il n'y a qu'un seul evenement possible a la fois (sauf en cas de breakpoint ou les evenements s'empilent)
		this.m_oEvent = oEvent;
		this._vSetDnDActif();

		// Appel du traitement de l'evenement
		fFonction.apply(this, []);
	}
	catch (e)
	{
		throw e;
	}
	finally
	{
		// Libere les variables
		this._vClearDnDActif();
		this.m_oEvent = null;
		delete this.m_oEvent;
	}
};
// Acces au donnes de l'evenement courant
WDDnDNatif.prototype._oGetEvent = function _oGetEvent()
{
	return this.m_oEvent;
};
WDDnDNatif.prototype._oGetEventData = function _oGetEventData()
{
	return this.m_oEvent.dataTransfer;
};

// Acces au donnes de l'evenement courant : type : verifie si un type est dans les donnees
WDDnDNatif.prototype._bVerifieEventDataType = function _bVerifieEventDataType(sTypeDonnees)
{
	// Pas de membre types si le navigateur ne gere pas la fonctionnalite
	var oDonnees = this._oGetEventData();
	var tabTypes = oDonnees.types;
	if (tabTypes)
	{
		return clWDUtil.bDansTableau(tabTypes, sTypeDonnees);
	}
	else if (bIE)
	{
		var sDonnees = oDonnees.getData(sTypeDonnees);
		return sDonnees && (0 < sDonnees.length);
	}
};
WDDnDNatif.prototype._oGetEventDataSelonType = function _oGetEventDataSelonType(sTypeDonnees)
{
	if (this._bVerifieEventDataType(sTypeDonnees))
	{
		return this._oGetEventData().getData(sTypeDonnees);
	}
	else
	{
		return "";
	}
};
WDDnDNatif.prototype._SetEventDataSelonType = function _SetEventDataSelonType(sTypeDonnees, sDonnees)
{
	this._oGetEventData().setData(sTypeDonnees, sDonnees);
};

WDDnDNatif.prototype._sDataTypeAvecCorrectionNombre = function _sDataTypeAvecCorrectionNombre(sTypeDonnees)
{
	// CF_TEXT => text/plain
	if (sTypeDonnees == 1)
	{
		return this.ms_tabTypes[0];
	}
	return sTypeDonnees;
};


if (bIE)
{
	// Corrige le type de donnees pour IE
	WDDnDNatif.prototype.ms_tabTypesIE = ["Text", "URL"];
	WDDnDNatif.prototype._sDataTypeAvecCorrection = function _sDataTypeAvecCorrection(sTypeDonnees)
	{
		// Corrige pour CF_TEXT
		sTypeDonnees = this._sDataTypeAvecCorrectionNombre(sTypeDonnees);
		// Et recherche la valeur a convertir
		var nType = clWDUtil.nDansTableau(this.ms_tabTypes, sTypeDonnees);
		if (clWDUtil.nElementInconnu != nType)
		{
			return this.ms_tabTypesIE[nType];
		}
		return sTypeDonnees;
	};
}
else
{
	WDDnDNatif.prototype._sDataTypeAvecCorrection = WDDnDNatif.prototype._sDataTypeAvecCorrectionNombre;
}
WDDnDNatif.prototype._bVerifieEventDataTypeAvecCorrection = function _bVerifieEventDataTypeAvecCorrection(sTypeDonnees)
{
	return this._bVerifieEventDataType(this._sDataTypeAvecCorrection(sTypeDonnees));
};
WDDnDNatif.prototype._oGetEventDataSelonTypeAvecCorrection = function _oGetEventDataSelonTypeAvecCorrection(sTypeDonnees)
{
	return this._oGetEventDataSelonType(this._sDataTypeAvecCorrection(sTypeDonnees));
};
WDDnDNatif.prototype._SetEventDataSelonTypeAvecCorrection = function _SetEventDataSelonTypeAvecCorrection(sTypeDonnees, sDonnees)
{
	this._SetEventDataSelonType(this._sDataTypeAvecCorrection(sTypeDonnees), sDonnees);
};

WDDnDNatif.prototype._vSetDnDActif = clWDUtil.m_pfVide;
WDDnDNatif.prototype._vClearDnDActif = clWDUtil.m_pfVide;

//////////////////////////////////////////////////////////////////////////
// Evenements

// Debut de drag/drop
WDDnDNatif.prototype._OnDragStart = function _OnDragStart()
{
	// Se memorise comme source du DnD
	WDDnDNatif.prototype.ms_oDnDSource = this;

	this._oGetEventData().effectAllowed = "all";

	// Ecrit la/les valeurs
	this._vSetDonneesDnD();
};
// Fin du drag/drop pour la source
WDDnDNatif.prototype._OnDragEnd = function _OnDragEnd()
{
	try
	{
		// Notifie de la fin
		this._vOnDragEnd();
	}
	catch (e)
	{
		throw e;
	}
	finally
	{
		// Se supprime comme source du DnD (le test est normalement inutile)
		if (WDDnDNatif.prototype.ms_oDnDSource == this)
		{
			WDDnDNatif.prototype.ms_oDnDSource = null;
			delete WDDnDNatif.prototype.ms_oDnDSource;
		}
	}
};

// Entree et survol : dragenter/dragover
WDDnDNatif.prototype._OnDragEnter = function _OnDragEnter()
{
	this._OnDragSurvol(this.ms_nDnDEntreeChamp);
};
WDDnDNatif.prototype._OnDragOver = function _OnDragOver()
{
	this._OnDragSurvol(this.ms_nDnDSurvol);
};
WDDnDNatif.prototype._OnDragSurvol = function _OnDragSurvol(nDnDOperation)
{
	// Se memorise comme cible du DnD (normalement inutile dans le cas dragover)
	WDDnDNatif.prototype.ms_oDnDCible = this;

	// Valide si le format est acceptable
	var nOperation = this._vnGetOperationSurDrop(nDnDOperation);

	if (nOperation != this.ms_nOperationSans)
	{
		nOperation = this._vnOnDragSurvol(nDnDOperation, nOperation);
		if (nOperation != this.ms_nOperationDejaFait)
		{
			this._oGetEventData().effectAllowed = this.ms_tabEffectAllowed[nOperation];
			// Si une operation est permise : appel de la methode virtuelle
			if ((nOperation != this.ms_nOperationSans) && !bIE)
			{
				this._oGetEventData().dropEffect = this.ms_tabDropEffect[nOperation];
			}
		}
	}
};
// Fin de survol : dragexit
WDDnDNatif.prototype._OnDragExit = function _OnDragExit()
{
	try
	{
		// Si une operation est permise : appel de la methode virtuelle
		if (this._vnGetOperationSurDrop(this.ms_nDnDSortieChamp) != this.ms_nOperationSans)
		{
			this._vOnDragExit();
		}
	}
	catch (e)
	{
		throw e;
	}
	finally
	{
		// Se supprime comme cible du DnD (le test est normalement inutile)
		if (WDDnDNatif.prototype.ms_oDnDCible == this)
		{
			WDDnDNatif.prototype.ms_oDnDCible = null;
			delete WDDnDNatif.prototype.ms_oDnDCible;
		}
	}
};
// Lacher : drop
WDDnDNatif.prototype._OnDrop = function _OnDrop()
{
	try
	{
		// Si une operation est permise : appel de la methode virtuelle
		if (this._vnGetOperationSurDrop(this.ms_nDnDLacher) != this.ms_nOperationSans)
		{
			this._vOnDrop();
		}
	}
	catch (e)
	{
		throw e;
	}
	finally
	{
		// Se supprime comme cible du DnD (le test est normalement inutile)
		if (WDDnDNatif.prototype.ms_oDnDCible == this)
		{
			WDDnDNatif.prototype.ms_oDnDCible = null;
			delete WDDnDNatif.prototype.ms_oDnDCible;
		}
	}
};

//////////////////////////////////////////////////////////////////////////
// Traitement des evenements

// Ecrit la/les valeurs : par defaut pas de donnees
WDDnDNatif.prototype._vSetDonneesDnD = clWDUtil.m_pfVide;
// Fin du DnD (pour l'appelant) : par defaut rien en fin
WDDnDNatif.prototype._vOnDragEnd = clWDUtil.m_pfVide;
// Indique les operations sur le drop
WDDnDNatif.prototype._vnGetOperationSurDrop = function _vnGetOperationSurDrop(nDnDOperation)
{
	return this.m_nOperationDefaut;
};
// Indique l'operation par defaut pour le drop effet
WDDnDNatif.prototype._vnOnDragSurvol = function _vnOnDragSurvol(nDnDOperation, nOperation)
{
	// Si on arrive ici c'est que _vnGetOperationSurDrop a valider le contenu du drop
	return nOperation;
};
WDDnDNatif.prototype._vOnDragExit = clWDUtil.m_pfVide;
// Lacher sur l'element
WDDnDNatif.prototype._vOnDrop = clWDUtil.m_pfVide;

// Gestion du drag+drop HTML 5 (+ drag+drop natif) sur un champ
// Ne fait pas de gestion de sources/cibles multiples
function WDDnDNatifChamp(sAliasChamp, nSource, nCible, oElement, tabFonctionsGet, tabFonctionsSet)
{
	if (sAliasChamp !== undefined)
	{
		// Appel le constructeur de la classe de base
		// Source/cible si on a une fonction
		// Conserve l'operation par defaut (copie)
		WDDnDNatif.prototype.constructor.apply(this, [nSource, nCible, oElement]);

		this.m_sAliasChamp = sAliasChamp;
		// Memorise les fonctions de get
		this.m_tabFonctionsGet = tabFonctionsGet;
		this.m_tabFonctionsSet = tabFonctionsSet;

		// Tableau des appels de DnDEvenement
		this.m_tabDnDEvenement = [];
	}
};

// Declare l'heritage
WDDnDNatifChamp.prototype = new WDDnDNatif();
// Surcharge le constructeur qui a ete efface
WDDnDNatifChamp.prototype.constructor = WDDnDNatifChamp;

// Operations en WL
WDDnDNatifChamp.prototype.ms_nDnDInterdit = 0;
WDDnDNatifChamp.prototype.ms_nDnDCopier	= 1;
WDDnDNatifChamp.prototype.ms_nDnDDeplacer = 2;
WDDnDNatifChamp.prototype.ms_nDnDDefaut = 3;
// C'est un tableau construit comme un objet pour avoir les membres nommees simplement
// copy > move > link
WDDnDNatifChamp.prototype.ms_tabEffectAllowedToWL =
{
	"none" : WDDnDNatifChamp.prototype.ms_nDnDInterdit,
	"copy" : WDDnDNatifChamp.prototype.ms_nDnDCopier,
	"move" : WDDnDNatifChamp.prototype.ms_nDnDDeplacer,
	"copyMove" : WDDnDNatifChamp.prototype.ms_nDnDCopier,
	"link": WDDnDNatifChamp.prototype.ms_nDnDInterdit,		// N'existe pas en WL
	"copyLink" : WDDnDNatifChamp.prototype.ms_nDnDCopier,
	"linkMove" : WDDnDNatifChamp.prototype.ms_nDnDDeplacer,
	"all" : WDDnDNatifChamp.prototype.ms_nDnDCopier
};
// Tableau des DnD activee
WDDnDNatifChamp.prototype.ms_tabDnDNatifChamp = [];

WDDnDNatifChamp.prototype.s_DeclareChamp = function s_DeclareChamp(sAliasChamp, sAliasZR, nSource, nCible, oElement, tabFonctionsGet, tabFonctionsSet)
{
	if ((0 < nSource) || (0 < nCible))
	{
		WDDnDNatifChamp.prototype.ms_tabDnDNatifChamp[sAliasChamp] = new WDDnDNatifChamp(sAliasChamp, nSource, nCible, oElement, tabFonctionsGet, tabFonctionsSet);
	}
};

// Pour le DnD programme
WDDnDNatifChamp.prototype.pfGetDnDProgramme = function pfGetDnDProgramme(nDnDFonction)
{
	// Cible si < ms_nDnDDebutGlisser
	var nDnD = (nDnDFonction < this.ms_nDnDDebutGlisser) ? this.m_nCible : this.m_nSource;
	// 0 = Sans, 1 = Automatique, 2 = Programme
	return (2 == nDnD) ? this.m_tabDnDEvenement[nDnDFonction] : null;
};

WDDnDNatifChamp.prototype.__oGetVariable = function __oGetVariable(nVariable)
{
	var oEvent = this._oGetEvent();
	switch (nVariable)
	{
	case 0:
		// _DND.Action
		return this.ms_tabEffectAllowedToWL[this._oGetEventData().effectAllowed];
	case 1:
		// _DND.ChampCible
		return this.__sGetAliasChamp(this.ms_oDnDCible);
	case 2:
		// _DND.ChampSource
		return this.__sGetAliasChamp(this.ms_oDnDSource);
	case 3:
		// _DND.CtrlEnfonce
		return oEvent.ctrlKey;
	case 4:
		// _DND.FenSource
		// Pour avoir l'element il faut forcement etre dans la meme page
		return this.ms_oDnDSource ? document.forms[0].name : "";
	case 5:
		// _DND.SourisPosX
		// Code copie de SourisPosX
		return bIE ? oEvent.offsetX : (window.pageXOffset + this._nGetPosXEvent(oEvent) - _JCCP(oEvent.target.offsetLeft, oEvent.target, true, true));
	case 6:
		// _DND.SourisPosY
		// Code copie de SourisPosY
		return bIE ? oEvent.offsetY : (window.pageYOffset + this._nGetPosYEvent(oEvent) - _JCCP(oEvent.target.offsetTop, oEvent.target, false, true));
	}
};

// Conversion entre les valeurs internes et les valeurs WL
WDDnDNatifChamp.prototype.__SetEffectDepuisActionWL = function __SetEffectDepuisActionWL(nActionWL, bDropEffect)
{
	var nOperation;
	switch (nActionWL)
	{
	default:
	case this.ms_nDnDInterdit:
		nOperation = this.ms_nOperationSans;
		break;
	case this.ms_nDnDCopier:
		nOperation = this.ms_nOperationCopie;
		break;
	case this.ms_nDnDDeplacer:
		nOperation = this.ms_nOperationDeplacement;
		break;
	case this.ms_nDnDDefaut:
		nOperation = this.m_nOperationDefaut;
		break;
	}
	if (bDropEffect)
	{
		if (!bIE)
		{
			this._oGetEventData().dropEffect = this.ms_tabDropEffect[nOperation];
		}
	}
	else
	{
		this._oGetEventData().effectAllowed = this.ms_tabEffectAllowed[nOperation];
	}
};

WDDnDNatifChamp.prototype.__sGetAliasChamp = function __sGetAliasChamp(oDnDChamp)
{
	return (oDnDChamp ? oDnDChamp.m_sAliasChamp : "");
};

WDDnDNatifChamp.prototype._vSetDnDActif = function _vSetDnDActif()
{
	WDDnDNatifChamp.prototype.ms_oDnDActif = this;
};
WDDnDNatifChamp.prototype._vClearDnDActif = function _vClearDnDActif()
{
	WDDnDNatifChamp.prototype.ms_oDnDActif = null;
	delete WDDnDNatifChamp.prototype.ms_oDnDActif;
};

// Ecrit la/les valeurs : lit le champs
WDDnDNatifChamp.prototype._vSetDonneesDnD = function _vSetDonneesDnD()
{
	// Appel de la methode de la classe de base
	WDDnDNatif.prototype._vSetDonneesDnD.apply(this, arguments);

	// Si on est en DnD programme
	var pfDnDProgramme = this.pfGetDnDProgramme(this.ms_nDnDDebutGlisser);
	if (pfDnDProgramme)
	{
		pfDnDProgramme();
	}
	else
	{
		// Donne des donnees pour les types sur lequel on a une operation de get
		var tabFonctionsGet = this.m_tabFonctionsGet;
		var i;
		var nLimiteI = tabFonctionsGet.length;
		for (i = 0; i < nLimiteI; i++)
		{
			if (tabFonctionsGet[i])
			{
				this._SetEventDataSelonTypeAvecCorrection(this.ms_tabTypes[i], tabFonctionsGet[i]());
			}
		}
	}
};

// Fin du DnD (pour l'appelant) : traite le cas deplacement
WDDnDNatifChamp.prototype._vOnDragEnd = function _vOnDragEnd()
{
	// Appel de la methode de la classe de base
	WDDnDNatif.prototype._vOnDragEnd.apply(this, arguments);

	// Si on est en DnD programme
	var pfDnDProgramme = this.pfGetDnDProgramme(this.ms_nDnDFinGlisser);
	if (pfDnDProgramme)
	{
		pfDnDProgramme();
	}
	else
	{
		// Traite le deplacement des donnees pour les types sur lequel on a une operation de set
		if (this._oGetEventData().dropEffect == this.ms_tabEffectAllowed[this.ms_nOperationDeplacement])
		{
			// Interdit sur les listes car c'est ridicule de vider le texte de l'element
			if (!clWDUtil.bBaliseEstTag(clWDUtil._oGetOriginalTarget(this._oGetEvent()), "option"))
			{
				var tabFonctionsSet = this.m_tabFonctionsSet;
				var i;
				var nLimiteI = tabFonctionsSet.length;
				for (i = 0; i < nLimiteI; i++)
				{
					if (tabFonctionsSet[i])
					{
						tabFonctionsSet[i]("");
					}
				}
			}
		}
	}
};

// Operation de mouvement de la sourie
WDDnDNatifChamp.prototype._vnGetOperationSurDrop = function _vnGetOperationSurDrop(nDnDOperation)
{
	// Si on est en DnD programme
	var pfDnDProgramme = this.pfGetDnDProgramme(nDnDOperation);
	if (pfDnDProgramme)
	{
		// Le traitement lui meme doit faire un DnDAccepte
		return this.ms_nOperationCopie + this.ms_nOperationDeplacement + this.ms_nOperationLien;
	}
	else
	{
		// Verifie que l'on a bien des donnees sur un des types pour lequel on a une operation de set
		var tabFonctionsSet = this.m_tabFonctionsSet;
		var i;
		var nLimiteI = tabFonctionsSet.length;
		for (i = 0; i < nLimiteI; i++)
		{
			if (tabFonctionsSet[i] && this._bVerifieEventDataTypeAvecCorrection(this.ms_tabTypes[i]))
			{
				// Utilise l'operation par defaut definie
				return WDDnDNatif.prototype._vnGetOperationSurDrop.apply(this, arguments);
			}
		}

		// Navigateur incompatible ou donnees inavlides
		return this.ms_nOperationSans;
	}
};

// Indique l'operation par defaut pour le drop effet
WDDnDNatifChamp.prototype._vnOnDragSurvol = function _vnOnDragSurvol(nDnDOperation, nOperation)
{
	// Si on est en DnD programme
	var pfDnDProgramme = this.pfGetDnDProgramme(nDnDOperation);
	if (pfDnDProgramme)
	{
		pfDnDProgramme();
		return this.ms_nOperationDejaFait;
	}
	else
	{
		// Utilise l'operation par defaut definie
		return WDDnDNatif.prototype._vnOnDragSurvol.apply(this, arguments);
	}
};

// Indique que l'on sort du survol
WDDnDNatifChamp.prototype._vOnDragExit = function _vOnDragExit()
{
	var pfDnDProgramme = this.pfGetDnDProgramme(this.ms_nDnDSortieChamp);
	if (pfDnDProgramme)
	{
		pfDnDProgramme();
	}

	// Appel de la methode de la classe de base
	WDDnDNatif.prototype._vOnDragExit.apply(this, arguments);
};

// Lacher sur l'element
WDDnDNatifChamp.prototype._vOnDrop = function _vOnDrop()
{
	// Appel de la methode de la classe de base
	WDDnDNatif.prototype._vOnDrop.apply(this, arguments);

	var pfDnDProgramme = this.pfGetDnDProgramme(this.ms_nDnDLacher);
	if (pfDnDProgramme)
	{
		pfDnDProgramme();
	}
	else
	{
		// Lit les donnees pour les types sur lequel on a une operation de get
		var tabFonctionsSet = this.m_tabFonctionsSet;
		var i;
		var nLimiteI = tabFonctionsSet.length;
		for (i = 0; i < nLimiteI; i++)
		{
			if (tabFonctionsSet[i])
			{
				var sDonnees = this._oGetEventDataSelonTypeAvecCorrection(this.ms_tabTypes[i]);
				if (0 < sDonnees.length)
				{
					tabFonctionsSet[i](sDonnees);
				}
			}
		}
	}
};

//////////////////////////////////////////////////////////////////////////
// Interface pour le WL

WDDnDNatifChamp.prototype.s_DnDEvenement = function s_DnDEvenement(fProcedure, sAliasChamp, nEvenement)
{
	WDDnDNatifChamp.prototype.ms_tabDnDNatifChamp[sAliasChamp].m_tabDnDEvenement[nEvenement] = fProcedure;
};

WDDnDNatifChamp.prototype.s_DnDAccepte = function s_DnDAccepte(nActionWL)
{
	// Sans blindage : erreur JS hors d'un DnD
	// DnDAccepte force dropEffect et effectAllowed car sinon il faut appeler DnDCurseur explictement
	WDDnDNatifChamp.prototype.ms_oDnDActif.__SetEffectDepuisActionWL(nActionWL, false);
	WDDnDNatifChamp.prototype.s_DnDCurseur(nActionWL);
};

WDDnDNatifChamp.prototype.s_DnDCurseur = function s_DnDCurseur(nActionWL)
{
	// Sans blindage : erreur JS hors d'un DnD
	WDDnDNatifChamp.prototype.ms_oDnDActif.__SetEffectDepuisActionWL(nActionWL, true);
};

WDDnDNatifChamp.prototype.s_DnDDonne = function s_DnDDonne(sTypeDonnees, sDonnees)
{
	// Sans blindage : erreur JS hors d'un DnD
	WDDnDNatifChamp.prototype.ms_oDnDActif._SetEventDataSelonTypeAvecCorrection(sTypeDonnees, sDonnees);
};

WDDnDNatifChamp.prototype.s_DnDDonneeDisponible = function s_DnDDonneeDisponible(sTypeDonnees)
{
	// Sans blindage : erreur JS hors d'un DnD
	return WDDnDNatifChamp.prototype.ms_oDnDActif._bVerifieEventDataTypeAvecCorrection(sTypeDonnees);
};

WDDnDNatifChamp.prototype.s_DnDRecupere = function s_DnDRecupere(sTypeDonnees)
{
	// Sans blindage : erreur JS hors d'un DnD
	return WDDnDNatifChamp.prototype.ms_oDnDActif._oGetEventDataSelonTypeAvecCorrection(sTypeDonnees);
};

WDDnDNatifChamp.prototype.s_oGetVariable = function s_oGetVariable(nVariable)
{
	// Sans blindage : erreur JS hors d'un DnD
	return WDDnDNatifChamp.prototype.ms_oDnDActif.__oGetVariable(nVariable);
};

// Gestion du drag+drop HTML 5 (+ drag+drop natif) de fichiers
// Ne fait pas de gestion de sources/cibles multiples
function WDDnDFichiers(bMultiFichiers, fCallbackFichiers, oElement)
{
	// Si on est pas dans l'init d'un protoype
	if (bMultiFichiers != undefined)
	{
		// Appel le constructeur de la classe de base
		// Uniquement cible
		// Et par defaut on fait un lien
		WDDnDNatif.prototype.constructor.apply(this, [false, true, oElement, this.ms_nOperationLien]);

		this.m_bMultiFichiers = bMultiFichiers;
		this.m_fCallbackFichiers = fCallbackFichiers;
	}
};

// Declare l'heritage
WDDnDFichiers.prototype = new WDDnDNatif();
// Surcharge le constructeur qui a ete efface
WDDnDFichiers.prototype.constructor = WDDnDFichiers;

// Acces aux fichiers de l'evenement courant
WDDnDFichiers.prototype._oGetEventDataFiles = function _oGetEventDataFiles()
{
	return this._oGetEventData().files;
};

// Indique les operations sur le drop
WDDnDFichiers.prototype._vnGetOperationSurDrop = function _vnGetOperationSurDrop(nDnDOperation)
{
	// Valide que le ce sont des fichiers et leur nombre
	if (nDnDOperation == this.ms_nDnDLacher)
	{
		var oFiles = this._oGetEventDataFiles();
		if (oFiles && ((1 == oFiles.length) || ((1 < oFiles.length) && this.m_bMultiFichiers)))
		{
			// Utilise l'operation par defaut definie
			return WDDnDNatif.prototype._vnGetOperationSurDrop.apply(this, arguments);
		}
	}
	else if (this._bVerifieEventDataType("Files"))
	{
		// Si on n'a pas encore les donnees (dispo uniquement sur le drop)
		// Utilise l'operation par defaut definie
		return WDDnDNatif.prototype._vnGetOperationSurDrop.apply(this, arguments);
	}

	// Navigateur incompatible ou nombre de fichiers incompatibles
	return this.ms_nOperationSans;
};

// Lacher sur l'element
WDDnDFichiers.prototype._vOnDrop = function _vOnDrop()
{
	// Appel de la methode de la classe de base
	WDDnDNatif.prototype._vOnDrop.apply(this, arguments);
	// Si on arrive ici c'est que _vnGetOperationSurDrop a valider le contenu du drop
	this.m_fCallbackFichiers(this._oGetEventDataFiles());
};
