Pokonywanie barier za pomocą interfejsu DataTransfer API

Zezwól użytkownikowi na udostępnianie danych poza oknem przeglądarki.

Być może znasz już interfejs DataTransfer API, który jest częścią interfejsów API przeciągania i upuszczania HTML5 oraz zdarzeń w schowku. Może służyć do przenoszenia danych między miejscami docelowymi a celami źródłowymi.

Obsługa przeglądarek

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

Źródło

Interakcje „przeciągnij, upuść” oraz „kopiuj i wklej” są często używane na stronie do przenoszenia prostego tekstu z punktu A do punktu B. Często pomija się jednak fakt, że te same interakcje można wykorzystać poza oknem przeglądarki.

Zarówno funkcja przeciągania i upuszczania, jak i interfejs kopiowania i wklejania mogą komunikować się z innymi aplikacjami, internetowymi lub innymi, i nie są powiązane z żadnym źródłem. Interfejs API obsługuje wiele wpisów danych o różnym działaniu w zależności od miejsca ich przesyłania. Podczas nasłuchiwania przychodzących zdarzeń aplikacja internetowa może wysyłać i odbierać dane.

Ta możliwość może zmienić nasz sposób myślenia o udostępnianiu i interoperacyjności aplikacji internetowych na komputerach. Przenoszenie danych między aplikacjami nie musi już korzystać ze ściśle sprzężonych integracji. Zamiast tego można dać użytkownikom pełną kontrolę na przenoszeniu danych, gdzie chcą.

Przykład interakcji możliwych za pomocą interfejsu DataTransfer API. (Film nie zawiera dźwięku).

Przenoszenie danych

Aby rozpocząć, należy wdrożyć metodę przeciągania i upuszczania lub kopiowania i wklejania. Poniższe przykłady pokazują interakcje metodą „przeciągnij i upuść”, ale proces kopiowania i wklejania jest podobny. Jeśli nie znasz interfejsu API Przeciągnij i upuść, możesz zapoznać się ze świetnym artykułem o przeciąganiu i upuszczaniu w HTML5, który zawiera szczegółowe informacje na jego temat.

Dzięki udostępnieniu danych z kluczem typu MIME możesz swobodnie korzystać z zewnętrznych aplikacji. Większość edytorów WYSIWYG, edytorów tekstu i przeglądarek reaguje na „proste” typy mime używane w przykładzie poniżej.

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');
});

Zwróć uwagę na właściwość event.dataTransfer. Spowoduje to zwrócenie instancji DataTransfer. Jak zobaczysz, ten obiekt jest czasem zwracany przez właściwości o innych nazwach.

Odbieranie przenoszenia danych działa prawie tak samo jak jego przekazanie. Wysłuchaj zdarzeń odbierania (drop lub paste) i odczytaj klucze. Podczas przeciągania elementu przeglądarka ma dostęp tylko do kluczy type danych. Same dane można uzyskać dopiero po ich spadku.

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();
});

W aplikacjach można powszechnie używać 3 typów MIME:

  • text/html: renderuje ładunek HTML w elementach contentEditable i w edytorach tekstu sformatowanego (WYSIWYG), takich jak Dokumenty Google czy Microsoft Word.
  • text/plain: Ustawia wartość elementów wejściowych, zawartość edytorów kodu i wartość zastępczą z text/html.
  • text/uri-list: powoduje przejście do adresu URL po upuszczeniu adresu na pasku adresu lub na stronie przeglądarki. Gdy przeniesiesz plik do katalogu lub na pulpit, zostanie utworzony skrót do adresu URL.

Jest ono bardzo przydatne, ponieważ jest powszechnie używane w edytorach WYSIWYG. Podobnie jak w dokumentach HTML możesz umieszczać zasoby, korzystając z adresów URL danych lub publicznie dostępnych adresów URL. Działa to dobrze w przypadku eksportowania elementów wizualnych (na przykład z obszaru roboczego) do edytorów takich jak Dokumenty Google.

const redPixel = 'data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=';
const html = '<img src="' + redPixel + '" width="100" height="100" alt="" />';
event.dataTransfer.setData('text/html', html);

Przenoszenie za pomocą kopiowania i wklejania

Poniżej pokazano, jak używać interfejsu DataTransfer API z kopiowaniem i wklejaniem. Zwróć uwagę, że w przypadku zdarzeń schowka obiekt DataTransfer jest zwracany przez właściwość o nazwie clipboardData.

// 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);
  }
});

Niestandardowe formaty danych

Nie musisz ograniczać się do prymitywnych typów MIME. Możesz użyć dowolnego klucza do identyfikacji przesyłanych danych. Może to być przydatne w przypadku interakcji w różnych przeglądarkach w aplikacji. Jak widać poniżej, możesz przesyłać bardziej złożone dane za pomocą funkcji JSON.stringify() i 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);
  }
});

Łączenie z internetem

Formaty niestandardowe są przydatne do komunikacji między aplikacjami, nad którymi masz kontrolę, ale ograniczają też użytkownika podczas przenoszenia danych do aplikacji, które nie obsługują Twojego formatu. Jeśli chcesz połączyć się z aplikacjami innych firm w internecie, musisz użyć uniwersalnego formatu danych.

Standard JSON-LD (połączone dane) doskonale się do tego nadaje. Jest lekki i łatwy do odczytu i zapisu w JavaScript. Schema.org zawiera wiele wstępnie zdefiniowanych typów, których można używać, a także definicje niestandardowych schematów.

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));

Jeśli używasz typów schema.org, możesz zacząć od ogólnego typu Thing lub użyć czegoś bardziej pasującego do Twojego przypadku użycia, np. Event, Person, MediaObject, Place, a w razie potrzeby nawet typów bardzo szczegółowych, takich jak MedicalEntity. Jeśli używasz TypeScript, możesz korzystać z definicji interfejsów z definicji typów schema-dts.

Przesyłając i odbierając dane w formacie JSON-LD, przyczyniasz się do tworzenia bardziej połączonej i otwartej sieci. Gdy aplikacje mówią w tym samym języku, możesz tworzyć głęboką integrację z aplikacjami zewnętrznymi. Nie ma potrzeby skomplikowanych integracji interfejsów API – wszystkie potrzebne informacje są zawarte w przenoszonych danych.

Pomyśl o wszystkich możliwościach przenoszenia danych między dowolnymi aplikacjami (internetowymi) bez żadnych ograniczeń: udostępnianie wydarzeń z kalendarza w ulubionej aplikacji do zarządzania zadaniami, dołączanie plików wirtualnych do e-maili, udostępnianie kontaktów. To byłoby świetne, prawda? Wszystko zaczyna się od Ciebie. 🙌

Potencjalne problemy

Interfejs DataTransfer API jest już dostępny, ale przed integracją należy wziąć pod uwagę kilka kwestii.

Zgodność z przeglądarką

Wszystkie przeglądarki na komputerach bardzo dobrze obsługują opisaną powyżej technikę, w przeciwieństwie do urządzeń mobilnych. Metoda ta została przetestowana we wszystkich najpopularniejszych przeglądarkach (Chrome, Edge, Firefox, Safari) i systemach operacyjnych (Android, ChromeOS, iOS, macOS, Ubuntu Linux i Windows), ale Android i iOS nie przeszły testów. Ponieważ przeglądarki są stale ulepszane, ta technika jest obecnie ograniczona do przeglądarek na komputery.

Widoczność kanału i treści

Przeciąganie i upuszczanie oraz kopiowanie i wklejanie to interakcje na poziomie systemu podczas pracy na komputerze stacjonarnym, których korzenie sięgają pierwszych interfejsów graficznych sprzed ponad 40 lat. Zastanów się, ile razy korzystałeś/korzystałaś z tych interakcji do porządkowania plików. Nie jest to jeszcze zbyt powszechne w internecie.

Musisz poinformować użytkowników o tej nowej interakcji i opracować wzorce UX, które ułatwią im jej rozpoznanie, zwłaszcza osobom, które do tej pory korzystały z komputerów tylko na urządzeniach mobilnych.

Ułatwienia dostępu

Przeciąganie i upuszczanie nie jest bardzo przystępną interakcją, ale interfejs DataTransfer API działa też z kopiowaniem i wklejaniem. Nasłuchuj zdarzeń kopiowania i wklejania. Nie wymaga to wiele pracy, a użytkownicy będą Ci wdzięczni za jej dodanie.

Bezpieczeństwo i prywatność

Podczas korzystania z tej techniki należy wziąć pod uwagę kilka kwestii związanych z bezpieczeństwem i prywatnością.

  • Dane z Schowka są dostępne dla innych aplikacji na urządzeniu użytkownika.
  • Aplikacje internetowe, które przeciągasz, mają dostęp do kluczy typu, a nie danych. Dane stają się dostępne tylko po upuszczeniu lub wklejeniu.
  • Otrzymane dane należy traktować jak dowolne inne dane użytkownika. Przed użyciem należy je sprawdzić i sprawdzić.

Pierwsze kroki z biblioteką pomocniczą Transmat

Czy chcesz korzystać z interfejsu DataTransfer API w swojej aplikacji? Zajrzyj do biblioteki Transmat na GitHubie. Ta biblioteka open source wyrównuje różnice w przeglądarkach, udostępnia narzędzia JSON-LD, zawiera obserwatora do reagowania na zdarzenia transferu w celu wyróżniania obszarów upuszczania oraz pozwala zintegrować operacje przesyłania danych z dotychczasowymi implementacjami przeciągania i upuszczania.

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);

Podziękowania

Baner powitalny: Luba Ertel na kanale Unsplash.