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

Commit

Permalink
feat(ngTouch): add optional ngSwipeDisableMouse attribute to `ngSwi…
Browse files Browse the repository at this point in the history
…pe` directives to ignore mouse events.

This attribute is useful for text that should still be selectable
by the mouse and not trigger the swipe action.

This also adds an optional third argument to `$swipe.bind` to define
the pointer types that should be listened to.

Closes #6627
Fixes #6626
  • Loading branch information
robinboehm authored and tbosch committed May 14, 2014
1 parent e9bc51c commit 5a568b4
Show file tree
Hide file tree
Showing 4 changed files with 431 additions and 382 deletions.
9 changes: 8 additions & 1 deletion src/ngTouch/directive/ngSwipe.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
* Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag
* too.
*
* To disable the mouse click and drag functionality, add `ng-swipe-disable-mouse` to
* the `ng-swipe-left` or `ng-swipe-right` DOM Element.
*
* Requires the {@link ngTouch `ngTouch`} module to be installed.
*
* @element ANY
Expand Down Expand Up @@ -101,6 +104,10 @@ function makeSwipeDirective(directiveName, direction, eventName) {
deltaY / deltaX < MAX_VERTICAL_RATIO;
}

var pointerTypes = ['touch'];
if (!angular.isDefined(attr['ngSwipeDisableMouse'])) {
pointerTypes.push('mouse');
}
$swipe.bind(element, {
'start': function(coords, event) {
startCoords = coords;
Expand All @@ -117,7 +124,7 @@ function makeSwipeDirective(directiveName, direction, eventName) {
});
}
}
});
}, pointerTypes);
};
}]);
}
Expand Down
49 changes: 40 additions & 9 deletions src/ngTouch/swipe.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ ngTouch.factory('$swipe', [function() {
// The total distance in any direction before we make the call on swipe vs. scroll.
var MOVE_BUFFER_RADIUS = 10;

var POINTER_EVENTS = {
'mouse': {
start: 'mousedown',
move: 'mousemove',
end: 'mouseup'
},
'touch': {
start: 'touchstart',
move: 'touchmove',
end: 'touchend',
cancel: 'touchcancel'
}
};

function getCoordinates(event) {
var touches = event.touches && event.touches.length ? event.touches : [event];
var e = (event.changedTouches && event.changedTouches[0]) ||
Expand All @@ -38,6 +52,17 @@ ngTouch.factory('$swipe', [function() {
};
}

function getEvents(pointerTypes, eventType) {
var res = [];
angular.forEach(pointerTypes, function(pointerType) {
var eventName = POINTER_EVENTS[pointerType][eventType];
if (eventName) {
res.push(eventName);
}
});
return res.join(' ');
}

return {
/**
* @ngdoc method
Expand All @@ -46,6 +71,9 @@ ngTouch.factory('$swipe', [function() {
* @description
* The main method of `$swipe`. It takes an element to be watched for swipe motions, and an
* object containing event handlers.
* The pointer types that should be used can be specified via the optional
* third argument, which is an array of strings `'mouse'` and `'touch'`. By default,
* `$swipe` will listen for `mouse` and `touch` events.
*
* The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`
* receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }`.
Expand All @@ -68,7 +96,7 @@ ngTouch.factory('$swipe', [function() {
* as described above.
*
*/
bind: function(element, eventHandlers) {
bind: function(element, eventHandlers, pointerTypes) {
// Absolute total movement, used to control swipe vs. scroll.
var totalX, totalY;
// Coordinates of the start position.
Expand All @@ -78,21 +106,24 @@ ngTouch.factory('$swipe', [function() {
// Whether a swipe is active.
var active = false;

element.on('touchstart mousedown', function(event) {
pointerTypes = pointerTypes || ['mouse', 'touch'];
element.on(getEvents(pointerTypes, 'start'), function(event) {
startCoords = getCoordinates(event);
active = true;
totalX = 0;
totalY = 0;
lastPos = startCoords;
eventHandlers['start'] && eventHandlers['start'](startCoords, event);
});
var events = getEvents(pointerTypes, 'cancel');
if (events) {
element.on(events, function(event) {
active = false;
eventHandlers['cancel'] && eventHandlers['cancel'](event);
});
}

element.on('touchcancel', function(event) {
active = false;
eventHandlers['cancel'] && eventHandlers['cancel'](event);
});

element.on('touchmove mousemove', function(event) {
element.on(getEvents(pointerTypes, 'move'), function(event) {
if (!active) return;

// Android will send a touchcancel if it thinks we're starting to scroll.
Expand Down Expand Up @@ -126,7 +157,7 @@ ngTouch.factory('$swipe', [function() {
}
});

element.on('touchend mouseup', function(event) {
element.on(getEvents(pointerTypes, 'end'), function(event) {
if (!active) return;
active = false;
eventHandlers['end'] && eventHandlers['end'](getCoordinates(event), event);
Expand Down
18 changes: 18 additions & 0 deletions test/ngTouch/directive/ngSwipeSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,24 @@ var swipeTests = function(description, restrictBrowsers, startEvent, moveEvent,
expect($rootScope.swiped).toBe(true);
}));

it('should only swipe given ng-swipe-disable-mouse attribute for touch events', inject(function($rootScope, $compile) {
element = $compile('<div ng-swipe-left="swiped = true" ng-swipe-disable-mouse></div>')($rootScope);
$rootScope.$digest();
expect($rootScope.swiped).toBeUndefined();

browserTrigger(element, startEvent, {
keys : [],
x : 100,
y : 20
});
browserTrigger(element, endEvent,{
keys: [],
x: 20,
y: 20
});
expect(!!$rootScope.swiped).toBe(description !== 'mouse');
}));

it('should pass event object', inject(function($rootScope, $compile) {
element = $compile('<div ng-swipe-left="event = $event"></div>')($rootScope);
$rootScope.$digest();
Expand Down
Loading

0 comments on commit 5a568b4

Please sign in to comment.