Skip to content

Commit 7807a68

Browse files
martinRossSTRML
authored andcommitted
Properly detect if SVG element is being used and use transform attribute 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.
1 parent bb5b030 commit 7807a68

File tree

2 files changed

+90
-15
lines changed

2 files changed

+90
-15
lines changed

lib/draggable.js

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ function createCSSTransform(style) {
219219
return out;
220220
}
221221

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

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

469472
componentWillReceiveProps: function(newProps) {
@@ -473,6 +476,13 @@ module.exports = React.createClass({
473476
}
474477
},
475478

479+
componentDidMount: function() {
480+
// Check to see if the element passed is an instanceof SVGElement
481+
if( React.findDOMNode(this) instanceof SVGElement) {
482+
this.setState({ isElementSVG: true });
483+
}
484+
},
485+
476486
componentWillUnmount: function() {
477487
// Remove any leftover event handlers
478488
removeEvent(document, dragEventFor.move, this.handleDrag);
@@ -494,7 +504,7 @@ module.exports = React.createClass({
494504
onStart: emptyFunction,
495505
onDrag: emptyFunction,
496506
onStop: emptyFunction,
497-
onMouseDown: emptyFunction
507+
onMouseDown: emptyFunction,
498508
};
499509
},
500510

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

511521
// Current transform x and y.
512-
clientX: props.start.x, clientY: props.start.y
522+
clientX: props.start.x, clientY: props.start.y,
523+
524+
// Can only determine if is SVG after mounted
525+
isElementSVG: false
526+
513527
};
514528
},
515529

@@ -667,17 +681,33 @@ module.exports = React.createClass({
667681
// without worrying about whether or not it is relatively or absolutely positioned.
668682
// If the item you are dragging already has a transform set, wrap it in a <span> so <Draggable>
669683
// has a clean slate.
670-
var transform = createCSSTransform({
671-
// Set left if horizontal drag is enabled
672-
x: canDragX(this) ?
673-
this.state.clientX :
674-
this.props.start.x,
675-
676-
// Set top if vertical drag is enabled
677-
y: canDragY(this) ?
678-
this.state.clientY :
679-
this.props.start.y
680-
});
684+
var transform = this.state.isElementSVG ? null :
685+
createCSSTransform({
686+
// Set left if horizontal drag is enabled
687+
x: canDragX(this) ?
688+
this.state.clientX :
689+
this.props.start.x,
690+
691+
// Set top if vertical drag is enabled
692+
y: canDragY(this) ?
693+
this.state.clientY :
694+
this.props.start.y
695+
});
696+
697+
698+
var svgTransform = !this.state.isElementSVG ? null :
699+
createSVGTransform({
700+
// Set left if horizontal drag is enabled
701+
x: canDragX(this) ?
702+
this.state.clientX :
703+
this.props.start.x,
704+
705+
// Set top if vertical drag is enabled
706+
y: canDragY(this) ?
707+
this.state.clientY :
708+
this.props.start.y
709+
});
710+
681711

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

706737
onMouseDown: this.onMouseDown,

specs/draggable.spec.js

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ describe('react-draggable', function () {
9191
expect(called).toEqual(true);
9292
});
9393

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

109109
var style = node.getAttribute('style');
110110
expect(style.indexOf('transform: translate(100px, 100px);')).not.toEqual(-1);
111+
111112
});
112113

114+
it('should detect if an element is instanceof SVGElement and set state.isElementSVG to true', function() {
115+
drag = TestUtils.renderIntoDocument(
116+
<Draggable>
117+
<svg />
118+
</Draggable>
119+
);
120+
121+
var node = drag.getDOMNode();
122+
expect(drag.state.isElementSVG).toEqual(true);
123+
124+
});
125+
126+
it('should detect if an element is NOT an instanceof SVGElement and set state.isElementSVG to false', function() {
127+
drag = TestUtils.renderIntoDocument(
128+
<Draggable>
129+
<div />
130+
</Draggable>
131+
);
132+
133+
var node = drag.getDOMNode();
134+
expect(drag.state.isElementSVG).toEqual(false);
135+
136+
});
137+
138+
it('should render with transform translate() for SVG nodes', function () {
139+
drag = TestUtils.renderIntoDocument(
140+
<Draggable>
141+
<svg />
142+
</Draggable>
143+
);
144+
145+
var node = drag.getDOMNode();
146+
147+
TestUtils.Simulate.mouseDown(node, {clientX: 0, clientY: 0});
148+
drag.handleDrag({clientX: 100, clientY:100});
149+
TestUtils.Simulate.mouseUp(node);
150+
151+
var transform = node.getAttribute('transform');
152+
expect(transform.indexOf('translate(100,100)')).not.toEqual(-1);
153+
154+
});
155+
156+
113157
it('should add and remove user-select styles', function () {
114158
// Karma runs in firefox in our tests
115159
var userSelectStyle = ';user-select: none;-moz-user-select: none;';

0 commit comments

Comments
 (0)