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 API i zdarzeń schowka. Może służyć do przesyłania danych między źródłem a miejscem docelowym.
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.
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 elementachcontentEditablei 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ą ztext/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() 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 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.