Skip to content

Commit 3ee5ea7

Browse files
committed
fix(tap): Deactivate elements during scroll at the same time click is ignored, #997
Previously I disabled the activation class immediately on a touchmove, where as the click will still work if you touchstart and touchend within a few pixels of each other. So visually it may have looked like the click shouldn't have worked. I just updated it so the use the same numbers. For example, if you hold down an item and move just 5 pixels, the item will stay active (before it wouldn't have), and the click will fire. But at the same time, if you hold down an item, and move a larger distance, once it realizes that it went farther than 6 pixels it'll not allow a click to happen, AND it'll not show the item as being active.
1 parent 4ff6acb commit 3ee5ea7

File tree

4 files changed

+29
-9
lines changed

4 files changed

+29
-9
lines changed

Diff for: js/ext/angular/test/list.html

+6
Original file line numberDiff line numberDiff line change
@@ -267,11 +267,14 @@ <h1>YELLOW {{slideBox.slideIndex}}</h1>
267267
});
268268

269269
var mouseTimerId;
270+
var mouseMoveCount = 0;
270271
function onMouseMove(e) {
271272
clearTimeout(mouseTimerId);
272273
mouseTimerId = setTimeout(function(){
273274
var el = document.getElementById('mousemove-notify');
274275
el.style.display = 'block';
276+
mouseMoveCount++;
277+
el.innerText = 'Mouse Move! ' + mouseMoveCount;
275278
clearTimeout(mouseTimerId);
276279
mouseTimerId = setTimeout(function(){
277280
el.style.display = 'none';
@@ -280,11 +283,14 @@ <h1>YELLOW {{slideBox.slideIndex}}</h1>
280283
}
281284

282285
var touchTimerId;
286+
var touchMoveCount = 0;
283287
function onTouchMove(e) {
284288
clearTimeout(touchTimerId);
285289
touchTimerId = setTimeout(function(){
286290
var el = document.getElementById('touchmove-notify');
287291
el.style.display = 'block';
292+
touchMoveCount++;
293+
el.innerText = 'Touch Move! ' + touchMoveCount;
288294
clearTimeout(touchTimerId);
289295
touchTimerId = setTimeout(function(){
290296
el.style.display = 'none';

Diff for: js/ext/angular/test/service/ionicTap.unit.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,16 @@ describe('Ionic Tap', function() {
7171
it('Should setStart and hasScrolled true if >= touch tolerance', function() {
7272
ionic.tap.setStart({ clientX: 100, clientY: 100 });
7373

74-
var s = ionic.tap.hasScrolled({ clientX: 105, clientY: 100 });
74+
var s = ionic.tap.hasScrolled({ clientX: 111, clientY: 100 });
7575
expect(s).toEqual(true);
7676

77-
s = ionic.tap.hasScrolled({ clientX: 95, clientY: 100 });
77+
s = ionic.tap.hasScrolled({ clientX: 89, clientY: 100 });
7878
expect(s).toEqual(true);
7979

80-
s = ionic.tap.hasScrolled({ clientX: 100, clientY: 103 });
80+
s = ionic.tap.hasScrolled({ clientX: 100, clientY: 107 });
8181
expect(s).toEqual(true);
8282

83-
s = ionic.tap.hasScrolled({ clientX: 100, clientY: 97 });
83+
s = ionic.tap.hasScrolled({ clientX: 100, clientY: 93 });
8484
expect(s).toEqual(true);
8585

8686
s = ionic.tap.hasScrolled({ clientX: 100, clientY: 200 });

Diff for: js/utils/activator.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
var activeElements = {}; // elements that are currently active
66
var keyId = 0; // a counter for unique keys for the above ojects
77
var ACTIVATED_CLASS = 'activated';
8+
var touchMoveClearTimer;
89

910
ionic.activator = {
1011

1112
start: function(e) {
13+
clearTimeout(touchMoveClearTimer);
14+
1215
// when an element is touched/clicked, it climbs up a few
1316
// parents to see if it is an .item or .button element
1417
ionic.requestAnimationFrame(function(){
@@ -39,7 +42,9 @@
3942
// add listeners to clear all queued/active elements onMove
4043
if(e.type === 'touchstart') {
4144
document.body.removeEventListener('mousedown', ionic.activator.start);
42-
document.body.addEventListener('touchmove', clear, false);
45+
touchMoveClearTimer = setTimeout(function(){
46+
document.body.addEventListener('touchmove', onTouchMove, false);
47+
}, 85);
4348
setTimeout(activateElements, 85);
4449
} else {
4550
document.body.addEventListener('mousemove', clear, false);
@@ -73,12 +78,20 @@
7378
}
7479
}
7580

81+
function onTouchMove(e) {
82+
if( ionic.tap.hasScrolled(e) ) {
83+
clear();
84+
}
85+
}
86+
7687
function onEnd(e) {
7788
// clear out any active/queued elements after XX milliseconds
7889
setTimeout(clear, 200);
7990
}
8091

8192
function clear() {
93+
clearTimeout(touchMoveClearTimer);
94+
8295
// clear out any elements that are queued to be set to active
8396
queueElements = {};
8497

Diff for: js/utils/tap.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
var REMOVE_PREVENT_DELAY = 380; // delay after a touchend/mouseup before removing the ghostclick prevent
66
var REMOVE_PREVENT_DELAY_GRADE_C = 800; // same as REMOVE_PREVENT_DELAY, but for grade c devices
77
var HIT_RADIUS = 15; // surrounding area of a click that if a ghostclick happens it would get ignored
8-
var TOUCH_TOLERANCE_X = 4; // how much the X coordinates can be off between start/end, but still a click
9-
var TOUCH_TOLERANCE_Y = 2; // how much the Y coordinates can be off between start/end, but still a click
8+
var TOUCH_TOLERANCE_X = 10; // how much the X coordinates can be off between start/end, but still a click
9+
var TOUCH_TOLERANCE_Y = 6; // how much the Y coordinates can be off between start/end, but still a click
1010
var tapCoordinates = {}; // used to remember coordinates to ignore if they happen again quickly
1111
var startCoordinates = {}; // used to remember where the coordinates of the start of a touch
1212
var clickPreventTimerId;
@@ -110,11 +110,11 @@
110110

111111
} else if(ionic.tap.hasScrolled(e)) {
112112
// this click's coordinates are different than its touchstart/mousedown, must have been scrolling
113-
console.debug('preventGhostClick', 'hasScrolled, startCoordinates, x:' + startCoordinates.x + ' y:' + startCoordinates.y);
113+
console.debug('preventGhostClick', 'hasScrolled');
114114
}
115115

116116
var c = ionic.tap.getCoordinates(e);
117-
return 'click at x:' + c.x + ', y:' + c.y;
117+
return 'click(' + c.x + ',' + c.y + '), start(' + startCoordinates.x + ',' + startCoordinates.y + ')';
118118
})());
119119

120120

@@ -153,6 +153,7 @@
153153
return false;
154154
}
155155

156+
// the allowed distance between touchstart/mousedown and
156157
return (c.x > startCoordinates.x + TOUCH_TOLERANCE_X ||
157158
c.x < startCoordinates.x - TOUCH_TOLERANCE_X ||
158159
c.y > startCoordinates.y + TOUCH_TOLERANCE_Y ||

0 commit comments

Comments
 (0)