Funcionalidad de arrastrar con jQueryUI

  • Por
Cómo implementar el comportamiento arrastrar a través de jQueryUI y los elementos draggable.

Las aplicaciones de escritorio permiten arrastrar y soltar y es un comportamiento que los usuarios hacen con naturalidad. Desgraciadamente, las aplicaciones web no disponen de esa posibilidad de manera nativa, por lo que se tiene que implementar a través de complejas instrucciones Javascript.

Lo cierto es que sería difícil hacer, desde cero, un comportamiento de arrastrar y soltar en Javascript, que además funcione bien en todos los navegadores. Por suerte existen diversas librerías que implementan APIs para poder hacer posible esa comunicación usuario-aplicación y que cualquiera de nosotros podría utilizar sin necesidad de grandes complicaciones.

jQueryUI dispone de un método que vamos a mostrar llamado draggable() que permite aplicar a elementos de la página la funcionalidad de arrastrar, y en este artículo del Manual de jQueryUI demostraremos hasta qué punto es sencillo utilizarlo.

Plugin draggable: sencillez por encima de todo

Con draggable() ocurre lo que muchas veces deja con la boca abierta a más de uno, pues resulta tan sencillo de utilizar que no paro de maravillarme. Para hacer que cualquier elemento de la página se pueda arrastrar a cualquier lugar de la página, simplemente tendremos que invocar dicho método sobre el elemento que queramos.

Por ejemplo tenemos cualquier tag en la página:

<h1>Probando el comportamiento draggable</h1>

Es una etiqueta normal y corriente. Ni siquiera necesita que le indiquemos estilos CSS para que el comportamiento se pueda implementar. Y ahora invocamos al método draggable de jQueryUI.

$("h1").draggable();

Con eso conseguimos que todos los encabezamientos H1 de la página se puedan arrastrar a otro lugar.

Es así de sencillo, ya tenemos un titular que se puede arrastrar y por supuesto, podríamos hacerlo con cualquier otro elemento de la página y sirve para tanto elementos block como inline.

Por ejemplo, en este código:

Este texto es de <span id="d2">prueba</span> para arrastrar

Podríamos hacer que la palabra prueba se pudiera arrastrar, con la siguiente sentencia:

$("#d2").draggable();

Puedes ver estos ejemplos en una página aparte.

Opciones disponibles para la configuración de draggable

Además del comportamiento predeterminado, el método draggable permite recibir diversas opciones para personalizar un poco más la forma en la que se implementa. Existen multitud de opciones y lógicamente unas son más útiles que otras. Veremos a continuación algunas que hemos querido destacar, pero recordar siempre que en la documentación de las librerías encontraréis muchas otras opciones.

Definir el cursor del ratón durante el arrastre:

Esto lo conseguimos con la opción "cursor". Es tan sencillo como indicar el nombre que CSS da al cursor que queremos que se utilice.

$("#arrastrame").draggable({
   cursor: 'move'   
});

Así se define que, durante el arrastre, se muestre el cursor del ratón que es como una cruz con puntas de flecha en cada uno de los extremos, que sería el adecuado para simbolizar que se está moviendo ese elemento.

Podemos ver un ejemplo en una página aparte.

Retrasar el arrastre en el tiempo:

Si lo deseamos, podemos conseguir que pase una pequeña fracción de tiempo antes que el arrastre comience. Sería como un pequeño retardo antes de que el elemento empiece a acompañar al ratón durante la acción de arrastrar y sirve para que no se produzcan arrastres no deseados cuando se hace clic sobre un elemento arrastrable.

$("#arrastrame").draggable({
   delay: 500   
});

Puedes ver un ejemplo en funcionamiento.

Distancia para comenzar a arrastrar:

Esta opción es parecida a la anterior, pero en vez de jugar con el tiempo arrastrando, tiene en cuenta el espacio en píxeles a partir del cual el elemento se moverá.

$("#arrastrame").draggable({
   distance: 50   
});

Acoplar a rejilla:

Una interesante opción que permite arrastrar, pero dentro de una rejilla. Por medio de esta opción se deben indicar dos valores en un array que servirían para especificar la anchura y altura de la rejilla donde se podría acoplar el elemento durante el arrastre.

$("#arrastrame").draggable({
   grid: [200, 50]
});

Así el arrastre se produciría siempre en una rejilla de 200 píxeles de ancho x 50 de alto. El arrastre va situando el elemento en cada uno de los espacios de esa rejilla imaginaria. Es decir, la rejilla no aparece en la página (a no ser que nosotros hagamos un fondo u otra cosa manualmente para que se muestre), sino que simplemente se utilizará para definir las posiciones válidas para situar ese elemento arrastrado.

Podemos ver un ejemplo en funcionamiento con la opción grid.

Eventos en el comportamiento de arrastrar

Claro que implementar un comportamiento de arrastrar así, sin más, no sirve de mucho, de modo que jQueryUI pone a nuestra disposición varias utilidades como los eventos, que nos permiten hacer cosas cuando el usuario realiza acciones que tienen que ver con arrastrar los elementos.

Existen 4 eventos distintos relacionados con la capacidad de arrastrar:

  • Evento create: Que se produce cuando se aplica la funcionalidad de arrastre a un elemento.
  • Evento start: Que ocurre cuando comienza un arrastre.
  • Evento drag: Se producen múltiples eventos drag cuando el ratón se está moviendo durante el proceso de arrastrar.
  • Evento stop: Que se produce cuando se suelta el elemento, es decir, en el momento que se deja de arrastrar.

El código asociado a los eventos se define tal como estamos acostumbrados a hacer en jQuery. O bien al crear el elemento:

$("#arrastrame").draggable({
   start: function(){
      $("#log").html("Se ha producido el evento start");
   }
});

O bien en cualquier otro momento con el método bind:

$("#arrastrame").bind("drag", function(evento, ui){
   $("#log").html("Se ha producido el evento darg");
});
Nota: Ten en cuenta que si utilizas bind() para definir un evento "stop" tienes que utilizar como nombre del evento "dragstop".
$("#arrastrame").bind("dragstop", function(evento, ui){
   $("#log").html("Se ha producido el evento stop");
})

Pero no fíjate que, si creas el evento al invocar a draggable(), tienes que utilizar el nombre original "stop".

$("#arrastrame").draggable({
   stop: function(){
      $("#log").html("Se ha producido el evento stop");
   }
});

Ahora vamos el código completo de un ejemplo donde se han puesto en marcha esos códigos de definición de eventos.

Por un lado tenemos dos elementos HTML:

<div id="arrastrame" class="ui-corner-all ui-state-highlight">Arrastra suavemente esta capa!</div>
<div id="log"></div>
Nota: Las clases aplicadas al primer DIV "ui-corner-all" y "ui-state-highlight" son de las existentes en el Framework CSS de jQueryUI.

Por otro lado el siguiente Javascript:

$(document).ready(function(){
   $("#arrastrame").draggable({
      start: function(evento, ui){
         $("#log").html('<span style="color: #090;">Se ha producido el evento start</span>' + "<br>" + $("#log").html());
      }
   });
   $("#arrastrame").bind("drag", function(evento, ui){
      $("#log").html('<span style="color: #009;">Se ha producido el evento darg</span>' + "<br>" + $("#log").html());
   })
   $("#arrastrame").bind("dragstop", function(evento, ui){
      $("#log").html('<span style="color: #900;">Se ha producido el evento stop</span>' + "<br>" + $("#log").html());
   })
})

El ejemplo simplemente define los tres eventos relatados anteriormente y cuando se producen va escribiendo mensajes en la capa con id="log". Comprobarás que al arrastrar se ejecuta un evento start, seguido de tantos eventos log como píxeles movamos el elemento arrastrado. Finalmente, al soltar el botón del ratón y dejar de arrastrar se produce el evento stop.

Puedes ver el ejemplo en marcha, pero ten en cuenta que tendrás que arrastrar con suavidad para que no se te llene la pantalla de mensajes por el evento drag que se ejecuta muchas veces.

Como has podido ver en el código anterior, cada función que implementa un evento recibe dos parámetros. El primero es el objeto evento del navegador y el segundo es un objeto relacionado con el elemento draggable, del que podemos obtener algunos datos.

Utilizando un nombre de parámetro llamado ui, los datos a los que accedemos serán los siguientes:

  • ui.helper: es el objeto jQuery que se ha transformado en elemento draggable.
  • ui.position: es un objeto que da la posición relativa del elemento draggable, con respecto a su contenedor. Tiene dos propiedades {top, left} para acceder a sus dos coordenadas.
  • ui.offset: es un objeto que da la posición, pero en este caso la absoluta con respecto al comienzo de la página.

Métodos adicionales de los elementos draggable

Los elementos que hemos convertido en draggable tienen una serie de métodos adicionales implementados, que podemos invocar cuando se desee. Para ello tenemos que invocar al mismo método draggable(), pero indicando entre paréntesis lo que queremos hacer.

Por ejemplo, el método "destroy" elimina la funcionalidad de arrastrar de un elemento draggable.

$("#elementodraggable").draggable("destroy");

El método "disable" aplica el estilo desactivado en el elemento draggable y momentáneamente no permite moverlo.

$("#arrastrame").draggable("disable");

Si queremos volver a activar la funcionalidad de draggable sobre un elemento que se ha desactivado previamente, tenemos que invocar al método "enable".

El método "option" permite asignar nuevos valores a las opciones del elemento draggable, una vez ha sido creado. Por ejemplo, vamos a hacer que el elemento vuelva a su posición original después de soltarlo.

$("#arrastrame").draggable("option", "revert", true);

Por último, el método "widget" nos sirve para devolver el elemento que se marcó como draggable.

elementoDraggable = $("#arrastrame").draggable("widget");
Nota: En el ejemplo dedicado a los eventos pudiste encontrar diversos enlaces que hacen uso de los métodos relatados aquí.

Conclusión

Si te habías imaginado alguna vez una interfaz web con elementos que se pudieran arrastrar pero la has descartado por ser algo muy difícil de conseguir, con jQueryUI puedes replantearte ese objetivo. Si a tu cliente se le ha ocurrido una aplicación en la que haya que arrastrar elementos, no te preocupes! ya no hace falta imaginar argumentos para quitarle la idea de la cabeza, con jQueryUI lo tienes muy fácil.

Como hemos visto, en pocos segundos puedes crear elementos que se pueden arrastrar y existen multitud de maneras de controlarlos y de realizar distintas operaciones cuando se arrastran. En el próximo artículo del Manual de jQueryUI seguiremos tratando otras cosas relacionadas con los elementos draggable y encontrarás mucha más información y ejemplos para seguir aprendiendo.

Autor

Miguel Angel Alvarez

Miguel es fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Comenzó en el mundo del desarrollo web en el año 1997, transformando su hobby en su trabajo.

Compartir

Comentarios

Raul Mendoza

29/9/2011
Position absolute
Estoy viendo que al arrastrar de coloca el atributo position absolute. Eso permitiria arrastrar por toda la pagina.... Aunque a veces podemos desear arrastrar por un espacio restringido y no sabria hacerlo si es q se puede...

franarias1986

29/5/2012
duda
Mi duda es la siguiente:

En mi caso mi objeto draggeable es una section y en la funcionalidad de cuando salte el evento drop me gustaria llamar a una funcion que va a necesitar como parametros de entrada el id de la section "draggeable" y el id de la section "drop", la forma de obtenerlos seria:

ui.draggable.id y $(this).id respectivamente?

Gracias de antemano