Pokonywanie barier za pomocą interfejsu DataTransfer API

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

Być może słyszałeś/słyszałaś o interfejsie DataTransfer API, który jest częścią interfejsu HTML5 Drag and Drop API oraz zdarzeń związanych z buforem wymiany. Może służyć do przesyłania danych między źródłem a miejscami docelowymi, które dane mają otrzymywać.

Obsługa przeglądarek

  • Chrome:
  • Edge: 12.
  • Firefox: 3,5.
  • Safari: 4.

Źródło

Interakcje polegające na przeciąganiu i upuszczaniu oraz kopiowaniu i wklejaniu są często używane do interakcji na stronie w celu przeniesienia prostego tekstu z miejsca A do miejsca 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 z różnymi zachowaniami w zależności od miejsca przeniesienia danych. Podczas nasłuchiwania przychodzących zdarzeń aplikacja internetowa może wysyłać i odbierać dane.

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

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

Przenoszenie danych

Aby rozpocząć, musisz przeciągać i upuszczać elementy lub kopiować i wklejać. Przykłady poniżej pokazują interakcje polegające na przeciąganiu i upuszczaniu, ale proces kopiowania i wklejania jest podobny. Jeśli nie znasz interfejsu API przeciągania i upuszczania, przeczytaj świetny artykuł HTML5 przeciąganie i upuszczanie, który zawiera wszystkie niezbędne informacje.

Dzięki udostępnianiu danych kluczy typu MIME możesz swobodnie współpracować z zewnętrznymi aplikacjami. 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. Zwraca instancję DataTransfer. Jak zobaczysz, ten obiekt jest czasem zwracany przez właściwości o innych nazwach.

Odbieranie przenoszonych danych działa prawie tak samo jak ich przekazywanie. Nasłuchuj zdarzenia otrzymujące (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 utworzeniu 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();
});

W aplikacjach powszechnie obsługiwane są 3 typy MIME:

  • text/html: renderowanie ładunku HTML w elementach contentEditable i edytorach tekstu RTF (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: otwiera adres URL po upuszczeniu na pasku adresu lub 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.text/html Podobnie jak w przypadku dokumentów HTML, możesz osadzić zasoby za pomocą adresów URL danych lub publicznie dostępnych adresów URL. Ta metoda dobrze sprawdza się w przypadku eksportowania elementów wizualnych (np. z płótna) 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 znajdziesz przykład użycia interfejsu DataTransfer API do interakcji polegających na kopiowaniu i wklejaniu. Zwróć uwagę, że obiekt DataTransfer jest zwracany przez usługę o nazwie clipboardData w przypadku zdarzeń związanych ze schowkiem.

// 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, ale 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.

Do tego celu świetnie nadaje się standard JSON-LD (Linked Data). 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ć. Dostępne są też niestandardowe definicje schematu.

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. W przypadku aplikacji w tym samym języku możesz tworzyć zaawansowane integracje z aplikacjami zewnętrznymi. Nie musisz stosować skomplikowanych integracji interfejsu API. Wszystkie potrzebne informacje są zawarte w przekazywanych 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ą

Opisane powyżej techniki są dobrze obsługiwane przez przeglądarki na komputery, ale nie przez przeglądarki mobilne. 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 Android i iOS nie przeszły testu. 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. Ich 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 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 dużo dodatkowej pracy, a użytkownicy będą wdzięczni za dodanie tej funkcji.

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 są dostępne tylko po przeciągnięciu 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 używać interfejsu DataTransfer API w swojej aplikacji? Zapoznaj się z biblioteką Transmat na GitHubie. Ta biblioteka open source dopasowuje różnice między przeglądarkami, udostępnia narzędzia JSON-LD, zawiera obserwatora, który reaguje na zdarzenia przesyłania w celu wyróżniania obszarów przenoszenia, a także umożliwia integrację operacji przesyłania danych między 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 Luba Ertel na Unsplash.