angularjs-rails 1.5.8 → 1.6.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/lib/angularjs-rails/engine.rb +1 -1
- data/lib/angularjs-rails/version.rb +1 -1
- data/vendor/assets/javascripts/angular-animate.js +75 -60
- data/vendor/assets/javascripts/angular-aria.js +29 -32
- data/vendor/assets/javascripts/angular-cookies.js +19 -11
- data/vendor/assets/javascripts/angular-loader.js +9 -8
- data/vendor/assets/javascripts/angular-message-format.js +61 -70
- data/vendor/assets/javascripts/angular-messages.js +10 -8
- data/vendor/assets/javascripts/angular-mocks.js +392 -114
- data/vendor/assets/javascripts/angular-parse-ext.js +3 -1
- data/vendor/assets/javascripts/angular-resource.js +79 -95
- data/vendor/assets/javascripts/angular-route.js +219 -72
- data/vendor/assets/javascripts/angular-sanitize.js +52 -51
- data/vendor/assets/javascripts/angular-scenario.js +3421 -2491
- data/vendor/assets/javascripts/angular-touch.js +31 -19
- data/vendor/assets/javascripts/angular.js +3332 -2205
- metadata +2 -2
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.
|
2
|
+
* @license AngularJS v1.6.0
|
3
3
|
* (c) 2010-2016 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -1223,6 +1223,8 @@ function IDC_Y(cp) {
|
|
1223
1223
|
return false;
|
1224
1224
|
}
|
1225
1225
|
|
1226
|
+
/* eslint-disable new-cap */
|
1227
|
+
|
1226
1228
|
/**
|
1227
1229
|
* @ngdoc module
|
1228
1230
|
* @name ngParseExt
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.
|
2
|
+
* @license AngularJS v1.6.0
|
3
3
|
* (c) 2010-2016 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -137,9 +137,12 @@ function shallowClearAndCopy(src, dst) {
|
|
137
137
|
* Note that the parameter will be ignored, when calling a "GET" action method (i.e. an action
|
138
138
|
* method that does not accept a request body)
|
139
139
|
*
|
140
|
-
* @param {Object.<Object>=} actions Hash with declaration of custom actions that
|
141
|
-
* the default set of resource actions.
|
142
|
-
*
|
140
|
+
* @param {Object.<Object>=} actions Hash with declaration of custom actions that will be available
|
141
|
+
* in addition to the default set of resource actions (see below). If a custom action has the same
|
142
|
+
* key as a default action (e.g. `save`), then the default action will be *overwritten*, and not
|
143
|
+
* extended.
|
144
|
+
*
|
145
|
+
* The declaration should be created in the format of {@link ng.$http#usage $http.config}:
|
143
146
|
*
|
144
147
|
* {action1: {method:?, params:?, isArray:?, headers:?, ...},
|
145
148
|
* action2: {method:?, params:?, isArray:?, headers:?, ...},
|
@@ -164,12 +167,13 @@ function shallowClearAndCopy(src, dst) {
|
|
164
167
|
* transform function or an array of such functions. The transform function takes the http
|
165
168
|
* request body and headers and returns its transformed (typically serialized) version.
|
166
169
|
* By default, transformRequest will contain one function that checks if the request data is
|
167
|
-
* an object and serializes
|
170
|
+
* an object and serializes it using `angular.toJson`. To prevent this behavior, set
|
168
171
|
* `transformRequest` to an empty array: `transformRequest: []`
|
169
172
|
* - **`transformResponse`** –
|
170
|
-
* `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
|
173
|
+
* `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
|
171
174
|
* transform function or an array of such functions. The transform function takes the http
|
172
|
-
* response body and
|
175
|
+
* response body, headers and status and returns its transformed (typically deserialized)
|
176
|
+
* version.
|
173
177
|
* By default, transformResponse will contain one function that checks if the response looks
|
174
178
|
* like a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior,
|
175
179
|
* set `transformResponse` to an empty array: `transformResponse: []`
|
@@ -243,9 +247,9 @@ function shallowClearAndCopy(src, dst) {
|
|
243
247
|
* - non-GET instance actions: `instance.$action([parameters], [success], [error])`
|
244
248
|
*
|
245
249
|
*
|
246
|
-
* Success callback is called with (value, responseHeaders)
|
247
|
-
*
|
248
|
-
* with (httpResponse) argument.
|
250
|
+
* Success callback is called with (value (Object|Array), responseHeaders (Function),
|
251
|
+
* status (number), statusText (string)) arguments, where the value is the populated resource
|
252
|
+
* instance or collection object. The error callback is called with (httpResponse) argument.
|
249
253
|
*
|
250
254
|
* Class actions return empty instance (with additional properties below).
|
251
255
|
* Instance actions return promise of the action.
|
@@ -430,8 +434,9 @@ function shallowClearAndCopy(src, dst) {
|
|
430
434
|
*
|
431
435
|
*/
|
432
436
|
angular.module('ngResource', ['ng']).
|
433
|
-
provider('$resource', function() {
|
434
|
-
var
|
437
|
+
provider('$resource', function ResourceProvider() {
|
438
|
+
var PROTOCOL_AND_IPV6_REGEX = /^https?:\/\/\[[^\]]*][^/]*/;
|
439
|
+
|
435
440
|
var provider = this;
|
436
441
|
|
437
442
|
/**
|
@@ -475,7 +480,7 @@ angular.module('ngResource', ['ng']).
|
|
475
480
|
* ```js
|
476
481
|
* angular.
|
477
482
|
* module('myApp').
|
478
|
-
* config(['resourceProvider', function ($resourceProvider) {
|
483
|
+
* config(['$resourceProvider', function ($resourceProvider) {
|
479
484
|
* $resourceProvider.defaults.actions.update = {
|
480
485
|
* method: 'PUT'
|
481
486
|
* };
|
@@ -487,9 +492,9 @@ angular.module('ngResource', ['ng']).
|
|
487
492
|
* ```js
|
488
493
|
* angular.
|
489
494
|
* module('myApp').
|
490
|
-
* config(['resourceProvider', function ($resourceProvider) {
|
495
|
+
* config(['$resourceProvider', function ($resourceProvider) {
|
491
496
|
* $resourceProvider.defaults.actions = {
|
492
|
-
* create: {method: 'POST'}
|
497
|
+
* create: {method: 'POST'},
|
493
498
|
* get: {method: 'GET'},
|
494
499
|
* getAll: {method: 'GET', isArray:true},
|
495
500
|
* update: {method: 'PUT'},
|
@@ -519,49 +524,15 @@ angular.module('ngResource', ['ng']).
|
|
519
524
|
this.$get = ['$http', '$log', '$q', '$timeout', function($http, $log, $q, $timeout) {
|
520
525
|
|
521
526
|
var noop = angular.noop,
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
* segment = *pchar
|
532
|
-
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
533
|
-
* pct-encoded = "%" HEXDIG HEXDIG
|
534
|
-
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
535
|
-
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
536
|
-
* / "*" / "+" / "," / ";" / "="
|
537
|
-
*/
|
538
|
-
function encodeUriSegment(val) {
|
539
|
-
return encodeUriQuery(val, true).
|
540
|
-
replace(/%26/gi, '&').
|
541
|
-
replace(/%3D/gi, '=').
|
542
|
-
replace(/%2B/gi, '+');
|
543
|
-
}
|
544
|
-
|
545
|
-
|
546
|
-
/**
|
547
|
-
* This method is intended for encoding *key* or *value* parts of query component. We need a
|
548
|
-
* custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't
|
549
|
-
* have to be encoded per http://tools.ietf.org/html/rfc3986:
|
550
|
-
* query = *( pchar / "/" / "?" )
|
551
|
-
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
552
|
-
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
553
|
-
* pct-encoded = "%" HEXDIG HEXDIG
|
554
|
-
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
555
|
-
* / "*" / "+" / "," / ";" / "="
|
556
|
-
*/
|
557
|
-
function encodeUriQuery(val, pctEncodeSpaces) {
|
558
|
-
return encodeURIComponent(val).
|
559
|
-
replace(/%40/gi, '@').
|
560
|
-
replace(/%3A/gi, ':').
|
561
|
-
replace(/%24/g, '$').
|
562
|
-
replace(/%2C/gi, ',').
|
563
|
-
replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
|
564
|
-
}
|
527
|
+
forEach = angular.forEach,
|
528
|
+
extend = angular.extend,
|
529
|
+
copy = angular.copy,
|
530
|
+
isArray = angular.isArray,
|
531
|
+
isDefined = angular.isDefined,
|
532
|
+
isFunction = angular.isFunction,
|
533
|
+
isNumber = angular.isNumber,
|
534
|
+
encodeUriQuery = angular.$$encodeUriQuery,
|
535
|
+
encodeUriSegment = angular.$$encodeUriSegment;
|
565
536
|
|
566
537
|
function Route(template, defaults) {
|
567
538
|
this.template = template;
|
@@ -575,42 +546,42 @@ angular.module('ngResource', ['ng']).
|
|
575
546
|
url = actionUrl || self.template,
|
576
547
|
val,
|
577
548
|
encodedVal,
|
578
|
-
|
549
|
+
protocolAndIpv6 = '';
|
579
550
|
|
580
|
-
var urlParams = self.urlParams =
|
551
|
+
var urlParams = self.urlParams = Object.create(null);
|
581
552
|
forEach(url.split(/\W/), function(param) {
|
582
553
|
if (param === 'hasOwnProperty') {
|
583
|
-
throw $resourceMinErr('badname',
|
554
|
+
throw $resourceMinErr('badname', 'hasOwnProperty is not a valid parameter name.');
|
584
555
|
}
|
585
|
-
if (!(new RegExp(
|
586
|
-
(new RegExp(
|
556
|
+
if (!(new RegExp('^\\d+$').test(param)) && param &&
|
557
|
+
(new RegExp('(^|[^\\\\]):' + param + '(\\W|$)').test(url))) {
|
587
558
|
urlParams[param] = {
|
588
|
-
isQueryParamValue: (new RegExp(
|
559
|
+
isQueryParamValue: (new RegExp('\\?.*=:' + param + '(?:\\W|$)')).test(url)
|
589
560
|
};
|
590
561
|
}
|
591
562
|
});
|
592
563
|
url = url.replace(/\\:/g, ':');
|
593
|
-
url = url.replace(
|
594
|
-
|
564
|
+
url = url.replace(PROTOCOL_AND_IPV6_REGEX, function(match) {
|
565
|
+
protocolAndIpv6 = match;
|
595
566
|
return '';
|
596
567
|
});
|
597
568
|
|
598
569
|
params = params || {};
|
599
570
|
forEach(self.urlParams, function(paramInfo, urlParam) {
|
600
571
|
val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
|
601
|
-
if (
|
572
|
+
if (isDefined(val) && val !== null) {
|
602
573
|
if (paramInfo.isQueryParamValue) {
|
603
574
|
encodedVal = encodeUriQuery(val, true);
|
604
575
|
} else {
|
605
576
|
encodedVal = encodeUriSegment(val);
|
606
577
|
}
|
607
|
-
url = url.replace(new RegExp(
|
578
|
+
url = url.replace(new RegExp(':' + urlParam + '(\\W|$)', 'g'), function(match, p1) {
|
608
579
|
return encodedVal + p1;
|
609
580
|
});
|
610
581
|
} else {
|
611
|
-
url = url.replace(new RegExp(
|
582
|
+
url = url.replace(new RegExp('(/?):' + urlParam + '(\\W|$)', 'g'), function(match,
|
612
583
|
leadingSlashes, tail) {
|
613
|
-
if (tail.charAt(0)
|
584
|
+
if (tail.charAt(0) === '/') {
|
614
585
|
return tail;
|
615
586
|
} else {
|
616
587
|
return leadingSlashes + tail;
|
@@ -628,7 +599,7 @@ angular.module('ngResource', ['ng']).
|
|
628
599
|
// E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x`
|
629
600
|
url = url.replace(/\/\.(?=\w+($|\?))/, '.');
|
630
601
|
// replace escaped `/\.` with `/.`
|
631
|
-
config.url =
|
602
|
+
config.url = protocolAndIpv6 + url.replace(/\/\\\./, '/.');
|
632
603
|
|
633
604
|
|
634
605
|
// set params - delegate param encoding to $http
|
@@ -652,7 +623,7 @@ angular.module('ngResource', ['ng']).
|
|
652
623
|
actionParams = extend({}, paramDefaults, actionParams);
|
653
624
|
forEach(actionParams, function(value, key) {
|
654
625
|
if (isFunction(value)) { value = value(data); }
|
655
|
-
ids[key] = value && value.charAt && value.charAt(0)
|
626
|
+
ids[key] = value && value.charAt && value.charAt(0) === '@' ?
|
656
627
|
lookupDottedPath(data, value.substr(1)) : value;
|
657
628
|
});
|
658
629
|
return ids;
|
@@ -676,11 +647,10 @@ angular.module('ngResource', ['ng']).
|
|
676
647
|
forEach(actions, function(action, name) {
|
677
648
|
var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);
|
678
649
|
var numericTimeout = action.timeout;
|
679
|
-
var cancellable =
|
680
|
-
|
681
|
-
provider.defaults.cancellable;
|
650
|
+
var cancellable = isDefined(action.cancellable) ?
|
651
|
+
action.cancellable : route.defaults.cancellable;
|
682
652
|
|
683
|
-
if (numericTimeout && !
|
653
|
+
if (numericTimeout && !isNumber(numericTimeout)) {
|
684
654
|
$log.debug('ngResource:\n' +
|
685
655
|
' Only numeric values are allowed as `timeout`.\n' +
|
686
656
|
' Promises are not supported in $resource, because the same value would ' +
|
@@ -693,12 +663,11 @@ angular.module('ngResource', ['ng']).
|
|
693
663
|
Resource[name] = function(a1, a2, a3, a4) {
|
694
664
|
var params = {}, data, success, error;
|
695
665
|
|
696
|
-
/* jshint -W086 */ /* (purposefully fall through case statements) */
|
697
666
|
switch (arguments.length) {
|
698
667
|
case 4:
|
699
668
|
error = a4;
|
700
669
|
success = a3;
|
701
|
-
|
670
|
+
// falls through
|
702
671
|
case 3:
|
703
672
|
case 2:
|
704
673
|
if (isFunction(a2)) {
|
@@ -710,13 +679,14 @@ angular.module('ngResource', ['ng']).
|
|
710
679
|
|
711
680
|
success = a2;
|
712
681
|
error = a3;
|
713
|
-
//
|
682
|
+
// falls through
|
714
683
|
} else {
|
715
684
|
params = a1;
|
716
685
|
data = a2;
|
717
686
|
success = a3;
|
718
687
|
break;
|
719
688
|
}
|
689
|
+
// falls through
|
720
690
|
case 1:
|
721
691
|
if (isFunction(a1)) success = a1;
|
722
692
|
else if (hasBody) data = a1;
|
@@ -725,10 +695,9 @@ angular.module('ngResource', ['ng']).
|
|
725
695
|
case 0: break;
|
726
696
|
default:
|
727
697
|
throw $resourceMinErr('badargs',
|
728
|
-
|
698
|
+
'Expected up to 4 arguments [params, data, success, error], got {0} arguments',
|
729
699
|
arguments.length);
|
730
700
|
}
|
731
|
-
/* jshint +W086 */ /* (purposefully fall through case statements) */
|
732
701
|
|
733
702
|
var isInstanceCall = this instanceof Resource;
|
734
703
|
var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data));
|
@@ -737,6 +706,8 @@ angular.module('ngResource', ['ng']).
|
|
737
706
|
defaultResponseInterceptor;
|
738
707
|
var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||
|
739
708
|
undefined;
|
709
|
+
var hasError = !!error;
|
710
|
+
var hasResponseErrorInterceptor = !!responseErrorInterceptor;
|
740
711
|
var timeoutDeferred;
|
741
712
|
var numericTimeoutPromise;
|
742
713
|
|
@@ -772,18 +743,16 @@ angular.module('ngResource', ['ng']).
|
|
772
743
|
|
773
744
|
if (data) {
|
774
745
|
// Need to convert action.isArray to boolean in case it is undefined
|
775
|
-
|
776
|
-
if (angular.isArray(data) !== (!!action.isArray)) {
|
746
|
+
if (isArray(data) !== (!!action.isArray)) {
|
777
747
|
throw $resourceMinErr('badcfg',
|
778
748
|
'Error in resource configuration for action `{0}`. Expected response to ' +
|
779
749
|
'contain an {1} but got an {2} (Request: {3} {4})', name, action.isArray ? 'array' : 'object',
|
780
|
-
|
750
|
+
isArray(data) ? 'array' : 'object', httpConfig.method, httpConfig.url);
|
781
751
|
}
|
782
|
-
// jshint +W018
|
783
752
|
if (action.isArray) {
|
784
753
|
value.length = 0;
|
785
754
|
forEach(data, function(item) {
|
786
|
-
if (typeof item ===
|
755
|
+
if (typeof item === 'object') {
|
787
756
|
value.push(new Resource(item));
|
788
757
|
} else {
|
789
758
|
// Valid JSON values may be string literals, and these should not be converted
|
@@ -801,15 +770,12 @@ angular.module('ngResource', ['ng']).
|
|
801
770
|
response.resource = value;
|
802
771
|
|
803
772
|
return response;
|
804
|
-
}, function(response) {
|
805
|
-
(error || noop)(response);
|
806
|
-
return $q.reject(response);
|
807
773
|
});
|
808
774
|
|
809
|
-
promise['finally'](function() {
|
775
|
+
promise = promise['finally'](function() {
|
810
776
|
value.$resolved = true;
|
811
777
|
if (!isInstanceCall && cancellable) {
|
812
|
-
value.$cancelRequest =
|
778
|
+
value.$cancelRequest = noop;
|
813
779
|
$timeout.cancel(numericTimeoutPromise);
|
814
780
|
timeoutDeferred = numericTimeoutPromise = httpConfig.timeout = null;
|
815
781
|
}
|
@@ -818,10 +784,22 @@ angular.module('ngResource', ['ng']).
|
|
818
784
|
promise = promise.then(
|
819
785
|
function(response) {
|
820
786
|
var value = responseInterceptor(response);
|
821
|
-
(success || noop)(value, response.headers);
|
787
|
+
(success || noop)(value, response.headers, response.status, response.statusText);
|
822
788
|
return value;
|
823
789
|
},
|
824
|
-
|
790
|
+
(hasError || hasResponseErrorInterceptor) ?
|
791
|
+
function(response) {
|
792
|
+
if (hasError) error(response);
|
793
|
+
return hasResponseErrorInterceptor ?
|
794
|
+
responseErrorInterceptor(response) :
|
795
|
+
$q.reject(response);
|
796
|
+
} :
|
797
|
+
undefined);
|
798
|
+
if (hasError && !hasResponseErrorInterceptor) {
|
799
|
+
// Avoid `Possibly Unhandled Rejection` error,
|
800
|
+
// but still fulfill the returned promise with a rejection
|
801
|
+
promise.catch(noop);
|
802
|
+
}
|
825
803
|
|
826
804
|
if (!isInstanceCall) {
|
827
805
|
// we are creating instance / collection
|
@@ -829,13 +807,18 @@ angular.module('ngResource', ['ng']).
|
|
829
807
|
// - return the instance / collection
|
830
808
|
value.$promise = promise;
|
831
809
|
value.$resolved = false;
|
832
|
-
if (cancellable) value.$cancelRequest =
|
810
|
+
if (cancellable) value.$cancelRequest = cancelRequest;
|
833
811
|
|
834
812
|
return value;
|
835
813
|
}
|
836
814
|
|
837
815
|
// instance call
|
838
816
|
return promise;
|
817
|
+
|
818
|
+
function cancelRequest(value) {
|
819
|
+
promise.catch(noop);
|
820
|
+
timeoutDeferred.resolve(value);
|
821
|
+
}
|
839
822
|
};
|
840
823
|
|
841
824
|
|
@@ -849,7 +832,8 @@ angular.module('ngResource', ['ng']).
|
|
849
832
|
});
|
850
833
|
|
851
834
|
Resource.bind = function(additionalParamDefaults) {
|
852
|
-
|
835
|
+
var extendedParamDefaults = extend({}, paramDefaults, additionalParamDefaults);
|
836
|
+
return resourceFactory(url, extendedParamDefaults, actions, options);
|
853
837
|
};
|
854
838
|
|
855
839
|
return Resource;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.
|
2
|
+
* @license AngularJS v1.6.0
|
3
3
|
* (c) 2010-2016 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -34,10 +34,11 @@ function shallowCopy(src, dst) {
|
|
34
34
|
|
35
35
|
/* global shallowCopy: false */
|
36
36
|
|
37
|
-
//
|
37
|
+
// `isArray` and `isObject` are necessary for `shallowCopy()` (included via `src/shallowCopy.js`).
|
38
38
|
// They are initialized inside the `$RouteProvider`, to ensure `window.angular` is available.
|
39
39
|
var isArray;
|
40
40
|
var isObject;
|
41
|
+
var isDefined;
|
41
42
|
|
42
43
|
/**
|
43
44
|
* @ngdoc module
|
@@ -54,14 +55,22 @@ var isObject;
|
|
54
55
|
*
|
55
56
|
* <div doc-module-components="ngRoute"></div>
|
56
57
|
*/
|
57
|
-
|
58
|
-
var ngRouteModule = angular.
|
59
|
-
|
60
|
-
|
58
|
+
/* global -ngRouteModule */
|
59
|
+
var ngRouteModule = angular.
|
60
|
+
module('ngRoute', []).
|
61
|
+
provider('$route', $RouteProvider).
|
62
|
+
// Ensure `$route` will be instantiated in time to capture the initial `$locationChangeSuccess`
|
63
|
+
// event (unless explicitly disabled). This is necessary in case `ngView` is included in an
|
64
|
+
// asynchronously loaded template.
|
65
|
+
run(instantiateRoute);
|
66
|
+
var $routeMinErr = angular.$$minErr('ngRoute');
|
67
|
+
var isEagerInstantiationEnabled;
|
68
|
+
|
61
69
|
|
62
70
|
/**
|
63
71
|
* @ngdoc provider
|
64
72
|
* @name $routeProvider
|
73
|
+
* @this
|
65
74
|
*
|
66
75
|
* @description
|
67
76
|
*
|
@@ -76,6 +85,7 @@ var ngRouteModule = angular.module('ngRoute', ['ng']).
|
|
76
85
|
function $RouteProvider() {
|
77
86
|
isArray = angular.isArray;
|
78
87
|
isObject = angular.isObject;
|
88
|
+
isDefined = angular.isDefined;
|
79
89
|
|
80
90
|
function inherit(parent, extra) {
|
81
91
|
return angular.extend(Object.create(parent), extra);
|
@@ -112,12 +122,12 @@ function $RouteProvider() {
|
|
112
122
|
*
|
113
123
|
* Object properties:
|
114
124
|
*
|
115
|
-
* - `controller` – `{(string|
|
125
|
+
* - `controller` – `{(string|Function)=}` – Controller fn that should be associated with
|
116
126
|
* newly created scope or the name of a {@link angular.Module#controller registered
|
117
127
|
* controller} if passed as a string.
|
118
128
|
* - `controllerAs` – `{string=}` – An identifier name for a reference to the controller.
|
119
129
|
* If present, the controller will be published to scope under the `controllerAs` name.
|
120
|
-
* - `template` – `{string
|
130
|
+
* - `template` – `{(string|Function)=}` – html template as a string or a function that
|
121
131
|
* returns an html template as a string which should be used by {@link
|
122
132
|
* ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
|
123
133
|
* This property takes precedence over `templateUrl`.
|
@@ -127,7 +137,9 @@ function $RouteProvider() {
|
|
127
137
|
* - `{Array.<Object>}` - route parameters extracted from the current
|
128
138
|
* `$location.path()` by applying the current route
|
129
139
|
*
|
130
|
-
*
|
140
|
+
* One of `template` or `templateUrl` is required.
|
141
|
+
*
|
142
|
+
* - `templateUrl` – `{(string|Function)=}` – path or function that returns a path to an html
|
131
143
|
* template that should be used by {@link ngRoute.directive:ngView ngView}.
|
132
144
|
*
|
133
145
|
* If `templateUrl` is a function, it will be called with the following parameters:
|
@@ -135,7 +147,9 @@ function $RouteProvider() {
|
|
135
147
|
* - `{Array.<Object>}` - route parameters extracted from the current
|
136
148
|
* `$location.path()` by applying the current route
|
137
149
|
*
|
138
|
-
*
|
150
|
+
* One of `templateUrl` or `template` is required.
|
151
|
+
*
|
152
|
+
* - `resolve` - `{Object.<string, Function>=}` - An optional map of dependencies which should
|
139
153
|
* be injected into the controller. If any of these dependencies are promises, the router
|
140
154
|
* will wait for them all to be resolved or one to be rejected before the controller is
|
141
155
|
* instantiated.
|
@@ -155,7 +169,7 @@ function $RouteProvider() {
|
|
155
169
|
* The map object is:
|
156
170
|
*
|
157
171
|
* - `key` – `{string}`: a name of a dependency to be injected into the controller.
|
158
|
-
* - `factory` - `{string|
|
172
|
+
* - `factory` - `{string|Function}`: If `string` then it is an alias for a service.
|
159
173
|
* Otherwise if function, then it is {@link auto.$injector#invoke injected}
|
160
174
|
* and the return value is treated as the dependency. If the result is a promise, it is
|
161
175
|
* resolved before its value is injected into the controller. Be aware that
|
@@ -165,7 +179,7 @@ function $RouteProvider() {
|
|
165
179
|
* - `resolveAs` - `{string=}` - The name under which the `resolve` map will be available on
|
166
180
|
* the scope of the route. If omitted, defaults to `$resolve`.
|
167
181
|
*
|
168
|
-
* - `redirectTo` – `{(string|
|
182
|
+
* - `redirectTo` – `{(string|Function)=}` – value to update
|
169
183
|
* {@link ng.$location $location} path with and trigger route redirection.
|
170
184
|
*
|
171
185
|
* If `redirectTo` is a function, it will be called with the following parameters:
|
@@ -176,7 +190,31 @@ function $RouteProvider() {
|
|
176
190
|
* - `{Object}` - current `$location.search()`
|
177
191
|
*
|
178
192
|
* The custom `redirectTo` function is expected to return a string which will be used
|
179
|
-
* to update `$location.
|
193
|
+
* to update `$location.url()`. If the function throws an error, no further processing will
|
194
|
+
* take place and the {@link ngRoute.$route#$routeChangeError $routeChangeError} event will
|
195
|
+
* be fired.
|
196
|
+
*
|
197
|
+
* Routes that specify `redirectTo` will not have their controllers, template functions
|
198
|
+
* or resolves called, the `$location` will be changed to the redirect url and route
|
199
|
+
* processing will stop. The exception to this is if the `redirectTo` is a function that
|
200
|
+
* returns `undefined`. In this case the route transition occurs as though there was no
|
201
|
+
* redirection.
|
202
|
+
*
|
203
|
+
* - `resolveRedirectTo` – `{Function=}` – a function that will (eventually) return the value
|
204
|
+
* to update {@link ng.$location $location} URL with and trigger route redirection. In
|
205
|
+
* contrast to `redirectTo`, dependencies can be injected into `resolveRedirectTo` and the
|
206
|
+
* return value can be either a string or a promise that will be resolved to a string.
|
207
|
+
*
|
208
|
+
* Similar to `redirectTo`, if the return value is `undefined` (or a promise that gets
|
209
|
+
* resolved to `undefined`), no redirection takes place and the route transition occurs as
|
210
|
+
* though there was no redirection.
|
211
|
+
*
|
212
|
+
* If the function throws an error or the returned promise gets rejected, no further
|
213
|
+
* processing will take place and the
|
214
|
+
* {@link ngRoute.$route#$routeChangeError $routeChangeError} event will be fired.
|
215
|
+
*
|
216
|
+
* `redirectTo` takes precedence over `resolveRedirectTo`, so specifying both on the same
|
217
|
+
* route definition, will cause the latter to be ignored.
|
180
218
|
*
|
181
219
|
* - `[reloadOnSearch=true]` - `{boolean=}` - reload route when only `$location.search()`
|
182
220
|
* or `$location.hash()` changes.
|
@@ -210,7 +248,7 @@ function $RouteProvider() {
|
|
210
248
|
|
211
249
|
// create redirection for trailing slashes
|
212
250
|
if (path) {
|
213
|
-
var redirectPath = (path[path.length - 1]
|
251
|
+
var redirectPath = (path[path.length - 1] === '/')
|
214
252
|
? path.substr(0, path.length - 1)
|
215
253
|
: path + '/';
|
216
254
|
|
@@ -255,7 +293,7 @@ function $RouteProvider() {
|
|
255
293
|
|
256
294
|
path = path
|
257
295
|
.replace(/([().])/g, '\\$1')
|
258
|
-
.replace(/(\/)?:(\w+)(\*\?|[
|
296
|
+
.replace(/(\/)?:(\w+)(\*\?|[?*])?/g, function(_, slash, key, option) {
|
259
297
|
var optional = (option === '?' || option === '*?') ? '?' : null;
|
260
298
|
var star = (option === '*' || option === '*?') ? '*' : null;
|
261
299
|
keys.push({ name: key, optional: !!optional });
|
@@ -269,7 +307,7 @@ function $RouteProvider() {
|
|
269
307
|
+ ')'
|
270
308
|
+ (optional || '');
|
271
309
|
})
|
272
|
-
.replace(/([
|
310
|
+
.replace(/([/$*])/g, '\\$1');
|
273
311
|
|
274
312
|
ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
|
275
313
|
return ret;
|
@@ -295,6 +333,47 @@ function $RouteProvider() {
|
|
295
333
|
return this;
|
296
334
|
};
|
297
335
|
|
336
|
+
/**
|
337
|
+
* @ngdoc method
|
338
|
+
* @name $routeProvider#eagerInstantiationEnabled
|
339
|
+
* @kind function
|
340
|
+
*
|
341
|
+
* @description
|
342
|
+
* Call this method as a setter to enable/disable eager instantiation of the
|
343
|
+
* {@link ngRoute.$route $route} service upon application bootstrap. You can also call it as a
|
344
|
+
* getter (i.e. without any arguments) to get the current value of the
|
345
|
+
* `eagerInstantiationEnabled` flag.
|
346
|
+
*
|
347
|
+
* Instantiating `$route` early is necessary for capturing the initial
|
348
|
+
* {@link ng.$location#$locationChangeStart $locationChangeStart} event and navigating to the
|
349
|
+
* appropriate route. Usually, `$route` is instantiated in time by the
|
350
|
+
* {@link ngRoute.ngView ngView} directive. Yet, in cases where `ngView` is included in an
|
351
|
+
* asynchronously loaded template (e.g. in another directive's template), the directive factory
|
352
|
+
* might not be called soon enough for `$route` to be instantiated _before_ the initial
|
353
|
+
* `$locationChangeSuccess` event is fired. Eager instantiation ensures that `$route` is always
|
354
|
+
* instantiated in time, regardless of when `ngView` will be loaded.
|
355
|
+
*
|
356
|
+
* The default value is true.
|
357
|
+
*
|
358
|
+
* **Note**:<br />
|
359
|
+
* You may want to disable the default behavior when unit-testing modules that depend on
|
360
|
+
* `ngRoute`, in order to avoid an unexpected request for the default route's template.
|
361
|
+
*
|
362
|
+
* @param {boolean=} enabled - If provided, update the internal `eagerInstantiationEnabled` flag.
|
363
|
+
*
|
364
|
+
* @returns {*} The current value of the `eagerInstantiationEnabled` flag if used as a getter or
|
365
|
+
* itself (for chaining) if used as a setter.
|
366
|
+
*/
|
367
|
+
isEagerInstantiationEnabled = true;
|
368
|
+
this.eagerInstantiationEnabled = function eagerInstantiationEnabled(enabled) {
|
369
|
+
if (isDefined(enabled)) {
|
370
|
+
isEagerInstantiationEnabled = enabled;
|
371
|
+
return this;
|
372
|
+
}
|
373
|
+
|
374
|
+
return isEagerInstantiationEnabled;
|
375
|
+
};
|
376
|
+
|
298
377
|
|
299
378
|
this.$get = ['$rootScope',
|
300
379
|
'$location',
|
@@ -388,12 +467,12 @@ function $RouteProvider() {
|
|
388
467
|
* })
|
389
468
|
*
|
390
469
|
* .controller('BookController', function($scope, $routeParams) {
|
391
|
-
* $scope.name =
|
470
|
+
* $scope.name = 'BookController';
|
392
471
|
* $scope.params = $routeParams;
|
393
472
|
* })
|
394
473
|
*
|
395
474
|
* .controller('ChapterController', function($scope, $routeParams) {
|
396
|
-
* $scope.name =
|
475
|
+
* $scope.name = 'ChapterController';
|
397
476
|
* $scope.params = $routeParams;
|
398
477
|
* })
|
399
478
|
*
|
@@ -426,15 +505,15 @@ function $RouteProvider() {
|
|
426
505
|
* it('should load and compile correct template', function() {
|
427
506
|
* element(by.linkText('Moby: Ch1')).click();
|
428
507
|
* 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
|
508
|
+
* expect(content).toMatch(/controller: ChapterController/);
|
509
|
+
* expect(content).toMatch(/Book Id: Moby/);
|
510
|
+
* expect(content).toMatch(/Chapter Id: 1/);
|
432
511
|
*
|
433
512
|
* element(by.partialLinkText('Scarlet')).click();
|
434
513
|
*
|
435
514
|
* content = element(by.css('[ng-view]')).getText();
|
436
|
-
* expect(content).toMatch(/controller
|
437
|
-
* expect(content).toMatch(/Book Id
|
515
|
+
* expect(content).toMatch(/controller: BookController/);
|
516
|
+
* expect(content).toMatch(/Book Id: Scarlet/);
|
438
517
|
* });
|
439
518
|
* </file>
|
440
519
|
* </example>
|
@@ -482,12 +561,14 @@ function $RouteProvider() {
|
|
482
561
|
* @name $route#$routeChangeError
|
483
562
|
* @eventType broadcast on root scope
|
484
563
|
* @description
|
485
|
-
* Broadcasted if any
|
564
|
+
* Broadcasted if a redirection function fails or any redirection or resolve promises are
|
565
|
+
* rejected.
|
486
566
|
*
|
487
567
|
* @param {Object} angularEvent Synthetic event object
|
488
568
|
* @param {Route} current Current route information.
|
489
569
|
* @param {Route} previous Previous route information.
|
490
|
-
* @param {Route} rejection
|
570
|
+
* @param {Route} rejection The thrown error or the rejection reason of the promise. Usually
|
571
|
+
* the rejection reason is the error that caused the promise to get rejected.
|
491
572
|
*/
|
492
573
|
|
493
574
|
/**
|
@@ -628,37 +709,103 @@ function $RouteProvider() {
|
|
628
709
|
} else if (nextRoute || lastRoute) {
|
629
710
|
forceReload = false;
|
630
711
|
$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
712
|
|
643
|
-
$q.
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
713
|
+
var nextRoutePromise = $q.resolve(nextRoute);
|
714
|
+
|
715
|
+
nextRoutePromise.
|
716
|
+
then(getRedirectionData).
|
717
|
+
then(handlePossibleRedirection).
|
718
|
+
then(function(keepProcessingRoute) {
|
719
|
+
return keepProcessingRoute && nextRoutePromise.
|
720
|
+
then(resolveLocals).
|
721
|
+
then(function(locals) {
|
722
|
+
// after route change
|
723
|
+
if (nextRoute === $route.current) {
|
724
|
+
if (nextRoute) {
|
725
|
+
nextRoute.locals = locals;
|
726
|
+
angular.copy(nextRoute.params, $routeParams);
|
727
|
+
}
|
728
|
+
$rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);
|
729
|
+
}
|
730
|
+
});
|
731
|
+
}).catch(function(error) {
|
732
|
+
if (nextRoute === $route.current) {
|
656
733
|
$rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);
|
657
734
|
}
|
658
735
|
});
|
659
736
|
}
|
660
737
|
}
|
661
738
|
|
739
|
+
function getRedirectionData(route) {
|
740
|
+
var data = {
|
741
|
+
route: route,
|
742
|
+
hasRedirection: false
|
743
|
+
};
|
744
|
+
|
745
|
+
if (route) {
|
746
|
+
if (route.redirectTo) {
|
747
|
+
if (angular.isString(route.redirectTo)) {
|
748
|
+
data.path = interpolate(route.redirectTo, route.params);
|
749
|
+
data.search = route.params;
|
750
|
+
data.hasRedirection = true;
|
751
|
+
} else {
|
752
|
+
var oldPath = $location.path();
|
753
|
+
var oldSearch = $location.search();
|
754
|
+
var newUrl = route.redirectTo(route.pathParams, oldPath, oldSearch);
|
755
|
+
|
756
|
+
if (angular.isDefined(newUrl)) {
|
757
|
+
data.url = newUrl;
|
758
|
+
data.hasRedirection = true;
|
759
|
+
}
|
760
|
+
}
|
761
|
+
} else if (route.resolveRedirectTo) {
|
762
|
+
return $q.
|
763
|
+
resolve($injector.invoke(route.resolveRedirectTo)).
|
764
|
+
then(function(newUrl) {
|
765
|
+
if (angular.isDefined(newUrl)) {
|
766
|
+
data.url = newUrl;
|
767
|
+
data.hasRedirection = true;
|
768
|
+
}
|
769
|
+
|
770
|
+
return data;
|
771
|
+
});
|
772
|
+
}
|
773
|
+
}
|
774
|
+
|
775
|
+
return data;
|
776
|
+
}
|
777
|
+
|
778
|
+
function handlePossibleRedirection(data) {
|
779
|
+
var keepProcessingRoute = true;
|
780
|
+
|
781
|
+
if (data.route !== $route.current) {
|
782
|
+
keepProcessingRoute = false;
|
783
|
+
} else if (data.hasRedirection) {
|
784
|
+
var oldUrl = $location.url();
|
785
|
+
var newUrl = data.url;
|
786
|
+
|
787
|
+
if (newUrl) {
|
788
|
+
$location.
|
789
|
+
url(newUrl).
|
790
|
+
replace();
|
791
|
+
} else {
|
792
|
+
newUrl = $location.
|
793
|
+
path(data.path).
|
794
|
+
search(data.search).
|
795
|
+
replace().
|
796
|
+
url();
|
797
|
+
}
|
798
|
+
|
799
|
+
if (newUrl !== oldUrl) {
|
800
|
+
// Exit out and don't process current next value,
|
801
|
+
// wait for next location change from redirect
|
802
|
+
keepProcessingRoute = false;
|
803
|
+
}
|
804
|
+
}
|
805
|
+
|
806
|
+
return keepProcessingRoute;
|
807
|
+
}
|
808
|
+
|
662
809
|
function resolveLocals(route) {
|
663
810
|
if (route) {
|
664
811
|
var locals = angular.extend({}, route.resolve);
|
@@ -675,7 +822,6 @@ function $RouteProvider() {
|
|
675
822
|
}
|
676
823
|
}
|
677
824
|
|
678
|
-
|
679
825
|
function getTemplateFor(route) {
|
680
826
|
var template, templateUrl;
|
681
827
|
if (angular.isDefined(template = route.template)) {
|
@@ -694,7 +840,6 @@ function $RouteProvider() {
|
|
694
840
|
return template;
|
695
841
|
}
|
696
842
|
|
697
|
-
|
698
843
|
/**
|
699
844
|
* @returns {Object} the current active route, by matching it against the URL
|
700
845
|
*/
|
@@ -734,6 +879,14 @@ function $RouteProvider() {
|
|
734
879
|
}];
|
735
880
|
}
|
736
881
|
|
882
|
+
instantiateRoute.$inject = ['$injector'];
|
883
|
+
function instantiateRoute($injector) {
|
884
|
+
if (isEagerInstantiationEnabled) {
|
885
|
+
// Instantiate `$route`
|
886
|
+
$injector.get('$route');
|
887
|
+
}
|
888
|
+
}
|
889
|
+
|
737
890
|
ngRouteModule.provider('$routeParams', $RouteParamsProvider);
|
738
891
|
|
739
892
|
|
@@ -741,6 +894,7 @@ ngRouteModule.provider('$routeParams', $RouteParamsProvider);
|
|
741
894
|
* @ngdoc service
|
742
895
|
* @name $routeParams
|
743
896
|
* @requires $route
|
897
|
+
* @this
|
744
898
|
*
|
745
899
|
* @description
|
746
900
|
* The `$routeParams` service allows you to retrieve the current set of route parameters.
|
@@ -800,13 +954,6 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
|
800
954
|
*
|
801
955
|
* The enter and leave animation occur concurrently.
|
802
956
|
*
|
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
957
|
* @scope
|
811
958
|
* @priority 400
|
812
959
|
* @param {string=} onload Expression to evaluate whenever the view updates.
|
@@ -917,17 +1064,17 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
|
917
1064
|
$locationProvider.html5Mode(true);
|
918
1065
|
}])
|
919
1066
|
.controller('MainCtrl', ['$route', '$routeParams', '$location',
|
920
|
-
function($route, $routeParams, $location) {
|
1067
|
+
function MainCtrl($route, $routeParams, $location) {
|
921
1068
|
this.$route = $route;
|
922
1069
|
this.$location = $location;
|
923
1070
|
this.$routeParams = $routeParams;
|
924
1071
|
}])
|
925
|
-
.controller('BookCtrl', ['$routeParams', function($routeParams) {
|
926
|
-
this.name =
|
1072
|
+
.controller('BookCtrl', ['$routeParams', function BookCtrl($routeParams) {
|
1073
|
+
this.name = 'BookCtrl';
|
927
1074
|
this.params = $routeParams;
|
928
1075
|
}])
|
929
|
-
.controller('ChapterCtrl', ['$routeParams', function($routeParams) {
|
930
|
-
this.name =
|
1076
|
+
.controller('ChapterCtrl', ['$routeParams', function ChapterCtrl($routeParams) {
|
1077
|
+
this.name = 'ChapterCtrl';
|
931
1078
|
this.params = $routeParams;
|
932
1079
|
}]);
|
933
1080
|
|
@@ -937,15 +1084,15 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
|
937
1084
|
it('should load and compile correct template', function() {
|
938
1085
|
element(by.linkText('Moby: Ch1')).click();
|
939
1086
|
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
|
1087
|
+
expect(content).toMatch(/controller: ChapterCtrl/);
|
1088
|
+
expect(content).toMatch(/Book Id: Moby/);
|
1089
|
+
expect(content).toMatch(/Chapter Id: 1/);
|
943
1090
|
|
944
1091
|
element(by.partialLinkText('Scarlet')).click();
|
945
1092
|
|
946
1093
|
content = element(by.css('[ng-view]')).getText();
|
947
|
-
expect(content).toMatch(/controller
|
948
|
-
expect(content).toMatch(/Book Id
|
1094
|
+
expect(content).toMatch(/controller: BookCtrl/);
|
1095
|
+
expect(content).toMatch(/Book Id: Scarlet/);
|
949
1096
|
});
|
950
1097
|
</file>
|
951
1098
|
</example>
|
@@ -988,8 +1135,8 @@ function ngViewFactory($route, $anchorScroll, $animate) {
|
|
988
1135
|
}
|
989
1136
|
if (currentElement) {
|
990
1137
|
previousLeaveAnimation = $animate.leave(currentElement);
|
991
|
-
previousLeaveAnimation.
|
992
|
-
previousLeaveAnimation = null;
|
1138
|
+
previousLeaveAnimation.done(function(response) {
|
1139
|
+
if (response !== false) previousLeaveAnimation = null;
|
993
1140
|
});
|
994
1141
|
currentElement = null;
|
995
1142
|
}
|
@@ -1010,8 +1157,8 @@ function ngViewFactory($route, $anchorScroll, $animate) {
|
|
1010
1157
|
// function is called before linking the content, which would apply child
|
1011
1158
|
// directives to non existing elements.
|
1012
1159
|
var clone = $transclude(newScope, function(clone) {
|
1013
|
-
$animate.enter(clone, null, currentElement || $element).
|
1014
|
-
if (angular.isDefined(autoScrollExp)
|
1160
|
+
$animate.enter(clone, null, currentElement || $element).done(function onNgViewEnter(response) {
|
1161
|
+
if (response !== false && angular.isDefined(autoScrollExp)
|
1015
1162
|
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
|
1016
1163
|
$anchorScroll();
|
1017
1164
|
}
|