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 ini mendukung beberapa entri data dengan perilaku yang berbeda berdasarkan tempat data ditransfer. Aplikasi web Anda dapat mengirim dan menerima data yang ditransfer saat memproses peristiwa masuk.
Kemampuan ini dapat mengubah cara kita berpikir tentang berbagi dan interoperabilitas dalam aplikasi web di desktop. Mentransfer data antar-aplikasi tidak perlu lagi mengandalkan integrasi yang terikat 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 menunjukkan interaksi tarik lalu lepas, tetapi proses untuk menyalin dan menempel mirip. Jika Anda tidak terbiasa dengan Drag and Drop API, ada artikel menarik yang menjelaskan Drag and Drop HTML5, yang menjelaskan seluk-beluknya.
Dengan menyediakan data dengan kunci jenis MIME, Anda dapat berinteraksi dengan bebas 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.
Menerima 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 penurunan.
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 dalam elemencontentEditable
dan editor teks kaya (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 di-drop di kolom URL atau halaman browser. Pintasan URL akan dibuat saat dilempar ke 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);
Mentransfer 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 terbatas 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, 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 (Linked Data) 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 umum, 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 mengirimkan 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 antar-aplikasi (web) tanpa batasan: membagikan acara dari kalender ke aplikasi Daftar Tugas favorit Anda, melampirkan file virtual ke email, membagikan kontak. Pastinya 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 mendukung. 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 hanya terbatas pada browser desktop.
Visibilitas
Tarik lalu lepas dan salin-tempel adalah interaksi tingkat sistem saat bekerja di komputer desktop, dengan akar yang kembali ke GUI pertama lebih dari 40 tahun yang lalu. Pikirkan berapa kali Anda menggunakan interaksi ini untuk mengatur file. Hal ini belum terlalu umum di web.
Anda harus mengedukasi pengguna tentang interaksi baru ini, dan membuat pola UX agar dapat dikenali, terutama bagi orang-orang yang pengalamannya dengan komputer sejauh ini 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 pekerjaan tambahan, dan pengguna akan berterima kasih kepada Anda karena telah 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 dilempar atau ditempel.
- Data yang diterima harus diperlakukan seperti input pengguna lainnya; bersihkan dan validasi sebelum digunakan.
Mulai menggunakan 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
Gambar hero oleh Luba Ertel di Unsplash.