Skip to content

Commit

Permalink
Clean up OffsetUtils.js (#795)
Browse files Browse the repository at this point in the history
* Claen up OffsetUtils.js

* Correct linting issues
  • Loading branch information
darthtrevino committed Jun 13, 2017
1 parent d1f078b commit 3e9a3fe
Showing 1 changed file with 68 additions and 48 deletions.
116 changes: 68 additions & 48 deletions packages/react-dnd-html5-backend/src/OffsetUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,25 @@ export function getEventClientOffset(e) {
};
}

function isImageNode(node) {
return node.nodeName === 'IMG' && (
isFirefox() ||
!document.documentElement.contains(node)
);
}

function getDragPreviewSize(isImage, dragPreview, sourceWidth, sourceHeight) {
let dragPreviewWidth = isImage ? dragPreview.width : sourceWidth;
let dragPreviewHeight = isImage ? dragPreview.height : sourceHeight;

// Work around @2x coordinate discrepancies in browsers
if (isSafari() && isImage) {
dragPreviewHeight /= window.devicePixelRatio;
dragPreviewWidth /= window.devicePixelRatio;
}
return { dragPreviewWidth, dragPreviewHeight };
}

export function getDragPreviewOffset(
sourceNode,
dragPreview,
Expand All @@ -35,63 +54,64 @@ export function getDragPreviewOffset(
) {
// The browsers will use the image intrinsic size under different conditions.
// Firefox only cares if it's an image, but WebKit also wants it to be detached.
const isImage = dragPreview.nodeName === 'IMG' && (
isFirefox() ||
!document.documentElement.contains(dragPreview)
);
const isImage = isImageNode(dragPreview);
const dragPreviewNode = isImage ? sourceNode : dragPreview;

const dragPreviewNodeOffsetFromClient = getNodeClientOffset(dragPreviewNode);
const offsetFromDragPreview = {
x: clientOffset.x - dragPreviewNodeOffsetFromClient.x,
y: clientOffset.y - dragPreviewNodeOffsetFromClient.y,
};
const {
offsetWidth: sourceWidth,
offsetHeight: sourceHeight,
} = sourceNode;
const {
anchorX,
anchorY,
} = anchorPoint;
const {
dragPreviewWidth,
dragPreviewHeight,
} = getDragPreviewSize(isImage, dragPreview, sourceWidth, sourceHeight);

const { offsetWidth: sourceWidth, offsetHeight: sourceHeight } = sourceNode;
const { anchorX, anchorY } = anchorPoint;

let dragPreviewWidth = isImage ? dragPreview.width : sourceWidth;
let dragPreviewHeight = isImage ? dragPreview.height : sourceHeight;

// Work around @2x coordinate discrepancies in browsers
if (isSafari() && isImage) {
dragPreviewHeight /= window.devicePixelRatio;
dragPreviewWidth /= window.devicePixelRatio;
}

// Interpolate coordinates depending on anchor point
// If you know a simpler way to do this, let me know
const interpolantX = new MonotonicInterpolant([0, 0.5, 1], [
// Dock to the left
offsetFromDragPreview.x,
// Align at the center
(offsetFromDragPreview.x / sourceWidth) * dragPreviewWidth,
// Dock to the right
offsetFromDragPreview.x + dragPreviewWidth - sourceWidth,
]);
const interpolantY = new MonotonicInterpolant([0, 0.5, 1], [
// Dock to the top
offsetFromDragPreview.y,
// Align at the center
(offsetFromDragPreview.y / sourceHeight) * dragPreviewHeight,
// Dock to the bottom
offsetFromDragPreview.y + dragPreviewHeight - sourceHeight,
]);
let x = interpolantX.interpolate(anchorX);
let y = interpolantY.interpolate(anchorY);
const calculateYOffset = () => {
const interpolantY = new MonotonicInterpolant([0, 0.5, 1], [
// Dock to the top
offsetFromDragPreview.y,
// Align at the center
(offsetFromDragPreview.y / sourceHeight) * dragPreviewHeight,
// Dock to the bottom
offsetFromDragPreview.y + dragPreviewHeight - sourceHeight,
]);
let y = interpolantY.interpolate(anchorY);
// Work around Safari 8 positioning bug
if (isSafari() && isImage) {
// We'll have to wait for @3x to see if this is entirely correct
y += (window.devicePixelRatio - 1) * dragPreviewHeight;
}
return y;
};

// Work around Safari 8 positioning bug
if (isSafari() && isImage) {
// We'll have to wait for @3x to see if this is entirely correct
y += (window.devicePixelRatio - 1) * dragPreviewHeight;
}
const calculateXOffset = () => {
// Interpolate coordinates depending on anchor point
// If you know a simpler way to do this, let me know
const interpolantX = new MonotonicInterpolant([0, 0.5, 1], [
// Dock to the left
offsetFromDragPreview.x,
// Align at the center
(offsetFromDragPreview.x / sourceWidth) * dragPreviewWidth,
// Dock to the right
offsetFromDragPreview.x + dragPreviewWidth - sourceWidth,
]);
return interpolantX.interpolate(anchorX);
};

// Force offsets if specified in the options.
const { offsetX, offsetY } = offsetPoint;
const forceOffsetX = offsetX === 0 || offsetX;
const forceOffsetY = offsetY === 0 || offsetY;
x = forceOffsetX ? offsetX : x;
y = forceOffsetY ? offsetY : y;

return { x, y };
const isManualOffsetX = offsetX === 0 || offsetX;
const isManualOffsetY = offsetY === 0 || offsetY;
return {
x: isManualOffsetX ? offsetX : calculateXOffset(),
y: isManualOffsetY ? offsetY : calculateYOffset(),
};
}

0 comments on commit 3e9a3fe

Please sign in to comment.