ให้ผู้ใช้แชร์ข้อมูลนอกหน้าต่างเบราว์เซอร์ได้
คุณอาจเคยได้ยินเกี่ยวกับ DataTransfer API ซึ่งก็คือ ส่วนของ API การลากและวางของ HTML5 และเหตุการณ์ในคลิปบอร์ด ช่วย ซึ่งใช้ในการโอนข้อมูลระหว่างเป้าหมายต้นทางและเป้าหมายที่รับ
การโต้ตอบแบบลากและวางและคัดลอกและวางมักจะใช้สำหรับการโต้ตอบภายในหน้าเว็บ เพื่อโอนข้อความธรรมดาจาก A ไปยัง B แต่สิ่งที่มักถูกมองข้ามคือความสามารถในการใช้ ออกไปนอกหน้าต่างเบราว์เซอร์เสียอีก
การโต้ตอบแบบลากและวางภายในเบราว์เซอร์และการคัดลอก-วางสามารถสื่อสารกันได้ กับแอปพลิเคชัน เว็บ หรืออย่างอื่น และไม่ได้ผูกกับต้นทางใดๆ API รองรับ รายการข้อมูลที่มีลักษณะการทำงานแตกต่างกันตามตำแหน่งที่โอนข้อมูลไป บัญชี เว็บแอปพลิเคชันสามารถส่งและรับข้อมูลที่โอนเมื่อฟังเหตุการณ์ที่เข้ามาใหม่
ความสามารถนี้สามารถเปลี่ยนมุมมองของเราเกี่ยวกับการแชร์และความสามารถในการทำงานร่วมกันบนเว็บได้ แอปพลิเคชันบนเดสก์ท็อป ไม่จำเป็นต้องโอนข้อมูลระหว่างแอปพลิเคชัน ผสานรวมกันอย่างเหนียวแน่นอีกต่อไป แต่คุณสามารถให้สิทธิ์ผู้ใช้ควบคุมการโอนได้อย่างเต็มที่ ข้อมูลไปยังที่ใดก็ได้ที่ต้องการ
กำลังโอนข้อมูล
คุณจะต้องใช้การลากและวางหรือคัดลอกและวางเพื่อเริ่มต้นใช้งาน ตัวอย่าง ด้านล่างแสดงการโต้ตอบแบบลากและวาง แต่กระบวนการคัดลอกและวางนั้นคล้ายกัน ถ้า คุณยังไม่คุ้นเคยกับการลากและวาง API เรามีบทความดีๆ คำอธิบายการลากและวางของ HTML5 ซึ่งจะอธิบายรายละเอียดทั้งหมด
การระบุข้อมูลที่คีย์ประเภท MIME คุณสามารถโต้ตอบกับแอปพลิเคชันภายนอกได้อย่างอิสระ โปรแกรมแก้ไขแบบ 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
และ Rich โปรแกรมแก้ไขข้อความ (WYSIWYG) เช่น Google เอกสาร, Microsoft Word และอื่นๆtext/plain:
ตั้งค่าขององค์ประกอบอินพุต เนื้อหาของตัวแก้ไขโค้ด และรายการสำรอง จากtext/html
text/uri-list
: ไปที่ URL เมื่อวางในแถบ URL หรือหน้าเบราว์เซอร์ URL จะมีการสร้างทางลัดเมื่อวางในไดเรกทอรีหรือบนเดสก์ท็อป
การใช้ text/html
โดยตัวแก้ไขแบบ WYSIWYG อย่างแพร่หลายทำให้แอปนี้มีประโยชน์มาก เช่นเดียวกับ HTML
คุณสามารถฝังทรัพยากรได้โดยใช้
URL ข้อมูลหรือแบบสาธารณะ
URL ที่สามารถเข้าถึงได้ วิธีนี้ได้ผลดีกับการส่งออกภาพ (เช่น จากภาพพิมพ์แคนวาส) ไปยังเครื่องมือแก้ไข
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 ร่วมกับการโต้ตอบแบบคัดลอกและวางจะแสดงอยู่ด้านล่าง โปรดสังเกตว่า
พร็อพเพอร์ตี้ชื่อ clipboardData
จะแสดงผลออบเจ็กต์ DataTransfer
สำหรับเหตุการณ์คลิปบอร์ด
// 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 (ข้อมูลที่ลิงก์) เป็นตัวเลือกที่ยอดเยี่ยมในกรณีนี้ ใช่เลย น้ำหนักเบาและสามารถอ่านและเขียนจากใน 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 ทั่วไป หรือใช้สิ่งอื่นที่ใกล้กับ Use Case ของคุณมากขึ้น เช่น กิจกรรม บุคคล MediaObject, Place หรือแม้แต่ประเภทที่มีความเฉพาะเจาะจงสูง เช่น MedicalEntity หากจำเป็น เมื่อคุณใช้ TypeScript คุณสามารถใช้เมธอด คำจำกัดความอินเทอร์เฟซจากคำจำกัดความของประเภท schema-dts
การส่งและรับข้อมูล JSON-LD จะรองรับเว็บที่เชื่อมต่อและเปิดกว้างมากขึ้น ด้วย แอปพลิเคชันที่พูดภาษาเดียวกัน คุณสามารถสร้าง การผสานรวมเชิงลึกกับภายนอกได้ แอปพลิเคชัน ไม่จำเป็นต้องผสานรวม API ที่ซับซ้อน ข้อมูลทั้งหมดที่จำเป็นคือ ที่รวมอยู่ในข้อมูลที่โอน
นึกถึงความเป็นไปได้ทั้งหมดในการโอนข้อมูลระหว่างแอปพลิเคชัน (เว็บ) ที่ไม่มี ข้อจำกัด: การแชร์กิจกรรมจากปฏิทินไปยังแอป ToDo ที่คุณชื่นชอบ การแนบไฟล์เสมือนไปยัง อีเมล การแชร์รายชื่อติดต่อ คงจะดีใช่ไหม เริ่มต้นจากตรงนี้ได้เลย! 🙌
ข้อกังวล
แม้ว่า 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, มีผู้สังเกตการณ์ที่จะตอบสนองต่อเหตุการณ์การโอนสำหรับ การไฮไลต์พื้นที่แบบเลื่อนลง และให้คุณผสานรวมการดำเนินการโอนข้อมูลระหว่างการลากและวางที่มีอยู่ การนำไปใช้งานจริง
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 ใน หน้าจอแนะนํา