提交 55bde0bc 编写于 作者: O owen-m1

added ghost fix

上级 9a32b933
......@@ -70,6 +70,10 @@
targetMoveDistance,
// For positioning ghost absolutely
ghostRelativeParent,
ghostRelativeParentInitialScroll = [], // (left, top)
forRepaintDummy,
realDragElRect, // dragEl rect after current animation
......@@ -96,6 +100,9 @@
Edge = !!navigator.userAgent.match(/Edge/i),
FireFox = !!navigator.userAgent.match(/firefox/i),
Safari = !!(navigator.userAgent.match(/safari/i) && !navigator.userAgent.match(/chrome/i) && !navigator.userAgent.match(/android/i)),
IOS = !!(navigator.userAgent.match(/iP(ad|od|hone)/i)),
PositionGhostAbsolutely = IOS,
CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float',
......@@ -353,6 +360,7 @@
// emulate drag over during autoscroll (fallback), emulating native DnD behaviour
if (isFallback && this.layer === 0) {
Sortable.active._emulateDragOver(true);
Sortable.active._onTouchMove(touchEvt, true);
}
var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0;
var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0;
......@@ -948,9 +956,9 @@
}
},
_emulateDragOver: function (bypassLastTouchCheck) {
_emulateDragOver: function (forAutoScroll) {
if (touchEvt) {
if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY && !bypassLastTouchCheck) {
if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY && !forAutoScroll) {
return;
}
this._lastX = touchEvt.clientX;
......@@ -995,7 +1003,7 @@
},
_onTouchMove: function (/**TouchEvent*/evt) {
_onTouchMove: function (/**TouchEvent*/evt, forAutoScroll) {
if (tapEvt) {
var options = this.options,
fallbackTolerance = options.fallbackTolerance,
......@@ -1004,11 +1012,15 @@
matrix = ghostEl && _matrix(ghostEl),
scaleX = ghostEl && matrix && matrix.a,
scaleY = ghostEl && matrix && matrix.d,
dx = ((touch.clientX - tapEvt.clientX) + fallbackOffset.x) / (scaleX ? scaleX : 1),
dy = ((touch.clientY - tapEvt.clientY) + fallbackOffset.y) / (scaleY ? scaleY : 1),
relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && _getRelativeScrollOffset(ghostRelativeParent),
dx = ((touch.clientX - tapEvt.clientX)
+ fallbackOffset.x) / (scaleX || 1)
+ (relativeScrollOffset ? (relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0]) : 0) / (scaleX || 1),
dy = ((touch.clientY - tapEvt.clientY)
+ fallbackOffset.y) / (scaleY || 1)
+ (relativeScrollOffset ? (relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1]) : 0) / (scaleY || 1),
translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';
// only set the status to dragging, when we are actually dragging
if (!Sortable.active && !awaitingDragStarted) {
if (fallbackTolerance &&
......@@ -1019,13 +1031,11 @@
this._onDragStart(evt, true);
}
this._handleAutoScroll(touch, true);
!forAutoScroll && this._handleAutoScroll(touch, true);
moved = true;
touchEvt = touch;
_css(ghostEl, 'webkitTransform', translate3d);
_css(ghostEl, 'mozTransform', translate3d);
_css(ghostEl, 'msTransform', translate3d);
......@@ -1036,11 +1046,41 @@
},
_appendGhost: function () {
// Bug if using scale(): https://stackoverflow.com/questions/2637058
// Not being adjusted for
if (!ghostEl) {
var rect = _getRect(dragEl, this.options.fallbackOnBody ? document.body : rootEl, true),
var container = this.options.fallbackOnBody ? document.body : rootEl,
rect = _getRect(dragEl, true, container, !PositionGhostAbsolutely),
css = _css(dragEl),
options = this.options;
// Position absolutely
if (PositionGhostAbsolutely) {
// Get relatively positioned parent
ghostRelativeParent = container;
while (
_css(ghostRelativeParent, 'position') === 'static' &&
_css(ghostRelativeParent, 'transform') === 'none' &&
ghostRelativeParent !== document.body
) {
ghostRelativeParent = ghostRelativeParent.parentNode;
}
var ghostRelativeParentRect = _getRect(ghostRelativeParent, true);
rect.top -= ghostRelativeParentRect.top;
rect.left -= ghostRelativeParentRect.left;
if (ghostRelativeParent === document.body) ghostRelativeParent = _getWindowScrollingElement();
ghostRelativeParentInitialScroll = _getRelativeScrollOffset(ghostRelativeParent);
rect.top += ghostRelativeParent.scrollTop;
rect.left += ghostRelativeParent.scrollLeft;
}
ghostEl = dragEl.cloneNode(true);
_toggleClass(ghostEl, options.ghostClass, false);
......@@ -1054,11 +1094,11 @@
_css(ghostEl, 'width', rect.width);
_css(ghostEl, 'height', rect.height);
_css(ghostEl, 'opacity', '0.8');
_css(ghostEl, 'position', 'fixed');
_css(ghostEl, 'position', (PositionGhostAbsolutely ? 'absolute' : 'fixed'));
_css(ghostEl, 'zIndex', '100000');
_css(ghostEl, 'pointerEvents', 'none');
options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);
container.appendChild(ghostEl);
}
},
......@@ -2241,7 +2281,7 @@
* @param {[Boolean]} adjustForTransform Whether the rect should compensate for parent's transform
* @return {Object} The boundingClientRect of el
*/
function _getRect(el, container, adjustForTransform) {
function _getRect(el, adjustForTransform, container, adjustForFixed) {
if (!el.getBoundingClientRect && el !== win) return;
var elRect,
......@@ -2269,7 +2309,7 @@
width = window.innerWidth;
}
if (adjustForTransform && el !== win) {
if (adjustForFixed && el !== win) {
// Adjust for translate()
container = container || el.parentNode;
......@@ -2291,9 +2331,11 @@
/* jshint boss:true */
} while (container = container.parentNode);
}
}
if (adjustForTransform && el !== win) {
// Adjust for scale()
var matrix = _matrix(el),
var matrix = _matrix(container || el),
scaleX = matrix && matrix.a,
scaleY = matrix && matrix.d;
......@@ -2324,7 +2366,6 @@
* Checks if a side of an element is scrolled past a side of it's parents
* @param {HTMLElement} el The element who's side being scrolled out of view is in question
* @param {String} side Side of the element in question ('top', 'left', 'right', 'bottom')
* @return {int} Amount the element is overflowing over the specified side of it's parent scroll element
* @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element
*/
function _isScrolledPast(el, side) {
......@@ -2352,6 +2393,34 @@
return false;
}
/**
* Returns the scroll offset of the given element, added with all the scroll offsets of parent elements.
* The value is returned in real pixels.
* @param {HTMLElement} el
* @return {Array} Offsets in the format of [left, top]
*/
function _getRelativeScrollOffset(el) {
var offsetLeft = 0, offsetTop = 0;
while (el && el.parentNode) {
var matrix = _matrix(el),
scaleX = matrix.a,
scaleY = matrix.d;
offsetLeft += el.scrollLeft * scaleX;
offsetTop += el.scrollTop * scaleY;
el = el.parentNode;
if (el === _getWindowScrollingElement()) {
offsetLeft += _getWindowScrollingElement().scrollLeft;
offsetTop += _getWindowScrollingElement().scrollTop;
break;
}
}
return [offsetLeft, offsetTop];
}
// Fixed #973:
_on(document, 'touchmove', function(evt) {
if ((Sortable.active || awaitingDragStarted) && evt.cancelable) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册