Mendobrak hambatan menggunakan DataTransfer API

Memungkinkan pengguna berbagi data di luar jendela browser.

Anda mungkin pernah mendengar tentang DataTransfer API, yang merupakan bagian dari API Tarik lalu Lepas HTML5 dan peristiwa papan klip. Teknologi ini dapat digunakan untuk mentransfer data antara target sumber dan penerima.

Dukungan Browser

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

Sumber

Interaksi tarik-lepas dan salin-tempel sering digunakan untuk interaksi dalam laman untuk mentransfer teks sederhana dari A ke B. Tetapi yang sering terabaikan adalah kemampuan dalam memanfaatkan interaksi yang sama ini melampaui jendela {i>browser<i}.

Interaksi tarik dan lepas bawaan browser serta 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. Nama aplikasi web dapat mengirim dan menerima data yang ditransfer saat memproses {i>event<i} yang masuk.

Kemampuan ini dapat mengubah cara berpikir kita tentang proses berbagi dan interoperabilitas di web aplikasi di desktop. Transfer data antaraplikasi tidak perlu bergantung pada integrasi yang terkait erat lagi. Sebagai gantinya, Anda dapat memberikan kontrol penuh 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-lepas atau salin-tempel. Contoh di bawah ini menampilkan interaksi {i>drag-drop<i}, tetapi proses untuk {i>copy-paste<i} serupa. Jika Anda belum terbiasa dengan Drag and Drop API, ada artikel bagus menjelaskan tarik lalu Lepas HTML5, yang menjelaskan seluk beluk.

Dengan menyediakan data yang terkunci jenis MIME, Anda dapat dengan bebas berinteraksi dengan aplikasi eksternal. Kebanyakan editor WYSIWYG, editor teks, dan browser menanggapi "primitif" jenis mime yang digunakan dalam contoh di bawah ini.

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. Ini akan mengembalikan instance DataTransfer Sebagai seperti yang terlihat, objek ini terkadang dikembalikan oleh properti dengan nama lain.

Cara kerja penerimaan transfer data hampir sama dengan menyediakannya. Memproses peristiwa penerimaan (drop, atau paste) dan baca kuncinya. 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 dalam elemen contentEditable dan multimedia editor teks (WYSIWYG) seperti Google Docs, 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. URL {i>shortcut<i} akan dibuat saat menempatkan pada direktori atau {i>desktop<i}.

Penggunaan text/html yang luas oleh editor WYSIWYG membuatnya sangat berguna. Seperti dalam HTML dokumen, Anda dapat menyematkan sumber daya menggunakan URL data atau secara publik yang dapat diakses. 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. 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 objek yang ditransfer layanan otomatis dan data skalabel. 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 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 (Data Tertaut) adalah kandidat yang tepat untuk hal ini. Penting ringan dan mudah untuk 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 bisa memulai dengan jenis Thing generik, atau gunakan sesuatu yang lebih dekat dengan kasus penggunaan Anda seperti Peristiwa, Orang, 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 menggunakan berbagai aplikasi obrolan. Tidak perlu integrasi API yang rumit; semua informasi yang diperlukan adalah disertakan dalam data yang ditransfer.

Pikirkan segala 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? Hal ini dimulai dari Anda. 🙌

Masalah

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

Kompatibilitas browser

Semua {i>browser<i} desktop memiliki dukungan besar untuk teknik yang dijelaskan di atas, sementara 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. Sementara browser terus berkembang, untuk saat ini tekniknya masih terbatas pada {i>browser<i} desktop saja.

Visibilitas

{i>Drag-drop<i} dan {i>copy-paste<i} adalah interaksi tingkat sistem saat bekerja di komputer {i>desktop<i}, dengan berakar pada GUI pertama lebih dari 40 tahun yang lalu. Pikirkan tentang berapa kali Anda menggunakan interaksi ini untuk mengatur file. Ini belum terlalu umum di web.

Anda perlu mengedukasi pengguna tentang interaksi baru ini, dan mencari pola UX untuk membuatnya. dikenali, terutama bagi orang yang pengalamannya dengan komputer sejauh ini terbatas pada perangkat seluler.

Aksesibilitas

{i>Drag-drop<i} bukanlah interaksi yang mudah diakses, tetapi DataTransfer API juga dapat berfungsi dengan salin-tempel. Pastikan Anda memproses peristiwa salin-tempel. Ini tidak membutuhkan upaya ekstra, 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 seret memiliki akses ke tombol jenis, bukan data. Hanya data tersedia saat dilepas atau ditempel.
  • Data yang diterima harus diperlakukan seperti input pengguna lainnya; sanitasi dan validasi sebelum digunakan.

Memulai library helper Transmat

Anda ingin menggunakan DataTransfer API di aplikasi Anda? Pertimbangkan untuk melihat Library transmat di GitHub. Library open source ini menyelaraskan browser menyediakan utilitas JSON-LD, berisi observer untuk merespons peristiwa transfer untuk menyoroti area lepas, dan memungkinkan Anda mengintegrasikan operasi transfer data di antara operasi tarik lalu lepas yang sudah ada implementasi yang tepat.

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 Buka pembuka.