آموزش HTML - کشیدن و رها کردن API

رابط برنامه‌نویسی Drag and Drop (کشیدن و رها کردن)

کشیدن و رها کردن (Drag and Drop یا به اختصار DnD) یک مفهوم قدرتمند در رابط کاربری است که کپی کردن، تغییر ترتیب و حذف آیتم‌ها را به کمک کلیک و حرکت‌های ماوس آسان می‌سازد. این ویژگی به کاربر اجازه می‌دهد تا کلیک کند و دکمه ماوس را روی یک عنصر نگه دارد، آن را به محل دیگری بکشد و با رها کردن دکمه ماوس، عنصر را در آنجا بیندازد.

برای دستیابی به قابلیت کشیدن و رها کردن در HTML4 سنتی، توسعه‌دهندگان مجبور بودند یا از برنامه‌نویسی پیچیده JavaScript استفاده کنند یا از فریم‌ورک‌های دیگر JavaScript مانند jQuery و غیره بهره ببرند.

اکنون HTML5 با ارائه یک Drag and Drop (DnD) API پشتیبانی نیتیو (داخلی) از DnD را به مرورگر آورده است که کدنویسی آن را بسیار آسان‌تر می‌کند. این ویژگی توسط تمامی مرورگرهای اصلی مانند Chrome، Firefox 3.5، Safari 4 و غیره پشتیبانی می‌شود.

قابل کشیدن کردن یک عنصر HTML

شما می‌توانید با استفاده از صفت draggable برای یک عنصر خاص، آن عنصر HTML را قابل کشیدن کنید. مقدار "true" را برای صفت draggable تنظیم کنید تا هر عنصر HTML مانند تصاویر، divها، فایل‌ها یا لینک‌ها، قابلیت کشیده شدن پیدا کنند.

سنتکس (نحو)

سنتکس زیر، نحوه قابل کشیدن کردن یک عنصر div را نشان می‌دهد:

<div draggable="true">

رویدادهای Drag and Drop

تعدادی رویداد وجود دارند که در مراحل مختلف عملیات کشیدن و رها کردن فراخوانی می‌شوند. این رویدادها در زیر فهرست شده‌اند −

شماره رویدادها و توضیحات
1

dragstart

زمانی فراخوانی می‌شود که کاربر شروع به کشیدن عنصر می‌کند.

2

dragenter

زمانی فراخوانی می‌شود که ماوس برای اولین بار در حین کشیدن روی عنصر مقصد قرار می‌گیرد. شنونده (Listener) این رویداد باید مشخص کند که آیا رها کردن عنصر در این محل مجاز است یا خیر. اگر هیچ شنونده‌ای وجود نداشته باشد یا شنونده‌ها هیچ عملیاتی انجام ندهند، رها کردن به طور پیش‌فرض مجاز نخواهد بود.

3

dragover

این رویداد زمانی فراخوانی می‌شود که ماوس در حین کشیدن، روی یک عنصر حرکت می‌کند. در بیشتر مواقع، عملیاتی که در شنونده این رویداد رخ می‌دهد، همانند رویداد dragenter است.

4

dragleave

این رویداد زمانی فراخوانی می‌شود که ماوس در حین کشیدن، از روی یک عنصر خارج می‌شود. شنونده‌ها باید هرگونه هایلایت یا نشانگر ادغامی را که برای بازخورد رها کردن استفاده شده بود، حذف کنند.

5

drag

هر بار که ماوس در حین کشیدن عنصر حرکت می‌کند، فراخوانی می‌شود.

6

drop

رویداد drop در پایان عملیات کشیدن، روی عنصری که رها کردن در آن اتفاق افتاده فراخوانی می‌شود. یک شنونده مسئول بازیابی داده‌های در حال کشیده شدن و قرار دادن آن‌ها در محل رها کردن خواهد بود.

7

dragend

زمانی فراخوانی می‌شود که کاربر دکمه ماوس را هنگام کشیدن یک عنصر رها می‌کند.

توجه − توجه داشته باشید که فقط رویدادهای کشیدن (drag events) فراخوانی می‌شوند؛ رویدادهای ماوس مانند mousemove در طول عملیات کشیدن فراخوانی نمی‌شوند.

شیء DataTransfer

متدهای شنونده رویداد برای تمامی رویدادهای کشیدن و رها کردن، شیء Event را می‌پذیرند که دارای یک صفت فقط‌خواندنی (readonly) به نام dataTransfer است.

عبارت event.dataTransfer شیء DataTransfer مرتبط با رویداد را به صورت زیر برمی‌گرداند:

function EnterHandler(event) {
   DataTransfer dt = event.dataTransfer;
   .............
}

شیء DataTransfer داده‌های مربوط به عملیات کشیدن و رها کردن را در خود نگه می‌دارد. این داده‌ها را می‌توان بر اساس صفات مختلف مرتبط با شیء DataTransfer، همان‌طور که در زیر توضیح داده شده است، بازیابی و تنظیم کرد −

شماره صفت و توضیحات
1

dataTransfer.dropEffect [ = value ]

  • نوع عملیاتی را که در حال حاضر انتخاب شده است برمی‌گرداند.

  • این صفت را می‌توان برای تغییر عملیات انتخاب‌شده تنظیم کرد.

  • مقادیر ممکن عبارتند از: none، copy، link و move.

2

dataTransfer.effectAllowed [ = value ]

  • انواع عملیاتی را که مجاز هستند برمی‌گرداند.

  • این صفت را می‌توان برای تغییر عملیات مجاز تنظیم کرد.

  • مقادیر ممکن عبارتند از: none، copy، copyLink، copyMove، link، linkMove، move، all و uninitialized.

3

dataTransfer.types

یک DOMStringList شامل فرمت‌هایی که در رویداد dragstart تنظیم شده‌اند را برمی‌گرداند. علاوه بر این، اگر فایلی در حال کشیده شدن باشد، یکی از انواع (types) رشته "Files" خواهد بود.

4

dataTransfer.clearData ( [ format ] )

داده‌های فرمت‌های مشخص‌شده را حذف می‌کند. اگر آرگومان حذف شود، همه داده‌ها را پاک می‌کند.

5

dataTransfer.setData(format, data)

داده‌های مشخص‌شده را اضافه می‌کند.

6

data = dataTransfer.getData(format)

داده‌های مشخص‌شده را برمی‌گرداند. اگر چنین داده‌ای وجود نداشته باشد، یک رشته خالی برمی‌گرداند.

7

dataTransfer.files

یک FileList از فایل‌های در حال کشیده شدن (در صورت وجود) را برمی‌گرداند.

8

dataTransfer.setDragImage(element, x, y)

از عنصر داده‌شده برای به‌روزرسانی بازخورد visual کشیدن استفاده می‌کند و جایگزین هر بازخورد قبلی می‌شود.

9

dataTransfer.addElement(element)

عنصر داده‌شده را به لیست عناصر مورد استفاده برای رندر بازخورد کشیدن اضافه می‌کند.

فرآیند Drag and Drop

مراحل زیر برای پیاده‌سازی عملیات کشیدن و رها کردن باید انجام شوند −

مرحله ۱ − قابل کشیدن کردن یک شیء

مراحلی که باید طی شوند به شرح زیر است −

  • اگر می‌خواهید عنصری را بکشید، باید صفت draggable را برای آن عنصر برابر با true قرار دهید.

  • یک شنونده رویداد برای dragstart تنظیم کنید که داده‌های در حال کشیده شدن را ذخیره کند.

  • شنونده رویداد dragstart افکت‌های مجاز (copy، move، link یا ترکیبی از آن‌ها) را تعیین می‌کند.

مثال

در ادامه مثالی از قابل کشیدن کردن یک شیء آورده شده است −

<!DOCTYPE html>
<html>
<head>
   <style type="text/css">
      #boxA,
      #boxB {
         float: left;
         padding: 10px;
         margin: 10px;
         -moz-user-select: none;
      }
      #boxA {
         background-color: #6633FF;
         width: 75px;
         height: 75px;
      }
      #boxB {
         background-color: #FF6699;
         width: 150px;
         height: 150px;
      }
   </style>
   <script type="text/javascript">
      function dragStart(ev) {
         ev.dataTransfer.effectAllowed = 'move';
         ev.dataTransfer.setData("Text", ev.target.getAttribute('id'));
         ev.dataTransfer.setDragImage(ev.target, 0, 0);
         return true;
      }
   </script>
</head>
<body>
   <center>
      <h2>Drag and drop HTML5 demo</h2>
      <div>Try to drag the purple box around.</div>
      <div id="boxA" draggable="true" ondragstart="return dragStart(event)">
         <p>Drag Me</p>
      </div>
      <div id="boxB">Dustbin</div>
   </center>
</body>
</html>

مرحله ۲ − رها کردن شیء

برای پذیرش رها کردن، مقصد رها کردن (drop target) باید حداقل به سه رویداد گوش دهد.

  • رویداد dragenter که برای تعیین این‌که آیا مقصد باید رها کردن را بپذیرد یا خیر استفاده می‌شود. اگر قرار است رها کردن پذیرفته شود، این رویداد باید لغو (cancel) شود.

  • رویداد dragover که برای تعیین این‌که چه بازخوردی به کاربر نشان داده شود استفاده می‌شود. اگر رویداد لغو شود، بازخورد (معمولاً مکان‌نما) بر اساس مقدار صفت dropEffect به‌روزرسانی می‌شود.

  • در نهایت، رویداد drop که اجازه می‌دهد عملیات اصلی رها کردن انجام شود.

مثال

در ادامه مثالی از رها کردن یک شیء درون شیء دیگر آورده شده است −

<!DOCTYPE html>
<html>
<head>
   <style type="text/css">
      #boxA,
      #boxB {
         float: left;
         padding: 10px;
         margin: 10px;
         -moz-user-select: none;
      }

      #boxA {
         background-color: #6633FF;
         width: 75px;
         height: 75px;
      }

      #boxB {
         background-color: #FF6699;
         width: 150px;
         height: 150px;
      }
   </style>
   <script type="text/javascript">
      function dragStart(ev) {
         ev.dataTransfer.effectAllowed = 'move';
         ev.dataTransfer.setData("Text", ev.target.getAttribute('id'));
         ev.dataTransfer.setDragImage(ev.target, 0, 0);
         return true;
      }

      function dragEnter(ev) {
         event.preventDefault();
         return true;
      }

      function dragOver(ev) {
         return false;
      }

      function dragDrop(ev) {
         var src = ev.dataTransfer.getData("Text");
         ev.target.appendChild(document.getElementById(src));
         ev.stopPropagation();
         return false;
      }
   </script>
</head>
<body>
   <center>
      <h2>Drag and drop HTML5 demo</h2>
      <div>Try to move the purple box into the pink box.</div>
      <div id="boxA" draggable="true" ondragstart="return dragStart(event)">
         <p>Drag Me</p>
      </div>
      <div id="boxB" ondragenter="return dragEnter(event)" ondrop="return dragDrop(event)" ondragover="return dragOver(event)">Dustbin</div>
   </center>
</body>
</html>

پیشرفت مطالعه: وضعیت خوانده‌شدن این درس فقط در همین مرورگر ذخیره می‌شود؛ بدون نیاز به حساب کاربری.