Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 52a55ec

Browse files
bshepherdsonjbdeboer
authored andcommitted
feat(ngTap): Add a CSS class while the element is held down.
1 parent e295eee commit 52a55ec

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

src/ngMobile/directive/ngClick.js

+28-5
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,19 @@
22

33
/**
44
* @ngdoc directive
5-
* @name ngMobile.directive:ngTap
5+
* @name ngMobile.directive:ngClick
66
*
77
* @description
8-
* Specify custom behavior when element is tapped on a touchscreen device.
9-
* A tap is a brief, down-and-up touch without much motion.
8+
* A more powerful replacement for the default ngClick designed to be used on touchscreen
9+
* devices. Most mobile browsers wait about 300ms after a tap-and-release before sending
10+
* the click event. This version handles them immediately, and then prevents the
11+
* following click event from propagating.
12+
*
13+
* This directive can fall back to using an ordinary click event, and so works on desktop
14+
* browsers as well as mobile.
15+
*
16+
* This directive also sets the CSS class `ng-click-active` while the element is being held
17+
* down (by a mouse click or touch) so you can restyle the depressed element if you wish.
1018
*
1119
* @element ANY
1220
* @param {expression} ngClick {@link guide/expression Expression} to evaluate
@@ -15,7 +23,7 @@
1523
* @example
1624
<doc:example>
1725
<doc:source>
18-
<button ng-tap="count = count + 1" ng-init="count=0">
26+
<button ng-click="count = count + 1" ng-init="count=0">
1927
Increment
2028
</button>
2129
count: {{ count }}
@@ -37,6 +45,8 @@ ngMobile.directive('ngClick', ['$parse', '$timeout', '$rootElement',
3745
var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers.
3846
var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click
3947
var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks.
48+
49+
var ACTIVE_CLASS_NAME = 'ng-click-active';
4050
var lastPreventedTime;
4151
var touchCoordinates;
4252

@@ -172,6 +182,7 @@ ngMobile.directive('ngClick', ['$parse', '$timeout', '$rootElement',
172182

173183
function resetState() {
174184
tapping = false;
185+
element.removeClass(ACTIVE_CLASS_NAME);
175186
}
176187

177188
element.bind('touchstart', function(event) {
@@ -182,6 +193,8 @@ ngMobile.directive('ngClick', ['$parse', '$timeout', '$rootElement',
182193
tapElement = tapElement.parentNode;
183194
}
184195

196+
element.addClass(ACTIVE_CLASS_NAME);
197+
185198
startTime = Date.now();
186199

187200
var touches = event.touches && event.touches.length ? event.touches : [event];
@@ -224,7 +237,8 @@ ngMobile.directive('ngClick', ['$parse', '$timeout', '$rootElement',
224237
clickHandler(scope, {$event: event});
225238
});
226239
}
227-
tapping = false;
240+
241+
resetState();
228242
});
229243

230244
// Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click
@@ -239,6 +253,15 @@ ngMobile.directive('ngClick', ['$parse', '$timeout', '$rootElement',
239253
clickHandler(scope, {$event: event});
240254
});
241255
});
256+
257+
element.bind('mousedown', function(event) {
258+
element.addClass(ACTIVE_CLASS_NAME);
259+
});
260+
261+
element.bind('mousemove mouseup', function(event) {
262+
element.removeClass(ACTIVE_CLASS_NAME);
263+
});
264+
242265
};
243266
}]);
244267

test/ngMobile/directive/ngClickSpec.js

+19-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ describe('ngClick (mobile)', function() {
8282

8383

8484
it('should not click if a touchmove comes before touchend', inject(function($rootScope, $compile, $rootElement) {
85-
element = $compile('<div ng-tap="tapped = true"></div>')($rootScope);
85+
element = $compile('<div ng-click="tapped = true"></div>')($rootScope);
8686
$rootElement.append(element);
8787
$rootScope.$digest();
8888

@@ -95,6 +95,22 @@ describe('ngClick (mobile)', function() {
9595
expect($rootScope.tapped).toBeUndefined();
9696
}));
9797

98+
it('should add the CSS class while the element is held down, and then remove it', inject(function($rootScope, $compile, $rootElement) {
99+
element = $compile('<div ng-click="tapped = true"></div>')($rootScope);
100+
$rootElement.append(element);
101+
$rootScope.$digest();
102+
expect($rootScope.tapped).toBeUndefined();
103+
104+
var CSS_CLASS = 'ng-click-active';
105+
106+
expect(element.hasClass(CSS_CLASS)).toBe(false);
107+
browserTrigger(element, 'touchstart', 10, 10);
108+
expect(element.hasClass(CSS_CLASS)).toBe(true);
109+
browserTrigger(element, 'touchend', 10, 10);
110+
expect(element.hasClass(CSS_CLASS)).toBe(false);
111+
expect($rootScope.tapped).toBe(true);
112+
}));
113+
98114

99115
describe('the clickbuster', function() {
100116
var element1, element2;
@@ -292,4 +308,6 @@ describe('ngClick (mobile)', function() {
292308
expect($rootScope.event).toBeDefined();
293309
}));
294310
});
311+
312+
295313
});

0 commit comments

Comments
 (0)