Pokonywanie barier za pomocą interfejsu DataTransfer API

Umożliwia użytkownikowi udostępnianie danych poza oknem przeglądarki.

Być może znasz interfejs DataTransfer API, który jest częścią interfejsu HTML5 Drag and Drop APIzdarzeń schowka. Może służyć do przesyłania danych między źródłem a miejscem docelowym.

Browser Support

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

Source

Interakcje typu „przeciągnij i upuść” oraz „kopiuj i wklej” są często używane na stronie do przenoszenia prostego tekstu z miejsca A do miejsca B. Często jednak pomija się możliwość wykorzystania tych samych interakcji poza oknem przeglądarki.

Zarówno wbudowana w przeglądarkę funkcja przeciągania i upuszczania, jak i interakcje związane z kopiowaniem i wklejaniem mogą komunikować się z innymi aplikacjami (internetowymi i nieinternetowymi) 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, gdzie dane są przesyłane. Aplikacja internetowa może wysyłać i odbierać przesyłane dane, gdy nasłuchuje zdarzeń przychodzących.

Ta funkcja może zmienić sposób, w jaki myślimy o udostępnianiu i współdziałaniu w aplikacjach internetowych na komputerach. Przenoszenie danych między aplikacjami nie musi już opierać się na ściśle powiązanych integracjach. Zamiast tego możesz dać użytkownikom pełną kontrolę nad przenoszeniem danych w dowolne miejsce.

Przykład interakcji możliwych dzięki interfejsowi DataTransfer API. (Film nie zawiera dźwięku).

Przenoszenie danych

Aby rozpocząć, musisz wdrożyć funkcję przeciągania i upuszczania lub kopiowania i wklejania. Przykłady poniżej pokazują interakcje typu „przeciągnij i upuść”, ale proces kopiowania i wklejania jest podobny. Jeśli nie znasz interfejsu Drag and Drop API, przeczytaj ten artykuł wyjaśniający funkcję przeciągania i upuszczania w HTML5.

Dostarczając dane kluczowe typu MIME, możesz swobodnie wchodzić w interakcje z aplikacjami zewnętrznymi. Większość edytorów WYSIWYG, edytorów tekstu i przeglądarek reaguje na „podstawowe” typy MIME użyte 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. Zwraca instancję klasy DataTransfer. Jak widać, ten obiekt jest czasami zwracany przez właściwości o innych nazwach.

Odbieranie danych działa prawie tak samo jak ich udostępnianie. Nasłuchuj zdarzeń odbioru (drop lub paste) i odczytuj klucze. Podczas przeciągania elementu przeglądarka ma dostęp tylko do kluczy type danych. Dostęp do samych danych jest możliwy dopiero po zakończeniu dropu.

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

Trzy typy MIME są powszechnie obsługiwane w aplikacjach:

  • text/html: renderuje ładunek HTML w elementach contentEditable i edytorach tekstu sformatowanego (WYSIWYG), takich jak Dokumenty Google, Microsoft Word i inne.
  • text/plain: Ustawia wartość elementów wejściowych, zawartość edytorów kodu i wartość domyślną z text/html.
  • text/uri-list: przechodzi do adresu URL po upuszczeniu go na pasku adresu lub na stronie przeglądarki. Po upuszczeniu w katalogu lub na pulpicie zostanie utworzony skrót URL.

Powszechne stosowanie text/html przez edytory WYSIWYG sprawia, że jest to bardzo przydatne narzędzie. Podobnie jak w przypadku dokumentów HTML możesz osadzać zasoby za pomocą adresów URL danych lub publicznie dostępnych adresów URL. Jest to przydatne podczas eksportowania elementów wizualnych (np. z elementu canvas) 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 pokazujemy, jak używać interfejsu DataTransfer API w interakcjach typu „kopiuj i wklej”. 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 podstawowych typów MIME, ale możesz użyć dowolnego klucza do identyfikowania przesyłanych danych. Może to być przydatne w przypadku interakcji w aplikacji w różnych przeglądarkach. Jak widać poniżej, bardziej złożone dane możesz przenieść za pomocą funkcji JSON.stringify()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 internetu

Formaty niestandardowe świetnie sprawdzają się w komunikacji między aplikacjami, nad którymi masz kontrolę, ale ograniczają użytkownika podczas przesyłania danych do aplikacji, które nie korzystają z Twojego formatu. Jeśli chcesz łączyć się z aplikacjami innych firm w internecie, potrzebujesz uniwersalnego formatu danych.

Świetnie nadaje się do tego standard JSON-LD (Linked Data). Jest lekki i łatwy do odczytu i zapisu w JavaScript. Schema.org zawiera wiele predefiniowanych typów, których można używać. Możesz też tworzyć własne 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));

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

Przesyłając i odbierając dane JSON-LD, przyczyniasz się do tworzenia bardziej połączonej i otwartej sieci. Dzięki temu, że aplikacje „mówią” tym samym językiem, możesz tworzyć zaawansowane integracje z aplikacjami zewnętrznymi. Nie musisz przeprowadzać skomplikowanych integracji interfejsu API – wszystkie potrzebne informacje są zawarte w przenoszonych danych.

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

Potencjalne problemy

Interfejs DataTransfer API jest dostępny od dziś, ale przed jego zintegrowaniem warto pamiętać o kilku kwestiach.

Zgodność z przeglądarką

Przeglądarki na komputery stacjonarne w pełni obsługują opisaną powyżej technikę, a urządzenia mobilne – nie. Technika została przetestowana we wszystkich głównych przeglądarkach (Chrome, Edge, Firefox, Safari) i systemach operacyjnych (Android, ChromeOS, iOS, macOS, Ubuntu Linux i Windows), ale niestety nie przeszła testu na urządzeniach z Androidem i iOS. Przeglądarki są wciąż rozwijane, ale obecnie ta technika jest ograniczona tylko 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óre mają swoje korzenie w pierwszych graficznych interfejsach użytkownika sprzed ponad 40 lat. Zastanów się, ile razy używasz 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 sprawią, że będzie ona rozpoznawalna, zwłaszcza dla osób, 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 zbyt przystępną interakcją, ale interfejs DataTransfer API działa też z kopiowaniem i wklejaniem. Upewnij się, że nasłuchujesz zdarzeń kopiowania i wklejania. Nie wymaga to wiele dodatkowej pracy, a użytkownicy będą Ci wdzięczni za dodanie tej funkcji.

Bezpieczeństwo i prywatność

Podczas korzystania z tej techniki należy pamiętać o pewnych 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 do danych. Dane stają się dostępne dopiero po upuszczeniu lub wklejeniu.
  • Otrzymane dane należy traktować jak każde inne dane wejściowe użytkownika – przed użyciem należy je oczyścić i zweryfikować.

Pierwsze kroki z biblioteką pomocniczą Transmat

Czy chcesz używać interfejsu DataTransfer API w swojej aplikacji? Zapoznaj się z biblioteką Transmat w GitHubie. Ta biblioteka open source ujednolica różnice między przeglądarkami, udostępnia narzędzia JSON-LD, zawiera obserwatora, który reaguje na zdarzenia przesyłania, aby wyróżniać obszary docelowe, i umożliwia integrację operacji przesyłania danych z istniejącymi 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 autorstwa Luby Ertel na stronie Unsplash.