Quebra de barreiras com a API DataTransfer

Permita que o usuário compartilhe dados além da janela do navegador.

Você já deve ter ouvido falar sobre API DataTransfer, que é parte do API HTML5 Drag and Drop e eventos da área de transferência. Ela pode ser usado para transferir dados entre destinos de origem e de recebimento.

Compatibilidade com navegadores

  • Chrome: 3.
  • Borda: 12.
  • Firefox: 3.5.
  • Safari: 4.

Origem

As interações de arrastar, soltar e copiar/colar costumam ser usadas para interações em uma página para transferir textos simples de A para B. Mas o que muitas vezes é negligenciado é a capacidade de usar essas mesmas interações para ir além da janela do navegador.

Tanto as interações de arrastar e soltar integradas do navegador quanto as interações de copiar e colar podem se comunicar a outros aplicativos, da Web ou de outro modo, e não estão vinculados a nenhuma origem. A API oferece suporte a vários entradas de dados com comportamentos diferentes de acordo com o local para onde os dados são transferidos. Seu aplicativo da web pode enviar e receber os dados transferidos ao ouvir eventos de entrada.

Esse recurso pode mudar a maneira como pensamos sobre compartilhamento e interoperabilidade na Web aplicativos no computador. A transferência de dados entre aplicativos não precisa depender de integrações com acoplamento rígido. Em vez disso, você pode dar aos usuários controle total para transferir para onde eles quiserem.

Um exemplo de interações possíveis com a API DataTransfer. O vídeo não inclui som.

Transferência de dados

Para começar, você precisa implementar o recurso de arrastar e soltar ou copiar e colar. Os exemplos abaixo mostram as interações de arrastar e soltar, mas o processo de copiar e colar é semelhante. Se não estiver familiarizado com a API Drag and Drop, há um ótimo artigo explicação do recurso de arrastar e soltar do HTML5, que explica todos os detalhes.

Ao fornecer dados com chave no tipo MIME, permite interagir livremente com aplicativos externos. A maioria dos editores WYSIWYG, editores de texto e navegadores respondem ao mime-types usados na exemplo abaixo.

document.querySelector('#dragSource')
.addEventListener('dragstart', (event) => {
  event.dataTransfer.setData('text/plain', 'Foo bar');
  event.dataTransfer.setData('text/html', '<h1>Foo bar</h1>');
  event.dataTransfer.setData('text/uri-list', 'https://example.com');
});

Observe a propriedade event.dataTransfer. Isso retorna uma instância do DataTransfer Conforme você verá que, às vezes, esse objeto é retornado por propriedades com outros nomes.

Receber a transferência de dados funciona quase da mesma forma que fornecê-la. Ouvir os eventos de recebimento (drop ou paste) e leia as chaves. Ao arrastar sobre um elemento, o navegador só tem acesso às chaves type dos dados. Os dados só podem ser acessados depois de uma ação de soltar.

document.querySelector('#dropTarget')
.addEventListener('dragover', (event) => {
  console.log(event.dataTransfer.types);
  // Without this, the drop event won't fire.
  event.preventDefault();
});

document.querySelector('#dropTarget')
.addEventListener('drop', (event) => {
  // Log all the transferred data items to the console.
  for (let type of event.dataTransfer.types) {
    console.log({ type, data: event.dataTransfer.getData(type) });
  }
  event.preventDefault();
});

Três tipos MIME têm suporte amplo nos aplicativos:

  • text/html:renderiza o payload HTML em elementos contentEditable e editores de texto (WYSIWYG), como o Google Docs, o Microsoft Word e outros.
  • text/plain: Define o valor dos elementos de entrada, o conteúdo dos editores de código e o substituto. a partir de text/html.
  • text/uri-list:navega para o URL ao soltar na barra de URL ou na página do navegador. Um URL será criado ao soltar em um diretório ou na área de trabalho.

A ampla adoção do text/html por editores WYSIWYG o torna muito útil. Como em HTML documentos, é possível incorporar recursos usando URLs de dados ou publicamente URLs acessíveis. Isso funciona bem com a exportação de recursos visuais (por exemplo, de uma tela) para editores como Documentos Google.

const redPixel = 'data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=';
const html = '<img src="' + redPixel + '" width="100" height="100" alt="" />';
event.dataTransfer.setData('text/html', html);

Transferir usando o recurso de copiar e colar

O uso da API DataTransfer com interações de copiar e colar é mostrado abaixo. Note que o objeto DataTransfer é retornado por uma propriedade com o nome clipboardData para eventos da área de transferência.

// Listen to copy-paste events on the document.
document.addEventListener('copy', (event) => {
  const copySource = document.querySelector('#copySource');
  // Only copy when the `activeElement` (i.e., focused element) is,
  // or is within, the `copySource` element.
  if (copySource.contains(document.activeElement)) {
    event.clipboardData.setData('text/plain', 'Foo bar');
    event.preventDefault();
  }
});

document.addEventListener('paste', (event) => {
  const pasteTarget = document.querySelector('#pasteTarget');
  if (pasteTarget.contains(document.activeElement)) {
    const data = event.clipboardData.getData('text/plain');
    console.log(data);
  }
});

Formatos de dados personalizados

Você não está limitado aos tipos MIME primitivos, mas pode usar qualquer chave para identificar os dados. Isso pode ser útil para interações entre navegadores no seu aplicativo. Conforme mostrado abaixo, pode transferir dados mais complexos usando as funções JSON.stringify() e JSON.parse().

document.querySelector('#dragSource')
.addEventListener('dragstart', (event) => {
  const data = { foo: 'bar' };
  event.dataTransfer.setData('my-custom-type', JSON.stringify(data));
});

document.querySelector('#dropTarget')
.addEventListener('dragover', (event) => {
  // Only allow dropping when our custom data is available.
  if (event.dataTransfer.types.includes('my-custom-type')) {
    event.preventDefault();
  }
});

document.querySelector('#dropTarget')
.addEventListener('drop', (event) => {
  if (event.dataTransfer.types.includes('my-custom-type')) {
    event.preventDefault();
    const dataString = event.dataTransfer.getData('my-custom-type');
    const data = JSON.parse(dataString);
    console.log(data);
  }
});

Conexão da Web

Embora os formatos personalizados sejam ótimos para a comunicação entre aplicativos que você tem sob seu controle, eles também limita o usuário ao transferir dados para aplicativos que não estão usando seu formato. Se você quiser se conectar a aplicativos de terceiros na web, você precisa de um formato de dados universal.

O padrão JSON-LD (dados vinculados) é um ótimo candidato para isso. É leve e fácil de ler e gravar em JavaScript. O Schema.org contém muitas tipos predefinidos que podem ser usados, e definições de esquemas personalizados também são uma opção.

const data = {
  '@context': 'https://schema.org',
  '@type': 'ImageObject',
  contentLocation: 'Venice, Italy',
  contentUrl: 'venice.jpg',
  datePublished: '2010-08-08',
  description: 'I took this picture during our honey moon.',
  name: 'Canal in Venice',
};
event.dataTransfer.setData('application/ld+json', JSON.stringify(data));

Ao usar os tipos schema.org, você pode começar com o tipo genérico Thing, ou algo mais próximo ao seu caso de uso, como Evento, Pessoa, MediaObject, Place ou até mesmo tipos altamente específicos, como MedicalEntity, se necessário. Com o TypeScript, você pode usar a de interface com base nas definições de tipo schema-dts.

Ao transmitir e receber dados JSON-LD, você apoiará uma Web mais aberta e conectada. Com aplicativos que falam a mesma linguagem, você pode criar integrações profundas com aplicativos conteinerizados. Não é preciso fazer integrações de API complicadas. todas as informações necessárias incluídos nos dados transferidos.

Pense em todas as possibilidades de transferência de dados entre qualquer aplicativo (Web) sem nenhuma restrições: compartilhar eventos de uma agenda com seu aplicativo de ToDo favorito, anexar arquivos virtuais ao e-mails, compartilhamento de contatos. Seria ótimo, certo? Isso começa com você! 🙌

Problemas

Embora a API DataTransfer já esteja disponível, há algumas coisas que você precisa considerar antes da integração.

Compatibilidade com navegadores

Todos os navegadores de desktop oferecem um ótimo suporte para a técnica descrita acima, enquanto os dispositivos móveis não não. A técnica foi testada em todos os principais navegadores (Chrome, Edge, Firefox, Safari) e sistemas operacionais (Android, ChromeOS, iOS, macOS, Ubuntu Linux e Windows), mas infelizmente Android e iOS não foram aprovados no teste. Embora os navegadores continuem a ser desenvolvidos, por enquanto, a técnica é limitada a navegadores de computador.

Facilidade de ser descoberto

Arrastar e soltar e copiar e colar são interações em nível de sistema ao trabalhar em um computador desktop, com desde as primeiras GUIs há mais de 40 anos. Pense em quantas vezes você tem usou essas interações para organizar arquivos. Isso ainda não é muito comum na Web.

Você precisará educar os usuários sobre essa nova interação e criar padrões de UX para torná-la reconhecíveis, especialmente para pessoas cuja experiência com computadores até agora está restrita a dispositivos móveis.

Acessibilidade

Arrastar e soltar não é uma interação muito acessível, mas a API DataTransfer também funciona com copiar e colar. Preste atenção aos eventos de copiar e colar. Isso não exige muito trabalho, e seus usuários ficará grato por adicioná-lo.

Segurança e privacidade

Há algumas considerações de segurança e privacidade que você precisa considerar ao usar a técnica.

  • Os dados da área de transferência ficam disponíveis para outros aplicativos no dispositivo do usuário.
  • Os aplicativos da Web que você está arrastando têm acesso às teclas de tipo, não aos dados. Somente os dados fica disponível ao soltar ou colar.
  • Os dados recebidos precisam ser tratados como qualquer outra entrada do usuário. higienizar e validar antes de usar.

Primeiros passos com a biblioteca auxiliar Transmat

Você está animado em usar a API DataTransfer em seu aplicativo? Confira o Biblioteca Transmat no GitHub. Essa biblioteca de código aberto alinha o navegador de armazenamento, oferece utilitários JSON-LD, contém um observador para responder a eventos de transferência para destacando áreas de soltar e permite integrar as operações de transferência de dados entre recursos de arrastar e soltar e implementações.

import { Transmat, TransmatObserver, addListeners } from 'transmat';

// Send data on drag/copy.
addListeners(myElement, 'transmit', (event) => {
  const transmat = new Transmat(event);
  transmat.setData({
    'text/plain': 'Foobar',
    'application/json': { foo: 'bar' },
  });
});

// Receive data on drop/paste.
addListeners(myElement, 'receive', (event) => {
  const transmat = new Transmat(event);
  if (transmat.hasType('application/json') && transmat.accept()) {
    const data = JSON.parse(transmat.getData('application/json'));
  }
});

// Observe transfer events and highlight drop areas.
const obs = new TransmatObserver((entries) => {
  for (const entry of entries) {
    const transmat = new Transmat(entry.event);
    if (transmat.hasMimeType('application/json')) {
      entry.target.classList.toggle('drag-over', entry.isTarget);
      entry.target.classList.toggle('drag-active', entry.isActive);
    }
  }
});
obs.observe(myElement);

Agradecimentos

Imagem principal de Luba Ertel no Abrir a página.