واجهة برمجة التطبيقات لسحب وإفلات HTML5

تشرح هذه المشاركة أساسيات السحب والإفلات.

إنشاء محتوى قابل للسحب

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

لإتاحة سحب كائن، اضبط draggable=true على هذا العنصر. تقريبًا فيمكن أن يكون أي شيء مع تمكين السحب، بما في ذلك الصور والملفات والروابط والملفات أو أي الترميز على صفحتك.

ينشئ المثال التالي واجهة لإعادة ترتيب الأعمدة التي الموضوعة باستخدام CSS Grid. يبدو الترميز الأساسي للأعمدة على هذا النحو، السمة draggable لكل عمود تم ضبطه على true:

<div class="container">
  <div draggable="true" class="box">A</div>
  <div draggable="true" class="box">B</div>
  <div draggable="true" class="box">C</div>
</div>

في ما يلي CSS لعنصرَي الحاوية والمربّع. خدمة CSS الوحيدة المرتبطة ميزة السحب هي cursor: move الموقع. يتحكم باقي الرمز في تنسيق الحاوية وتصميمها وعناصر المربع.

.container {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
}

.box {
  border: 3px solid #666;
  background-color: #ddd;
  border-radius: .5em;
  padding: 10px;
  cursor: move;
}

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

الاستماع إلى أحداث السحب

لمراقبة عملية السحب، يمكنك رصد أي من الأحداث التالية:

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

بدء تسلسل سحب وإنهائه

بعد تحديد سمات draggable="true" في المحتوى الخاص بك، عليك إرفاق معالِج أحداث dragstart لبدء تسلسل السحب لكل عمود

يضبط هذا الرمز معدل شفافية العمود على 40٪ عندما يبدأ المستخدم في سحبه، ثم إرجاعه إلى 100% عند انتهاء حدث السحب.

function handleDragStart(e) {
  this.style.opacity = '0.4';
}

function handleDragEnd(e) {
  this.style.opacity = '1';
}

let items = document.querySelectorAll('.container .box');
items.forEach(function (item) {
  item.addEventListener('dragstart', handleDragStart);
  item.addEventListener('dragend', handleDragEnd);
});

ويمكن الاطّلاع على النتيجة في العرض التوضيحي التالي لتطبيق Glitch. سحب عنصر تغييرات التعتيم. ولأن العنصر المصدر يحتوي على الحدث dragstart، فقد تم ضبط إعداد تقدم نسبة this.style.opacity إلى 40٪ للمستخدم ملاحظات مرئية أن هذا العنصر التحديد الحالي الذي يتم نقله. عند إسقاط العنصر، يتم عرض عنصر المصدر يعود إلى معدل تعتيم 100%، على الرغم من أنك لم تحدد سلوك الانخفاض في الوقت الحالي.

إضافة إشارات مرئية أخرى

لمساعدة المستخدم في فهم كيفية التفاعل مع واجهتك، استخدِم معالِجات أحداث dragenter وdragover وdragleave في هذا المثال، تشير والأعمدة هي أهداف للإفلات بالإضافة إلى كونها قابلة للسحب. ساعد المستخدم في فهم ذلك عن طريق جعل الحدود متقطعة عندما تحمل عنصرًا تم سحبه فوق . على سبيل المثال، في خدمة مقارنة الأسعار (CSS)، يمكنك إنشاء فئة over العناصر التي تُعدّ أهدافًا الانخفاض:

.box.over {
  border: 3px dotted #666;
}

بعد ذلك، يمكنك إعداد معالِجات الأحداث في JavaScript وإضافة الفئة over عند يتم سحب العمود وإزالته عندما يغادر العنصر الذي تم سحبه. ضِمن إلى معالج dragend، نحرص أيضًا على إزالة الفئات في نهاية السحب.

document.addEventListener('DOMContentLoaded', (event) => {

  function handleDragStart(e) {
    this.style.opacity = '0.4';
  }

  function handleDragEnd(e) {
    this.style.opacity = '1';

    items.forEach(function (item) {
      item.classList.remove('over');
    });
  }

  function handleDragOver(e) {
    e.preventDefault();
    return false;
  }

  function handleDragEnter(e) {
    this.classList.add('over');
  }

  function handleDragLeave(e) {
    this.classList.remove('over');
  }

  let items = document.querySelectorAll('.container .box');
  items.forEach(function(item) {
    item.addEventListener('dragstart', handleDragStart);
    item.addEventListener('dragover', handleDragOver);
    item.addEventListener('dragenter', handleDragEnter);
    item.addEventListener('dragleave', handleDragLeave);
    item.addEventListener('dragend', handleDragEnd);
    item.addEventListener('drop', handleDrop);
  });
});

هناك عدة نقاط تستحق تناولها في هذه التعليمة البرمجية:

  • الإجراء التلقائي بالنسبة إلى الحدث dragover هو ضبط الخاصية dataTransfer.dropEffect على "none" وسنتناول السمة dropEffect لاحقًا في هذه الصفحة. في الوقت الحالي، فقط، اعلم أنه يمنع تنشيط حدث drop. لإلغاء هذا السلوك، طلب e.preventDefault(). هناك ممارسة جيدة أخرى وهي عرض false في المعالج نفسه.

  • يُستخدَم معالج أحداث dragenter لتبديل الفئة over بدلاً من dragover في حال استخدام dragover، يتم تنشيط الحدث بشكل متكرّر أثناء استخدام المستخدِم. تحتفظ بالعنصر المسحوب فوق عمود، مما يتسبب في تبديل فئة CSS بشكل متكرر. يؤدي ذلك إلى إجراء المتصفّح الكثير من أعمال العرض غير الضرورية، مما قد يؤثر على تجربة المستخدم. نوصي بشدة بتقليل وإعادة الرسم، وإذا كنت بحاجة إلى استخدام dragover، يمكنك تقييد أداة معالجة الحدث أو إقلاعها

إكمال عملية الهبوط

لمعالجة عملية الانخفاض، أضِف أداة معالجة حدث drop. في drop فستحتاج إلى منع السلوك الافتراضي للمتصفح لعمليات الإزالة، يكون عادةً نوعًا من عمليات إعادة التوجيه المزعجة. ولإجراء ذلك، اتّصِل بالرقم e.stopPropagation().

function handleDrop(e) {
  e.stopPropagation(); // stops the browser from redirecting.
  return false;
}

تأكد من تسجيل المعالج الجديد إلى جانب المعالجات الأخرى:

  let items = document.querySelectorAll('.container .box');
  items.forEach(function(item) {
    item.addEventListener('dragstart', handleDragStart);
    item.addEventListener('dragover', handleDragOver);
    item.addEventListener('dragenter', handleDragEnter);
    item.addEventListener('dragleave', handleDragLeave);
    item.addEventListener('dragend', handleDragEnd);
    item.addEventListener('drop', handleDrop);
  });

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

تحتفظ السمة dataTransfer بالبيانات المُرسَلة في إجراء سحب. dataTransfer يتم ضبطها في الحدث dragstart وتتم قراءتها أو معالجتها في حدث الإفلات. إجراء المكالمات يتيح لك "e.dataTransfer.setData(mimeType, dataPayload)" ضبط بروتوكول MIME للكائن النوع وحمولة البيانات.

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

function handleDragStart(e) {
  this.style.opacity = '0.4';

  dragSrcEl = this;

  e.dataTransfer.effectAllowed = 'move';
  e.dataTransfer.setData('text/html', this.innerHTML);
}

في الحدث drop، يمكنك معالجة انخفاض العمود من خلال ضبط قيمة HTML في HTML للعمود المستهدف الذي خفضت البيانات إليه. هذا النمط التحقق من أن المستخدم لا يعود إلى نفس العمود الذي سحبها منه.

function handleDrop(e) {
  e.stopPropagation();

  if (dragSrcEl !== this) {
    dragSrcEl.innerHTML = this.innerHTML;
    this.innerHTML = e.dataTransfer.getData('text/html');
  }

  return false;
}

يمكنك مشاهدة النتيجة في العرض التوضيحي التالي. لكي ينجح ذلك، ستحتاج إلى متصفح سطح المكتب. لا تتوفّر واجهة برمجة التطبيقات "السحب والإفلات" على الأجهزة الجوّالة. السحب حرر العمود A أعلى العمود B ولاحظ كيف تغير الأماكن:

المزيد من خصائص السحب

يعرض الكائن dataTransfer السمات لتقديم ملاحظات مرئية إلى المستخدم أثناء عملية السحب والتحكم في كيفية استجابة كل هدف إفلات لنوع بيانات معين.

  • dataTransfer.effectAllowed يقيد "نوع السحب" يمكن للمستخدم تنفيذها على العنصر. إنها مُستخدَمة في نموذج معالجة السحب والإفلات لإعداد dropEffect أثناء حدثين dragenter وdragover. يمكن أن يتضمّن الموقع القيم التالية: none، copy، copyLink، copyMove، link، linkMove، move وall وuninitialized.
  • dataTransfer.dropEffect تتحكّم هذه السياسة في الملاحظات التي يتلقّاها المستخدم خلال dragenter وdragover. أحداث. عندما يمسك المستخدم بالمؤشر فوق عنصر هدف، فإن واجهة يشير المؤشر إلى نوع العملية التي ستحدث، مثل نسخ أو حركة. يمكن أن يحصل التأثير على إحدى القيم التالية: none أو copy أو link، move.
  • e.dataTransfer.setDragImage(imgElement, x, y) بمعنى أنه بدلاً من استخدام "صورة شبح" الافتراضية في المتصفح الملاحظات، تعيين أيقونة السحب.

تحميل ملف

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

يتم استخدام السحب والإفلات بشكل متكرر للسماح للمستخدمين بسحب العناصر من سطح المكتب إلى أحد التطبيقات. يكمن الاختلاف الرئيسي في معالِج drop. بدلاً من استخدام dataTransfer.getData() للوصول إلى الملفات، يتم تضمين بياناتها في السمة dataTransfer.files:

function handleDrop(e) {
  e.stopPropagation(); // Stops some browsers from redirecting.
  e.preventDefault();

  var files = e.dataTransfer.files;
  for (var i = 0, f; (f = files[i]); i++) {
    // Read the File objects in this FileList.
  }
}

يمكنك العثور على مزيد من المعلومات حول هذا الموضوع في السحب والإفلات المخصّص:

مزيد من الموارد