Browse Source

+ merge 'scroll'

pull/168/head
RubaXa 10 years ago
parent
commit
b32ce4f678
  1. 6
      README.md
  2. 132
      Sortable.js
  3. 2
      Sortable.min.js

6
README.md

@ -10,6 +10,7 @@ Demo: http://rubaxa.github.io/Sortable/
* Can drag from one list to another or within the same list * Can drag from one list to another or within the same list
* CSS animation when moving items * CSS animation when moving items
* Supports drag handles *and selectable text* (better than voidberg's html5sortable) * Supports drag handles *and selectable text* (better than voidberg's html5sortable)
* Smart auto-scrolling
* Built using native HTML5 drag and drop API * Built using native HTML5 drag and drop API
* Supports [AngularJS](#ng) and and any CSS library, e.g. [Bootstrap](#bs) * Supports [AngularJS](#ng) and and any CSS library, e.g. [Bootstrap](#bs)
* Simple API * Simple API
@ -48,6 +49,11 @@ var sortable = new Sortable(el, {
filter: ".ignore-elements", // Selectors that do not lead to dragging (String or Function) filter: ".ignore-elements", // Selectors that do not lead to dragging (String or Function)
draggable: ".item", // Specifies which items inside the element should be sortable 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 - jsbin.com/luxero/3
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) { setData: function (dataTransfer, dragEl) {
dataTransfer.setData('Text', dragEl.textContent); dataTransfer.setData('Text', dragEl.textContent);
}, },

132
Sortable.js

@ -29,12 +29,14 @@
ghostEl, ghostEl,
cloneEl, cloneEl,
rootEl, rootEl,
scrollEl,
nextEl, nextEl,
lastEl, lastEl,
lastCSS, lastCSS,
activeGroup, activeGroup,
autoScroll = {},
tapEvt, tapEvt,
touchEvt, touchEvt,
@ -65,6 +67,8 @@
_customEvents = 'onAdd onUpdate onRemove onStart onEnd onFilter onSort'.split(' '), _customEvents = 'onAdd onUpdate onRemove onStart onEnd onFilter onSort'.split(' '),
noop = function () {}, noop = function () {},
abs = Math.abs,
slice = [].slice, slice = [].slice,
touchDragOverListeners = [] touchDragOverListeners = []
@ -89,6 +93,9 @@
disabled: false, disabled: false,
store: null, store: null,
handle: null, handle: null,
scroll: true,
scrollSensitivity: 30,
scrollSpeed: 10,
draggable: el.children[0] && el.children[0].nodeName || (/[uo]l/i.test(el.nodeName) ? 'li' : '*'), draggable: el.children[0] && el.children[0].nodeName || (/[uo]l/i.test(el.nodeName) ? 'li' : '*'),
ghostClass: 'sortable-ghost', ghostClass: 'sortable-ghost',
ignore: 'a, img', ignore: 'a, img',
@ -242,9 +249,10 @@
_on(document, 'touchend', this._onDrop); _on(document, 'touchend', this._onDrop);
_on(document, 'touchcancel', this._onDrop); _on(document, 'touchcancel', this._onDrop);
_on(this.el, 'dragstart', this._onDragStart); _on(rootEl, 'dragstart', this._onDragStart);
_on(this.el, 'dragend', this._onDrop); _on(rootEl, 'dragend', this._onDrop);
_on(document, 'dragover', _globalDragOver);
_on(document, 'dragover', this);
try { try {
@ -318,6 +326,7 @@
_css(ghostEl, 'msTransform', translate3d); _css(ghostEl, 'msTransform', translate3d);
_css(ghostEl, 'transform', translate3d); _css(ghostEl, 'transform', translate3d);
this._onDrag(touch);
evt.preventDefault(); evt.preventDefault();
} }
}, },
@ -362,12 +371,77 @@
dataTransfer.effectAllowed = 'move'; dataTransfer.effectAllowed = 'move';
options.setData && options.setData.call(this, dataTransfer, dragEl); 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) { _onDragOver: function (/**Event*/evt) {
var el = this.el, var el = this.el,
@ -496,15 +570,17 @@
}, },
_onDrop: function (/**Event*/evt) { _onDrop: function (/**Event*/evt) {
var el = this.el;
clearInterval(this._loopId); clearInterval(this._loopId);
clearInterval(autoScroll.pid);
// Unbind events // Unbind events
_off(document, 'drop', this._onDrop); _off(document, 'drop', this);
_off(document, 'dragover', _globalDragOver); _off(document, 'dragover', this);
_off(this.el, 'dragend', this._onDrop); _off(el, 'dragend', this._onDrop);
_off(this.el, 'dragstart', this._onDragStart); _off(el, 'dragstart', this._onDragStart);
_off(this.el, 'selectstart', this._onTapStart);
this._offUpEvents(); this._offUpEvents();
@ -564,6 +640,19 @@
}, },
handleEvent: function (/**Event*/evt) {
var type = evt.type;
if (type === 'dragover') {
this._onDrag(evt);
_globalDragOver(evt);
}
else if (type === 'drop') {
this._onDrop(evt);
}
},
/** /**
* Serializes the item into an array of string. * Serializes the item into an array of string.
* @returns {String[]} * @returns {String[]}
@ -824,6 +913,28 @@
return index; 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 // Export utils
Sortable.utils = { Sortable.utils = {
on: _on, on: _on,
@ -834,6 +945,7 @@
is: function (el, selector) { is: function (el, selector) {
return !!_closest(el, selector, el); return !!_closest(el, selector, el);
}, },
throttle: _throttle,
closest: _closest, closest: _closest,
toggleClass: _toggleClass, toggleClass: _toggleClass,
dispatchEvent: _dispatchEvent, dispatchEvent: _dispatchEvent,

2
Sortable.min.js vendored

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save