mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
fix(sideMenu): fix stopping content scrolling
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
This commit is contained in:
107
js/angular/directive/sideMenuContent.js
vendored
107
js/angular/directive/sideMenuContent.js
vendored
@@ -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');
|
||||
|
||||
@@ -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;
|
||||
|
||||
var dragVertFn = function(e) {
|
||||
if(isDragging) {
|
||||
if( getPrimaryScrollAxis(e) == 'x') {
|
||||
sideMenuCtrl._handleDrag(e);
|
||||
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 onDragY(e) {
|
||||
if( getPrimaryScrollAxis(e) == 'x' ) {
|
||||
e.gesture.srcEvent.preventDefault();
|
||||
}
|
||||
defaultPrevented = false;
|
||||
};
|
||||
}
|
||||
|
||||
var releaseGesture = $ionicGesture.on('release', dragReleaseFn, $element);
|
||||
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
|
||||
}
|
||||
|
||||
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],
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -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);
|
||||
@@ -342,7 +357,7 @@ function tapMouseDown(e) {
|
||||
}
|
||||
|
||||
tapPointerMoved = false;
|
||||
tapPointerStart = getPointerCoordinates(e);
|
||||
tapPointerStart = ionic.tap.pointerCoord(e);
|
||||
|
||||
tapEventListener('mousemove');
|
||||
ionic.activator.start(e);
|
||||
@@ -382,7 +397,7 @@ function tapTouchStart(e) {
|
||||
tapPointerMoved = false;
|
||||
|
||||
tapEnableTouchEvents();
|
||||
tapPointerStart = getPointerCoordinates(e);
|
||||
tapPointerStart = ionic.tap.pointerCoord(e);
|
||||
|
||||
tapEventListener(tapTouchMoveListener);
|
||||
ionic.activator.start(e);
|
||||
@@ -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') ?
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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;
|
||||
@@ -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) &&
|
||||
|
||||
@@ -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});
|
||||
});
|
||||
|
||||
@@ -634,7 +634,7 @@ 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});
|
||||
});
|
||||
|
||||
@@ -642,7 +642,7 @@ describe('Ionic Tap', 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});
|
||||
});
|
||||
|
||||
@@ -650,13 +650,13 @@ describe('Ionic Tap', 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});
|
||||
});
|
||||
|
||||
@@ -1232,8 +1232,8 @@ describe('Ionic Tap', function() {
|
||||
|
||||
ele.type = 'text';
|
||||
expect( ionic.tap.isDateInput(ele) ).toEqual(false);
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
it('Should isLabelWithTextInput', function() {
|
||||
|
||||
Reference in New Issue
Block a user