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

Commit

Permalink
feat(ngTap): Add a CSS class while the element is held down.
Browse files Browse the repository at this point in the history
  • Loading branch information
bshepherdson authored and jbdeboer committed Apr 30, 2013
1 parent e295eee commit 52a55ec
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 6 deletions.
33 changes: 28 additions & 5 deletions src/ngMobile/directive/ngClick.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@

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

var ACTIVE_CLASS_NAME = 'ng-click-active';
var lastPreventedTime;
var touchCoordinates;

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

function resetState() {
tapping = false;
element.removeClass(ACTIVE_CLASS_NAME);
}

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

element.addClass(ACTIVE_CLASS_NAME);

startTime = Date.now();

var touches = event.touches && event.touches.length ? event.touches : [event];
Expand Down Expand Up @@ -224,7 +237,8 @@ ngMobile.directive('ngClick', ['$parse', '$timeout', '$rootElement',
clickHandler(scope, {$event: event});
});
}
tapping = false;

resetState();
});

// Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click
Expand All @@ -239,6 +253,15 @@ ngMobile.directive('ngClick', ['$parse', '$timeout', '$rootElement',
clickHandler(scope, {$event: event});
});
});

element.bind('mousedown', function(event) {
element.addClass(ACTIVE_CLASS_NAME);
});

element.bind('mousemove mouseup', function(event) {
element.removeClass(ACTIVE_CLASS_NAME);
});

};
}]);

20 changes: 19 additions & 1 deletion test/ngMobile/directive/ngClickSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ describe('ngClick (mobile)', function() {


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

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

it('should add the CSS class while the element is held down, and then remove it', inject(function($rootScope, $compile, $rootElement) {
element = $compile('<div ng-click="tapped = true"></div>')($rootScope);
$rootElement.append(element);
$rootScope.$digest();
expect($rootScope.tapped).toBeUndefined();

var CSS_CLASS = 'ng-click-active';

expect(element.hasClass(CSS_CLASS)).toBe(false);
browserTrigger(element, 'touchstart', 10, 10);
expect(element.hasClass(CSS_CLASS)).toBe(true);
browserTrigger(element, 'touchend', 10, 10);
expect(element.hasClass(CSS_CLASS)).toBe(false);
expect($rootScope.tapped).toBe(true);
}));


describe('the clickbuster', function() {
var element1, element2;
Expand Down Expand Up @@ -292,4 +308,6 @@ describe('ngClick (mobile)', function() {
expect($rootScope.event).toBeDefined();
}));
});


});

0 comments on commit 52a55ec

Please sign in to comment.