Mendobrak hambatan menggunakan DataTransfer API

Izinkan pengguna untuk berbagi data di luar jendela browser.

Anda mungkin pernah mendengar tentang DataTransfer API, yang merupakan bagian dari Peristiwa Tarik lalu Lepas HTML5 dan peristiwa Papan Klip. Dapat digunakan untuk mentransfer data antara sumber dan target penerima.

Dukungan Browser

  • 3
  • 12
  • 3,5
  • 4

Sumber

Interaksi tarik-lepas dan salin-tempel sering digunakan untuk interaksi dalam halaman untuk mentransfer teks sederhana dari A ke B. Namun, yang sering diabaikan adalah kemampuan menggunakan interaksi yang sama ini untuk melakukan lebih dari sekadar 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 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 berpikir kita tentang berbagi dan interoperabilitas dalam aplikasi web di desktop. Mentransfer data antar-aplikasi tidak perlu lagi mengandalkan integrasi yang terkait erat. Sebagai gantinya, Anda dapat memberi pengguna kontrol penuh untuk mentransfer data ke mana pun mereka suka.

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

Mentransfer data

Untuk memulai, Anda perlu mengimplementasikan {i>drag-drop<i} atau {i>copy-paste<i}. Contoh di bawah ini menunjukkan interaksi tarik lalu lepas, tetapi proses salin-tempelnya serupa. Jika Anda tidak terbiasa dengan Drag and Drop API, ada artikel bagus yang menjelaskan tentang Tarik lalu Lepas HTML5, yang menjelaskan seluk beluknya.

Dengan menyediakan data kunci 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.

Fungsi penerimaan transfer data hampir sama seperti menyediakannya. Proses peristiwa penerimaan (drop, atau paste) dan baca tombol. 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 berbagai aplikasi:

  • text/html: Merender payload HTML dalam elemen contentEditable dan editor rich text (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 membuka kolom URL atau halaman browser. Pintasan URL akan dibuat saat membuka direktori atau desktop.

Penggunaan text/html secara luas oleh editor WYSIWYG membuatnya sangat berguna. Seperti pada dokumen HTML, Anda dapat menyematkan resource menggunakan URL Data atau URL yang dapat diakses publik. Cara ini berfungsi baik dengan 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 ditampilkan di bawah ini. 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 sangat cocok untuk komunikasi antara aplikasi yang Anda miliki dalam kontrol, format kustom 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) sangat cocok untuk hal ini. Teks ini ringan, mudah dibaca, dan ditulis di 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 sudah 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? Ini dimulai dengan 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 pada 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 ini. Sementara 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 tentang berapa kali Anda telah menggunakan interaksi ini untuk mengatur file. Hal ini belum terlalu umum di web.

Anda perlu mengedukasi pengguna tentang interaksi baru ini, dan mengembangkan pola UX agar dapat dikenali, terutama bagi orang yang pengalamannya dengan komputer sejauh ini hanya terbatas pada perangkat seluler.

Aksesibilitas

{i>Drag-drop<i} bukanlah interaksi yang mudah diakses, tetapi DataTransfer API juga berfungsi dengan salin-tempel. Pastikan Anda memproses peristiwa salin-tempel. Tidak membutuhkan 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 seret memiliki akses ke tombol jenis, bukan data. Data hanya tersedia saat {i>drop or paste<i}.
  • Data yang diterima harus diperlakukan seperti input pengguna lainnya; bersihkan dan validasi sebelum digunakan.

Memulai library helper Transmat

Apakah Anda senang menggunakan DataTransfer API di aplikasi Anda? Pertimbangkan untuk melihat library Transmat di GitHub. Library open source ini menyelaraskan perbedaan browser, menyediakan utilitas JSON-LD, berisi observer untuk merespons peristiwa transfer untuk menandai area lepas, 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.