Drag & Drop archivo

Las interfaces Drag-and-Drop posibilitan arrastrar y soltar archivos en una página web. En este documento se describe cómo una aplicación puede aceptar uno, o más, archivos que son arrastrados desde el explorador de archivos de la plataforma y soltados en una página web.

Los pasos principales para configurar Drag-and-drop son: 1) definir una "zona drop (drop zone), es decir, definir un elemento donde se podrá soltar el archivo; y 2) definir funciones para la gestión de los eventos drop (en-US)dragover. Estos pasos se describen a continuación, tambien se incluyen ejemplos snippets de código. El código fuente completo está disponible en el repositorio drag-and-drop de MDN (cualquier sugerencia o  tema que revisar es bienvenido).

Nota: HTML drag and drop define 2 diferentes APIs para soportar drag and drop de archivos. Una API es la interfaz DataTransfer (en-US) y la segunda API son las interfaces DataTransferItem (en-US) y DataTransferItemList (en-US).  Este ejemplo ilustra el uso de ambas APIs (y no usa ninguna interfaz específica de Gecko).

Define la zona "drop" [drop zone]

Es necesario configurar un evento drop (en-US) en el objeto sobre el cual se soltará el objeto arrastrado. Este evento llamará una función global ondrop (en-US) que recibe los datos del objeto arrastrado. El siguiente código muestra cómo se hace con un elemento <div>:

<div id="drop_zone" ondrop="dropHandler(event);">
  <p>Arrastra y suelta uno o más archivos a esta zona ...</p>
</div>

Normalmente, una aplicación incluirá una función de gestión de eventos dragover en el elemento objetivo del arrastre y esa función desactivará el comportamiento de arrastre por defecto del browser. Para añadir esta función necesita incluir una función global ondragover (en-US):

<div id="drop_zone" ondrop="dropHandler(event);" ondragover="dragOverHandler(event);">
  <p>Arrastra y suelta uno o más archivos a esta zona ...</p>
</div>

Por último, puede que una aplicación quiera personalizar el estilo del elemento objetivo del arrastre para indicar visualmente que es una zona drag and drop. En este ejemplo, el elemento objetivo usa el siguiente estilo:

#drop_zone {
  border: 5px solid blue;
  width:  200px;
  height: 100px;
}

Fíjese que los eventos dragstart y dragend no son activados cuando se arrastra un archivo al browser desde el SO.

Procesar la acción de soltar [drop]

El evento drop (en-US) se ejecuta cuando el usuario suelta el o los archivos. En el siguiente manejador, si el navegador sorporta la interfaz DataTransferItemList (en-US) , el método getAsFile() (en-US) se utiliza para acceder cada fichero; de lo contrario la propiedad DataTransfer (en-US) de la interfaz files (en-US) es usada para acceder cada archivo.

El ejemplo siguiente muestra como escribir el nombre de cada fichero arrastrado en la consola. En una aplicación real, se querrá procesar un archivo usando File API.

Nótese que en este ejemplo, cualquier item arrastrado que no sea un archivo es ignorado.

function dropHandler(ev) {
  console.log('Fichero(s) arrastrados');

  // Evitar el comportamiendo por defecto (Evitar que el fichero se abra/ejecute)
  ev.preventDefault();

  if (ev.dataTransfer.items) {
    // Usar la interfaz DataTransferItemList para acceder a el/los archivos)
    for (var i = 0; i < ev.dataTransfer.items.length; i++) {
      // Si los elementos arrastrados no son ficheros, rechazarlos
      if (ev.dataTransfer.items[i].kind === 'file') {
        var file = ev.dataTransfer.items[i].getAsFile();
        console.log('... file[' + i + '].name = ' + file.name);
      }
    }
  } else {
    // Usar la interfaz DataTransfer para acceder a el/los archivos
    for (var i = 0; i < ev.dataTransfer.files.length; i++) {
      console.log('... file[' + i + '].name = ' + ev.dataTransfer.files[i].name);
    }
  }

  // Pasar el evento a removeDragData para limpiar
  removeDragData(ev)
}

Prevenir el comportamiento default de arrastrado en el browser 

El siguiente evento dragover llama a  preventDefault() para deshabilitar (turn off) la respuesta estandar drag-and-drop del browser.

function dragOverHandler(ev) {
  console.log('File(s) in drop zone');

  // Prevent default behavior (Prevent file from being opened)
  ev.preventDefault();
}

Limpieza (Cleanup)

Typically, an application may want to perform some cleanup by deleting the file drag data. In this example, the drop event is passed along from drop handler to a custom function called removeDragData. If the browser supports the DataTransferItemList (en-US) interface, the list's clear() (en-US) method is used to delete the file drag data; otherwise the DataTransfer (en-US) object's clearData() (en-US) method is used to delete the data.

function removeDragData(ev) {
  console.log('Removing drag data')

  if (ev.dataTransfer.items) {
    // Use DataTransferItemList interface to remove the drag data
    ev.dataTransfer.items.clear();
  } else {
    // Use DataTransfer interface to remove the drag data
    ev.dataTransfer.clearData();
  }
}

See also