diff --git a/js/angular/controller/scrollController.js b/js/angular/controller/scrollController.js index daf6a71729b..f6564261c7a 100644 --- a/js/angular/controller/scrollController.js +++ b/js/angular/controller/scrollController.js @@ -184,6 +184,7 @@ function($scope, }; self.freezeScroll = scrollView.freeze; + self.freezeScrollShut = scrollView.freezeShut; self.freezeAllScrolls = function(shouldFreeze) { for (var i = 0; i < $ionicScrollDelegate._instances.length; i++) { diff --git a/js/angular/controller/sideMenuController.js b/js/angular/controller/sideMenuController.js index 44e24687b93..8567fb327f4 100644 --- a/js/angular/controller/sideMenuController.js +++ b/js/angular/controller/sideMenuController.js @@ -157,9 +157,10 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io // equal 0, otherwise remove the class from the body element $ionicBody.enableClass((percentage !== 0), 'menu-open'); - freezeAllScrolls(false); + self.content.setCanScroll(percentage == 0); }; + /* function freezeAllScrolls(shouldFreeze) { if (shouldFreeze && !self.isScrollFreeze) { $ionicScrollDelegate.freezeAllScrolls(shouldFreeze); @@ -169,6 +170,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io } self.isScrollFreeze = shouldFreeze; } + */ /** * Open the menu the given pixel amount. @@ -320,8 +322,6 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io // End a drag with the given event self._endDrag = function(e) { - freezeAllScrolls(false); - if (isAsideExposed) return; if (isDragging) { @@ -359,7 +359,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io if (isDragging) { self.openAmount(offsetX + (lastX - startX)); - freezeAllScrolls(true); + self.content.setCanScroll(false); } }; @@ -443,7 +443,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io } // ensure scrolls are unfrozen - freezeAllScrolls(false); + self.content.setCanScroll(true); }); self.initialize({ diff --git a/js/angular/directive/content.js b/js/angular/directive/content.js index 6e53f3dcb84..bdc260dad2c 100644 --- a/js/angular/directive/content.js +++ b/js/angular/directive/content.js @@ -159,6 +159,8 @@ function($timeout, $controller, $ionicBind, $ionicConfig) { scrollViewOptions: scrollViewOptions }); + $scope.scrollCtrl = scrollCtrl; + $scope.$on('$destroy', function() { if (scrollViewOptions) { scrollViewOptions.scrollingComplete = noop; diff --git a/js/angular/directive/sideMenuContent.js b/js/angular/directive/sideMenuContent.js index 31e9551d73d..337887c9cd1 100644 --- a/js/angular/directive/sideMenuContent.js +++ b/js/angular/directive/sideMenuContent.js @@ -133,6 +133,22 @@ function($timeout, $ionicGesture, $window) { element: element[0], onDrag: function() {}, endDrag: function() {}, + setCanScroll: function(canScroll) { + var c = $element[0].querySelector('.scroll'); + + if(!c) { + return; + } + + var content = angular.element(c.parentElement); + if(!content) { + return; + } + + // freeze our scroll container if we have one + var scrollScope = content.scope(); + scrollScope.scrollCtrl && scrollScope.scrollCtrl.freezeScrollShut(!canScroll); + }, getTranslateX: function() { return $scope.sideMenuContentTranslateX || 0; }, diff --git a/js/utils/poly.js b/js/utils/poly.js index ad892c14467..5331d0b4179 100644 --- a/js/utils/poly.js +++ b/js/utils/poly.js @@ -6,6 +6,8 @@ ionic.CSS.TRANSITION = []; ionic.CSS.TRANSFORM = []; + ionic.EVENTS = {}; + (function() { // transform @@ -41,6 +43,29 @@ ionic.CSS.TRANSITIONEND = (isWebkit ? 'webkitTransitionEnd ' : '') + 'transitionend'; })(); + (function() { + var touchStartEvent = 'touchstart' + var touchMoveEvent = 'touchmove' + var touchEndEvent = 'touchend' + var touchCancelEvent = 'touchcancel' + if (window.navigator.pointerEnabled) { + touchStartEvent = 'pointerdown'; + touchMoveEvent = 'pointermove'; + touchEndEvent = 'pointerup'; + touchCancelEvent = 'pointercancel'; + } else if (window.navigator.msPointerEnabled) { + touchStartEvent = 'MSPointerDown'; + touchMoveEvent = 'MSPointerMove'; + touchEndEvent = 'MSPointerUp'; + touchCancelEvent = 'MSPointerCancel'; + } + + ionic.EVENTS.touchstart = touchStartEvent; + ionic.EVENTS.touchmove = touchMoveEvent; + ionic.EVENTS.touchend = touchEndEvent; + ionic.EVENTS.touchcancel = touchCancelEvent; + })(); + // classList polyfill for them older Androids // https://gist.github.com/devongovett/1381839 if (!("classList" in document.documentElement) && Object.defineProperty && typeof HTMLElement !== 'undefined') { diff --git a/js/views/scrollView.js b/js/views/scrollView.js index e086cb5192a..74507e6c2e9 100644 --- a/js/views/scrollView.js +++ b/js/views/scrollView.js @@ -411,6 +411,9 @@ ionic.views.Scroll = ionic.views.View.inherit({ return self.options.freeze; }; + // We can just use the standard freeze pop in our mouth + self.freezeShut = self.freeze; + self.setScrollStart = function() { ionic.scroll.isScrolling = Math.abs(ionic.scroll.lastTop - self.__scrollTop) > 1; clearTimeout(self.scrollTimer); diff --git a/js/views/scrollViewNative.js b/js/views/scrollViewNative.js index e3595125c55..5eb168ea3aa 100644 --- a/js/views/scrollViewNative.js +++ b/js/views/scrollViewNative.js @@ -9,6 +9,8 @@ var self = this; self.__container = self.el = options.el; self.__content = options.el.firstElementChild; + // Whether scrolling is frozen or not + self.__frozen = false; self.isNative = true; self.__scrollTop = self.el.scrollTop; @@ -60,7 +62,13 @@ }, 80); }; - self.freeze = NOOP; + self.freeze = function(shouldFreeze) { + self.__frozen = shouldFreeze; + }; + // A more powerful freeze pop that dominates all other freeze pops + self.freezeShut = function(shouldFreezeShut) { + self.__frozenShut = shouldFreezeShut; + }; self.__initEventHandlers(); }, @@ -442,12 +450,23 @@ self.resize(); }; + self.handleTouchMove = function(e) { + if(self.__frozen || self.__frozenShut) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + } + container.addEventListener('scroll', self.onScroll); //Broadcasted when keyboard is shown on some platforms. //See js/utils/keyboard.js container.addEventListener('scrollChildIntoView', self.scrollChildIntoView); + container.addEventListener(ionic.EVENTS.touchstart, self.handleTouchMove); + container.addEventListener(ionic.EVENTS.touchmove, self.handleTouchMove); + // Listen on document because container may not have had the last // keyboardActiveElement, for example after closing a modal with a focused // input and returning to a previously resized scroll view in an ion-content. @@ -466,6 +485,9 @@ container.removeEventListener('scrollChildIntoView', self.scrollChildIntoView); container.removeEventListener('resetScrollView', self.resetScrollView); + container.removeEventListener(ionic.EVENTS.touchstart, self.handleTouchMove); + container.removeEventListener(ionic.EVENTS.touchmove, self.handleTouchMove); + ionic.tap.removeClonedInputs(container, self); delete self.__container; diff --git a/scss/_menu.scss b/scss/_menu.scss index ee10f4a5ba0..174667586b4 100644 --- a/scss/_menu.scss +++ b/scss/_menu.scss @@ -35,7 +35,12 @@ .menu-open .menu-content .pane, .menu-open .menu-content .scroll-content { pointer-events: none; - //overflow: hidden; +} +.menu-open .menu-content .scroll-content .scroll { + pointer-events: none; +} +.menu-open .menu-content .scroll-content:not(.overflow-scroll) { + overflow: hidden; } .grade-b .menu-content, diff --git a/test/html/sideMenu.html b/test/html/sideMenu.html index 8a10e3151d5..e30fe6444fc 100644 --- a/test/html/sideMenu.html +++ b/test/html/sideMenu.html @@ -28,6 +28,9 @@

Content

Sup Hello + + {{item.text}} +