Skip to content

Commit 430afe7

Browse files
committed
Fix #51; touch events rework based on first event.
Also fixes #37 and #43.
1 parent 96c9f74 commit 430afe7

File tree

2 files changed

+69
-61
lines changed

2 files changed

+69
-61
lines changed

example/index.html

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@
5858
return {
5959
position: {
6060
top: 0, left: 0
61-
}
61+
},
62+
activeDrags: 0
6263
};
6364
},
6465

@@ -68,69 +69,79 @@
6869
});
6970
},
7071

72+
onStart: function() {
73+
this.setState({activeDrags: ++this.state.activeDrags});
74+
},
75+
76+
onStop: function() {
77+
this.setState({activeDrags: --this.state.activeDrags});
78+
},
79+
7180
render: function () {
81+
var drags = {onStart: this.onStart, onStop: this.onStop};
7282
return (
7383
<div>
7484
<h1>React Draggable</h1>
85+
<p>Active Drags: {this.state.activeDrags}</p>
7586
<p>
7687
<a href="https://github.com/mzabriskie/react-draggable/blob/master/example/index.html">Demo Source</a>
7788
</p>
78-
<Draggable zIndex={100}>
89+
<Draggable zIndex={100} {...drags}>
7990
<div className="box">I can be dragged anywhere</div>
8091
</Draggable>
81-
<Draggable axis="x" zIndex={100}>
92+
<Draggable axis="x" {...drags}>
8293
<div className="box cursor-x">I can only be dragged horizonally</div>
8394
</Draggable>
84-
<Draggable axis="y" zIndex={100}>
95+
<Draggable axis="y" {...drags}>
8596
<div className="box cursor-y">I can only be dragged vertically</div>
8697
</Draggable>
87-
<Draggable onDrag={this.handleDrag} zIndex={100}>
98+
<Draggable onDrag={this.handleDrag} {...drags}>
8899
<div className="box">
89100
<div>I track my position</div>
90-
<div>top: {this.state.position.top}, left: {this.state.position.left}</div>
101+
<div>top: {this.state.position.top.toFixed(0)}, left: {this.state.position.left.toFixed(0)}</div>
91102
</div>
92103
</Draggable>
93-
<Draggable handle="strong" zIndex={100}>
104+
<Draggable handle="strong" {...drags}>
94105
<div className="box no-cursor">
95106
<strong className="cursor">Drag here</strong>
96107
<div>You must click my handle to drag me</div>
97108
</div>
98109
</Draggable>
99-
<Draggable cancel="strong" zIndex={100}>
110+
<Draggable cancel="strong" {...drags}>
100111
<div className="box">
101112
<strong className="no-cursor">Can't drag here</strong>
102113
<div>Dragging here works</div>
103114
</div>
104115
</Draggable>
105-
<Draggable grid={[25, 25]}>
116+
<Draggable grid={[25, 25]} {...drags}>
106117
<div className="box">I snap to a 25 x 25 grid</div>
107118
</Draggable>
108-
<Draggable grid={[50, 50]}>
119+
<Draggable grid={[50, 50]} {...drags}>
109120
<div className="box">I snap to a 50 x 50 grid</div>
110121
</Draggable>
111-
<Draggable bounds={{top: -100, left: -100, right: 100, bottom: 100}} zIndex={5}>
122+
<Draggable bounds={{top: -100, left: -100, right: 100, bottom: 100}} zIndex={5} {...drags}>
112123
<div className="box">I can only be moved 100px in any direction.</div>
113124
</Draggable>
114125
<div className="box" style={{height: '500px', width: '500px', position: 'relative'}}>
115-
<Draggable bounds="parent">
126+
<Draggable bounds="parent" {...drags}>
116127
<div className="box">
117128
I can only be moved within my offsetParent.<br /><br />
118129
Both parent padding and child margin work properly.
119130
</div>
120131
</Draggable>
121-
<Draggable bounds="parent">
132+
<Draggable bounds="parent" {...drags}>
122133
<div className="box">
123134
I also can only be moved within my offsetParent.<br /><br />
124135
Both parent padding and child margin work properly.
125136
</div>
126137
</Draggable>
127138
</div>
128139
<Draggable>
129-
<div className="box" style={{position: 'absolute', bottom: '100px', right: '100px'}}>
140+
<div className="box" style={{position: 'absolute', bottom: '100px', right: '100px'}} {...drags}>
130141
I already have an absolute position.
131142
</div>
132143
</Draggable>
133-
<Draggable start={{x: 25, y: 25}}>
144+
<Draggable start={{x: 25, y: 25}} {...drags}>
134145
<div className="box">
135146
{"I have a start position of {x: 25, y: 25}, so I'm slightly offset."}
136147
</div>

lib/draggable.js

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -56,41 +56,24 @@ function matchesSelector(el, selector) {
5656
return el[method].call(el, selector);
5757
}
5858

59-
// @credits: http://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript/4819886#4819886
60-
/* Conditional to fix node server side rendering of component */
61-
if (typeof window === 'undefined') {
62-
// Do Node Stuff
63-
var isTouchDevice = false;
64-
} else {
65-
// Do Browser Stuff
66-
var isTouchDevice = 'ontouchstart' in window || // works on most browsers
67-
'onmsgesturechange' in window; // works on ie10 on ms surface
68-
69-
}
70-
71-
// look ::handleDragStart
72-
//function isMultiTouch(e) {
73-
// return e.touches && Array.isArray(e.touches) && e.touches.length > 1
74-
//}
75-
7659
/**
7760
* simple abstraction for dragging events names
7861
* */
79-
var dragEventFor = (function () {
80-
var eventsFor = {
81-
touch: {
82-
start: 'touchstart',
83-
move: 'touchmove',
84-
end: 'touchend'
85-
},
86-
mouse: {
87-
start: 'mousedown',
88-
move: 'mousemove',
89-
end: 'mouseup'
90-
}
91-
};
92-
return eventsFor[isTouchDevice ? 'touch' : 'mouse'];
93-
})();
62+
var eventsFor = {
63+
touch: {
64+
start: 'touchstart',
65+
move: 'touchmove',
66+
end: 'touchend'
67+
},
68+
mouse: {
69+
start: 'mousedown',
70+
move: 'mousemove',
71+
end: 'mouseup'
72+
}
73+
};
74+
75+
// Default to mouse events
76+
var dragEventFor = eventsFor['mouse'];
9477

9578
/**
9679
* get {clientX, clientY} positions of control
@@ -528,13 +511,6 @@ module.exports = React.createClass({
528511
},
529512

530513
handleDragStart: function (e) {
531-
// todo: write right implementation to prevent multitouch drag
532-
// prevent multi-touch events
533-
// if (isMultiTouch(e)) {
534-
// this.handleDragEnd.apply(e, arguments);
535-
// return
536-
// }
537-
538514
// Make it possible to attach event handlers on top of this one
539515
this.props.onMouseDown(e);
540516

@@ -619,6 +595,24 @@ module.exports = React.createClass({
619595
});
620596
},
621597

598+
onMouseDown: function(ev) {
599+
// Prevent 'ghost click' which happens 300ms after touchstart if the event isn't cancelled.
600+
// We don't cancel the event on touchstart because of #37; we might want to make a scrollable item draggable.
601+
// More on ghost clicks: http://ariatemplates.com/blog/2014/05/ghost-clicks-in-mobile-browsers/
602+
if (dragEventFor == eventsFor['touch']) {
603+
return ev.preventDefault();
604+
}
605+
606+
return this.handleDragStart.apply(this, arguments);
607+
},
608+
609+
onTouchStart: function(ev) {
610+
// We're on a touch device now, so change the event handlers
611+
dragEventFor = eventsFor['touch'];
612+
613+
return this.handleDragStart.apply(this, arguments);
614+
},
615+
622616
render: function () {
623617
// Create style object. We extend from existing styles so we don't
624618
// remove anything already set (like background, color, etc).
@@ -639,7 +633,14 @@ module.exports = React.createClass({
639633
this.state.clientY :
640634
0
641635
});
642-
var style = assign({}, childStyle, transform);
636+
637+
// Workaround IE pointer events; see #51
638+
// https://github.com/mzabriskie/react-draggable/issues/51#issuecomment-103488278
639+
var touchHacks = {
640+
touchAction: 'none'
641+
};
642+
643+
var style = assign({}, childStyle, transform, touchHacks);
643644

644645
// Set zIndex if currently dragging and prop has been provided
645646
if (this.state.dragging && !isNaN(this.props.zIndex)) {
@@ -657,12 +658,8 @@ module.exports = React.createClass({
657658
style: style,
658659
className: className,
659660

660-
onMouseDown: this.handleDragStart,
661-
onTouchStart: function(ev){
662-
ev.preventDefault(); // prevent for scroll
663-
return this.handleDragStart.apply(this, arguments);
664-
}.bind(this),
665-
661+
onMouseDown: this.onMouseDown,
662+
onTouchStart: this.onTouchStart,
666663
onMouseUp: this.handleDragEnd,
667664
onTouchEnd: this.handleDragEnd
668665
});

0 commit comments

Comments
 (0)