react-draggable
Advanced tools
Comparing version 0.5.0 to 0.6.0
{ | ||
"name": "react-draggable", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"homepage": "https://github.com/mzabriskie/react-draggable", | ||
@@ -5,0 +5,0 @@ "authors": [ |
@@ -37,4 +37,4 @@ # Changelog | ||
- Remove react/addons dependency (now depending on `react` directly) | ||
- Add MIT License file | ||
- Remove react/addons dependency (now depending on `react` directly). | ||
- Add MIT License file. | ||
- Fix an issue where browser may be detected as touch-enabled but touch event isn't thrown. | ||
@@ -50,1 +50,16 @@ | ||
- Fix React.addons error caused by faulty test. | ||
### 0.5.0 (May 2, 2015) | ||
- Remove browserify browser config, reactify, and jsx pragma. Fixes #38 | ||
- Use React.cloneElement instead of addons cloneWithProps (requires React 0.13) | ||
- Move to CSS transforms. Simplifies implementation and fixes #48, #34, #31. | ||
- Fixup linting and space/tab errors. Fixes #46. | ||
### 0.6.0 (May 2, 2015) | ||
- Breaking change: Cancel dragging when onDrag or onStart handlers return an explicit `false`. | ||
- Fix sluggish movement when `grid` option was active. | ||
- Example updates. | ||
- Move `user-select:none` hack to document.body for better highlight prevention. | ||
- Add `bounds` option to restrict dragging within parent or within coordinates. |
@@ -128,28 +128,100 @@ 'use strict'; | ||
function snapToGrid(draggable, clientX, clientY) { | ||
var stateX = parseInt(draggable.state.clientX, 10); | ||
var stateY = parseInt(draggable.state.clientY, 10); | ||
var directionX = clientX < stateX ? -1 : 1; | ||
var directionY = clientY < stateY ? -1 : 1; | ||
function outerHeight(node) { | ||
// This is deliberately excluding margin for our calculations, since we are using | ||
// offsetTop which is including margin. See getBoundPosition | ||
var height = node.clientHeight; | ||
var computedStyle = window.getComputedStyle(node); | ||
height += int(computedStyle.borderTopWidth); | ||
height += int(computedStyle.borderBottomWidth); | ||
return height; | ||
} | ||
clientX = Math.abs(clientX - stateX) >= draggable.props.grid[0] ? | ||
(stateX + (draggable.props.grid[0] * directionX)) : | ||
stateX; | ||
function outerWidth(node) { | ||
// This is deliberately excluding margin for our calculations, since we are using | ||
// offsetLeft which is including margin. See getBoundPosition | ||
var width = node.clientWidth; | ||
var computedStyle = window.getComputedStyle(node); | ||
width += int(computedStyle.borderLeftWidth); | ||
width += int(computedStyle.borderRightWidth); | ||
return width; | ||
} | ||
function innerHeight(node) { | ||
var height = node.clientHeight; | ||
var computedStyle = window.getComputedStyle(node); | ||
height -= int(computedStyle.paddingTop); | ||
height -= int(computedStyle.paddingBottom); | ||
return height; | ||
} | ||
clientY = Math.abs(clientY - stateY) >= draggable.props.grid[1] ? | ||
(stateY + (draggable.props.grid[1] * directionY)) : | ||
stateY; | ||
function innerWidth(node) { | ||
var width = node.clientWidth; | ||
var computedStyle = window.getComputedStyle(node); | ||
width -= int(computedStyle.paddingLeft); | ||
width -= int(computedStyle.paddingRight); | ||
return width; | ||
} | ||
function isNum(num) { | ||
return typeof num === 'number' && !isNaN(num); | ||
} | ||
function int(a) { | ||
return parseInt(a, 10); | ||
} | ||
function getBoundPosition(draggable, clientX, clientY) { | ||
var bounds = JSON.parse(JSON.stringify(draggable.props.bounds)); | ||
var node = draggable.getDOMNode(); | ||
var parent = node.parentNode; | ||
if (bounds === 'parent') { | ||
var nodeStyle = window.getComputedStyle(node); | ||
var parentStyle = window.getComputedStyle(parent); | ||
// Compute bounds. This is a pain with padding and offsets but this gets it exactly right. | ||
bounds = { | ||
left: -node.offsetLeft + int(parentStyle.paddingLeft) + | ||
int(nodeStyle.borderLeftWidth) + int(nodeStyle.marginLeft), | ||
top: -node.offsetTop + int(parentStyle.paddingTop) + | ||
int(nodeStyle.borderTopWidth) + int(nodeStyle.marginTop), | ||
right: innerWidth(parent) - outerWidth(node) - node.offsetLeft, | ||
bottom: innerHeight(parent) - outerHeight(node) - node.offsetTop | ||
}; | ||
} else { | ||
if (isNum(bounds.right)) bounds.right -= outerWidth(node); | ||
if (isNum(bounds.bottom)) bounds.bottom -= outerHeight(node); | ||
} | ||
// Keep x and y below right and bottom limits... | ||
if (isNum(bounds.right)) clientX = Math.min(clientX, bounds.right); | ||
if (isNum(bounds.bottom)) clientY = Math.min(clientY, bounds.bottom); | ||
// But above left and top limits. | ||
if (isNum(bounds.left)) clientX = Math.max(clientX, bounds.left); | ||
if (isNum(bounds.top)) clientY = Math.max(clientY, bounds.top); | ||
return [clientX, clientY]; | ||
} | ||
function snapToGrid(grid, pendingX, pendingY) { | ||
var x = Math.round(pendingX / grid[0]) * grid[0]; | ||
var y = Math.round(pendingY / grid[1]) * grid[1]; | ||
return [x, y]; | ||
} | ||
// Useful for preventing blue highlights all over everything when dragging. | ||
var userSelectStyle = { | ||
WebkitUserSelect: 'none', | ||
MozUserSelect: 'none', | ||
msUserSelect: 'none', | ||
OUserSelect: 'none', | ||
userSelect: 'none', | ||
}; | ||
var userSelectStyle = ';user-select: none;-webkit-user-select:none;-moz-user-select:none;' + | ||
'-o-user-select:none;-ms-user-select:none;'; | ||
function addUserSelectStyles(draggable) { | ||
if (!draggable.props.enableUserSelectHack) return; | ||
var style = document.body.getAttribute('style') || ''; | ||
document.body.setAttribute('style', style + userSelectStyle); | ||
} | ||
function removeUserSelectStyles(draggable) { | ||
if (!draggable.props.enableUserSelectHack) return; | ||
var style = document.body.getAttribute('style') || ''; | ||
document.body.setAttribute('style', style.replace(userSelectStyle, '')); | ||
} | ||
function createCSSTransform(style) { | ||
@@ -194,2 +266,45 @@ if (!style.x && !style.y) return {}; | ||
/** | ||
* `bounds` determines the range of movement available to the element. | ||
* Available values are: | ||
* | ||
* 'parent' restricts movement within the Draggable's parent node. | ||
* | ||
* Alternatively, pass an object with the following properties, all of which are optional: | ||
* | ||
* {left: LEFT_BOUND, right: RIGHT_BOUND, bottom: BOTTOM_BOUND, top: TOP_BOUND} | ||
* | ||
* All values are in px. | ||
* | ||
* Example: | ||
* | ||
* ```jsx | ||
* var App = React.createClass({ | ||
* render: function () { | ||
* return ( | ||
* <Draggable bounds={{right: 300, bottom: 300}}> | ||
* <div>Content</div> | ||
* </Draggable> | ||
* ); | ||
* } | ||
* }); | ||
* ``` | ||
*/ | ||
bounds: React.PropTypes.oneOfType([ | ||
React.PropTypes.shape({ | ||
left: React.PropTypes.Number, | ||
right: React.PropTypes.Number, | ||
top: React.PropTypes.Number, | ||
bottom: React.PropTypes.Number | ||
}), | ||
React.PropTypes.oneOf(['parent', false]) | ||
]), | ||
/** | ||
* By default, we add 'user-select:none' attributes to the document body | ||
* to prevent ugly text selection during drag. If this is causing problems | ||
* for your app, set this to `false`. | ||
*/ | ||
enableUserSelectHack: React.PropTypes.bool, | ||
/** | ||
* `handle` specifies a selector to be used as the handle that initiates drag. | ||
@@ -278,2 +393,3 @@ * | ||
* Called when dragging starts. | ||
* If this function returns the boolean false, dragging will be canceled. | ||
* | ||
@@ -299,2 +415,3 @@ * Example: | ||
* Called while dragging. | ||
* If this function returns the boolean false, dragging will be canceled. | ||
* | ||
@@ -349,2 +466,3 @@ * Example: | ||
removeEvent(window, dragEventFor['end'], this.handleDragEnd); | ||
removeUserSelectStyles(this); | ||
}, | ||
@@ -355,2 +473,3 @@ | ||
axis: 'both', | ||
bounds: false, | ||
handle: null, | ||
@@ -360,2 +479,3 @@ cancel: null, | ||
zIndex: NaN, | ||
enableUserSelectHack: true, | ||
onStart: emptyFunction, | ||
@@ -398,4 +518,12 @@ onDrag: emptyFunction, | ||
// Call event handler. If it returns explicit false, cancel. | ||
var shouldStart = this.props.onStart(e, createUIEvent(this)); | ||
if (shouldStart === false) return; | ||
var dragPoint = getControlPosition(e); | ||
// Add a style to the body to disable user-select. This prevents text from | ||
// being selected all over the page. | ||
addUserSelectStyles(this); | ||
// Initiate dragging. Set the current x and y as offsets | ||
@@ -410,4 +538,2 @@ // so we know how much we've moved during the drag. This allows us | ||
// Call event handler | ||
this.props.onStart(e, createUIEvent(this)); | ||
@@ -425,2 +551,4 @@ // Add event handlers | ||
removeUserSelectStyles(this); | ||
// Turn off dragging | ||
@@ -448,6 +576,15 @@ this.setState({ | ||
if (Array.isArray(this.props.grid)) { | ||
var coords = snapToGrid(this, clientX, clientY); | ||
var coords = snapToGrid(this.props.grid, clientX, clientY); | ||
clientX = coords[0], clientY = coords[1]; | ||
} | ||
if (this.props.bounds) { | ||
var pos = getBoundPosition(this, clientX, clientY); | ||
clientX = pos[0], clientY = pos[1]; | ||
} | ||
// Call event handler. If it returns explicit false, cancel. | ||
var shouldUpdate = this.props.onDrag(e, createUIEvent(this)); | ||
if (shouldUpdate === false) return this.handleDragEnd(); | ||
// Update transform | ||
@@ -458,5 +595,2 @@ this.setState({ | ||
}); | ||
// Call event handler | ||
this.props.onDrag(e, createUIEvent(this)); | ||
}, | ||
@@ -484,3 +618,3 @@ | ||
}); | ||
var style = assign({}, userSelectStyle, childStyle, transform); | ||
var style = assign({}, childStyle, transform); | ||
@@ -487,0 +621,0 @@ // Set zIndex if currently dragging and prop has been provided |
{ | ||
"name": "react-draggable", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "React draggable component", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -19,4 +19,5 @@ # react-draggable [![Build Status](https://travis-ci.org/mzabriskie/react-draggable.svg?branch=master)](https://travis-ci.org/mzabriskie/react-draggable) | ||
If you aren't using browserify/webpack, a | ||
[UMD version of react-draggable](http://mzabriskie.github.io/react-draggable/example/react-draggable.js) | ||
is updated in the `gh-pages` branch and used for the demo. You can generate it yourself from master by cloning this | ||
[UMD version of react-draggable](dist/react-draggable.js) is available. It is updated per-release only. | ||
If you want a UMD version of the latest `master` revision, you can generate it yourself from master by cloning this | ||
repository and running `$ make`. This will create umd dist files in the `dist/` folder. | ||
@@ -77,2 +78,7 @@ | ||
// | ||
// `bounds` specifies movement boundaries. Pass: | ||
// - 'parent' restricts movement within the node's offsetParent | ||
// (nearest node with position relative or absolute), or | ||
// - An object with left, top, right, and bottom properties. | ||
// | ||
// `zIndex` specifies the zIndex to use while dragging. | ||
@@ -79,0 +85,0 @@ // |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
27968
582
130
0