Skip to content

Commit dbe4e39

Browse files
committed
feat(ionic): remove all delegates
BREAKING CHANGE: $ionicScrollDelegate, $ionicSlideBoxDelegate, and $ionicSideMenuDelegate have been removed. - $ionicScrollDelegate has been changed to $ionicScrollController. Documentation: [ionContent]( http://ajoslin.github.io/docs/nightly/api/directive/ionContent), [ionScroll]( http://ajoslin.github.io/docs/nightly/api/directive/ionScroll) Change your code from this: ```html <ion-content ng-controller="MyCtrl"> <button ng-click="scrollBottom()">Scroll to bottom!</button> </ion-content> ``` ```js function MyCtrl($scope, $ionicScrollDelegate) { $scope.scrollBottom = function() { $ionicScrollDelegate.scrollBottom(); }; } ``` To this: ```html <!-- optional attr controller-bind, see docs --> <ion-content ng-controller="MyCtrl"> <button ng-click="scrollBottom()">Scroll to bottom!</button> </ion-content> ``` ```js function MyCtrl($scope) { $scope.scrollBottom = function() { $scope.$ionicScrollController.scrollBottom(); }; } ``` - $ionicSideMenuDelegate has been changed to $ionicSideMenusController. Documentation: [ionSideMenus](http://ajoslin.github.io/docs/nightly/api/directive/ionSideMenus) Change your code from this: ```html <ion-side-menus> <ion-side-menu side="left">Side Menu Left</ion-side-menu> <ion-pane ion-side-menu-content ng-controller="MyCtrl"> <button ng-click="toggleLeftMenu()"> Toggle Left Menu! </button> </ion-pane> </ion-side-menus> ``` ```js function MyCtrl($scope, $ionicSideMenuDelegate) { $scope.toggleLeftMenu = function() { $ionicSideMenuDelegate.toggleLeft(); }; } ``` To this: ```html <!-- optional attr controller-bind, see documentation --> <ion-side-menus> <ion-side-menu side="left">Side Menu Left</ion-side-menu> <ion-pane ion-side-menu-content ng-controller="MyCtrl"> <button ng-click="toggleLeftMenu()"> Toggle Left Menu! </button> </ion-pane> </ion-side-menus> ``` ```js function MyCtrl($scope) { $scope.toggleLeftMenu = function() { $scope.$ionicSideMenuController.toggleLeft(); }; } ``` - $ionicSlideBoxDelegate has been removed and upgraded to $ionicSlideBoxController. It had only one method that was unneeded. [Documentation]( http://ajoslin.github.io/docs/nightly/api/directive/ionSlideBox)
1 parent 630c648 commit dbe4e39

23 files changed

+430
-687
lines changed

js/ext/angular/src/controller/ionicScrollController.js

+111-29
Original file line numberDiff line numberDiff line change
@@ -6,58 +6,144 @@ angular.module('ionic.ui.scroll')
66
/**
77
* @private
88
*/
9-
.controller('$ionicScroll', ['$scope', 'scrollViewOptions', '$timeout', '$ionicScrollDelegate', '$window', function($scope, scrollViewOptions, $timeout, $ionicScrollDelegate, $window) {
9+
.factory('$$scrollValueCache', function() {
10+
return {};
11+
})
12+
13+
.controller('$ionicScroll', [
14+
'$scope',
15+
'scrollViewOptions',
16+
'$timeout',
17+
'$window',
18+
'$$scrollValueCache',
19+
'$location',
20+
'$parse',
21+
'$rootScope',
22+
'$document',
23+
function($scope, scrollViewOptions, $timeout, $window, $$scrollValueCache, $location, $parse, $rootScope, $document) {
1024

1125
var self = this;
1226

1327
var element = this.element = scrollViewOptions.el;
28+
var $element = this.$element = angular.element(element);
1429
var scrollView = this.scrollView = new ionic.views.Scroll(scrollViewOptions);
1530

16-
this.$scope = $scope;
17-
$scope.$parent.$$ionicScrollController = this;
31+
//Attach self to element as a controller so other directives can require this controller
32+
//through `require: '$ionicScroll'
33+
//Also attach to parent so that sibling elements can require this
34+
($element.parent().length ? $element.parent() : $element)
35+
.data('$$ionicScrollController', this);
36+
37+
$parse(scrollViewOptions.controllerBind || '$ionicScrollController')
38+
.assign($scope.$parent, this);
1839

1940
if (!angular.isDefined(scrollViewOptions.bouncing)) {
2041
ionic.Platform.ready(function() {
2142
scrollView.options.bouncing = !ionic.Platform.isAndroid();
2243
});
2344
}
2445

25-
var $element = this.$element = angular.element(element);
46+
var resize = angular.bind(scrollView, scrollView.resize);
47+
$window.addEventListener('resize', resize);
2648

27-
//Attach self to element as a controller so other directives can require this controller
28-
//through `require: '$ionicScroll'
29-
$element.data('$$ionicScrollController', this);
49+
// set by rootScope listener if needed
50+
var backListenDone = angular.noop;
3051

31-
//Register delegate for event handling
32-
$ionicScrollDelegate.register($scope, $element, scrollView);
52+
$scope.$on('$destroy', function() {
53+
$window.removeEventListener('resize', resize);
54+
backListenDone();
55+
if (self._rememberScrollId) {
56+
$$scrollValueCache[self._rememberScrollId] = scrollView.getValues();
57+
}
58+
});
3359

34-
var resize = angular.bind(scrollView, scrollView.resize);
35-
$window.addEventListener('resize', resize);
60+
$element.on('scroll', function(e) {
61+
var detail = (e.originalEvent || e).detail || {};
62+
$scope.$onScroll && $scope.$onScroll({
63+
event: e,
64+
scrollTop: detail.scrollTop || 0,
65+
scrollLeft: detail.scrollLeft || 0
66+
});
67+
});
3668

3769
$scope.$on('$viewContentLoaded', function(e, historyData) {
38-
if (e.defaultPrevented) {
39-
return;
40-
}
4170
//only the top-most scroll area under a view should remember that view's
4271
//scroll position
72+
if (e.defaultPrevented) { return; }
4373
e.preventDefault();
4474

45-
var values = historyData && historyData.rememberedScrollValues;
46-
if (values) {
47-
$timeout(function() {
48-
scrollView.scrollTo(+values.left || null, +values.top || null);
49-
}, 0, false);
50-
}
51-
$scope.$on('$destroy', function() {
52-
historyData && (historyData.rememberedScrollValues = scrollView.getValues());
75+
var viewId = historyData.viewId;
76+
77+
self.rememberScrollPosition(viewId);
78+
self.scrollToRememberedPosition();
79+
80+
backListenDone = $rootScope.$on('$viewHistory.viewBack', function(e, fromViewId, toViewId) {
81+
//When going back from this view, forget its saved scroll position
82+
if (viewId === fromViewId) {
83+
self.forgetScrollPosition();
84+
}
5385
});
5486
});
5587

56-
$scope.$on('$destroy', function() {
57-
$window.removeEventListener('resize', resize);
88+
$timeout(function() {
89+
scrollView.run();
5890
});
5991

60-
this.setRefresher = function(refresherScope, refresherElement) {
92+
this._rememberScrollId = null;
93+
this.rememberScrollPosition = function(id) {
94+
if (!id) {
95+
throw new Error("Must supply an id to remember the scroll by!");
96+
}
97+
this._rememberScrollId = id;
98+
};
99+
this.forgetScrollPosition = function() {
100+
delete $$scrollValueCache[this._rememberScrollId];
101+
this._rememberScrollId = null;
102+
};
103+
this.scrollToRememberedPosition = function(shouldAnimate) {
104+
var values = $$scrollValueCache[this._rememberScrollId];
105+
if (values) {
106+
scrollView.scrollTo(+values.left, +values.top, shouldAnimate);
107+
}
108+
};
109+
110+
this.resize = function() {
111+
return $timeout(resize);
112+
};
113+
this.scrollTop = function(shouldAnimate) {
114+
this.resize().then(function() {
115+
scrollView.scrollTo(0, 0, !!shouldAnimate);
116+
});
117+
};
118+
this.scrollBottom = function(shouldAnimate) {
119+
this.resize().then(function() {
120+
var max = scrollView.getScrollMax();
121+
scrollView.scrollTo(max.left, max.top, !!shouldAnimate);
122+
});
123+
};
124+
this.scrollTo = function(left, top, shouldAnimate) {
125+
this.resize().then(function() {
126+
scrollView.scrollTo(left, top, !!shouldAnimate);
127+
});
128+
};
129+
this.anchorScroll = function(shouldAnimate) {
130+
this.resize().then(function() {
131+
var hash = $location.hash();
132+
var elm = hash && $document[0].getElementById(hash);
133+
if (hash && elm) {
134+
var scroll = ionic.DomUtil.getPositionInParent(elm, self.$element);
135+
scrollView.scrollTo(scroll.left, scroll.top, !!shouldAnimate);
136+
} else {
137+
scrollView.scrollTo(0,0, !!shouldAnimate);
138+
}
139+
});
140+
};
141+
142+
143+
/**
144+
* @private
145+
*/
146+
this._setRefresher = function(refresherScope, refresherElement) {
61147
var refresher = this.refresher = refresherElement;
62148
var refresherHeight = self.refresher.clientHeight || 0;
63149
scrollView.activatePullToRefresh(refresherHeight, function() {
@@ -71,10 +157,6 @@ angular.module('ionic.ui.scroll')
71157
refresherScope.$onRefresh();
72158
});
73159
};
74-
75-
$timeout(function() {
76-
scrollView.run();
77-
});
78160
}]);
79161

80162
})();

js/ext/angular/src/directive/ionicBar.js

+27-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,36 @@
33

44
angular.module('ionic.ui.header', ['ngAnimate', 'ngSanitize'])
55

6-
.directive('barHeader', ['$ionicScrollDelegate', function($ionicScrollDelegate) {
6+
.directive('barHeader', ['$document', function($document) {
77
return {
88
restrict: 'C',
99
link: function($scope, $element, $attr) {
10-
$ionicScrollDelegate($scope).tapScrollToTop($element);
10+
ionic.requestAnimationFrame(function() {
11+
var scrollCtrl = $element.controller('$ionicScroll');
12+
if (!scrollCtrl) {
13+
return;
14+
}
15+
16+
ionic.on('tap', onTap, $element[0]);
17+
$scope.$on('$destroy', function() {
18+
ionic.off('tap', onTap, $element[0]);
19+
});
20+
21+
function onTap(e) {
22+
if (ionic.DomUtil.getParentOrSelfWithClass(e.target, 'button', 4)) {
23+
return;
24+
}
25+
var touch = e.gesture && e.gesture.touches[0] || e.detail.touches[0];
26+
var bounds = $element[0].getBoundingClientRect();
27+
if(ionic.DomUtil.rectContains(
28+
touch.pageX, touch.pageY,
29+
bounds.left, bounds.top - 20,
30+
bounds.left + bounds.width, bounds.top + bounds.height)
31+
) {
32+
scrollCtrl.scrollTop(true);
33+
}
34+
}
35+
});
1136
}
1237
};
1338
}])

js/ext/angular/src/directive/ionicContent.js

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
(function() {
22
'use strict';
33

4-
angular.module('ionic.ui.content', ['ionic.ui.service', 'ionic.ui.scroll'])
4+
angular.module('ionic.ui.content', ['ionic.ui.scroll'])
55

66
/**
77
* Panel is a simple 100% width and height, fixed panel. It's meant for content to be
@@ -28,6 +28,8 @@ angular.module('ionic.ui.content', ['ionic.ui.service', 'ionic.ui.scroll'])
2828
* @ngdoc directive
2929
* @name ionContent
3030
* @module ionic
31+
* @controller ionicScroll as $scope.$ionicScrollController
32+
* @restrict E
3133
*
3234
* @description
3335
* The ionContent directive provides an easy to use content area that can be configured
@@ -45,6 +47,9 @@ angular.module('ionic.ui.content', ['ionic.ui.service', 'ionic.ui.scroll'])
4547
* Use the classes 'has-header', 'has-subheader', 'has-footer', and 'has-tabs'
4648
* to modify the positioning of the ion-content relative to surrounding elements.
4749
*
50+
* @param {string=} controller-bind The scope variable to bind this element's scrollView's
51+
* {@link ionic.controller:ionicScroll ionicScroll controller} to.
52+
* Default: $scope.$ionicScrollController.
4853
* @param {boolean=} padding Whether to add padding to the content.
4954
* of the content. Defaults to true on iOS, false on Android.
5055
* @param {boolean=} scroll Whether to allow scrolling of content. Defaults to true.
@@ -67,6 +72,7 @@ function($parse, $timeout, $controller, $ionicBind) {
6772
transclude: true,
6873
require: '^?ionNavView',
6974
scope: true,
75+
priority: 501,
7076
template:
7177
'<div class="scroll-content">' +
7278
'<div class="scroll"></div>' +
@@ -97,9 +103,11 @@ function($parse, $timeout, $controller, $ionicBind) {
97103
scrollEventInterval: '@'
98104
});
99105

100-
$scope.$watch($attr.padding, function(newVal) {
101-
scrollContent.toggleClass('padding', !!newVal);
102-
});
106+
if (angular.isDefined($attr.padding)) {
107+
$scope.$watch($attr.padding, function(newVal) {
108+
scrollContent.toggleClass('padding', !!newVal);
109+
});
110+
}
103111

104112
if ($scope.scroll === "false") {
105113
//do nothing
@@ -111,6 +119,7 @@ function($parse, $timeout, $controller, $ionicBind) {
111119
$scope: $scope,
112120
scrollViewOptions: {
113121
el: $element[0],
122+
controllerBind: $attr.controllerBind,
114123
bouncing: $scope.$eval($scope.hasBouncing),
115124
startX: $scope.$eval($scope.startX) || 0,
116125
startY: $scope.$eval($scope.startY) || 0,
@@ -128,7 +137,7 @@ function($parse, $timeout, $controller, $ionicBind) {
128137
}
129138
});
130139
//Publish scrollView to parent so children can access it
131-
scrollView = $scope.$parent.scrollView = scrollCtrl.scrollView;
140+
scrollView = scrollCtrl.scrollView;
132141
}
133142

134143
transclude($scope, function(clone) {
@@ -227,7 +236,7 @@ function($parse, $timeout, $controller, $ionicBind) {
227236
$onPulling: '&onPulling'
228237
});
229238

230-
scrollCtrl.setRefresher($scope, $element[0]);
239+
scrollCtrl._setRefresher($scope, $element[0]);
231240
$scope.$on('scroll.refreshComplete', function() {
232241
$element[0].classList.remove('active');
233242
scrollCtrl.scrollView.finishPullToRefresh();

js/ext/angular/src/directive/ionicScroll.js

+5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@ angular.module('ionic.ui.scroll', [])
77
* @ngdoc directive
88
* @name ionScroll
99
* @module ionic
10+
* @controller ionicScroll as $scope.$ionicScrollController
1011
* @restrict E
1112
*
1213
* @description
1314
* Creates a scrollable container for all content inside.
1415
*
16+
* @param {string=} controller-bind The scope variable to bind this element's scrollView's
17+
* {@link ionic.controller:ionicScroll ionicScroll controller} to.
18+
* Default: $scope.$ionicScrollController.
1519
* @param {string=} direction Which way to scroll. 'x' or 'y'. Default 'y'.
1620
* @param {boolean=} paging Whether to scroll with paging.
1721
* @param {expression=} on-refresh Called on pull-to-refresh, triggered by an {@link ionic.directive:ionRefresher}.
@@ -61,6 +65,7 @@ angular.module('ionic.ui.scroll', [])
6165

6266
var scrollViewOptions= {
6367
el: $element[0],
68+
controllerBind: $attr.controllerBind,
6469
paging: isPaging,
6570
scrollbarX: $scope.$eval($scope.scrollbarX) !== false,
6671
scrollbarY: $scope.$eval($scope.scrollbarY) !== false,

js/ext/angular/src/directive/ionicSideMenu.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture', 'ionic.service.vie
9494
* ```js
9595
* function ContentController($scope) {
9696
* $scope.toggleLeft = function() {
97-
* $scope.sideMenuController.toggleLeft();
97+
* $scope.$ionicSideMenusController.toggleLeft();
9898
* };
9999
* }
100100
* ```

js/ext/angular/src/directive/ionicTabBar.js

+3
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ function($rootScope, $animate, $ionicBind, $compile, $ionicViewService) {
270270
tabsCtrl = ctrls[0],
271271
tabCtrl = ctrls[1];
272272

273+
//Remove title attribute so browser-tooltip does not apear
274+
$element[0].removeAttribute('title');
275+
273276
$ionicBind($scope, $attr, {
274277
animate: '=',
275278
onSelect: '&',

js/ext/angular/src/ionicAngular.js

-6
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ angular.module('ionic.service', [
2323
'ionic.decorator.location'
2424
]);
2525

26-
// UI specific services and delegates
27-
angular.module('ionic.ui.service', [
28-
'ionic.ui.service.scrollDelegate'
29-
]);
30-
3126
angular.module('ionic.ui', [
3227
'ionic.ui.checkbox',
3328
'ionic.ui.content',
@@ -47,7 +42,6 @@ angular.module('ionic.ui', [
4742

4843
angular.module('ionic', [
4944
'ionic.service',
50-
'ionic.ui.service',
5145
'ionic.ui',
5246

5347
// Angular deps

0 commit comments

Comments
 (0)