Skip to content

Commit c119498

Browse files
committed
feat($ionicScrollDelegate): add scrollTo(left,top,animate) to delegate
Also moves $ionicScrollDelegate.register to $ionicScroll controller, and makes `<scroll>` directive be registered with $ionicScrollDelegate.
1 parent 801d2d7 commit c119498

File tree

10 files changed

+158
-85
lines changed

10 files changed

+158
-85
lines changed

Diff for: config/karma.conf.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module.exports = function(config) {
1818
'config/lib/js/angular/angular.js',
1919
'config/lib/js/angular/angular-animate.js',
2020
'config/lib/js/angular/angular-mocks.js',
21-
'config/lib/js/angular-ui/angular-ui-router.js',
21+
'config/lib/js/angular-ui/angular-ui-router.js'
2222
]
2323
.concat(buildConfig.ionicFiles)
2424
.concat(buildConfig.angularIonicFiles)

Diff for: js/ext/angular/src/controller/ionicScrollController.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

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

6-
.controller('$ionicScroll', ['$scope', 'scrollViewOptions', '$timeout',
7-
function($scope, scrollViewOptions, $timeout) {
6+
.controller('$ionicScroll', ['$scope', 'scrollViewOptions', '$timeout', '$ionicScrollDelegate',
7+
function($scope, scrollViewOptions, $timeout, $ionicScrollDelegate) {
88

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

18-
this.$element = angular.element(element);
18+
var $element = this.$element = angular.element(element);
1919

2020
//Attach self to element as a controller so other directives can require this controller
2121
//through `require: '$ionicScroll'
22-
this.$element.data('$$ionicScrollController', this);
22+
$element.data('$$ionicScrollController', this);
23+
24+
//Register delegate for event handling
25+
$ionicScrollDelegate.register($scope, $element, scrollView);
2326

2427
$timeout(function() {
2528
scrollView.run();

Diff for: js/ext/angular/src/directive/ionicContent.js

-3
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,6 @@ angular.module('ionic.ui.content', ['ionic.ui.service', 'ionic.ui.scroll'])
120120
};
121121
}
122122

123-
// Register for scroll delegate event handling
124-
$ionicScrollDelegate.register($scope, $element);
125-
126123
// Check if this supports infinite scrolling and listen for scroll events
127124
// to trigger the infinite scrolling
128125
// TODO(ajoslin): move functionality out of this function and make testable

Diff for: js/ext/angular/src/directive/ionicScroll.js

-21
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ angular.module('ionic.ui.scroll', [])
3333
function prelink($scope, $element, $attr) {
3434
var scrollView, scrollCtrl, sc = $element[0].children[0];
3535

36-
// Create the internal scroll div
37-
sc.className = 'scroll';
3836
if(attr.padding == "true") {
3937
sc.classList.add('padding');
4038
}
@@ -63,25 +61,6 @@ angular.module('ionic.ui.scroll', [])
6361
scrollViewOptions: scrollViewOptions
6462
});
6563
scrollView = $scope.$parent.scrollView = scrollCtrl.scrollView;
66-
67-
$element.bind('scroll', function(e) {
68-
$scope.onScroll({
69-
event: e,
70-
scrollTop: e.detail ? e.detail.scrollTop : e.originalEvent ? e.originalEvent.detail.scrollTop : 0,
71-
scrollLeft: e.detail ? e.detail.scrollLeft: e.originalEvent ? e.originalEvent.detail.scrollLeft : 0
72-
});
73-
});
74-
75-
$scope.$parent.$on('scroll.resize', function(e) {
76-
// Run the resize after this digest
77-
$timeout(function() {
78-
scrollView && scrollView.resize();
79-
});
80-
});
81-
82-
$scope.$parent.$on('scroll.refreshComplete', function(e) {
83-
scrollView && scrollView.finishPullToRefresh();
84-
});
8564
}
8665
}
8766
};

Diff for: js/ext/angular/src/service/delegates/ionicScrollDelegate.js

+15-16
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ angular.module('ionic.ui.service.scrollDelegate', [])
1414
scrollBottom: function(animate) {
1515
$rootScope.$broadcast('scroll.scrollBottom', animate);
1616
},
17+
scrollTo: function(left, top, animate) {
18+
$rootScope.$broadcast('scroll.scrollTo', left, top, animate);
19+
},
1720
resize: function() {
1821
$rootScope.$broadcast('scroll.resize');
1922
},
@@ -45,18 +48,14 @@ angular.module('ionic.ui.service.scrollDelegate', [])
4548
getScrollView: function($scope) {
4649
return $scope.scrollView;
4750
},
51+
4852
/**
49-
* Register a scope for scroll event handling.
53+
* Register a scope and scroll view for scroll event handling.
5054
* $scope {Scope} the scope to register and listen for events
5155
*/
52-
register: function($scope, $element) {
53-
//Get scroll controller from parent
54-
var scrollCtrl = $element.controller('$ionicScroll');
55-
if (!scrollCtrl) {
56-
return;
57-
}
58-
var scrollView = scrollCtrl.scrollView;
59-
var scrollEl = scrollCtrl.element;
56+
register: function($scope, $element, scrollView) {
57+
58+
var scrollEl = $element[0];
6059

6160
function scrollViewResize() {
6261
// Run the resize after this digest
@@ -93,22 +92,22 @@ angular.module('ionic.ui.service.scrollDelegate', [])
9392
});
9493
});
9594

96-
/**
97-
* Called to scroll to the top of the content
98-
*
99-
* @param animate {boolean} whether to animate or just snap
100-
*/
95+
$scope.$parent.$on('scroll.scrollTo', function(e, left, top, animate) {
96+
scrollViewResize().then(function() {
97+
scrollView.scrollTo(left, top, !!animate);
98+
});
99+
});
101100
$scope.$parent.$on('scroll.scrollTop', function(e, animate) {
102101
scrollViewResize().then(function() {
103-
scrollView.scrollTo(0, 0, animate === false ? false : true);
102+
scrollView.scrollTo(0, 0, !!animate);
104103
});
105104
});
106105
$scope.$parent.$on('scroll.scrollBottom', function(e, animate) {
107106
scrollViewResize().then(function() {
108107
var sv = scrollView;
109108
if (sv) {
110109
var max = sv.getScrollMax();
111-
sv.scrollTo(0, max.top, animate === false ? false : true);
110+
sv.scrollTo(max.left, max.top, !!animate);
112111
}
113112
});
114113
});

Diff for: js/ext/angular/test/controller/ionicScrollController.unit.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
describe('$ionicScroll Controller', function() {
22

3-
beforeEach(module('ionic.ui.scroll'));
3+
beforeEach(module('ionic'));
44

55
var scope, ctrl, timeout;
66
function setup(options) {
@@ -41,6 +41,12 @@ describe('$ionicScroll Controller', function() {
4141
expect(ctrl.scrollView.run).toHaveBeenCalled();
4242
});
4343

44+
it('should register with $ionicScrollDelegate', inject(function($ionicScrollDelegate) {
45+
spyOn($ionicScrollDelegate, 'register');
46+
setup();
47+
expect($ionicScrollDelegate.register).toHaveBeenCalledWith(scope, ctrl.$element, ctrl.scrollView);
48+
}));
49+
4450
it('should not setup if no child .scroll-refresher', function() {
4551
setup();
4652
timeout.flush();
@@ -70,7 +76,6 @@ describe('$ionicScroll Controller', function() {
7076
});
7177

7278
scope.onRefresh = jasmine.createSpy('onRefresh');
73-
scope.$parent.$broadcast = jasmine.createSpy('$broadcast');
7479

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

8994
expect(scope.onRefresh).not.toHaveBeenCalled();
90-
expect(scope.$parent.$broadcast).not.toHaveBeenCalledWith('scroll.onRefresh');
9195

9296
doneCb();
9397
expect(refresher.classList.contains('active')).toBe(false);
9498
expect(refresher.classList.contains('refreshing')).toBe(true);
9599
expect(scope.onRefresh).toHaveBeenCalled();
96-
expect(scope.$parent.$broadcast).toHaveBeenCalledWith('scroll.onRefresh');
97100
});
98101

99102
});

Diff for: js/ext/angular/test/directive/ionicContent.unit.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
describe('Ionic Content directive', function() {
22
var compile, element, scope;
33

4-
beforeEach(module('ionic.ui.content'));
4+
beforeEach(module('ionic'));
55

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

14+
it('Has $ionicScroll controller', function() {
15+
element = compile('<content></content>')(scope);
16+
expect(element.controller('$ionicScroll').element).toBe(element[0]);
17+
});
18+
1419
it('Has content class', function() {
1520
element = compile('<content></content>')(scope);
1621
expect(element.hasClass('scroll-content')).toBe(true);

Diff for: js/ext/angular/test/directive/ionicScroll.unit.js

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
describe('Ionic Scroll Directive', function() {
2+
var compile, element, scope;
3+
4+
beforeEach(module('ionic'));
5+
6+
beforeEach(inject(function($compile, $rootScope, $timeout, $window) {
7+
compile = $compile;
8+
scope = $rootScope;
9+
timeout = $timeout;
10+
window = $window;
11+
ionic.Platform.setPlatform('Android');
12+
}));
13+
14+
it('Has $ionicScroll controller', function() {
15+
element = compile('<scroll></scroll>')(scope);
16+
expect(element.controller('$ionicScroll').element).toBe(element[0]);
17+
});
18+
19+
it('Has scroll-view class', function() {
20+
element = compile('<scroll></scroll>')(scope);
21+
expect(element.hasClass('scroll-view')).toBe(true);
22+
});
23+
24+
it('should add padding classname', function() {
25+
element = compile('<scroll padding="true"></scroll>')(scope);
26+
expect(element.children().eq(0).hasClass('padding')).toEqual(true);
27+
var scrollElement = element.find('.scroll');
28+
expect(scrollElement.hasClass('padding')).toEqual(true);
29+
});
30+
31+
it('Enables bouncing by default', function() {
32+
ionic.Platform.setPlatform('iPhone');
33+
element = compile('<content has-header="true"></scroll>')(scope);
34+
scope.$apply();
35+
var newScope = element.isolateScope();
36+
var scrollView = scope.scrollView;
37+
expect(scrollView.options.bouncing).toBe(true);
38+
});
39+
40+
it('Disables bouncing when has-bouncing = false', function() {
41+
ionic.Platform.setPlatform('iPhone');
42+
element = compile('<content has-header="true" has-bouncing="false"></scroll>')(scope);
43+
scope.$apply();
44+
var newScope = element.isolateScope();
45+
var scrollView = scope.scrollView;
46+
expect(scrollView.options.bouncing).toBe(false);
47+
});
48+
49+
it('Disables bouncing by default on Android', function() {
50+
ionic.Platform.setPlatform('Android');
51+
element = compile('<content has-header="true"></scroll>')(scope);
52+
scope.$apply();
53+
var newScope = element.isolateScope();
54+
var scrollView = scope.scrollView;
55+
expect(scrollView.options.bouncing).toBe(false);
56+
});
57+
58+
it('Should set start x and y', function() {
59+
element = compile('<content start-x="100" start-y="300" has-header="true"></scroll>')(scope);
60+
scope.$apply();
61+
var newScope = element.isolateScope();
62+
var scrollView = scope.scrollView;
63+
var vals = scrollView.getValues();
64+
expect(vals.left).toBe(100);
65+
expect(vals.top).toBe(300);
66+
});
67+
});

Diff for: js/ext/angular/test/scroll.html

+11-3
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,24 @@
5252

5353
<content has-header="true" scroll="false">
5454
<h3>Hourly Forecast</h3>
55-
<scroll direction="x" style="width: 100%">
55+
<scroll direction="x" style="width: 100%; height: 20%;">
5656
<div class="hours">
5757
<div ng-repeat="hour in hours">
5858
<div class="icons">
5959
<i class="icon ion-ios7-sunny-outline"></i>
6060
<i class="icon ion-cloud"></i>
6161
</div>
62+
</a>
6263
<div>
6364
{{hour.temp}} &deg;F
6465
</div>
6566
</div>
6667
</div>
6768
</scroll>
68-
<scroll direction="y" style="height: 400px; width: 300px">
69+
<a class="button" ng-click="scrollTo()">
70+
Scroll to 100
71+
</a>
72+
<scroll direction="y" style="height: 400px; width: 300px; background: red;">
6973
<div style="width: 100px; height: 4000px; background: url('tree_bark.png') repeat"></div>
7074
</scroll>
7175
</content>
@@ -83,7 +87,7 @@ <h3>Hourly Forecast</h3>
8387
}
8488
})
8589

86-
.controller('ThisCtrl', function($scope) {
90+
.controller('ThisCtrl', function($scope, $ionicScrollDelegate) {
8791
var header = document.getElementById('header');
8892
var content = document.getElementById('container');
8993

@@ -97,6 +101,10 @@ <h3>Hourly Forecast</h3>
97101
$scope.onScrollComplete = function(event, scrollTop, scrollLeft) {
98102
console.log('Scroll complete', scrollTop, scrollLeft);
99103
}
104+
$scope.scrollTo = function() {
105+
console.log('scrollTo');
106+
$ionicScrollDelegate.scrollTo(0, 100, true);
107+
};
100108
$scope.onScroll = function(event, scrollTop, scrollLeft) {
101109
/*
102110
if(scrollTop > startTop) {

0 commit comments

Comments
 (0)