diff --git a/README.md b/README.md index 5eb7882c..61891df9 100644 --- a/README.md +++ b/README.md @@ -249,6 +249,7 @@ on itself and thus must have callbacks attached to be useful. cancel: string, disabled: boolean, enableUserSelectHack: boolean, + offsetParent: HTMLElement, grid: [number, number], handle: string, onStart: DraggableEventHandler, diff --git a/lib/DraggableCore.es6 b/lib/DraggableCore.es6 index 3c4d9b43..36e7f8ea 100644 --- a/lib/DraggableCore.es6 +++ b/lib/DraggableCore.es6 @@ -66,6 +66,16 @@ export default class DraggableCore extends React.Component { */ enableUserSelectHack: PropTypes.bool, + /** + * `offsetParent`, if set, uses the passed DOM node to compute drag offsets + * instead of using the parent node. + */ + offsetParent: function(props, propName) { + if (process.browser && props[propName] && props[propName].nodeType !== 1) { + throw new Error('Draggable\'s offsetParent must be a DOM Node.'); + } + }, + /** * `grid` specifies the x and y that dragging should snap to. */ @@ -152,6 +162,7 @@ export default class DraggableCore extends React.Component { cancel: null, disabled: false, enableUserSelectHack: true, + offsetParent: null, handle: null, grid: null, transform: null, diff --git a/lib/utils/domFns.es6 b/lib/utils/domFns.es6 index 9afa67a5..b06b6be7 100644 --- a/lib/utils/domFns.es6 +++ b/lib/utils/domFns.es6 @@ -2,6 +2,7 @@ import {findInArray, isFunction, int} from './shims'; import browserPrefix, {getPrefix, browserPrefixToStyle, browserPrefixToKey} from './getPrefix'; +import type DraggableCore from '../DraggableCore'; import type {ControlPosition} from './types'; let matchesSelectorFunc = ''; @@ -95,9 +96,9 @@ export function innerWidth(node: HTMLElement): number { } // Get from offsetParent -export function offsetXYFromParentOf(evt: {clientX: number, clientY: number}, node: HTMLElement & {offsetParent: HTMLElement}): ControlPosition { - const offsetParent = node.offsetParent || document.body; - const offsetParentRect = node.offsetParent === document.body ? {left: 0, top: 0} : offsetParent.getBoundingClientRect(); +export function offsetXYFromParentOf(evt: {clientX: number, clientY: number}, node: HTMLElement & {offsetParent: HTMLElement}, draggableCore: DraggableCore): ControlPosition { + const offsetParent = draggableCore.props.offsetParent || node.offsetParent || document.body; + const offsetParentRect = offsetParent ? {left: 0, top: 0} : offsetParent.getBoundingClientRect(); const x = evt.clientX + offsetParent.scrollLeft - offsetParentRect.left; const y = evt.clientY + offsetParent.scrollTop - offsetParentRect.top; diff --git a/lib/utils/positionFns.es6 b/lib/utils/positionFns.es6 index b2df07b4..3b88b7c4 100644 --- a/lib/utils/positionFns.es6 +++ b/lib/utils/positionFns.es6 @@ -66,7 +66,7 @@ export function canDragY(draggable: Draggable): boolean { export function getControlPosition(e: MouseEvent, touchIdentifier: ?number, draggableCore: DraggableCore): ?ControlPosition { const touchObj = typeof touchIdentifier === 'number' ? getTouch(e, touchIdentifier) : null; if (typeof touchIdentifier === 'number' && !touchObj) return null; // not the right touch - return offsetXYFromParentOf(touchObj || e, ReactDOM.findDOMNode(draggableCore)); + return offsetXYFromParentOf(touchObj || e, ReactDOM.findDOMNode(draggableCore), draggableCore); } // Create an data object exposed by 's events