ช่วยให้ผู้ใช้แชร์ข้อมูลนอกหน้าต่างเบราว์เซอร์ได้
คุณอาจเคยได้ยินเกี่ยวกับ DataTransfer API ซึ่งเป็นส่วนหนึ่งของ HTML5 Drag and Drop API และเหตุการณ์ในคลิปบอร์ด ซึ่งใช้เพื่อโอนข้อมูลระหว่างแหล่งที่มาและเป้าหมายที่รับได้
การโต้ตอบแบบลากและวาง รวมถึงการคัดลอกและวาง มักใช้สำหรับการโต้ตอบภายในหน้าเว็บ เพื่อโอนข้อความธรรมดาจาก A ไปยัง B แต่สิ่งที่มักถูกมองข้ามคือความสามารถในการใช้ การโต้ตอบเดียวกันนี้เพื่อขยายขอบเขตไปไกลกว่าหน้าต่างเบราว์เซอร์
ทั้งการลากและวางในตัวของเบราว์เซอร์และการโต้ตอบแบบคัดลอกและวางสามารถสื่อสาร กับแอปพลิเคชันอื่นๆ เว็บ หรืออื่นๆ และไม่ได้เชื่อมโยงกับต้นทางใดๆ API รองรับรายการข้อมูลหลายรายการที่มีลักษณะการทำงานแตกต่างกันตามตำแหน่งที่จะโอนข้อมูล เว็บแอปพลิเคชันสามารถส่งและรับข้อมูลที่โอนเมื่อฟังเหตุการณ์ขาเข้า
ความสามารถนี้สามารถเปลี่ยนวิธีคิดเกี่ยวกับการแชร์และการทำงานร่วมกันในเว็บแอปพลิเคชันบนเดสก์ท็อป การโอนข้อมูลระหว่างแอปพลิเคชันไม่จำเป็นต้องอาศัยการผสานรวมที่เชื่อมโยงกันอย่างใกล้ชิดอีกต่อไป แต่คุณสามารถให้สิทธิ์ผู้ใช้ในการควบคุมการโอนข้อมูลไปยังที่ใดก็ได้ตามต้องการ
การโอนข้อมูล
คุณจะต้องใช้การลากและวางหรือการคัดลอกและวางเพื่อเริ่มต้นใช้งาน ตัวอย่าง ด้านล่างแสดงการโต้ตอบแบบลากและวาง แต่กระบวนการคัดลอกและวางจะคล้ายกัน หากคุณไม่คุ้นเคยกับ Drag and Drop API เราขอแนะนำบทความดีๆ ที่อธิบายการลากและวางใน HTML5 ซึ่งจะอธิบายรายละเอียดต่างๆ
การระบุข้อมูลที่คีย์ด้วย MIME-type จะช่วยให้คุณโต้ตอบกับแอปพลิเคชันภายนอกได้อย่างอิสระ ตัวแก้ไข WYSIWYG, โปรแกรมแก้ไขข้อความ และเบราว์เซอร์ส่วนใหญ่จะตอบสนองต่อ MIME ประเภท "ดั้งเดิม" ที่ใช้ใน ตัวอย่างด้านล่าง
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');
});
สังเกตพร็อพเพอร์ตี้ event.dataTransfer ซึ่งจะแสดงอินสแตนซ์ของ
DataTransfer ดังที่คุณเห็น ออบเจ็กต์นี้บางครั้งจะแสดงผลโดยพร็อพเพอร์ตี้ที่มีชื่ออื่น
การรับการโอนข้อมูลจะทำงานเกือบเหมือนกับการให้ข้อมูล ฟังเหตุการณ์ที่ได้รับ
(drop หรือ paste) และอ่านคีย์ เมื่อลากผ่านองค์ประกอบ เบราว์เซอร์จะมีสิทธิ์เข้าถึง
เฉพาะคีย์ type ของข้อมูล คุณจะเข้าถึงข้อมูลได้หลังจากที่ดรอปสิ้นสุดลงแล้วเท่านั้น
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();
});
แอปพลิเคชันส่วนใหญ่รองรับประเภท MIME 3 ประเภทต่อไปนี้
text/html: แสดงผลเพย์โหลด HTML ในองค์ประกอบcontentEditableและโปรแกรมแก้ไขข้อความที่จัดรูปแบบแล้ว (WYSIWYG) เช่น Google เอกสาร, Microsoft Word และอื่นๆtext/plain:ตั้งค่าขององค์ประกอบอินพุต เนื้อหาของโปรแกรมแก้ไขโค้ด และรายการสำรอง จากtext/htmltext/uri-list: ไปยัง URL เมื่อวางในแถบ URL หรือหน้าเบราว์เซอร์ ระบบจะสร้างทางลัด URL เมื่อวางลงในไดเรกทอรีหรือเดสก์ท็อป
การนำ text/html ไปใช้กันอย่างแพร่หลายในตัวแก้ไข WYSIWYG ทำให้มีประโยชน์อย่างมาก คุณฝังทรัพยากรได้โดยใช้URL ข้อมูลหรือ URL ที่เข้าถึงได้แบบสาธารณะเช่นเดียวกับในเอกสาร HTML
ซึ่งเหมาะกับการส่งออกภาพ (เช่น จาก Canvas) ไปยังโปรแกรมแก้ไขอย่าง
Google เอกสาร
const redPixel = 'data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=';
const html = '<img src="' + redPixel + '" width="100" height="100" alt="" />';
event.dataTransfer.setData('text/html', html);
โอนโดยใช้การคัดลอกและวาง
การใช้ DataTransfer API กับการโต้ตอบแบบคัดลอกและวางแสดงอยู่ด้านล่าง โปรดทราบว่าระบบจะแสดงผลออบเจ็กต์ DataTransfer โดยพร็อพเพอร์ตี้ที่ชื่อ 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);
}
});
รูปแบบข้อมูลที่กำหนดเอง
คุณไม่ได้จำกัดอยู่แค่ประเภท MIME ดั้งเดิม แต่สามารถใช้คีย์ใดก็ได้เพื่อระบุข้อมูลที่โอน ซึ่งอาจเป็นประโยชน์สำหรับการโต้ตอบข้ามเบราว์เซอร์ภายในแอปพลิเคชัน ดังที่แสดงด้านล่าง คุณ
สามารถโอนข้อมูลที่ซับซ้อนมากขึ้นได้โดยใช้ฟังก์ชัน 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);
}
});
การเชื่อมต่อเว็บ
แม้ว่ารูปแบบที่กำหนดเองจะเหมาะสำหรับการสื่อสารระหว่างแอปพลิเคชันที่คุณควบคุมได้ แต่ก็จำกัดผู้ใช้เมื่อโอนข้อมูลไปยังแอปพลิเคชันที่ไม่ได้ใช้รูปแบบของคุณด้วย หากต้องการ เชื่อมต่อกับแอปพลิเคชันของบุคคลที่สามทั่วทั้งเว็บ คุณต้องมีรูปแบบข้อมูลสากล
มาตรฐาน JSON-LD (Linked Data) เป็นตัวเลือกที่ยอดเยี่ยมสำหรับกรณีนี้ ซึ่งมีขนาดเล็กและอ่านง่าย รวมถึงเขียนใน JavaScript ได้ Schema.org มีประเภทที่กำหนดไว้ล่วงหน้ามากมายที่คุณใช้ได้ และคุณยังเลือกใช้คำจำกัดความสคีมาที่กำหนดเองได้ด้วย
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));
เมื่อใช้ประเภท Schema.org คุณสามารถเริ่มต้นด้วยประเภท Thing ทั่วไป หรือใช้ประเภทที่ใกล้เคียงกับกรณีการใช้งานของคุณมากขึ้น เช่น Event, Person, MediaObject, Place หรือแม้แต่ประเภทที่มีความเฉพาะเจาะจงสูง เช่น MedicalEntity หากจำเป็น เมื่อใช้ TypeScript คุณจะใช้คำจำกัดความของอินเทอร์เฟซจากคำจำกัดความของประเภท schema-dts ได้
การส่งและรับข้อมูล JSON-LD จะช่วยสนับสนุนเว็บที่เชื่อมต่อและเปิดกว้างมากขึ้น เมื่อแอปพลิเคชันใช้ภาษาเดียวกัน คุณจะสร้างการผสานรวมอย่างลึกซึ้งกับแอปพลิเคชันภายนอกได้ คุณไม่จำเป็นต้องผสานรวม API ที่ซับซ้อน เนื่องจากข้อมูลที่จำเป็นทั้งหมดจะรวมอยู่ในข้อมูลที่โอน
ลองนึกถึงความเป็นไปได้ทั้งหมดในการโอนข้อมูลระหว่างแอปพลิเคชัน (เว็บ) ใดๆ โดยไม่มีข้อจำกัด เช่น การแชร์กิจกรรมจากปฏิทินไปยังแอปสิ่งที่ต้องทำที่คุณชื่นชอบ การแนบไฟล์เสมือนจริงไปกับ อีเมล การแชร์รายชื่อติดต่อ ดีเลยใช่ไหม ซึ่งเริ่มต้นจากคุณ 🙌
ข้อกังวล
แม้ว่า DataTransfer API จะพร้อมใช้งานแล้วในวันนี้ แต่ก็มีบางสิ่งที่คุณควรทราบก่อนที่จะผสานรวม
ความเข้ากันได้กับเบราว์เซอร์
เบราว์เซอร์บนเดสก์ท็อปทั้งหมดรองรับเทคนิคที่อธิบายไว้ข้างต้นเป็นอย่างดี แต่อุปกรณ์เคลื่อนที่ไม่รองรับ เราได้ทดสอบเทคนิคนี้ในเบราว์เซอร์หลักๆ ทั้งหมด (Chrome, Edge, Firefox, Safari) และระบบปฏิบัติการ (Android, ChromeOS, iOS, macOS, Ubuntu Linux และ Windows) แต่ Android และ iOS ไม่ผ่านการทดสอบ ในขณะที่เบราว์เซอร์ยังคงพัฒนาต่อไป ปัจจุบันเทคนิคนี้ใช้ได้กับเบราว์เซอร์ในเดสก์ท็อปเท่านั้น
การค้นพบได้
การลากและวาง รวมถึงการคัดลอกและวางเป็นการโต้ตอบระดับระบบเมื่อทำงานบนคอมพิวเตอร์เดสก์ท็อป โดยมี รากฐานย้อนกลับไปที่ GUI แรกเมื่อกว่า 40 ปีที่แล้ว ลองคิดดูว่าคุณใช้การโต้ตอบเหล่านี้เพื่อจัดระเบียบไฟล์กี่ครั้ง ซึ่งยังไม่ค่อยพบเห็นบนเว็บ
คุณจะต้องให้ความรู้แก่ผู้ใช้เกี่ยวกับการโต้ตอบแบบใหม่นี้ และคิดรูปแบบ UX เพื่อให้ผู้ใช้จดจำได้ โดยเฉพาะอย่างยิ่งสำหรับผู้ที่เคยใช้คอมพิวเตอร์ในอุปกรณ์เคลื่อนที่เท่านั้น
การช่วยเหลือพิเศษ
การลากและวางเป็นการโต้ตอบที่เข้าถึงได้ไม่ดีนัก แต่ DataTransfer API ก็ใช้ได้กับการคัดลอกและวางด้วย ตรวจสอบว่าคุณรอเหตุการณ์คัดลอกและวาง ซึ่งไม่ได้เป็นการเพิ่มงานมากนัก และผู้ใช้จะขอบคุณที่คุณเพิ่มฟีเจอร์นี้
ความปลอดภัยและความเป็นส่วนตัว
คุณควรทราบถึงข้อควรพิจารณาด้านความปลอดภัยและความเป็นส่วนตัวบางประการเมื่อใช้เทคนิคนี้
- ข้อมูลในคลิปบอร์ดจะพร้อมใช้งานในแอปพลิเคชันอื่นๆ บนอุปกรณ์ของผู้ใช้
- เว็บแอปพลิเคชันที่คุณลากไปจะมีสิทธิ์เข้าถึงคีย์ประเภท ไม่ใช่ข้อมูล ข้อมูลจะพร้อมใช้งานเมื่อวางเท่านั้น
- คุณควรถือว่าข้อมูลที่ได้รับเป็นเหมือนข้อมูลอื่นๆ ที่ผู้ใช้ป้อนเข้ามา โดยให้ล้างและตรวจสอบความถูกต้องก่อนใช้งาน
การเริ่มต้นใช้งานไลบรารีตัวช่วย Transmat
คุณตื่นเต้นที่จะใช้ DataTransfer API ในแอปพลิเคชันของคุณไหม ลองดูไลบรารี Transmat ใน GitHub ไลบรารีโอเพนซอร์สนี้จะปรับความแตกต่างของเบราว์เซอร์ ให้สอดคล้องกัน มีเครื่องมือ JSON-LD มี Observer เพื่อตอบสนองต่อเหตุการณ์การโอนสำหรับการ ไฮไลต์พื้นที่วาง และช่วยให้คุณผสานรวมการดำเนินการโอนข้อมูลระหว่างการใช้งานการลากและวางที่มีอยู่
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);
การรับทราบ
รูปภาพหลักโดย Luba Ertel ใน Unsplash