Arrastrar y soltar (drag and drop)

Un algoritmo muy interesante es el de arrastrar y soltar objetos. A esto lo podemos implementar capturando los eventos mouseDown, mouseMove, mouseUp.

Haremos un programa que cree un div directamente desde JavaScript y luego permita su desplazamiento con el mouse.

<!DOCTYPE html>
<html>
<head>
<title>Problema</title>
<script>
window.addEventListener('load',inicializarEventos,false);
function inicializarEventos(e)
{
  var ob=document.createElement('div');
  ob.style.left='0px';
  ob.style.top='0px';
  ob.style.width='100px';
  ob.style.height='100px';
  ob.style.background='#ff0';
  ob.style.position='relative';
  var x=document.getElementsByTagName('body');
  x[0].appendChild(ob);
  var recu1=new Recuadro(ob);
}
Recuadro=function(div)
{
    var tX=0;
    var tY=0;
    var difX=0;
    var difY=0;
    div.addEventListener('mousedown',inicioDrag,false);
    function coordenadaX(e)
    {
      return e.pageX;
    }
    function coordenadaY(e)
    {
      return e.pageY;
    }
    function inicioDrag(e) 
    {
      var eX=coordenadaX(e);
      var eY=coordenadaY(e);
      var oX=parseInt(div.style.left);
      var oY=parseInt(div.style.top);
      difX=oX-eX;
      difY=oY-eY;
      document.addEventListener('mousemove',drag,false);
      document.addEventListener('mouseup',soltar,false);
    }
    function drag(e) 
    { 
      tX=coordenadaY(e)+difY+'px';
      tY=coordenadaX(e)+difX+'px'
      div.style.top=tX; 
      div.style.left=tY; 
    }
      function soltar(e)
    { 
      document.removeEventListener('mousemove',drag,false);
      document.removeEventListener('mouseup',soltar,false);
    }
}
</script>
</head>
<body>

</body>
</html>

El código javascript es:

window.addEventListener('load',inicializarEventos,false);
function inicializarEventos(e)
{
  var ob=document.createElement('div');
  ob.style.left='0px';
  ob.style.top='0px';
  ob.style.width='100px';
  ob.style.height='100px';
  ob.style.background='#ff0';
  ob.style.position='relative';
  var x=document.getElementsByTagName('body');
  x[0].appendChild(ob);
  var recu1=new Recuadro(ob);
}


Recuadro=function(div)
{
    var tX=0;
    var tY=0;
    var difX=0;
    var difY=0;

    div.addEventListener('mousedown',inicioDrag,false);


    function coordenadaX(e)
    {
      return e.pageX;
    }

    function coordenadaY(e)
    {
      return e.pageY;
    }

    function inicioDrag(e) 
    {
      var eX=coordenadaX(e);
      var eY=coordenadaY(e);
      var oX=parseInt(div.style.left);
      var oY=parseInt(div.style.top);
      difX=oX-eX;
      difY=oY-eY;
      document.addEventListener('mousemove',drag,false);
      document.addEventListener('mouseup',soltar,false);
    }

    function drag(e) 
    { 
      tX=coordenadaY(e)+difY+'px';
      tY=coordenadaX(e)+difX+'px'
      div.style.top=tX; 
      div.style.left=tY; 
    }
  

    function soltar(e)
    { 
      document.removeEventListener('mousemove',drag,false);
      document.removeEventListener('mouseup',soltar,false);
    }
}

Lo primero que hacemos es crear un div en forma dinámica e inicializar sus propiedades:

  var ob=document.createElement('div');
  ob.style.left='0px';
  ob.style.top='0px';
  ob.style.width='100px';
  ob.style.height='100px';
  ob.style.background='#ff0';
  ob.style.position='relative';

Luego, obtenemos la referencia al body de la página y añadimos el div que acabamos de crear:

  var x=document.getElementsByTagName('body');
  x[0].appendChild(ob);

Ahora viene la parte más compleja que es el algoritmo de arrastrar y soltar, para que sea lo más genérica posible implementaremos una clase que reciba en el parémetro del constructor la referencia del div que le permitirá moverse.

La clase se llama Recuadro y recibe como referencia el div, define varios atributos para almacenar la coordenada actual del objeto y la diferencia de pixeles entre el punto donde presionamos con el mouse y el comienzo del div. También registramos el evento mouseDown para saber cuando el operador presiona el botón del mouse dentro del div:

Recuadro=function(div)
{
    var tX=0;
    var tY=0;
    var difX=0;
    var difY=0;

    div.addEventListener('mousedown',inicioDrag,false);

Luego, la función inicioDrag que se dispara cuando seleccionamos el div, obtiene la coordenada del mouse dentro de la ventana y la posición actual del div, almacena la diferencia que hay en píxeles entre estos dos valores. Además registra los eventos mouseMove y mouseUp:

    function inicioDrag(e) 
    {
      var eX=coordenadaX(e);
      var eY=coordenadaY(e);
      var oX=parseInt(div.style.left);
      var oY=parseInt(div.style.top);
      difX=oX-eX;
      difY=oY-eY;
      document.addEventListener('mousemove',drag,false);
      document.addEventListener('mouseup',soltar,false);

    }

La función drag se dispara cada vez que mueve la flecha del mouse dentro del div, siempre y cuando se tenga el botón del mouse presionado:

    function drag(e) 
    { 
      tX=coordenadaY(e)+difY+'px';
      tY=coordenadaX(e)+difX+'px'
      div.style.top=tX; 
      div.style.left=tY; 
    }

Por último, la función soltar se dispara cuando levantamos el dedo del botón del mouse, aquí removemos los eventos mouseMove y mouseUp:

    function soltar(e)
    { 
      document.removeEventListener('mousemove',drag,false);
      document.removeEventListener('mouseup',soltar,false);
    }

Para crear un objeto de la clase Recuadro la sintaxis es la siguiente:

  var recu1=new Recuadro(ob);