Skip to content

Commit

Permalink
feat($ionicScrollDelegate): add scrollTo(left,top,animate) to delegate
Browse files Browse the repository at this point in the history
Also moves $ionicScrollDelegate.register to $ionicScroll controller,
and makes `<scroll>` directive be registered with $ionicScrollDelegate.
  • Loading branch information
ajoslin committed Feb 11, 2014
1 parent 801d2d7 commit c119498
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 85 deletions.
2 changes: 1 addition & 1 deletion config/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module.exports = function(config) {
'config/lib/js/angular/angular.js',
'config/lib/js/angular/angular-animate.js',
'config/lib/js/angular/angular-mocks.js',
'config/lib/js/angular-ui/angular-ui-router.js',
'config/lib/js/angular-ui/angular-ui-router.js'
]
.concat(buildConfig.ionicFiles)
.concat(buildConfig.angularIonicFiles)
Expand Down
11 changes: 7 additions & 4 deletions js/ext/angular/src/controller/ionicScrollController.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

angular.module('ionic.ui.scroll')

.controller('$ionicScroll', ['$scope', 'scrollViewOptions', '$timeout',
function($scope, scrollViewOptions, $timeout) {
.controller('$ionicScroll', ['$scope', 'scrollViewOptions', '$timeout', '$ionicScrollDelegate',
function($scope, scrollViewOptions, $timeout, $ionicScrollDelegate) {

scrollViewOptions.bouncing = angular.isDefined(scrollViewOptions.bouncing) ?
scrollViewOptions.bouncing :
Expand All @@ -15,11 +15,14 @@ angular.module('ionic.ui.scroll')
var element = this.element = scrollViewOptions.el;
var scrollView = this.scrollView = new ionic.views.Scroll(scrollViewOptions);

this.$element = angular.element(element);
var $element = this.$element = angular.element(element);

//Attach self to element as a controller so other directives can require this controller
//through `require: '$ionicScroll'
this.$element.data('$$ionicScrollController', this);
$element.data('$$ionicScrollController', this);

//Register delegate for event handling
$ionicScrollDelegate.register($scope, $element, scrollView);

$timeout(function() {
scrollView.run();
Expand Down
3 changes: 0 additions & 3 deletions js/ext/angular/src/directive/ionicContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,6 @@ angular.module('ionic.ui.content', ['ionic.ui.service', 'ionic.ui.scroll'])
};
}

// Register for scroll delegate event handling
$ionicScrollDelegate.register($scope, $element);

// Check if this supports infinite scrolling and listen for scroll events
// to trigger the infinite scrolling
// TODO(ajoslin): move functionality out of this function and make testable
Expand Down
21 changes: 0 additions & 21 deletions js/ext/angular/src/directive/ionicScroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ angular.module('ionic.ui.scroll', [])
function prelink($scope, $element, $attr) {
var scrollView, scrollCtrl, sc = $element[0].children[0];

// Create the internal scroll div
sc.className = 'scroll';
if(attr.padding == "true") {
sc.classList.add('padding');
}
Expand Down Expand Up @@ -63,25 +61,6 @@ angular.module('ionic.ui.scroll', [])
scrollViewOptions: scrollViewOptions
});
scrollView = $scope.$parent.scrollView = scrollCtrl.scrollView;

$element.bind('scroll', function(e) {
$scope.onScroll({
event: e,
scrollTop: e.detail ? e.detail.scrollTop : e.originalEvent ? e.originalEvent.detail.scrollTop : 0,
scrollLeft: e.detail ? e.detail.scrollLeft: e.originalEvent ? e.originalEvent.detail.scrollLeft : 0
});
});

$scope.$parent.$on('scroll.resize', function(e) {
// Run the resize after this digest
$timeout(function() {
scrollView && scrollView.resize();
});
});

$scope.$parent.$on('scroll.refreshComplete', function(e) {
scrollView && scrollView.finishPullToRefresh();
});
}
}
};
Expand Down
31 changes: 15 additions & 16 deletions js/ext/angular/src/service/delegates/ionicScrollDelegate.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ angular.module('ionic.ui.service.scrollDelegate', [])
scrollBottom: function(animate) {
$rootScope.$broadcast('scroll.scrollBottom', animate);
},
scrollTo: function(left, top, animate) {
$rootScope.$broadcast('scroll.scrollTo', left, top, animate);
},
resize: function() {
$rootScope.$broadcast('scroll.resize');
},
Expand Down Expand Up @@ -45,18 +48,14 @@ angular.module('ionic.ui.service.scrollDelegate', [])
getScrollView: function($scope) {
return $scope.scrollView;
},

/**
* Register a scope for scroll event handling.
* Register a scope and scroll view for scroll event handling.
* $scope {Scope} the scope to register and listen for events
*/
register: function($scope, $element) {
//Get scroll controller from parent
var scrollCtrl = $element.controller('$ionicScroll');
if (!scrollCtrl) {
return;
}
var scrollView = scrollCtrl.scrollView;
var scrollEl = scrollCtrl.element;
register: function($scope, $element, scrollView) {

var scrollEl = $element[0];

function scrollViewResize() {
// Run the resize after this digest
Expand Down Expand Up @@ -93,22 +92,22 @@ angular.module('ionic.ui.service.scrollDelegate', [])
});
});

/**
* Called to scroll to the top of the content
*
* @param animate {boolean} whether to animate or just snap
*/
$scope.$parent.$on('scroll.scrollTo', function(e, left, top, animate) {
scrollViewResize().then(function() {
scrollView.scrollTo(left, top, !!animate);
});
});
$scope.$parent.$on('scroll.scrollTop', function(e, animate) {
scrollViewResize().then(function() {
scrollView.scrollTo(0, 0, animate === false ? false : true);
scrollView.scrollTo(0, 0, !!animate);
});
});
$scope.$parent.$on('scroll.scrollBottom', function(e, animate) {
scrollViewResize().then(function() {
var sv = scrollView;
if (sv) {
var max = sv.getScrollMax();
sv.scrollTo(0, max.top, animate === false ? false : true);
sv.scrollTo(max.left, max.top, !!animate);
}
});
});
Expand Down
11 changes: 7 additions & 4 deletions js/ext/angular/test/controller/ionicScrollController.unit.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
describe('$ionicScroll Controller', function() {

beforeEach(module('ionic.ui.scroll'));
beforeEach(module('ionic'));

var scope, ctrl, timeout;
function setup(options) {
Expand Down Expand Up @@ -41,6 +41,12 @@ describe('$ionicScroll Controller', function() {
expect(ctrl.scrollView.run).toHaveBeenCalled();
});

it('should register with $ionicScrollDelegate', inject(function($ionicScrollDelegate) {
spyOn($ionicScrollDelegate, 'register');
setup();
expect($ionicScrollDelegate.register).toHaveBeenCalledWith(scope, ctrl.$element, ctrl.scrollView);
}));

it('should not setup if no child .scroll-refresher', function() {
setup();
timeout.flush();
Expand Down Expand Up @@ -70,7 +76,6 @@ describe('$ionicScroll Controller', function() {
});

scope.onRefresh = jasmine.createSpy('onRefresh');
scope.$parent.$broadcast = jasmine.createSpy('$broadcast');

timeout.flush();
var refresher = ctrl.refresher;
Expand All @@ -87,13 +92,11 @@ describe('$ionicScroll Controller', function() {
expect(refresher.classList.contains('refreshing')).toBe(false);

expect(scope.onRefresh).not.toHaveBeenCalled();
expect(scope.$parent.$broadcast).not.toHaveBeenCalledWith('scroll.onRefresh');

doneCb();
expect(refresher.classList.contains('active')).toBe(false);
expect(refresher.classList.contains('refreshing')).toBe(true);
expect(scope.onRefresh).toHaveBeenCalled();
expect(scope.$parent.$broadcast).toHaveBeenCalledWith('scroll.onRefresh');
});

});
7 changes: 6 additions & 1 deletion js/ext/angular/test/directive/ionicContent.unit.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
describe('Ionic Content directive', function() {
var compile, element, scope;

beforeEach(module('ionic.ui.content'));
beforeEach(module('ionic'));

beforeEach(inject(function($compile, $rootScope, $timeout, $window) {
compile = $compile;
Expand All @@ -11,6 +11,11 @@ describe('Ionic Content directive', function() {
ionic.Platform.setPlatform('Android');
}));

it('Has $ionicScroll controller', function() {
element = compile('<content></content>')(scope);
expect(element.controller('$ionicScroll').element).toBe(element[0]);
});

it('Has content class', function() {
element = compile('<content></content>')(scope);
expect(element.hasClass('scroll-content')).toBe(true);
Expand Down
67 changes: 67 additions & 0 deletions js/ext/angular/test/directive/ionicScroll.unit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
describe('Ionic Scroll Directive', function() {
var compile, element, scope;

beforeEach(module('ionic'));

beforeEach(inject(function($compile, $rootScope, $timeout, $window) {
compile = $compile;
scope = $rootScope;
timeout = $timeout;
window = $window;
ionic.Platform.setPlatform('Android');
}));

it('Has $ionicScroll controller', function() {
element = compile('<scroll></scroll>')(scope);
expect(element.controller('$ionicScroll').element).toBe(element[0]);
});

it('Has scroll-view class', function() {
element = compile('<scroll></scroll>')(scope);
expect(element.hasClass('scroll-view')).toBe(true);
});

it('should add padding classname', function() {
element = compile('<scroll padding="true"></scroll>')(scope);
expect(element.children().eq(0).hasClass('padding')).toEqual(true);
var scrollElement = element.find('.scroll');
expect(scrollElement.hasClass('padding')).toEqual(true);
});

it('Enables bouncing by default', function() {
ionic.Platform.setPlatform('iPhone');
element = compile('<content has-header="true"></scroll>')(scope);
scope.$apply();
var newScope = element.isolateScope();
var scrollView = scope.scrollView;
expect(scrollView.options.bouncing).toBe(true);
});

it('Disables bouncing when has-bouncing = false', function() {
ionic.Platform.setPlatform('iPhone');
element = compile('<content has-header="true" has-bouncing="false"></scroll>')(scope);
scope.$apply();
var newScope = element.isolateScope();
var scrollView = scope.scrollView;
expect(scrollView.options.bouncing).toBe(false);
});

it('Disables bouncing by default on Android', function() {
ionic.Platform.setPlatform('Android');
element = compile('<content has-header="true"></scroll>')(scope);
scope.$apply();
var newScope = element.isolateScope();
var scrollView = scope.scrollView;
expect(scrollView.options.bouncing).toBe(false);
});

it('Should set start x and y', function() {
element = compile('<content start-x="100" start-y="300" has-header="true"></scroll>')(scope);
scope.$apply();
var newScope = element.isolateScope();
var scrollView = scope.scrollView;
var vals = scrollView.getValues();
expect(vals.left).toBe(100);
expect(vals.top).toBe(300);
});
});
14 changes: 11 additions & 3 deletions js/ext/angular/test/scroll.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,24 @@

<content has-header="true" scroll="false">
<h3>Hourly Forecast</h3>
<scroll direction="x" style="width: 100%">
<scroll direction="x" style="width: 100%; height: 20%;">
<div class="hours">
<div ng-repeat="hour in hours">
<div class="icons">
<i class="icon ion-ios7-sunny-outline"></i>
<i class="icon ion-cloud"></i>
</div>
</a>
<div>
{{hour.temp}} &deg;F
</div>
</div>
</div>
</scroll>
<scroll direction="y" style="height: 400px; width: 300px">
<a class="button" ng-click="scrollTo()">
Scroll to 100
</a>
<scroll direction="y" style="height: 400px; width: 300px; background: red;">
<div style="width: 100px; height: 4000px; background: url('tree_bark.png') repeat"></div>
</scroll>
</content>
Expand All @@ -83,7 +87,7 @@ <h3>Hourly Forecast</h3>
}
})

.controller('ThisCtrl', function($scope) {
.controller('ThisCtrl', function($scope, $ionicScrollDelegate) {
var header = document.getElementById('header');
var content = document.getElementById('container');

Expand All @@ -97,6 +101,10 @@ <h3>Hourly Forecast</h3>
$scope.onScrollComplete = function(event, scrollTop, scrollLeft) {
console.log('Scroll complete', scrollTop, scrollLeft);
}
$scope.scrollTo = function() {
console.log('scrollTo');
$ionicScrollDelegate.scrollTo(0, 100, true);
};
$scope.onScroll = function(event, scrollTop, scrollLeft) {
/*
if(scrollTop > startTop) {
Expand Down
Loading

0 comments on commit c119498

Please sign in to comment.