Skip to content

Commit

Permalink
Properly detect if SVG element is being used and use transform attrib…
Browse files Browse the repository at this point in the history
…ute instead of style transform.

Tests added - 1) Detect if element is instanceof SVGElement 2) Detect if element is NOT instanceof SVGElement 3) Test if SVGs are use the appropriate transform property.
  • Loading branch information
martinRoss authored and STRML committed Oct 15, 2015
1 parent bb5b030 commit 7807a68
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 15 deletions.
59 changes: 45 additions & 14 deletions lib/draggable.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ function createCSSTransform(style) {
return out;
}

function createSVGTransform(args) {
return 'translate(' + args.x + ',' + args.y + ')';
}

//
// End Helpers.
Expand Down Expand Up @@ -463,7 +466,7 @@ module.exports = React.createClass({
* A workaround option which can be passed if onMouseDown needs to be accessed,
* since it'll always be blocked (due to that there's internal use of onMouseDown)
*/
onMouseDown: React.PropTypes.func
onMouseDown: React.PropTypes.func,
},

componentWillReceiveProps: function(newProps) {
Expand All @@ -473,6 +476,13 @@ module.exports = React.createClass({
}
},

componentDidMount: function() {
// Check to see if the element passed is an instanceof SVGElement
if( React.findDOMNode(this) instanceof SVGElement) {
this.setState({ isElementSVG: true });
}
},

componentWillUnmount: function() {
// Remove any leftover event handlers
removeEvent(document, dragEventFor.move, this.handleDrag);
Expand All @@ -494,7 +504,7 @@ module.exports = React.createClass({
onStart: emptyFunction,
onDrag: emptyFunction,
onStop: emptyFunction,
onMouseDown: emptyFunction
onMouseDown: emptyFunction,
};
},

Expand All @@ -509,7 +519,11 @@ module.exports = React.createClass({
offsetX: 0, offsetY: 0,

// Current transform x and y.
clientX: props.start.x, clientY: props.start.y
clientX: props.start.x, clientY: props.start.y,

// Can only determine if is SVG after mounted
isElementSVG: false

};
},

Expand Down Expand Up @@ -667,17 +681,33 @@ module.exports = React.createClass({
// without worrying about whether or not it is relatively or absolutely positioned.
// If the item you are dragging already has a transform set, wrap it in a <span> so <Draggable>
// has a clean slate.
var transform = createCSSTransform({
// Set left if horizontal drag is enabled
x: canDragX(this) ?
this.state.clientX :
this.props.start.x,

// Set top if vertical drag is enabled
y: canDragY(this) ?
this.state.clientY :
this.props.start.y
});
var transform = this.state.isElementSVG ? null :
createCSSTransform({
// Set left if horizontal drag is enabled
x: canDragX(this) ?
this.state.clientX :
this.props.start.x,

// Set top if vertical drag is enabled
y: canDragY(this) ?
this.state.clientY :
this.props.start.y
});


var svgTransform = !this.state.isElementSVG ? null :
createSVGTransform({
// Set left if horizontal drag is enabled
x: canDragX(this) ?
this.state.clientX :
this.props.start.x,

// Set top if vertical drag is enabled
y: canDragY(this) ?
this.state.clientY :
this.props.start.y
});


// Workaround IE pointer events; see #51
// https://github.com/mzabriskie/react-draggable/issues/51#issuecomment-103488278
Expand All @@ -701,6 +731,7 @@ module.exports = React.createClass({
// This makes it flexible to use whatever element is wanted (div, ul, etc)
return React.cloneElement(React.Children.only(this.props.children), {
style: style,
transform: svgTransform,
className: className,

onMouseDown: this.onMouseDown,
Expand Down
46 changes: 45 additions & 1 deletion specs/draggable.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ describe('react-draggable', function () {
expect(called).toEqual(true);
});

it('should render with translate()', function () {
it('should render with style translate() for DOM nodes', function () {
drag = TestUtils.renderIntoDocument(
<Draggable>
<div />
Expand All @@ -108,8 +108,52 @@ describe('react-draggable', function () {

var style = node.getAttribute('style');
expect(style.indexOf('transform: translate(100px, 100px);')).not.toEqual(-1);

});

it('should detect if an element is instanceof SVGElement and set state.isElementSVG to true', function() {
drag = TestUtils.renderIntoDocument(
<Draggable>
<svg />
</Draggable>
);

var node = drag.getDOMNode();
expect(drag.state.isElementSVG).toEqual(true);

});

it('should detect if an element is NOT an instanceof SVGElement and set state.isElementSVG to false', function() {
drag = TestUtils.renderIntoDocument(
<Draggable>
<div />
</Draggable>
);

var node = drag.getDOMNode();
expect(drag.state.isElementSVG).toEqual(false);

});

it('should render with transform translate() for SVG nodes', function () {
drag = TestUtils.renderIntoDocument(
<Draggable>
<svg />
</Draggable>
);

var node = drag.getDOMNode();

TestUtils.Simulate.mouseDown(node, {clientX: 0, clientY: 0});
drag.handleDrag({clientX: 100, clientY:100});
TestUtils.Simulate.mouseUp(node);

var transform = node.getAttribute('transform');
expect(transform.indexOf('translate(100,100)')).not.toEqual(-1);

});


it('should add and remove user-select styles', function () {
// Karma runs in firefox in our tests
var userSelectStyle = ';user-select: none;-moz-user-select: none;';
Expand Down

0 comments on commit 7807a68

Please sign in to comment.