Browse Source

+ dev

pull/191/head
RubaXa 10 years ago
parent
commit
357d0cb7e9
  1. 54
      README.md
  2. 167
      Sortable.js
  3. 2
      Sortable.min.js
  4. 1
      index.html
  5. BIN
      st/og-image.png

54
README.md

@ -10,6 +10,7 @@ Demo: http://rubaxa.github.io/Sortable/
* 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
* Built using native HTML5 drag and drop API
* Supports [AngularJS](#ng) and and any CSS library, e.g. [Bootstrap](#bs)
* Simple API
@ -47,7 +48,12 @@ var sortable = new Sortable(el, {
handle: ".my-handle", // Drag handle selector within list items
filter: ".ignore-elements", // Selectors that do not lead to dragging (String or Function)
draggable: ".item", // Specifies which items inside the element should be sortable
ghostClass: "sortable-ghost", // Class name for the drop placeholder - jsbin.com/luxero/3
ghostClass: "sortable-ghost", // Class name for the drop placeholder
scroll: true, // or HTMLElement
scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling.
scrollSpeed: 10, // px
setData: function (dataTransfer, dragEl) {
dataTransfer.setData('Text', dragEl.textContent);
},
@ -192,6 +198,52 @@ Sortable.create(list, {
---
#### `ghostClass` option
Class name for the drop placeholder.
Demo: http://jsbin.com/boqugumiqi/1/edit?css,js,output
```css
.ghost {
opacity: 0.4;
}
```
```js
Sortable.create(list, {
ghostClass: "ghost"
});
```
---
#### `scroll` option
If set to `true`, the page (or sortable-area) scrolls when coming to an edge.
Demo:
- `window`: http://jsbin.com/boqugumiqi/1/edit?html,js,output
- `overflow: hidden`: http://jsbin.com/kohamakiwi/1/edit?html,js,output
---
#### `scrollSensitivity` option
Defines how near the mouse must be to an edge to start scrolling.
---
#### `scrollSpeed` option
The speed at which the window should scroll once the mouse pointer gets within the `scrollSensitivity` distance.
---
<a name="ng"></a>
### Support AngularJS
Include [ng-sortable.js](ng-sortable.js)

167
Sortable.js

@ -29,12 +29,14 @@
ghostEl,
cloneEl,
rootEl,
scrollEl,
nextEl,
lastEl,
lastCSS,
activeGroup,
autoScroll = {},
tapEvt,
touchEvt,
@ -65,6 +67,8 @@
_customEvents = 'onAdd onUpdate onRemove onStart onEnd onFilter onSort'.split(' '),
noop = function () {},
abs = Math.abs,
slice = [].slice,
touchDragOverListeners = []
@ -89,7 +93,10 @@
disabled: false,
store: null,
handle: null,
draggable: el.children[0] && el.children[0].nodeName || (/[uo]l/i.test(el.nodeName) ? 'li' : '*'),
scroll: true,
scrollSensitivity: 30,
scrollSpeed: 10,
draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',
ghostClass: 'sortable-ghost',
ignore: 'a, img',
filter: null,
@ -97,7 +104,8 @@
setData: function (dataTransfer, dragEl) {
dataTransfer.setData('Text', dragEl.textContent);
}
};
},
group;
// Set default options
@ -109,11 +117,12 @@
if (!options.group.name) {
options.group = { name: options.group };
}
group = options.group;
['pull', 'put'].forEach(function (key) {
if (!(key in options.group)) {
options.group[key] = true;
if (!(key in group)) {
group[key] = true;
}
});
@ -126,7 +135,7 @@
// Export group name
el[expando] = options.group.name;
el[expando] = group.name + ' ' + (group.put.join ? group.put.join(' ') : '');
// Bind all private methods
@ -242,9 +251,10 @@
_on(document, 'touchend', this._onDrop);
_on(document, 'touchcancel', this._onDrop);
_on(this.el, 'dragstart', this._onDragStart);
_on(this.el, 'dragend', this._onDrop);
_on(document, 'dragover', _globalDragOver);
_on(dragEl, 'dragend', this);
_on(rootEl, 'dragstart', this._onDragStart);
_on(document, 'dragover', this);
try {
@ -274,13 +284,11 @@
_css(ghostEl, 'display', 'none');
var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY),
parent = target,
parent = target.parentNode,
groupName = this.options.group.name,
i = touchDragOverListeners.length;
if (parent) {
do {
if (parent[expando] === groupName) {
if (parent && (' ' + parent[expando] + ' ').indexOf(groupName) > -1) {
while (i--) {
touchDragOverListeners[i]({
clientX: touchEvt.clientX,
@ -289,14 +297,6 @@
rootEl: parent
});
}
break;
}
target = parent; // store last element
}
/* jshint boss:true */
while (parent = parent.parentNode);
}
_css(ghostEl, 'display', '');
@ -318,6 +318,7 @@
_css(ghostEl, 'msTransform', translate3d);
_css(ghostEl, 'transform', translate3d);
this._onDrag(touch);
evt.preventDefault();
}
},
@ -362,12 +363,77 @@
dataTransfer.effectAllowed = 'move';
options.setData && options.setData.call(this, dataTransfer, dragEl);
_on(document, 'drop', this._onDrop);
_on(document, 'drop', this);
}
setTimeout(this._applyEffects);
setTimeout(this._applyEffects, 0);
scrollEl = options.scroll;
if (scrollEl === true) {
scrollEl = rootEl;
do {
if ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||
(scrollEl.offsetHeight < scrollEl.scrollHeight)
) {
break;
}
/* jshint boss:true */
} while (scrollEl = scrollEl.parentNode);
}
},
_onDrag: _throttle(function (/**Event*/evt) {
// Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
if (rootEl && this.options.scroll) {
var el,
rect,
options = this.options,
sens = options.scrollSensitivity,
speed = options.scrollSpeed,
x = evt.clientX,
y = evt.clientY,
winWidth = window.innerWidth,
winHeight = window.innerHeight,
vx = (winWidth - x <= sens) - (x <= sens),
vy = (winHeight - y <= sens) - (y <= sens)
;
if (vx || vy) {
el = win;
}
else if (scrollEl) {
el = scrollEl;
rect = scrollEl.getBoundingClientRect();
vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
}
if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
autoScroll.el = el;
autoScroll.vx = vx;
autoScroll.vy = vy;
clearInterval(autoScroll.pid);
if (el) {
autoScroll.pid = setInterval(function () {
if (el === win) {
win.scrollTo(win.scrollX + vx * speed, win.scrollY + vy * speed);
} else {
vy && (el.scrollTop += vy * speed);
vx && (el.scrollLeft += vx * speed);
}
}, 24);
}
}
}
}, 30),
_onDragOver: function (/**Event*/evt) {
var el = this.el,
@ -496,15 +562,16 @@
},
_onDrop: function (/**Event*/evt) {
var el = this.el;
clearInterval(this._loopId);
clearInterval(autoScroll.pid);
// Unbind events
_off(document, 'drop', this._onDrop);
_off(document, 'dragover', _globalDragOver);
_off(document, 'drop', this);
_off(document, 'dragover', this);
_off(this.el, 'dragend', this._onDrop);
_off(this.el, 'dragstart', this._onDragStart);
_off(this.el, 'selectstart', this._onTapStart);
_off(el, 'dragstart', this._onDragStart);
this._offUpEvents();
@ -515,8 +582,11 @@
ghostEl && ghostEl.parentNode.removeChild(ghostEl);
if (dragEl) {
_off(dragEl, 'dragend', this);
// get the index of the dragged element within its parent
var newIndex = _index(dragEl);
_disableDraggable(dragEl);
_toggleClass(dragEl, this.options.ghostClass, false);
@ -564,6 +634,19 @@
},
handleEvent: function (/**Event*/evt) {
var type = evt.type;
if (type === 'dragover') {
this._onDrag(evt);
_globalDragOver(evt);
}
else if (type === 'drop' || type === 'dragend') {
this._onDrop(evt);
}
},
/**
* Serializes the item into an array of string.
* @returns {String[]}
@ -679,10 +762,7 @@
function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {
if (selector === '*') {
return el;
}
else if (el) {
if (el) {
ctx = ctx || document;
selector = selector.split('.');
@ -691,8 +771,10 @@
do {
if (
(tag === '>*' && el.parentNode === ctx) || (
(tag === '' || el.nodeName == tag) &&
(!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)
)
) {
return el;
}
@ -824,6 +906,28 @@
return index;
}
function _throttle(callback, ms) {
var args, _this;
return function () {
if (args === void 0) {
args = arguments;
_this = this;
setTimeout(function () {
if (args.length === 1) {
callback.call(_this, args[0]);
} else {
callback.apply(_this, args);
}
args = void 0;
}, ms);
}
};
}
// Export utils
Sortable.utils = {
on: _on,
@ -834,6 +938,7 @@
is: function (el, selector) {
return !!_closest(el, selector, el);
},
throttle: _throttle,
closest: _closest,
toggleClass: _toggleClass,
dispatchEvent: _dispatchEvent,

2
Sortable.min.js vendored

File diff suppressed because one or more lines are too long

1
index.html

@ -3,6 +3,7 @@
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta property="og:image" content="/st/og-image.png"/>
<title>Sortable. No jQuery.</title>

BIN
st/og-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Loading…
Cancel
Save