Preguntas y respuestas con el elemento draggable de jQueryUI

  • Por
Algunas cuestiones que nos parece útil explicar sobre el plugin draggable de jQueryUI, como modificar sus estilos, averiguar su posición o restringir su localización a un contenedor.

En el artículo anterior ya ofrecimos una bastante completa guía de uso del plugin draggable de jQueryUI, para implementar elementos que se puedan arrastrar en la página. Lo cierto es que el plugin draggable es tan completo que nos quedaron bastantes cosas por ver y para ello hemos creado un ejemplo que nos sirve para responder a varias de las cuestiones más típicas que existen sobre la funcionalidad de arrastrar elementos.

Hemos orientado este artículo como si fuera una lista de preguntas y respuestas. Primero nos plantearemos todas ellas de manera independiente y para terminar crearemos un ejemplo global que las pondrá en práctica lo aprendido.

¿Cómo puedo definir estilos CSS para los elementos draggables?

Cuando se convierte un elemento para que se pueda arrastrar, invocando el plugin draggable, jQueryUI coloca automáticamente una clase CSS llamada "ui-draggable". Podemos usar esa clase para aplicar los estilos que queramos a los elementos que se puedan arrastrar.

.ui-draggable{
   background: #feb;
}

¿Existe algún atajo para definir un estilo especial a utilizar en el momento en el que se está arrastrando un elemento?

Cuando un elemento draggable está siendo arrastrado, jQueryUI coloca de manera automática una clase CSS llamada "ui-draggable-dragging" que podríamos utilizar para definir estilos que se aplicarían sobre el elemento únicamente cuando está siendo arrastrado.

.ui-draggable-dragging{
   background: #def;
}
>

¿Existe alguna manera de colocar un elemento draggable dentro de un contenedor y que, al moverlo, si se sobrepasa el contenedor, que salgan unas barras de desplazamiento?

Cualquier elemento draggable está realmente en un contenedor, aunque sea el propio documento global. Puedes colocarlo en un contenedor simplemente anidando ese elemento arrastrable en el código HTML sobre ese contenedor. Las barras de desplazamiento cuando el elemento sale del contenedor se consiguen si en el contenedor colocas el atributo overflow: auto.

El código HTML sería:

<div id="contenedor">
   <div id="arrastrame">Arrastra esta capa!</div>
</div>

El código CSS del contenedor:

#contenedor{
   width: 500px;
   height: 300px;
   border: 1px solid #ccc;
   overflow: auto;
}

¿Puedo conseguir que el elemento arrastrable no sobrepase nunca los límites marcados por el contenedor?

La opción containment de los elementos draggable permite colocar varias posibilidades para definir qué elementos deben trabajar como contenedores. Además hace que la posición del elemento arrastrable se restrinja a las que permita el espacio disponible en el contenedor. Un valor típico sería 'parent', que indica que la etiqueta padre del elemento arrastrable debe trabajar como contenedor. Pero también admite otros valores como 'document', 'window', un selector o incluso unas coordenadas en un array como [100, 100, 300, 300], para que se restrinja al espacio definido por los dos puntos [x1, y1, x2, y2].

$("#arrastrame").draggable({
   containment: 'parent'
})

¿En un evento, como puedo obtener una referencia al objeto jQuery que está siendo arrastrado?

Puedes definir acciones a realizar cuando arrastras un elemento, por medio del evento drag u otros eventos como start o stop. Dentro del código de las funciones definidas para esos eventos puedes acceder al objeto jQuery por medio de la variable this. Pero recuerda que para invocar métodos del framework debes convertirla en un objeto jQuery con la función dólar.

$("#arrastrame").draggable({
   drag: function(event, ui){
      $(this).html("ui-state-highlight");
   }
})

Además tienes acceso a un helper, con una referencia al objeto que está siendo arrastrado por medio del segundo parámetro recibido por la función que ejecuta el evento y la propiedad helper.

$("#arrastrame").draggable({
   drag: function(event, ui){
      ui.helper.html("Estoy siendo arrastrado");
   }
})

En la función que define el evento drag has recibido ui como segundo parámetro. Por medio de ui.helper tienes el objeto jQuery que se está arrastrando. A través de ese objeto puedes invocar métodos de jQuery para hacer cosas con ese elemento, como:

ui.helper.html("Estoy siendo arrastrado");

Eso hace que se cambie el HTML del elemento arrastrado para colocar el texto "Estoy siendo arrastrado".

¿Cómo puedo saber la posición de un elemento arrastrable?

En el mencionado parámetro ui, que se recibe en la función que implementa un evento, aparte de helper, existen otras dos propiedades que te servirán para acceder a la posición de ese elemento. Ambas propiedades son objetos con atributos top y left, que podemos acceder para saber la posición del elemento.

Para obtener la posición relativa al contenedor donde está situado el elemento draggable se utiliza la propiedad "position".

$("#arrastrame").draggable({
   drag: function(event, ui){
      $("#posx").text(ui.position.left);
      $("#posy").text(ui.position.top);
   }
})

Para acceder a la posición absoluta, cuyo origen de coordenadas sería la esquina superior derecha del espacio disponible para el documento HTML, se utiliza la propiedad "offset".

$("#arrastrame").draggable({
   drag: function(event, ui){
      $("#offsetx").text(ui.offset.left);
      $("#offsety").text(ui.offset.top);
   }
})

¿Puedo hacer que el elemento arrastrable se pueda soltar en un lugar determinado y hacer cosas cuando esto ocurra?

Las posibilidades de implementar scripts con los elementos draggable son tantas como desees. Pero en el caso de arrastrar y soltar en un lugar determinado ten en cuenta que en jQueryUI dispone de un plugin adicional llamado Droppable. Por medio de los elementos droppable podemos definir contenedores donde es posible soltar elementos draggable y existe un evento específico para hacer cosas cuando se produzca la acción de soltar. Es decir, el elemento droppable ya está preparado con la funcionalidad de detectar cuándo otro elemento ha sido arrastrado y soltado encima de él.

Ejemplo que ilustra algunas preguntas y respuestas sobre el elemento draggable

Ahora vamos a ver un ejemplo donde hemos puesto en marcha los conocimientos adquiridos al responder las anteriores preguntas.

Podemos ver directamente el código fuente, pues con lo comentado anteriormente espero que el lector pueda identificar las partes del código que responden las preguntas.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd"
>
<html lang="es">
<head>
<title>Probando el comportamiento draggable de jQueryUI</title>
   <link type="text/css" href="css/blitzer/jquery-ui-1.8.16.custom.css" rel="Stylesheet" id="linkestilo" />
   <style type="text/css">
   body{
      font-family: sans-serif;
   }
   h1{
      padding: 10px;
      font-size: 30px;
   }
   #contenedor{
      width: 500px;
      height: 300px;
      border: 1px solid #ccc;
      overflow: auto;
      float: left;
   }
   #arrastrame{
      position: relative;
      top: 10px;
      left: 20px;
      width: 160px;
      padding: 7px;
      font-size: 10px;
      font-weight: bold;
      text-align: center;
   }
   #posicion{
      font-size: 12px;
      margin-left: 520px;
      line-height: 150%;
   }
   .ui-draggable{
      background: #feb;
   }
   .ui-draggable-dragging{
      background: #def;
   }
   </style>
   <script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
   <script type="text/javascript" src="js/jquery-ui-1.8.16.custom.min.js"></script>
   <script type="text/javascript">
      $(document).ready(function(){
         $("#arrastrame").draggable({
            containment: 'parent',
            drag: function(event, ui){
               $("#posx").text(ui.position.left);
               $("#posy").text(ui.position.top);
               
               $("#offsetx").text(ui.offset.left);
               $("#offsety").text(ui.offset.top);
            }
         })
      })
   </script>
</head>
<body>
   <h1 class="ui-state-default ui-corner-all">Probando la funcionalidad "draggable"</h1>
   <div id="contenedor">
      <div id="arrastrame" class="ui-corner-all ui-state-highlight">Arrastra esta capa!</div>
   </div>
   <div id="posicion">
      Coordenadas del elemento relativas al contenedor:
      <br>
      X: <span id="posx"></span>
      <br>
      Y: <span id="posy"></span>
      <br>
      <br>
      Coordenadas del elemento absolutas a la página:
      <br>
      X: <span id="offsetx"></span>
      <br>
      Y: <span id="offsety"></span>
   </div>
</body>
</html>

El ejemplo se puede ver en una página aparte.

Conclusión

Seguramente haya muchas cosas en el aire todavía sobre los elementos arrastrables que podemos crear con jQuery UI. No obstante, aquí hemos podido encontrar respuestas a lo que podrían ser las dudas más típicas.

Solo queda recomendar echar un vistazo a la documentación, donde podremos encontrar bastantes más ejemplos y una descripción completa de opciones de configuración, eventos y métodos que permiten los elementos con la funcionalidad de arrastrar en este framework.

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

Fenix014

20/10/2011
Gracias por el aporte
La verdad es que es una propiedad muy interesante. La utilizaré en alguno de mis proyectos ;) Gracias!

Missael

31/12/2011
Estilizar un dropping
Tengo una duda, existe alguna clase (como en el caso de ".ui-draggable-dragging") pero que actue sobre el elemento "Droppable", cuando un elemento "Draggable" es soltado ahi?
Gracias

Lucas

03/8/2012
Pregunta
Es posible hacer que un elemento draggable no se superponga a otro elemento draggable?

Javier

11/10/2018
como saco los datos que arrastro al contenedor :s
como saco los datos que arrastro al contenedor :s