Pokonywanie barier za pomocą interfejsu DataTransfer API

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

Być może znasz interfejs DataTransfer API, który wchodzi w skład interfejsu HTML5 przeciągnij i upuść API oraz zdarzeń schowka. Można go używać do przenoszenia danych między miejscami docelowymi w źródle i w miejscu docelowym.

Obsługa przeglądarek

  • 3
  • 12
  • 3,5
  • 4

Źródło

Interakcje takie jak przeciąganie i wklejanie są często używane do przenoszenia prostego tekstu z punktu A do B w obrębie strony. Jednak często pomija się możliwość użycia tych samych interakcji, by wyjść poza okno przeglądarki.

Zarówno wbudowane w przeglądarkę funkcje przeciągania i upuszczania oraz kopiowania i wklejania mogą komunikować się z innymi aplikacjami, internetem lub innymi aplikacjami 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 tego, dokąd są przesyłane dane. Aplikacja internetowa może wysyłać i odbierać przesyłane dane podczas nasłuchiwania zdarzeń przychodzących.

Ta możliwość może zmienić sposób myślenia o udostępnianiu i interoperacyjności aplikacji internetowych na komputerach. Przenoszenie danych między aplikacjami nie musi już polegać na ściśle sprzężonych integracji. Zamiast tego daj użytkownikom pełną kontrolę nad przenoszeniem danych w dowolne miejsce.

Przykład interakcji, które są możliwe przy użyciu interfejsu DataTransfer API. (Film nie zawiera dźwięku).

Przenoszenie danych

Aby rozpocząć, musisz zastosować przeciąganie i upuszczanie albo kopiowanie i wklejanie. Poniższe przykłady pokazują interakcje z przeciąganiem, ale proces kopiowania i wklejania jest podobny. Jeśli nie znasz interfejsu przeciągania i upuszczania interfejsu API, skorzystaj ze świetnego artykułu o przeciąganiu i upuszczaniu elementów HTML5, który objaśnia wszystkie szczegółowe informacje.

Jeśli podasz dane typu MIME, możesz swobodnie korzystać z zewnętrznych aplikacji. Większość edytorów, edytorów tekstu i przeglądarek WYSIWYG reaguje na „podstawowe” typy MIME użyte w poniższym przykładzie.

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. Zwraca ono wystąpienie DataTransfer. Ten obiekt jest czasami zwracany przez właściwości o innych nazwach.

Odebranie przeniesienia danych działa prawie tak samo jak jego przekazanie. Wysłuchaj zdarzeń odbierających (drop lub paste) i odczytaj klucze. Podczas przeciągania elementu przeglądarka ma dostęp tylko do kluczy danych type. Same dane są dostępne dopiero po upuszczeniu.

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 są powszechnie obsługiwane trzy typy MIME:

  • text/html: renderuje ładunek HTML w elementach contentEditable i 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: przechodzi do adresu URL po upuszczeniu na pasku adresu lub stronie przeglądarki. Skrót adresu URL zostanie utworzony podczas upuszczania katalogu lub pulpitu.

Powszechne udostępnienie text/html w edytorach WYSIWYG sprawia, że jest ona bardzo użyteczna. Podobnie jak w przypadku dokumentów HTML zasoby możesz umieszczać za pomocą adresów URL danych lub publicznie dostępnych adresów URL. Sprawdza się to dobrze w przypadku eksportowania elementów wizualnych (np. 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 interakcjami związanymi z kopiowaniem i wklejaniem. Zwróć uwagę, że w przypadku zdarzeń ze schowka zwracany jest obiekt DataTransfer przez właściwość 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 podstawowych typów MIME, ale do identyfikowania przesyłanych danych możesz używać dowolnego klucza. Jest to przydatne w przypadku interakcji w różnych przeglądarkach w obrębie aplikacji. Jak pokazano 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);
  }
});

Łączę z internetem

Formaty niestandardowe doskonale nadają się do komunikacji między aplikacjami, nad którymi masz kontrolę, ale ograniczają też użytkownika przy przenoszeniu danych do aplikacji, które nie używają Twojego formatu. Jeśli chcesz łączyć się z aplikacjami innych firm w internecie, potrzebujesz uniwersalnego formatu danych.

Doskonale nadaje się do tego standard JSON-LD (Linked Data). Jest lekki i łatwy do odczytu i zapisu w języku JavaScript. Schema.org zawiera wiele wstępnie zdefiniowanych typów, których można użyć. Możesz też wybrać niestandardowe definicje 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));

Stosując typy Schema.org, możesz zacząć od ogólnego typu Thing lub użyć czegoś bardziej zbliżonego do Twojego zastosowania, np. Event, Person, MediaObject, Place, albo nawet bardzo specyficznych typów, takich jak MedicalEntity. Gdy korzystasz z TypeScriptu, możesz używać definicji interfejsu z definicji typów schema-dts.

Przesyłając i odbierając dane w formacie JSON-LD, wspierasz bardziej skomunikowaną i otwartą sieć. Gdy aplikacje mówią w tym samym języku, można tworzyć precyzyjne integracje z aplikacjami zewnętrznymi. Nie trzeba tworzyć skomplikowanych integracji z interfejsami API – wszystkie potrzebne informacje są zawarte w przenoszonych danych.

Pomyśl o wszystkich możliwościach przenoszenia danych między dowolną (internetową) aplikacją bez żadnych ograniczeń: udostępniania wydarzeń z kalendarza do ulubionej aplikacji Do zrobienia, dołączania wirtualnych plików do e-maili, udostępniania kontaktów. Wspaniale, nie? Wszystko zaczyna się od Ciebie. 🙌

Potencjalne problemy

Chociaż interfejs DataTransfer API jest już dostępny, przed integracją warto wziąć pod uwagę kilka kwestii.

Zgodność z przeglądarką

Wszystkie przeglądarki na komputerach świetnie obsługują opisaną powyżej metodę, w przeciwieństwie do urządzeń mobilnych. Ta metoda została przetestowana we wszystkich najpopularniejszych przeglądarkach (Chrome, Edge, Firefox, Safari) i systemach operacyjnych (Android, ChromeOS, iOS, macOS, Ubuntu Linux i Windows), ale niestety nie zdołał ich przejść na Androida i iOS. Chociaż przeglądarki wciąż się rozwijają, na razie technologia ta ogranicza się tylko do przeglądarek na komputerach.

Wykrywalność

„Przeciąganie i wklejanie” to interakcje na poziomie systemu występujące w przypadku komputera stacjonarnego, których korzenie sięgają do pierwszego interfejsu GUI sprzed ponad 40 lat. Zastanów się, ile razy zdarzyło Ci się używać tych interakcji do porządkowania plików. Rzadko się to pojawia w internecie.

Trzeba poinformować użytkowników o nowej interakcji i wypracować wzorce UX, by można ją było rozpoznać, zwłaszcza osoby, które do tej pory korzystają z komputerów wyłącznie na urządzeniach mobilnych.

Ułatwienia dostępu

Funkcja przeciągania i upuszczania nie jest łatwo dostępna, ale interfejs DataTransfer API obsługuje też funkcję kopiowania i wklejania. Pamiętaj, aby nasłuchiwać zdarzeń typu kopiuj i wklej. Nie wymaga to dużo dodatkowej pracy, a użytkownicy będą Ci wdzięczni za jego dodanie.

Prywatność i bezpieczeństwo

Korzystając z tej metody, musisz pamiętać o kilku kwestiach związanych z bezpieczeństwem i prywatnością.

  • Dane ze 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.
  • Otrzymywane dane należy traktować tak, jak wszystkie inne dane wejściowe użytkownika. Przed użyciem należy oczyścić i zweryfikować dane.

Pierwsze kroki z biblioteką pomocniczą Transmat

Czy podoba Ci się możliwość korzystania 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, obserwatora, który odpowiada na zdarzenia transferu w celu wyróżnienia obszarów usunięcia, oraz umożliwia integrację operacji przenoszenia danych z istniejącymi implementacjami typu „przeciągnij i upuść”.

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 od Luby Ertel w serwisie Unsplash.