Abbattere le barriere con l'API DataTransfer

Consente all'utente di condividere dati oltre la finestra del browser.

Probabilmente hai già sentito parlare dell'API DataTransfer, che fa parte dell'API HTML5 Drag and Drop e degli eventi per appunti. Può essere utilizzato per trasferire dati tra l'origine e le destinazioni riceventi.

Supporto dei browser

  • 3
  • 12
  • 3,5
  • 4

Fonte

Le interazioni di trascinamento e copia e incolla vengono spesso utilizzate per le interazioni all'interno di una pagina al fine di trasferire un testo semplice da A a B. Spesso, però, viene trascurata la possibilità di utilizzare queste stesse interazioni per andare oltre la finestra del browser.

Le interazioni di trascinamento integrate e di copia e incolla del browser possono comunicare con altre applicazioni, sul web o di altro tipo e non sono collegate ad alcuna origine. L'API supporta più voci di dati con comportamenti diversi in base a dove vengono trasferiti i dati. L'applicazione web può inviare e ricevere i dati trasferiti quando ascolti gli eventi in arrivo.

Questa funzionalità può cambiare il nostro modo di concepire la condivisione e l'interoperabilità nelle applicazioni web su desktop. Il trasferimento di dati tra applicazioni non deve più fare affidamento su integrazioni a stretto accoppiamento. Potete invece dare agli utenti il controllo completo per trasferire i dati dove vogliono.

Un esempio di interazioni possibili con l'API DataTransfer. Il video non include l'audio.

Trasferimento di dati

Per iniziare, dovrai implementare il trascinamento o il copia e incolla. Gli esempi riportati di seguito mostrano le interazioni con trascinamento, ma la procedura per il copia e incolla è simile. Se non hai dimestichezza con l'API Drag and Drop, leggi l'articolo che spiega la funzionalità di trascinamento di HTML5, in cui vengono illustrati i trucchi del mestiere.

Se fornisci dati con chiave di tipo MIME, puoi interagire liberamente con le applicazioni esterne. La maggior parte degli editor di testo, dei browser e degli editor di testo WYSIWYG risponde ai tipi MIME "primitivi" utilizzati nell'esempio riportato di seguito.

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

Osserva la proprietà event.dataTransfer. Questa operazione restituisce un'istanza di DataTransfer. Come vedrai, a volte questo oggetto viene restituito da proprietà con altri nomi.

La ricezione del trasferimento di dati funziona quasi come il trasferimento. Ascolta gli eventi di ricezione (drop o paste) e leggi i tasti. Quando trascini un elemento, il browser ha accesso solo ai tasti type dei dati. È possibile accedere ai dati solo dopo un calo.

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

Tre tipi MIME sono ampiamente supportati nelle diverse applicazioni:

  • text/html: esegue il rendering del payload HTML negli elementi contentEditable e negli editor RTF (WYSIWYG) come Documenti Google, Microsoft Word e altri.
  • text/plain: Imposta il valore degli elementi di input, i contenuti degli editor di codice e il fallback di text/html.
  • text/uri-list: consente di accedere all'URL quando viene rilasciato nella barra degli URL o nella pagina del browser. Verrà creata una scorciatoia URL quando esegui il rilascio in una directory o sul desktop.

L'adozione diffusa di text/html da parte degli editor WYSIWYG lo rende molto utile. Come nei documenti HTML, puoi incorporare risorse utilizzando URL di dati o URL accessibili pubblicamente. Questo metodo funziona bene con l'esportazione di immagini (ad esempio da un canvas) in editor come Documenti Google.

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

Trasferisci tramite copia e incolla

Di seguito è riportato l'utilizzo dell'API DataTransfer con le interazioni di copia e incolla. Nota che l'oggetto DataTransfer viene restituito da una proprietà chiamata clipboardData per gli eventi degli appunti.

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

Formati di dati personalizzati

Non puoi limitarti ai tipi MIME primitivi, ma puoi utilizzare qualsiasi chiave per identificare i dati trasferiti. Questo può essere utile per le interazioni tra browser all'interno della tua applicazione. Come mostrato di seguito, puoi trasferire dati più complessi utilizzando le funzioni 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);
  }
});

Connessione al web

Sebbene siano ottimi per la comunicazione tra le applicazioni che hai tu sotto controllo, i formati personalizzati limitano anche l'utilizzo da parte dell'utente quando trasferiscono dati ad applicazioni che non utilizzano il tuo formato. Se vuoi connetterti con applicazioni di terze parti sul web, hai bisogno di un formato dati universale.

Lo standard JSON-LD (Linked Data) è perfetto per questo scopo. È leggero e di facile lettura e scrittura in JavaScript. Schema.org contiene molti tipi predefiniti che possono essere utilizzati, oltre alle definizioni di schemi personalizzati.

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

Quando utilizzi i tipi di Schema.org, puoi iniziare con il tipo generico Thing o utilizzare qualcosa di più simile al tuo caso d'uso, come Event, Person, MediaObject, Place o persino tipi altamente specifici come MedicalEntity, se necessario. Quando usi TypeScript, puoi usare le definizioni dell'interfaccia delle definizioni dei tipi schema-dts.

Trasmettendo e ricevendo dati JSON-LD, supporterai un web più connesso e aperto. Con applicazioni che parlano la stessa lingua, puoi creare integrazioni profonde con applicazioni esterne. Non sono necessarie complesse integrazioni dell'API; tutte le informazioni necessarie sono incluse nei dati trasferiti.

Pensa a tutte le possibilità di trasferire dati tra qualsiasi applicazione (web) senza limitazioni: condivisione di eventi da un calendario alla tua app Da fare preferita, allegato file virtuali alle email, condivisione dei contatti. Sarebbe fantastico, vero? Inizia da te. 🙌

Problemi

Sebbene l'API DataTransfer sia già disponibile, ci sono alcuni aspetti da conoscere prima dell'integrazione.

Compatibilità del browser

I browser desktop supportano tutti la tecnica descritta sopra, al contrario dei dispositivi mobili. La tecnica è stata testata su tutti i principali browser (Chrome, Edge, Firefox, Safari) e i sistemi operativi (Android, ChromeOS, iOS, macOS, Ubuntu Linux e Windows), ma purtroppo Android e iOS non hanno superato il test. Sebbene i browser continuino a svilupparsi, per il momento la tecnica è limitata ai solo browser desktop.

Visibilità

Il trascinamento e il copia e incolla sono interazioni a livello di sistema quando si lavora su un computer desktop, con le radici alle prime GUI più di 40 anni fa. Pensa a quante volte hai usato queste interazioni per organizzare i file. Ciò non è ancora molto comune sul web.

Dovrai informare gli utenti riguardo a questa nuova interazione e definire modelli di UX che rendano riconoscibili questa novità, soprattutto per le persone la cui esperienza con i computer finora è stata limitata ai dispositivi mobili.

Accessibilità

Il trascinamento non è un'interazione molto accessibile, ma l'API DataTransfer funziona anche con il copia-incolla. Assicurati di ascoltare gli eventi di copia e incolla. Non richiede molto lavoro aggiuntivo e i tuoi utenti ti saranno grati per averlo aggiunto.

Sicurezza e privacy

Quando utilizzi questa tecnica, devi tenere presenti alcuni aspetti sulla sicurezza e sulla privacy.

  • I dati degli appunti sono disponibili per altre applicazioni sul dispositivo dell'utente.
  • Le applicazioni web su cui stai eseguendo il trascinamento hanno accesso ai tasti del tipo, non ai dati. I dati diventano disponibili solo se vengono trascinati o incollati.
  • I dati ricevuti devono essere trattati come qualsiasi altro input utente; deve essere sottoposto a sanitizzazione e convalida prima dell'utilizzo.

Introduzione alla libreria di supporto Transmat

Sei entusiasta di utilizzare l'API DataTransfer nella tua applicazione? Potresti dare un'occhiata alla libreria Transmat su GitHub. Questa libreria open source allinea le differenze del browser, fornisce utilità JSON-LD, contiene un osservatore per rispondere agli eventi di trasferimento per evidenziare le aree di rilascio e consente di integrare le operazioni di trasferimento dati tra le implementazioni di trascinamento esistenti.

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

Ringraziamenti

Immagine hero di Luba Ertel su Unsplash.