Skip to content

Commit

Permalink
fix(sideMenu): fix stopping content scrolling
Browse files Browse the repository at this point in the history
When a list was within a side menu it could scroll up and down, but if
the user happened to drag a little bit on the X axis, then it would try
to open the side menu and the Y scroll of the content stopped. Closes
#1541
  • Loading branch information
adamdbradley committed Aug 7, 2014
1 parent e5b5906 commit 944d259
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 66 deletions.
109 changes: 72 additions & 37 deletions js/angular/directive/sideMenuContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ function($timeout, $ionicGesture) {
compile: function(element, attr) {
return { pre: prelink };
function prelink($scope, $element, $attr, sideMenuCtrl) {
var startCoord = null;
var primaryScrollAxis = null;

$element.addClass('menu-content pane');

Expand All @@ -54,48 +56,75 @@ function($timeout, $ionicGesture) {
$scope.$watch(attr.edgeDragThreshold, function(value) {
sideMenuCtrl.edgeDragThreshold(value);
});
}

var defaultPrevented = false;
var isDragging = false;
}

// Listen for taps on the content to close the menu
function contentTap(e) {
function onContentTap(e) {
if(sideMenuCtrl.getOpenAmount() !== 0) {
sideMenuCtrl.close();
e.gesture.srcEvent.preventDefault();
startCoord = null;
primaryScrollAxis = null;
}
}
ionic.on('tap', contentTap, $element[0]);

var dragFn = function(e) {
if(defaultPrevented || !sideMenuCtrl.isDraggableTarget(e)) return;
isDragging = true;
sideMenuCtrl._handleDrag(e);
e.gesture.srcEvent.preventDefault();
};
function onDragX(e) {
if(!sideMenuCtrl.isDraggableTarget(e)) return;

if( getPrimaryScrollAxis(e) == 'x') {
sideMenuCtrl._handleDrag(e);
e.gesture.srcEvent.preventDefault();
}
}

var dragVertFn = function(e) {
if(isDragging) {
function onDragY(e) {
if( getPrimaryScrollAxis(e) == 'x' ) {
e.gesture.srcEvent.preventDefault();
}
};

//var dragGesture = Gesture.on('drag', dragFn, $element);
var dragRightGesture = $ionicGesture.on('dragright', dragFn, $element);
var dragLeftGesture = $ionicGesture.on('dragleft', dragFn, $element);
var dragUpGesture = $ionicGesture.on('dragup', dragVertFn, $element);
var dragDownGesture = $ionicGesture.on('dragdown', dragVertFn, $element);

var dragReleaseFn = function(e) {
isDragging = false;
if(!defaultPrevented) {
sideMenuCtrl._endDrag(e);
}

function onDragRelease(e) {
sideMenuCtrl._endDrag(e);
startCoord = null;
primaryScrollAxis = null;
}

function getPrimaryScrollAxis(gestureEvt) {
// gets whether the user is primarily scrolling on the X or Y
// If a majority of the drag has been on the Y since the start of
// the drag, but the X has moved a little bit, it's still a Y drag

if(primaryScrollAxis) {
// we already figured out which way they're scrolling
return primaryScrollAxis
}
defaultPrevented = false;
};

var releaseGesture = $ionicGesture.on('release', dragReleaseFn, $element);
if(gestureEvt && gestureEvt.gesture) {

if(!startCoord) {
// get the starting point
startCoord = ionic.tap.pointerCoord(gestureEvt.gesture.srcEvent);

} else {
// we already have a starting point, figure out which direction they're going
var endCoord = ionic.tap.pointerCoord(gestureEvt.gesture.srcEvent);

var xDistance = Math.abs(endCoord.x - startCoord.x);
var yDistance = Math.abs(endCoord.y - startCoord.y);

var scrollAxis = ( xDistance > yDistance ? 'x' : 'y' );

if( Math.max(xDistance, yDistance) > 30 ) {
// ok, we pretty much know which way they're going
// let's lock it in
primaryScrollAxis = scrollAxis;
}

return scrollAxis;
}

}
}

sideMenuCtrl.setContent({
element: element[0],
Expand All @@ -111,25 +140,31 @@ function($timeout, $ionicGesture) {
});
}),
enableAnimation: function() {
//this.el.classList.add(this.animateClass);
$scope.animationEnabled = true;
$element[0].classList.add('menu-animated');
},
disableAnimation: function() {
//this.el.classList.remove(this.animateClass);
$scope.animationEnabled = false;
$element[0].classList.remove('menu-animated');
}
});

// add gesture handlers
var dragRightGesture = $ionicGesture.on('dragright', onDragX, $element);
var dragLeftGesture = $ionicGesture.on('dragleft', onDragX, $element);
var dragUpGesture = $ionicGesture.on('dragup', onDragY, $element);
var dragDownGesture = $ionicGesture.on('dragdown', onDragY, $element);
var releaseGesture = $ionicGesture.on('release', onDragRelease, $element);
var contentTapGesture = $ionicGesture.on('tap', onContentTap, $element);

// Cleanup
$scope.$on('$destroy', function() {
$ionicGesture.off(dragLeftGesture, 'dragleft', dragFn);
$ionicGesture.off(dragRightGesture, 'dragright', dragFn);
$ionicGesture.off(dragUpGesture, 'dragup', dragFn);
$ionicGesture.off(dragDownGesture, 'dragdown', dragFn);
$ionicGesture.off(releaseGesture, 'release', dragReleaseFn);
ionic.off('tap', contentTap, $element[0]);
$ionicGesture.off(dragLeftGesture, 'dragleft', onDragX);
$ionicGesture.off(dragRightGesture, 'dragright', onDragX);
$ionicGesture.off(dragUpGesture, 'dragup', onDragY);
$ionicGesture.off(dragDownGesture, 'dragdown', onDragY);
$ionicGesture.off(releaseGesture, 'release', onDragRelease);
$ionicGesture.off(contentTapGesture, 'tap', onContentTap);
});
}
}
Expand Down
38 changes: 19 additions & 19 deletions js/utils/tap.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,21 @@ ionic.tap = {
// used to cancel any simulated clicks which may happen on a touchend/mouseup
// gestures uses this method within its tap and hold events
tapPointerMoved = true;
},

pointerCoord: function(event) {
// This method can get coordinates for both a mouse click
// or a touch depending on the given event
var c = { x:0, y:0 };
if(event) {
var touches = event.touches && event.touches.length ? event.touches : [event];
var e = (event.changedTouches && event.changedTouches[0]) || touches[0];
if(e) {
c.x = e.clientX || e.pageX || 0;
c.y = e.clientY || e.pageY || 0;
}
}
return c;
}

};
Expand All @@ -285,7 +300,7 @@ function tapClick(e) {

if( ionic.tap.requiresNativeClick(ele) || tapPointerMoved ) return false;

var c = getPointerCoordinates(e);
var c = ionic.tap.pointerCoord(e);

console.log('tapClick', e.type, ele.tagName, '('+c.x+','+c.y+')');
triggerMouseEvent('click', ele, c.x, c.y);
Expand Down Expand Up @@ -342,7 +357,7 @@ function tapMouseDown(e) {
}

tapPointerMoved = false;
tapPointerStart = getPointerCoordinates(e);
tapPointerStart = ionic.tap.pointerCoord(e);

tapEventListener('mousemove');
ionic.activator.start(e);
Expand Down Expand Up @@ -382,7 +397,7 @@ function tapTouchStart(e) {
tapPointerMoved = false;

tapEnableTouchEvents();
tapPointerStart = getPointerCoordinates(e);
tapPointerStart = ionic.tap.pointerCoord(e);

tapEventListener(tapTouchMoveListener);
ionic.activator.start(e);
Expand Down Expand Up @@ -530,7 +545,7 @@ function tapHasPointerMoved(endEvent) {
if(!endEvent || endEvent.target.nodeType !== 1 || !tapPointerStart || ( tapPointerStart.x === 0 && tapPointerStart.y === 0 )) {
return false;
}
var endCoordinates = getPointerCoordinates(endEvent);
var endCoordinates = ionic.tap.pointerCoord(endEvent);

var hasClassList = !!(endEvent.target.classList && endEvent.target.classList.contains);
var releaseTolerance = hasClassList & endEvent.target.classList.contains('button') ?
Expand All @@ -541,21 +556,6 @@ function tapHasPointerMoved(endEvent) {
Math.abs(tapPointerStart.y - endCoordinates.y) > releaseTolerance;
}

function getPointerCoordinates(event) {
// This method can get coordinates for both a mouse click
// or a touch depending on the given event
var c = { x:0, y:0 };
if(event) {
var touches = event.touches && event.touches.length ? event.touches : [event];
var e = (event.changedTouches && event.changedTouches[0]) || touches[0];
if(e) {
c.x = e.clientX || e.pageX || 0;
c.y = e.clientY || e.pageY || 0;
}
}
return c;
}

function tapContainingElement(ele, allowSelf) {
var climbEle = ele;
for(var x=0; x<6; x++) {
Expand Down
4 changes: 2 additions & 2 deletions js/views/scrollView.js
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ ionic.views.Scroll = ionic.views.View.inherit({
}

self.touchStart = function(e) {
self.startCoordinates = getPointerCoordinates(e);
self.startCoordinates = ionic.tap.pointerCoord(e);

if ( ionic.tap.ignoreScrollStart(e) ) {
return;
Expand Down Expand Up @@ -744,7 +744,7 @@ ionic.views.Scroll = ionic.views.View.inherit({

if(self.startCoordinates) {
// we have start coordinates, so get this touch move's current coordinates
var currentCoordinates = getPointerCoordinates(e);
var currentCoordinates = ionic.tap.pointerCoord(e);

if( self.__isSelectable &&
ionic.tap.isTextInput(e.target) &&
Expand Down
16 changes: 8 additions & 8 deletions test/unit/utils/tap.unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -619,13 +619,13 @@ describe('Ionic Tap', function() {

it('Should get coordinates from page mouse event', function() {
var e = { pageX: 77, pageY: 77 };
var c = getPointerCoordinates(e);
var c = ionic.tap.pointerCoord(e);
expect(c).toEqual({x:77, y: 77});
});

it('Should get coordinates from client mouse event', function() {
var e = { clientX: 77, clientY: 77 };
var c = getPointerCoordinates(e);
var c = ionic.tap.pointerCoord(e);
expect(c).toEqual({x:77, y: 77});
});

Expand All @@ -634,29 +634,29 @@ describe('Ionic Tap', function() {
touches: [{ clientX: 99, clientY: 99 }],
changedTouches: [{ clientX: 88, clientY: 88 }]
};
var c = getPointerCoordinates(e);
var c = ionic.tap.pointerCoord(e);
expect(c).toEqual({x:88, y: 88});
});

it('Should get coordinates from page touches', function() {
var e = {
touches: [{ pageX: 99, pageY: 99 }]
};
var c = getPointerCoordinates(e);
var c = ionic.tap.pointerCoord(e);
expect(c).toEqual({x:99, y: 99});
});

it('Should get coordinates from client touches', function() {
var e = {
touches: [{ clientX: 99, clientY: 99 }]
};
var c = getPointerCoordinates(e);
var c = ionic.tap.pointerCoord(e);
expect(c).toEqual({x:99, y: 99});
});

it('Should get 0 coordinates', function() {
var e = {};
var c = getPointerCoordinates(e);
var c = ionic.tap.pointerCoord(e);
expect(c).toEqual({x:0, y: 0});
});

Expand Down Expand Up @@ -1232,8 +1232,8 @@ describe('Ionic Tap', function() {

ele.type = 'text';
expect( ionic.tap.isDateInput(ele) ).toEqual(false);


});

it('Should isLabelWithTextInput', function() {
Expand Down

0 comments on commit 944d259

Please sign in to comment.