/**
 * Glisser.js : faire glisser les éléments HTML positionnés de manière absolue.
 *
 * Ce module définit la fonction drag() conçue pour être appelée depuis
 * un gestionnaire d’événements onmousedown. Les événements mousemove
 * survenant ensuite déplacent l’élément indiqué. Un événement mouseup 
 * termine le déplacement de l’élément. Si l’élément est déplacé en dehors
 * de l’écran, la fenêtre ne défile pas. Cette implémentation fonctionne 
 * avec les modèles d’événements du DOM Niveau 2 et d’IE.
 * 
 * Arguments :
 *
 *   elementDeplace : l’élément qui a reçu l’événement mousedown ou un
 *     élément conteneur. Il doit être positionné de manière absolue.
 *     Ses valeurs style.left et style.top sont modifiées en fonction
 *     du glissement opéré par utilisateur.
 *
 *   evenement : l’objet Event de l’événement mousedown.
 **/
function startDrag(boundingElement, moveHandler, evenement) {

    // Enregistrer les gestionnaires qui répondent aux événements mousemove
    // et à l’événement mouseup qui vient après cet événement mousedown.
    if (document.addEventListener) {  // Modèle d’événements du DOM Niveau 2.
        // Enregistrer des gestionnaires d’événements avec capture.
        document.addEventListener("mousemove", moveHandler, true);
        document.addEventListener("mouseup", gestionnaireRelachement, true);
    }
    else if (document.attachEvent) {  // Modèle d’événements d’IE 5+.
        // Dans le modèle d’événements d’IE, les événements sont capturés
        // par un appel à setCapture() sur l’élément.
        boundingElement.setCapture();
        boundingElement.attachEvent("onmousemove", moveHandler);
        boundingElement.attachEvent("onmouseup", gestionnaireRelachement);
        // Traiter la perte de la capture de la souris comme 
        // un événement mouseup.
        boundingElement.attachEvent("onlosecapture", gestionnaireRelachement);
    }
    else {  // Modèle d’événements d’IE 4.
        // Dans IE 4, nous ne pouvons utiliser attachEvent() ou setCapture(),
        // nous fixons donc directement les gestionnaires d’événements dans
        // l’objet de document et espérons que les événements de la souris 
        // dont nous avons besoin se propageront.
        var ancienGestDeplacement = document.onmousemove; // Utilisé par gestionnaireRelachement().
        var ancienGestRelachement = document.onmouseup;
        document.onmousemove = moveHandler;
        document.onmouseup = gestionnaireRelachement;
    }

    // Puisque nous traitons l’événement, ne laisser personne d’autre le voir.
    if (evenement.stopPropagation)
        evenement.stopPropagation();          // DOM Niveau 2.
    else evenement.cancelBubble = true;       // IE.

    // Empêcher les actions par défaut.
    if (evenement.preventDefault)
        evenement.preventDefault();           // DOM Niveau 2.
    else evenement.returnValue = false;       // IE.

    /**
     * Voici le gestionnaire qui capture l’événement final mouseup qui
     * se produit à la fin de l’opération de glissement.
     **/
    function gestionnaireRelachement(e) {
        if (!e) e = window.event;  // Modèle d’événements d’IE.

        // Désenregistrer les gestionnaires d’événements avec capture.
        if (document.removeEventListener) {  // Modèle d’événements du DOM.
            document.removeEventListener("mouseup", gestionnaireRelachement, true);
            document.removeEventListener("mousemove", moveHandler, true);
        }
        else if (document.detachEvent) {     // Modèle d’événements d’IE 5+.
            boundingElement.detachEvent("onlosecapture", gestionnaireRelachement);
            boundingElement.detachEvent("onmouseup", gestionnaireRelachement);
            boundingElement.detachEvent("onmousemove", moveHandler);
            boundingElement.releaseCapture();
        }
        else {  // Modèle d’événements d’IE 4.
            // Restaurer les gestionnaires d’origine, si présents.
            document.onmouseup = ancienGestRelachement;
            document.onmousemove = ancienGestDeplacement;
        }

        // Empêcher la propagation de l’événement.
        if (e.stopPropagation) e.stopPropagation();  // DOM Niveau 2.
        else e.cancelBubble = true;                  // IE.
    }
}