angularjs-rails 1.5.8 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +6 -1
- data/lib/angularjs-rails/engine.rb +1 -1
- data/lib/angularjs-rails/version.rb +1 -1
- data/vendor/assets/javascripts/angular-animate.js +426 -293
- data/vendor/assets/javascripts/angular-aria.js +64 -43
- data/vendor/assets/javascripts/angular-cookies.js +24 -93
- data/vendor/assets/javascripts/angular-loader.js +190 -36
- data/vendor/assets/javascripts/angular-message-format.js +72 -84
- data/vendor/assets/javascripts/angular-messages.js +158 -68
- data/vendor/assets/javascripts/angular-mocks.js +1033 -402
- data/vendor/assets/javascripts/angular-parse-ext.js +14 -10
- data/vendor/assets/javascripts/angular-resource.js +317 -269
- data/vendor/assets/javascripts/angular-route.js +329 -132
- data/vendor/assets/javascripts/angular-sanitize.js +268 -93
- data/vendor/assets/javascripts/angular-touch.js +46 -413
- data/vendor/assets/javascripts/angular.js +9213 -4485
- metadata +2 -3
- data/vendor/assets/javascripts/angular-scenario.js +0 -44134
@@ -1,6 +1,6 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.
|
3
|
-
* (c) 2010-
|
2
|
+
* @license AngularJS v1.8.0
|
3
|
+
* (c) 2010-2020 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
6
6
|
(function(window, angular) {'use strict';
|
@@ -32,43 +32,96 @@ function shallowCopy(src, dst) {
|
|
32
32
|
return dst || src;
|
33
33
|
}
|
34
34
|
|
35
|
+
/* global routeToRegExp: true */
|
36
|
+
|
37
|
+
/**
|
38
|
+
* @param {string} path - The path to parse. (It is assumed to have query and hash stripped off.)
|
39
|
+
* @param {Object} opts - Options.
|
40
|
+
* @return {Object} - An object containing an array of path parameter names (`keys`) and a regular
|
41
|
+
* expression (`regexp`) that can be used to identify a matching URL and extract the path
|
42
|
+
* parameter values.
|
43
|
+
*
|
44
|
+
* @description
|
45
|
+
* Parses the given path, extracting path parameter names and a regular expression to match URLs.
|
46
|
+
*
|
47
|
+
* Originally inspired by `pathRexp` in `visionmedia/express/lib/utils.js`.
|
48
|
+
*/
|
49
|
+
function routeToRegExp(path, opts) {
|
50
|
+
var keys = [];
|
51
|
+
|
52
|
+
var pattern = path
|
53
|
+
.replace(/([().])/g, '\\$1')
|
54
|
+
.replace(/(\/)?:(\w+)(\*\?|[?*])?/g, function(_, slash, key, option) {
|
55
|
+
var optional = option === '?' || option === '*?';
|
56
|
+
var star = option === '*' || option === '*?';
|
57
|
+
keys.push({name: key, optional: optional});
|
58
|
+
slash = slash || '';
|
59
|
+
return (
|
60
|
+
(optional ? '(?:' + slash : slash + '(?:') +
|
61
|
+
(star ? '(.+?)' : '([^/]+)') +
|
62
|
+
(optional ? '?)?' : ')')
|
63
|
+
);
|
64
|
+
})
|
65
|
+
.replace(/([/$*])/g, '\\$1');
|
66
|
+
|
67
|
+
if (opts.ignoreTrailingSlashes) {
|
68
|
+
pattern = pattern.replace(/\/+$/, '') + '/*';
|
69
|
+
}
|
70
|
+
|
71
|
+
return {
|
72
|
+
keys: keys,
|
73
|
+
regexp: new RegExp(
|
74
|
+
'^' + pattern + '(?:[?#]|$)',
|
75
|
+
opts.caseInsensitiveMatch ? 'i' : ''
|
76
|
+
)
|
77
|
+
};
|
78
|
+
}
|
79
|
+
|
80
|
+
/* global routeToRegExp: false */
|
35
81
|
/* global shallowCopy: false */
|
36
82
|
|
37
|
-
//
|
83
|
+
// `isArray` and `isObject` are necessary for `shallowCopy()` (included via `src/shallowCopy.js`).
|
38
84
|
// They are initialized inside the `$RouteProvider`, to ensure `window.angular` is available.
|
39
85
|
var isArray;
|
40
86
|
var isObject;
|
87
|
+
var isDefined;
|
88
|
+
var noop;
|
41
89
|
|
42
90
|
/**
|
43
91
|
* @ngdoc module
|
44
92
|
* @name ngRoute
|
45
93
|
* @description
|
46
94
|
*
|
47
|
-
*
|
48
|
-
*
|
49
|
-
* The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
|
95
|
+
* The `ngRoute` module provides routing and deeplinking services and directives for AngularJS apps.
|
50
96
|
*
|
51
97
|
* ## Example
|
52
|
-
* See {@link ngRoute.$route#
|
98
|
+
* See {@link ngRoute.$route#examples $route} for an example of configuring and using `ngRoute`.
|
53
99
|
*
|
54
|
-
*
|
55
|
-
* <div doc-module-components="ngRoute"></div>
|
56
100
|
*/
|
57
|
-
|
58
|
-
var ngRouteModule = angular.
|
59
|
-
|
60
|
-
|
101
|
+
/* global -ngRouteModule */
|
102
|
+
var ngRouteModule = angular.
|
103
|
+
module('ngRoute', []).
|
104
|
+
info({ angularVersion: '1.8.0' }).
|
105
|
+
provider('$route', $RouteProvider).
|
106
|
+
// Ensure `$route` will be instantiated in time to capture the initial `$locationChangeSuccess`
|
107
|
+
// event (unless explicitly disabled). This is necessary in case `ngView` is included in an
|
108
|
+
// asynchronously loaded template.
|
109
|
+
run(instantiateRoute);
|
110
|
+
var $routeMinErr = angular.$$minErr('ngRoute');
|
111
|
+
var isEagerInstantiationEnabled;
|
112
|
+
|
61
113
|
|
62
114
|
/**
|
63
115
|
* @ngdoc provider
|
64
116
|
* @name $routeProvider
|
117
|
+
* @this
|
65
118
|
*
|
66
119
|
* @description
|
67
120
|
*
|
68
121
|
* Used for configuring routes.
|
69
122
|
*
|
70
123
|
* ## Example
|
71
|
-
* See {@link ngRoute.$route#
|
124
|
+
* See {@link ngRoute.$route#examples $route} for an example of configuring and using `ngRoute`.
|
72
125
|
*
|
73
126
|
* ## Dependencies
|
74
127
|
* Requires the {@link ngRoute `ngRoute`} module to be installed.
|
@@ -76,6 +129,8 @@ var ngRouteModule = angular.module('ngRoute', ['ng']).
|
|
76
129
|
function $RouteProvider() {
|
77
130
|
isArray = angular.isArray;
|
78
131
|
isObject = angular.isObject;
|
132
|
+
isDefined = angular.isDefined;
|
133
|
+
noop = angular.noop;
|
79
134
|
|
80
135
|
function inherit(parent, extra) {
|
81
136
|
return angular.extend(Object.create(parent), extra);
|
@@ -112,12 +167,12 @@ function $RouteProvider() {
|
|
112
167
|
*
|
113
168
|
* Object properties:
|
114
169
|
*
|
115
|
-
* - `controller` – `{(string|
|
170
|
+
* - `controller` – `{(string|Function)=}` – Controller fn that should be associated with
|
116
171
|
* newly created scope or the name of a {@link angular.Module#controller registered
|
117
172
|
* controller} if passed as a string.
|
118
173
|
* - `controllerAs` – `{string=}` – An identifier name for a reference to the controller.
|
119
174
|
* If present, the controller will be published to scope under the `controllerAs` name.
|
120
|
-
* - `template` – `{string
|
175
|
+
* - `template` – `{(string|Function)=}` – html template as a string or a function that
|
121
176
|
* returns an html template as a string which should be used by {@link
|
122
177
|
* ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
|
123
178
|
* This property takes precedence over `templateUrl`.
|
@@ -127,7 +182,9 @@ function $RouteProvider() {
|
|
127
182
|
* - `{Array.<Object>}` - route parameters extracted from the current
|
128
183
|
* `$location.path()` by applying the current route
|
129
184
|
*
|
130
|
-
*
|
185
|
+
* One of `template` or `templateUrl` is required.
|
186
|
+
*
|
187
|
+
* - `templateUrl` – `{(string|Function)=}` – path or function that returns a path to an html
|
131
188
|
* template that should be used by {@link ngRoute.directive:ngView ngView}.
|
132
189
|
*
|
133
190
|
* If `templateUrl` is a function, it will be called with the following parameters:
|
@@ -135,7 +192,9 @@ function $RouteProvider() {
|
|
135
192
|
* - `{Array.<Object>}` - route parameters extracted from the current
|
136
193
|
* `$location.path()` by applying the current route
|
137
194
|
*
|
138
|
-
*
|
195
|
+
* One of `templateUrl` or `template` is required.
|
196
|
+
*
|
197
|
+
* - `resolve` - `{Object.<string, Function>=}` - An optional map of dependencies which should
|
139
198
|
* be injected into the controller. If any of these dependencies are promises, the router
|
140
199
|
* will wait for them all to be resolved or one to be rejected before the controller is
|
141
200
|
* instantiated.
|
@@ -155,7 +214,7 @@ function $RouteProvider() {
|
|
155
214
|
* The map object is:
|
156
215
|
*
|
157
216
|
* - `key` – `{string}`: a name of a dependency to be injected into the controller.
|
158
|
-
* - `factory` - `{string|
|
217
|
+
* - `factory` - `{string|Function}`: If `string` then it is an alias for a service.
|
159
218
|
* Otherwise if function, then it is {@link auto.$injector#invoke injected}
|
160
219
|
* and the return value is treated as the dependency. If the result is a promise, it is
|
161
220
|
* resolved before its value is injected into the controller. Be aware that
|
@@ -165,7 +224,7 @@ function $RouteProvider() {
|
|
165
224
|
* - `resolveAs` - `{string=}` - The name under which the `resolve` map will be available on
|
166
225
|
* the scope of the route. If omitted, defaults to `$resolve`.
|
167
226
|
*
|
168
|
-
* - `redirectTo` – `{(string|
|
227
|
+
* - `redirectTo` – `{(string|Function)=}` – value to update
|
169
228
|
* {@link ng.$location $location} path with and trigger route redirection.
|
170
229
|
*
|
171
230
|
* If `redirectTo` is a function, it will be called with the following parameters:
|
@@ -176,13 +235,48 @@ function $RouteProvider() {
|
|
176
235
|
* - `{Object}` - current `$location.search()`
|
177
236
|
*
|
178
237
|
* The custom `redirectTo` function is expected to return a string which will be used
|
179
|
-
* to update `$location.
|
238
|
+
* to update `$location.url()`. If the function throws an error, no further processing will
|
239
|
+
* take place and the {@link ngRoute.$route#$routeChangeError $routeChangeError} event will
|
240
|
+
* be fired.
|
241
|
+
*
|
242
|
+
* Routes that specify `redirectTo` will not have their controllers, template functions
|
243
|
+
* or resolves called, the `$location` will be changed to the redirect url and route
|
244
|
+
* processing will stop. The exception to this is if the `redirectTo` is a function that
|
245
|
+
* returns `undefined`. In this case the route transition occurs as though there was no
|
246
|
+
* redirection.
|
247
|
+
*
|
248
|
+
* - `resolveRedirectTo` – `{Function=}` – a function that will (eventually) return the value
|
249
|
+
* to update {@link ng.$location $location} URL with and trigger route redirection. In
|
250
|
+
* contrast to `redirectTo`, dependencies can be injected into `resolveRedirectTo` and the
|
251
|
+
* return value can be either a string or a promise that will be resolved to a string.
|
252
|
+
*
|
253
|
+
* Similar to `redirectTo`, if the return value is `undefined` (or a promise that gets
|
254
|
+
* resolved to `undefined`), no redirection takes place and the route transition occurs as
|
255
|
+
* though there was no redirection.
|
256
|
+
*
|
257
|
+
* If the function throws an error or the returned promise gets rejected, no further
|
258
|
+
* processing will take place and the
|
259
|
+
* {@link ngRoute.$route#$routeChangeError $routeChangeError} event will be fired.
|
260
|
+
*
|
261
|
+
* `redirectTo` takes precedence over `resolveRedirectTo`, so specifying both on the same
|
262
|
+
* route definition, will cause the latter to be ignored.
|
263
|
+
*
|
264
|
+
* - `[reloadOnUrl=true]` - `{boolean=}` - reload route when any part of the URL changes
|
265
|
+
* (including the path) even if the new URL maps to the same route.
|
266
|
+
*
|
267
|
+
* If the option is set to `false` and the URL in the browser changes, but the new URL maps
|
268
|
+
* to the same route, then a `$routeUpdate` event is broadcasted on the root scope (without
|
269
|
+
* reloading the route).
|
180
270
|
*
|
181
271
|
* - `[reloadOnSearch=true]` - `{boolean=}` - reload route when only `$location.search()`
|
182
272
|
* or `$location.hash()` changes.
|
183
273
|
*
|
184
|
-
* If the option is set to `false` and
|
185
|
-
*
|
274
|
+
* If the option is set to `false` and the URL in the browser changes, then a `$routeUpdate`
|
275
|
+
* event is broadcasted on the root scope (without reloading the route).
|
276
|
+
*
|
277
|
+
* <div class="alert alert-warning">
|
278
|
+
* **Note:** This option has no effect if `reloadOnUrl` is set to `false`.
|
279
|
+
* </div>
|
186
280
|
*
|
187
281
|
* - `[caseInsensitiveMatch=false]` - `{boolean=}` - match routes without being case sensitive
|
188
282
|
*
|
@@ -197,6 +291,9 @@ function $RouteProvider() {
|
|
197
291
|
this.when = function(path, route) {
|
198
292
|
//copy original route object to preserve params inherited from proto chain
|
199
293
|
var routeCopy = shallowCopy(route);
|
294
|
+
if (angular.isUndefined(routeCopy.reloadOnUrl)) {
|
295
|
+
routeCopy.reloadOnUrl = true;
|
296
|
+
}
|
200
297
|
if (angular.isUndefined(routeCopy.reloadOnSearch)) {
|
201
298
|
routeCopy.reloadOnSearch = true;
|
202
299
|
}
|
@@ -205,18 +302,19 @@ function $RouteProvider() {
|
|
205
302
|
}
|
206
303
|
routes[path] = angular.extend(
|
207
304
|
routeCopy,
|
208
|
-
|
305
|
+
{originalPath: path},
|
306
|
+
path && routeToRegExp(path, routeCopy)
|
209
307
|
);
|
210
308
|
|
211
309
|
// create redirection for trailing slashes
|
212
310
|
if (path) {
|
213
|
-
var redirectPath = (path[path.length - 1]
|
311
|
+
var redirectPath = (path[path.length - 1] === '/')
|
214
312
|
? path.substr(0, path.length - 1)
|
215
313
|
: path + '/';
|
216
314
|
|
217
315
|
routes[redirectPath] = angular.extend(
|
218
|
-
{redirectTo: path},
|
219
|
-
|
316
|
+
{originalPath: path, redirectTo: path},
|
317
|
+
routeToRegExp(redirectPath, routeCopy)
|
220
318
|
);
|
221
319
|
}
|
222
320
|
|
@@ -234,47 +332,6 @@ function $RouteProvider() {
|
|
234
332
|
*/
|
235
333
|
this.caseInsensitiveMatch = false;
|
236
334
|
|
237
|
-
/**
|
238
|
-
* @param path {string} path
|
239
|
-
* @param opts {Object} options
|
240
|
-
* @return {?Object}
|
241
|
-
*
|
242
|
-
* @description
|
243
|
-
* Normalizes the given path, returning a regular expression
|
244
|
-
* and the original path.
|
245
|
-
*
|
246
|
-
* Inspired by pathRexp in visionmedia/express/lib/utils.js.
|
247
|
-
*/
|
248
|
-
function pathRegExp(path, opts) {
|
249
|
-
var insensitive = opts.caseInsensitiveMatch,
|
250
|
-
ret = {
|
251
|
-
originalPath: path,
|
252
|
-
regexp: path
|
253
|
-
},
|
254
|
-
keys = ret.keys = [];
|
255
|
-
|
256
|
-
path = path
|
257
|
-
.replace(/([().])/g, '\\$1')
|
258
|
-
.replace(/(\/)?:(\w+)(\*\?|[\?\*])?/g, function(_, slash, key, option) {
|
259
|
-
var optional = (option === '?' || option === '*?') ? '?' : null;
|
260
|
-
var star = (option === '*' || option === '*?') ? '*' : null;
|
261
|
-
keys.push({ name: key, optional: !!optional });
|
262
|
-
slash = slash || '';
|
263
|
-
return ''
|
264
|
-
+ (optional ? '' : slash)
|
265
|
-
+ '(?:'
|
266
|
-
+ (optional ? slash : '')
|
267
|
-
+ (star && '(.+?)' || '([^/]+)')
|
268
|
-
+ (optional || '')
|
269
|
-
+ ')'
|
270
|
-
+ (optional || '');
|
271
|
-
})
|
272
|
-
.replace(/([\/$\*])/g, '\\$1');
|
273
|
-
|
274
|
-
ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
|
275
|
-
return ret;
|
276
|
-
}
|
277
|
-
|
278
335
|
/**
|
279
336
|
* @ngdoc method
|
280
337
|
* @name $routeProvider#otherwise
|
@@ -295,6 +352,47 @@ function $RouteProvider() {
|
|
295
352
|
return this;
|
296
353
|
};
|
297
354
|
|
355
|
+
/**
|
356
|
+
* @ngdoc method
|
357
|
+
* @name $routeProvider#eagerInstantiationEnabled
|
358
|
+
* @kind function
|
359
|
+
*
|
360
|
+
* @description
|
361
|
+
* Call this method as a setter to enable/disable eager instantiation of the
|
362
|
+
* {@link ngRoute.$route $route} service upon application bootstrap. You can also call it as a
|
363
|
+
* getter (i.e. without any arguments) to get the current value of the
|
364
|
+
* `eagerInstantiationEnabled` flag.
|
365
|
+
*
|
366
|
+
* Instantiating `$route` early is necessary for capturing the initial
|
367
|
+
* {@link ng.$location#$locationChangeStart $locationChangeStart} event and navigating to the
|
368
|
+
* appropriate route. Usually, `$route` is instantiated in time by the
|
369
|
+
* {@link ngRoute.ngView ngView} directive. Yet, in cases where `ngView` is included in an
|
370
|
+
* asynchronously loaded template (e.g. in another directive's template), the directive factory
|
371
|
+
* might not be called soon enough for `$route` to be instantiated _before_ the initial
|
372
|
+
* `$locationChangeSuccess` event is fired. Eager instantiation ensures that `$route` is always
|
373
|
+
* instantiated in time, regardless of when `ngView` will be loaded.
|
374
|
+
*
|
375
|
+
* The default value is true.
|
376
|
+
*
|
377
|
+
* **Note**:<br />
|
378
|
+
* You may want to disable the default behavior when unit-testing modules that depend on
|
379
|
+
* `ngRoute`, in order to avoid an unexpected request for the default route's template.
|
380
|
+
*
|
381
|
+
* @param {boolean=} enabled - If provided, update the internal `eagerInstantiationEnabled` flag.
|
382
|
+
*
|
383
|
+
* @returns {*} The current value of the `eagerInstantiationEnabled` flag if used as a getter or
|
384
|
+
* itself (for chaining) if used as a setter.
|
385
|
+
*/
|
386
|
+
isEagerInstantiationEnabled = true;
|
387
|
+
this.eagerInstantiationEnabled = function eagerInstantiationEnabled(enabled) {
|
388
|
+
if (isDefined(enabled)) {
|
389
|
+
isEagerInstantiationEnabled = enabled;
|
390
|
+
return this;
|
391
|
+
}
|
392
|
+
|
393
|
+
return isEagerInstantiationEnabled;
|
394
|
+
};
|
395
|
+
|
298
396
|
|
299
397
|
this.$get = ['$rootScope',
|
300
398
|
'$location',
|
@@ -303,7 +401,8 @@ function $RouteProvider() {
|
|
303
401
|
'$injector',
|
304
402
|
'$templateRequest',
|
305
403
|
'$sce',
|
306
|
-
|
404
|
+
'$browser',
|
405
|
+
function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce, $browser) {
|
307
406
|
|
308
407
|
/**
|
309
408
|
* @ngdoc service
|
@@ -388,12 +487,12 @@ function $RouteProvider() {
|
|
388
487
|
* })
|
389
488
|
*
|
390
489
|
* .controller('BookController', function($scope, $routeParams) {
|
391
|
-
* $scope.name =
|
490
|
+
* $scope.name = 'BookController';
|
392
491
|
* $scope.params = $routeParams;
|
393
492
|
* })
|
394
493
|
*
|
395
494
|
* .controller('ChapterController', function($scope, $routeParams) {
|
396
|
-
* $scope.name =
|
495
|
+
* $scope.name = 'ChapterController';
|
397
496
|
* $scope.params = $routeParams;
|
398
497
|
* })
|
399
498
|
*
|
@@ -426,15 +525,15 @@ function $RouteProvider() {
|
|
426
525
|
* it('should load and compile correct template', function() {
|
427
526
|
* element(by.linkText('Moby: Ch1')).click();
|
428
527
|
* var content = element(by.css('[ng-view]')).getText();
|
429
|
-
* expect(content).toMatch(/controller
|
430
|
-
* expect(content).toMatch(/Book Id
|
431
|
-
* expect(content).toMatch(/Chapter Id
|
528
|
+
* expect(content).toMatch(/controller: ChapterController/);
|
529
|
+
* expect(content).toMatch(/Book Id: Moby/);
|
530
|
+
* expect(content).toMatch(/Chapter Id: 1/);
|
432
531
|
*
|
433
532
|
* element(by.partialLinkText('Scarlet')).click();
|
434
533
|
*
|
435
534
|
* content = element(by.css('[ng-view]')).getText();
|
436
|
-
* expect(content).toMatch(/controller
|
437
|
-
* expect(content).toMatch(/Book Id
|
535
|
+
* expect(content).toMatch(/controller: BookController/);
|
536
|
+
* expect(content).toMatch(/Book Id: Scarlet/);
|
438
537
|
* });
|
439
538
|
* </file>
|
440
539
|
* </example>
|
@@ -482,12 +581,14 @@ function $RouteProvider() {
|
|
482
581
|
* @name $route#$routeChangeError
|
483
582
|
* @eventType broadcast on root scope
|
484
583
|
* @description
|
485
|
-
* Broadcasted if any
|
584
|
+
* Broadcasted if a redirection function fails or any redirection or resolve promises are
|
585
|
+
* rejected.
|
486
586
|
*
|
487
587
|
* @param {Object} angularEvent Synthetic event object
|
488
588
|
* @param {Route} current Current route information.
|
489
589
|
* @param {Route} previous Previous route information.
|
490
|
-
* @param {Route} rejection
|
590
|
+
* @param {Route} rejection The thrown error or the rejection reason of the promise. Usually
|
591
|
+
* the rejection reason is the error that caused the promise to get rejected.
|
491
592
|
*/
|
492
593
|
|
493
594
|
/**
|
@@ -495,8 +596,9 @@ function $RouteProvider() {
|
|
495
596
|
* @name $route#$routeUpdate
|
496
597
|
* @eventType broadcast on root scope
|
497
598
|
* @description
|
498
|
-
*
|
499
|
-
*
|
599
|
+
* Broadcasted if the same instance of a route (including template, controller instance,
|
600
|
+
* resolved dependencies, etc.) is being reused. This can happen if either `reloadOnSearch` or
|
601
|
+
* `reloadOnUrl` has been set to `false`.
|
500
602
|
*
|
501
603
|
* @param {Object} angularEvent Synthetic event object
|
502
604
|
* @param {Route} current Current/previous route information.
|
@@ -556,7 +658,7 @@ function $RouteProvider() {
|
|
556
658
|
// interpolate modifies newParams, only query params are left
|
557
659
|
$location.search(newParams);
|
558
660
|
} else {
|
559
|
-
throw $routeMinErr('norout', 'Tried updating route
|
661
|
+
throw $routeMinErr('norout', 'Tried updating route with no current route');
|
560
662
|
}
|
561
663
|
}
|
562
664
|
};
|
@@ -604,9 +706,7 @@ function $RouteProvider() {
|
|
604
706
|
var lastRoute = $route.current;
|
605
707
|
|
606
708
|
preparedRoute = parseRoute();
|
607
|
-
preparedRouteIsUpdateOnly = preparedRoute
|
608
|
-
&& angular.equals(preparedRoute.pathParams, lastRoute.pathParams)
|
609
|
-
&& !preparedRoute.reloadOnSearch && !forceReload;
|
709
|
+
preparedRouteIsUpdateOnly = isNavigationUpdateOnly(preparedRoute, lastRoute);
|
610
710
|
|
611
711
|
if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {
|
612
712
|
if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {
|
@@ -628,37 +728,112 @@ function $RouteProvider() {
|
|
628
728
|
} else if (nextRoute || lastRoute) {
|
629
729
|
forceReload = false;
|
630
730
|
$route.current = nextRoute;
|
631
|
-
if (nextRoute) {
|
632
|
-
if (nextRoute.redirectTo) {
|
633
|
-
if (angular.isString(nextRoute.redirectTo)) {
|
634
|
-
$location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)
|
635
|
-
.replace();
|
636
|
-
} else {
|
637
|
-
$location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))
|
638
|
-
.replace();
|
639
|
-
}
|
640
|
-
}
|
641
|
-
}
|
642
731
|
|
643
|
-
$q.
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
732
|
+
var nextRoutePromise = $q.resolve(nextRoute);
|
733
|
+
|
734
|
+
$browser.$$incOutstandingRequestCount('$route');
|
735
|
+
|
736
|
+
nextRoutePromise.
|
737
|
+
then(getRedirectionData).
|
738
|
+
then(handlePossibleRedirection).
|
739
|
+
then(function(keepProcessingRoute) {
|
740
|
+
return keepProcessingRoute && nextRoutePromise.
|
741
|
+
then(resolveLocals).
|
742
|
+
then(function(locals) {
|
743
|
+
// after route change
|
744
|
+
if (nextRoute === $route.current) {
|
745
|
+
if (nextRoute) {
|
746
|
+
nextRoute.locals = locals;
|
747
|
+
angular.copy(nextRoute.params, $routeParams);
|
748
|
+
}
|
749
|
+
$rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);
|
750
|
+
}
|
751
|
+
});
|
752
|
+
}).catch(function(error) {
|
753
|
+
if (nextRoute === $route.current) {
|
656
754
|
$rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);
|
657
755
|
}
|
756
|
+
}).finally(function() {
|
757
|
+
// Because `commitRoute()` is called from a `$rootScope.$evalAsync` block (see
|
758
|
+
// `$locationWatch`), this `$$completeOutstandingRequest()` call will not cause
|
759
|
+
// `outstandingRequestCount` to hit zero. This is important in case we are redirecting
|
760
|
+
// to a new route which also requires some asynchronous work.
|
761
|
+
|
762
|
+
$browser.$$completeOutstandingRequest(noop, '$route');
|
658
763
|
});
|
659
764
|
}
|
660
765
|
}
|
661
766
|
|
767
|
+
function getRedirectionData(route) {
|
768
|
+
var data = {
|
769
|
+
route: route,
|
770
|
+
hasRedirection: false
|
771
|
+
};
|
772
|
+
|
773
|
+
if (route) {
|
774
|
+
if (route.redirectTo) {
|
775
|
+
if (angular.isString(route.redirectTo)) {
|
776
|
+
data.path = interpolate(route.redirectTo, route.params);
|
777
|
+
data.search = route.params;
|
778
|
+
data.hasRedirection = true;
|
779
|
+
} else {
|
780
|
+
var oldPath = $location.path();
|
781
|
+
var oldSearch = $location.search();
|
782
|
+
var newUrl = route.redirectTo(route.pathParams, oldPath, oldSearch);
|
783
|
+
|
784
|
+
if (angular.isDefined(newUrl)) {
|
785
|
+
data.url = newUrl;
|
786
|
+
data.hasRedirection = true;
|
787
|
+
}
|
788
|
+
}
|
789
|
+
} else if (route.resolveRedirectTo) {
|
790
|
+
return $q.
|
791
|
+
resolve($injector.invoke(route.resolveRedirectTo)).
|
792
|
+
then(function(newUrl) {
|
793
|
+
if (angular.isDefined(newUrl)) {
|
794
|
+
data.url = newUrl;
|
795
|
+
data.hasRedirection = true;
|
796
|
+
}
|
797
|
+
|
798
|
+
return data;
|
799
|
+
});
|
800
|
+
}
|
801
|
+
}
|
802
|
+
|
803
|
+
return data;
|
804
|
+
}
|
805
|
+
|
806
|
+
function handlePossibleRedirection(data) {
|
807
|
+
var keepProcessingRoute = true;
|
808
|
+
|
809
|
+
if (data.route !== $route.current) {
|
810
|
+
keepProcessingRoute = false;
|
811
|
+
} else if (data.hasRedirection) {
|
812
|
+
var oldUrl = $location.url();
|
813
|
+
var newUrl = data.url;
|
814
|
+
|
815
|
+
if (newUrl) {
|
816
|
+
$location.
|
817
|
+
url(newUrl).
|
818
|
+
replace();
|
819
|
+
} else {
|
820
|
+
newUrl = $location.
|
821
|
+
path(data.path).
|
822
|
+
search(data.search).
|
823
|
+
replace().
|
824
|
+
url();
|
825
|
+
}
|
826
|
+
|
827
|
+
if (newUrl !== oldUrl) {
|
828
|
+
// Exit out and don't process current next value,
|
829
|
+
// wait for next location change from redirect
|
830
|
+
keepProcessingRoute = false;
|
831
|
+
}
|
832
|
+
}
|
833
|
+
|
834
|
+
return keepProcessingRoute;
|
835
|
+
}
|
836
|
+
|
662
837
|
function resolveLocals(route) {
|
663
838
|
if (route) {
|
664
839
|
var locals = angular.extend({}, route.resolve);
|
@@ -675,7 +850,6 @@ function $RouteProvider() {
|
|
675
850
|
}
|
676
851
|
}
|
677
852
|
|
678
|
-
|
679
853
|
function getTemplateFor(route) {
|
680
854
|
var template, templateUrl;
|
681
855
|
if (angular.isDefined(template = route.template)) {
|
@@ -694,7 +868,6 @@ function $RouteProvider() {
|
|
694
868
|
return template;
|
695
869
|
}
|
696
870
|
|
697
|
-
|
698
871
|
/**
|
699
872
|
* @returns {Object} the current active route, by matching it against the URL
|
700
873
|
*/
|
@@ -713,6 +886,29 @@ function $RouteProvider() {
|
|
713
886
|
return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
|
714
887
|
}
|
715
888
|
|
889
|
+
/**
|
890
|
+
* @param {Object} newRoute - The new route configuration (as returned by `parseRoute()`).
|
891
|
+
* @param {Object} oldRoute - The previous route configuration (as returned by `parseRoute()`).
|
892
|
+
* @returns {boolean} Whether this is an "update-only" navigation, i.e. the URL maps to the same
|
893
|
+
* route and it can be reused (based on the config and the type of change).
|
894
|
+
*/
|
895
|
+
function isNavigationUpdateOnly(newRoute, oldRoute) {
|
896
|
+
// IF this is not a forced reload
|
897
|
+
return !forceReload
|
898
|
+
// AND both `newRoute`/`oldRoute` are defined
|
899
|
+
&& newRoute && oldRoute
|
900
|
+
// AND they map to the same Route Definition Object
|
901
|
+
&& (newRoute.$$route === oldRoute.$$route)
|
902
|
+
// AND `reloadOnUrl` is disabled
|
903
|
+
&& (!newRoute.reloadOnUrl
|
904
|
+
// OR `reloadOnSearch` is disabled
|
905
|
+
|| (!newRoute.reloadOnSearch
|
906
|
+
// AND both routes have the same path params
|
907
|
+
&& angular.equals(newRoute.pathParams, oldRoute.pathParams)
|
908
|
+
)
|
909
|
+
);
|
910
|
+
}
|
911
|
+
|
716
912
|
/**
|
717
913
|
* @returns {string} interpolation of the redirect path with the parameters
|
718
914
|
*/
|
@@ -734,6 +930,14 @@ function $RouteProvider() {
|
|
734
930
|
}];
|
735
931
|
}
|
736
932
|
|
933
|
+
instantiateRoute.$inject = ['$injector'];
|
934
|
+
function instantiateRoute($injector) {
|
935
|
+
if (isEagerInstantiationEnabled) {
|
936
|
+
// Instantiate `$route`
|
937
|
+
$injector.get('$route');
|
938
|
+
}
|
939
|
+
}
|
940
|
+
|
737
941
|
ngRouteModule.provider('$routeParams', $RouteParamsProvider);
|
738
942
|
|
739
943
|
|
@@ -741,6 +945,7 @@ ngRouteModule.provider('$routeParams', $RouteParamsProvider);
|
|
741
945
|
* @ngdoc service
|
742
946
|
* @name $routeParams
|
743
947
|
* @requires $route
|
948
|
+
* @this
|
744
949
|
*
|
745
950
|
* @description
|
746
951
|
* The `$routeParams` service allows you to retrieve the current set of route parameters.
|
@@ -784,7 +989,6 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
|
784
989
|
* @restrict ECA
|
785
990
|
*
|
786
991
|
* @description
|
787
|
-
* # Overview
|
788
992
|
* `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
|
789
993
|
* including the rendered template of the current route into the main layout (`index.html`) file.
|
790
994
|
* Every time the current route changes, the included view changes with it according to the
|
@@ -800,13 +1004,6 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
|
800
1004
|
*
|
801
1005
|
* The enter and leave animation occur concurrently.
|
802
1006
|
*
|
803
|
-
* @knownIssue If `ngView` is contained in an asynchronously loaded template (e.g. in another
|
804
|
-
* directive's templateUrl or in a template loaded using `ngInclude`), then you need to
|
805
|
-
* make sure that `$route` is instantiated in time to capture the initial
|
806
|
-
* `$locationChangeStart` event and load the appropriate view. One way to achieve this
|
807
|
-
* is to have it as a dependency in a `.run` block:
|
808
|
-
* `myModule.run(['$route', function() {}]);`
|
809
|
-
*
|
810
1007
|
* @scope
|
811
1008
|
* @priority 400
|
812
1009
|
* @param {string=} onload Expression to evaluate whenever the view updates.
|
@@ -917,17 +1114,17 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
|
917
1114
|
$locationProvider.html5Mode(true);
|
918
1115
|
}])
|
919
1116
|
.controller('MainCtrl', ['$route', '$routeParams', '$location',
|
920
|
-
function($route, $routeParams, $location) {
|
1117
|
+
function MainCtrl($route, $routeParams, $location) {
|
921
1118
|
this.$route = $route;
|
922
1119
|
this.$location = $location;
|
923
1120
|
this.$routeParams = $routeParams;
|
924
1121
|
}])
|
925
|
-
.controller('BookCtrl', ['$routeParams', function($routeParams) {
|
926
|
-
this.name =
|
1122
|
+
.controller('BookCtrl', ['$routeParams', function BookCtrl($routeParams) {
|
1123
|
+
this.name = 'BookCtrl';
|
927
1124
|
this.params = $routeParams;
|
928
1125
|
}])
|
929
|
-
.controller('ChapterCtrl', ['$routeParams', function($routeParams) {
|
930
|
-
this.name =
|
1126
|
+
.controller('ChapterCtrl', ['$routeParams', function ChapterCtrl($routeParams) {
|
1127
|
+
this.name = 'ChapterCtrl';
|
931
1128
|
this.params = $routeParams;
|
932
1129
|
}]);
|
933
1130
|
|
@@ -937,15 +1134,15 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
|
937
1134
|
it('should load and compile correct template', function() {
|
938
1135
|
element(by.linkText('Moby: Ch1')).click();
|
939
1136
|
var content = element(by.css('[ng-view]')).getText();
|
940
|
-
expect(content).toMatch(/controller
|
941
|
-
expect(content).toMatch(/Book Id
|
942
|
-
expect(content).toMatch(/Chapter Id
|
1137
|
+
expect(content).toMatch(/controller: ChapterCtrl/);
|
1138
|
+
expect(content).toMatch(/Book Id: Moby/);
|
1139
|
+
expect(content).toMatch(/Chapter Id: 1/);
|
943
1140
|
|
944
1141
|
element(by.partialLinkText('Scarlet')).click();
|
945
1142
|
|
946
1143
|
content = element(by.css('[ng-view]')).getText();
|
947
|
-
expect(content).toMatch(/controller
|
948
|
-
expect(content).toMatch(/Book Id
|
1144
|
+
expect(content).toMatch(/controller: BookCtrl/);
|
1145
|
+
expect(content).toMatch(/Book Id: Scarlet/);
|
949
1146
|
});
|
950
1147
|
</file>
|
951
1148
|
</example>
|
@@ -988,8 +1185,8 @@ function ngViewFactory($route, $anchorScroll, $animate) {
|
|
988
1185
|
}
|
989
1186
|
if (currentElement) {
|
990
1187
|
previousLeaveAnimation = $animate.leave(currentElement);
|
991
|
-
previousLeaveAnimation.
|
992
|
-
previousLeaveAnimation = null;
|
1188
|
+
previousLeaveAnimation.done(function(response) {
|
1189
|
+
if (response !== false) previousLeaveAnimation = null;
|
993
1190
|
});
|
994
1191
|
currentElement = null;
|
995
1192
|
}
|
@@ -1010,8 +1207,8 @@ function ngViewFactory($route, $anchorScroll, $animate) {
|
|
1010
1207
|
// function is called before linking the content, which would apply child
|
1011
1208
|
// directives to non existing elements.
|
1012
1209
|
var clone = $transclude(newScope, function(clone) {
|
1013
|
-
$animate.enter(clone, null, currentElement || $element).
|
1014
|
-
if (angular.isDefined(autoScrollExp)
|
1210
|
+
$animate.enter(clone, null, currentElement || $element).done(function onNgViewEnter(response) {
|
1211
|
+
if (response !== false && angular.isDefined(autoScrollExp)
|
1015
1212
|
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
|
1016
1213
|
$anchorScroll();
|
1017
1214
|
}
|