تجاوز العوائق باستخدام واجهة برمجة التطبيقات DataTransfer API

تمكين المستخدم من مشاركة البيانات خارج نافذة المتصفح.

ربما تكون قد سمعت عن DataTransfer API، وهي من واجهة برمجة تطبيقات "السحب والإفلات" في HTML5 وأحداث الحافظة. مُمْكِنْ تُستخدم لنقل البيانات بين المصدر والأهداف المستلمة.

دعم المتصفح

  • Chrome: 3-
  • الحافة: 12.
  • Firefox: 3.5
  • Safari: الإصدار 4-

المصدر

غالبًا ما يتم استخدام تفاعلات السحب والإفلات والنسخ واللصق للتفاعلات داخل الصفحة لنقل النص البسيط من النقطة "أ" إلى "ب". ولكن ما يتم تجاهله في كثير من الأحيان هو القدرة على استخدام هذه التفاعلات نفسها لتجاوز نافذة المتصفح.

يمكن لكل من التفاعل عن طريق السحب والإفلات المدمج في المتصفح وتفاعلات النسخ واللصق مع تطبيقات أخرى أو ويب أو غيرها، ولا تكون مرتبطة بأي مصدر. تتيح واجهة برمجة التطبيقات العديد من إدخالات البيانات ذات السلوكيات المختلفة استنادًا إلى المكان الذي يتم نقل البيانات إليه. إرسال واستقبال البيانات المنقولة عند الاستماع إلى الأحداث الواردة.

وقد تغيّر هذه الميزة طريقة تفكيرنا في المشاركة وإمكانية التشغيل التفاعلي على الويب. التطبيقات على سطح المكتب. لا يحتاج نقل البيانات بين التطبيقات إلى الاعتماد على عمليات دمج مترابطة بإحكام بعد الآن. بدلاً من ذلك، يمكنك منح المستخدمين تحكمًا كاملاً لنقل البيانات البيانات إلى أي مكان يريدونه.

مثال على التفاعلات التي يمكن إجراؤها باستخدام واجهة برمجة التطبيقات DataTransfer 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: يعرض حمولة HTML بعناصر contentEditable الغنية بصريًا (WYSIWYG) مثل برامج تحرير مستندات Google وMicrosoft Word وغيرها.
  • text/plain: تضبط قيمة عناصر الإدخال ومحتوى أدوات تحرير الرموز والعنصر الاحتياطي من text/html.
  • text/uri-list: للانتقال إلى عنوان URL عند ظهوره في شريط عنوان URL أو صفحة المتصفّح. عنوان URL سيتم إنشاء اختصار عند إفلاته في دليل أو على سطح المكتب.

إن الاعتماد على نطاق واسع لـ text/html من قِبل محرري WYSIWYG يجعله مفيدًا للغاية. كما في HTML المستندات، يمكنك تضمين الموارد باستخدام عناوين 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 مع تفاعلات النسخ واللصق. لاحظ أن يتم عرض الكائن 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 وتلقّيها، سيكون بإمكانك توفير شبكة ويب أكثر ارتباطًا وانفتاحًا. مع التطبيقات التي تتحدث اللغة نفسها، فيمكنك إنشاء تكاملات متعمقة مع التطبيقات. ليست هناك حاجة إلى عمليات دمج واجهة برمجة تطبيقات معقدة، فإن جميع المعلومات المطلوبة تضمينها في البيانات المنقولة.

فكر في كل احتمالات نقل البيانات بين أي تطبيق (ويب) بدون القيود: مشاركة الأحداث من تقويم إلى تطبيق قائمة المهام المفضل لديك، وإرفاق الملفات الافتراضية بـ ورسائل البريد الإلكتروني ومشاركة جهات الاتصال. سيكون ذلك رائعًا، أليس كذلك؟ هذا يبدأ معك! 🙌

المخاوف والمشاكل الطبية

على الرغم من توفُّر واجهة برمجة التطبيقات DataTransfer API اليوم، هناك بعض النقاط التي يجب أن تكون على دراية بها قبل الدمج.

توافُق المتصفح

تدعم جميع متصفحات سطح المكتب بشكل كبير الأسلوب الموضح أعلاه، بينما تدعم الأجهزة المحمولة لا. تم اختبار الأسلوب على جميع المتصفحات الرئيسية (Chrome وEdge وFirefox وSafari) و أنظمة التشغيل (Android وChromeOS وiOS وmacOS وUbuntu Linux وWindows)، لكن للأسف Android لم يجتَز نظام التشغيل iOS الاختبار. وبينما تستمر المتصفّحات في التطوير، فإن الأسلوب محدود في الوقت الحالي المتصفحات المتوافقة مع أجهزة الكمبيوتر المكتبي فقط

سهولة العثور على المحتوى

السحب والإفلات والنسخ واللصق هما تفاعلات على مستوى النظام عند العمل على كمبيوتر مكتبي، مع إلى أول واجهة مستخدم تصويرية قبل أكثر من 40 عامًا. فكر في عدد المرات التي هذه التفاعلات لتنظيم الملفات. وهذا ليس شائعًا على الويب إلى الآن.

ستحتاج إلى تعريف المستخدمين بهذا التفاعل الجديد، والتوصل إلى أنماط تجربة مستخدم لجعل ذلك يمكن التعرف عليها، خاصة للأشخاص الذين تقتصر تجربتهم مع أجهزة الكمبيوتر حتى الآن على الأجهزة المحمولة.

تسهيل الاستخدام

لا يعتبر السحب والإفلات تفاعلاً يسهل الوصول إليه، ولكن واجهة برمجة التطبيقات DataTransfer API تعمل مع النسخ واللصق أيضًا. تأكَّد من الاستماع إلى أحداث النسخ واللصق. لن يتطلب الأمر الكثير من العمل الإضافي، وسيكون ممتنًا لك لإضافته.

الأمان والخصوصية

هناك بعض اعتبارات الأمان والخصوصية التي يجب أن تكون على دراية بها عند استخدام هذا الأسلوب.

  • تتوفّر بيانات الحافظة للتطبيقات الأخرى على جهاز المستخدم.
  • تطبيقات الويب التي تسحبها يمكنها الوصول إلى أنواع المفاتيح، وليس البيانات. البيانات فقط يصبح متاحًا عند الإفلات أو اللصق.
  • يجب التعامل مع البيانات المُستلَمة مثل أي بيانات إدخال أخرى للمستخدم. وتصححها والتحقق من صحتها قبل استخدامها.

بدء استخدام مكتبة Transmat المساعدة

هل أنت متحمس لاستخدام واجهة برمجة التطبيقات DataTransfer API في تطبيقك؟ ننصحك بإلقاء نظرة على مكتبة النقل على 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);

شكر وتقدير

الصورة الرئيسية التي رسمها لوبا إرتل على إزالة البداية