angular-gem 1.1.5 → 1.2.0

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