آموزش جامع Sortable.js
Drag and Drop قدرتمند بدون وابستگی — لیست، Kanban، Clone و رویداد.
📚معرفی و شروع سریع
Sortable.js یک کتابخانه مستقل برای ایجاد لیستهای قابل مرتبسازی با Drag & Drop است. بدون jQuery، با پشتیبانی از Touch موبایل و سازگار با همه فریمورکها.
<!-- فایل محلی --> <script src="Sortable.min.js"></script> // سادهترین استفاده var el = document.getElementById('myList'); Sortable.create(el, { animation: 150, // انیمیشن ms ghostClass: 'ghost-cls', // کلاس placeholder chosenClass: 'chosen-cls' // کلاس هنگام کشیدن }); // یا با new var sortable = new Sortable(el, { animation: 150 });
⇅ دمو: لیست ساده — آیتمها را بکشید
- آیتم اول — HTML/CSS
- آیتم دوم — JavaScript
- آیتم سوم — React
- آیتم چهارم — Vue.js
- آیتم پنجم — Node.js
💡 نکته: متد
Sortable.create(el, opts) و new Sortable(el, opts) معادل هم هستند. هر دو یک نمونه Sortable برمیگردانند که میتوانید آن را برای کنترل بعدی ذخیره کنید.
⚙تنظیمات پایه
| گزینه | پیشفرض | توضیح |
|---|---|---|
| animation | 0 | ms انیمیشن جابجایی (توصیه: ۱۵۰) |
| handle | — | CSS selector دستگیره drag |
| ghostClass | — | کلاس placeholder هنگام drag |
| chosenClass | — | کلاس آیتم انتخابشده |
| dragClass | — | کلاس عنصر در حال کشیدن |
| delay | 0 | تأخیر ms برای شروع drag |
| disabled | false | غیرفعال کردن کامل |
| draggable | — | selector — فقط این آیتمها قابل drag |
| filter | — | selector — این آیتمها قابل drag نیستند |
| sort | true | false = فقط drag بین لیستها، بدون مرتبسازی داخلی |
| forceFallback | false | true = انیمیشن یکنواختتر |
| swapThreshold | 1 | آستانه تعویض (0–1) |
var sortable = Sortable.create(listEl, { animation: 200, handle: '.handle', // فقط از دستگیره ghostClass: 'ghost-cls', chosenClass: 'chosen-cls', dragClass: 'drag-cls', delay: 100, // ۱۰۰ms تأخیر (مفید برای موبایل) forceFallback: true });
≡ دمو: با Handle — فقط آیکون ≡ را بکشید
- ≡مدیریت پروژه
- ≡طراحی رابط کاربری
- ≡توسعه فرانتاند
- ≡توسعه بکاند
- ≡تست و کیفیت
🔗گروهبندی (group)
با گزینه group میتوانید چند لیست را به هم متصل کنید تا آیتمها بین آنها جابجا شوند.
// نام گروه مشترک Sortable.create(document.getElementById('list-a'), { group: 'shared', animation: 150 }); Sortable.create(document.getElementById('list-b'), { group: 'shared', animation: 150 }); // تنظیمات پیشرفته گروه Sortable.create(listEl, { group: { name: 'myGroup', pull: true, // true | false | 'clone' put: true // true | false | ['groupName'] } });
🔗 دمو: drag بین دو لیست
💻 Frontend
- React.js
- Vue.js
- Angular
- Svelte
⚙️ Backend
- Node.js
- Express.js
- Fastify
📋حالت Clone
با pull: 'clone' آیتمها کپی میشوند و نسخه اصلی در لیست منبع باقی میماند.
Sortable.create(sourceList, { group: { name: 'clone-g', pull: 'clone', put: false }, sort: false, // منبع مرتب نمیشود animation: 150 }); Sortable.create(targetList, { group: { name: 'clone-g', pull: true, put: true }, animation: 150 }); // سفارشیسازی کلون Sortable.create(sourceList, { group: { name: 'g', pull: 'clone' }, onClone: function(evt) { evt.clone.textContent += ' (کپی)'; evt.clone.style.color = '#e74c3c'; } });
📋 دمو: Clone — آیتم اصلی باقی میماند
منبع — کلون میشود
- HTML
- CSS
- JavaScript
- TypeScript
🨀 سبد انتخاب
🚫Filter و Disabled
// آیتمهای .no-drag قابل کشیدن نیستند Sortable.create(listEl, { animation: 150, filter: '.no-drag', onFilter: function(evt) { // شیک کردن آیتم قفلشده evt.item.style.transform = 'translateX(-6px)'; setTimeout(function(){ evt.item.style.transform = ''; }, 150); } }); // غیرفعال / فعال کردن sortable.option('disabled', true); // غیرفعال sortable.option('disabled', false); // فعال // draggable — عکس filter Sortable.create(listEl, { draggable: '.sortable-item' });
🔒 دمو: آیتمهای قفلشده قابل drag نیستند
- وظیفه ۱ — آزاد
- 🔒 وظیفه ۲ — قفل (filter)
- وظیفه ۳ — آزاد
- 🔒 وظیفه ۴ — قفل (filter)
- وظیفه ۵ — آزاد
- وظیفه ۶ — آزاد
📡رویدادها (Callbacks)
| رویداد | زمان | پارامترهای مهم |
|---|---|---|
| onStart | شروع کشیدن | item, from, oldIndex |
| onEnd | پایان کشیدن | item, from, to, oldIndex, newIndex |
| onAdd | آیتمی از لیست دیگر اضافه شد | item, from, to, newIndex |
| onRemove | آیتمی به لیست دیگر رفت | item, from, to, oldIndex |
| onSort | ترتیب تغییر کرد (هر نوع) | item, from, oldIndex, newIndex |
| onUpdate | ترتیب در همان لیست عوض شد | item, from, oldIndex, newIndex |
| onMove | در حین کشیدن هر frame | dragged, related |
| onClone | آیتم کلون شد | item, clone, from |
| onFilter | کلیک روی آیتم فیلترشده | item |
Sortable.create(listEl, { animation: 150, dataIdAttr: 'data-id', onStart: function(evt) { console.log('شروع — index:', evt.oldIndex); }, onEnd: function(evt) { console.log('از', evt.oldIndex, 'به', evt.newIndex); }, onSort: function() { var order = sortable.toArray(); // ['id1','id2',...] console.log('ترتیب جدید:', order); } });
📡 دمو: لاگ زنده رویدادها
- آیتم A — طراحی
- آیتم B — توسعه
- آیتم C — تست
- آیتم D — استقرار
- آیتم E — نگهداری
// آیتمها را جابجا کنید...
⚡API و متدها
var sortable = Sortable.create(listEl, { animation: 150, dataIdAttr: 'data-id' }); // toArray — آرایه data-id ها به ترتیب فعلی var order = sortable.toArray(); // ['id3','id1','id2'] // sort — مرتبسازی برنامهنویسی sortable.sort(['id1', 'id2', 'id3']); // option — خواندن / تنظیم گزینه sortable.option('animation'); // خواندن sortable.option('disabled', true); // تنظیم sortable.option('animation', 300); // تنظیم // destroy — حذف کامل sortable.destroy(); // Sortable.get — گرفتن instance از element var instance = Sortable.get(document.getElementById('myList'));
⚡ دمو: کنترل API
- ۱ وظیفه اول
- ۲ وظیفه دوم
- ۳ وظیفه سوم
- ۴ وظیفه چهارم
- ۵ وظیفه پنجم
نتیجه اینجا...
📋تخته Kanban
ترکیب group و چند لیست Sortable برای ساختن یک تخته Kanban واقعی مثل Trello:
// هر ستون = یک Sortable با group مشترک ['todo', 'doing', 'done'].forEach(function(col) { Sortable.create(document.getElementById('col-' + col), { group: 'kanban', animation: 200, ghostClass: 'ghost-class', chosenClass: 'chosen-class', onAdd: function(evt) { updateColumnCounts(); // آپدیت شمارنده ستون } }); });
📋 دمو: تخته Kanban — کارتها را بین ستونها بکشید
📆 انجام نشده3
- 📄 طراحی ماکاپUI
- 🔧 راهاندازی پروژهDEV
- 📋 مستندنویسی APIDOC
▶ در حال انجام2
- 💻 پیادهسازی لاگینDEV
- 🌐 اتصال به APIDEV
✓ انجام شده2
- 🔍 تحلیل نیازمندیهاDONE
- 🌐 تنظیم سرورDONE
🔗یکپارچهسازی
React — با useRef و useEffect
// React import { useEffect, useRef } from 'react'; import Sortable from 'sortablejs'; function SortableList({ items, onReorder }) { const listRef = useRef(null); useEffect(() => { const sortable = Sortable.create(listRef.current, { animation: 150, onEnd: (evt) => { onReorder(evt.oldIndex, evt.newIndex); } }); return () => sortable.destroy(); // cleanup }, []); return <ul ref={listRef}> {items.map(item => <li key={item.id} data-id={item.id}>{item.text}</li>)} </ul>; }
Vue 3 — با onMounted
import { onMounted, onUnmounted, ref } from 'vue'; import Sortable from 'sortablejs'; setup() { const listEl = ref(null); let sortable; onMounted(() => { sortable = Sortable.create(listEl.value, { animation: 150 }); }); onUnmounted(() => sortable.destroy()); return { listEl }; }
ذخیره ترتیب در سرور
Sortable.create(listEl, { animation: 150, dataIdAttr: 'data-id', onSort: function() { var order = sortable.toArray(); fetch('/api/save-order', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ order }) }); } });
🔥بهترین شیوهها
| موضوع | توصیه | دلیل |
|---|---|---|
| انیمیشن | ✓ animation: 150 | تجربه بصری بهتر — بالاتر از 300ms سنگین |
| data-id | ✓ روی هر آیتم | برای toArray() و ذخیره ترتیب |
| destroy | ✓ هنگام unmount | جلوگیری از memory leak |
| handle | ✓ برای محتوای کلیکپذیر | از تداخل drag با کلیک جلوگیری میکند |
| forceFallback | ✓ برای انیمیشن یکنواخت | از CSS transform بهره میبرد |
| ذخیره بیدرنگ | ✗ در onMove | از onEnd یا onSort استفاده کنید |
| sort: false | ✓ برای منبع Clone | آیتمهای منبع جابجا نمیشوند |
| delay موبایل | ✓ delay: 150 | جلوگیری از تداخل با scroll موبایل |
💡 خلاصه Sortable.js:
Sortable.create(el, {animation:150})— راهاندازیgroup: 'name'— drag بین لیستهاpull: 'clone'— کپی به جای جابجاییfilter: '.no-drag'— آیتمهای محرومhandle: '.handle'— دستگیره اختصاصیonEnd / onSort— رویداد تغییرsortable.toArray()— ترتیب فعلیsortable.destroy()— پاکسازی
🚀زمین بازی کد (Playground)
با Sortable.js لیستها را Drag & Drop کن. مرتبسازی، جابجایی بین دو لیست و رویدادها را امتحان کن. نسخهٔ ۱.۱۵.۲ آفلاین بارگذاری میشود.