Browse Source

Merge pull request #441 from ChiefORZ/dev

fix click event for mobile devices and old browser
pull/461/merge
Lebedev Konstantin 10 years ago
parent
commit
71f4362e3c
  1. 16
      README.md
  2. 97
      Sortable.js
  3. 2
      package.json
  4. 5
      react-sortable-mixin.js

16
README.md

@ -65,6 +65,10 @@ var sortable = new Sortable(el, {
ghostClass: "sortable-ghost", // Class name for the drop placeholder ghostClass: "sortable-ghost", // Class name for the drop placeholder
dataIdAttr: 'data-id', dataIdAttr: 'data-id',
forceFallback: false, // ignore the HTML5 DnD behaviour and force the fallback to kick in
fallbackClass: "sortable-fallback" // Class name for the cloned DOM Element when using forceFallback
fallbackOnBody: false // Appends the cloned DOM Element into the Document's Body
scroll: true, // or HTMLElement scroll: true, // or HTMLElement
scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling. scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling.
scrollSpeed: 10, // px scrollSpeed: 10, // px
@ -253,6 +257,18 @@ Sortable.create(list, {
--- ---
#### `forceFallback` option
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 possiblity 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` definied in the options. This behaviour controls the look of this 'dragged' Element.
Demo: http://jsbin.com/xinuyenabi/edit?html,css,js,output
---
#### `scroll` option #### `scroll` option
If set to `true`, the page (or sortable-area) scrolls when coming to an edge. If set to `true`, the page (or sortable-area) scrolls when coming to an edge.

97
Sortable.js

@ -45,6 +45,8 @@
tapEvt, tapEvt,
touchEvt, touchEvt,
moved,
/** @const */ /** @const */
RSPACE = /\s+/g, RSPACE = /\s+/g,
@ -176,7 +178,10 @@
dropBubble: false, dropBubble: false,
dragoverBubble: false, dragoverBubble: false,
dataIdAttr: 'data-id', dataIdAttr: 'data-id',
delay: 0 delay: 0,
forceFallback: false,
fallbackClass: 'sortable-fallback',
fallbackOnBody: false
}; };
@ -323,8 +328,12 @@
_on(ownerDocument, 'touchcancel', _this._onDrop); _on(ownerDocument, 'touchcancel', _this._onDrop);
if (options.delay) { if (options.delay) {
// If the user moves the pointer before the delay has been reached: // If the user moves the pointer or let go the click or touch
// before the delay has been reached:
// disable the delayed drag // disable the delayed drag
_on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
_on(ownerDocument, 'touchend', _this._disableDelayedDrag);
_on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
_on(ownerDocument, 'mousemove', _this._disableDelayedDrag); _on(ownerDocument, 'mousemove', _this._disableDelayedDrag);
_on(ownerDocument, 'touchmove', _this._disableDelayedDrag); _on(ownerDocument, 'touchmove', _this._disableDelayedDrag);
@ -339,7 +348,9 @@
var ownerDocument = this.el.ownerDocument; var ownerDocument = this.el.ownerDocument;
clearTimeout(this._dragStartTimer); clearTimeout(this._dragStartTimer);
_off(ownerDocument, 'mouseup', this._disableDelayedDrag);
_off(ownerDocument, 'touchend', this._disableDelayedDrag);
_off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
_off(ownerDocument, 'mousemove', this._disableDelayedDrag); _off(ownerDocument, 'mousemove', this._disableDelayedDrag);
_off(ownerDocument, 'touchmove', this._disableDelayedDrag); _off(ownerDocument, 'touchmove', this._disableDelayedDrag);
}, },
@ -355,7 +366,7 @@
this._onDragStart(tapEvt, 'touch'); this._onDragStart(tapEvt, 'touch');
} }
else if (!supportDraggable) { else if (!supportDraggable || this.options.forceFallback) {
this._onDragStart(tapEvt, true); this._onDragStart(tapEvt, true);
} }
else { else {
@ -422,6 +433,12 @@
_onTouchMove: function (/**TouchEvent*/evt) { _onTouchMove: function (/**TouchEvent*/evt) {
if (tapEvt) { if (tapEvt) {
// only set the status to dragging, when we are actually dragging
if(!Sortable.active) {
this._dragStarted();
}
// as well as creating the ghost element on the document body
this._appendGhost();
var touch = evt.touches ? evt.touches[0] : evt, var touch = evt.touches ? evt.touches[0] : evt,
dx = touch.clientX - tapEvt.clientX, dx = touch.clientX - tapEvt.clientX,
dy = touch.clientY - tapEvt.clientY, dy = touch.clientY - tapEvt.clientY,
@ -429,6 +446,8 @@
touchEvt = touch; touchEvt = touch;
moved = true;
_css(ghostEl, 'webkitTransform', translate3d); _css(ghostEl, 'webkitTransform', translate3d);
_css(ghostEl, 'mozTransform', translate3d); _css(ghostEl, 'mozTransform', translate3d);
_css(ghostEl, 'msTransform', translate3d); _css(ghostEl, 'msTransform', translate3d);
@ -438,26 +457,17 @@
} }
}, },
_appendGhost: function() {
_onDragStart: function (/**Event*/evt, /**boolean*/useFallback) { if(!ghostEl) {
var dataTransfer = evt.dataTransfer,
options = this.options;
this._offUpEvents();
if (activeGroup.pull == 'clone') {
cloneEl = dragEl.cloneNode(true);
_css(cloneEl, 'display', 'none');
rootEl.insertBefore(cloneEl, dragEl);
}
if (useFallback) {
var rect = dragEl.getBoundingClientRect(), var rect = dragEl.getBoundingClientRect(),
css = _css(dragEl), css = _css(dragEl),
ghostRect; ghostRect;
ghostEl = dragEl.cloneNode(true); ghostEl = dragEl.cloneNode(true);
_toggleClass(ghostEl, this.options.ghostClass, false);
_toggleClass(ghostEl, this.options.fallbackClass, true);
_css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10)); _css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));
_css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10)); _css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));
_css(ghostEl, 'width', rect.width); _css(ghostEl, 'width', rect.width);
@ -466,12 +476,28 @@
_css(ghostEl, 'position', 'fixed'); _css(ghostEl, 'position', 'fixed');
_css(ghostEl, 'zIndex', '100000'); _css(ghostEl, 'zIndex', '100000');
rootEl.appendChild(ghostEl); this.options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);
// Fixing dimensions. // Fixing dimensions.
ghostRect = ghostEl.getBoundingClientRect(); ghostRect = ghostEl.getBoundingClientRect();
_css(ghostEl, 'width', rect.width * 2 - ghostRect.width); _css(ghostEl, 'width', rect.width * 2 - ghostRect.width);
_css(ghostEl, 'height', rect.height * 2 - ghostRect.height); _css(ghostEl, 'height', rect.height * 2 - ghostRect.height);
}
},
_onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {
var dataTransfer = evt.dataTransfer,
options = this.options;
this._offUpEvents();
if (activeGroup.pull == 'clone') {
cloneEl = dragEl.cloneNode(true);
_css(cloneEl, 'display', 'none');
rootEl.insertBefore(cloneEl, dragEl);
}
if (useFallback) {
if (useFallback === 'touch') { if (useFallback === 'touch') {
// Bind touch events // Bind touch events
@ -493,9 +519,9 @@
} }
_on(document, 'drop', this); _on(document, 'drop', this);
setTimeout(this._dragStarted, 0);
} }
setTimeout(this._dragStarted, 0);
}, },
_onDragOver: function (/**Event*/evt) { _onDragOver: function (/**Event*/evt) {
@ -665,9 +691,10 @@
this._offUpEvents(); this._offUpEvents();
if (evt) { if (evt) {
evt.preventDefault(); if(moved) {
!options.dropBubble && evt.stopPropagation(); evt.preventDefault();
!options.dropBubble && evt.stopPropagation();
}
ghostEl && ghostEl.parentNode.removeChild(ghostEl); ghostEl && ghostEl.parentNode.removeChild(ghostEl);
if (dragEl) { if (dragEl) {
@ -725,6 +752,8 @@
tapEvt = tapEvt =
touchEvt = touchEvt =
moved =
lastEl = lastEl =
lastCSS = lastCSS =
@ -996,17 +1025,19 @@
onMoveFn = sortable.options.onMove, onMoveFn = sortable.options.onMove,
retVal; retVal;
if (onMoveFn) { evt = document.createEvent('Event');
evt = document.createEvent('Event'); evt.initEvent('move', true, true);
evt.initEvent('move', true, true);
evt.to = toEl; evt.to = toEl;
evt.from = fromEl; evt.from = fromEl;
evt.dragged = dragEl; evt.dragged = dragEl;
evt.draggedRect = dragRect; evt.draggedRect = dragRect;
evt.related = targetEl || toEl; evt.related = targetEl || toEl;
evt.relatedRect = targetRect || toEl.getBoundingClientRect(); evt.relatedRect = targetRect || toEl.getBoundingClientRect();
fromEl.dispatchEvent(evt);
if (onMoveFn) {
retVal = onMoveFn.call(sortable, evt); retVal = onMoveFn.call(sortable, evt);
} }

2
package.json

@ -1,7 +1,7 @@
{ {
"name": "sortablejs", "name": "sortablejs",
"exportName": "Sortable", "exportName": "Sortable",
"version": "1.2.1", "version": "1.2.2",
"devDependencies": { "devDependencies": {
"grunt": "*", "grunt": "*",
"grunt-version": "*", "grunt-version": "*",

5
react-sortable-mixin.js vendored

@ -34,7 +34,8 @@
onUpdate: 'handleUpdate', onUpdate: 'handleUpdate',
onRemove: 'handleRemove', onRemove: 'handleRemove',
onSort: 'handleSort', onSort: 'handleSort',
onFilter: 'handleFilter' onFilter: 'handleFilter',
onMove: 'handleMove'
}; };
@ -90,7 +91,7 @@
// Bind callbacks so that "this" refers to the component // Bind callbacks so that "this" refers to the component
'onStart onEnd onAdd onSort onUpdate onRemove onFilter'.split(' ').forEach(function (/** string */name) { 'onStart onEnd onAdd onSort onUpdate onRemove onFilter onMove'.split(' ').forEach(function (/** string */name) {
copyOptions[name] = function (evt) { copyOptions[name] = function (evt) {
if (name === 'onStart') { if (name === 'onStart') {
_nextSibling = evt.item.nextElementSibling; _nextSibling = evt.item.nextElementSibling;

Loading…
Cancel
Save