Drag & Drop en HTML5 sobre Firefox 3.5

Tomado de blogografia.com

July 16, 2009 by anieto2k
Muchas son las mejoras que hemos visto en Firefox 3.5, desde geolocalización en el navegador hasta ajax cross domain que no nos ancla a un único servidor, pasando por los tags multimedia de HTML5.
Una de las que más desapercibido han pasado, es la de los nuevos eventos disponibles para facilitar el ya conocido Drag & Drop.
Drag & Drop
Ya conocemos esta técnica, es una de las más implementadas en los diferentes frameworks Javascript. Hasta el momento, teníamos que usar Javascript para simular que podíamos arrastrar elementos por nuestras páginas web, haciendo que este siguiera al ratón en momento de hacer click.

Todas ellas requieren unas cuantas líneas de código para conseguir el efecto de movimiento. En cambio con el nuevo estandar esto ya lo implementa el navegador y únicamente tenemos a nuestra disposición los eventos necesarios para controlar las acciones que ellos producen.
Eventos Drag & Drop

dragstart
Se ha iniciado el evento. El target del evento hace referencia al elementos agarrado.
drag
El ratón se está moviendo con el elemento seleccioando.
dragenter
El elemento ha sido movido dentro de un recipiente (drop). Aún no ha sido soltado.
dragover
El elemento ha salido del recipiente.
dragleave
El elemento ha sido soltado fuera del espacio del recipiente.
drop
El elemento ha sido soltado en el recipiente.
dragend
El evento a terminado

Atributos Drag & Drop
Para convertir un elemento en “Draggable” únicamente tendremos que hacérselo saber al DOM mediante el cambio de un atributo disponible en los elementos.
elemento.draggable = true; // Por defecto false
De esta forma, estamos indicando al navegador que el elemento (elemento) tendrá disponibles los eventos destinados al Drag & Drop.
Ejemplo
ver ejemplo . . .

// HTML
<div id="newschool">
<div>Drag me!</div>
<div>Drop here!</div>
</div>

// Javascript
<script type="text/javascript">
$(document).ready(function() {
/* DRAG */
$('#newschool .dragme')
.attr('draggable', 'true') // Hacemos los elementos draggable.
.bind('dragstart', function(ev) { // Evento inicial
var dt = ev.originalEvent.dataTransfer; // dataTransfer es un atributo del evento
// var dt = ev.dataTransfer; // Versión no jQuery
dt.setData("Text", "Dropped in zone!");
return true;
})
.bind('dragend', function(ev) { // evento final
return false;
});

/* DROP */
$('#newschool .drophere')
.bind('dragenter', function(ev) { // El elemento está sobre él.
$(ev.target).addClass('dragover');
return false;
})
.bind('dragleave', function(ev) { // El elemento abandona el recipiente
$(ev.target).removeClass('dragover');
return false;
})
.bind('dragover', function(ev) { // El elemento está fuera del recipiente
return false;
})
.bind('drop', function(ev) { // El elemento es depositado en el recipiente.
var dt = ev.originalEvent.dataTransfer;
alert(dt.getData('Text'));
return false;
});
});
</script>
Como podemos ver en el ejemplo (de hacks.mozilla) se han diferenciado 2 elementos.

Por un lado tenemos los drag, elementos con el atributo draggable = true, que posibilita que puedan ser arrastrados por la página. Por otro lado tenemos los elementos drop, que se convierten en recipientes donde poder alojar los elementos drag.
Ambos tipos de elementos tienen diferentes eventos dependiendo de su misión, esto nos permite ver más claro el funcionamiento de estos eventos.
dataTransfer
Se trata de un atributo nuevo que podemos encontrar asociado al evento y que nos hace referencia a lo que estamos arrastrando por la página. En el ejemplo he puesto en cursiva el código que haría falta si no usáramos jQuery.
Recordemos que jQuery encapsula los elementos, eventos,.. y por eso hemos de usar originalEvent para acceder al evento nativo.
Propiedades
Este atributo se compone, además, de una serie de propiedades interesantes para complementar la información que tenemos disponible del elemento arrastrado.

  • dropEffect (String): Especifica el efecto actual que se está usando (copy, move, link, none).
  • effectAllowed (String): Especifica los efectos disponibles para el elemento que estamos arrastrando (copy, move, link, copyLink, copyMove, linkMove, all, none, uninitialized).
  • Types (StringList): Listado de formatos posibles para alojar en él.
  • mozItemCount (unsigned long): Número de items que estamos arrastrando.

Métodos
Además dispone de una serie de métodos para ayudarnos a interáctuar con el contenido:
void addElement(in Element image):
Inserta el contenido, generalmente nunca se usará.
void clearData([in String type]):
Elimina la información asociada de un tipo dado.
String getData(in String type):
Nos duelve el tipo de contenido.
var dt = ev.originalEvent.dataTransfer;
$('.content_url .content').text(dt.getData('text/uri-list'));
$('.content_text .content').text(dt.getData('text/plain'));
$('.content_html .content').html(dt.getData('text/html'));

void setData(in String type, in String data):

Nos permite insertar información con un tipo definido.
var dt = ev.originalEvent.dataTransfer;
dt.setData('text/plain', $('#logo').parent().text());
dt.setData('text/html', $('#logo').parent().html());
dt.setData('text/uri-list', $('#logo')[0].src);

void setDragImage(in nsIDOMElement image, in long x, in long y):

Especifica una imagen para mostrar mientras arrastramos.
var dt = ev.originalEvent.dataTransfer;
dt.setDragImage( $('#feedback_image h2')[0], 0, 0);