//--------------------------------------------------------------------------------------------------
//         API Opera/Explorer/Navigator : drag & drop (on dit glisser/déposer en français)
// Cette API est indépendante.
// La fenêtre qui l'utilise doit :
//   - créer et positionner ses couches.
//   - les déclarer en donnant une liste de pointeurs sur les couches dans le tableau "couchesBougeables"
//     La déclaration se fait dans l'ordre, de la plus basse à la plus haute.
//   - appeler initDragDrop(dragFunction, releaseFunction, engageFunction)
//
// dragFunction est appelée à chaque mouvement d'une couche, avec l'indice de la couche dans le
//              tableau couchesBougeables. Elle peut lire/écrire dans xPosition et yPosition.
// releaseFunction est appelée à chaque relâchement d'une couche, avec le numéro de la couche comme
//                 paramètre. Cette function peut lire/écrire dans xPosition et yPosition.
// engageFunction est appelée à chaque clic sur une couche, avec le numéro de la couche comme
//                 paramètre. Cette function peut lire/écrire dans xPosition et yPosition.
//--------------------------------------------------------------------------------------------------

var dragDropVersion = 2.8;
var couchesBougeables = new Array();      // liste de pointeurs sur les couches à déplacer
var engageFunction;                       // fonction à appeler à la prise d'une couche.
var dragFunction;                         // fonction à appeler au déplacement d'une couche.
var releaseFunction;                      // fonction à appeler au relâchement d'une couche.

var selectedLayer;                        // pointeur sur la couche sélectionnée
var selectedLayerStyle;                   // pointeur sur la propriété Style de la couche sélectionnée.
var selectedLayerNum;                     // numéro de la couche sélectionnée dans couchesBougeables
var objSelected = false;                  // drapeau qui dit si une couche est en déplacement ou non. 
var offsetX, offsetY;                     // Décalage entre la souris et le coin de la couche.
var xPosition, yPosition;                 // dernières coordonnées de la couche bougée
var mouseX, mouseY;                       // dernières coordonnées de la souris
var dMouseX, dMouseY;                     // variation des coordonnées de la souris
var zIndex;                               // Mémorise l'ancien z-index de la couche en train de glisser.
var la_piece_passe_au_dessus = true;      // Avec false, on ne touche pas au z-index.

var isNav4   = (document.layers) ? true : false;
var isOpera  = (navigator.userAgent.indexOf('Opera') >= 0);
var isOpera6 = isOpera && (parseFloat(navigator.appVersion) < 7);
var isIE     = (navigator.userAgent.indexOf('MSIE') >= 0) && !isOpera;
var isNav6   = (navigator.userAgent.indexOf('Gecko') != -1);
var isW3     = (document.getElementById) ? true : false;
var unite    = (isW3 && !isOpera) ? 'px' : 0;

var scrollX = 0;      // Position de l'écran sur la page web. Dépend du navigateur, voir initDragDrop();
var scrollY = 0;

function setSelectedElem(evt) {
  if (isNav4) {
    var testObj;
    var clickX = evt.pageX;
    var clickY = evt.pageY;
    for (var i = couchesBougeables.length-1; i >= 0; i--) {
      testObj = couchesBougeables[i];
      if ((clickX >= testObj.left) && 
          (clickX <  testObj.left + testObj.clip.width) && 
          (clickY >= testObj.top) && 
          (clickY <  testObj.top + testObj.clip.height)) {
        selectedLayerStyle = selectedLayer = testObj;
        selectedLayerNum = i;
        objSelected = true;
        return;
      }
    }
  } else if (isIE) {
    var testObj, x, y;
    var clickX = window.event.x + document.body.scrollLeft;
    var clickY = window.event.y + document.body.scrollTop;
    for (var i = couchesBougeables.length-1; i >= 0; i--) {
      testObj = couchesBougeables[i];
      x = testObj.offsetLeft;
      y = testObj.offsetTop;
      if ((clickX >= x) && 
          (clickX < x + testObj.clientWidth) && 
          (clickY >= y) && 
          (clickY < y + testObj.clientHeight)) {
        selectedLayer = testObj;
        selectedLayerStyle = testObj.style;
        selectedLayerNum = i;
        objSelected = true;
        return;
      }
    }
  } else if (isNav6) {
    var testObj, testObjStyle, x, y;
    var clickX = evt.clientX + window.scrollX;
    var clickY = evt.clientY + window.scrollY;
    for (var i = couchesBougeables.length-1; i >= 0; i--) {
      testObj = couchesBougeables[i];
      testObjStyle = testObj.style;
      x = parseInt(testObjStyle.left);
      y = parseInt(testObjStyle.top);
      if ((clickX >= x) && 
          (clickX < x + testObj.offsetWidth) && 
          (clickY >= y) && 
          (clickY < y + testObj.offsetHeight)) {
        selectedLayer = testObj;
        selectedLayerStyle = testObjStyle;
        selectedLayerNum = i;
        objSelected = true;
        return;
      }
    }
  } else if (isOpera) {
    var testObj, testObjStyle, x, y;
    var clickX = evt.clientX + scrollX;
    var clickY = evt.clientY + scrollY;
    for (var i = couchesBougeables.length-1; i >= 0; i--) {
      testObj = couchesBougeables[i];
      testObjStyle = testObj.style;
      x = testObjStyle.pixelLeft;
      y = testObjStyle.pixelTop;
      if ((clickX >= x) && 
          (clickX < x + testObjStyle.pixelWidth) && 
          (clickY >= y) && 
          (clickY < y + testObjStyle.pixelHeight)) {
        selectedLayer = testObj;
        selectedLayerStyle = testObjStyle;
        selectedLayerNum = i;
        objSelected = true;
        return;
      }
    }
  }
  objSelected = false;
}

function dragIt(evt) {
  if (objSelected) {
    if (isNav4) {
      mouseX = evt.pageX;
      mouseY = evt.pageY;
    } else if (isIE) {
      mouseX = window.event.clientX + document.body.scrollLeft;
      mouseY = window.event.clientY + document.body.scrollTop;
    } else if (isW3) {
      mouseX = evt.clientX + ((isNav6) ? window.scrollX : 0);
      mouseY = evt.clientY + ((isNav6) ? window.scrollY : 0);
    }
    xPosition = mouseX - offsetX;
    yPosition = mouseY - offsetY;
    if (dragFunction) dragFunction (selectedLayerNum);
    selectedLayerStyle.left = xPosition + unite;
    selectedLayerStyle.top  = yPosition + unite;
    return false;
  } else return true;
}

function engage(evt) {
  if (isOpera && !isOpera6) {
    scrollX = document.body.scrollLeft;
    scrollY = document.body.scrollTop;
  }
  setSelectedElem(evt);
  if (objSelected) {
    if (engageFunction) engageFunction (selectedLayerNum);
    if (isNav4) {
      mouseX = evt.pageX;
      mouseY = evt.pageY;
      offsetX = mouseX - selectedLayer.left;
      offsetY = mouseY - selectedLayer.top;
    } else if (isIE) {
      mouseX = window.event.clientX + document.body.scrollLeft;
      mouseY = window.event.clientY + document.body.scrollTop;
      offsetX = mouseX - selectedLayer.offsetLeft;
      offsetY = mouseY - selectedLayer.offsetTop;
    } else if (isNav6) {
      mouseX = evt.clientX + window.scrollX;
      mouseY = evt.clientY + window.scrollY;
      offsetX = mouseX - parseInt(selectedLayerStyle.left);
      offsetY = mouseY - parseInt(selectedLayerStyle.top);
    } else if (isOpera) {
      mouseX = evt.clientX;
      mouseY = evt.clientY;
      offsetX = mouseX - selectedLayerStyle.pixelLeft;
      offsetY = mouseY - selectedLayerStyle.pixelTop;
    }
    zIndex = selectedLayerStyle.zIndex;
    if (la_piece_passe_au_dessus) selectedLayerStyle.zIndex += 1000;  // La couche sélectionnée passe au-dessus des autres.
    xPosition = mouseX - offsetX;
    yPosition = mouseY - offsetY;
    return false;
  }
  return true;
}

function release(evt) {
  if (objSelected) {
    if (releaseFunction) {
      releaseFunction (selectedLayerNum);
      selectedLayerStyle.left = xPosition + unite;
      selectedLayerStyle.top  = yPosition + unite;
    }
    selectedLayerStyle.zIndex = zIndex;                // La couche sélectionnée redescend à sa z-place.
    objSelected = false;
  }
}

function stopDragDrop () {
  if (isNav4 || isNav6) document.releaseEvents(Event.MOUSEDOWN | Event.MOUSEUP | Event.MOUSEMOVE);
  window.document.onmousedown = null;
  window.document.onmousemove = null;
  window.document.onmouseup = null;
}
//--------------------------------------------------------------------------------------------------
// Initialisation
//   dragfonc et releaseFonc sont des pointeurs sur des fonctions (donc pas de guillemets).
//   Ces fonctions seront appelées à chaque fois qu'une couche est bougée (dragFonc) ou
//   relâchée (releaseFonc), avec comme paramètre le numéro de la couche dans le tableau
//   couchesBougeables.
//   dragFunction peut récupérer et modifier la position dans (xPosition,yPosition) .
//   Passer null s'il n'y en a pas besoin.
//--------------------------------------------------------------------------------------------------
function initDragDrop(dragFonc, releaseFonc, engFunc) {
  if (isNav4 || isNav6) document.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP | Event.MOUSEMOVE);
  window.document.onmousedown = engage;
  window.document.onmousemove = dragIt;
  window.document.onmouseup = release;
  engageFunction  = engFunc;
  dragFunction    = dragFonc;
  releaseFunction = releaseFonc;
}
