@pantograph/sortable 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +432 -829
- package/Sortable.js +1674 -1957
- package/{src/index.d.ts → index.d.ts} +13 -25
- package/modular/sortable.complete.esm.js +1674 -1957
- package/modular/sortable.core.esm.js +1566 -1913
- package/modular/sortable.esm.js +1674 -1956
- package/package.json +58 -58
- package/{src/plugins.d.ts → plugins.d.ts} +0 -33
- package/Sortable.min.js +0 -2
- package/src/Animation.js +0 -175
- package/src/BrowserInfo.js +0 -12
- package/src/EventDispatcher.js +0 -57
- package/src/PluginManager.js +0 -94
- package/src/Sortable.js +0 -2099
- package/src/utils.js +0 -600
package/README.md
CHANGED
|
@@ -1,829 +1,432 @@
|
|
|
1
|
-
# Sortable
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
//
|
|
68
|
-
import Sortable from 'sortablejs';
|
|
69
|
-
|
|
70
|
-
//
|
|
71
|
-
import Sortable from 'sortablejs/modular/sortable.
|
|
72
|
-
|
|
73
|
-
//
|
|
74
|
-
import Sortable from 'sortablejs
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
Sortable.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
Class name for the drop placeholder (default `sortable-ghost`).
|
|
434
|
-
|
|
435
|
-
Demo: https://jsbin.com/henuyiw/edit?css,js,output
|
|
436
|
-
|
|
437
|
-
```css
|
|
438
|
-
.ghost {
|
|
439
|
-
opacity: 0.4;
|
|
440
|
-
}
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
```js
|
|
444
|
-
Sortable.create(list, {
|
|
445
|
-
ghostClass: "ghost"
|
|
446
|
-
});
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
---
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
#### `chosenClass` option
|
|
454
|
-
Class name for the chosen item (default `sortable-chosen`).
|
|
455
|
-
|
|
456
|
-
Demo: https://jsbin.com/hoqufox/edit?css,js,output
|
|
457
|
-
|
|
458
|
-
```css
|
|
459
|
-
.chosen {
|
|
460
|
-
color: #fff;
|
|
461
|
-
background-color: #c00;
|
|
462
|
-
}
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
```js
|
|
466
|
-
Sortable.create(list, {
|
|
467
|
-
delay: 500,
|
|
468
|
-
chosenClass: "chosen"
|
|
469
|
-
});
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
---
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
#### `forceFallback` option
|
|
477
|
-
If set to `true`, the Fallback for non HTML5 Browser will be used, even if we are using an HTML5 Browser.
|
|
478
|
-
This gives us the possibility to test the behaviour for older Browsers even in newer Browser, or make the Drag 'n Drop feel more consistent between Desktop , Mobile and old Browsers.
|
|
479
|
-
|
|
480
|
-
On top of that, the Fallback always generates a copy of that DOM Element and appends the class `fallbackClass` defined in the options. This behaviour controls the look of this 'dragged' Element.
|
|
481
|
-
|
|
482
|
-
Demo: https://jsbin.com/sibiput/edit?html,css,js,output
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
---
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
#### `fallbackTolerance` option
|
|
489
|
-
Emulates the native drag threshold. Specify in pixels how far the mouse should move before it's considered as a drag.
|
|
490
|
-
Useful if the items are also clickable like in a list of links.
|
|
491
|
-
|
|
492
|
-
When the user clicks inside a sortable element, it's not uncommon for your hand to move a little between the time you press and the time you release.
|
|
493
|
-
Dragging only starts if you move the pointer past a certain tolerance, so that you don't accidentally start dragging every time you click.
|
|
494
|
-
|
|
495
|
-
3 to 5 are probably good values.
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
---
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
#### `dragoverBubble` option
|
|
502
|
-
If set to `true`, the dragover event will bubble to parent sortables. Works on both fallback and native dragover event.
|
|
503
|
-
By default, it is false, but Sortable will only stop bubbling the event once the element has been inserted into a parent Sortable, or *can* be inserted into a parent Sortable, but isn't at that specific time (due to animation, etc).
|
|
504
|
-
|
|
505
|
-
Since 1.8.0, you will probably want to leave this option as false. Before 1.8.0, it may need to be `true` for nested sortables to work.
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
---
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
#### `removeCloneOnHide` option
|
|
512
|
-
If set to `false`, the clone is hidden by having it's CSS `display` property set to `none`.
|
|
513
|
-
By default, this option is `true`, meaning Sortable will remove the cloned element from the DOM when it is supposed to be hidden.
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
---
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
#### `emptyInsertThreshold` option
|
|
520
|
-
The distance (in pixels) the mouse must be from an empty sortable while dragging for the drag element to be inserted into that sortable. Defaults to `5`. Set to `0` to disable this feature.
|
|
521
|
-
|
|
522
|
-
Demo: https://jsbin.com/becavoj/edit?js,output
|
|
523
|
-
|
|
524
|
-
An alternative to this option would be to set a padding on your list when it is empty.
|
|
525
|
-
|
|
526
|
-
For example:
|
|
527
|
-
```css
|
|
528
|
-
ul:empty {
|
|
529
|
-
padding-bottom: 20px;
|
|
530
|
-
}
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
Warning: For `:empty` to work, it must have no node inside (even text one).
|
|
534
|
-
|
|
535
|
-
Demo:
|
|
536
|
-
https://jsbin.com/yunakeg/edit?html,css,js,output
|
|
537
|
-
|
|
538
|
-
---
|
|
539
|
-
### Event object ([demo](https://jsbin.com/fogujiv/edit?js,output))
|
|
540
|
-
|
|
541
|
-
- to:`HTMLElement` — list, in which moved element
|
|
542
|
-
- from:`HTMLElement` — previous list
|
|
543
|
-
- item:`HTMLElement` — dragged element
|
|
544
|
-
- clone:`HTMLElement`
|
|
545
|
-
- oldIndex:`Number|undefined` — old index within parent
|
|
546
|
-
- newIndex:`Number|undefined` — new index within parent
|
|
547
|
-
- oldDraggableIndex: `Number|undefined` — old index within parent, only counting draggable elements
|
|
548
|
-
- newDraggableIndex: `Number|undefined` — new index within parent, only counting draggable elements
|
|
549
|
-
- pullMode:`String|Boolean|undefined` — Pull mode if dragging into another sortable (`"clone"`, `true`, or `false`), otherwise undefined
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
#### `move` event object
|
|
553
|
-
- to:`HTMLElement`
|
|
554
|
-
- from:`HTMLElement`
|
|
555
|
-
- dragged:`HTMLElement`
|
|
556
|
-
- draggedRect:`DOMRect`
|
|
557
|
-
- related:`HTMLElement` — element on which have guided
|
|
558
|
-
- relatedRect:`DOMRect`
|
|
559
|
-
- willInsertAfter:`Boolean` — `true` if will element be inserted after target (or `false` if before)
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
---
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
### Methods
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
##### option(name:`String`[, value:`*`]):`*`
|
|
569
|
-
Get or set the option.
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
##### closest(el:`HTMLElement`[, selector:`String`]):`HTMLElement|null`
|
|
574
|
-
For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
##### toArray():`String[]`
|
|
578
|
-
Serializes the sortable's item `data-id`'s (`dataIdAttr` option) into an array of string.
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
##### sort(order:`String[]`, useAnimation:`Boolean`)
|
|
582
|
-
Sorts the elements according to the array.
|
|
583
|
-
|
|
584
|
-
```js
|
|
585
|
-
var order = sortable.toArray();
|
|
586
|
-
sortable.sort(order.reverse(), true); // apply
|
|
587
|
-
```
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
##### save()
|
|
591
|
-
Save the current sorting (see [store](#store))
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
##### destroy()
|
|
595
|
-
Removes the sortable functionality completely.
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
---
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
<a name="store"></a>
|
|
602
|
-
### Store
|
|
603
|
-
Saving and restoring of the sort.
|
|
604
|
-
|
|
605
|
-
```html
|
|
606
|
-
<ul>
|
|
607
|
-
<li data-id="1">order</li>
|
|
608
|
-
<li data-id="2">save</li>
|
|
609
|
-
<li data-id="3">restore</li>
|
|
610
|
-
</ul>
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
```js
|
|
614
|
-
Sortable.create(el, {
|
|
615
|
-
group: "localStorage-example",
|
|
616
|
-
store: {
|
|
617
|
-
/**
|
|
618
|
-
* Get the order of elements. Called once during initialization.
|
|
619
|
-
* @param {Sortable} sortable
|
|
620
|
-
* @returns {Array}
|
|
621
|
-
*/
|
|
622
|
-
get: function (sortable) {
|
|
623
|
-
var order = localStorage.getItem(sortable.options.group.name);
|
|
624
|
-
return order ? order.split('|') : [];
|
|
625
|
-
},
|
|
626
|
-
|
|
627
|
-
/**
|
|
628
|
-
* Save the order of elements. Called onEnd (when the item is dropped).
|
|
629
|
-
* @param {Sortable} sortable
|
|
630
|
-
*/
|
|
631
|
-
set: function (sortable) {
|
|
632
|
-
var order = sortable.toArray();
|
|
633
|
-
localStorage.setItem(sortable.options.group.name, order.join('|'));
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
})
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
---
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
<a name="bs"></a>
|
|
644
|
-
### Bootstrap
|
|
645
|
-
Demo: https://jsbin.com/visimub/edit?html,js,output
|
|
646
|
-
|
|
647
|
-
```html
|
|
648
|
-
<!-- Latest compiled and minified CSS -->
|
|
649
|
-
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
<!-- Latest Sortable -->
|
|
653
|
-
<script src="http://SortableJS.github.io/Sortable/Sortable.js"></script>
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
<!-- Simple List -->
|
|
657
|
-
<ul id="simpleList" class="list-group">
|
|
658
|
-
<li class="list-group-item">This is <a href="http://SortableJS.github.io/Sortable/">Sortable</a></li>
|
|
659
|
-
<li class="list-group-item">It works with Bootstrap...</li>
|
|
660
|
-
<li class="list-group-item">...out of the box.</li>
|
|
661
|
-
<li class="list-group-item">It has support for touch devices.</li>
|
|
662
|
-
<li class="list-group-item">Just drag some elements around.</li>
|
|
663
|
-
</ul>
|
|
664
|
-
|
|
665
|
-
<script>
|
|
666
|
-
// Simple list
|
|
667
|
-
Sortable.create(simpleList, { /* options */ });
|
|
668
|
-
</script>
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
---
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
### Static methods & properties
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
##### Sortable.create(el:`HTMLElement`[, options:`Object`]):`Sortable`
|
|
680
|
-
Create new instance.
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
---
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
##### Sortable.active:`Sortable`
|
|
687
|
-
The active Sortable instance.
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
---
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
##### Sortable.dragged:`HTMLElement`
|
|
694
|
-
The element being dragged.
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
---
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
##### Sortable.ghost:`HTMLElement`
|
|
701
|
-
The ghost element.
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
---
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
##### Sortable.clone:`HTMLElement`
|
|
708
|
-
The clone element.
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
---
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
##### Sortable.get(element:`HTMLElement`):`Sortable`
|
|
715
|
-
Get the Sortable instance on an element.
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
---
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
##### Sortable.mount(plugin:`...SortablePlugin|SortablePlugin[]`)
|
|
722
|
-
Mounts a plugin to Sortable.
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
---
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
##### Sortable.utils
|
|
729
|
-
* on(el`:HTMLElement`, event`:String`, fn`:Function`) — attach an event handler function
|
|
730
|
-
* off(el`:HTMLElement`, event`:String`, fn`:Function`) — remove an event handler
|
|
731
|
-
* css(el`:HTMLElement`)`:Object` — get the values of all the CSS properties
|
|
732
|
-
* css(el`:HTMLElement`, prop`:String`)`:Mixed` — get the value of style properties
|
|
733
|
-
* css(el`:HTMLElement`, prop`:String`, value`:String`) — set one CSS properties
|
|
734
|
-
* css(el`:HTMLElement`, props`:Object`) — set more CSS properties
|
|
735
|
-
* find(ctx`:HTMLElement`, tagName`:String`[, iterator`:Function`])`:Array` — get elements by tag name
|
|
736
|
-
* bind(ctx`:Mixed`, fn`:Function`)`:Function` — Takes a function and returns a new one that will always have a particular context
|
|
737
|
-
* is(el`:HTMLElement`, selector`:String`)`:Boolean` — check the current matched set of elements against a selector
|
|
738
|
-
* closest(el`:HTMLElement`, selector`:String`[, ctx`:HTMLElement`])`:HTMLElement|Null` — for each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree
|
|
739
|
-
* clone(el`:HTMLElement`)`:HTMLElement` — create a deep copy of the set of matched elements
|
|
740
|
-
* toggleClass(el`:HTMLElement`, name`:String`, state`:Boolean`) — add or remove one classes from each element
|
|
741
|
-
* detectDirection(el`:HTMLElement`)`:String` — automatically detect the [direction](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#direction) of the element as either `'vertical'` or `'horizontal'`
|
|
742
|
-
* index(el`:HTMLElement`, selector`:String`)`:Number` — index of the element within its parent for a selected set of elements
|
|
743
|
-
* getChild(el`:HTMLElement`, childNum`:Number`, options`:Object`, includeDragEl`:Boolean`):`HTMLElement` — get the draggable element at a given index of draggable elements within a Sortable instance
|
|
744
|
-
* expando`:String` — expando property name for internal use, sortableListElement[expando] returns the Sortable instance of that elemenet
|
|
745
|
-
---
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
### Plugins
|
|
749
|
-
#### Extra Plugins (included in complete versions)
|
|
750
|
-
- [MultiDrag](https://github.com/SortableJS/Sortable/tree/master/plugins/MultiDrag)
|
|
751
|
-
- [Swap](https://github.com/SortableJS/Sortable/tree/master/plugins/Swap)
|
|
752
|
-
|
|
753
|
-
#### Default Plugins (included in default versions)
|
|
754
|
-
- [AutoScroll](https://github.com/SortableJS/Sortable/tree/master/plugins/AutoScroll)
|
|
755
|
-
- [OnSpill](https://github.com/SortableJS/Sortable/tree/master/plugins/OnSpill)
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
---
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
<a name="cdn"></a>
|
|
762
|
-
### CDN
|
|
763
|
-
|
|
764
|
-
```html
|
|
765
|
-
<!-- jsDelivr :: Sortable :: Latest (https://www.jsdelivr.com/package/npm/sortablejs) -->
|
|
766
|
-
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
|
|
767
|
-
```
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
---
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
### Contributing (Issue/PR)
|
|
774
|
-
|
|
775
|
-
Please, [read this](CONTRIBUTING.md).
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
---
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
## Contributors
|
|
782
|
-
|
|
783
|
-
### Code Contributors
|
|
784
|
-
|
|
785
|
-
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
|
|
786
|
-
<a href="https://github.com/SortableJS/Sortable/graphs/contributors"><img src="https://opencollective.com/Sortable/contributors.svg?width=890&button=false" /></a>
|
|
787
|
-
|
|
788
|
-
### Financial Contributors
|
|
789
|
-
|
|
790
|
-
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/Sortable/contribute)]
|
|
791
|
-
|
|
792
|
-
#### Individuals
|
|
793
|
-
|
|
794
|
-
<a href="https://opencollective.com/Sortable"><img src="https://opencollective.com/Sortable/individuals.svg?width=890"></a>
|
|
795
|
-
|
|
796
|
-
#### Organizations
|
|
797
|
-
|
|
798
|
-
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/Sortable/contribute)]
|
|
799
|
-
|
|
800
|
-
<a href="https://opencollective.com/Sortable/organization/0/website"><img src="https://opencollective.com/Sortable/organization/0/avatar.svg"></a>
|
|
801
|
-
<a href="https://opencollective.com/Sortable/organization/1/website"><img src="https://opencollective.com/Sortable/organization/1/avatar.svg"></a>
|
|
802
|
-
<a href="https://opencollective.com/Sortable/organization/2/website"><img src="https://opencollective.com/Sortable/organization/2/avatar.svg"></a>
|
|
803
|
-
<a href="https://opencollective.com/Sortable/organization/3/website"><img src="https://opencollective.com/Sortable/organization/3/avatar.svg"></a>
|
|
804
|
-
<a href="https://opencollective.com/Sortable/organization/4/website"><img src="https://opencollective.com/Sortable/organization/4/avatar.svg"></a>
|
|
805
|
-
<a href="https://opencollective.com/Sortable/organization/5/website"><img src="https://opencollective.com/Sortable/organization/5/avatar.svg"></a>
|
|
806
|
-
<a href="https://opencollective.com/Sortable/organization/6/website"><img src="https://opencollective.com/Sortable/organization/6/avatar.svg"></a>
|
|
807
|
-
<a href="https://opencollective.com/Sortable/organization/7/website"><img src="https://opencollective.com/Sortable/organization/7/avatar.svg"></a>
|
|
808
|
-
<a href="https://opencollective.com/Sortable/organization/8/website"><img src="https://opencollective.com/Sortable/organization/8/avatar.svg"></a>
|
|
809
|
-
<a href="https://opencollective.com/Sortable/organization/9/website"><img src="https://opencollective.com/Sortable/organization/9/avatar.svg"></a>
|
|
810
|
-
|
|
811
|
-
## MIT LICENSE
|
|
812
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
813
|
-
a copy of this software and associated documentation files (the
|
|
814
|
-
"Software"), to deal in the Software without restriction, including
|
|
815
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
816
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
817
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
818
|
-
the following conditions:
|
|
819
|
-
|
|
820
|
-
The above copyright notice and this permission notice shall be
|
|
821
|
-
included in all copies or substantial portions of the Software.
|
|
822
|
-
|
|
823
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
824
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
825
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
826
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
827
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
828
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
829
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
# Sortable.js
|
|
2
|
+
|
|
3
|
+
[](https://opencollective.com/Sortable) [](https://circleci.com/gh/SortableJS/Sortable) [](https://deepscan.io/dashboard#view=project&tid=3901&pid=5666&bid=43977) [](https://www.jsdelivr.com/package/npm/sortablejs) [](https://www.npmjs.com/package/sortablejs)
|
|
4
|
+
|
|
5
|
+
A modern JavaScript library for reorderable drag-and-drop lists with touch support.
|
|
6
|
+
|
|
7
|
+
**Live Demo:** http://sortablejs.github.io/Sortable/
|
|
8
|
+
|
|
9
|
+
[<img width="250px" src="https://raw.githubusercontent.com/SortableJS/Sortable/HEAD/st/saucelabs.svg?sanitize=true">](https://saucelabs.com/)
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Touch Support**: Works on mobile devices and touch screens
|
|
14
|
+
- **Modern Browsers**: Full support for all modern browsers (including IE9+)
|
|
15
|
+
- **Cross-List Dragging**: Drag items between different lists
|
|
16
|
+
- **Smooth Animations**: CSS animations and transitions
|
|
17
|
+
- **Drag Handles**: Support for drag handles and selectable text
|
|
18
|
+
- **Auto-Scrolling**: Smart auto-scroll during drag operations
|
|
19
|
+
- **Plugin System**: Extensible with plugins
|
|
20
|
+
- **Framework Support**: Works with React, Vue, Angular, and more
|
|
21
|
+
- **No Dependencies**: Pure JavaScript, no jQuery required
|
|
22
|
+
- **TypeScript**: Full TypeScript definitions available
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
### Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install sortablejs --save
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Basic Usage
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<ul id="items">
|
|
36
|
+
<li>Item 1</li>
|
|
37
|
+
<li>Item 2</li>
|
|
38
|
+
<li>Item 3</li>
|
|
39
|
+
</ul>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
import Sortable from 'sortablejs';
|
|
44
|
+
|
|
45
|
+
const el = document.getElementById('items');
|
|
46
|
+
const sortable = Sortable.create(el);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Installation Options
|
|
50
|
+
|
|
51
|
+
### NPM
|
|
52
|
+
```bash
|
|
53
|
+
npm install sortablejs --save
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### CDN
|
|
57
|
+
```html
|
|
58
|
+
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Import Options
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
// Default SortableJS (with default plugins)
|
|
65
|
+
import Sortable from 'sortablejs';
|
|
66
|
+
|
|
67
|
+
// Core SortableJS (without plugins)
|
|
68
|
+
import Sortable from 'sortablejs/modular/sortable.core.esm.js';
|
|
69
|
+
|
|
70
|
+
// Complete SortableJS (with all plugins)
|
|
71
|
+
import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
|
|
72
|
+
|
|
73
|
+
// Cherry-pick plugins
|
|
74
|
+
import Sortable, { Swap, AutoScroll } from 'sortablejs';
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Configuration
|
|
78
|
+
|
|
79
|
+
### Basic Options
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
const sortable = Sortable.create(el, {
|
|
83
|
+
group: "name", // Group name for cross-list dragging
|
|
84
|
+
sort: true, // Enable sorting within list
|
|
85
|
+
delay: 0, // Delay before drag starts (ms)
|
|
86
|
+
disabled: false, // Disable the sortable
|
|
87
|
+
animation: 150, // Animation duration (ms)
|
|
88
|
+
handle: ".drag-handle", // Drag handle selector
|
|
89
|
+
filter: ".ignore", // Elements to ignore
|
|
90
|
+
draggable: ".item", // Draggable elements
|
|
91
|
+
ghostClass: "sortable-ghost", // Class for drop placeholder
|
|
92
|
+
chosenClass: "sortable-chosen", // Class for chosen item
|
|
93
|
+
dragClass: "sortable-drag", // Class for dragging item
|
|
94
|
+
swapThreshold: 0.65, // Swap zone threshold
|
|
95
|
+
direction: 'vertical', // Sort direction
|
|
96
|
+
forceFallback: false, // Force fallback mode
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Advanced Options
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
const sortable = Sortable.create(el, {
|
|
104
|
+
// Group configuration
|
|
105
|
+
group: {
|
|
106
|
+
name: "shared",
|
|
107
|
+
pull: true, // Can pull from this group
|
|
108
|
+
put: true, // Can put into this group
|
|
109
|
+
revertClone: true // Revert cloned element
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
// Animation settings
|
|
113
|
+
animation: 150,
|
|
114
|
+
easing: "cubic-bezier(1, 0, 0, 1)",
|
|
115
|
+
|
|
116
|
+
// Touch settings
|
|
117
|
+
delayOnTouchOnly: false,
|
|
118
|
+
touchStartThreshold: 3,
|
|
119
|
+
|
|
120
|
+
// Fallback settings
|
|
121
|
+
fallbackClass: "sortable-fallback",
|
|
122
|
+
fallbackOnBody: false,
|
|
123
|
+
fallbackTolerance: 0,
|
|
124
|
+
|
|
125
|
+
// Scroll settings
|
|
126
|
+
scroll: true,
|
|
127
|
+
scrollSensitivity: 30,
|
|
128
|
+
scrollSpeed: 10,
|
|
129
|
+
|
|
130
|
+
// Event handlers
|
|
131
|
+
onStart: function(evt) {
|
|
132
|
+
console.log('Drag started');
|
|
133
|
+
},
|
|
134
|
+
onEnd: function(evt) {
|
|
135
|
+
console.log('Drag ended');
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Event Handlers
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
const sortable = Sortable.create(el, {
|
|
144
|
+
// Element is chosen
|
|
145
|
+
onChoose: function(evt) {
|
|
146
|
+
console.log('Element chosen:', evt.item);
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
// Element is unchosen
|
|
150
|
+
onUnchoose: function(evt) {
|
|
151
|
+
console.log('Element unchosen:', evt.item);
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
// Element dragging started
|
|
155
|
+
onStart: function(evt) {
|
|
156
|
+
console.log('Drag started:', evt.item);
|
|
157
|
+
console.log('Old index:', evt.oldIndex);
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
// Element dragging ended
|
|
161
|
+
onEnd: function(evt) {
|
|
162
|
+
console.log('Drag ended');
|
|
163
|
+
console.log('Item:', evt.item);
|
|
164
|
+
console.log('From:', evt.from);
|
|
165
|
+
console.log('To:', evt.to);
|
|
166
|
+
console.log('Old index:', evt.oldIndex);
|
|
167
|
+
console.log('New index:', evt.newIndex);
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
// Element is added to list
|
|
171
|
+
onAdd: function(evt) {
|
|
172
|
+
console.log('Element added:', evt.item);
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
// Element is removed from list
|
|
176
|
+
onRemove: function(evt) {
|
|
177
|
+
console.log('Element removed:', evt.item);
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
// List order changed
|
|
181
|
+
onUpdate: function(evt) {
|
|
182
|
+
console.log('List updated');
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
// Any change to list
|
|
186
|
+
onSort: function(evt) {
|
|
187
|
+
console.log('List sorted');
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
// Element is filtered
|
|
191
|
+
onFilter: function(evt) {
|
|
192
|
+
console.log('Element filtered:', evt.item);
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
// Element is moved
|
|
196
|
+
onMove: function(evt, originalEvent) {
|
|
197
|
+
console.log('Element moved');
|
|
198
|
+
// Return false to cancel
|
|
199
|
+
// Return -1 to insert before
|
|
200
|
+
// Return 1 to insert after
|
|
201
|
+
return true;
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
// Clone is created
|
|
205
|
+
onClone: function(evt) {
|
|
206
|
+
console.log('Clone created:', evt.clone);
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
// Element position changed
|
|
210
|
+
onChange: function(evt) {
|
|
211
|
+
console.log('Element changed position');
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Methods
|
|
217
|
+
|
|
218
|
+
### Instance Methods
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
const sortable = Sortable.create(el);
|
|
222
|
+
|
|
223
|
+
// Get/set options
|
|
224
|
+
sortable.option('disabled', true);
|
|
225
|
+
const disabled = sortable.option('disabled');
|
|
226
|
+
|
|
227
|
+
// Get array of item IDs
|
|
228
|
+
const order = sortable.toArray();
|
|
229
|
+
|
|
230
|
+
// Sort items by array
|
|
231
|
+
sortable.sort(['item3', 'item1', 'item2']);
|
|
232
|
+
|
|
233
|
+
// Save current order
|
|
234
|
+
sortable.save();
|
|
235
|
+
|
|
236
|
+
// Destroy sortable
|
|
237
|
+
sortable.destroy();
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Static Methods
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
// Create new instance
|
|
244
|
+
const sortable = Sortable.create(el, options);
|
|
245
|
+
|
|
246
|
+
// Get instance from element
|
|
247
|
+
const sortable = Sortable.get(element);
|
|
248
|
+
|
|
249
|
+
// Mount plugin
|
|
250
|
+
Sortable.mount(Plugin);
|
|
251
|
+
|
|
252
|
+
// Get active instance
|
|
253
|
+
const active = Sortable.active;
|
|
254
|
+
|
|
255
|
+
// Get dragged element
|
|
256
|
+
const dragged = Sortable.dragged;
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Plugins
|
|
260
|
+
|
|
261
|
+
### Default Plugins (Included)
|
|
262
|
+
|
|
263
|
+
- **AutoScroll**: Automatic scrolling during drag operations
|
|
264
|
+
- **OnSpill**: Handle items dropped outside valid targets
|
|
265
|
+
- `RemoveOnSpill`: Remove spilled items
|
|
266
|
+
- `RevertOnSpill`: Revert spilled items to original position
|
|
267
|
+
|
|
268
|
+
### Extra Plugins
|
|
269
|
+
|
|
270
|
+
- **Swap**: Swap items instead of reordering
|
|
271
|
+
- **FlatTree**: Hierarchical tree-like drag and drop
|
|
272
|
+
|
|
273
|
+
### Plugin Usage
|
|
274
|
+
|
|
275
|
+
```javascript
|
|
276
|
+
import Sortable, { Swap, AutoScroll } from 'sortablejs';
|
|
277
|
+
|
|
278
|
+
// Mount plugins
|
|
279
|
+
Sortable.mount(Swap);
|
|
280
|
+
Sortable.mount(AutoScroll);
|
|
281
|
+
|
|
282
|
+
// Use plugins
|
|
283
|
+
const sortable = Sortable.create(el, {
|
|
284
|
+
swap: true,
|
|
285
|
+
scroll: true
|
|
286
|
+
});
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Framework Integration
|
|
290
|
+
|
|
291
|
+
### React
|
|
292
|
+
```bash
|
|
293
|
+
npm install react-sortablejs
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Vue
|
|
297
|
+
```bash
|
|
298
|
+
npm install vuedraggable
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Angular
|
|
302
|
+
```bash
|
|
303
|
+
npm install angular-sortablejs
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Meteor
|
|
307
|
+
```bash
|
|
308
|
+
meteor add sortablejs:sortable
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Examples
|
|
312
|
+
|
|
313
|
+
### Basic List
|
|
314
|
+
```html
|
|
315
|
+
<ul id="basic-list">
|
|
316
|
+
<li>Item 1</li>
|
|
317
|
+
<li>Item 2</li>
|
|
318
|
+
<li>Item 3</li>
|
|
319
|
+
</ul>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
```javascript
|
|
323
|
+
Sortable.create(document.getElementById('basic-list'));
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Drag Handles
|
|
327
|
+
```html
|
|
328
|
+
<ul id="handle-list">
|
|
329
|
+
<li><span class="handle">⋮⋮</span> Item 1</li>
|
|
330
|
+
<li><span class="handle">⋮⋮</span> Item 2</li>
|
|
331
|
+
<li><span class="handle">⋮⋮</span> Item 3</li>
|
|
332
|
+
</ul>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
```javascript
|
|
336
|
+
Sortable.create(document.getElementById('handle-list'), {
|
|
337
|
+
handle: '.handle'
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Cross-List Dragging
|
|
342
|
+
```html
|
|
343
|
+
<div id="list1" class="list">
|
|
344
|
+
<div class="item">Item 1</div>
|
|
345
|
+
<div class="item">Item 2</div>
|
|
346
|
+
</div>
|
|
347
|
+
<div id="list2" class="list">
|
|
348
|
+
<div class="item">Item 3</div>
|
|
349
|
+
<div class="item">Item 4</div>
|
|
350
|
+
</div>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
```javascript
|
|
354
|
+
Sortable.create(document.getElementById('list1'), {
|
|
355
|
+
group: 'shared'
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
Sortable.create(document.getElementById('list2'), {
|
|
359
|
+
group: 'shared'
|
|
360
|
+
});
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Bootstrap Integration
|
|
364
|
+
```html
|
|
365
|
+
<ul class="list-group" id="bootstrap-list">
|
|
366
|
+
<li class="list-group-item">Item 1</li>
|
|
367
|
+
<li class="list-group-item">Item 2</li>
|
|
368
|
+
<li class="list-group-item">Item 3</li>
|
|
369
|
+
</ul>
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
```javascript
|
|
373
|
+
Sortable.create(document.getElementById('bootstrap-list'));
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Browser Support
|
|
377
|
+
|
|
378
|
+
- **Modern Browsers**: Chrome, Firefox, Safari, Edge
|
|
379
|
+
- **Mobile**: iOS Safari, Chrome Mobile, Firefox Mobile
|
|
380
|
+
- **Legacy**: Internet Explorer 9+
|
|
381
|
+
- **Touch Devices**: Full touch support
|
|
382
|
+
|
|
383
|
+
## Performance Tips
|
|
384
|
+
|
|
385
|
+
1. **Use Drag Handles**: Reduces accidental drags
|
|
386
|
+
2. **Limit Animation Duration**: Keep animations under 200ms
|
|
387
|
+
3. **Use Efficient Selectors**: Avoid complex CSS selectors
|
|
388
|
+
4. **Disable When Not Needed**: Use `disabled` option
|
|
389
|
+
5. **Optimize Event Handlers**: Keep handlers lightweight
|
|
390
|
+
|
|
391
|
+
## Contributing
|
|
392
|
+
|
|
393
|
+
Please read our [Contributing Guide](CONTRIBUTING.md) before submitting issues or pull requests.
|
|
394
|
+
|
|
395
|
+
## License
|
|
396
|
+
|
|
397
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
398
|
+
|
|
399
|
+
## Support
|
|
400
|
+
|
|
401
|
+
- **Documentation**: [GitHub Wiki](https://github.com/SortableJS/Sortable/wiki)
|
|
402
|
+
- **Issues**: [GitHub Issues](https://github.com/SortableJS/Sortable/issues)
|
|
403
|
+
- **Discussions**: [GitHub Discussions](https://github.com/SortableJS/Sortable/discussions)
|
|
404
|
+
|
|
405
|
+
## Contributors
|
|
406
|
+
|
|
407
|
+
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]
|
|
408
|
+
|
|
409
|
+
<a href="https://github.com/SortableJS/Sortable/graphs/contributors"><img src="https://opencollective.com/Sortable/contributors.svg?width=890&button=false" /></a>
|
|
410
|
+
|
|
411
|
+
### Financial Contributors
|
|
412
|
+
|
|
413
|
+
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/Sortable/contribute)]
|
|
414
|
+
|
|
415
|
+
#### Individuals
|
|
416
|
+
|
|
417
|
+
<a href="https://opencollective.com/Sortable"><img src="https://opencollective.com/Sortable/individuals.svg?width=890"></a>
|
|
418
|
+
|
|
419
|
+
#### Organizations
|
|
420
|
+
|
|
421
|
+
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/Sortable/contribute)]
|
|
422
|
+
|
|
423
|
+
<a href="https://opencollective.com/Sortable/organization/0/website"><img src="https://opencollective.com/Sortable/organization/0/avatar.svg"></a>
|
|
424
|
+
<a href="https://opencollective.com/Sortable/organization/1/website"><img src="https://opencollective.com/Sortable/organization/1/avatar.svg"></a>
|
|
425
|
+
<a href="https://opencollective.com/Sortable/organization/2/website"><img src="https://opencollective.com/Sortable/organization/2/avatar.svg"></a>
|
|
426
|
+
<a href="https://opencollective.com/Sortable/organization/3/website"><img src="https://opencollective.com/Sortable/organization/3/avatar.svg"></a>
|
|
427
|
+
<a href="https://opencollective.com/Sortable/organization/4/website"><img src="https://opencollective.com/Sortable/organization/4/avatar.svg"></a>
|
|
428
|
+
<a href="https://opencollective.com/Sortable/organization/5/website"><img src="https://opencollective.com/Sortable/organization/5/avatar.svg"></a>
|
|
429
|
+
<a href="https://opencollective.com/Sortable/organization/6/website"><img src="https://opencollective.com/Sortable/organization/6/avatar.svg"></a>
|
|
430
|
+
<a href="https://opencollective.com/Sortable/organization/7/website"><img src="https://opencollective.com/Sortable/organization/7/avatar.svg"></a>
|
|
431
|
+
<a href="https://opencollective.com/Sortable/organization/8/website"><img src="https://opencollective.com/Sortable/organization/8/avatar.svg"></a>
|
|
432
|
+
<a href="https://opencollective.com/Sortable/organization/9/website"><img src="https://opencollective.com/Sortable/organization/9/avatar.svg"></a>
|