قابلیت های Drag and Drop و Web Storage در HTML5

09 خرداد 1398
درسنامه درس 37 از سری آموزش صفر تا صد HTML
HTML-drag-and-drop-webstorage

Drag and Drop چیست؟

Drag and Drop یکی از قابلیت های رایج در برنامه های کامپیوتری است. در این قابلیت شما چیزی را با موس گرفته (drag) و در جایی می برید و آنجا رها (drop) می کنید. در HTML5 هر عنصری قابل drag شدن است و مشکلی سر راهمان نیست. وضعیت پشتیبانی از این ویژگی در مرورگر های مطرح دنیا به این شرح است:

مرورگر کروم فایرفاکس اپرا سافاری اینترنت اکسپلورر یا Edge
نسخه 4.0 3.5 12.0 6.0 9.0

به مثال زیر توجه کنید:

<!DOCTYPE HTML>
<html>
<head>
<style>
#div1 {
  width: 350px;
  height: 70px;
  padding: 10px;
  border: 1px solid #aaaaaa;
}
</style>
<script>
function allowDrop(ev) {
  ev.preventDefault();
}

function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
  ev.preventDefault();
  var data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>

<p dir='rtl'>لوگوی روکسو را گرفته (drag) و آن را داخل مستطیل بالا پایین رها (drop) کنید.</p>

<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<img id="drag1" src="https://www.roxo.ir/blog-panel/wp-content/uploads/2019/03/roxo-plus-new.png" draggable="true" ondragstart="drag(event)" width="236" height="79">

</body>
</html>

مشاهده ی خروجی در JSBin

شاید در نگاه اول برایتان عجیب و سخت باشد اما اینطور نیست. بگذارید آن را بررسی کنیم.

اولین قدم ما این است که تصویر را draggable (قابلیت Drag و کشیده شدن) کنیم. برای این کار از خصوصیت draggable استفاده می کنیم:

<img draggable="true">

سپس باید مشخص کنیم که اگر عنصر ما drag شد چه اتفاقی بیوفتد. در مثال بالا ondragstart تابعی را صدا می زند که مشخص می کند که چه محتوایی drag شود. متد ()dataTransfer.setData، نوع داده و مقدار محتوای Drag شده را مشخص می کند:

function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
}

در اینجا نوع داده text (یعنی متن) و مقدار هم id مربوط به عنصر drag شده است (drag1).

سپس رویداد ondragover مشخص می کند که محتوای drag شده در چه قسمتی می تواند drop شود. در حالت پیش فرض عناصر نمی توانند روی عناصر دیگر drop شوند بنابراین باید حالت پیش فرض را از بین ببریم. این کار را با استفاده از دستور ()event.preventDefault انجام می دهیم.

پس از اینکه عنصر مورد نظر drop شد، رویداد خاصی اجرا می شود. در مثال بالا attribute ای به نام ondrop تابعی به نام (drop(event را صدا می زند:

function drop(ev) {
  ev.preventDefault();
  var data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
}

توضیح این کد بدین صورت است: ابتدا ()preventDefault رفتار پیش فرض مرورگر را از بین می برد (در حالت پیش فرض این است که در زمان drop و رها سازی عنصر آن را به عنوان یک لینک باز کند). سپس عنصر drag شده را با استفاده از متد ()dataTransfer.getData می گیریم؛ این متد هر عنصری را برمیگرداند که در ()setData دارای type (نوع) یکسانی باشد. داده ی drag همان id مربوط به عنصر drag شده است (در مثال ما همان drag1). در آخر عنصر drag شده را به عنصر drop شده متصل می کنیم.

برای روشن تر شدن موضوع همین فرآیند را در قالب چند مثال دیگر مینویسیم:

<!DOCTYPE HTML>
<html>
<head>
<style>
#div1, #div2 {
  float: left;
  width: 100px;
  height: 35px;
  margin: 10px;
  padding: 10px;
  border: 1px solid black;
}
</style>
<script>
function allowDrop(ev) {
  ev.preventDefault();
}

function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
  ev.preventDefault();
  var data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>

<h2>Drag and Drop</h2>
<p dir='rtl'>لوگوی روکسو را بین دو مستطیل drag و drop کنید.</p>

<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
  <img src="https://www.roxo.ir/blog-panel/wp-content/uploads/2019/03/roxo-plus-new.png" draggable="true" ondragstart="drag(event)" id="drag1" width="88" height="31">
</div>

<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

</body>
</html>

مشاهده ی خروجی در JSBin

Web Storage چیست؟

با استفاده از Web Storage ها، وب سایت ها و برنامه های وب می توانند داده هایی را به صورت محلی در مرورگر کاربر ذخیره کنند. قبل از معرفی HTML5 تمامی این داده ها (حتی تمامی درخواست های سرور و ....) می بایست در کوکی ها ذخیره می شد اما Web storage ها امن تر هستند و می توان از طریق آن ها حجم بالایی از داده را در مرورگر کاربر ذخیره کرد بدون آنکه وب سایت مان را کند کنیم. بر خلاف کوکی ها که حداکثر سایزشان می تواند 4096 بایت (نه کیلو بایت) باشد، Web Storage ها می توانند مقدار بسیار بیشتری را در خود ذخیره کنند (حداقل 5 مگابایت) و اطلاعات نیز هیچ وقت به سرور منتقل نمی شوند. همچنین Web Storage ها بر اساس منبع عمل می کنند؛ یعنی تمام صفحات وبی که از یک منبع (یک دامنه یا پروتکل) باشند می توانند داده ها را ذخیره کرده و همگی به همان داده دسترسی داشته باشند.

پشتیبانی از Web Storage ها به شرح زیر است:

مرورگر کروم فایرفاکس اپرا سافاری اینترنت اکسپلورر یا Edge
نسخه 4.0 3.5 11.5 4.0 8.0

HTML دو شیء برای ذخیره ی داده ها در web storage به ما می دهد:

  • window.localStorage : داده ها را بدون زمان انقضاء ذخیره کنید.
  • window.sessionStorage : داده ها را برای یک نشست (session) ذخیره می کند و زمانی که پنجره یا tab مرورگر بسته شود داده ها نیز از بین می روند.

قبل از اینکه از web storage استفاده کنید با استفاده از کد زیر از پشتیبانی مرورگرتان از localStorage و sessionStorage مطمئن شوید:

if (typeof(Storage) !== "undefined") {
  // کد برای ذخیره سازی داده ها
} else {
  // متاسفانه مرورگر شما از web storage پشتیبانی نمی کند.
}

شیء localStorage

این شیء داده ها را بدون تاریخ انقضاء ذخیره می کند بنابراین زمانی که مرورگر بسته شود داده ها حذف نمی شوند و تا روز بعد، ماه بعد، سال بعد و ... در دسترس خواهند بود. مثال:

<!DOCTYPE html>
<html>
<body>

<div id="result"></div>

<script>
// Check browser support
if (typeof(Storage) !== "undefined") {
  // Store
  localStorage.setItem("lastname", "Smith");
  // Retrieve
  document.getElementById("result".innerHTML = localStorage.getItem("lastname");
} else {
  document.getElementById("result").innerHTML = "متاسفانه مرورگر شما از Web Storage پشتیبانی نمی کند.";
}
</script>

</body>
</html>

مشاهده ی خروجی در JSBin

در مثال بالا ابتدا یک جفت name/value به صورت "name="lastname و "value="Smith ساخته ایم. سپس مقدار lastname را گرفته و آن را داخل عنصری قرار داده ایم که id اش برابر با "id="result باشد. ما می توانستیم مثال بالا را به این شکل نیز بنویسیم:

// ذخیره سازی
localStorage.lastname = "Smith";
// دریافت
document.getElementById("result").innerHTML = localStorage.lastname;

نحوه ی حذف کردن lastname نیز به شکل زیر است:

localStorage.removeItem("lastname");

نکته: جفت های Name/value همیشه به عنوان رشته (String) ذخیره می شوند. اگر در فرمت دیگری به آن ها احتیاج دارید یادتان باشد که باید آن ها را تبدیل فرمت کنید؛ مثال زیر تعداد دفعاتی که کاربری روی دکمه ای کلیک کرده را می شمارد بنابراین باید رشته را تبدیل به عدد کنیم تا بتوانیم هر واحد را به صورت ریاضی به آن اضافه کنیم:

<!DOCTYPE html>
<html>
<head>
<script>
function clickCounter() {
  if (typeof(Storage) !== "undefined") {
    if (localStorage.clickcount) {
      localStorage.clickcount = Number(localStorage.clickcount)+1;
    } else {
      localStorage.clickcount = 1;
    }
    document.getElementById("result").innerHTML = "شما " + localStorage.clickcount + " بار روی دکمه کلیک کرده اید";
  } else {
    document.getElementById("result").innerHTML = "متاسفانه مرورگر شما از web storage پشتیبانی نمی کند.";
  }
}
</script>
</head>
<body>

<p><button onclick="clickCounter()" type="button">اینجا را کلیک کنید</button></p>
<div id="result"></div>
<p dir='rtl'>روی دکمه ی بالا کلیک کنید تا اضافه شدن شمارنده را ببینید.</p>
<p dir='rtl'>مرورگر خود یا tab فعلی را ببندید و دوباره به این صفحه بیایید. خواهید دید که شمارنده از صفر شروع نمی شود بلکه ذخیره شده است.</p>

</body>
</html>

مشاهده ی خروجی در JSBin

شیء sessionStorage

این شیء شبیه شیء localStorage است و تنها تفاوتشان این است که sessionStorage داده ها را تنها برای یک نشست (session) تعیین می کند و زمانی که کاربر پنجره ی مرورگر خود را ببندد داده ها هم از بین می روند. مثال زیر همان مثال بالا است اما با استفاده از sessionStorage ها نوشته شده است:

<!DOCTYPE html>
<html>
<head>
<script>
function clickCounter() {
  if (typeof(Storage) !== "undefined") {
    if (sessionStorage.clickcount) {
      sessionStorage.clickcount = Number(sessionStorage.clickcount)+1;
    } else {
      sessionStorage.clickcount = 1;
    }
    document.getElementById("result").innerHTML = "شما " + sessionStorage.clickcount + " بار روی دکمه کلیک کرده اید";
  } else {
    document.getElementById("result").innerHTML = "متاسفانه مرورگر شما از web storage پشتیبانی نمی کند.";
  }
}
</script>
</head>
<body>

<p><button onclick="clickCounter()" type="button">اینجا را کلیک کنید</button></p>
<div id="result"></div>
<p dir='rtl'>روی دکمه ی بالا کلیک کنید تا اضافه شدن شمارنده را ببینید.</p>
<p dir='rtl'>مرورگر خود یا tab فعلی را ببندید و دوباره به این صفحه بیایید. خواهید دید که شمارنده از صفر شروع می شود و داده ها از بین می روند.</p>


</body>
</html>

مشاهده ی خروجی در JSBin

امیدوارم از این قسمت لذت برده باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش صفر تا صد HTML توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.