Consente all'utente di condividere 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 della clipboard. Può essere utilizzato per trasferire i dati tra la destinazione di origine e quella di destinazione.
Le interazioni di trascinamento e copia-incolla vengono spesso utilizzate per le interazioni all'interno di una pagina al fine di trasferire un testo semplice da A a B. Tuttavia, spesso viene trascurata la possibilità di utilizzare queste stesse interazioni per andare oltre la finestra del browser.
Sia le interazioni di trascinamento e rilascio integrate del browser sia le interazioni di copia e incolla possono comunicare con altre applicazioni, web o di altro tipo, e non sono legate a nessuna 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 ascolta gli eventi in arrivo.
Questa funzionalità può cambiare il nostro modo di pensare alla condivisione e all'interoperabilità nelle applicazioni web su computer. Il trasferimento dei dati tra le applicazioni non richiede più l'uso di integrazioni a stretto accoppiamento. In alternativa, puoi dare agli utenti il controllo completo per trasferire i dati dove vogliono.
Trasferimento di dati
Per iniziare, dovrai implementare il trascinamento o il copia e incolla. Gli esempi riportati di seguito mostrano le interazioni tramite trascinamento, ma la procedura per il copia e incolla è simile. Se non hai dimestichezza con l'API Drag and Drop, consulta un ottimo articolo che spiega il trascinamento HTML5, che illustra tutti i dettagli.
Fornendo dati con chiave di tipo MIME 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');
});
Osserva la proprietà event.dataTransfer
. Viene restituita un'istanza di
DataTransfer
. Come vedrai, a volte questo oggetto viene restituito da proprietà con altri nomi.
La ricezione del trasferimento dei dati funziona quasi come la relativa impostazione. 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 sono accessibili solo dopo un rilascio.
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 elementicontentEditable
e negli editor di testo avanzato (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 valore di riserva datext/html
.text/uri-list
: consente di passare all'URL quando lo inserisci nella barra degli URL o nella pagina del browser. Una scorciatoia per l'URL viene creata quando si passa da una directory o dal desktop.
L'adozione diffusa di text/html
da parte degli editor WYSIWYG lo rende molto utile. Come nei documenti HTML, puoi incorporare le risorse utilizzando URL di dati o URL accessibili pubblicamente. Questo metodo funziona bene con l'esportazione di elementi visivi (ad esempio da una tela) 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);
Trasferimento tramite copia e incolla
Di seguito è riportato un esempio di 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 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 sei limitato 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 in corso...
Sebbene i formati personalizzati siano ideali per la comunicazione tra le applicazioni che hai sotto controllo, limita 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.
A questo scopo, lo standard JSON-LD (Linked Data) è un ottimo candidato. È leggero e facile da leggere e scrivere in JavaScript. Schema.org contiene molti tipi predefiniti che possono essere utilizzati, nonché 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 Thing generico o utilizzare qualcosa di più simile al tuo caso d'uso come Event, Person, MediaObject, Place o anche tipi altamente specifici come MedicalEntity, se necessario. Quando utilizzi TypeScript, puoi utilizzare le definizioni di interfaccia contenute nelle definizioni di tipo schema-dts.
Trasmettendo e ricevendo i dati JSON-LD, supporterai un web più connesso e aperto. Con le applicazioni che parlano la stessa lingua, puoi creare integrazioni approfondite con applicazioni esterne. Non sono necessarie integrazioni complicate delle API; tutte le informazioni necessarie sono incluse nei dati trasferiti.
Pensa a tutte le possibilità di trasferire i dati tra qualsiasi applicazione (web) senza limitazioni: condivisione di eventi da un calendario alla tua app di Attività preferita, collegamento di file virtuali a email e condivisione di contatti. Sarebbe fantastico, giusto? Inizia da te. 🙌
Problemi
Sebbene l'API DataTransfer sia disponibile già da oggi, ci sono alcuni aspetti da tenere presenti prima dell'integrazione.
Compatibilità del browser
I browser desktop supportano tutti la tecnica descritta in precedenza, a differenza 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 sfortunatamente Android e iOS non hanno superato il test. Mentre i browser continuano a svilupparsi, per ora la tecnica è limitata solo ai browser desktop.
Visibilità
Le operazioni di trascinamento e copia-incolla sono interazioni a livello di sistema eseguite su un computer desktop e risalgono a più di 40 anni fa grazie alle prime GUI. Pensa a quante volte hai usato queste interazioni per organizzare i file. Questo non è ancora molto comune sul web.
Dovrai informare gli utenti di questa nuova interazione e creare pattern di 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 ringrazieranno per averlo aggiunto.
Sicurezza e privacy
Quando utilizzi questa tecnica, devi tenere conto di alcune considerazioni relative alla sicurezza e alla privacy.
- I dati degli appunti sono disponibili per altre applicazioni sul dispositivo dell'utente.
- Le applicazioni web che stai trascinando hanno accesso ai tasti di digitazione, non ai dati. I dati diventano disponibili solo trascinati o incollati.
- I dati ricevuti devono essere trattati come qualsiasi altro input utente; sottoponili a sanificazione e convalida prima dell'utilizzo.
Iniziare a utilizzare la libreria di assistenza Transmat
Ti entusiasma l'idea di utilizzare l'API DataTransfer nella tua applicazione? Valuta la possibilità di consultare la libreria Transmat su GitHub. Questa libreria open source allinea le differenze dei 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 di 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.