อนุญาตให้ผู้ใช้แชร์ข้อมูลนอกหน้าต่างเบราว์เซอร์
คุณอาจเคยได้ยินเกี่ยวกับ DataTransfer API ซึ่งเป็นส่วนหนึ่งของ HTML5 Drag and Drop API และเหตุการณ์คลิปบอร์ด โดยใช้เพื่อโอนข้อมูลระหว่างต้นทางและเป้าหมายที่รับได้
การโต้ตอบแบบลากและวางและคัดลอกและวางมักจะใช้สำหรับการโต้ตอบภายในหน้าเว็บเพื่อโอนข้อความธรรมดาจาก 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 Text (WYSIWYG) เช่น Google เอกสาร, Microsoft Word และอื่นๆtext/plain:
ตั้งค่าขององค์ประกอบอินพุต เนื้อหาของตัวแก้ไขโค้ด และรายการสำรองจากtext/html
text/uri-list
: ไปที่ URL เมื่อวางในแถบ URL หรือหน้าเบราว์เซอร์ ระบบจะสร้างทางลัด URL เมื่อวางในไดเรกทอรีหรือเดสก์ท็อป
การใช้ text/html
โดยเอดิเตอร์ของ WYSIWYG อย่างแพร่หลายมีประโยชน์อย่างมาก เช่นเดียวกับในเอกสาร HTML คุณจะฝังทรัพยากรโดยใช้ URL ข้อมูลหรือ URL ที่เข้าถึงได้แบบสาธารณะ ซึ่งวิธีนี้ได้ผลดีกับการส่งออกภาพ (เช่น จาก 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 กับการโต้ตอบคัดลอกและวางจะแสดงอยู่ด้านล่าง โปรดสังเกตว่าพร็อพเพอร์ตี้ชื่อ 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 ทั่วไปหรือใช้ประเภทที่ใกล้กับกรณีการใช้งานของคุณมากขึ้น เช่น Event, Person, 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 ใน Unsplash