Memungkinkan pengguna berbagi data di luar jendela browser.
Anda mungkin pernah mendengar tentang DataTransfer API, yang merupakan bagian dari HTML5 Drag and Drop API dan Peristiwa papan klip. Fungsi ini dapat digunakan untuk mentransfer data antara sumber dan target penerima.
Interaksi tarik lalu lepas dan salin-tempel sering digunakan untuk interaksi dalam halaman untuk mentransfer teks sederhana dari A ke B. Namun, yang sering kali diabaikan adalah kemampuan untuk menggunakan interaksi yang sama ini untuk melampaui jendela browser.
Interaksi tarik lalu lepas bawaan browser dan interaksi salin-tempel dapat berkomunikasi dengan aplikasi lain, web, atau lainnya, dan tidak terikat dengan asal apa pun. API mendukung beberapa entri data dengan perilaku yang berbeda berdasarkan tujuan transfer data. Aplikasi web Anda dapat mengirim dan menerima data yang ditransfer saat memproses peristiwa yang masuk.
Kemampuan ini dapat mengubah cara berpikir kita tentang berbagi dan interoperabilitas dalam aplikasi web di desktop. Mentransfer data antar-aplikasi tidak perlu lagi bergantung pada integrasi yang dikaitkan secara erat. Sebagai gantinya, Anda dapat memberi pengguna kontrol penuh untuk mentransfer data ke mana pun mereka suka.
Mentransfer data
Untuk memulai, Anda harus menerapkan tarik lalu lepas atau salin lalu tempel. Contoh di bawah ini menunjukkan interaksi tarik lalu lepas, tetapi proses untuk salin-tempel serupa. Jika Anda belum terbiasa dengan API Tarik lalu Lepas, ada artikel bagus yang menjelaskan Tarik lalu Lepas HTML5, yang menjelaskan seluk beluknya.
Dengan menyediakan data yang terkunci jenis MIME, Anda dapat bebas berinteraksi dengan aplikasi eksternal. Sebagian besar editor WYSIWYG, editor teks, dan browser merespons jenis mime "primitif" yang digunakan dalam contoh di bawah.
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');
});
Perhatikan properti event.dataTransfer
. Tindakan ini akan menampilkan instance
DataTransfer
. Seperti
yang akan Anda lihat, objek ini terkadang ditampilkan oleh properti dengan nama lain.
Cara kerja penerimaan transfer data hampir sama dengan menyediakannya. Proses peristiwa penerima
(drop
, atau paste
) dan baca kunci. Saat menarik elemen, browser hanya memiliki akses
ke kunci type
data. Data itu sendiri hanya dapat diakses setelah pelepasan.
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();
});
Tiga jenis MIME didukung secara luas di seluruh aplikasi:
text/html
: Merender payload HTML di elemencontentEditable
dan editor rich text (WYSIWYG) seperti Google Dokumen, Microsoft Word, dan lainnya.text/plain:
Menetapkan nilai elemen input, konten editor kode, dan penggantian daritext/html
.text/uri-list
: Membuka URL saat membuka kolom URL atau halaman browser. Pintasan URL akan dibuat saat membuka direktori atau desktop.
Penerapan text/html
yang luas oleh editor WYSIWYG membuatnya sangat berguna. Seperti dalam dokumen HTML, Anda dapat menyematkan resource menggunakan URL Data atau URL yang dapat diakses secara publik. Hal ini berfungsi dengan baik saat mengekspor visual (misalnya dari kanvas) ke editor seperti Google Dokumen.
const redPixel = 'data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=';
const html = '<img src="' + redPixel + '" width="100" height="100" alt="" />';
event.dataTransfer.setData('text/html', html);
Transfer menggunakan salin dan tempel
Penggunaan DataTransfer API dengan interaksi salin-tempel ditunjukkan di bawah. Perhatikan bahwa
objek DataTransfer
ditampilkan oleh properti yang disebut clipboardData
untuk peristiwa papan klip.
// 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);
}
});
Format data kustom
Anda tidak dibatasi pada jenis MIME primitif, tetapi dapat menggunakan kunci apa pun untuk mengidentifikasi data yang ditransfer. Hal ini dapat berguna untuk interaksi lintas browser dalam aplikasi Anda. Seperti yang ditunjukkan di bawah ini, Anda dapat mentransfer data yang lebih kompleks menggunakan fungsi JSON.stringify()
dan 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);
}
});
Menghubungkan web
Meskipun format kustom sangat cocok untuk komunikasi antar-aplikasi yang Anda kontrol, format tersebut juga membatasi pengguna saat mentransfer data ke aplikasi yang tidak menggunakan format Anda. Jika ingin terhubung dengan aplikasi pihak ketiga di seluruh web, Anda memerlukan format data universal.
Standar JSON-LD (Data Tertaut) adalah kandidat yang tepat untuk hal ini. JSON bersifat ringan dan mudah dibaca serta ditulis dalam JavaScript. Schema.org berisi banyak jenis standar yang dapat digunakan, dan definisi skema kustom juga merupakan opsi.
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));
Saat menggunakan jenis Schema.org, Anda dapat memulai dengan jenis Thing generik, atau menggunakan sesuatu yang lebih dekat dengan kasus penggunaan Anda seperti Event, Person, MediaObject, Place, atau bahkan jenis yang sangat spesifik seperti MedicalEntity jika diperlukan. Saat menggunakan TypeScript, Anda dapat menggunakan definisi antarmuka dari definisi jenis schema-dts.
Dengan mengirim dan menerima data JSON-LD, Anda akan mendukung web yang lebih terhubung dan terbuka. Dengan aplikasi yang menggunakan bahasa yang sama, Anda dapat membuat integrasi mendalam dengan aplikasi eksternal. Tidak perlu integrasi API yang rumit; semua informasi yang diperlukan disertakan dalam data yang ditransfer.
Pikirkan semua kemungkinan untuk mentransfer data antara aplikasi (web) apa pun tanpa batasan: berbagi acara dari kalender ke aplikasi ToDo favorit Anda, melampirkan file virtual ke email, berbagi kontak. Bagus bukan? Semuanya dimulai dari Anda. 🙌
Masalah
Meskipun DataTransfer API tersedia saat ini, ada beberapa hal yang perlu diperhatikan sebelum melakukan integrasi.
Kompatibilitas browser
Semua browser desktop memiliki dukungan yang baik untuk teknik yang dijelaskan di atas, sedangkan perangkat seluler tidak. Teknik ini telah diuji di semua browser utama (Chrome, Edge, Firefox, Safari) dan sistem operasi (Android, ChromeOS, iOS, macOS, Ubuntu Linux, dan Windows), tetapi sayangnya Android dan iOS tidak lulus pengujian. Meskipun browser terus berkembang, untuk saat ini teknik ini terbatas untuk browser desktop saja.
Visibilitas
Tarik-lepas dan salin-tempel adalah interaksi tingkat sistem saat bekerja di komputer desktop, dengan root kembali ke GUI pertama lebih dari 40 tahun yang lalu. Pikirkan berapa kali Anda menggunakan interaksi ini untuk mengatur file. Ini belum terlalu umum di web.
Anda perlu mengedukasi pengguna tentang interaksi baru ini, dan menemukan pola UX agar hal ini dapat dikenali, terutama bagi orang yang pengalamannya dengan komputer sejauh ini hanya terbatas pada perangkat seluler.
Aksesibilitas
Tarik lalu lepas bukanlah interaksi yang sangat mudah diakses, tetapi DataTransfer API juga berfungsi dengan salin-tempel. Pastikan Anda memproses peristiwa salin-tempel. Anda tidak perlu melakukan banyak hal, dan pengguna akan berterima kasih karena Anda sudah menambahkannya.
Keamanan dan privasi
Ada beberapa pertimbangan keamanan dan privasi yang harus Anda perhatikan saat menggunakan teknik ini.
- Data papan klip tersedia untuk aplikasi lain di perangkat pengguna.
- Aplikasi web yang Anda tarik memiliki akses ke kunci jenis, bukan data. Data hanya tersedia saat melepaskan atau menempelkan.
- Data yang diterima harus diperlakukan seperti input pengguna lainnya; bersihkan dan validasi sebelum digunakan.
Memulai library helper Transmat
Apakah Anda tertarik untuk menggunakan DataTransfer API di aplikasi Anda? Sebaiknya lihat library Transmat di GitHub. Library open source ini menyelaraskan perbedaan browser, menyediakan utilitas JSON-LD, berisi observer untuk merespons peristiwa transfer guna menandai area drop, dan memungkinkan Anda mengintegrasikan operasi transfer data di antara implementasi tarik lalu lepas yang ada.
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);
Ucapan terima kasih
Banner besar oleh Luba Ertel di Unsplash.