forked from ionic-team/ionic-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnavView.js
206 lines (184 loc) · 7.35 KB
/
navView.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/**
* @ngdoc directive
* @name ionNavView
* @module ionic
* @restrict E
* @codepen odqCz
*
* @description
* As a user navigates throughout your app, Ionic is able to keep track of their
* navigation history. By knowing their history, transitions between views
* correctly slide either left or right, or no transition at all. An additional
* benefit to Ionic's navigation system is its ability to manage multiple
* histories.
*
* Ionic uses the AngularUI Router module so app interfaces can be organized
* into various "states". Like Angular's core $route service, URLs can be used
* to control the views. However, the AngularUI Router provides a more powerful
* state manager in that states are bound to named, nested, and parallel views,
* allowing more than one template to be rendered on the same page.
* Additionally, each state is not required to be bound to a URL, and data can
* be pushed to each state which allows much flexibility.
*
* The ionNavView directive is used to render templates in your application. Each template
* is part of a state. States are usually mapped to a url, and are defined programatically
* using angular-ui-router (see [their docs](https://github.com/angular-ui/ui-router/wiki),
* and remember to replace ui-view with ion-nav-view in examples).
*
* @usage
* In this example, we will create a navigation view that contains our different states for the app.
*
* To do this, in our markup we use ionNavView top level directive. To display a header bar we use
* the {@link ionic.directive:ionNavBar} directive that updates as we navigate through the
* navigation stack.
*
* You can use any [animation class](/docs/components#animation) on the navView's `animation` attribute
* to have its pages animate.
*
* Recommended for page transitions: 'slide-left-right', 'slide-left-right-ios7', 'slide-in-up'.
*
* ```html
* <ion-nav-bar></ion-nav-bar>
* <ion-nav-view animation="slide-left-right">
* <!-- Center content -->
* </ion-nav-view>
* ```
*
* Next, we need to setup our states that will be rendered.
*
* ```js
* var app = angular.module('myApp', ['ionic']);
* app.config(function($stateProvider) {
* $stateProvider
* .state('index', {
* url: '/',
* templateUrl: 'home.html'
* })
* .state('music', {
* url: '/music',
* templateUrl: 'music.html'
* });
* });
* ```
* Then on app start, $stateProvider will look at the url, see it matches the index state,
* and then try to load home.html into the `<ion-nav-view>`.
*
* Pages are loaded by the URLs given. One simple way to create templates in Angular is to put
* them directly into your HTML file and use the `<script type="text/ng-template">` syntax.
* So here is one way to put home.html into our app:
*
* ```html
* <script id="home" type="text/ng-template">
* <!-- The title of the ion-view will be shown on the navbar -->
* <ion-view title="'Home'">
* <ion-content ng-controller="HomeCtrl">
* <!-- The content of the page -->
* <a href="#/music">Go to music page!</a>
* </ion-content>
* </ion-view>
* </script>
* ```
*
* This is good to do because the template will be cached for very fast loading, instead of
* having to fetch them from the network.
*
* Please visit [AngularUI Router's docs](https://github.com/angular-ui/ui-router/wiki) for
* more info. Below is a great video by the AngularUI Router guys that may help to explain
* how it all works:
*
* <iframe width="560" height="315" src="//www.youtube.com/embed/dqJRoh8MnBo"
* frameborder="0" allowfullscreen></iframe>
*
* @param {string=} name A view name. The name should be unique amongst the other views in the
* same state. You can have views of the same name that live in different states. For more
* information, see ui-router's [ui-view documentation](http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.directive:ui-view).
*/
IonicModule
.directive('ionNavView', [
'$ionicViewService',
'$state',
'$compile',
'$controller',
'$animate',
function( $ionicViewService, $state, $compile, $controller, $animate) {
// IONIC's fork of Angular UI Router, v0.2.7
// the navView handles registering views in the history, which animation to use, and which
var viewIsUpdating = false;
var directive = {
restrict: 'E',
terminal: true,
priority: 2000,
transclude: true,
controller: function(){},
compile: function (element, attr, transclude) {
return function(scope, element, attr, navViewCtrl) {
var viewScope, viewLocals,
name = attr[directive.name] || attr.name || '',
onloadExp = attr.onload || '',
initialView = transclude(scope);
// Put back the compiled initial view
element.append(initialView);
// Find the details of the parent view directive (if any) and use it
// to derive our own qualified view name, then hang our own details
// off the DOM so child directives can find it.
var parent = element.parent().inheritedData('$uiView');
if (name.indexOf('@') < 0) name = name + '@' + ((parent && parent.state) ? parent.state.name : '');
var view = { name: name, state: null };
element.data('$uiView', view);
var eventHook = function() {
if (viewIsUpdating) return;
viewIsUpdating = true;
try { updateView(true); } catch (e) {
viewIsUpdating = false;
throw e;
}
viewIsUpdating = false;
};
scope.$on('$stateChangeSuccess', eventHook);
// scope.$on('$viewContentLoading', eventHook);
updateView(false);
function updateView(doAnimate) {
//===false because $animate.enabled() is a noop without angular-animate included
if ($animate.enabled() === false) {
doAnimate = false;
}
var locals = $state.$current && $state.$current.locals[name];
if (locals === viewLocals) return; // nothing to do
var renderer = $ionicViewService.getRenderer(element, attr, scope);
// Destroy previous view scope
if (viewScope) {
viewScope.$destroy();
viewScope = null;
}
if (!locals) {
viewLocals = null;
view.state = null;
// Restore the initial view
return element.append(initialView);
}
var newElement = jqLite('<div></div>').html(locals.$template).contents();
var viewRegisterData = renderer().register(newElement);
// Remove existing content
renderer(doAnimate).leave();
viewLocals = locals;
view.state = locals.$$state;
renderer(doAnimate).enter(newElement);
var link = $compile(newElement);
viewScope = scope.$new();
viewScope.$navDirection = viewRegisterData.navDirection;
if (locals.$$controller) {
locals.$scope = viewScope;
var controller = $controller(locals.$$controller, locals);
element.children().data('$ngControllerController', controller);
}
link(viewScope);
var viewHistoryData = $ionicViewService._getViewById(viewRegisterData.viewId) || {};
viewScope.$broadcast('$viewContentLoaded', viewHistoryData);
if (onloadExp) viewScope.$eval(onloadExp);
newElement = null;
}
};
}
};
return directive;
}]);