Mendobrak hambatan menggunakan DataTransfer API

Memungkinkan pengguna membagikan data di luar jendela browser.

Anda mungkin pernah mendengar tentang DataTransfer API, yang merupakan bagian dari HTML5 Drag and Drop API dan Clipboard events. Dapat digunakan untuk mentransfer data antara target sumber dan penerima.

Browser Support

  • Chrome: 3.
  • Edge: 12.
  • Firefox: 3.5.
  • Safari: 4.

Source

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 salin tempel dapat berkomunikasi dengan aplikasi lain, web atau lainnya, dan tidak terikat ke asal mana 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 masuk.

Kemampuan ini dapat mengubah cara kita berpikir tentang berbagi dan interoperabilitas di aplikasi web di desktop. Transfer data antar-aplikasi tidak perlu lagi mengandalkan integrasi yang terhubung erat. Sebagai gantinya, Anda dapat memberi pengguna kontrol penuh untuk mentransfer data ke mana pun mereka mau.

Contoh interaksi yang dapat dilakukan dengan DataTransfer API. (Video tidak menyertakan suara.)

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 salin-tempel serupa. Jika Anda belum memahami Drag and Drop API, ada artikel bagus yang menjelaskan Drag and Drop HTML5, yang menjelaskan seluk-beluknya.

Dengan menyediakan data yang dikelompokkan menurut jenis MIME, Anda dapat berinteraksi secara 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 menyediakan transfer data. Dengarkan peristiwa penerimaan (drop, atau paste) dan baca kunci. Saat menarik elemen, browser hanya memiliki akses ke kunci type data. Data itu sendiri hanya dapat diakses setelah rilis.

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 elemen contentEditable dan editor teks lengkap (WYSIWYG) seperti Google Dokumen, Microsoft Word, dan lainnya.
  • text/plain: Menetapkan nilai elemen input, konten editor kode, dan penggantian dari text/html.
  • text/uri-list: Membuka URL saat dilepas di kolom URL atau halaman browser. Pintasan URL akan dibuat saat dilepas di direktori atau desktop.

Penggunaan text/html secara 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 untuk 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 kendalikan, format ini juga membatasi pengguna saat mentransfer data ke aplikasi yang tidak menggunakan format Anda. Jika Anda 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. Ringan dan mudah dibaca serta ditulis dari dan ke 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 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 antar-aplikasi (web) tanpa batasan: membagikan acara dari kalender ke aplikasi ToDo favorit Anda, melampirkan file virtual ke email, membagikan kontak. Itu akan sangat bagus, bukan? Semuanya dimulai dari Anda. 🙌

Masalah

Meskipun DataTransfer API tersedia hari ini, ada beberapa hal yang perlu diketahui sebelum melakukan integrasi.

Kompatibilitas browser

Semua browser desktop memiliki dukungan yang sangat 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 hanya terbatas pada browser desktop.

Visibilitas

Tarik lalu lepas dan salin lalu tempel adalah interaksi tingkat sistem saat bekerja di komputer desktop, dengan akar yang berasal dari GUI pertama lebih dari 40 tahun yang lalu. Pikirkan berapa kali Anda telah menggunakan interaksi ini untuk mengatur file. Fitur ini belum terlalu umum di web.

Anda harus mengedukasi pengguna tentang interaksi baru ini, dan membuat pola UX agar interaksi ini dapat dikenali, terutama bagi orang yang selama ini hanya menggunakan 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 Anda 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 dilepas atau ditempel.
  • Data yang diterima harus diperlakukan seperti input pengguna lainnya; bersihkan dan validasi sebelum digunakan.

Mulai menggunakan library helper Transmat

Apakah Anda tertarik menggunakan DataTransfer API di aplikasi Anda? Sebaiknya lihat library Transmat di GitHub. Library open source ini menyelaraskan perbedaan browser, menyediakan utilitas JSON-LD, berisi pengamat untuk merespons peristiwa transfer untuk menandai area pelepasan, dan memungkinkan Anda mengintegrasikan operasi transfer data di antara penerapan 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 utama oleh Luba Ertel di Unsplash.