El Drag and Drop en HTML5 (JavaScript)

- Andrés Cruz

El Drag and Drop en HTML5 (JavaScript)

El Drag and Drop (Arrastrar y Soltar) es una característica que permite "agarrar" un objeto y arrastrarlo a una diferente localización:

Drag and drop ejemplo básico

El Drag and Drop es uno de los grandes cambios que incorpora HTML5 es la característica de arrastrar y soltar (Drag and Drop) que puede ser aplicado a cualquier clase de elementos como contenedores (divs), textareas, párrafos, títulos, imágenes, etc.

El Drag and Drop es una herramienta poderosísima que permite llevar la interacción con el usuario a otro nivel que aprovecha sobre todo en esta "fiebre" que existe con los dispositivos móviles inteligentes como tablets o teléfonos que cuentan con una pantalla táctil que resulta en una combinación muy atractiva.

Una aplicación debe ser intuitiva, y que más intuitivo que arrastrar un "objeto" de una parte a otra.

¿En qué consiste la característica de arrastrar y soltar?

Con el Drag and Drop simplemente llevamos un elemento de A a B "arrastrándolo" de un lado a otro (no solo aplica en HTML, todas las tecnologías que lo empleen -como Android- emplean el mismo principio); aunque al momento del desarrollo puede que no nos resulte tan sencillo sobre todo porque cuenta (al menos en la API de HTML5) con una cantidad importante de métodos, eventos y propiedades que nos permiten explotar esta tecnología al máximo.

Empezando con el Drag and Drop en HTML5

En esta entrega veremos algunas definiciones claves de cómo funciona esta tecnología, sus componentes, métodos, atributos, y varios ejemplos muy prácticos que seguro te resultan interesantes.

Para crear elementos arrastrables ya no es necesario usar un plugin para llevar a cabo dicha tarea, usando HTML o mejor dicho HTML5 con JavaScript nativo podremos realizar Drag and Drop sobre todos los elementos que queremos.

Eventos del Drag and Drop (JavaScript) - Drag

Los elementos arrastrables producen tres eventos:

1.0 dragstar()

Este evento es accionado cuando empezamos el arrastre de un elemento; en específico en este evento debemos especificar que es lo que estamos arrastrando y establecer los valores correspondientes mediante el método JavaScript setData; este evento solo es invocado una vez (al seleccionar el elemento).

Además en este evento podemos definir un estilo personalizado al elemento que está siendo arrastrado.

2.0 drag()

Este evento es accionado inmediatamente después del método dragstar y ocurre cuando estamos arrastrando el elemento (tenemos el clic presionado sobre el elemento y no lo hemos soltado) y continuará mediante el "arrastrado" (drag) del mismo; el número de veces que se invoque este evento depende del navegador.

Este evento es muy útil para saber en todo momento el estado del elemento arrastrable; por ejemplo, para saber la posición exacta del elemento.

3.0 dragend()

Ocurre cuando terminamos de arrastrar el elemento y solo se ejecuta una vez; además es invocado independientemente de si el elemento es "soltado" dentro del contenedor o no.

Los atributos que colocamos en los elementos son: ondragstar, ondrag y ondragend respectivamente.

Eventos del Drag and Drop (JavaScript) - Drop

El contenedor produce cuatro eventos:

1.0 dragenter()

Ocurre cuando empezamos a mover un elemento de tipo arrastrable dentro de su contenedor, pero todavía no ha sido soltado; en otras palabras, este evento se dispara cuando el elemento "arrastrable" entra dentro de la "zona para soltar" -drop zone-.

Este evento es ideal para cambiar las reglas de estilo del contenedor al estar "dentro" del elemento arrastrable.

En este evento podemos inspeccionar la data transferida (dataTransfer) mediante el evento, esta data fue la inicializada mediante el método setData; además, podemos inspeccionar el tipo de dato devuelto.

2.0 dragleave()

Ocurre cuando un elemento arrastrable ha sido soltado/movido fuera del contenedor.

este evento es perfecto para eliminar cualquier estilo aplicado a nuestro contenedor.

3.0 dragover()

Ocurre de manera continuamente cuando un elemento arrastrable se mueve dentro de su contenedor y solo se deja de ejecutar hasta que soltemos el elemento arrastrable dentro del contenedor o salgamos del mismo; este evento es perfecto para saber cual es la posición del elemento arrastrable dentro del contenedor.

Al igual que ocurre con el evento drag, es perfecto para determinar la posición exacta del elemento arrastrable debido a que se invoca repetidamente mientras que el elemento "arrastrable" esté dentro del contenedor; el número de veces que se invoque este evento depende del navegador.

4.0 drop()

Ocurre cuando un elemento arrastrable es soltado dentro de un contenedor; en este evento debemos recolectar la información del elemento arrastrable mediante el método getData.

Los atributos que colocamos en los elementos son: ondragenter, ondragleave, ondragover y ondrop respectivamente.

Atributos del Drag and Drop en HTML5

Con sólo manejar los eventos no es suficiente para empezar a trabajar con el Drag and Drop en HTML5. Se debe añadir el atributo draggable="true" a los elementos del DOM que deseamos que sean arrastrables.

Cualquier elemento del DOM puede ser arrastrable.

Hasta ahora se ha explicado cuáles eventos ocurren en el ciclo de vida del Drag and Drop; es decir cómo interactúan los elementos arrastrables con sus contenedores; pero...

...¿Cómo enviamos los datos que están mantenidos en la operación del arrastrado?

Es decir; ¿cómo se determina que datos (que estamos arrastrando) tiene el elemento que está siendo arrastrados?; para eso utilizamos el siguiente objeto.

El objeto dataTransfer en el Drag and Drop (HTML5)

Simplemente arrastrando y soltando elementos a diestra y siniestra no es suficiente a menos que los datos que estamos moviendo se vean afectados; se utiliza este objeto para personalizar las operaciones del Drag and Drop; por ejemplo se emplea para establecer la información del evento arrastrable en el evento dragstart() y se procesa esta información en el evento drop(), veamos algunos de sus métodos más importantes:

.setData(formato, dato)

Con este método debemos insertar la información que se desea guardar desde el elemento arrastrable (drag) y debe tener un tipo definido aunque debes estar pendiente con el soporte de los navegadores:

  • Si vas a insertar texto: "text/plain".
  • Si vas a insertar una url: "text/uri-list".

Esta información se debe establecer en el evento dragstar mediante event.datatransfer.setData(type, data).

Indicamos el tipo de dato (formato) a insertar ("Data", para cualquier tipo de dato) y el dato.

.getData(formato)

Al contrario del método anterior, este nos devuelve la data recolectada establecida mediante el método setData.

Para recuperar la información se debe hacer solo en el evento drop() mediante event.dataTransfer.getData(type).

.clearData()

Limpia todos los datos establecidos por el método setData(formato, dato) mediante event.dataTransfer.clearData(type).

1.0 Ejemplo básico de Drag and Drop en HTML5 con el selector :after

Este es un ejemplo bastante básico en el cual empleamos los mínimos eventos necesarios para trabajar con el Drap and Drop.

Código completo (HTML y JavaScript)

function dragstart(caja, evento) {
    // el elemento a arrastrar
    event.dataTransfer.setData('Data', caja.id);
}

function drop(target, evento) {
    // obtenemos los datos
    var caja = event.dataTransfer.getData('Data');
    // agregamos el elemento de arrastre al contenedor
    target.appendChild(document.getElementById(caja));
}

Como vimos anteriormente, al empezar a arrastrar (se dispara el evento dragstart) indicamos la data a transferir mediante el método setData() y cuando el elemento arrastrable sea posicionado dentro del contenedor y soldado se dispara el último evento (drop) que lee la información transferida y lo copia dentro del contenedor.

Puedes ver el ejemplo completo en:

Cómo ves nos las ingeniamos para emplear el selector after para definir otro estilo variando el contenido (texto) de nuestro elemento arrastrable (caja) al estar dentro del contenedor.

2.0 Ejemplo básico de Drag and Drop en HTML5 con el selector :after y todos los eventos

Para conocer mejor cómo interactuar con todos los eventos, se presenta el mismo ejemplo presentado anteriormente pero esta vez definiremos soportados por el Drag and Drop en HTML5 y se mostrará un mensaje en la consola personalizado para cada uno:

Código JavaScript completo

function dragstart(caja, event) {
    // el elemento a arrastrar
    event.dataTransfer.setData('Data', caja.id);
}

function drag(target, event) {
    console.log("drag");
    return false;
}

function dragend(target, event) {
    console.log("dragend");
    return false;
}

function dragenter(target, event) {
    console.log("dragenter");
    return false;
}

function dragleave(target, event) {
    console.log("dragleave");
    return false;
}

function dragover(event) {
    console.log("dragover");
    event.preventDefault();
    return false;
}

function drop(target, event) {
    // obtenemos los datos
    var caja = event.dataTransfer.getData('Data');
    // agregamos el elemento de arrastre al contenedor
    target.appendChild(document.getElementById(caja));
}

La descripción vista en el ejemplo anterior se aplica a este ejemplo; además como cotación adicional, verás múltiples eventos ejecutandose en la Consola de Desarrollador según posiciones el elemento arrastrable.

Puedes ver el ejemplo completo en:

3.0 Arrastrando y soltando archivos

Seguramente has empleado más de una vez la fantástica opción que ofrece Gmail para adjuntar archivos mediante el Drag and Drop:

Drag and drop en Gmail

Con HTML es realmente sencillo incorporar esta característica de Drag and Drop de archivos hacia una aplicación web:

Código JavaScript completo

var MAX_BYTES = 102400; // 100 KB

function dragenter(event) {
    event.stopPropagation();
    event.preventDefault();
}

function dragover(event) {
    event.stopPropagation();
    event.preventDefault();
}

function drop(event) {

    console.log('drop', event);
    event.stopPropagation();
    event.preventDefault();

    var data = event.dataTransfer;
    var files = data.files;
    var file;
    var reader;

    for (var i = 0; i < files.length; i++) {
        file = files[i];
        reader = new FileReader();
        reader.onloadend = onFileLoaded;
        reader.readAsBinaryString(file);
    }
}

function onFileLoaded(event) {
    document.getElementById("resultado").value = event.currentTarget.result.substr(0, MAX_BYTES);
}

var contenedor = document.getElementById("contenedor");

contenedor.addEventListener("dragenter", dragenter, false);
contenedor.addEventListener("dragover", dragover, false);
contenedor.addEventListener("drop", drop, false);

La API de archivos en JavaScript es tema de otra entrada y puedes verlo en el enlace anterior.

Puedes ver el ejemplo completo en:

4.0 Cambiando el estilo de los elementos con los eventos del Drag and Drop

Como último ejemplo veremos cómo variar el estilo de nuestros elementos empleando cada uno de los eventos existentes:

Código JavaScript completo

function dragstart(caja, event) {
    // el elemento a arrastrar
    document.getElementById(caja.id).className = "in";
    event.dataTransfer.setData('Data', caja.id);
}

function drag(caja, event) {
    return false;
}

function dragend(caja, event) {
    document.getElementById(caja.id).className = "out";
    return false;
}

function dragenter(target, event) {
    document.getElementById("contenedor").className = "inContainer";
    return false;
}

function dragleave(target, event) {
    document.getElementById("contenedor").className = "outContainer";
    return false;
}

function dragover(event) {
    event.preventDefault();

    return false;
}

function drop(target, event) {
    // obtenemos los datos
    var caja = event.dataTransfer.getData('Data');
    document.getElementById("contenedor").className = "outContainer";
    // agregamos el elemento de arrastre al contenedor
    target.appendChild(document.getElementById(caja));
}

Puedes ver el ejemplo completo en:

Algunos enlaces de interés

Conclusión

En esta un poco extensa introducción a el Drag and Drop con HTML5 vimos como crear nuestro propio sistema de Drag and Drop y múltiples ejemplo que evidencia el uso de los distintos eventos y varios casos de prueba de lo más útiles como el que permite obtener archivos desde el computador.

Además vimos que el gran número de eventos que maneja no es un inconveniente sino todo lo contrario que permiten obtener datos en todo momento del estado tanto del elemento arrastrable como contenedor y personalizar estas acciones casi que a un 100%.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz En Udemy

Acepto recibir anuncios de interes sobre este Blog.

!Cursos desde!

10$

En Udemy

Quedan 4d 11:55!


Udemy

!Cursos desde!

4$

En Academia

Ver los cursos

!Libros desde!

1$

Ver los libros
¡Hazte afiliado en Gumroad!