Consente all'utente di condividere i dati al di fuori della finestra del browser.
Potresti aver sentito parlare dell'API DataTransfer, che fa parte dell'API HTML5 Drag and Drop e degli eventi degli Appunti. Può essere utilizzato per trasferire dati tra le origini e le destinazioni di ricezione.
Le interazioni di trascinamento e copia-incolla vengono spesso utilizzate per le interazioni all'interno di una pagina per trasferire testo semplice da A a B. Ma ciò che spesso viene trascurato è la possibilità di utilizzare queste stesse interazioni per andare oltre la finestra del browser.
Sia il trascinamento della selezione integrato nel browser sia le interazioni di copia e incolla possono comunicare con altre applicazioni, web o di altro tipo, e non sono vincolate ad alcuna origine. L'API supporta più voci di dati con comportamenti diversi a seconda della destinazione del trasferimento dei dati. La tua applicazione web può inviare e ricevere i dati trasferiti quando è in ascolto degli eventi in entrata.
Questa funzionalità può cambiare il modo in cui pensiamo alla condivisione e all'interoperabilità nelle applicazioni web su computer. Il trasferimento di dati tra le applicazioni non deve più basarsi su integrazioni strettamente accoppiate. Puoi invece dare agli utenti il controllo completo per trasferire i dati dove preferiscono.
Trasferimento di dati
Per iniziare, devi implementare il trascinamento o il copia e incolla. Gli esempi di seguito mostrano le interazioni di trascinamento, ma la procedura di copia e incolla è simile. Se non hai familiarità con l'API Drag and Drop, c'è un ottimo articolo che spiega il drag and drop HTML5, che ne illustra i dettagli.
Fornendo dati con chiave MIME-type, puoi interagire liberamente con applicazioni esterne. La maggior parte degli editor WYSIWYG, degli editor di testo e dei browser 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');
});
Nota la proprietà event.dataTransfer. Viene restituita un'istanza di
DataTransfer. Come
vedrai, questo oggetto a volte viene restituito da proprietà con altri nomi.
La ricezione del trasferimento dei dati funziona quasi allo stesso modo della fornitura. Ascolta gli eventi di ricezione
(drop o paste) e leggi le chiavi. Quando trascini un elemento, il browser ha accesso
solo alle chiavi type dei dati. I dati stessi possono essere accessibili solo dopo una caduta.
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 applicazioni:
text/html: esegue il rendering del payload HTML negli elementicontentEditablee negli editor di testo RTF (WYSIWYG) come Documenti Google, Microsoft Word e altri.text/plain:Imposta il valore degli elementi di input, il contenuto degli editor di codice e il fallback datext/html.text/uri-list: passa all'URL quando lo rilasci nella barra degli URL o nella pagina del browser. Quando rilasci un URL su una directory o sul desktop, viene creato un collegamento.
La sua ampia adozione da parte degli editor WYSIWYG lo rende molto utile.text/html Come nei documenti HTML, puoi incorporare risorse utilizzando URL di dati o URL accessibili pubblicamente. Questa operazione è ideale per esportare elementi visivi (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);
Trasferire utilizzando copia e incolla
Di seguito viene mostrato l'utilizzo dell'API DataTransfer con le interazioni di copia e incolla. Tieni presente che l'oggetto DataTransfer viene restituito da una proprietà denominata 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 dati personalizzati
Non sei limitato ai tipi MIME primitivi, ma puoi utilizzare qualsiasi chiave per identificare i dati trasferiti. Ciò può essere utile per le interazioni cross-browser all'interno dell'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);
}
});
Connettere il web
Sebbene i formati personalizzati siano ideali per la comunicazione tra le applicazioni che controlli, limitano anche l'utente durante il trasferimento dei dati ad applicazioni che non utilizzano il tuo formato. Se vuoi connetterti con applicazioni di terze parti sul web, hai bisogno di un formato di dati universale.
Lo standard JSON-LD (Linked Data) è un ottimo candidato per questo scopo. È leggero e facile da leggere e scrivere in JavaScript. Schema.org contiene molti tipi predefiniti che possono essere utilizzati e le definizioni di schema personalizzate sono un'opzione.
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ù vicino al tuo caso d'uso, come Event, Person, MediaObject, Place o anche tipi molto specifici come MedicalEntity, se necessario. Quando utilizzi TypeScript, puoi utilizzare le definizioni di interfaccia dalle definizioni di tipo schema-dts.
Trasmettendo e ricevendo dati JSON-LD, contribuirai a un web più connesso e aperto. Con applicazioni che parlano la stessa lingua, puoi creare integrazioni avanzate con applicazioni esterne. Non sono necessarie integrazioni API complicate: tutte le informazioni necessarie sono incluse nei dati trasferiti.
Pensa a tutte le possibilità di trasferire dati tra qualsiasi applicazione (web) senza limitazioni: condividere eventi da un calendario alla tua app di cose da fare preferita, allegare file virtuali alle email, condividere contatti. Sarebbe fantastico, no? Tutto inizia da te. 🙌
Problemi
Sebbene l'API DataTransfer sia disponibile oggi, ci sono alcuni aspetti da tenere presenti prima dell'integrazione.
Compatibilità del browser
Tutti i browser desktop supportano perfettamente la tecnica descritta sopra, mentre i dispositivi mobili no. La tecnica è stata testata su tutti i principali browser (Chrome, Edge, Firefox, Safari) e sistemi operativi (Android, ChromeOS, iOS, macOS, Ubuntu Linux e Windows), ma purtroppo Android e iOS non hanno superato il test. Mentre i browser continuano a svilupparsi, per ora la tecnica è limitata ai soli browser desktop.
Visibilità
Il trascinamento e il copia-incolla sono interazioni a livello di sistema quando si lavora su un computer desktop, con radici che risalgono alle prime GUI più di 40 anni fa. Pensa a quante volte hai utilizzato queste interazioni per organizzare i file. Questa operazione non è ancora molto comune sul web.
Dovrai informare gli utenti di questa nuova interazione e ideare pattern UX per renderla riconoscibile, 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 e 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
Esistono alcune considerazioni sulla sicurezza e sulla privacy di cui devi essere a conoscenza quando utilizzi la tecnica.
- I dati degli appunti sono disponibili per altre applicazioni sul dispositivo dell'utente.
- Le applicazioni web che trascini hanno accesso alle chiavi di tipo, non ai dati. I dati diventano disponibili solo quando vengono rilasciati o incollati.
- I dati ricevuti devono essere trattati come qualsiasi altro input dell'utente: sanificali e convalidali prima di utilizzarli.
Iniziare a utilizzare la libreria helper Transmat
Non vedi l'ora di utilizzare l'API DataTransfer nella tua applicazione? Ti consigliamo di dare un'occhiata alla libreria Transmat su GitHub. Questa libreria open source allinea le differenze tra i 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 dei 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.