angular-rails-engine 1.1.5.0 → 1.2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,11 @@
1
1
  /**
2
- * @license AngularJS v1.1.5
2
+ * @license AngularJS v1.2.0rc1
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
6
- (function(window, angular, undefined) {
7
- 'use strict';
6
+ (function(window, angular, undefined) {'use strict';
7
+
8
+ var $resourceMinErr = angular.$$minErr('$resource');
8
9
 
9
10
  /**
10
11
  * @ngdoc overview
@@ -37,12 +38,11 @@
37
38
  *
38
39
  * @param {string} url A parametrized URL template with parameters prefixed by `:` as in
39
40
  * `/user/:username`. If you are using a URL with a port number (e.g.
40
- * `http://example.com:8080/api`), you'll need to escape the colon character before the port
41
- * number, like this: `$resource('http://example.com\\:8080/api')`.
41
+ * `http://example.com:8080/api`), it will be respected.
42
42
  *
43
- * If you are using a url with a suffix, just add the suffix, like this:
43
+ * If you are using a url with a suffix, just add the suffix, like this:
44
44
  * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')
45
- * or even `$resource('http://example.com/resource/:resource_id.:format')`
45
+ * or even `$resource('http://example.com/resource/:resource_id.:format')`
46
46
  * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be
47
47
  * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you
48
48
  * can escape it with `/\.`.
@@ -98,6 +98,9 @@
98
98
  * requests with credentials} for more information.
99
99
  * - **`responseType`** - `{string}` - see {@link
100
100
  * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
101
+ * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods -
102
+ * `response` and `responseError`. Both `response` and `responseError` interceptors get called
103
+ * with `http response` object. See {@link ng.$http $http interceptors}.
101
104
  *
102
105
  * @returns {Object} A resource "class" object with methods for the default set of resource actions
103
106
  * optionally extended with custom `actions`. The default set contains these actions:
@@ -136,24 +139,27 @@
136
139
  * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
137
140
  * - non-GET instance actions: `instance.$action([parameters], [success], [error])`
138
141
  *
142
+ * Success callback is called with (value, responseHeaders) arguments. Error callback is called
143
+ * with (httpResponse) argument.
139
144
  *
140
- * The Resource instances and collection have these additional properties:
145
+ * Class actions return empty instance (with additional properties below).
146
+ * Instance actions return promise of the action.
141
147
  *
142
- * - `$then`: the `then` method of a {@link ng.$q promise} derived from the underlying
143
- * {@link ng.$http $http} call.
148
+ * The Resource instances and collection have these additional properties:
144
149
  *
145
- * The success callback for the `$then` method will be resolved if the underlying `$http` requests
146
- * succeeds.
150
+ * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this
151
+ * instance or collection.
147
152
  *
148
- * The success callback is called with a single object which is the {@link ng.$http http response}
149
- * object extended with a new property `resource`. This `resource` property is a reference to the
150
- * result of the resource action resource object or array of resources.
153
+ * On success, the promise is resolved with the same resource instance or collection object,
154
+ * updated with data from server. This makes it easy to use in
155
+ * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view rendering
156
+ * until the resource(s) are loaded.
151
157
  *
152
- * The error callback is called with the {@link ng.$http http response} object when an http
153
- * error occurs.
158
+ * On failure, the promise is resolved with the {@link ng.$http http response} object,
159
+ * without the `resource` property.
154
160
  *
155
- * - `$resolved`: true if the promise has been resolved (either with success or rejection);
156
- * Knowing if the Resource has been resolved is useful in data-binding.
161
+ * - `$resolved`: `true` after first server interaction is completed (either with success or rejection),
162
+ * `false` before that. Knowing if the Resource has been resolved is useful in data-binding.
157
163
  *
158
164
  * @example
159
165
  *
@@ -274,7 +280,7 @@
274
280
  </doc:example>
275
281
  */
276
282
  angular.module('ngResource', ['ng']).
277
- factory('$resource', ['$http', '$parse', function($http, $parse) {
283
+ factory('$resource', ['$http', '$parse', '$q', function($http, $parse, $q) {
278
284
  var DEFAULT_ACTIONS = {
279
285
  'get': {method:'GET'},
280
286
  'save': {method:'POST'},
@@ -345,7 +351,7 @@ angular.module('ngResource', ['ng']).
345
351
 
346
352
  var urlParams = self.urlParams = {};
347
353
  forEach(url.split(/\W/), function(param){
348
- if (param && (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
354
+ if (!(new RegExp("^\\d+$").test(param)) && param && (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
349
355
  urlParams[param] = true;
350
356
  }
351
357
  });
@@ -376,7 +382,7 @@ angular.module('ngResource', ['ng']).
376
382
  url = url.replace(/\/\.(?=\w+($|\?))/, '.');
377
383
  // replace escaped `/\.` with `/.`
378
384
  config.url = url.replace(/\/\\\./, '/.');
379
-
385
+
380
386
 
381
387
  // set params - delegate param encoding to $http
382
388
  forEach(params, function(value, key){
@@ -404,19 +410,19 @@ angular.module('ngResource', ['ng']).
404
410
  return ids;
405
411
  }
406
412
 
413
+ function defaultResponseInterceptor(response) {
414
+ return response.resource;
415
+ }
416
+
407
417
  function Resource(value){
408
418
  copy(value || {}, this);
409
419
  }
410
420
 
411
421
  forEach(actions, function(action, name) {
412
- action.method = angular.uppercase(action.method);
413
- var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';
422
+ var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);
423
+
414
424
  Resource[name] = function(a1, a2, a3, a4) {
415
- var params = {};
416
- var data;
417
- var success = noop;
418
- var error = null;
419
- var promise;
425
+ var params = {}, data, success, error;
420
426
 
421
427
  switch(arguments.length) {
422
428
  case 4:
@@ -448,33 +454,35 @@ angular.module('ngResource', ['ng']).
448
454
  break;
449
455
  case 0: break;
450
456
  default:
451
- throw "Expected between 0-4 arguments [params, data, success, error], got " +
452
- arguments.length + " arguments.";
457
+ throw $resourceMinErr('badargs',
458
+ "Expected up to 4 arguments [params, data, success, error], got {0} arguments", arguments.length);
453
459
  }
454
460
 
455
- var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
456
- var httpConfig = {},
457
- promise;
461
+ var isInstanceCall = data instanceof Resource;
462
+ var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data));
463
+ var httpConfig = {};
464
+ var responseInterceptor = action.interceptor && action.interceptor.response || defaultResponseInterceptor;
465
+ var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || undefined;
458
466
 
459
467
  forEach(action, function(value, key) {
460
- if (key != 'params' && key != 'isArray' ) {
468
+ if (key != 'params' && key != 'isArray' && key != 'interceptor') {
461
469
  httpConfig[key] = copy(value);
462
470
  }
463
471
  });
472
+
464
473
  httpConfig.data = data;
465
474
  route.setUrlParams(httpConfig, extend({}, extractParams(data, action.params || {}), params), action.url);
466
475
 
467
- function markResolved() { value.$resolved = true; }
468
-
469
- promise = $http(httpConfig);
470
- value.$resolved = false;
471
-
472
- promise.then(markResolved, markResolved);
473
- value.$then = promise.then(function(response) {
474
- var data = response.data;
475
- var then = value.$then, resolved = value.$resolved;
476
+ var promise = $http(httpConfig).then(function(response) {
477
+ var data = response.data,
478
+ promise = value.$promise;
476
479
 
477
480
  if (data) {
481
+ if ( angular.isArray(data) != !!action.isArray ) {
482
+ throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected response' +
483
+ ' to contain an {0} but got an {1}',
484
+ action.isArray?'array':'object', angular.isArray(data)?'array':'object');
485
+ }
478
486
  if (action.isArray) {
479
487
  value.length = 0;
480
488
  forEach(data, function(item) {
@@ -482,44 +490,47 @@ angular.module('ngResource', ['ng']).
482
490
  });
483
491
  } else {
484
492
  copy(data, value);
485
- value.$then = then;
486
- value.$resolved = resolved;
493
+ value.$promise = promise;
487
494
  }
488
495
  }
489
496
 
497
+ value.$resolved = true;
498
+
490
499
  (success||noop)(value, response.headers);
491
500
 
492
501
  response.resource = value;
502
+
493
503
  return response;
494
- }, error).then;
504
+ }, function(response) {
505
+ value.$resolved = true;
495
506
 
496
- return value;
497
- };
507
+ (error||noop)(response);
498
508
 
509
+ return $q.reject(response);
510
+ }).then(responseInterceptor, responseErrorInterceptor);
499
511
 
500
- Resource.prototype['$' + name] = function(a1, a2, a3) {
501
- var params = extractParams(this),
502
- success = noop,
503
- error;
504
512
 
505
- switch(arguments.length) {
506
- case 3: params = a1; success = a2; error = a3; break;
507
- case 2:
508
- case 1:
509
- if (isFunction(a1)) {
510
- success = a1;
511
- error = a2;
512
- } else {
513
- params = a1;
514
- success = a2 || noop;
515
- }
516
- case 0: break;
517
- default:
518
- throw "Expected between 1-3 arguments [params, success, error], got " +
519
- arguments.length + " arguments.";
513
+ if (!isInstanceCall) {
514
+ // we are creating instance / collection
515
+ // - set the initial promise
516
+ // - return the instance / collection
517
+ value.$promise = promise;
518
+ value.$resolved = false;
519
+
520
+ return value;
521
+ }
522
+
523
+ // instance call
524
+ return promise;
525
+ };
526
+
527
+
528
+ Resource.prototype['$' + name] = function(params, success, error) {
529
+ if (isFunction(params)) {
530
+ error = success; success = params; params = {};
520
531
  }
521
- var data = hasBody ? this : undefined;
522
- Resource[name].call(this, params, data, success, error);
532
+ var result = Resource[name](params, this, success, error);
533
+ return result.$promise || result;
523
534
  };
524
535
  });
525
536
 
@@ -1,11 +1,14 @@
1
1
  /*
2
- AngularJS v1.1.5
2
+ AngularJS v1.2.0rc1
3
3
  (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  License: MIT
5
5
  */
6
- (function(B,f,w){'use strict';f.module("ngResource",["ng"]).factory("$resource",["$http","$parse",function(x,y){function u(b,d){this.template=b;this.defaults=d||{};this.urlParams={}}function v(b,d,e){function j(c,b){var p={},b=m({},d,b);l(b,function(a,b){k(a)&&(a=a());var g;a&&a.charAt&&a.charAt(0)=="@"?(g=a.substr(1),g=y(g)(c)):g=a;p[b]=g});return p}function c(c){t(c||{},this)}var n=new u(b),e=m({},z,e);l(e,function(b,d){b.method=f.uppercase(b.method);var p=b.method=="POST"||b.method=="PUT"||b.method==
7
- "PATCH";c[d]=function(a,d,g,A){function f(){h.$resolved=!0}var i={},e,o=q,r=null;switch(arguments.length){case 4:r=A,o=g;case 3:case 2:if(k(d)){if(k(a)){o=a;r=d;break}o=d;r=g}else{i=a;e=d;o=g;break}case 1:k(a)?o=a:p?e=a:i=a;break;case 0:break;default:throw"Expected between 0-4 arguments [params, data, success, error], got "+arguments.length+" arguments.";}var h=this instanceof c?this:b.isArray?[]:new c(e),s={};l(b,function(a,b){b!="params"&&b!="isArray"&&(s[b]=t(a))});s.data=e;n.setUrlParams(s,m({},
8
- j(e,b.params||{}),i),b.url);i=x(s);h.$resolved=!1;i.then(f,f);h.$then=i.then(function(a){var d=a.data,g=h.$then,e=h.$resolved;if(d)b.isArray?(h.length=0,l(d,function(a){h.push(new c(a))})):(t(d,h),h.$then=g,h.$resolved=e);(o||q)(h,a.headers);a.resource=h;return a},r).then;return h};c.prototype["$"+d]=function(a,b,g){var e=j(this),f=q,i;switch(arguments.length){case 3:e=a;f=b;i=g;break;case 2:case 1:k(a)?(f=a,i=b):(e=a,f=b||q);case 0:break;default:throw"Expected between 1-3 arguments [params, success, error], got "+
9
- arguments.length+" arguments.";}c[d].call(this,e,p?this:w,f,i)}});c.bind=function(c){return v(b,m({},d,c),e)};return c}var z={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},q=f.noop,l=f.forEach,m=f.extend,t=f.copy,k=f.isFunction;u.prototype={setUrlParams:function(b,d,e){var j=this,c=e||j.template,n,k,m=j.urlParams={};l(c.split(/\W/),function(b){b&&RegExp("(^|[^\\\\]):"+b+"(\\W|$)").test(c)&&(m[b]=!0)});c=c.replace(/\\:/g,
10
- ":");d=d||{};l(j.urlParams,function(b,a){n=d.hasOwnProperty(a)?d[a]:j.defaults[a];f.isDefined(n)&&n!==null?(k=encodeURIComponent(n).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),c=c.replace(RegExp(":"+a+"(\\W|$)","g"),k+"$1")):c=c.replace(RegExp("(/?):"+a+"(\\W|$)","g"),function(b,a,c){return c.charAt(0)=="/"?c:a+c})});c=c.replace(/\/+$/,"");c=c.replace(/\/\.(?=\w+($|\?))/,".");
11
- b.url=c.replace(/\/\\\./,"/.");l(d,function(c,a){if(!j.urlParams[a])b.params=b.params||{},b.params[a]=c})}};return v}])})(window,window.angular);
6
+ (function(H,g,C){'use strict';var A=g.$$minErr("$resource");g.module("ngResource",["ng"]).factory("$resource",["$http","$parse","$q",function(D,y,E){function n(g,h){this.template=g;this.defaults=h||{};this.urlParams={}}function u(l,h,d){function p(c,b){var e={};b=v({},h,b);q(b,function(a,b){t(a)&&(a=a());var m;a&&a.charAt&&"@"==a.charAt(0)?(m=a.substr(1),m=y(m)(c)):m=a;e[b]=m});return e}function b(c){return c.resource}function e(c){z(c||{},this)}var F=new n(l);d=v({},G,d);q(d,function(c,f){var h=
7
+ /^(POST|PUT|PATCH)$/i.test(c.method);e[f]=function(a,f,m,l){var d={},r,s,w;switch(arguments.length){case 4:w=l,s=m;case 3:case 2:if(t(f)){if(t(a)){s=a;w=f;break}s=f;w=m}else{d=a;r=f;s=m;break}case 1:t(a)?s=a:h?r=a:d=a;break;case 0:break;default:throw A("badargs",arguments.length);}var n=r instanceof e,k=n?r:c.isArray?[]:new e(r),x={},u=c.interceptor&&c.interceptor.response||b,y=c.interceptor&&c.interceptor.responseError||C;q(c,function(a,c){"params"!=c&&("isArray"!=c&&"interceptor"!=c)&&(x[c]=z(a))});
8
+ x.data=r;F.setUrlParams(x,v({},p(r,c.params||{}),d),c.url);d=D(x).then(function(a){var b=a.data,f=k.$promise;if(b){if(g.isArray(b)!=!!c.isArray)throw A("badcfg",c.isArray?"array":"object",g.isArray(b)?"array":"object");c.isArray?(k.length=0,q(b,function(a){k.push(new e(a))})):(z(b,k),k.$promise=f)}k.$resolved=!0;(s||B)(k,a.headers);a.resource=k;return a},function(a){k.$resolved=!0;(w||B)(a);return E.reject(a)}).then(u,y);return n?d:(k.$promise=d,k.$resolved=!1,k)};e.prototype["$"+f]=function(a,c,
9
+ b){t(a)&&(b=c,c=a,a={});a=e[f](a,this,c,b);return a.$promise||a}});e.bind=function(c){return u(l,v({},h,c),d)};return e}var G={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},B=g.noop,q=g.forEach,v=g.extend,z=g.copy,t=g.isFunction;n.prototype={setUrlParams:function(l,h,d){var p=this,b=d||p.template,e,n,c=p.urlParams={};q(b.split(/\W/),function(f){!/^\d+$/.test(f)&&(f&&RegExp("(^|[^\\\\]):"+f+"(\\W|$)").test(b))&&(c[f]=!0)});
10
+ b=b.replace(/\\:/g,":");h=h||{};q(p.urlParams,function(c,d){e=h.hasOwnProperty(d)?h[d]:p.defaults[d];g.isDefined(e)&&null!==e?(n=encodeURIComponent(e).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),b=b.replace(RegExp(":"+d+"(\\W|$)","g"),n+"$1")):b=b.replace(RegExp("(/?):"+d+"(\\W|$)","g"),function(a,c,b){return"/"==b.charAt(0)?b:c+b})});b=b.replace(/\/+$/,"");b=b.replace(/\/\.(?=\w+($|\?))/,
11
+ ".");l.url=b.replace(/\/\\\./,"/.");q(h,function(c,b){p.urlParams[b]||(l.params=l.params||{},l.params[b]=c)})}};return u}])})(window,window.angular);
12
+ /*
13
+ //@ sourceMappingURL=angular-resource.min.js.map
14
+ */
@@ -0,0 +1,860 @@
1
+ /**
2
+ * @license AngularJS v1.2.0rc1
3
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
4
+ * License: MIT
5
+ */
6
+ (function(window, angular, undefined) {'use strict';
7
+
8
+ var copy = angular.copy,
9
+ equals = angular.equals,
10
+ extend = angular.extend,
11
+ forEach = angular.forEach,
12
+ isDefined = angular.isDefined,
13
+ isFunction = angular.isFunction,
14
+ isString = angular.isString,
15
+ jqLite = angular.element,
16
+ noop = angular.noop,
17
+ toJson = angular.toJson;
18
+
19
+
20
+ function inherit(parent, extra) {
21
+ return extend(new (extend(function() {}, {prototype:parent}))(), extra);
22
+ }
23
+
24
+ /**
25
+ * @ngdoc overview
26
+ * @name ngRoute
27
+ * @description
28
+ *
29
+ * Module that provides routing and deeplinking services and directives for angular apps.
30
+ */
31
+
32
+ var ngRouteModule = angular.module('ngRoute', ['ng']).
33
+ provider('$route', $RouteProvider);
34
+
35
+ /**
36
+ * @ngdoc object
37
+ * @name ngRoute.$routeProvider
38
+ * @function
39
+ *
40
+ * @description
41
+ *
42
+ * Used for configuring routes. See {@link ngRoute.$route $route} for an example.
43
+ */
44
+ function $RouteProvider(){
45
+ var routes = {};
46
+
47
+ /**
48
+ * @ngdoc method
49
+ * @name ngRoute.$routeProvider#when
50
+ * @methodOf ngRoute.$routeProvider
51
+ *
52
+ * @param {string} path Route path (matched against `$location.path`). If `$location.path`
53
+ * contains redundant trailing slash or is missing one, the route will still match and the
54
+ * `$location.path` will be updated to add or drop the trailing slash to exactly match the
55
+ * route definition.
56
+ *
57
+ * * `path` can contain named groups starting with a colon (`:name`). All characters up
58
+ * to the next slash are matched and stored in `$routeParams` under the given `name`
59
+ * when the route matches.
60
+ * * `path` can contain named groups starting with a colon and ending with a star (`:name*`).
61
+ * All characters are eagerly stored in `$routeParams` under the given `name`
62
+ * when the route matches.
63
+ * * `path` can contain optional named groups with a question mark (`:name?`).
64
+ *
65
+ * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
66
+ * `/color/brown/largecode/code/with/slashs/edit` and extract:
67
+ *
68
+ * * `color: brown`
69
+ * * `largecode: code/with/slashs`.
70
+ *
71
+ *
72
+ * @param {Object} route Mapping information to be assigned to `$route.current` on route
73
+ * match.
74
+ *
75
+ * Object properties:
76
+ *
77
+ * - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly
78
+ * created scope or the name of a {@link angular.Module#controller registered controller}
79
+ * if passed as a string.
80
+ * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
81
+ * published to scope under the `controllerAs` name.
82
+ * - `template` – `{string=|function()=}` – html template as a string or a function that
83
+ * returns an html template as a string which should be used by {@link
84
+ * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
85
+ * This property takes precedence over `templateUrl`.
86
+ *
87
+ * If `template` is a function, it will be called with the following parameters:
88
+ *
89
+ * - `{Array.<Object>}` - route parameters extracted from the current
90
+ * `$location.path()` by applying the current route
91
+ *
92
+ * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
93
+ * template that should be used by {@link ngRoute.directive:ngView ngView}.
94
+ *
95
+ * If `templateUrl` is a function, it will be called with the following parameters:
96
+ *
97
+ * - `{Array.<Object>}` - route parameters extracted from the current
98
+ * `$location.path()` by applying the current route
99
+ *
100
+ * - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
101
+ * be injected into the controller. If any of these dependencies are promises, they will be
102
+ * resolved and converted to a value before the controller is instantiated and the
103
+ * `$routeChangeSuccess` event is fired. The map object is:
104
+ *
105
+ * - `key` – `{string}`: a name of a dependency to be injected into the controller.
106
+ * - `factory` - `{string|function}`: If `string` then it is an alias for a service.
107
+ * Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}
108
+ * and the return value is treated as the dependency. If the result is a promise, it is resolved
109
+ * before its value is injected into the controller. Be aware that `ngRoute.$routeParams` will
110
+ * still refer to the previous route within these resolve functions. Use `$route.current.params`
111
+ * to access the new route parameters, instead.
112
+ *
113
+ * - `redirectTo` – {(string|function())=} – value to update
114
+ * {@link ng.$location $location} path with and trigger route redirection.
115
+ *
116
+ * If `redirectTo` is a function, it will be called with the following parameters:
117
+ *
118
+ * - `{Object.<string>}` - route parameters extracted from the current
119
+ * `$location.path()` by applying the current route templateUrl.
120
+ * - `{string}` - current `$location.path()`
121
+ * - `{Object}` - current `$location.search()`
122
+ *
123
+ * The custom `redirectTo` function is expected to return a string which will be used
124
+ * to update `$location.path()` and `$location.search()`.
125
+ *
126
+ * - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()
127
+ * changes.
128
+ *
129
+ * If the option is set to `false` and url in the browser changes, then
130
+ * `$routeUpdate` event is broadcasted on the root scope.
131
+ *
132
+ * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive
133
+ *
134
+ * If the option is set to `true`, then the particular route can be matched without being
135
+ * case sensitive
136
+ *
137
+ * @returns {Object} self
138
+ *
139
+ * @description
140
+ * Adds a new route definition to the `$route` service.
141
+ */
142
+ this.when = function(path, route) {
143
+ routes[path] = extend(
144
+ {reloadOnSearch: true},
145
+ route,
146
+ path && pathRegExp(path, route)
147
+ );
148
+
149
+ // create redirection for trailing slashes
150
+ if (path) {
151
+ var redirectPath = (path[path.length-1] == '/')
152
+ ? path.substr(0, path.length-1)
153
+ : path +'/';
154
+
155
+ routes[redirectPath] = extend(
156
+ {redirectTo: path},
157
+ pathRegExp(redirectPath, route)
158
+ );
159
+ }
160
+
161
+ return this;
162
+ };
163
+
164
+ /**
165
+ * @param path {string} path
166
+ * @param opts {Object} options
167
+ * @return {?Object}
168
+ *
169
+ * @description
170
+ * Normalizes the given path, returning a regular expression
171
+ * and the original path.
172
+ *
173
+ * Inspired by pathRexp in visionmedia/express/lib/utils.js.
174
+ */
175
+ function pathRegExp(path, opts) {
176
+ var insensitive = opts.caseInsensitiveMatch,
177
+ ret = {
178
+ originalPath: path,
179
+ regexp: path
180
+ },
181
+ keys = ret.keys = [];
182
+
183
+ path = path
184
+ .replace(/([().])/g, '\\$1')
185
+ .replace(/(\/)?:(\w+)([\?|\*])?/g, function(_, slash, key, option){
186
+ var optional = option === '?' ? option : null;
187
+ var star = option === '*' ? option : null;
188
+ keys.push({ name: key, optional: !!optional });
189
+ slash = slash || '';
190
+ return ''
191
+ + (optional ? '' : slash)
192
+ + '(?:'
193
+ + (optional ? slash : '')
194
+ + (star && '(.+)?' || '([^/]+)?') + ')'
195
+ + (optional || '');
196
+ })
197
+ .replace(/([\/$\*])/g, '\\$1');
198
+
199
+ ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
200
+ return ret;
201
+ }
202
+
203
+ /**
204
+ * @ngdoc method
205
+ * @name ngRoute.$routeProvider#otherwise
206
+ * @methodOf ngRoute.$routeProvider
207
+ *
208
+ * @description
209
+ * Sets route definition that will be used on route change when no other route definition
210
+ * is matched.
211
+ *
212
+ * @param {Object} params Mapping information to be assigned to `$route.current`.
213
+ * @returns {Object} self
214
+ */
215
+ this.otherwise = function(params) {
216
+ this.when(null, params);
217
+ return this;
218
+ };
219
+
220
+
221
+ this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache', '$sce',
222
+ function( $rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) {
223
+
224
+ /**
225
+ * @ngdoc object
226
+ * @name ngRoute.$route
227
+ * @requires $location
228
+ * @requires $routeParams
229
+ *
230
+ * @property {Object} current Reference to the current route definition.
231
+ * The route definition contains:
232
+ *
233
+ * - `controller`: The controller constructor as define in route definition.
234
+ * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
235
+ * controller instantiation. The `locals` contain
236
+ * the resolved values of the `resolve` map. Additionally the `locals` also contain:
237
+ *
238
+ * - `$scope` - The current route scope.
239
+ * - `$template` - The current route template HTML.
240
+ *
241
+ * @property {Array.<Object>} routes Array of all configured routes.
242
+ *
243
+ * @description
244
+ * Is used for deep-linking URLs to controllers and views (HTML partials).
245
+ * It watches `$location.url()` and tries to map the path to an existing route definition.
246
+ *
247
+ * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
248
+ *
249
+ * The `$route` service is typically used in conjunction with {@link ngRoute.directive:ngView ngView}
250
+ * directive and the {@link ngRoute.$routeParams $routeParams} service.
251
+ *
252
+ * @example
253
+ This example shows how changing the URL hash causes the `$route` to match a route against the
254
+ URL, and the `ngView` pulls in the partial.
255
+
256
+ Note that this example is using {@link ng.directive:script inlined templates}
257
+ to get it working on jsfiddle as well.
258
+
259
+ <example module="ngView" deps="angular-route.js">
260
+ <file name="index.html">
261
+ <div ng-controller="MainCntl">
262
+ Choose:
263
+ <a href="Book/Moby">Moby</a> |
264
+ <a href="Book/Moby/ch/1">Moby: Ch1</a> |
265
+ <a href="Book/Gatsby">Gatsby</a> |
266
+ <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
267
+ <a href="Book/Scarlet">Scarlet Letter</a><br/>
268
+
269
+ <div ng-view></div>
270
+ <hr />
271
+
272
+ <pre>$location.path() = {{$location.path()}}</pre>
273
+ <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
274
+ <pre>$route.current.params = {{$route.current.params}}</pre>
275
+ <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
276
+ <pre>$routeParams = {{$routeParams}}</pre>
277
+ </div>
278
+ </file>
279
+
280
+ <file name="book.html">
281
+ controller: {{name}}<br />
282
+ Book Id: {{params.bookId}}<br />
283
+ </file>
284
+
285
+ <file name="chapter.html">
286
+ controller: {{name}}<br />
287
+ Book Id: {{params.bookId}}<br />
288
+ Chapter Id: {{params.chapterId}}
289
+ </file>
290
+
291
+ <file name="script.js">
292
+ angular.module('ngView', ['ngRoute']).config(function($routeProvider, $locationProvider) {
293
+ $routeProvider.when('/Book/:bookId', {
294
+ templateUrl: 'book.html',
295
+ controller: BookCntl,
296
+ resolve: {
297
+ // I will cause a 1 second delay
298
+ delay: function($q, $timeout) {
299
+ var delay = $q.defer();
300
+ $timeout(delay.resolve, 1000);
301
+ return delay.promise;
302
+ }
303
+ }
304
+ });
305
+ $routeProvider.when('/Book/:bookId/ch/:chapterId', {
306
+ templateUrl: 'chapter.html',
307
+ controller: ChapterCntl
308
+ });
309
+
310
+ // configure html5 to get links working on jsfiddle
311
+ $locationProvider.html5Mode(true);
312
+ });
313
+
314
+ function MainCntl($scope, $route, $routeParams, $location) {
315
+ $scope.$route = $route;
316
+ $scope.$location = $location;
317
+ $scope.$routeParams = $routeParams;
318
+ }
319
+
320
+ function BookCntl($scope, $routeParams) {
321
+ $scope.name = "BookCntl";
322
+ $scope.params = $routeParams;
323
+ }
324
+
325
+ function ChapterCntl($scope, $routeParams) {
326
+ $scope.name = "ChapterCntl";
327
+ $scope.params = $routeParams;
328
+ }
329
+ </file>
330
+
331
+ <file name="scenario.js">
332
+ it('should load and compile correct template', function() {
333
+ element('a:contains("Moby: Ch1")').click();
334
+ var content = element('.doc-example-live [ng-view]').text();
335
+ expect(content).toMatch(/controller\: ChapterCntl/);
336
+ expect(content).toMatch(/Book Id\: Moby/);
337
+ expect(content).toMatch(/Chapter Id\: 1/);
338
+
339
+ element('a:contains("Scarlet")').click();
340
+ sleep(2); // promises are not part of scenario waiting
341
+ content = element('.doc-example-live [ng-view]').text();
342
+ expect(content).toMatch(/controller\: BookCntl/);
343
+ expect(content).toMatch(/Book Id\: Scarlet/);
344
+ });
345
+ </file>
346
+ </example>
347
+ */
348
+
349
+ /**
350
+ * @ngdoc event
351
+ * @name ngRoute.$route#$routeChangeStart
352
+ * @eventOf ngRoute.$route
353
+ * @eventType broadcast on root scope
354
+ * @description
355
+ * Broadcasted before a route change. At this point the route services starts
356
+ * resolving all of the dependencies needed for the route change to occurs.
357
+ * Typically this involves fetching the view template as well as any dependencies
358
+ * defined in `resolve` route property. Once all of the dependencies are resolved
359
+ * `$routeChangeSuccess` is fired.
360
+ *
361
+ * @param {Route} next Future route information.
362
+ * @param {Route} current Current route information.
363
+ */
364
+
365
+ /**
366
+ * @ngdoc event
367
+ * @name ngRoute.$route#$routeChangeSuccess
368
+ * @eventOf ngRoute.$route
369
+ * @eventType broadcast on root scope
370
+ * @description
371
+ * Broadcasted after a route dependencies are resolved.
372
+ * {@link ngRoute.directive:ngView ngView} listens for the directive
373
+ * to instantiate the controller and render the view.
374
+ *
375
+ * @param {Object} angularEvent Synthetic event object.
376
+ * @param {Route} current Current route information.
377
+ * @param {Route|Undefined} previous Previous route information, or undefined if current is first route entered.
378
+ */
379
+
380
+ /**
381
+ * @ngdoc event
382
+ * @name ngRoute.$route#$routeChangeError
383
+ * @eventOf ngRoute.$route
384
+ * @eventType broadcast on root scope
385
+ * @description
386
+ * Broadcasted if any of the resolve promises are rejected.
387
+ *
388
+ * @param {Route} current Current route information.
389
+ * @param {Route} previous Previous route information.
390
+ * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
391
+ */
392
+
393
+ /**
394
+ * @ngdoc event
395
+ * @name ngRoute.$route#$routeUpdate
396
+ * @eventOf ngRoute.$route
397
+ * @eventType broadcast on root scope
398
+ * @description
399
+ *
400
+ * The `reloadOnSearch` property has been set to false, and we are reusing the same
401
+ * instance of the Controller.
402
+ */
403
+
404
+ var forceReload = false,
405
+ $route = {
406
+ routes: routes,
407
+
408
+ /**
409
+ * @ngdoc method
410
+ * @name ngRoute.$route#reload
411
+ * @methodOf ngRoute.$route
412
+ *
413
+ * @description
414
+ * Causes `$route` service to reload the current route even if
415
+ * {@link ng.$location $location} hasn't changed.
416
+ *
417
+ * As a result of that, {@link ngRoute.directive:ngView ngView}
418
+ * creates new scope, reinstantiates the controller.
419
+ */
420
+ reload: function() {
421
+ forceReload = true;
422
+ $rootScope.$evalAsync(updateRoute);
423
+ }
424
+ };
425
+
426
+ $rootScope.$on('$locationChangeSuccess', updateRoute);
427
+
428
+ return $route;
429
+
430
+ /////////////////////////////////////////////////////
431
+
432
+ /**
433
+ * @param on {string} current url
434
+ * @param route {Object} route regexp to match the url against
435
+ * @return {?Object}
436
+ *
437
+ * @description
438
+ * Check if the route matches the current url.
439
+ *
440
+ * Inspired by match in
441
+ * visionmedia/express/lib/router/router.js.
442
+ */
443
+ function switchRouteMatcher(on, route) {
444
+ var keys = route.keys,
445
+ params = {};
446
+
447
+ if (!route.regexp) return null;
448
+
449
+ var m = route.regexp.exec(on);
450
+ if (!m) return null;
451
+
452
+ var N = 0;
453
+ for (var i = 1, len = m.length; i < len; ++i) {
454
+ var key = keys[i - 1];
455
+
456
+ var val = 'string' == typeof m[i]
457
+ ? decodeURIComponent(m[i])
458
+ : m[i];
459
+
460
+ if (key && val) {
461
+ params[key.name] = val;
462
+ }
463
+ }
464
+ return params;
465
+ }
466
+
467
+ function updateRoute() {
468
+ var next = parseRoute(),
469
+ last = $route.current;
470
+
471
+ if (next && last && next.$$route === last.$$route
472
+ && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {
473
+ last.params = next.params;
474
+ copy(last.params, $routeParams);
475
+ $rootScope.$broadcast('$routeUpdate', last);
476
+ } else if (next || last) {
477
+ forceReload = false;
478
+ $rootScope.$broadcast('$routeChangeStart', next, last);
479
+ $route.current = next;
480
+ if (next) {
481
+ if (next.redirectTo) {
482
+ if (isString(next.redirectTo)) {
483
+ $location.path(interpolate(next.redirectTo, next.params)).search(next.params)
484
+ .replace();
485
+ } else {
486
+ $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))
487
+ .replace();
488
+ }
489
+ }
490
+ }
491
+
492
+ $q.when(next).
493
+ then(function() {
494
+ if (next) {
495
+ var locals = extend({}, next.resolve),
496
+ template, templateUrl;
497
+
498
+ forEach(locals, function(value, key) {
499
+ locals[key] = isString(value) ? $injector.get(value) : $injector.invoke(value);
500
+ });
501
+
502
+ if (isDefined(template = next.template)) {
503
+ if (isFunction(template)) {
504
+ template = template(next.params);
505
+ }
506
+ } else if (isDefined(templateUrl = next.templateUrl)) {
507
+ if (isFunction(templateUrl)) {
508
+ templateUrl = templateUrl(next.params);
509
+ }
510
+ templateUrl = $sce.getTrustedResourceUrl(templateUrl);
511
+ if (isDefined(templateUrl)) {
512
+ next.loadedTemplateUrl = templateUrl;
513
+ template = $http.get(templateUrl, {cache: $templateCache}).
514
+ then(function(response) { return response.data; });
515
+ }
516
+ }
517
+ if (isDefined(template)) {
518
+ locals['$template'] = template;
519
+ }
520
+ return $q.all(locals);
521
+ }
522
+ }).
523
+ // after route change
524
+ then(function(locals) {
525
+ if (next == $route.current) {
526
+ if (next) {
527
+ next.locals = locals;
528
+ copy(next.params, $routeParams);
529
+ }
530
+ $rootScope.$broadcast('$routeChangeSuccess', next, last);
531
+ }
532
+ }, function(error) {
533
+ if (next == $route.current) {
534
+ $rootScope.$broadcast('$routeChangeError', next, last, error);
535
+ }
536
+ });
537
+ }
538
+ }
539
+
540
+
541
+ /**
542
+ * @returns the current active route, by matching it against the URL
543
+ */
544
+ function parseRoute() {
545
+ // Match a route
546
+ var params, match;
547
+ forEach(routes, function(route, path) {
548
+ if (!match && (params = switchRouteMatcher($location.path(), route))) {
549
+ match = inherit(route, {
550
+ params: extend({}, $location.search(), params),
551
+ pathParams: params});
552
+ match.$$route = route;
553
+ }
554
+ });
555
+ // No route matched; fallback to "otherwise" route
556
+ return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
557
+ }
558
+
559
+ /**
560
+ * @returns interpolation of the redirect path with the parameters
561
+ */
562
+ function interpolate(string, params) {
563
+ var result = [];
564
+ forEach((string||'').split(':'), function(segment, i) {
565
+ if (i == 0) {
566
+ result.push(segment);
567
+ } else {
568
+ var segmentMatch = segment.match(/(\w+)(.*)/);
569
+ var key = segmentMatch[1];
570
+ result.push(params[key]);
571
+ result.push(segmentMatch[2] || '');
572
+ delete params[key];
573
+ }
574
+ });
575
+ return result.join('');
576
+ }
577
+ }];
578
+ }
579
+
580
+ ngRouteModule.provider('$routeParams', $RouteParamsProvider);
581
+
582
+
583
+ /**
584
+ * @ngdoc object
585
+ * @name ngRoute.$routeParams
586
+ * @requires $route
587
+ *
588
+ * @description
589
+ * Current set of route parameters. The route parameters are a combination of the
590
+ * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters
591
+ * are extracted when the {@link ngRoute.$route $route} path is matched.
592
+ *
593
+ * In case of parameter name collision, `path` params take precedence over `search` params.
594
+ *
595
+ * The service guarantees that the identity of the `$routeParams` object will remain unchanged
596
+ * (but its properties will likely change) even when a route change occurs.
597
+ *
598
+ * Note that the `$routeParams` are only updated *after* a route change completes successfully.
599
+ * This means that you cannot rely on `$routeParams` being correct in route resolve functions.
600
+ * Instead you can use `$route.current.params` to access the new route's parameters.
601
+ *
602
+ * @example
603
+ * <pre>
604
+ * // Given:
605
+ * // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
606
+ * // Route: /Chapter/:chapterId/Section/:sectionId
607
+ * //
608
+ * // Then
609
+ * $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}
610
+ * </pre>
611
+ */
612
+ function $RouteParamsProvider() {
613
+ this.$get = function() { return {}; };
614
+ }
615
+
616
+ /**
617
+ * @ngdoc directive
618
+ * @name ngRoute.directive:ngView
619
+ * @restrict ECA
620
+ *
621
+ * @description
622
+ * # Overview
623
+ * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
624
+ * including the rendered template of the current route into the main layout (`index.html`) file.
625
+ * Every time the current route changes, the included view changes with it according to the
626
+ * configuration of the `$route` service.
627
+ *
628
+ * @animations
629
+ * enter - animation is used to bring new content into the browser.
630
+ * leave - animation is used to animate existing content away.
631
+ *
632
+ * The enter and leave animation occur concurrently.
633
+ *
634
+ * @scope
635
+ * @example
636
+ <example module="ngViewExample" deps="angular-route.js" animations="true">
637
+ <file name="index.html">
638
+ <div ng-controller="MainCntl as main">
639
+ Choose:
640
+ <a href="Book/Moby">Moby</a> |
641
+ <a href="Book/Moby/ch/1">Moby: Ch1</a> |
642
+ <a href="Book/Gatsby">Gatsby</a> |
643
+ <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
644
+ <a href="Book/Scarlet">Scarlet Letter</a><br/>
645
+
646
+ <div class="example-animate-container">
647
+ <div ng-view class="view-example"></div>
648
+ </div>
649
+ <hr />
650
+
651
+ <pre>$location.path() = {{main.$location.path()}}</pre>
652
+ <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
653
+ <pre>$route.current.params = {{main.$route.current.params}}</pre>
654
+ <pre>$route.current.scope.name = {{main.$route.current.scope.name}}</pre>
655
+ <pre>$routeParams = {{main.$routeParams}}</pre>
656
+ </div>
657
+ </file>
658
+
659
+ <file name="book.html">
660
+ <div>
661
+ controller: {{book.name}}<br />
662
+ Book Id: {{book.params.bookId}}<br />
663
+ </div>
664
+ </file>
665
+
666
+ <file name="chapter.html">
667
+ <div>
668
+ controller: {{chapter.name}}<br />
669
+ Book Id: {{chapter.params.bookId}}<br />
670
+ Chapter Id: {{chapter.params.chapterId}}
671
+ </div>
672
+ </file>
673
+
674
+ <file name="animations.css">
675
+ .example-animate-container {
676
+ position:relative;
677
+ background:white;
678
+ border:1px solid black;
679
+ height:40px;
680
+ overflow:hidden;
681
+ }
682
+
683
+ .example-animate-container > div {
684
+ padding:10px;
685
+ }
686
+
687
+ .view-example.ng-enter, .view-example.ng-leave {
688
+ -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
689
+ -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
690
+ -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
691
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
692
+
693
+ display:block;
694
+ width:100%;
695
+ border-left:1px solid black;
696
+
697
+ position:absolute;
698
+ top:0;
699
+ left:0;
700
+ right:0;
701
+ bottom:0;
702
+ padding:10px;
703
+ }
704
+
705
+ .example-animate-container {
706
+ position:relative;
707
+ height:100px;
708
+ }
709
+
710
+ .view-example.ng-enter {
711
+ left:100%;
712
+ }
713
+ .view-example.ng-enter.ng-enter-active {
714
+ left:0;
715
+ }
716
+
717
+ .view-example.ng-leave { }
718
+ .view-example.ng-leave.ng-leave-active {
719
+ left:-100%;
720
+ }
721
+ </file>
722
+
723
+ <file name="script.js">
724
+ angular.module('ngViewExample', ['ngRoute', 'ngAnimate'], function($routeProvider, $locationProvider) {
725
+ $routeProvider.when('/Book/:bookId', {
726
+ templateUrl: 'book.html',
727
+ controller: BookCntl,
728
+ controllerAs: 'book'
729
+ });
730
+ $routeProvider.when('/Book/:bookId/ch/:chapterId', {
731
+ templateUrl: 'chapter.html',
732
+ controller: ChapterCntl,
733
+ controllerAs: 'chapter'
734
+ });
735
+
736
+ // configure html5 to get links working on jsfiddle
737
+ $locationProvider.html5Mode(true);
738
+ });
739
+
740
+ function MainCntl($route, $routeParams, $location) {
741
+ this.$route = $route;
742
+ this.$location = $location;
743
+ this.$routeParams = $routeParams;
744
+ }
745
+
746
+ function BookCntl($routeParams) {
747
+ this.name = "BookCntl";
748
+ this.params = $routeParams;
749
+ }
750
+
751
+ function ChapterCntl($routeParams) {
752
+ this.name = "ChapterCntl";
753
+ this.params = $routeParams;
754
+ }
755
+ </file>
756
+
757
+ <file name="scenario.js">
758
+ it('should load and compile correct template', function() {
759
+ element('a:contains("Moby: Ch1")').click();
760
+ var content = element('.doc-example-live [ng-view]').text();
761
+ expect(content).toMatch(/controller\: ChapterCntl/);
762
+ expect(content).toMatch(/Book Id\: Moby/);
763
+ expect(content).toMatch(/Chapter Id\: 1/);
764
+
765
+ element('a:contains("Scarlet")').click();
766
+ content = element('.doc-example-live [ng-view]').text();
767
+ expect(content).toMatch(/controller\: BookCntl/);
768
+ expect(content).toMatch(/Book Id\: Scarlet/);
769
+ });
770
+ </file>
771
+ </example>
772
+ */
773
+
774
+
775
+ /**
776
+ * @ngdoc event
777
+ * @name ngRoute.directive:ngView#$viewContentLoaded
778
+ * @eventOf ngRoute.directive:ngView
779
+ * @eventType emit on the current ngView scope
780
+ * @description
781
+ * Emitted every time the ngView content is reloaded.
782
+ */
783
+ var NG_VIEW_PRIORITY = 500;
784
+ var ngViewDirective = ['$route', '$anchorScroll', '$compile', '$controller', '$animate',
785
+ function($route, $anchorScroll, $compile, $controller, $animate) {
786
+ return {
787
+ restrict: 'ECA',
788
+ terminal: true,
789
+ priority: NG_VIEW_PRIORITY,
790
+ compile: function(element, attr) {
791
+ var onloadExp = attr.onload || '';
792
+
793
+ element.html('');
794
+ var anchor = jqLite(document.createComment(' ngView '));
795
+ element.replaceWith(anchor);
796
+
797
+ return function(scope) {
798
+ var currentScope, currentElement;
799
+
800
+ scope.$on('$routeChangeSuccess', update);
801
+ update();
802
+
803
+ function cleanupLastView() {
804
+ if (currentScope) {
805
+ currentScope.$destroy();
806
+ currentScope = null;
807
+ }
808
+ if(currentElement) {
809
+ $animate.leave(currentElement);
810
+ currentElement = null;
811
+ }
812
+ }
813
+
814
+ function update() {
815
+ var locals = $route.current && $route.current.locals,
816
+ template = locals && locals.$template;
817
+
818
+ if (template) {
819
+ cleanupLastView();
820
+
821
+ currentScope = scope.$new();
822
+ currentElement = element.clone();
823
+ currentElement.html(template);
824
+ $animate.enter(currentElement, null, anchor);
825
+
826
+ var link = $compile(currentElement, false, NG_VIEW_PRIORITY - 1),
827
+ current = $route.current;
828
+
829
+ if (current.controller) {
830
+ locals.$scope = currentScope;
831
+ var controller = $controller(current.controller, locals);
832
+ if (current.controllerAs) {
833
+ currentScope[current.controllerAs] = controller;
834
+ }
835
+ currentElement.data('$ngControllerController', controller);
836
+ currentElement.children().data('$ngControllerController', controller);
837
+ }
838
+
839
+ current.scope = currentScope;
840
+
841
+ link(currentScope);
842
+
843
+ currentScope.$emit('$viewContentLoaded');
844
+ currentScope.$eval(onloadExp);
845
+
846
+ // $anchorScroll might listen on event...
847
+ $anchorScroll();
848
+ } else {
849
+ cleanupLastView();
850
+ }
851
+ }
852
+ }
853
+ }
854
+ };
855
+ }];
856
+
857
+ ngRouteModule.directive('ngView', ngViewDirective);
858
+
859
+
860
+ })(window, window.angular);