lunes, 25 de abril de 2016

Arrastrar y soltar en la web - HTML, CSS y JavaScript - 1 de 2



Arrastrar un elemento desde un lugar y luego soltarlo en otro es algo que hacemos todo el tiempo en aplicaciones de escritorio, pero ni siquiera imaginamos hacerlo en la web. Esto no es debido a que las aplicaciones web son diferentes sino porque desarrolladores nunca contaron con una tecnología estándar disponible para ofrecer esta herramienta.
Ahora, gracias a la API Drag and Drop, introducida por la especificación HTML5, finalmente tenemos la oportunidad de crear software para la web que se comportará exactamente como las aplicaciones de escritorio que usamos desde siempre.


Nuevos eventos

Uno de los más importantes aspectos de esta API es un conjunto de siete nuevos eventos introducidos para informar sobre cada una de las situaciones involucradas en el proceso.
Algunos de estos eventos son disparados por la fuente (el elemento que es arrastrado) y otros son disparados por el destino (el elemento en el cual el elemento arrastrado será soltado). Por ejemplo, cuando el usuario realiza una operación de arrastrar y soltar, el elemento origen (el que es arrastrado) dispara estos tres eventos: 
  • dragstart Este evento es disparado en el momento en el que el arrastre comienza. Los datos asociados con el elemento origen son definidos en este momento en el sistema.
  • drag Este evento es similar al evento mousemove, excepto que será disparado durante una operación de arrastre por el elemento origen.
  • dragend Cuando la operación de arrastrar y soltar finaliza (sea la operación exitosa o no) este evento es disparado por el elemento origen.


Y estos son los eventos disparados por el elemento destino (donde el origen será soltado) durante la operación:
  • dragenter Cuando el puntero del ratón entra dentro del área ocupada por los posibles elementos destino durante una operación de arrastrar y soltar, este evento es disparado.
  • dragover Este evento es similar al evento mousemove, excepto que es disparado durante una operación de arrastre por posibles elementos destino.
  • drop Cuando el elemento origen es soltado durante una operación de arrastrar y soltar, este evento es disparado por el elemento destino.
  • dragleave Este evento es disparado cuando el ratón sale del área ocupada por un elemento durante una operación de arrastrar y soltar. Este evento es generalmente usado junto con dragenter para mostrar una ayuda visual al usuario que le permita identificar el elemento destino (donde soltar).


Antes de trabajar con esta nueva herramienta, existe un aspecto importante que debemos considerar. Los navegadores realizan acciones por defecto durante una operación de arrastrar y soltar. 
Para obtener el resultado que queremos, necesitamos prevenir en algunas ocasiones este comportamiento por defecto y personalizar las reacciones del navegador. Para algunos eventos, como dragenter, dragover y drop, la prevención es necesaria, incluso cuando una acción personalizada ya fue especificada.

Veamos cómo debemos proceder usando un ejemplo simple.

Código 8-1. Plantilla para la operación arrastrar y soltar.

<!DOCTYPE html>
<html lang="es">
<head>
<title>Drag and Drop</title>
<link rel="stylesheet" href="dragdrop.css">
<script src="dragdrop.js"></script>
</head>
<body>
<section id="cajasoltar">
Arrastre y suelte la imagen aquí
</section>
<section id="cajaimagenes">
<img id="imagen" src="http://www.minkbooks.com/content/
monster1.gif">
</section>
</body>
</html>

El documento HTML del Código 8-1 incluye un elemento <section> identificado como cajasoltar y una imagen. El elemento <section> será usado como elemento destino y la imagen será el elemento a arrastrar. También incluimos dos archivos para estilos CSS y el código javascript que se hará cargo de la operación.

Código 8-2. Estilos para la plantilla (dragdrop.css)

#cajasoltar{
float: left;
width: 500px;
height: 300px;
margin: 10px;
border: 1px solid #999999;
}
#cajaimagenes{
float: left;
width: 320px;
margin: 10px;
border: 1px solid #999999;
}
#cajaimagenes > img{
float: left;
padding: 5px;
}

Las reglas en el Código 8-2 simplemente otorgan estilos a las cajas que nos servirán para identificar el elemento a arrastrar y el destino.

Código 8-3. Código elemental para una operación arrastrar y soltar.

 
function iniciar(){
origen1=document.getElementById('imagen');
origen1.addEventListener('dragstart', arrastrado, false);
destino=document.getElementById('cajasoltar');
destino.addEventListener('dragenter', function(e){
e.preventDefault(); }, false);
destino.addEventListener('dragover', function(e){
e.preventDefault(); }, false);
destino.addEventListener('drop', soltado, false);
}
function arrastrado(e){
var codigo='<img src="'+origen1.getAttribute('src')+'">';
e.dataTransfer.setData('Text', codigo);
}
function soltado(e){
e.preventDefault();
destino.innerHTML=e.dataTransfer.getData('Text');
}
window.addEventListener('load', iniciar, false);

Existen algunos atributos que podemos usar en los elementos HTML para configurar el proceso de una operación arrastrar y soltar, pero básicamente todo puede ser hecho desde código Javascript. En el Código 8-3, presentamos tres funciones: la función iniciar() agrega las escuchas para los eventos necesarios en esta operación, y las funciones arrastrado() y soltado() generan y reciben la información que es transmitida por este proceso. 

Para que una operación arrastrar y soltar se realice normalmente, debemos preparar la información que será compartida entre el elemento origen y el elemento destino. Para lograr esto, una escucha para el evento dragstart fue agregada. La escucha llama a la función arrastrado() cuando el evento es disparado y la información a ser compartida es preparada en esta función usando setData(). 
La operación soltar no es normalmente permitida en la mayoría de los elementos de un documento por defecto. Por este motivo, para hacer esta operación disponible en nuestro elemento destino, debemos prevenir el comportamiento por defecto del navegador. Esto fue hecho agregando una escucha para los eventos dragenter y dragover y ejecutando el método preventDefault() cuando son disparados.
Finalmente, una escucha para el evento drop fue agregada para llamar a la función soltado() que recibirá y procesará los datos enviados por el elemento origen. 
Conceptos básicos: Para responder a los eventos dragenter y dragover usamos una función anónima y llamamos en su interior al método preventDefault() que cancela el comportamiento por defecto del navegador.
La variable e fue enviada para referenciar al evento dentro de la función. Para obtener más información acerca de funciones anónimas, visite nuestro sitio web y siga los enlaces correspondientes a este capítulo.
Cuando el elemento origen comienza a ser arrastrado, el evento dragstart es disparado y la función arrastrado() es llamada. En esta función obtenemos el valor del atributo src del elemento que está siendo arrastrado y declaramos los datos que serán transferidos usando el método setData() del objeto dataTransfer. Desde el otro lado, cuando un elemento es soltado dentro del elemento destino, el evento drop es disparado y la función soltado() es llamada. Esta función modifica el contenido del elemento destino con la información obtenida por el método getData(). Los navegadores también realizan acciones por defecto cuando estos eventos son disparados (por ejemplo, abrir un enlace o actualizar la ventana para mostrar la imagen que fue soltada) por lo que debemos prevenir este comportamiento usando el método preventDefault(), como ya hicimos para otros eventos anteriormente.
Hágalo usted Mismo: Cree un archivo HTML con la plantilla del Código 8-1, un archivo CSS llamado dragdrop.css con los estilos del Código 8-2, y un archivo Javascript llamado dragdrop.js con el código del Código 8-3. Para probar el ejemplo, abra el archivo HTML en su navegador y arrastre la imagen hacia el cuadro de la izquierda.


dataTransfer

Este es el objeto que contendrá la información en una operación arrastrar y soltar. El objeto dataTransfer tiene varios métodos y propiedades asociados. Ya utilizamos los métodos setData() y getData() en nuestro ejemplo del Código 8-3. Junto con clearData(), estos son los métodos a cargo de la información que es transferida:
  • setData(tipo, dato) Este método es usado para declarar los datos a ser enviados y su tipo. El método puede recibir tipos de datos regulares (como text/plain, text/html o text/uri-list), tipos de datos especiales (como URL o Text) o incluso tipos de datos personalizados. Un método setData() debe ser llamado por cada tipo de datos que queremos enviar en la misma operación. 
  • getData(tipo) Este método retorna los datos enviados por el origen, pero solo del tipo especificado.
  • clearData() Este método remueve los datos del tipo especificado.


En la función arrastrado() del Código 8-3, creamos un pequeño código HTML que incluye el valor del atributo src del elemento que comenzó a ser arrastrado, grabamos este código en la variable codigo y luego enviamos esta variable como el dato a ser transferido usando el método setData(). Debido a que estamos enviando texto, declaramos el tipo de dato como Text.
IMPORTANTE: Podríamos haber usado un tipo de datos más apropiado en nuestro ejemplo, como text/html o incluso un tipo personalizado, pero varios navegadores solo admiten un número limitado de tipos en este momento, por lo que el tipo Text hace a nuestra pequeña aplicación más compatible y la deja lista para ser ejecutada.
Cuando recuperamos los datos en la función soltado() usando el método getData(), tenemos que especificar el tipo de datos a ser leído. Esto es debido a que diferentes clases de datos pueden ser enviados por el mismo elemento. Por ejemplo, una imagen podría enviar la imagen misma, la URL y un texto describiendo la imagen. Toda esta información puede ser enviada usando varias declaraciones de setData() con diferentes tipos de valores y luego recuperada por getData() especificando los mismo tipos.
IMPORTANTE: Para obtener mayor información acerca de tipos de datos para la operación arrastrar y soltar, visite nuestro sitio web y siga los enlaces correspondientes a este capítulo.

El objeto dataTransfer tiene algunos métodos y propiedades más que a veces podrían resultar útil para nuestras aplicaciones:
  • setDragImage(elemento, x, y) Algunos navegadores muestran una imagen en miniatura junto al puntero del ratón que representa al elemento que está siendo arrastrado. Este método es usado para personalizar esa imagen y seleccionar la posición la posición en la que será mostrada relativa al puntero del ratón. Esta posición es determinada por los atributos x e y.
  • types Esta propiedad retorna un array conteniendo los tipos de datos que fueron declarados durante el evento dragstart (por el código o el navegador). Podemos grabar este array en una variable (lista=dataTransfer.types) y luego leerlo con un bucle for.
  • files Esta propiedad retorna un array conteniendo información acerca de los archivos que están siendo arrastrados.
  • dropEffect Esta propiedad retorna el tipo de operación actualmente seleccionada. Los posibles valores son none, copy, link y move.
  • effectAllowed Esta propiedad retorna los tipos de operaciones que están permitidas.


Puede ser usada para cambiar las operaciones permitidas. Los posibles valores son: 
none, copy, copyLink, copyMove, link, linkMove, move, all y uninitialized.

Aplicaremos algunos de estos métodos y propiedades en los siguientes ejemplos.


dragenter, dragleave y dragend

Nada fue hecho aún con el evento dragenter. Solo cancelamos el comportamiento por defecto de los navegadores cuando este evento es disparado para prevenir efectos no deseados. Y tampoco aprovechamos los eventos dragleave y dragend. Estos son eventos importantes que nos permitirán ayudar al usuario cuando se encuentra arrastrando objetos por la pantalla.

Código 8-4. Controlando todo el proceso de arrastrar y soltar.

 
function iniciar(){
origen1=document.getElementById('imagen');
origen1.addEventListener('dragstart', arrastrado, false);
origen1.addEventListener('dragend', finalizado, false);
soltar=document.getElementById('cajasoltar');
soltar.addEventListener('dragenter', entrando, false);
soltar.addEventListener('dragleave', saliendo, false);
soltar.addEventListener('dragover', function(e){
e.preventDefault(); }, false);
soltar.addEventListener('drop', soltado, false);
}
function entrando(e){
e.preventDefault();
soltar.style.background='rgba(0,150,0,.2)';
}
function saliendo(e){
e.preventDefault();
soltar.style.background='#FFFFFF';
}
function finalizado(e){
elemento=e.target;
elemento.style.visibility='hidden';
}
function arrastrado(e){
var codigo='<img src="'+origen1.getAttribute('src')+'">';
e.dataTransfer.setData('Text', codigo);
}
function soltado(e){
e.preventDefault();
soltar.style.background='#FFFFFF';
soltar.innerHTML=e.dataTransfer.getData('Text');
}
window.addEventListener('load', iniciar, false);

El Código 8-4 reemplaza al Código 8-3. En este nuevo ejemplo, agregamos dos funciones para el elemento destino y una para el elemento origen. Las funciones entrando() y saliendo() cambiarán el color de fondo del elemento destino cada vez que el puntero del ratón esté arrastrando un objeto y entre o salga del área ocupada por este elemento (estas acciones disparan los eventos dragenter y dragleave). Además, la función finalizado() será llamada por la escucha del evento dragend cuando el objeto arrastrado es soltado. Note que este evento o la función misma no controlan si el proceso fue exitoso o no. Este control lo deberemos hacer nosotros en el código.
Gracias a los eventos y funciones agregadas, cada vez que el ratón arrastra un objeto y entra en el área del elemento destino, este elemento se volverá verde, y cuando el objeto es soltado la imagen original es borrada de la pantalla. Estos cambios visibles no están afectando el proceso de arrastrar y soltar, pero sí están ofreciendo una guía clara para el usuario durante la operación.
Para prevenir acciones por defecto del navegador, tenemos que usar el método preventDefault() en cada función, incluso cuando acciones personalizadas fueron declaradas.
Hágalo usted mismo: Copie el Código 8-4 dentro del archivo Javascript, abra el documento HTML del Código 8-1 en su navegador, y arrastre la imagen que aparece en la pantalla dentro de la caja ubicada a su izquierda.


Espero haber ayudado en algo. Hasta la próxima oportunidad!

DESCARGAR PUBLICACIÓN










  

No hay comentarios:

Publicar un comentario en la entrada