sortablejs 中文文档
Sortable
Sortable is a JavaScript library for reorderable drag-and-drop lists.
Demo: http://sortablejs.github.io/Sortable/
Features
- Supports touch devices and modern browsers (including IE9)
- Can drag from one list to another or within the same list
- CSS animation when moving items
- Supports drag handles and selectable text (better than voidberg's html5sortable)
- Smart auto-scrolling
- Advanced swap detection
- Smooth animations
- Multi-drag support
- Support for CSS transforms
- Built using native HTML5 drag and drop API
- Supports
- Supports any CSS library, e.g. Bootstrap
- Simple API
- Support for plugins
- CDN
- No jQuery required (but there is support)
- Typescript definitions at
@types/sortablejs
Articles
- Dragging Multiple Items in Sortable (April 26, 2019)
- Swap Thresholds and Direction (December 2, 2018)
- Sortable v1.0 — New capabilities (December 22, 2014)
- Sorting with the help of HTML5 Drag'n'Drop API (December 23, 2013)
Getting Started
Install with NPM:
$ npm install sortablejs --save
Install with Bower:
$ bower install --save sortablejs
Import into your project:
// Default SortableJS
import Sortable from 'sortablejs';
// Core SortableJS (without default plugins)
import Sortable from 'sortablejs/modular/sortable.core.esm.js';
// Complete SortableJS (with all plugins)
import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
Cherrypick plugins:
// Cherrypick extra plugins
import Sortable, { MultiDrag, Swap } from 'sortablejs';
Sortable.mount(new MultiDrag(), new Swap());
// Cherrypick default plugins
import Sortable, { AutoScroll } from 'sortablejs/modular/sortable.core.esm.js';
Sortable.mount(new AutoScroll());
Usage
<ul id="items">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
var el = document.getElementById('items');
var sortable = Sortable.create(el);
You can use any element for the list and its elements, not just ul
/li
. Here is an example with div
s.
Options
var sortable = new Sortable(el, {
group: "name", // 或者 { name: "...", pull: [true, false, 'clone', array], put: [true, false, array] }
sort: true, // 排序内部列表
delay: 0, // 定义排序何时开始的时间 (毫秒)
delayOnTouchOnly: false, // 仅当用户使用触摸时才会延迟
touchStartThreshold: 0, // px, 在取消延迟拖动事件之前,该点应该移动多少像素
disabled: false, // 如果设置为 true,则禁用可排序。
store: null, // 请参阅商店
animation: 150, // ms, 排序时动画速度移动项目,“0”-无动画
easing: "cubic-bezier(1, 0, 0, 1)", // 移动动画。默认为 null。例如 https://easings.net/。
handle: ".my-handle", // 在列表项中拖动手柄选择器
filter: ".ignore-elements", // 不会导致拖动的选择器 (字符串或函数)
preventOnFilter: true, // 触发 “过滤” 时调用 “事件.预防性默认 ()”
draggable: ".item", // 指定元素中的哪些项目应该是可拖动的
dataIdAttr: 'data-id',
ghostClass: "sortable-ghost", // 放置占位符的类名
chosenClass: "sortable-chosen", // 所选项目的类名
dragClass: "sortable-drag", // 拖动项的类名
swapThreshold: 1, // 交换区域的阈值
invertSwap: false, // 如果设置为 true,将始终使用反转交换区域
invertedSwapThreshold: 1, // 反向交换区域的阈值 (默认情况下将设置为交换阈值)
direction: 'horizontal', // 可排序的方向 (如果没有给出,将自动检测)
forceFallback: false, // 忽略 HTML5 DnD 行为并强制回退启动
fallbackClass: "sortable-fallback", // 使用 forceFallback 时克隆的 DOM 元素的类名
fallbackOnBody: false, // 将克隆的 DOM 元素附加到文档正文中
fallbackTolerance: 0, // 以像素为单位指定鼠标在被视为拖动之前应移动的距离。
dragoverBubble: false,
removeCloneOnHide: true, // 当克隆元素没有显示时,删除它,而不仅仅是隐藏它
emptyInsertThreshold: 5, // px, 距离鼠标必须从空的可排序插入拖动元素到它
setData: function (/** DataTransfer */dataTransfer, /** HTMLElement*/dragEl) {
dataTransfer.setData('Text', dragEl.textContent); // HTML5 DragEvent 的 “datatransfers” 对象
},
// Element is chosen
onChoose: function (/**Event*/evt) {
evt.oldIndex; // 父级中的元素索引
},
// Element is unchosen
onUnchoose: function(/**Event*/evt) {
// 与 onEnd 相同的属性
},
// Element dragging started
onStart: function (/**Event*/evt) {
evt.oldIndex; // 父级中的元素索引
},
// Element dragging ended
onEnd: function (/**Event*/evt) {
var itemEl = evt.item; // 拖动的 HTMLElement
evt.to; // 目标列表
evt.from; // 上一个列表
evt.oldIndex; // 元素在旧父级中的旧索引
evt.newIndex; // 元素在新父级中的新索引
evt.oldDraggableIndex; // 元素在旧父级中的旧索引,仅计数可拖动的元素
evt.newDraggableIndex; // 元素在新父级中的新索引,仅计数可拖动元素
evt.clone // 克隆元素
evt.pullMode; // 当项目处于另一个可排序状态时: “clone” (如果克隆),“true” (如果移动)
},
// 元素从另一个列表中放入列表中
onAdd: function (/**Event*/evt) {
// 与 onEnd 相同的属性
},
// 已更改列表中的排序
onUpdate: function (/**Event*/evt) {
// 与 onEnd 相同的属性
},
// 通过对列表的任何更改调用 (add / update / remove)
onSort: function (/**Event*/evt) {
// 与 onEnd 相同的属性
},
// 元素从列表中删除到另一个列表中
onRemove: function (/**Event*/evt) {
// 与 onEnd 相同的属性
},
// 尝试拖动过滤元素
onFilter: function (/**Event*/evt) {
var itemEl = evt.item; // HTMLElement 接收 “mousedown | Tapstart” 事件。
},
// 在列表中或列表之间移动项目时的事件
onMove: function (/**Event*/evt, /**Event*/originalEvent) {
// Example: https://jsbin.com/nawahef/edit?js,output
evt.dragged; // 拖动的 HTMLElement
evt.draggedRect; // DOMRect {left, top, right, bottom}
evt.related; // 有指导的 HTMLElement
evt.relatedRect; // DOMRect
evt.willInsertAfter; // 默认情况下,如果 Sortable 将在目标后插入拖动元素,则为 true 的布尔值
originalEvent.clientY; // 鼠标位置
// return false; — 取消
// return -1; — 在目标前插入
// return 1; — 在目标后插入
},
// 创建元素的克隆时调用
onClone: function (/**Event*/evt) {
var origEl = evt.item;
var cloneEl = evt.clone;
},
// 拖动元素更改位置时调用
onChange: function(/**Event*/evt) {
evt.newIndex // most likely why this event is used is to get the dragging element's current index
// 与 onEnd 相同的属性
}
});
group
选项
To drag elements from one list into another, both lists must have the same group
value. You can also define whether lists can give away, give and keep a copy (clone
), and receive elements.
- name:
String
— 组名 - pull:
true|false|["foo", "bar"]|'clone'|function
— 从列表中移出的功能。clone
— 复制项目, 而不是移动。 或可放入元素的组名数组。默认为true
. - put:
true|false|["baz", "qux"]|function
— 可以从其他列表添加元素,还可以从其中添加元素的组名数组。 - revertClone:
boolean
— 移动到另一个列表后,将克隆的元素还原到初始位置。
Demo:
- https://jsbin.com/hijetos/edit?js,output
-
https://jsbin.com/nacoyah/edit?js,output — use of complex logic in the
pull
andput
-
https://jsbin.com/bifuyab/edit?js,output — use
revertClone: true
sort
选项
允许在列表内部排序。
Demo: https://jsbin.com/jayedig/edit?js,output
delay
选项
Time in milliseconds to define when the sorting should start. Unfortunately, due to browser restrictions, delaying is not possible on IE or Edge with native drag & drop.
Demo: https://jsbin.com/zosiwah/edit?js,output
delayOnTouchOnly
选项
Whether or not the delay should be applied only if the user is using touch (eg. on a mobile device). No delay will be applied in any other case. Defaults to false
.
swapThreshold
选项
Percentage of the target that the swap zone will take up, as a float between 0
and 1
.
Demo: http://sortablejs.github.io/Sortable#thresholds
invertSwap
选项
Set to true
to set the swap zone to the sides of the target, for the effect of sorting "in between" items.
Demo: http://sortablejs.github.io/Sortable#thresholds
invertedSwapThreshold
选项
Percentage of the target that the inverted swap zone will take up, as a float between 0
and 1
. If not given, will default to swapThreshold
.
direction
选项
Direction that the Sortable should sort in. Can be set to 'vertical'
, 'horizontal'
, or a function, which will be called whenever a target is dragged over. Must return 'vertical'
or 'horizontal'
.
Example of direction detection for vertical list that includes full column and half column elements:
Sortable.create(el, {
direction: function(evt, target, dragEl) {
if (target !== null && target.className.includes('half-column') && dragEl.className.includes('half-column')) {
return 'horizontal';
}
return 'vertical';
}
});
touchStartThreshold
选项
This option is similar to fallbackTolerance
选项.
When the delay
选项 is set, some phones with very sensitive touch displays like the Samsung Galaxy S8 will fire unwanted touchmove events even when your finger is not moving, resulting in the sort not triggering.
This option sets the minimum pointer movement that must occur before the delayed sorting is cancelled.
Values between 3 to 5 are good.
disabled
选项s
Disables the sortable if set to true
.
Demo: https://jsbin.com/sewokud/edit?js,output
var sortable = Sortable.create(list);
document.getElementById("switcher").onclick = function () {
var state = sortable.option("disabled"); // get
sortable.option("disabled", !state); // set
};
handle
选项
To make list items draggable, Sortable disables text selection by the user. That's not always desirable. To allow text selection, define a drag handler, which is an area of every list element that allows it to be dragged around.
Demo: https://jsbin.com/numakuh/edit?html,js,output
Sortable.create(el, {
handle: ".my-handle"
});
<ul>
<li><span class="my-handle">::</span> list item text one
<li><span class="my-handle">::</span> list item text two
</ul>
.my-handle {
cursor: move;
cursor: -webkit-grabbing;
}
filter
选项
Sortable.create(list, {
filter: ".js-remove, .js-edit",
onFilter: function (evt) {
var item = evt.item,
ctrl = evt.target;
if (Sortable.utils.is(ctrl, ".js-remove")) { // Click on remove button
item.parentNode.removeChild(item); // remove sortable item
}
else if (Sortable.utils.is(ctrl, ".js-edit")) { // Click on edit link
// ...
}
}
})
ghostClass
选项
Class name for the drop placeholder (default sortable-ghost
).
Demo: https://jsbin.com/henuyiw/edit?css,js,output
.ghost {
opacity: 0.4;
}
Sortable.create(list, {
ghostClass: "ghost"
});
chosenClass
选项
Class name for the chosen item (default sortable-chosen
).
Demo: https://jsbin.com/hoqufox/edit?css,js,output
.chosen {
color: #fff;
background-color: #c00;
}
Sortable.create(list, {
delay: 500,
chosenClass: "chosen"
});
forceFallback
选项
If set to true
, the Fallback for non HTML5 Browser will be used, even if we are using an HTML5 Browser. 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.
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.
Demo: https://jsbin.com/sibiput/edit?html,css,js,output
fallbackTolerance
选项
Emulates the native drag threshold. Specify in pixels how far the mouse should move before it's considered as a drag. Useful if the items are also clickable like in a list of links.
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. Dragging only starts if you move the pointer past a certain tolerance, so that you don't accidentally start dragging every time you click.
3 to 5 are probably good values.
dragoverBubble
选项
If set to true
, the dragover event will bubble to parent sortables. Works on both fallback and native dragover event. 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).
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.
removeCloneOnHide
选项
If set to false
, the clone is hidden by having it's CSS display
property set to none
. By default, this option is true
, meaning Sortable will remove the cloned element from the DOM when it is supposed to be hidden.
emptyInsertThreshold
选项
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.
Demo: https://jsbin.com/becavoj/edit?js,output
Event object (demo)
- to:
HTMLElement
— list, in which moved element - from:
HTMLElement
— previous list - item:
HTMLElement
— dragged element - clone:
HTMLElement
- oldIndex:
Number|undefined
— old index within parent - newIndex:
Number|undefined
— new index within parent - oldDraggableIndex:
Number|undefined
— old index within parent, only counting draggable elements - newDraggableIndex:
Number|undefined
— new index within parent, only counting draggable elements - pullMode:
String|Boolean|undefined
— Pull mode if dragging into another sortable ("clone"
,true
, orfalse
), otherwise undefined
move
event object
- to:
HTMLElement
- from:
HTMLElement
- dragged:
HTMLElement
- draggedRect:
DOMRect
- related:
HTMLElement
— element on which have guided - relatedRect:
DOMRect
- willInsertAfter:
Boolean
—true
if will element be inserted after target (orfalse
if before)
Method
option(name:String
[, value:*
]):*
Get or set the option.
closest(el:HTMLElement
[, selector:String
]):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.
toArray():String[]
Serializes the sortable's item data-id
's (dataIdAttr
选项) into an array of string.
sort(order:String[]
)
Sorts the elements according to the array.
var order = sortable.toArray();
sortable.sort(order.reverse()); // apply
save()
Save the current sorting (see store)
destroy()
Removes the sortable functionality completely.
Store
Saving and restoring of the sort.
<ul>
<li data-id="1">order</li>
<li data-id="2">save</li>
<li data-id="3">restore</li>
</ul>
Sortable.create(el, {
group: "localStorage-example",
store: {
/**
* Get the order of elements. Called once during initialization.
* @param {Sortable} sortable
* @returns {Array}
*/
get: function (sortable) {
var order = localStorage.getItem(sortable.options.group.name);
return order ? order.split('|') : [];
},
/**
* Save the order of elements. Called onEnd (when the item is dropped).
* @param {Sortable} sortable
*/
set: function (sortable) {
var order = sortable.toArray();
localStorage.setItem(sortable.options.group.name, order.join('|'));
}
}
})
Bootstrap
Demo: https://jsbin.com/visimub/edit?html,js,output
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>
<!-- Latest Sortable -->
<script src="http://SortableJS.github.io/Sortable/Sortable.js"></script>
<!-- Simple List -->
<ul id="simpleList" class="list-group">
<li class="list-group-item">This is <a href="http://SortableJS.github.io/Sortable/">Sortable</a></li>
<li class="list-group-item">It works with Bootstrap...</li>
<li class="list-group-item">...out of the box.</li>
<li class="list-group-item">It has support for touch devices.</li>
<li class="list-group-item">Just drag some elements around.</li>
</ul>
<script>
// Simple list
Sortable.create(simpleList, { /* options */ });
</script>
Static methods & properties
Sortable.create(el:HTMLElement
[, options:Object
]):Sortable
Create new instance.
Sortable.active:Sortable
The active Sortable instance.
Sortable.dragged:HTMLElement
The element being dragged.
Sortable.ghost:HTMLElement
The ghost element.
Sortable.clone:HTMLElement
The clone element.
Sortable.get(element:HTMLElement
):Sortable
Get the Sortable instance on an element.
Sortable.mount(plugin:...SortablePlugin|SortablePlugin[]
)
Mounts a plugin to Sortable.
Sortable.utils
- on(el
:HTMLElement
, event:String
, fn:Function
) — attach an event handler function - off(el
:HTMLElement
, event:String
, fn:Function
) — remove an event handler - css(el
:HTMLElement
):Object
— get the values of all the CSS properties - css(el
:HTMLElement
, prop:String
):Mixed
— get the value of style properties - css(el
:HTMLElement
, prop:String
, value:String
) — set one CSS properties - css(el
:HTMLElement
, props:Object
) — set more CSS properties - find(ctx
:HTMLElement
, tagName:String
[, iterator:Function
]):Array
— get elements by tag name - bind(ctx
:Mixed
, fn:Function
):Function
— Takes a function and returns a new one that will always have a particular context - is(el
:HTMLElement
, selector:String
):Boolean
— check the current matched set of elements against a selector - 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 - clone(el
:HTMLElement
):HTMLElement
— create a deep copy of the set of matched elements - toggleClass(el
:HTMLElement
, name:String
, state:Boolean
) — add or remove one classes from each element - detectDirection(el
:HTMLElement
):String
— automatically detect the direction of the element as either'vertical'
or'horizontal'
Plugins
Extra Plugins (included in complete versions)
Default Plugins (included in default versions)
CDN
<!-- jsDelivr :: Sortable :: Latest (https://www.jsdelivr.com/package/npm/sortablejs) -->
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>