Surmonter les obstacles avec l'API DataTransfer

Permettre à l'utilisateur de partager des données au-delà de la fenêtre du navigateur

Vous avez peut-être entendu parler de l'API DataTransfer, qui fait partie de l'API de glisser-déposer HTML5 et des événements du presse-papiers. Il peut être utilisé pour transférer des données entre les cibles source et réceptrice.

Navigateurs pris en charge

  • 3
  • 12
  • 3,5
  • 4

Source

Les interactions glisser-déposer et copier-coller sont souvent utilisées pour les interactions au sein d'une page afin de transférer du texte simple d'un point A à un point B. Mais ce qui est souvent négligé, c'est la possibilité d'utiliser ces mêmes interactions au-delà de la fenêtre du navigateur.

Les fonctionnalités de glisser-déposer et de copier-coller intégrées au navigateur peuvent communiquer avec d'autres applications, qu'elles soient sur le Web ou non, et ne sont liées à aucune origine. L'API accepte plusieurs entrées de données avec des comportements différents en fonction de l'emplacement vers lequel les données sont transférées. Votre application Web peut envoyer et recevoir les données transférées lors de l'écoute d'événements entrants.

Cette fonctionnalité peut changer notre vision du partage et de l'interopérabilité dans les applications Web sur ordinateur. Le transfert de données entre les applications n'a plus besoin de s'appuyer sur des intégrations étroitement couplées. Au lieu de cela, vous pouvez donner aux utilisateurs le contrôle total pour transférer leurs données vers l'emplacement de leur choix.

Exemple d'interactions possibles avec l'API DataTransfer. (La vidéo n'inclut pas de son.)

Transfert des données

Pour commencer, vous devez activer le glisser-déposer ou le copier-coller. Les exemples ci-dessous illustrent des interactions par glisser-déposer, mais le processus de copier-coller est similaire. Si vous ne connaissez pas l'API de glisser-déposer, vous pouvez consulter l'article qui explique en quoi consiste la fonctionnalité Glisser-déposer HTML5 dans les moindres détails.

En fournissant des données appariées par type MIME, vous pouvez interagir librement avec des applications externes. La plupart des éditeurs WYSIWYG, des éditeurs de texte et des navigateurs répondent aux types MIME "primitifs" utilisés dans l'exemple ci-dessous.

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

Notez la propriété event.dataTransfer. Cette opération renvoie une instance de DataTransfer. Comme vous le verrez, cet objet est parfois renvoyé par des propriétés portant d'autres noms.

La réception du transfert de données fonctionne presque de la même manière que la transmission. Écoutez les événements de réception (drop ou paste) et lisez les touches. Lorsque vous faites glisser un élément, le navigateur n'a accès qu'aux clés type des données. Les données elles-mêmes ne sont accessibles qu'après une suppression.

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

Trois types MIME sont largement pris en charge dans les applications:

  • text/html:affiche la charge utile HTML dans des éléments contentEditable et des éditeurs de texte enrichi (WYSIWYG) tels que Google Docs, Microsoft Word, etc.
  • text/plain: Définit la valeur des éléments d'entrée, du contenu des éditeurs de code et de la création de remplacement à partir de text/html.
  • text/uri-list:accède à l'URL lors d'un passage dans la barre d'adresse ou sur la page du navigateur. Un raccourci d'URL est créé lors de la suppression sur un répertoire ou sur le bureau.

L'adoption généralisée de text/html par les éditeurs WYSIWYG le rend très utile. Comme pour les documents HTML, vous pouvez intégrer des ressources à l'aide d'URL de données ou d'URL accessibles au public. Cette méthode est idéale pour exporter des visuels (par exemple, à partir d'un canevas) vers des éditeurs tels que Google Docs.

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

Transférer des données à l'aide d'un copier-coller

L'utilisation de l'API DataTransfer avec des interactions copier-coller est présentée ci-dessous. Notez que l'objet DataTransfer est renvoyé par une propriété appelée clipboardData pour les événements du presse-papiers.

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

Formats de données personnalisés

Vous n'êtes pas limité aux types MIME primitifs, mais vous pouvez utiliser n'importe quelle clé pour identifier les données transférées. Cela peut s'avérer utile pour les interactions entre navigateurs au sein de votre application. Comme indiqué ci-dessous, vous pouvez transférer des données plus complexes à l'aide des fonctions JSON.stringify() et 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);
  }
});

Connecter le Web

Bien que les formats personnalisés soient parfaits pour la communication entre les applications que vous contrôlez, ils limitent également l'utilisateur lors du transfert de données vers des applications qui n'utilisent pas votre format. Si vous souhaitez vous connecter à des applications tierces sur le Web, vous avez besoin d'un format de données universel.

La norme JSON-LD (données liées) est parfaitement adaptée à ce processus. Il est léger, et il est facile à lire et à écrire en JavaScript. Schema.org contient de nombreux types prédéfinis que vous pouvez utiliser. Les définitions de schémas personnalisés sont également disponibles.

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

Lorsque vous utilisez les types Schema.org, vous pouvez commencer par le type générique Thing, ou utiliser un élément plus proche de votre cas d'utilisation, comme Event, Person, MediaObject, Place, ou même des types très spécifiques tels que MedicalEntity, si nécessaire. Lorsque vous utilisez TypeScript, vous pouvez vous servir des définitions d'interface des définitions de type schema-dts.

En transmettant et en recevant des données JSON-LD, vous contribuerez à un Web plus connecté et plus ouvert. Lorsque les applications parlent le même langage, vous pouvez créer des intégrations avancées avec des applications externes. Il n'est pas nécessaire d'intégrer des API complexes. Toutes les informations nécessaires sont incluses dans les données transférées.

Réfléchissez à toutes les possibilités de transfert de données entre n'importe quelle application (Web) sans restriction: partage d'événements d'un agenda vers votre application ToDo préférée, ajout de fichiers virtuels à des e-mails, partage de contacts. Ce serait super, non ? Cela commence par vous ! 🙌

Problèmes

Bien que l'API DataTransfer soit disponible aujourd'hui, vous devez prendre en compte certains points avant l'intégration.

Compatibilité du navigateur

Les navigateurs pour ordinateur sont tous compatibles avec la technique décrite ci-dessus, contrairement aux appareils mobiles. Cette technique a été testée sur la plupart des navigateurs (Chrome, Edge, Firefox et Safari) et des systèmes d'exploitation (Android, ChromeOS, iOS, macOS, Ubuntu Linux et Windows). Malheureusement, Android et iOS n'ont pas réussi le test. Bien que les navigateurs continuent de se développer, la technique est pour le moment limitée aux navigateurs pour ordinateur.

Visibilité

Le glisser-déposer et le copier-coller sont des interactions au niveau du système lorsque vous travaillez sur un ordinateur de bureau, avec des racines remontant aux premières IUG il y a plus de 40 ans. Pensez au nombre de fois où vous avez utilisé ces interactions pour organiser les fichiers. Cela n'est pas encore très courant sur le Web.

Vous devrez informer les utilisateurs de cette nouvelle interaction et créer des modèles d'expérience utilisateur pour la rendre reconnaissable, en particulier pour les personnes dont l'expérience avec les ordinateurs a jusqu'à présent été limitée aux appareils mobiles.

Accessibilité

Le glisser-déposer n'est pas une interaction très accessible, mais l'API DataTransfer fonctionne également avec le copier-coller. Veillez à écouter les événements copier-coller. Cela ne demande pas beaucoup de travail supplémentaire, et vos utilisateurs vous en remercieront.

Sécurité et confidentialité

Lorsque vous utilisez cette technique, vous devez tenir compte de certains points de sécurité et de confidentialité.

  • Les données du presse-papiers sont disponibles pour d'autres applications sur l'appareil de l'utilisateur.
  • Les applications Web que vous déplacez ont accès aux touches de type, et non aux données. Les données ne sont disponibles que lors d'un copier-coller.
  • Les données reçues doivent être traitées comme toute autre entrée utilisateur ; nettoyez et validez avant d’utiliser.

Premiers pas avec la bibliothèque d'aide Transmat

Êtes-vous impatient d'utiliser l'API DataTransfer dans votre application ? Consultez la bibliothèque Transmat sur GitHub. Cette bibliothèque Open Source aligne les différences entre les navigateurs, fournit des utilitaires JSON-LD, contient un observateur qui répond aux événements de transfert pour mettre en surbrillance les zones de dépôt et vous permet d'intégrer les opérations de transfert de données aux implémentations de glisser-déposer existantes.

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

Remerciements

Image principale par Luba Ertel sur Unsplash.