הסרת מחסומים באמצעות DataTransfer API

המשתמשים יכולים לשתף נתונים מחוץ לחלון הדפדפן.

אולי שמעתם על DataTransfer API, שהוא חלק מ-HTML5 Drag and Drop API ואירועי הלוח. אפשר להשתמש בו כדי להעביר נתונים בין המקור ליעד המקבל.

תמיכה בדפדפן

  • 3
  • 12
  • 3.5
  • 4

מקור

האינטראקציות של גרירה ושחרור והדבקה משמשות לעיתים קרובות לאינטראקציות בתוך הדף כדי להעביר טקסט פשוט מ-A ל-B. אבל לעיתים קרובות מתעלמים ממנו היכולת להשתמש באינטראקציות האלה כדי מעבר לחלון הדפדפן.

פעולות הגרירה והשחרור המובנית בדפדפן וגם האינטראקציות של ההעתקה וההדבקה יכולות לתקשר עם אפליקציות אחרות, באינטרנט או בכל מקום אחר, והן לא קשורות לשום מקור. ה-API תומך במספר רשומות נתונים עם התנהגויות שונות, בהתאם למקום שאליו מועברים הנתונים. אפליקציית האינטרנט שלכם יכולה לשלוח ולקבל את הנתונים שהועברו במהלך האזנה לאירועים נכנסים.

היכולת הזו יכולה לשנות את הדרך שבה אנחנו מתייחסים לשיתוף וליכולת פעולה הדדית באפליקציות אינטרנט במחשב. העברת הנתונים בין אפליקציות לא צריכה להסתמך יותר על שילובים הדוקים. במקום זאת, אפשר לתת למשתמשים שליטה מלאה על העברת הנתונים לכל מקום שירצו.

דוגמה לאינטראקציות אפשריות עם DataTransfer 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:

  • text/html: עיבוד של המטען הייעודי (payload) של HTML ברכיבי contentEditable ובעורכי טקסט עשיר (WYSIWYG) כמו Google Docs , Microsoft Word ואחרים.
  • text/plain: קובע את הערך של רכיבי הקלט, התוכן של עורכי הקוד והחלופה ל-text/html.
  • text/uri-list: מנווט לכתובת ה-URL כשמשחררים אותו בסרגל כתובות ה-URL או בדף הדפדפן. ייווצר קיצור דרך לכתובת ה-URL כשתשחררו את הספרייה או את שולחן העבודה.

השימוש הנרחב של text/html בעורכי WYSIWYG הופך אותו למועיל מאוד. כמו במסמכי HTML, אפשר להטמיע משאבים באמצעות כתובות URL של נתונים או כתובות URL נגישות באופן ציבורי, כדי לעשות זאת היטב כשמייצאים רכיבים חזותיים (למשל מלוח הציור) לעורכים כמו Google Docs.

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 (נתונים מקושרים) הוא מועמד נהדר לכך. הוא קל לקריאה ולכתיבה ב-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 שנה. חשבו כמה פעמים השתמשתם באינטראקציות האלה לארגון קבצים. מצב זה עדיין לא נפוץ מאוד באינטרנט.

יהיה עליך ללמד את המשתמשים על האינטראקציה החדשה הזו, ולחשוב על דפוסי חוויית משתמש כדי שניתן יהיה לזהות את זה, במיוחד לאנשים שעד עכשיו הניסיון שלהם במחשבים מוגבל למכשירים ניידים.

נגישות

תהליך גרירה ושחרור אינו נגיש מאוד, אך ממשק ה-API של DataTransfer פועל גם עם העתקה-הדבקה. הקפידו להאזין לאירועים של העתקה-הדבקה. זה לא דורש הרבה עבודה נוספת, והמשתמשים שלכם יהיו אסירי תודה על הוספתם.

אבטחה ופרטיות

יש כמה שיקולי אבטחה ופרטיות שכדאי להיות מודעים אליהם כשמשתמשים בשיטה הזו.

  • נתוני הלוח זמינים לאפליקציות אחרות במכשיר של המשתמש.
  • לאפליקציות אינטרנט שאתם גוררים עליהן יש גישה למקשי הסוג, ולא לנתונים. הנתונים הופכים לזמינים רק לאחר שחרור או הדבקה.
  • יש להתייחס לנתונים שהתקבלו כמו לכל קלט אחר של משתמשים. יש לנקות ולאמת אותם לפני השימוש.

תחילת העבודה עם ספריית העזרה של 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);

אישורים

תמונה ראשית (Hero) מאת Luba Ertel באתר UnFlood.