Skip to content

Commit 1c00c85

Browse files
committed
Update click prevention to work properly with touch events AND mouse events
1 parent 0421700 commit 1c00c85

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

addon/components/scroll-view.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ function getScrolledToTopChanged(currentTop, lastTop, offset) {
4747
return { isAtTop, isAtTopChanged };
4848
}
4949

50+
function captureClick(e) {
51+
e.stopPropagation();
52+
window.removeEventListener('click', captureClick, true);
53+
}
54+
5055
class ScrollView extends Component {
5156
// @argument(optional('number'))
5257
// contentHeight; // optional, when not provided, we measure the size
@@ -155,18 +160,20 @@ class ScrollView extends Component {
155160
);
156161
}
157162

158-
onScrollChange(left, top) {
163+
onScrollChange(_left, top) {
159164
let scrollTop = top|0;
160165
if (this.isDestroyed || this.isDestroying) {
161166
return;
162167
}
163168
let { scroller } = this;
169+
let isScrolling = !!(scroller.__isDragging || scroller.__isDecelerating || scroller.__isAnimating);
170+
this._isScrolling = isScrolling;
164171
this._decelerationVelocityY = scroller.__decelerationVelocityY;
165172
this.applyScrollTop({
166173
scrollTop,
167174
lastTop: this._appliedScrollTop,
168-
isScrolling: !!(scroller.__isDragging || scroller.__isDecelerating || scroller.__isAnimating),
169-
decelerationVelocityY: this._decelerationVelocityY
175+
isScrolling,
176+
decelerationVelocityY: this._decelerationVelocityY
170177
});
171178
if (+(new Date()) - this._lastMeasurement > MEASUREMENT_INTERVAL_WHILE_SCROLLING_OR_OFFSCREEN) {
172179
this.measureClientAndContent();
@@ -242,25 +249,28 @@ class ScrollView extends Component {
242249
}
243250

244251
doTouchStart(touches, timeStamp) {
252+
this._wasScrollingAtTouchStart = this._isScrolling;
245253
this.scroller.doTouchStart(touches, timeStamp);
246254
}
247255

248256
doTouchMove(touches, timeStamp, scale) {
249257
this.scroller.doTouchMove(touches, timeStamp, scale)
250258
}
251259

252-
doTouchEnd(touches, timeStamp, event) {
260+
doTouchEnd(_touches, timeStamp, event) {
253261
let preventClick = this.needsPreventClick()
254-
262+
255263
if (preventClick) {
256-
event.preventDefault();
264+
// A touchend event can prevent a follow-on click event by calling preventDefault.
265+
// However, a mouseup event cannot do this so we need to capture the upcoming click instead.
266+
if (event instanceof MouseEvent) {
267+
window.addEventListener('click', captureClick, true);
268+
} else {
269+
event.preventDefault();
270+
}
257271
}
258272

259273
this.scroller.doTouchEnd(timeStamp);
260-
261-
if (preventClick) {
262-
this._decelerationVelocityY = null;
263-
}
264274
}
265275

266276
needsPreventClick() {
@@ -274,7 +284,7 @@ class ScrollView extends Component {
274284
//
275285
// This method determines whether either of these cases apply.
276286
let isFinishingDragging = this.scroller.__isDragging;
277-
let wasAnimatingWithMomentum = Math.abs(this._decelerationVelocityY) > 2;
287+
let wasAnimatingWithMomentum = this._wasScrollingAtTouchStart && Math.abs(this._decelerationVelocityY) > 2;
278288
return isFinishingDragging || wasAnimatingWithMomentum;
279289
}
280290

0 commit comments

Comments
 (0)