Supera los obstáculos con la API de DataTransfer

Permite que el usuario comparta datos más allá de la ventana del navegador.

Quizás hayas oído hablar de los API de DataTransfer, que es parte del API de HTML5 para arrastrar y soltar y eventos del Portapapeles. Puede usarse para transferir datos entre los destinos fuente y receptor.

Navegadores compatibles

  • Chrome: 3.
  • Límite: 12.
  • Firefox: 3.5
  • Safari: 4.

Origen

Las interacciones de arrastrar, soltar y copiar y pegar suelen usarse para las interacciones dentro de una página. para transferir texto simple de A a B. Pero lo que a menudo se pasa por alto es la capacidad de utilizar estas mismas interacciones para ir más allá de la ventana del navegador.

Tanto las interacciones de arrastrar y soltar integradas del navegador como las de copiar y pegar pueden comunicarse con otras aplicaciones, web o de otro tipo, y no están vinculadas a ningún origen. La API admite varias con diferentes comportamientos según dónde se transfieran los datos. Tu aplicación web puede enviar y recibir los datos transferidos cuando escucha eventos entrantes.

Esta capacidad puede cambiar nuestra forma de pensar sobre el uso compartido y la interoperabilidad en la Web en computadoras de escritorio. La transferencia de datos entre aplicaciones no depende de las integraciones con acoplamiento alto. En cambio, puedes darles a los usuarios control total para transferir a donde quiera que vayan.

Un ejemplo de las interacciones que son posibles con la API de DataTransfer. (El video no incluye sonido).

Cómo transferir datos

Para comenzar, implementa las funciones de arrastrar, soltar o copiar y pegar. Los ejemplos de abajo muestran interacciones de arrastrar y soltar, pero el proceso de copiar y pegar es similar. Si no conoces la API de arrastrar y soltar, hay un artículo excelente Explicación de arrastrar y soltar HTML5, que explica los pros y los contras

Cuando proporcionas datos con clave de tipo MIME, que puede interactuar libremente con aplicaciones externas. La mayoría de los editores, editores de texto y navegadores WYSIWYG responden a la respuesta los tipos de MIME utilizados en el ejemplo a continuación.

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');
});

Observa la propiedad event.dataTransfer. Esto muestra una instancia de DataTransfer Como Como verás, a veces las propiedades con otros nombres muestran este objeto.

Recibir la transferencia de datos funciona casi igual que proporcionarla. Escucha los eventos de recepción (drop o paste) y lee las claves. Al arrastrar un elemento, el navegador solo tiene acceso. a las claves type de los datos. Solo se puede acceder a los datos después de una acción 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();
});

Hay tres tipos de MIME ampliamente admitidos en todas las aplicaciones:

  • text/html: Renderiza la carga útil HTML en elementos contentEditable y enriquecidos de texto (WYSIWYG), como Google Docs, Microsoft Word y otros.
  • text/plain: Establece el valor de los elementos de entrada, el contenido de los editores de código y el resguardo. desde text/html.
  • text/uri-list: Navega a la URL cuando sueltas la barra de URL o la página del navegador. Una URL el acceso directo se creará al colocarte en un directorio o en el escritorio.

La adopción generalizada de text/html por los editores WYSIWYG la hace muy útil. Como en HTML en documentos, puedes incorporar recursos Data URLs o datos públicos URLs accesibles. Esto funciona bien con la exportación de imágenes (por ejemplo, desde un lienzo) a editores como Documentos de Google.

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

Cómo transferir mediante la función de copiar y pegar

A continuación, se muestra el uso de la API de DataTransfer con interacciones de copiar y pegar. Ten en cuenta que Una propiedad llamada clipboardData muestra el objeto DataTransfer para los eventos del portapapeles.

// 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 datos personalizados

No está limitado a los tipos MIME primitivos, pero puede usar cualquier clave para identificar de datos no estructurados. Esto puede ser útil para las interacciones entre navegadores dentro de tu aplicación. Como se muestra a continuación, Puedes transferir datos más complejos con las funciones JSON.stringify() y 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);
  }
});

Conexión a la Web

Si bien los formatos personalizados son ideales para la comunicación entre las aplicaciones que tienes bajo tu control, también limita al usuario cuando transfiere datos a aplicaciones que no utilizan tu formato. Si deseas para conectarte a aplicaciones de terceros en la Web, necesitas un formato de datos universal.

El estándar JSON-LD (datos vinculados) es un gran candidato para esto. Sí ligeros y fáciles de leer y escribir en JavaScript. Schema.org contiene muchas tipos predefinidos que se pueden usar y definiciones de esquemas personalizados también son una opción.

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));

Cuando usas los tipos de Schema.org, puedes comenzar con el tipo genérico Thing, o usa algo más cercano a tu caso de uso, como Event, Person, MediaObject, Place o incluso tipos muy específicos, como MedicalEntity si es necesario. Cuando usas TypeScript, puedes usar la Definiciones de interfaz de las definiciones de tipo de schema-dts.

Al transmitir y recibir datos JSON-LD, respaldarás una Web más conectada y abierta. Con aplicaciones que hablan el mismo idioma, puedes crear integraciones profundas con aplicaciones aplicaciones. No necesitas integraciones de API complicadas. toda la información que se necesita incluidos en los datos transferidos.

Piensa en todas las posibilidades de transferir datos entre cualquier aplicación (web) sin restricciones: compartir eventos de un calendario a tu aplicación favorita de Tareas pendientes, adjuntar archivos virtuales a correos electrónicos y compartir contactos. Sería genial, ¿verdad? ¡Comienza por ti! 🙌

Problemas

Si bien la API de DataTransfer está disponible en la actualidad, hay algunas cosas que debes tener en cuenta antes de realizar la integración.

Compatibilidad del navegador

Los navegadores de escritorio admiten una gran compatibilidad con la técnica descrita anteriormente, mientras que los dispositivos móviles sí no. La técnica se probó en todos los navegadores principales (Chrome, Edge, Firefox, Safari) y sistemas operativos (Android, ChromeOS, iOS, macOS, Ubuntu, Linux y Windows), pero lamentablemente y iOS no la pasó. Mientras los navegadores continúan desarrollándose, por ahora, la técnica es limitada. solo para navegadores de escritorio.

Visibilidad

Arrastrar, soltar y copiar y pegar son interacciones a nivel del sistema cuando se trabaja en una computadora, con sus raíces se remontan a las primeras GUI hace más de 40 años. Piensa cuántas veces tienes usaste estas interacciones para organizar los archivos. Todavía no es muy común en la Web.

Tendrás que educar a los usuarios sobre esta nueva interacción y idear patrones de UX para que sea reconocibles, especialmente para las personas cuya experiencia con computadoras hasta ahora se ha limitado a los dispositivos móviles.

Accesibilidad

La interacción de arrastrar y soltar no es muy accesible, pero la API de DataTransfer también funciona con la función de copiar y pegar. Asegúrate de escuchar los eventos de copiar y pegar. No requiere mucho trabajo adicional, y los usuarios estaremos agradecidos de que lo agregues.

Seguridad y privacidad

Hay algunas consideraciones de seguridad y privacidad que debes tener en cuenta al utilizar esta técnica.

  • Los datos del portapapeles están disponibles para otras aplicaciones en el dispositivo del usuario.
  • Las aplicaciones web que arrastras tienen acceso a las teclas de tipo, no a los datos. Solo los datos estará disponible al soltar o pegar.
  • Los datos recibidos deben tratarse como cualquier otra entrada del usuario. limpiar y validar antes de usarlos.

Comienza a usar la biblioteca de ayuda de Transmat

¿Te entusiasma usar la API de DataTransfer en tu aplicación? Considera echar un vistazo Biblioteca de Transmat en GitHub. Esta biblioteca de código abierto alinea el navegador diferencias, proporciona utilidades JSON-LD, contiene un observador para responder a eventos de transferencia para destacando las áreas de soltar, y te permite integrar las operaciones de transferencia de datos entre las funciones existentes de arrastrar y soltar de Google Cloud.

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);

Agradecimientos

Hero image de Luba Ertel en Retiro: