El Drag and Drop en HTML5 (JavaScript)
- Andrés Cruz
El Drag and Drop (Arrastrar y Soltar) es una característica que permite "agarrar" un objeto y arrastrarlo a una diferente localización:
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.
¿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.
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).
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.
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.
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-.
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.
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
.
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.
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...
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:
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%.
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter