diff --git a/dist/css/ionic.css b/dist/css/ionic.css index 9d599f748a..2c8abda114 100644 --- a/dist/css/ionic.css +++ b/dist/css/ionic.css @@ -2256,6 +2256,12 @@ body, .ionic-body { margin-top: -1px; width: auto; } +.scroll-view { + overflow: hidden; + -webkit-backface-visibility: hidden; + margin-top: -1px; + width: auto; } + /** * Scroll is the scroll view component available for complex and custom * scroll view functionality. @@ -2275,6 +2281,7 @@ body, .ionic-body { -webkit-transform-origin: left top; -moz-transform-origin: left top; transform-origin: left top; + white-space: nowrap; -webkit-backface-visibility: hidden; } .scroll-refresher { diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index 8f003045ed..77797106db 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -27,6 +27,7 @@ angular.module('ionic.service', [ angular.module('ionic.ui', [ 'ionic.ui.content', + 'ionic.ui.scroll', 'ionic.ui.tabs', 'ionic.ui.navRouter', 'ionic.ui.header', @@ -1572,6 +1573,102 @@ angular.module('ionic.ui.radio', []) (function() { 'use strict'; +angular.module('ionic.ui.scroll', []) + +.directive('scroll', ['$parse', '$timeout', function($parse, $timeout) { + return { + restrict: 'E', + replace: true, + template: '
', + transclude: true, + scope: { + direction: '@', + onRefresh: '&', + onScroll: '&', + refreshComplete: '=', + scroll: '@', + }, + + compile: function(element, attr, transclude) { + return function($scope, $element, $attr) { + var clone, sv, sc = document.createElement('div'); + + sc.className = 'scroll'; + if(attr.padding == "true") { + sc.className += ' padding'; + addedPadding = true; + } + $element.append(sc); + + // Pass the parent scope down to the child + clone = transclude($scope.$parent); + angular.element($element[0].firstElementChild).append(clone); + + var refresher = $element[0].querySelector('.scroll-refresher'); + var refresherHeight = refresher && refresher.clientHeight || 0; + + if(attr.refreshComplete) { + $scope.refreshComplete = function() { + if($scope.scrollView) { + refresher && refresher.classList.remove('active'); + $scope.scrollView.finishPullToRefresh(); + $scope.$parent.$broadcast('scroll.onRefreshComplete'); + } + }; + } + + + // Otherwise, supercharge this baby! + // Add timeout to let content render so Scroller.resize grabs the right content height + $timeout(function() { + var hasScrollingX = $scope.direction.indexOf('x') >= 0; + var hasScrollingY = $scope.direction.indexOf('y') >= 0; + + sv = new ionic.views.Scroll({ + el: $element[0], + scrollingX: hasScrollingX, + scrollingY: hasScrollingY + }); + + // Activate pull-to-refresh + if(refresher) { + sv.activatePullToRefresh(refresherHeight, function() { + refresher.classList.add('active'); + }, function() { + refresher.classList.remove('refreshing'); + refresher.classList.remove('active'); + }, function() { + refresher.classList.add('refreshing'); + $scope.onRefresh(); + $scope.$parent.$broadcast('scroll.onRefresh'); + }); + } + + $element.bind('scroll', function(e) { + $scope.onScroll({ + event: e, + scrollTop: e.detail.scrollTop, + scrollLeft: e.detail.scrollLeft + }); + }); + + $scope.$parent.$on('scroll.refreshComplete', function(e) { + sv && sv.finishPullToRefresh(); + }); + + // Let child scopes access this + $scope.$parent.scrollView = sv; + }, 500); + } + } + } +}]); + +})(); +; +(function() { +'use strict'; + /** * @description * The sideMenuCtrl lets you quickly have a draggable side diff --git a/js/ext/angular/src/directive/ionicScroll.js b/js/ext/angular/src/directive/ionicScroll.js new file mode 100644 index 0000000000..ae0ed0e604 --- /dev/null +++ b/js/ext/angular/src/directive/ionicScroll.js @@ -0,0 +1,95 @@ +(function() { +'use strict'; + +angular.module('ionic.ui.scroll', []) + +.directive('scroll', ['$parse', '$timeout', function($parse, $timeout) { + return { + restrict: 'E', + replace: true, + template: '
', + transclude: true, + scope: { + direction: '@', + onRefresh: '&', + onScroll: '&', + refreshComplete: '=', + scroll: '@', + }, + + compile: function(element, attr, transclude) { + return function($scope, $element, $attr) { + var clone, sv, sc = document.createElement('div'); + + sc.className = 'scroll'; + if(attr.padding == "true") { + sc.className += ' padding'; + addedPadding = true; + } + $element.append(sc); + + // Pass the parent scope down to the child + clone = transclude($scope.$parent); + angular.element($element[0].firstElementChild).append(clone); + + var refresher = $element[0].querySelector('.scroll-refresher'); + var refresherHeight = refresher && refresher.clientHeight || 0; + + if(attr.refreshComplete) { + $scope.refreshComplete = function() { + if($scope.scrollView) { + refresher && refresher.classList.remove('active'); + $scope.scrollView.finishPullToRefresh(); + $scope.$parent.$broadcast('scroll.onRefreshComplete'); + } + }; + } + + + // Otherwise, supercharge this baby! + // Add timeout to let content render so Scroller.resize grabs the right content height + $timeout(function() { + var hasScrollingX = $scope.direction.indexOf('x') >= 0; + var hasScrollingY = $scope.direction.indexOf('y') >= 0; + + sv = new ionic.views.Scroll({ + el: $element[0], + scrollingX: hasScrollingX, + scrollingY: hasScrollingY + }); + + // Activate pull-to-refresh + if(refresher) { + sv.activatePullToRefresh(refresherHeight, function() { + refresher.classList.add('active'); + }, function() { + refresher.classList.remove('refreshing'); + refresher.classList.remove('active'); + }, function() { + refresher.classList.add('refreshing'); + $scope.onRefresh(); + $scope.$parent.$broadcast('scroll.onRefresh'); + }); + } + + $element.bind('scroll', function(e) { + $scope.onScroll({ + event: e, + scrollTop: e.detail.scrollTop, + scrollLeft: e.detail.scrollLeft + }); + }); + + $scope.$parent.$on('scroll.refreshComplete', function(e) { + sv && sv.finishPullToRefresh(); + }); + + // Let child scopes access this + $scope.$parent.scrollView = sv; + }, 500); + } + } + } +}]); + +})(); diff --git a/js/ext/angular/src/ionicAngular.js b/js/ext/angular/src/ionicAngular.js index c94e8e8f8d..bc029e8a0f 100644 --- a/js/ext/angular/src/ionicAngular.js +++ b/js/ext/angular/src/ionicAngular.js @@ -14,6 +14,7 @@ angular.module('ionic.service', [ angular.module('ionic.ui', [ 'ionic.ui.content', + 'ionic.ui.scroll', 'ionic.ui.tabs', 'ionic.ui.navRouter', 'ionic.ui.header', diff --git a/js/ext/angular/test/header.html b/js/ext/angular/test/header.html index bf3ad328a8..ac5f323638 100644 --- a/js/ext/angular/test/header.html +++ b/js/ext/angular/test/header.html @@ -20,6 +20,7 @@ left-buttons="leftButtons" right-buttons="rightButtons" type="bar-primary"> + diff --git a/scss/_scaffolding.scss b/scss/_scaffolding.scss index 2645ceddb4..214cada7c4 100644 --- a/scss/_scaffolding.scss +++ b/scss/_scaffolding.scss @@ -77,6 +77,17 @@ body, .ionic-body { width: auto; } +.scroll-view { + overflow: hidden; + //-webkit-perspective: 1000; + -webkit-backface-visibility: hidden; + + // Hide the top border if any + margin-top: -1px; + + width: auto; +} + /** * Scroll is the scroll view component available for complex and custom * scroll view functionality. @@ -87,6 +98,7 @@ body, .ionic-body { @include text-size-adjust(none); @include translateZ(0); @include transform-origin(left, top); + white-space: nowrap; //-webkit-perspective: 1000; -webkit-backface-visibility: hidden; }