Arrastar e soltar
=================

As interfaces de Drag and Drop (arrastar e soltar) habilitam aplicações a usar funcionalidades de arrastar e soltar através do navegador. Por exemplo, com essas funcionalidades, o usuário pode selecionar elementos arrastáveis (*draggable*) com o mouse, arrastar elementos até um elemento soltável (*droppable*), e soltar o elemento ao soltar o botão do mouse. Uma representação translúcida de elementos arrastáveis (*draggable)* seguem o ponteiro do mouse durante a operação de arrastar (drag).

Para web sites, extensões e aplicações XUL, você pode customizar os tipos de elementos que podem se tornar arrastáveis (draggable) e o tipo de retorno que o elemento arrastável produz, assim como os elementos soltáveis (droppable).

**NT:** Para manter a tradução mais precisa e coesa, a partir daqui iremos manter os termos *drag* e *drop* e seus variantes conforme texto original. Sendo portanto mantidos também os termos *draggable* e *droppable*.

Este documento é uma visão geral do drag and drop no HTML. Ele inclui uma descrição de suas interfaces, funcionalidades básicas de como permitir a adesão de funcionalidades arrastar e soltar em uma aplicação e um sumário da interoperabilidade entre interfaces.

Eventos Drag
------------

O drag and drop em HTML usa o `modelo de eventos DOM` e os *`eventos drag` (en-US)* são hereditários dos `eventos do mouse`. Uma operação típica de drag começa quando o usuário seleciona um elemento arrastável com o mouse, move o mouse até um elemento soltável (droppable) e solta o mouse. Durante as operações, diversos tipos de evento são acionados e alguns podem até ser acionados multiplas vezes (como por exemplo os tipos de evento `drag (en-US)` e `dragover (en-US)`.

Todos os tipos de evento drag (en-US) são associados a um manipulador global de eventos (en-US). Cada tipo de evento drag e cada atributo drag global tem um documento de referência que o descreve. A tabela a seguir descreve brevemente os tipos de evento e um link de referência para seu documento.

| Event | On Event Handler | Description |
| --- | --- | --- |
| `drag (en-US)` | `ondrag` (en-US) | Acionado quando um elemento ou seleção de texto está sendo arrastado. |
| `dragend (en-US)` | `ondragend` (en-US) | Acionado quando uma operação de arrastar está terminando (por eexmplo, ao soltar o botão do mouse ou pressionar a tecla esc). (Veja Terminando um evento Drag (en-US).) |
| `dragenter (en-US)` | `ondragenter` (en-US) | Acionado quando um elemento arrastável ou seleção de texto entra em um ponto de soltura (drop target). (Veja Determinando Drop Targets (en-US).) |
| `dragexit` | `ondragexit` (en-US) | Acionado quando um elemento não é mais o ponto de seleção imediata da operação drag. |
| `dragleave (en-US)` | `ondragleave` (en-US) | Acionado quando um elemento arrastável ou seleção de texto abandona um ponto de soltura (drop target) válido. |
| `dragover (en-US)` | `ondragover` (en-US) | Acionado quando um elemento ou seleção de texto está sendo arrastado sobre um ponto de soltura válido (a cada aproximadamente 100 milisegundos). |
| `dragstart (en-US)` | `ondragstart` (en-US) | Acionado quando o usuário começa a arrastar um elemento válido ou seleção de texto. (Veja Começando uma Operação Drag (en-US).) |
| `drop (en-US)` | `ondrop` (en-US) | Acionado quando um elemento ou seleção de texto é solta em um ponto d soltura (drop target) válido. (Veja Realizando um Drop (en-US).) |

Note que eventos `dragstart` e `dragend` não são acionados ao arrastar um arquivo vindo do sistema operacional para o navegador.

Interfaces
----------

A interface HTML drag and drop é composta pelos eventos `DragEvent` (en-US), `DataTransfer`, `DataTransferItem` (en-US) e `DataTransferItemList` (en-US).

A interface `DragEvent` (en-US) consiste de um construtor e uma propriedade, a propriedade `dataTransfer` (en-US) que é um objeto `DataTransfer`. Os objetos `DataTransfer` incluem estados do evento drag como o tipo de drag sendo feito (por exemplo `copy` ou `move`), os dados do do evento drag (um ou mais itens) e o tipo de cada *item drag* (um MIME type). Objetos `DataTransfer` também contém métodos para adicionar itens aos dados do drag e remover um item. As interfaces `DragEvent` (en-US) e `DataTransfer` devem as únicas necessárias para adicionar capacidades de drag and drop para uma aplicação. Entretanto, note que o Firefox provê suporte para apenas algumas Gecko-specific extensions ao objeto `DataTransfer`, apesar de entretanto essas extensões funcionarem apenas no Firefox.

Cada objeto `DataTransfer` contém uma propriedade `items` (en-US) que é uma `lista` (en-US) dos objetos `DataTransferItem` (en-US). Cada objeto `DataTransferItem` (en-US) representa um único *drag item* e cada item tem uma propriedade `kind (tipo)` (en-US) que é o *tipo(kind)* de data (seja ela `string` ou `file`) e uma propriedade `type (tipo)` (en-US) que é o tipo de dado do item (ou seja, MIME type). O objeto `DataTransferItem` (en-US) também contém métodos para conseguir dados do item arrastável.

O objeto `DataTransferItemList` (en-US) é uma lista de objetos `DataTransferItem` (en-US). A lista de objetos contém métodos para: adicionar um item para uma lista, remover um item de uma lista e limpar a lista com todos os itens.

A diferença chave entre das interfaces `DataTransfer` e `DataTransferItem` (en-US) é que a primeira usa o método síncrono `getData()` (en-US) para acessar os dados de um item arrastável, e a segunda usa o método assíncrono `getAsString()` (en-US) para acessá-lo.

Note: as interfaces `DragEvent` (en-US) e a `DataTransfer` são vastamente interoperáveis com navegadores desktop. Entretanto, as interfaces `DataTransferItem` (en-US) e `DataTransferItemList` (en-US) tem suporte limitado entre navegadores. Veja Interoperabildade para mais informações.

### Interfaces específicas para o Gecko

A Mozilla e o Firefox suportam algumas funcionalidades fora dos padrões do modelo drag and drop. Elas são *cfunções convenientes* para facilitar o arraste múltiplo de elementos e a manipulação de dados que não são strings (como arquivos). Para mais informações, veja Dragging and Dropping Multiple Items. Para mais informações, veja a página de referência `DataTransfer` para todas as propriedades específicas para o Gecko e Métodos específicos para o Gecko.

O básico
--------

Esta seção dispõe de um resumo das etapas básicas para adicionar a funcionalidade drag and drop à uma aplicação. Cada seção inclui uma descrição da etapa, um breve exemplo em código, e links para informações adicionais.

### Identificando o que é arrastável *(draggable)*

Para fazer um elemento se tornar arrastável, é necessária a adição de um atributo `draggable` além da adição do manipulador de eventos global `ondragstart` (en-US), conforme descrito no exemplo a seguir


```js
function dragstart\_handler(ev) {
  console.log("dragStart");
  // Adiciona o id do elemento em questão ao objeto de transferência de dados (dataTransfer)
  ev.dataTransfer.setData("text/plain", ev.target.id);
}
```



```html
<body>
  <p id="p1" draggable="true" ondragstart="dragstart\_handler(event);">
    Este elemento é arrastável.
  </p>
</body>
```


Veja a referência do atributo draggable (en-US) e o Guia de operações drag (en-US) para mais informações.

### Defina os dados do drag

A aplicação é livre para incluir qualquer quantidade de dados do item em uma operação drag. Cada dado de um item é uma `string` de um tipo particular, tipicamente um MIME type como por exemplo `text/html`.

Cada `evento drag` (en-US) tem uma propriedade `dataTransfer` (en-US) que *segura* os dados do evento. Essa propridade (que é um objeto `DataTransfer`) também tem um método para *gerenciar* os dados do arraste (drag). O método `setData()` (en-US) é usado para adicionar um item aos dados do arraste, como demonstrado no exemplo a seguir.


```js
function dragstart\_handler(ev) {
  // Adiciona os dados do arraste (drag)
  ev.dataTransfer.setData("text/plain", ev.target.id);
  ev.dataTransfer.setData("text/html", "<p>Parágrafo de exemplo</p>");
  ev.dataTransfer.setData("text/uri-list", "http://developer.mozilla.org");
}
```


Para uma lista de tipos de dados mais comuns utilizados pelo drag and drop (como texto, HTML, links, e files), veja Tipos recomendados de Drag Types (en-US) e para mais informações sobre os dados do arraste (drag data), veja Drag Data (en-US).

### Defina uma imagem de arraste (drag image)

Por padrão, o navegador provê uma imagem que aparece por trás do ponteiro do mouse durante uma operação de arraste. Entretanto, uma aplicação pode definir uma imagem customizada utilizando o método `setDragImage()` (en-US) como demonstrado no exemplo a seguir.


```js
function dragstart\_handler(ev) {
  // Cria uma imagem e então a utiliza como a "drag image".
  // NOTA: mude "example.gif" como uma imagem existente, caso contrário
  // ela não será criada e a imagem padrão será utilizada como padrão.
  var img = new Image();
  img.src = "example.gif";
  ev.dataTransfer.setDragImage(img, 10, 10);
}
```


Para aprender mais sobre arrastar imagens de retorno, veja Definindo a imagem de retorno do arraste (Drag) (en-US).

### Defina o *efeito* do arraste (*Drag effect*)

A propriedade `dropEffect` (en-US) é usada para controlar o retorno (geralmente visual) que é dado ao usuário durante uma operação drag and drop. Ela afeta qual cursor o navegador irá mostrar enquanto o arraste é realizado. Por exemplo, quando o usuário passa sobre (famoso *hover*) o ponto de soltura (drop target), o cursor do navegador pode indicar o tipo de operação que irá acontecer.

Três efeitos podem ser definidos:

`copy` indica que os dados sendo arrastados podem ser copiados da localização atual para a localização de destino (localização do *drop*).

`move` indica que os dados sendo arrastados irá ser movido.

`link` indica que alguma forma de relação ou conexão será criada entre a localização de origem (source) e de destino (drop).

Durante a operação de arraste, os efeitos do arraste (drag) podem ser modificados para determinar que certos efeitos são permitidos em determinadas localizações. Se permitido, uma soltura (drop) pode ocorrer naquela localização.

O exemplo a seguir mostra como utilizar essa propriedade.


```js
function dragstart\_handler(ev) {
  // Determina o efeito de arraste para copy
  ev.dataTransfer.dropEffect = "copy";
}
```


Veja Efeitos do Arraste (Drag Effects) (en-US) para mais detalhes.

### Defina uma zona de soltura *(drop zone)*

Por padrão, o navegador previne tudo que possa acontecer ao soltar alguma coisa em um elemento HTML. Para mudar esse comportamento de forma que um elemento se torne uma zona de soltura (d*rop zone)* ou que seja soltável *(droppable)*, o elemento precisa ter ambos os atributos `ondragover` (en-US) e `ondrop` (en-US). O exemplo a seguir mostra como utilizar esses atributos e inclui manipuladores básicos de evento para cada um.


```js
function dragover\_handler(ev) {
  ev.preventDefault();
  // Define o dropEffect para ser do tipo move
  ev.dataTransfer.dropEffect = "move";
}
function drop\_handler(ev) {
  ev.preventDefault();
  // Pega o id do alvo e adiciona o elemento que foi movido para o DOM do alvo
  var data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
}
<body>
  <div
    id="target"
    ondrop="drop\_handler(event);"
    ondragover="dragover\_handler(event);">
    Zona de Soltura (Drop Zone)
  </div>
</body>;
```


Note que cada manipulador chama `preventDefault()` para previnir o processamento adicional de eventos (como eventos touch ou eventos pointer).

Para mais informações, veja Especificando pontos de soltura (Drop Targets) (en-US).

### Manipulando o *efeito* de soltura (drop)

O manipulador do evento `drop (en-US)` é livre para processar os dados do arraste (drag) de maneira específica em uma aplicação. Tipicamente, uma aplicação usaria o método `getData()` (en-US) para reter os itens arrastados e processá-los de acordo. A semântica da aplicação pode ser diferente dependendo do valor do `dropEffect` (en-US) e/ou o estado da chave que o modifica.

O exemplo a seguir mostra o manipulador de soltura (drop handler) pegando o id do elemento de origem atráves dos dados de drag (drag data) e então usando o id para mover o elemento de sua origem para o elemento de soltura (drop element).


```js
function dragstart\_handler(ev) {
  // Adiciona o id do elemento alvo para o objeto de transferência de dados
  ev.dataTransfer.setData("text/plain", ev.target.id);
  ev.dropEffect = "move";
}
function dragover\_handler(ev) {
  ev.preventDefault();
  // Define o dropEffect para ser do tipo move
  ev.dataTransfer.dropEffect = "move";
}
function drop\_handler(ev) {
  ev.preventDefault();
  // Pega o id do alvo e adiciona o elemento que foi movido para o DOM do alvo
  var data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
}
<body>
  <p id="p1" draggable="true" ondragstart="dragstart\_handler(event);">
    Este elemento é arrastável.
  </p>
  <div
    id="target"
    ondrop="drop\_handler(event);"
    ondragover="dragover\_handler(event);">
    Zona de Soltura (Drop Zone)
  </div>
</body>;
```


Para mais informações, veja Realizando uma soltura (Drop) (en-US).

### Fim da soltura (Drag end)

No início da operação de arraste (drag), o evento `dragend (en-US)` é acionado no elemento de origem (*source)* - o elemento que foi o alvo do início do arraste (drag start). Este evento é acionado sempre quando o arraste é completado ou cancelado. O manipulador de eventos `dragend (en-US)` pode verificar o valor da propriedade `dropEffect` (en-US) para determinar se a operação de arraste foi bem sucedida ou não.

Para mais informações sobre manipular o final de uma operação de arraste, veja Finalizando um arraste (Drag) (en-US).

Interoperabilidade
------------------

Como podem ser visto no DataTransferItem interface's Browser Compatibility table (en-US), drag-and-drop a interoperabilidade é relativamente ampla emtre ps brpwsers desktop (exceto as interfaces `DataTransferItem` (en-US) e `DataTransferItemList` (en-US) que tem o menor suport). Estes dados tambem indica que o suporte ao drag and drop entre browser mobile é muito menor.

Exemplos e demonstrações
------------------------

* Copiando e movendo elementos com a interface `DataTransfer`
* Copiando e movendo elementos com a interface `DataTransferListItem`
* Arrastando e soltando arquivos; Apenas para o Firefox: http://jsfiddle.net/9C2EF/
* Arrastando e soltando arquivos; Todos os navegadores: https://jsbin.com/hiqasek/
Veja também
-----------

* Operações de Arraste (en-US)
* Arrastando e Soltando múltiplos elementos
* Tipos re arraste (Drag Types) recomendados (en-US)
* HTML5 Living Standard: Drag and Drop
* Dados de unteroperabilidade Drag and Drop de acordo com o CanIUse