Banner

Ultima revisión 28/01/2013

Hacer Drag & Drop en HTML5

Todos los que nos dedicamos a la programación sabemos que para habilitar la tecnología Drag & Drop en una página Web hay que usar algún Framework del tipo de jQuery o Mootools. Bueno, pues desde hace algún tiempo ya no.

La tecnología Drag & Drop se implantado de forma nativa en HTML5 y ahora, de forma sencilla y rápida, podemos disponer y dotar a nuestras páginas de este efecto tan llamativo.

Drag & Drop es una nueva API incluida en HTML5 que, como todos sabréis, sirve para crear la capacidad de arrastras y soltar un elemento de un lugar a otro. Para activar esta tecnología sólo tenemos que añadirle la propiedad draggable al elemento dónde queremos que active el efecto de arrastrar. Además, esta API incluye 7 nuevos eventos que nos permiten controlar las todas las acciones posibles del elemento.

Eventos asociados a la propiedad de Arrastrar (Drag) son:

  • onDragStar: Que se crea cuando se empieza a arrastrar el elemento.
  • onDrag: Que se produce mientras se arrastra el elemento.
  • onDragEnd: Que se genera cuando se termina de arrastrar el elemento.

Eventos asociados a los contenedores:

  • onDragEnter: Se produce cuando un elemento arrastrable se arrastra dentro de un elemento.
  • onDragLeave: Se genera cuando el elemento arrastrable sale del elemento.
  • onDragOver: Se lanza cuando un elemento se mueve dentro de un elemento.

Y un último evento asociado a la propiedad de Soltar (Drop) que es:

  • OnDrop: Se dispara cuando un objeto arrastable es soltado dentro.

Parcecen muchas cosas y puede que abrume al pincipio pero es muy simple y lo vamos a ver con un ejemplo.

Primero definiremos la funciones JavaScript que utilizaremos en los eventos onDragStart y onDrop:

<script type="text/javascript">
    function dragItem(item, event) {
        event.dataTransfer.setData('Identificador de Objeto', item.id)
    }

    function dropItem(target, event) {
        var item = event.dataTransfer.getData('Identificador de Objeto');
        target.appendChild(document.getElementById(item));
    }
</script>

'Identificador de Objeto' es un texto o nombre que identifica internamente el objeto que se está arrastrando.

El método setData, como se aprecia, necesita 2 parámetros. Un string que especifica el formato de los datos que se deben asignar y otro string que transfiere el id del objeto a transferir.

El método getData, como se aprecia, necesita 1 único parámetro que especifica el formato de los datos que se debe asignar.

Aclaraciones con respecto a Firefox:

  • En Firefox, la modificación de los datos arrastrados no se permite durante la operación de arrastre sólo al iniciar la operación de arrastre. Por eso, los métodos y clearData y setData sólo puede ser llamados en las funciones asociadas al evento onDragStart. Si intentamos usar estos métodos en otro evento provocará una excepción.
  • En Firefox el formato de datos puede ser una cadena arbitraria. Si los datos para el formato especificado ya existen, se sustituyen por el nuevo valor. Si, por el contrario, el formato de datos especificado no existe, tanto los nuevos datos como su formato se añadirán a la transferencia de datos actual.

Aclaraciones con respecto a Google Chrome y Safari:

  • En Google Chrome y Safari funciona de forma similar a la de Firefox, aunque con la diferencia de que el método clearData no tiene ningún efecto y, parece ser, que podría ser un bug de Google Chrome y Safari.
  • El método GetData sólo funciona en Google Chrome y Safari para los eventos de arrastre onDragEnter, onDragOver, onDragLeave y onDrop. Por eso, los datos arrastrados no pueden ser recuperados por el elemento de origen. Parece que es otro bug.
  • En Google Chrome y Safari el formato de datos puede ser una cadena arbitraria. Si los datos para el formato especificado ya existen, se sustituyen por el nuevo valor. Si, por el contrario, el formato de datos especificado no existe, tanto los nuevos datos como su formato se añadirán a la transferencia de datos actual.

Ahora añadimos la propiedad draggable="true" a los elementos que queremos tengan la capacidad de ser arrastables y le indicamos al navegador, con la función en JavaScript, definida antes y dentro de la propiedad onDragStart, qué elemento hemos seleccionado:

<fieldset id="origen" class="container" onDrop="dropItem(this, event)" onDragEnter="return false" onDragOver="return false">
    <legend><b>Contenedor Origen</b>: Coge y arrastra un elemento al contenedor DESTINO</legend>
    <a draggable="true" onDragStart="dragItem(this, event)" class="item" id="Item1">Item 1</a>
    <a draggable="true" onDragStart="dragItem(this, event)" class="item red" id="Item2">Item 2</a>
    <a draggable="true" onDragStart="dragItem(this, event)" class="item orange" id="Item3">Item 3</a>
</fieldset>

Ya tenemos habilitado el efecto de arrastrar pero, ¿ Qué pasa con el efecto de soltar ?. Pues bien, la propiedad de soltar la estableceremos en el contenedor dónde queremos que finelice la acción del Drag & Drop.

<fieldset id="destino" class="container" onDrop="dropItem(this, event)" onDragEnter="return false" onDragOver="return false">
    <legend><b>Contenedor DESTINO</b>: Suelta el elemento aquí</legend>
</fieldset>

Finalmente, por ser un poco "finolis", le establecemos unos estilos:

<style>
    .item               { cursor:pointer; text-decoration:none; width:50px; margin:5px; padding:5px; background-color:#283a64; color:#ffffff; font-weight:bold; }
    .red                { background-color:red; }
    .orange             { background-color:orange; color:black; }
    .container          { display:block; padding-top:6px; width:100%; height:44px; background-color:#f0f0f0; }
    .container legend   { font-size:12px; color:black; margin-right: 20px; }
</style>

Ejemplo de Drag & Drop en HTML5

Contenedor Origen: Coge y arrastra un elemento al contenedor DESTINO Item 1 Item 2 Item 3


Contenedor DESTINO: Suelta el elemento aquí