HTML5 ড্র্যাগ অ্যান্ড ড্রপ এপিআই

এই পোস্টটি ড্র্যাগ অ্যান্ড ড্রপের মূল বিষয়গুলি ব্যাখ্যা করে৷

বেশিরভাগ ব্রাউজারে, পাঠ্য নির্বাচন, ছবি এবং লিঙ্কগুলি ডিফল্টরূপে টেনে নেওয়া যায়। উদাহরণস্বরূপ, যদি আপনি একটি ওয়েব পৃষ্ঠায় একটি লিঙ্ক টেনে আনেন তবে আপনি একটি শিরোনাম এবং URL সহ একটি ছোট বাক্স দেখতে পাবেন যা আপনি একটি শর্টকাট তৈরি করতে বা লিঙ্কটিতে নেভিগেট করতে ঠিকানা বার বা ডেস্কটপে ড্রপ করতে পারেন৷ অন্যান্য ধরনের বিষয়বস্তু টেনে আনার যোগ্য করতে, আপনাকে HTML5 টেনে আনতে হবে এবং এপিআই ব্যবহার করতে হবে।

একটি বস্তুকে টেনে আনার যোগ্য করতে, সেই উপাদানটিতে draggable=true সেট করুন। ছবি, ফাইল, লিঙ্ক, ফাইল বা আপনার পৃষ্ঠার যেকোন মার্কআপ সহ প্রায় যেকোনো কিছু টেনে-সক্ষম করা যেতে পারে।

নিচের উদাহরণটি CSS গ্রিড দিয়ে সাজানো কলামগুলিকে পুনরায় সাজানোর জন্য একটি ইন্টারফেস তৈরি করে। কলামগুলির জন্য মৌলিক মার্কআপটি এইরকম দেখায়, প্রতিটি কলামের জন্য 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 API ব্যবহার করতে হবে।

ঘটনা টেনে আনার জন্য শুনুন

টেনে আনার প্রক্রিয়াটি নিরীক্ষণ করতে, আপনি নিম্নলিখিত ইভেন্টগুলির যেকোনো একটি শুনতে পারেন:

ড্র্যাগ ফ্লো পরিচালনা করার জন্য, আপনার কিছু ধরণের উত্স উপাদান প্রয়োজন (যেখানে টেনে শুরু হয়), ডেটা পেলোড (যে জিনিসটি টেনে আনা হচ্ছে), এবং একটি লক্ষ্য (ড্রপ ধরার জন্য একটি এলাকা)। উৎস উপাদান প্রায় যেকোনো ধরনের উপাদান হতে পারে। লক্ষ্য হল ড্রপ জোন বা ড্রপ জোনের সেট যা ব্যবহারকারী যে ডেটা ড্রপ করার চেষ্টা করছে তা গ্রহণ করে। সব উপাদান লক্ষ্য হতে পারে না. উদাহরণস্বরূপ, আপনার লক্ষ্য একটি চিত্র হতে পারে না.

একটি টেনে আনার ক্রম শুরু করুন এবং শেষ করুন

আপনি আপনার সামগ্রীতে 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);
});

ফলাফল নিম্নলিখিত গ্লিচ ডেমোতে দেখা যাবে। একটি আইটেম টেনে আনুন, এবং এর অস্বচ্ছতা পরিবর্তিত হয়। কারণ উৎস উপাদানটিতে dragstart ইভেন্ট রয়েছে, this.style.opacity 40% এ সেট করা ব্যবহারকারীকে ভিজ্যুয়াল প্রতিক্রিয়া দেয় যে সেই উপাদানটি বর্তমান নির্বাচন সরানো হচ্ছে। আপনি যখন আইটেমটি ড্রপ করেন, উত্স উপাদানটি 100% অস্বচ্ছতায় ফিরে আসে, যদিও আপনি এখনও ড্রপ আচরণটি সংজ্ঞায়িত করেননি।

অতিরিক্ত চাক্ষুষ সংকেত যোগ করুন

আপনার ইন্টারফেসের সাথে কীভাবে ইন্টারঅ্যাক্ট করতে হয় তা ব্যবহারকারীকে বুঝতে সাহায্য করার জন্য, dragenter , dragover এবং dragleave ইভেন্ট হ্যান্ডলার ব্যবহার করুন। এই উদাহরণে, কলামগুলি ড্র্যাগযোগ্য হওয়ার পাশাপাশি ড্রপ টার্গেট। যখন তারা একটি কলামের উপর একটি টেনে আনা আইটেম ধরে রাখে তখন সীমানা ড্যাশ করে এটি বুঝতে ব্যবহারকারীকে সহায়তা করুন৷ উদাহরণস্বরূপ, আপনার CSS-এ, আপনি ড্রপ লক্ষ্যমাত্রার উপাদানগুলির জন্য একটি over ক্লাস তৈরি করতে পারেন:

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

তারপর, আপনার জাভাস্ক্রিপ্টে, ইভেন্ট হ্যান্ডলার সেট আপ করুন, কলামটি টেনে নিয়ে গেলে 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 ইভেন্ট হ্যান্ডলারটি dragover পরিবর্তে over ক্লাস টগল করতে ব্যবহৃত হয়। আপনি 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 প্রকার এবং ডেটা পেলোড সেট করতে দেয়।

এই উদাহরণে, আমরা ব্যবহারকারীদের কলামের ক্রম পুনর্বিন্যাস করতে দেব। এটি করার জন্য, প্রথমে আপনাকে উৎস উপাদানের এইচটিএমএল সংরক্ষণ করতে হবে যখন ড্র্যাগ শুরু হবে:

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;
}

আপনি নিম্নলিখিত ডেমো ফলাফল দেখতে পারেন. এটি কাজ করার জন্য, আপনার একটি ডেস্কটপ ব্রাউজার প্রয়োজন হবে৷ ড্র্যাগ অ্যান্ড ড্রপ API মোবাইলে সমর্থিত নয়৷ B কলামের উপরে A কলাম টেনে আনুন এবং ছেড়ে দিন এবং লক্ষ্য করুন কিভাবে তারা স্থান পরিবর্তন করে:

আরও টেনে আনার বৈশিষ্ট্য

dataTransfer অবজেক্টটি টেনে আনার প্রক্রিয়া চলাকালীন ব্যবহারকারীকে ভিজ্যুয়াল ফিডব্যাক প্রদান করার জন্য বৈশিষ্ট্যগুলি প্রকাশ করে এবং প্রতিটি ড্রপ টার্গেট কীভাবে একটি নির্দিষ্ট ডেটা টাইপের প্রতিক্রিয়া জানায় তা নিয়ন্ত্রণ করে।

  • dataTransfer.effectAllowed এলিমেন্টে ব্যবহারকারী কী ধরনের 'ড্র্যাগ' করতে পারে তা সীমাবদ্ধ করে। এটি dragenter এবং dragover ইভেন্টের সময় dropEffect শুরু করতে ড্র্যাগ-এন্ড-ড্রপ প্রসেসিং মডেলে ব্যবহৃত হয়। সম্পত্তির নিম্নলিখিত মান থাকতে পারে: none , copy , copyLink , কপিমুভ , copyMove , link , move , all , এবং uninitialized linkMove
  • dataTransfer.dropEffect ব্যবহারকারী dragenter এবং dragover ইভেন্টের সময় যে প্রতিক্রিয়া পায় তা নিয়ন্ত্রণ করে। যখন ব্যবহারকারী একটি লক্ষ্য উপাদানের উপর তাদের পয়েন্টার ধরে রাখে, তখন ব্রাউজারের কার্সার নির্দেশ করে যে কোন ধরনের অপারেশন হতে চলেছে, যেমন একটি অনুলিপি বা সরানো। প্রভাব নিম্নলিখিত মানগুলির মধ্যে একটি গ্রহণ করতে পারে: none , copy , link , move
  • e.dataTransfer.setDragImage(imgElement, x, y) মানে ব্রাউজারের ডিফল্ট 'ভূতের ছবি' ফিডব্যাক ব্যবহার করার পরিবর্তে, আপনি একটি ড্র্যাগ আইকন সেট করতে পারেন।

ফাইল আপলোড

এই সাধারণ উদাহরণটি ড্র্যাগ সোর্স এবং টার্গেট টার্গেট উভয় হিসাবে একটি কলাম ব্যবহার করে। এটি একটি UI-তে ঘটতে পারে যা ব্যবহারকারীকে আইটেমগুলি পুনরায় সাজাতে বলে। কিছু পরিস্থিতিতে, ড্র্যাগ টার্গেট এবং সোর্স বিভিন্ন উপাদানের ধরন হতে পারে, যেমন একটি ইন্টারফেসে যেখানে ব্যবহারকারীকে একটি পণ্যের জন্য একটি ইমেজকে একটি টার্গেটে টেনে এনে একটি পণ্যের জন্য প্রধান ছবি হিসেবে নির্বাচন করতে হবে।

ড্র্যাগ অ্যান্ড ড্রপ প্রায়শই ব্যবহারকারীদের তাদের ডেস্কটপ থেকে আইটেমগুলিকে একটি অ্যাপ্লিকেশনে টেনে আনতে ব্যবহার করা হয়। প্রধান পার্থক্য হল আপনার 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.
  }
}

আপনি কাস্টম ড্র্যাগ-এন্ড-ড্রপ- এ এই সম্পর্কে আরও তথ্য পেতে পারেন।

আরও সম্পদ