ionic-rails-engine 0.9.26.1 → 0.9.99.11

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * State-based routing for AngularJS
3
- * @version v0.2.7
3
+ * @version v0.2.10
4
4
  * @link http://angular-ui.github.com/
5
5
  * @license MIT License, http://www.opensource.org/licenses/MIT
6
6
  */
@@ -50,8 +50,7 @@ function ancestors(first, second) {
50
50
  var path = [];
51
51
 
52
52
  for (var n in first.path) {
53
- if (first.path[n] === "") continue;
54
- if (!second.path[n]) break;
53
+ if (first.path[n] !== second.path[n]) break;
55
54
  path.push(first.path[n]);
56
55
  }
57
56
  return path;
@@ -176,19 +175,98 @@ function filterByKeys(keys, values) {
176
175
  });
177
176
  return filtered;
178
177
  }
179
-
178
+ /**
179
+ * @ngdoc overview
180
+ * @name ui.router.util
181
+ *
182
+ * @description
183
+ * # ui.router.util sub-module
184
+ *
185
+ * This module is a dependency of other sub-modules. Do not include this module as a dependency
186
+ * in your angular app (use {@link ui.router} module instead).
187
+ *
188
+ */
180
189
  angular.module('ui.router.util', ['ng']);
190
+
191
+ /**
192
+ * @ngdoc overview
193
+ * @name ui.router.router
194
+ *
195
+ * @requires ui.router.util
196
+ *
197
+ * @description
198
+ * # ui.router.router sub-module
199
+ *
200
+ * This module is a dependency of other sub-modules. Do not include this module as a dependency
201
+ * in your angular app (use {@link ui.router} module instead).
202
+ */
181
203
  angular.module('ui.router.router', ['ui.router.util']);
204
+
205
+ /**
206
+ * @ngdoc overview
207
+ * @name ui.router.state
208
+ *
209
+ * @requires ui.router.router
210
+ * @requires ui.router.util
211
+ *
212
+ * @description
213
+ * # ui.router.state sub-module
214
+ *
215
+ * This module is a dependency of the main ui.router module. Do not include this module as a dependency
216
+ * in your angular app (use {@link ui.router} module instead).
217
+ *
218
+ */
182
219
  angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']);
220
+
221
+ /**
222
+ * @ngdoc overview
223
+ * @name ui.router
224
+ *
225
+ * @requires ui.router.state
226
+ *
227
+ * @description
228
+ * # ui.router
229
+ *
230
+ * ## The main module for ui.router
231
+ * There are several sub-modules included with the ui.router module, however only this module is needed
232
+ * as a dependency within your angular app. The other modules are for organization purposes.
233
+ *
234
+ * The modules are:
235
+ * * ui.router - the main "umbrella" module
236
+ * * ui.router.router -
237
+ *
238
+ * *You'll need to include **only** this module as the dependency within your angular app.*
239
+ *
240
+ * <pre>
241
+ * <!doctype html>
242
+ * <html ng-app="myApp">
243
+ * <head>
244
+ * <script src="js/angular.js"></script>
245
+ * <!-- Include the ui-router script -->
246
+ * <script src="js/angular-ui-router.min.js"></script>
247
+ * <script>
248
+ * // ...and add 'ui.router' as a dependency
249
+ * var myApp = angular.module('myApp', ['ui.router']);
250
+ * </script>
251
+ * </head>
252
+ * <body>
253
+ * </body>
254
+ * </html>
255
+ * </pre>
256
+ */
183
257
  angular.module('ui.router', ['ui.router.state']);
184
- angular.module('ui.router.compat', ['ui.router']);
185
258
 
259
+ angular.module('ui.router.compat', ['ui.router']);
186
260
 
187
261
  /**
188
- * Service (`ui-util`). Manages resolution of (acyclic) graphs of promises.
189
- * @module $resolve
262
+ * @ngdoc object
263
+ * @name ui.router.util.$resolve
264
+ *
190
265
  * @requires $q
191
266
  * @requires $injector
267
+ *
268
+ * @description
269
+ * Manages resolution of (acyclic) graphs of promises.
192
270
  */
193
271
  $Resolve.$inject = ['$q', '$injector'];
194
272
  function $Resolve( $q, $injector) {
@@ -202,15 +280,24 @@ function $Resolve( $q, $injector) {
202
280
 
203
281
 
204
282
  /**
283
+ * @ngdoc function
284
+ * @name ui.router.util.$resolve#study
285
+ * @methodOf ui.router.util.$resolve
286
+ *
287
+ * @description
205
288
  * Studies a set of invocables that are likely to be used multiple times.
206
- * $resolve.study(invocables)(locals, parent, self)
289
+ * <pre>
290
+ * $resolve.study(invocables)(locals, parent, self)
291
+ * </pre>
207
292
  * is equivalent to
208
- * $resolve.resolve(invocables, locals, parent, self)
209
- * but the former is more efficient (in fact `resolve` just calls `study` internally).
210
- * See {@link module:$resolve/resolve} for details.
211
- * @function
212
- * @param {Object} invocables
213
- * @return {Function}
293
+ * <pre>
294
+ * $resolve.resolve(invocables, locals, parent, self)
295
+ * </pre>
296
+ * but the former is more efficient (in fact `resolve` just calls `study`
297
+ * internally).
298
+ *
299
+ * @param {object} invocables Invocable objects
300
+ * @return {function} a function to pass in locals, parent and self
214
301
  */
215
302
  this.study = function (invocables) {
216
303
  if (!isObject(invocables)) throw new Error("'invocables' must be an object");
@@ -346,51 +433,65 @@ function $Resolve( $q, $injector) {
346
433
  };
347
434
 
348
435
  /**
349
- * Resolves a set of invocables. An invocable is a function to be invoked via `$injector.invoke()`,
350
- * and can have an arbitrary number of dependencies. An invocable can either return a value directly,
351
- * or a `$q` promise. If a promise is returned it will be resolved and the resulting value will be
352
- * used instead. Dependencies of invocables are resolved (in this order of precedence)
436
+ * @ngdoc function
437
+ * @name ui.router.util.$resolve#resolve
438
+ * @methodOf ui.router.util.$resolve
439
+ *
440
+ * @description
441
+ * Resolves a set of invocables. An invocable is a function to be invoked via
442
+ * `$injector.invoke()`, and can have an arbitrary number of dependencies.
443
+ * An invocable can either return a value directly,
444
+ * or a `$q` promise. If a promise is returned it will be resolved and the
445
+ * resulting value will be used instead. Dependencies of invocables are resolved
446
+ * (in this order of precedence)
353
447
  *
354
448
  * - from the specified `locals`
355
449
  * - from another invocable that is part of this `$resolve` call
356
- * - from an invocable that is inherited from a `parent` call to `$resolve` (or recursively
357
- * from any ancestor `$resolve` of that parent).
450
+ * - from an invocable that is inherited from a `parent` call to `$resolve`
451
+ * (or recursively
452
+ * - from any ancestor `$resolve` of that parent).
358
453
  *
359
- * The return value of `$resolve` is a promise for an object that contains (in this order of precedence)
454
+ * The return value of `$resolve` is a promise for an object that contains
455
+ * (in this order of precedence)
360
456
  *
361
457
  * - any `locals` (if specified)
362
458
  * - the resolved return values of all injectables
363
459
  * - any values inherited from a `parent` call to `$resolve` (if specified)
364
460
  *
365
- * The promise will resolve after the `parent` promise (if any) and all promises returned by injectables
366
- * have been resolved. If any invocable (or `$injector.invoke`) throws an exception, or if a promise
367
- * returned by an invocable is rejected, the `$resolve` promise is immediately rejected with the same error.
368
- * A rejection of a `parent` promise (if specified) will likewise be propagated immediately. Once the
369
- * `$resolve` promise has been rejected, no further invocables will be called.
461
+ * The promise will resolve after the `parent` promise (if any) and all promises
462
+ * returned by injectables have been resolved. If any invocable
463
+ * (or `$injector.invoke`) throws an exception, or if a promise returned by an
464
+ * invocable is rejected, the `$resolve` promise is immediately rejected with the
465
+ * same error. A rejection of a `parent` promise (if specified) will likewise be
466
+ * propagated immediately. Once the `$resolve` promise has been rejected, no
467
+ * further invocables will be called.
370
468
  *
371
- * Cyclic dependencies between invocables are not permitted and will caues `$resolve` to throw an
372
- * error. As a special case, an injectable can depend on a parameter with the same name as the injectable,
373
- * which will be fulfilled from the `parent` injectable of the same name. This allows inherited values
374
- * to be decorated. Note that in this case any other injectable in the same `$resolve` with the same
469
+ * Cyclic dependencies between invocables are not permitted and will caues `$resolve`
470
+ * to throw an error. As a special case, an injectable can depend on a parameter
471
+ * with the same name as the injectable, which will be fulfilled from the `parent`
472
+ * injectable of the same name. This allows inherited values to be decorated.
473
+ * Note that in this case any other injectable in the same `$resolve` with the same
375
474
  * dependency would see the decorated value, not the inherited value.
376
475
  *
377
- * Note that missing dependencies -- unlike cyclic dependencies -- will cause an (asynchronous) rejection
378
- * of the `$resolve` promise rather than a (synchronous) exception.
476
+ * Note that missing dependencies -- unlike cyclic dependencies -- will cause an
477
+ * (asynchronous) rejection of the `$resolve` promise rather than a (synchronous)
478
+ * exception.
379
479
  *
380
- * Invocables are invoked eagerly as soon as all dependencies are available. This is true even for
381
- * dependencies inherited from a `parent` call to `$resolve`.
480
+ * Invocables are invoked eagerly as soon as all dependencies are available.
481
+ * This is true even for dependencies inherited from a `parent` call to `$resolve`.
382
482
  *
383
- * As a special case, an invocable can be a string, in which case it is taken to be a service name
384
- * to be passed to `$injector.get()`. This is supported primarily for backwards-compatibility with the
385
- * `resolve` property of `$routeProvider` routes.
483
+ * As a special case, an invocable can be a string, in which case it is taken to
484
+ * be a service name to be passed to `$injector.get()`. This is supported primarily
485
+ * for backwards-compatibility with the `resolve` property of `$routeProvider`
486
+ * routes.
386
487
  *
387
- * @function
388
- * @param {Object.<string, Function|string>} invocables functions to invoke or `$injector` services to fetch.
389
- * @param {Object.<string, *>} [locals] values to make available to the injectables
390
- * @param {Promise.<Object>} [parent] a promise returned by another call to `$resolve`.
391
- * @param {Object} [self] the `this` for the invoked methods
392
- * @return {Promise.<Object>} Promise for an object that contains the resolved return value
393
- * of all invocables, as well as any inherited and local values.
488
+ * @param {object} invocables functions to invoke or
489
+ * `$injector` services to fetch.
490
+ * @param {object} locals values to make available to the injectables
491
+ * @param {object} parent a promise returned by another call to `$resolve`.
492
+ * @param {object} self the `this` for the invoked methods
493
+ * @return {object} Promise for an object that contains the resolved return value
494
+ * of all invocables, as well as any inherited and local values.
394
495
  */
395
496
  this.resolve = function (invocables, locals, parent, self) {
396
497
  return this.study(invocables)(locals, parent, self);
@@ -401,35 +502,43 @@ angular.module('ui.router.util').service('$resolve', $Resolve);
401
502
 
402
503
 
403
504
  /**
404
- * Service. Manages loading of templates.
405
- * @constructor
406
- * @name $templateFactory
505
+ * @ngdoc object
506
+ * @name ui.router.util.$templateFactory
507
+ *
407
508
  * @requires $http
408
509
  * @requires $templateCache
409
510
  * @requires $injector
511
+ *
512
+ * @description
513
+ * Service. Manages loading of templates.
410
514
  */
411
515
  $TemplateFactory.$inject = ['$http', '$templateCache', '$injector'];
412
516
  function $TemplateFactory( $http, $templateCache, $injector) {
413
517
 
414
518
  /**
519
+ * @ngdoc function
520
+ * @name ui.router.util.$templateFactory#fromConfig
521
+ * @methodOf ui.router.util.$templateFactory
522
+ *
523
+ * @description
415
524
  * Creates a template from a configuration object.
416
- * @function
417
- * @name $templateFactory#fromConfig
418
- * @methodOf $templateFactory
419
- * @param {Object} config Configuration object for which to load a template. The following
420
- * properties are search in the specified order, and the first one that is defined is
421
- * used to create the template:
422
- * @param {string|Function} config.template html string template or function to load via
423
- * {@link $templateFactory#fromString fromString}.
424
- * @param {string|Function} config.templateUrl url to load or a function returning the url
425
- * to load via {@link $templateFactory#fromUrl fromUrl}.
426
- * @param {Function} config.templateProvider function to invoke via
427
- * {@link $templateFactory#fromProvider fromProvider}.
428
- * @param {Object} params Parameters to pass to the template function.
429
- * @param {Object} [locals] Locals to pass to `invoke` if the template is loaded via a
430
- * `templateProvider`. Defaults to `{ params: params }`.
431
- * @return {string|Promise.<string>} The template html as a string, or a promise for that string,
432
- * or `null` if no template is configured.
525
+ *
526
+ * @param {object} config Configuration object for which to load a template.
527
+ * The following properties are search in the specified order, and the first one
528
+ * that is defined is used to create the template:
529
+ *
530
+ * @param {string|object} config.template html string template or function to
531
+ * load via {@link ui.router.util.$templateFactory#fromString fromString}.
532
+ * @param {string|object} config.templateUrl url to load or a function returning
533
+ * the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}.
534
+ * @param {Function} config.templateProvider function to invoke via
535
+ * {@link ui.router.util.$templateFactory#fromProvider fromProvider}.
536
+ * @param {object} params Parameters to pass to the template function.
537
+ * @param {object} locals Locals to pass to `invoke` if the template is loaded
538
+ * via a `templateProvider`. Defaults to `{ params: params }`.
539
+ *
540
+ * @return {string|object} The template html as a string, or a promise for
541
+ * that string,or `null` if no template is configured.
433
542
  */
434
543
  this.fromConfig = function (config, params, locals) {
435
544
  return (
@@ -441,27 +550,37 @@ function $TemplateFactory( $http, $templateCache, $injector) {
441
550
  };
442
551
 
443
552
  /**
553
+ * @ngdoc function
554
+ * @name ui.router.util.$templateFactory#fromString
555
+ * @methodOf ui.router.util.$templateFactory
556
+ *
557
+ * @description
444
558
  * Creates a template from a string or a function returning a string.
445
- * @function
446
- * @name $templateFactory#fromString
447
- * @methodOf $templateFactory
448
- * @param {string|Function} template html template as a string or function that returns an html
449
- * template as a string.
450
- * @param {Object} params Parameters to pass to the template function.
451
- * @return {string|Promise.<string>} The template html as a string, or a promise for that string.
559
+ *
560
+ * @param {string|object} template html template as a string or function that
561
+ * returns an html template as a string.
562
+ * @param {object} params Parameters to pass to the template function.
563
+ *
564
+ * @return {string|object} The template html as a string, or a promise for that
565
+ * string.
452
566
  */
453
567
  this.fromString = function (template, params) {
454
568
  return isFunction(template) ? template(params) : template;
455
569
  };
456
570
 
457
571
  /**
572
+ * @ngdoc function
573
+ * @name ui.router.util.$templateFactory#fromUrl
574
+ * @methodOf ui.router.util.$templateFactory
575
+ *
576
+ * @description
458
577
  * Loads a template from the a URL via `$http` and `$templateCache`.
459
- * @function
460
- * @name $templateFactory#fromUrl
461
- * @methodOf $templateFactory
462
- * @param {string|Function} url url of the template to load, or a function that returns a url.
463
- * @param {Object} params Parameters to pass to the url function.
464
- * @return {string|Promise.<string>} The template html as a string, or a promise for that string.
578
+ *
579
+ * @param {string|Function} url url of the template to load, or a function
580
+ * that returns a url.
581
+ * @param {Object} params Parameters to pass to the url function.
582
+ * @return {string|Promise.<string>} The template html as a string, or a promise
583
+ * for that string.
465
584
  */
466
585
  this.fromUrl = function (url, params) {
467
586
  if (isFunction(url)) url = url(params);
@@ -472,14 +591,19 @@ function $TemplateFactory( $http, $templateCache, $injector) {
472
591
  };
473
592
 
474
593
  /**
594
+ * @ngdoc function
595
+ * @name ui.router.util.$templateFactory#fromUrl
596
+ * @methodOf ui.router.util.$templateFactory
597
+ *
598
+ * @description
475
599
  * Creates a template by invoking an injectable provider function.
476
- * @function
477
- * @name $templateFactory#fromUrl
478
- * @methodOf $templateFactory
600
+ *
479
601
  * @param {Function} provider Function to invoke via `$injector.invoke`
480
602
  * @param {Object} params Parameters for the template.
481
- * @param {Object} [locals] Locals to pass to `invoke`. Defaults to `{ params: params }`.
482
- * @return {string|Promise.<string>} The template html as a string, or a promise for that string.
603
+ * @param {Object} locals Locals to pass to `invoke`. Defaults to
604
+ * `{ params: params }`.
605
+ * @return {string|Promise.<string>} The template html as a string, or a promise
606
+ * for that string.
483
607
  */
484
608
  this.fromProvider = function (provider, params, locals) {
485
609
  return $injector.invoke(provider, null, locals || { params: params });
@@ -489,19 +613,23 @@ function $TemplateFactory( $http, $templateCache, $injector) {
489
613
  angular.module('ui.router.util').service('$templateFactory', $TemplateFactory);
490
614
 
491
615
  /**
616
+ * @ngdoc object
617
+ * @name ui.router.util.type:UrlMatcher
618
+ *
619
+ * @description
492
620
  * Matches URLs against patterns and extracts named parameters from the path or the search
493
621
  * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list
494
622
  * of search parameters. Multiple search parameter names are separated by '&'. Search parameters
495
623
  * do not influence whether or not a URL is matched, but their values are passed through into
496
- * the matched parameters returned by {@link UrlMatcher#exec exec}.
624
+ * the matched parameters returned by {@link ui.router.util.type:UrlMatcher#methods_exec exec}.
497
625
  *
498
626
  * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace
499
627
  * syntax, which optionally allows a regular expression for the parameter to be specified:
500
628
  *
501
- * * ':' name - colon placeholder
502
- * * '*' name - catch-all placeholder
503
- * * '{' name '}' - curly placeholder
504
- * * '{' name ':' regexp '}' - curly placeholder with regexp. Should the regexp itself contain
629
+ * * `':'` name - colon placeholder
630
+ * * `'*'` name - catch-all placeholder
631
+ * * `'{' name '}'` - curly placeholder
632
+ * * `'{' name ':' regexp '}'` - curly placeholder with regexp. Should the regexp itself contain
505
633
  * curly braces, they must be in matched pairs or escaped with a backslash.
506
634
  *
507
635
  * Parameter names may contain only word characters (latin letters, digits, and underscore) and
@@ -510,26 +638,36 @@ angular.module('ui.router.util').service('$templateFactory', $TemplateFactory);
510
638
  * number of characters other than '/'. For catch-all placeholders the path parameter matches
511
639
  * any number of characters.
512
640
  *
513
- * ### Examples
641
+ * Examples:
514
642
  *
515
- * * '/hello/' - Matches only if the path is exactly '/hello/'. There is no special treatment for
643
+ * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for
516
644
  * trailing slashes, and patterns have to match the entire path, not just a prefix.
517
- * * '/user/:id' - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or
645
+ * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or
518
646
  * '/user/bob/details'. The second path segment will be captured as the parameter 'id'.
519
- * * '/user/{id}' - Same as the previous example, but using curly brace syntax.
520
- * * '/user/{id:[^/]*}' - Same as the previous example.
521
- * * '/user/{id:[0-9a-fA-F]{1,8}}' - Similar to the previous example, but only matches if the id
647
+ * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax.
648
+ * * `'/user/{id:[^/]*}'` - Same as the previous example.
649
+ * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id
522
650
  * parameter consists of 1 to 8 hex digits.
523
- * * '/files/{path:.*}' - Matches any URL starting with '/files/' and captures the rest of the
651
+ * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the
524
652
  * path into the parameter 'path'.
525
- * * '/files/*path' - ditto.
653
+ * * `'/files/*path'` - ditto.
526
654
  *
527
- * @constructor
528
655
  * @param {string} pattern the pattern to compile into a matcher.
529
656
  *
530
657
  * @property {string} prefix A static prefix of this pattern. The matcher guarantees that any
531
- * URL matching this matcher (i.e. any string for which {@link UrlMatcher#exec exec()} returns
658
+ * URL matching this matcher (i.e. any string for which {@link ui.router.util.type:UrlMatcher#methods_exec exec()} returns
532
659
  * non-null) will start with this prefix.
660
+ *
661
+ * @property {string} source The pattern that was passed into the contructor
662
+ *
663
+ * @property {string} sourcePath The path portion of the source property
664
+ *
665
+ * @property {string} sourceSearch The search portion of the source property
666
+ *
667
+ * @property {string} regex The constructed regex that will be used to match against the url when
668
+ * it is time to determine which url will match.
669
+ *
670
+ * @returns {Object} New UrlMatcher object
533
671
  */
534
672
  function UrlMatcher(pattern) {
535
673
 
@@ -600,12 +738,17 @@ function UrlMatcher(pattern) {
600
738
  }
601
739
 
602
740
  /**
741
+ * @ngdoc function
742
+ * @name ui.router.util.type:UrlMatcher#concat
743
+ * @methodOf ui.router.util.type:UrlMatcher
744
+ *
745
+ * @description
603
746
  * Returns a new matcher for a pattern constructed by appending the path part and adding the
604
747
  * search parameters of the specified pattern to this pattern. The current pattern is not
605
748
  * modified. This can be understood as creating a pattern for URLs that are relative to (or
606
749
  * suffixes of) the current pattern.
607
750
  *
608
- * ### Example
751
+ * @example
609
752
  * The following two matchers are equivalent:
610
753
  * ```
611
754
  * new UrlMatcher('/user/{id}?q').concat('/details?date');
@@ -613,7 +756,7 @@ function UrlMatcher(pattern) {
613
756
  * ```
614
757
  *
615
758
  * @param {string} pattern The pattern to append.
616
- * @return {UrlMatcher} A matcher for the concatenated pattern.
759
+ * @returns {ui.router.util.type:UrlMatcher} A matcher for the concatenated pattern.
617
760
  */
618
761
  UrlMatcher.prototype.concat = function (pattern) {
619
762
  // Because order of search parameters is irrelevant, we can add our own search
@@ -627,13 +770,18 @@ UrlMatcher.prototype.toString = function () {
627
770
  };
628
771
 
629
772
  /**
773
+ * @ngdoc function
774
+ * @name ui.router.util.type:UrlMatcher#exec
775
+ * @methodOf ui.router.util.type:UrlMatcher
776
+ *
777
+ * @description
630
778
  * Tests the specified path against this matcher, and returns an object containing the captured
631
779
  * parameter values, or null if the path does not match. The returned object contains the values
632
780
  * of any search parameters that are mentioned in the pattern, but their value may be null if
633
781
  * they are not present in `searchParams`. This means that search parameters are always treated
634
782
  * as optional.
635
783
  *
636
- * ### Example
784
+ * @example
637
785
  * ```
638
786
  * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', { x:'1', q:'hello' });
639
787
  * // returns { id:'bob', q:'hello', r:null }
@@ -641,7 +789,7 @@ UrlMatcher.prototype.toString = function () {
641
789
  *
642
790
  * @param {string} path The URL path to match, e.g. `$location.path()`.
643
791
  * @param {Object} searchParams URL search parameters, e.g. `$location.search()`.
644
- * @return {Object} The captured parameter values.
792
+ * @returns {Object} The captured parameter values.
645
793
  */
646
794
  UrlMatcher.prototype.exec = function (path, searchParams) {
647
795
  var m = this.regexp.exec(path);
@@ -660,8 +808,14 @@ UrlMatcher.prototype.exec = function (path, searchParams) {
660
808
  };
661
809
 
662
810
  /**
811
+ * @ngdoc function
812
+ * @name ui.router.util.type:UrlMatcher#parameters
813
+ * @methodOf ui.router.util.type:UrlMatcher
814
+ *
815
+ * @description
663
816
  * Returns the names of all path and search parameters of this pattern in an unspecified order.
664
- * @return {Array.<string>} An array of parameter names. Must be treated as read-only. If the
817
+ *
818
+ * @returns {Array.<string>} An array of parameter names. Must be treated as read-only. If the
665
819
  * pattern has no parameters, an empty array is returned.
666
820
  */
667
821
  UrlMatcher.prototype.parameters = function () {
@@ -669,18 +823,23 @@ UrlMatcher.prototype.parameters = function () {
669
823
  };
670
824
 
671
825
  /**
826
+ * @ngdoc function
827
+ * @name ui.router.util.type:UrlMatcher#format
828
+ * @methodOf ui.router.util.type:UrlMatcher
829
+ *
830
+ * @description
672
831
  * Creates a URL that matches this pattern by substituting the specified values
673
832
  * for the path and search parameters. Null values for path parameters are
674
833
  * treated as empty strings.
675
834
  *
676
- * ### Example
835
+ * @example
677
836
  * ```
678
837
  * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
679
838
  * // returns '/user/bob?q=yes'
680
839
  * ```
681
840
  *
682
841
  * @param {Object} values the values to substitute for the parameters in this pattern.
683
- * @return {string} the formatted URL (path and optionally search part).
842
+ * @returns {string} the formatted URL (path and optionally search part).
684
843
  */
685
844
  UrlMatcher.prototype.format = function (values) {
686
845
  var segments = this.segments, params = this.params;
@@ -706,37 +865,49 @@ UrlMatcher.prototype.format = function (values) {
706
865
  return result;
707
866
  };
708
867
 
868
+
869
+
709
870
  /**
710
- * Service. Factory for {@link UrlMatcher} instances. The factory is also available to providers
871
+ * @ngdoc object
872
+ * @name ui.router.util.$urlMatcherFactory
873
+ *
874
+ * @description
875
+ * Factory for {@link ui.router.util.type:UrlMatcher} instances. The factory is also available to providers
711
876
  * under the name `$urlMatcherFactoryProvider`.
712
- * @constructor
713
- * @name $urlMatcherFactory
714
877
  */
715
878
  function $UrlMatcherFactory() {
879
+
716
880
  /**
717
- * Creates a {@link UrlMatcher} for the specified pattern.
718
- * @function
719
- * @name $urlMatcherFactory#compile
720
- * @methodOf $urlMatcherFactory
881
+ * @ngdoc function
882
+ * @name ui.router.util.$urlMatcherFactory#compile
883
+ * @methodOf ui.router.util.$urlMatcherFactory
884
+ *
885
+ * @description
886
+ * Creates a {@link ui.router.util.type:UrlMatcher} for the specified pattern.
887
+ *
721
888
  * @param {string} pattern The URL pattern.
722
- * @return {UrlMatcher} The UrlMatcher.
889
+ * @returns {ui.router.util.type:UrlMatcher} The UrlMatcher.
723
890
  */
724
891
  this.compile = function (pattern) {
725
892
  return new UrlMatcher(pattern);
726
893
  };
727
894
 
728
895
  /**
896
+ * @ngdoc function
897
+ * @name ui.router.util.$urlMatcherFactory#isMatcher
898
+ * @methodOf ui.router.util.$urlMatcherFactory
899
+ *
900
+ * @description
729
901
  * Returns true if the specified object is a UrlMatcher, or false otherwise.
730
- * @function
731
- * @name $urlMatcherFactory#isMatcher
732
- * @methodOf $urlMatcherFactory
733
- * @param {Object} o
734
- * @return {boolean}
902
+ *
903
+ * @param {Object} object The object to perform the type check against.
904
+ * @returns {Boolean} Returns `true` if the object has the following functions: `exec`, `format`, and `concat`.
735
905
  */
736
906
  this.isMatcher = function (o) {
737
907
  return isObject(o) && isFunction(o.exec) && isFunction(o.format) && isFunction(o.concat);
738
908
  };
739
-
909
+
910
+ /* No need to document $get, since it returns this */
740
911
  this.$get = function () {
741
912
  return this;
742
913
  };
@@ -745,7 +916,21 @@ function $UrlMatcherFactory() {
745
916
  // Register as a provider so it's available to other providers
746
917
  angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory);
747
918
 
748
-
919
+ /**
920
+ * @ngdoc object
921
+ * @name ui.router.router.$urlRouterProvider
922
+ *
923
+ * @requires ui.router.util.$urlMatcherFactoryProvider
924
+ *
925
+ * @description
926
+ * `$urlRouterProvider` has the responsibility of watching `$location`.
927
+ * When `$location` changes it runs through a list of rules one by one until a
928
+ * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify
929
+ * a url in a state configuration. All urls are compiled into a UrlMatcher object.
930
+ *
931
+ * There are several methods on `$urlRouterProvider` that make it useful to use directly
932
+ * in your module config.
933
+ */
749
934
  $UrlRouterProvider.$inject = ['$urlMatcherFactoryProvider'];
750
935
  function $UrlRouterProvider( $urlMatcherFactory) {
751
936
  var rules = [],
@@ -764,6 +949,37 @@ function $UrlRouterProvider( $urlMatcherFactory) {
764
949
  });
765
950
  }
766
951
 
952
+ /**
953
+ * @ngdoc function
954
+ * @name ui.router.router.$urlRouterProvider#rule
955
+ * @methodOf ui.router.router.$urlRouterProvider
956
+ *
957
+ * @description
958
+ * Defines rules that are used by `$urlRouterProvider to find matches for
959
+ * specific URLs.
960
+ *
961
+ * @example
962
+ * <pre>
963
+ * var app = angular.module('app', ['ui.router.router']);
964
+ *
965
+ * app.config(function ($urlRouterProvider) {
966
+ * // Here's an example of how you might allow case insensitive urls
967
+ * $urlRouterProvider.rule(function ($injector, $location) {
968
+ * var path = $location.path(),
969
+ * normalized = path.toLowerCase();
970
+ *
971
+ * if (path !== normalized) {
972
+ * return normalized;
973
+ * }
974
+ * });
975
+ * });
976
+ * </pre>
977
+ *
978
+ * @param {object} rule Handler function that takes `$injector` and `$location`
979
+ * services as arguments. You can use them to return a valid path as a string.
980
+ *
981
+ * @return {object} $urlRouterProvider - $urlRouterProvider instance
982
+ */
767
983
  this.rule =
768
984
  function (rule) {
769
985
  if (!isFunction(rule)) throw new Error("'rule' must be a function");
@@ -771,6 +987,37 @@ function $UrlRouterProvider( $urlMatcherFactory) {
771
987
  return this;
772
988
  };
773
989
 
990
+ /**
991
+ * @ngdoc object
992
+ * @name ui.router.router.$urlRouterProvider#otherwise
993
+ * @methodOf ui.router.router.$urlRouterProvider
994
+ *
995
+ * @description
996
+ * Defines a path that is used when an invalied route is requested.
997
+ *
998
+ * @example
999
+ * <pre>
1000
+ * var app = angular.module('app', ['ui.router.router']);
1001
+ *
1002
+ * app.config(function ($urlRouterProvider) {
1003
+ * // if the path doesn't match any of the urls you configured
1004
+ * // otherwise will take care of routing the user to the
1005
+ * // specified url
1006
+ * $urlRouterProvider.otherwise('/index');
1007
+ *
1008
+ * // Example of using function rule as param
1009
+ * $urlRouterProvider.otherwise(function ($injector, $location) {
1010
+ * ...
1011
+ * });
1012
+ * });
1013
+ * </pre>
1014
+ *
1015
+ * @param {string|object} rule The url path you want to redirect to or a function
1016
+ * rule that returns the url path. The function version is passed two params:
1017
+ * `$injector` and `$location` services.
1018
+ *
1019
+ * @return {object} $urlRouterProvider - $urlRouterProvider instance
1020
+ */
774
1021
  this.otherwise =
775
1022
  function (rule) {
776
1023
  if (isString(rule)) {
@@ -789,6 +1036,43 @@ function $UrlRouterProvider( $urlMatcherFactory) {
789
1036
  return isDefined(result) ? result : true;
790
1037
  }
791
1038
 
1039
+ /**
1040
+ * @ngdoc function
1041
+ * @name ui.router.router.$urlRouterProvider#when
1042
+ * @methodOf ui.router.router.$urlRouterProvider
1043
+ *
1044
+ * @description
1045
+ * Registers a handler for a given url matching. if handle is a string, it is
1046
+ * treated as a redirect, and is interpolated according to the syyntax of match
1047
+ * (i.e. like String.replace() for RegExp, or like a UrlMatcher pattern otherwise).
1048
+ *
1049
+ * If the handler is a function, it is injectable. It gets invoked if `$location`
1050
+ * matches. You have the option of inject the match object as `$match`.
1051
+ *
1052
+ * The handler can return
1053
+ *
1054
+ * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter`
1055
+ * will continue trying to find another one that matches.
1056
+ * - **string** which is treated as a redirect and passed to `$location.url()`
1057
+ * - **void** or any **truthy** value tells `$urlRouter` that the url was handled.
1058
+ *
1059
+ * @example
1060
+ * <pre>
1061
+ * var app = angular.module('app', ['ui.router.router']);
1062
+ *
1063
+ * app.config(function ($urlRouterProvider) {
1064
+ * $urlRouterProvider.when($state.url, function ($match, $stateParams) {
1065
+ * if ($state.$current.navigable !== state ||
1066
+ * !equalForKeys($match, $stateParams) {
1067
+ * $state.transitionTo(state, $match, false);
1068
+ * }
1069
+ * });
1070
+ * });
1071
+ * </pre>
1072
+ *
1073
+ * @param {string|object} what The incoming path that you want to redirect.
1074
+ * @param {string|object} handler The path you want to redirect your user to.
1075
+ */
792
1076
  this.when =
793
1077
  function (what, handler) {
794
1078
  var redirect, handlerIsString = isString(handler);
@@ -835,6 +1119,17 @@ function $UrlRouterProvider( $urlMatcherFactory) {
835
1119
  throw new Error("invalid 'what' in when()");
836
1120
  };
837
1121
 
1122
+ /**
1123
+ * @ngdoc object
1124
+ * @name ui.router.router.$urlRouter
1125
+ *
1126
+ * @requires $location
1127
+ * @requires $rootScope
1128
+ * @requires $injector
1129
+ *
1130
+ * @description
1131
+ *
1132
+ */
838
1133
  this.$get =
839
1134
  [ '$location', '$rootScope', '$injector',
840
1135
  function ($location, $rootScope, $injector) {
@@ -860,6 +1155,32 @@ function $UrlRouterProvider( $urlMatcherFactory) {
860
1155
  $rootScope.$on('$locationChangeSuccess', update);
861
1156
 
862
1157
  return {
1158
+ /**
1159
+ * @ngdoc function
1160
+ * @name ui.router.router.$urlRouter#sync
1161
+ * @methodOf ui.router.router.$urlRouter
1162
+ *
1163
+ * @description
1164
+ * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`.
1165
+ * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event,
1166
+ * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed
1167
+ * with the transition by calling `$urlRouter.sync()`.
1168
+ *
1169
+ * @example
1170
+ * <pre>
1171
+ * angular.module('app', ['ui.router']);
1172
+ * .run(function($rootScope, $urlRouter) {
1173
+ * $rootScope.$on('$locationChangeSuccess', function(evt) {
1174
+ * // Halt state change from even starting
1175
+ * evt.preventDefault();
1176
+ * // Perform custom logic
1177
+ * var meetsRequirement = ...
1178
+ * // Continue with the update and state transition if logic allows
1179
+ * if (meetsRequirement) $urlRouter.sync();
1180
+ * });
1181
+ * });
1182
+ * </pre>
1183
+ */
863
1184
  sync: function () {
864
1185
  update();
865
1186
  }
@@ -869,6 +1190,28 @@ function $UrlRouterProvider( $urlMatcherFactory) {
869
1190
 
870
1191
  angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider);
871
1192
 
1193
+ /**
1194
+ * @ngdoc object
1195
+ * @name ui.router.state.$stateProvider
1196
+ *
1197
+ * @requires ui.router.router.$urlRouterProvider
1198
+ * @requires ui.router.util.$urlMatcherFactoryProvider
1199
+ * @requires $locationProvider
1200
+ *
1201
+ * @description
1202
+ * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely
1203
+ * on state.
1204
+ *
1205
+ * A state corresponds to a "place" in the application in terms of the overall UI and
1206
+ * navigation. A state describes (via the controller / template / view properties) what
1207
+ * the UI looks like and does at that place.
1208
+ *
1209
+ * States often have things in common, and the primary way of factoring out these
1210
+ * commonalities in this model is via the state hierarchy, i.e. parent/child states aka
1211
+ * nested states.
1212
+ *
1213
+ * The `$stateProvider` provides interfaces to declare these states for your app.
1214
+ */
872
1215
  $StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider', '$locationProvider'];
873
1216
  function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $locationProvider) {
874
1217
 
@@ -1067,6 +1410,41 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1067
1410
  return state;
1068
1411
  }
1069
1412
 
1413
+ // Checks text to see if it looks like a glob.
1414
+ function isGlob (text) {
1415
+ return text.indexOf('*') > -1;
1416
+ }
1417
+
1418
+ // Returns true if glob matches current $state name.
1419
+ function doesStateMatchGlob (glob) {
1420
+ var globSegments = glob.split('.'),
1421
+ segments = $state.$current.name.split('.');
1422
+
1423
+ //match greedy starts
1424
+ if (globSegments[0] === '**') {
1425
+ segments = segments.slice(segments.indexOf(globSegments[1]));
1426
+ segments.unshift('**');
1427
+ }
1428
+ //match greedy ends
1429
+ if (globSegments[globSegments.length - 1] === '**') {
1430
+ segments.splice(segments.indexOf(globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE);
1431
+ segments.push('**');
1432
+ }
1433
+
1434
+ if (globSegments.length != segments.length) {
1435
+ return false;
1436
+ }
1437
+
1438
+ //match single stars
1439
+ for (var i = 0, l = globSegments.length; i < l; i++) {
1440
+ if (globSegments[i] === '*') {
1441
+ segments[i] = '*';
1442
+ }
1443
+ }
1444
+
1445
+ return segments.join('') === globSegments.join('');
1446
+ }
1447
+
1070
1448
 
1071
1449
  // Implicit root state that is always active
1072
1450
  root = registerState({
@@ -1078,9 +1456,96 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1078
1456
  root.navigable = null;
1079
1457
 
1080
1458
 
1081
- // .decorator()
1082
- // .decorator(name)
1083
- // .decorator(name, function)
1459
+ /**
1460
+ * @ngdoc function
1461
+ * @name ui.router.state.$stateProvider#decorator
1462
+ * @methodOf ui.router.state.$stateProvider
1463
+ *
1464
+ * @description
1465
+ * Allows you to extend (carefully) or override (at your own peril) the
1466
+ * `stateBuilder` object used internally by `$stateProvider`. This can be used
1467
+ * to add custom functionality to ui-router, for example inferring templateUrl
1468
+ * based on the state name.
1469
+ *
1470
+ * When passing only a name, it returns the current (original or decorated) builder
1471
+ * function that matches `name`.
1472
+ *
1473
+ * The builder functions that can be decorated are listed below. Though not all
1474
+ * necessarily have a good use case for decoration, that is up to you to decide.
1475
+ *
1476
+ * In addition, users can attach custom decorators, which will generate new
1477
+ * properties within the state's internal definition. There is currently no clear
1478
+ * use-case for this beyond accessing internal states (i.e. $state.$current),
1479
+ * however, expect this to become increasingly relevant as we introduce additional
1480
+ * meta-programming features.
1481
+ *
1482
+ * **Warning**: Decorators should not be interdependent because the order of
1483
+ * execution of the builder functions in non-deterministic. Builder functions
1484
+ * should only be dependent on the state definition object and super function.
1485
+ *
1486
+ *
1487
+ * Existing builder functions and current return values:
1488
+ *
1489
+ * - **parent** `{object}` - returns the parent state object.
1490
+ * - **data** `{object}` - returns state data, including any inherited data that is not
1491
+ * overridden by own values (if any).
1492
+ * - **url** `{object}` - returns a {link ui.router.util.type:UrlMatcher} or null.
1493
+ * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is
1494
+ * navigable).
1495
+ * - **params** `{object}` - returns an array of state params that are ensured to
1496
+ * be a super-set of parent's params.
1497
+ * - **views** `{object}` - returns a views object where each key is an absolute view
1498
+ * name (i.e. "viewName@stateName") and each value is the config object
1499
+ * (template, controller) for the view. Even when you don't use the views object
1500
+ * explicitly on a state config, one is still created for you internally.
1501
+ * So by decorating this builder function you have access to decorating template
1502
+ * and controller properties.
1503
+ * - **ownParams** `{object}` - returns an array of params that belong to the state,
1504
+ * not including any params defined by ancestor states.
1505
+ * - **path** `{string}` - returns the full path from the root down to this state.
1506
+ * Needed for state activation.
1507
+ * - **includes** `{object}` - returns an object that includes every state that
1508
+ * would pass a '$state.includes()' test.
1509
+ *
1510
+ * @example
1511
+ * <pre>
1512
+ * // Override the internal 'views' builder with a function that takes the state
1513
+ * // definition, and a reference to the internal function being overridden:
1514
+ * $stateProvider.decorator('views', function ($state, parent) {
1515
+ * var result = {},
1516
+ * views = parent(state);
1517
+ *
1518
+ * angular.forEach(view, function (config, name) {
1519
+ * var autoName = (state.name + '.' + name).replace('.', '/');
1520
+ * config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
1521
+ * result[name] = config;
1522
+ * });
1523
+ * return result;
1524
+ * });
1525
+ *
1526
+ * $stateProvider.state('home', {
1527
+ * views: {
1528
+ * 'contact.list': { controller: 'ListController' },
1529
+ * 'contact.item': { controller: 'ItemController' }
1530
+ * }
1531
+ * });
1532
+ *
1533
+ * // ...
1534
+ *
1535
+ * $state.go('home');
1536
+ * // Auto-populates list and item views with /partials/home/contact/list.html,
1537
+ * // and /partials/home/contact/item.html, respectively.
1538
+ * </pre>
1539
+ *
1540
+ * @param {string} name The name of the builder function to decorate.
1541
+ * @param {object} func A function that is responsible for decorating the original
1542
+ * builder function. The function receives two parameters:
1543
+ *
1544
+ * - `{object}` - state - The state config object.
1545
+ * - `{object}` - super - The original builder function.
1546
+ *
1547
+ * @return {object} $stateProvider - $stateProvider instance
1548
+ */
1084
1549
  this.decorator = decorator;
1085
1550
  function decorator(name, func) {
1086
1551
  /*jshint validthis: true */
@@ -1097,8 +1562,138 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1097
1562
  return this;
1098
1563
  }
1099
1564
 
1100
- // .state(state)
1101
- // .state(name, state)
1565
+ /**
1566
+ * @ngdoc function
1567
+ * @name ui.router.state.$stateProvider#state
1568
+ * @methodOf ui.router.state.$stateProvider
1569
+ *
1570
+ * @description
1571
+ * Registers a state configuration under a given state name. The stateConfig object
1572
+ * has the following acceptable properties.
1573
+ *
1574
+ * <a id='template'></a>
1575
+ *
1576
+ * - **`template`** - {string|function=} - html template as a string or a function that returns
1577
+ * an html template as a string which should be used by the uiView directives. This property
1578
+ * takes precedence over templateUrl.
1579
+ *
1580
+ * If `template` is a function, it will be called with the following parameters:
1581
+ *
1582
+ * - {array.&lt;object&gt;} - state parameters extracted from the current $location.path() by
1583
+ * applying the current state
1584
+ *
1585
+ * <a id='templateUrl'></a>
1586
+ *
1587
+ * - **`templateUrl`** - {string|function=} - path or function that returns a path to an html
1588
+ * template that should be used by uiView.
1589
+ *
1590
+ * If `templateUrl` is a function, it will be called with the following parameters:
1591
+ *
1592
+ * - {array.&lt;object&gt;} - state parameters extracted from the current $location.path() by
1593
+ * applying the current state
1594
+ *
1595
+ * <a id='templateProvider'></a>
1596
+ *
1597
+ * - **`templateProvider`** - {function=} - Provider function that returns HTML content
1598
+ * string.
1599
+ *
1600
+ * <a id='controller'></a>
1601
+ *
1602
+ * - **`controller`** - {string|function=} - Controller fn that should be associated with newly
1603
+ * related scope or the name of a registered controller if passed as a string.
1604
+ *
1605
+ * <a id='controllerProvider'></a>
1606
+ *
1607
+ * - **`controllerProvider`** - {function=} - Injectable provider function that returns
1608
+ * the actual controller or string.
1609
+ *
1610
+ * <a id='controllerAs'></a>
1611
+ *
1612
+ * - **`controllerAs`** – {string=} – A controller alias name. If present the controller will be
1613
+ * published to scope under the controllerAs name.
1614
+ *
1615
+ * <a id='resolve'></a>
1616
+ *
1617
+ * - **`resolve`** - {object.&lt;string, function&gt;=} - An optional map of dependencies which
1618
+ * should be injected into the controller. If any of these dependencies are promises,
1619
+ * the router will wait for them all to be resolved or one to be rejected before the
1620
+ * controller is instantiated. If all the promises are resolved successfully, the values
1621
+ * of the resolved promises are injected and $stateChangeSuccess event is fired. If any
1622
+ * of the promises are rejected the $stateChangeError event is fired. The map object is:
1623
+ *
1624
+ * - key - {string}: name of dependency to be injected into controller
1625
+ * - factory - {string|function}: If string then it is alias for service. Otherwise if function,
1626
+ * it is injected and return value it treated as dependency. If result is a promise, it is
1627
+ * resolved before its value is injected into controller.
1628
+ *
1629
+ * <a id='url'></a>
1630
+ *
1631
+ * - **`url`** - {string=} - A url with optional parameters. When a state is navigated or
1632
+ * transitioned to, the `$stateParams` service will be populated with any
1633
+ * parameters that were passed.
1634
+ *
1635
+ * <a id='params'></a>
1636
+ *
1637
+ * - **`params`** - {object=} - An array of parameter names or regular expressions. Only
1638
+ * use this within a state if you are not using url. Otherwise you can specify your
1639
+ * parameters within the url. When a state is navigated or transitioned to, the
1640
+ * $stateParams service will be populated with any parameters that were passed.
1641
+ *
1642
+ * <a id='views'></a>
1643
+ *
1644
+ * - **`views`** - {object=} - Use the views property to set up multiple views or to target views
1645
+ * manually/explicitly.
1646
+ *
1647
+ * <a id='abstract'></a>
1648
+ *
1649
+ * - **`abstract`** - {boolean=} - An abstract state will never be directly activated,
1650
+ * but can provide inherited properties to its common children states.
1651
+ *
1652
+ * <a id='onEnter'></a>
1653
+ *
1654
+ * - **`onEnter`** - {object=} - Callback function for when a state is entered. Good way
1655
+ * to trigger an action or dispatch an event, such as opening a dialog.
1656
+ *
1657
+ * <a id='onExit'></a>
1658
+ *
1659
+ * - **`onExit`** - {object=} - Callback function for when a state is exited. Good way to
1660
+ * trigger an action or dispatch an event, such as opening a dialog.
1661
+ *
1662
+ * <a id='reloadOnSearch'></a>
1663
+ *
1664
+ * - **`reloadOnSearch = true`** - {boolean=} - If `false`, will not retrigger the same state
1665
+ * just because a search/query parameter has changed (via $location.search() or $location.hash()).
1666
+ * Useful for when you'd like to modify $location.search() without triggering a reload.
1667
+ *
1668
+ * <a id='data'></a>
1669
+ *
1670
+ * - **`data`** - {object=} - Arbitrary data object, useful for custom configuration.
1671
+ *
1672
+ * @example
1673
+ * <pre>
1674
+ * // Some state name examples
1675
+ *
1676
+ * // stateName can be a single top-level name (must be unique).
1677
+ * $stateProvider.state("home", {});
1678
+ *
1679
+ * // Or it can be a nested state name. This state is a child of the
1680
+ * // above "home" state.
1681
+ * $stateProvider.state("home.newest", {});
1682
+ *
1683
+ * // Nest states as deeply as needed.
1684
+ * $stateProvider.state("home.newest.abc.xyz.inception", {});
1685
+ *
1686
+ * // state() returns $stateProvider, so you can chain state declarations.
1687
+ * $stateProvider
1688
+ * .state("home", {})
1689
+ * .state("about", {})
1690
+ * .state("contacts", {});
1691
+ * </pre>
1692
+ *
1693
+ * @param {string} name A unique state name, e.g. "home", "about", "contacts".
1694
+ * To create a parent/child state use a dot, e.g. "about.sales", "home.newest".
1695
+ * @param {object} definition State configuration object.
1696
+ */
1102
1697
  this.state = state;
1103
1698
  function state(name, definition) {
1104
1699
  /*jshint validthis: true */
@@ -1108,16 +1703,40 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1108
1703
  return this;
1109
1704
  }
1110
1705
 
1706
+ /**
1707
+ * @ngdoc object
1708
+ * @name ui.router.state.$state
1709
+ *
1710
+ * @requires $rootScope
1711
+ * @requires $q
1712
+ * @requires ui.router.state.$view
1713
+ * @requires $injector
1714
+ * @requires ui.router.util.$resolve
1715
+ * @requires ui.router.state.$stateParams
1716
+ *
1717
+ * @property {object} params A param object, e.g. {sectionId: section.id)}, that
1718
+ * you'd like to test against the current active state.
1719
+ * @property {object} current A reference to the state's config object. However
1720
+ * you passed it in. Useful for accessing custom data.
1721
+ * @property {object} transition Currently pending transition. A promise that'll
1722
+ * resolve or reject.
1723
+ *
1724
+ * @description
1725
+ * `$state` service is responsible for representing states as well as transitioning
1726
+ * between them. It also provides interfaces to ask for current state or even states
1727
+ * you're coming from.
1728
+ */
1111
1729
  // $urlRouter is injected just to ensure it gets instantiated
1112
1730
  this.$get = $get;
1113
- $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$location', '$urlRouter'];
1114
- function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $location, $urlRouter) {
1731
+ $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$location', '$urlRouter', '$browser'];
1732
+ function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $location, $urlRouter, $browser) {
1115
1733
 
1116
1734
  var TransitionSuperseded = $q.reject(new Error('transition superseded'));
1117
1735
  var TransitionPrevented = $q.reject(new Error('transition prevented'));
1118
1736
  var TransitionAborted = $q.reject(new Error('transition aborted'));
1119
1737
  var TransitionFailed = $q.reject(new Error('transition failed'));
1120
1738
  var currentLocation = $location.url();
1739
+ var baseHref = $browser.baseHref();
1121
1740
 
1122
1741
  function syncUrl() {
1123
1742
  if ($location.url() !== currentLocation) {
@@ -1134,14 +1753,145 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1134
1753
  transition: null
1135
1754
  };
1136
1755
 
1756
+ /**
1757
+ * @ngdoc function
1758
+ * @name ui.router.state.$state#reload
1759
+ * @methodOf ui.router.state.$state
1760
+ *
1761
+ * @description
1762
+ * A method that force reloads the current state. All resolves are re-resolved, events are not re-fired,
1763
+ * and controllers reinstantiated (bug with controllers reinstantiating right now, fixing soon).
1764
+ *
1765
+ * @example
1766
+ * <pre>
1767
+ * var app angular.module('app', ['ui.router']);
1768
+ *
1769
+ * app.controller('ctrl', function ($scope, $state) {
1770
+ * $scope.reload = function(){
1771
+ * $state.reload();
1772
+ * }
1773
+ * });
1774
+ * </pre>
1775
+ *
1776
+ * `reload()` is just an alias for:
1777
+ * <pre>
1778
+ * $state.transitionTo($state.current, $stateParams, {
1779
+ * reload: true, inherit: false, notify: false
1780
+ * });
1781
+ * </pre>
1782
+ */
1137
1783
  $state.reload = function reload() {
1138
1784
  $state.transitionTo($state.current, $stateParams, { reload: true, inherit: false, notify: false });
1139
1785
  };
1140
1786
 
1787
+ /**
1788
+ * @ngdoc function
1789
+ * @name ui.router.state.$state#go
1790
+ * @methodOf ui.router.state.$state
1791
+ *
1792
+ * @description
1793
+ * Convenience method for transitioning to a new state. `$state.go` calls
1794
+ * `$state.transitionTo` internally but automatically sets options to
1795
+ * `{ location: true, inherit: true, relative: $state.$current, notify: true }`.
1796
+ * This allows you to easily use an absolute or relative to path and specify
1797
+ * only the parameters you'd like to update (while letting unspecified parameters
1798
+ * inherit from the currently active ancestor states).
1799
+ *
1800
+ * @example
1801
+ * <pre>
1802
+ * var app = angular.module('app', ['ui.router']);
1803
+ *
1804
+ * app.controller('ctrl', function ($scope, $state) {
1805
+ * $scope.changeState = function () {
1806
+ * $state.go('contact.detail');
1807
+ * };
1808
+ * });
1809
+ * </pre>
1810
+ * <img src='../ngdoc_assets/StateGoExamples.png'/>
1811
+ *
1812
+ * @param {string} to Absolute state name or relative state path. Some examples:
1813
+ *
1814
+ * - `$state.go('contact.detail')` - will go to the `contact.detail` state
1815
+ * - `$state.go('^')` - will go to a parent state
1816
+ * - `$state.go('^.sibling')` - will go to a sibling state
1817
+ * - `$state.go('.child.grandchild')` - will go to grandchild state
1818
+ *
1819
+ * @param {object=} params A map of the parameters that will be sent to the state,
1820
+ * will populate $stateParams. Any parameters that are not specified will be inherited from currently
1821
+ * defined parameters. This allows, for example, going to a sibling state that shares parameters
1822
+ * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e.
1823
+ * transitioning to a sibling will get you the parameters for all parents, transitioning to a child
1824
+ * will get you all current parameters, etc.
1825
+ * @param {object=} options Options object. The options are:
1826
+ *
1827
+ * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false`
1828
+ * will not. If string, must be `"replace"`, which will update url and also replace last history record.
1829
+ * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url.
1830
+ * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'),
1831
+ * defines which state to be relative from.
1832
+ * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.
1833
+ * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params
1834
+ * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd
1835
+ * use this when you want to force a reload when *everything* is the same, including search params.
1836
+ *
1837
+ * @returns {promise} A promise representing the state of the new transition.
1838
+ *
1839
+ * Possible success values:
1840
+ *
1841
+ * - $state.current
1842
+ *
1843
+ * <br/>Possible rejection values:
1844
+ *
1845
+ * - 'transition superseded' - when a newer transition has been started after this one
1846
+ * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener
1847
+ * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or
1848
+ * when a `$stateNotFound` `event.retry` promise errors.
1849
+ * - 'transition failed' - when a state has been unsuccessfully found after 2 tries.
1850
+ * - *resolve error* - when an error has occurred with a `resolve`
1851
+ *
1852
+ */
1141
1853
  $state.go = function go(to, params, options) {
1142
1854
  return this.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options));
1143
1855
  };
1144
1856
 
1857
+ /**
1858
+ * @ngdoc function
1859
+ * @name ui.router.state.$state#transitionTo
1860
+ * @methodOf ui.router.state.$state
1861
+ *
1862
+ * @description
1863
+ * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go}
1864
+ * uses `transitionTo` internally. `$state.go` is recommended in most situations.
1865
+ *
1866
+ * @example
1867
+ * <pre>
1868
+ * var app = angular.module('app', ['ui.router']);
1869
+ *
1870
+ * app.controller('ctrl', function ($scope, $state) {
1871
+ * $scope.changeState = function () {
1872
+ * $state.transitionTo('contact.detail');
1873
+ * };
1874
+ * });
1875
+ * </pre>
1876
+ *
1877
+ * @param {string} to State name.
1878
+ * @param {object=} toParams A map of the parameters that will be sent to the state,
1879
+ * will populate $stateParams.
1880
+ * @param {object=} options Options object. The options are:
1881
+ *
1882
+ * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false`
1883
+ * will not. If string, must be `"replace"`, which will update url and also replace last history record.
1884
+ * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url.
1885
+ * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'),
1886
+ * defines which state to be relative from.
1887
+ * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.
1888
+ * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params
1889
+ * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd
1890
+ * use this when you want to force a reload when *everything* is the same, including search params.
1891
+ *
1892
+ * @returns {promise} A promise representing the state of the new transition. See
1893
+ * {@link ui.router.state.$state#methods_go $state.go}.
1894
+ */
1145
1895
  $state.transitionTo = function transitionTo(to, toParams, options) {
1146
1896
  toParams = toParams || {};
1147
1897
  options = extend({
@@ -1154,6 +1904,39 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1154
1904
  if (!isDefined(toState)) {
1155
1905
  // Broadcast not found event and abort the transition if prevented
1156
1906
  var redirect = { to: to, toParams: toParams, options: options };
1907
+
1908
+ /**
1909
+ * @ngdoc event
1910
+ * @name ui.router.state.$state#$stateNotFound
1911
+ * @eventOf ui.router.state.$state
1912
+ * @eventType broadcast on root scope
1913
+ * @description
1914
+ * Fired when a requested state **cannot be found** using the provided state name during transition.
1915
+ * The event is broadcast allowing any handlers a single chance to deal with the error (usually by
1916
+ * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler,
1917
+ * you can see its three properties in the example. You can use `event.preventDefault()` to abort the
1918
+ * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value.
1919
+ *
1920
+ * @param {Object} event Event object.
1921
+ * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties.
1922
+ * @param {State} fromState Current state object.
1923
+ * @param {Object} fromParams Current state params.
1924
+ *
1925
+ * @example
1926
+ *
1927
+ * <pre>
1928
+ * // somewhere, assume lazy.state has not been defined
1929
+ * $state.go("lazy.state", {a:1, b:2}, {inherit:false});
1930
+ *
1931
+ * // somewhere else
1932
+ * $scope.$on('$stateNotFound',
1933
+ * function(event, unfoundState, fromState, fromParams){
1934
+ * console.log(unfoundState.to); // "lazy.state"
1935
+ * console.log(unfoundState.toParams); // {a:1, b:2}
1936
+ * console.log(unfoundState.options); // {inherit:false} + default options
1937
+ * })
1938
+ * </pre>
1939
+ */
1157
1940
  evt = $rootScope.$broadcast('$stateNotFound', redirect, from.self, fromParams);
1158
1941
  if (evt.defaultPrevented) {
1159
1942
  syncUrl();
@@ -1219,6 +2002,33 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1219
2002
 
1220
2003
  // Broadcast start event and cancel the transition if requested
1221
2004
  if (options.notify) {
2005
+ /**
2006
+ * @ngdoc event
2007
+ * @name ui.router.state.$state#$stateChangeStart
2008
+ * @eventOf ui.router.state.$state
2009
+ * @eventType broadcast on root scope
2010
+ * @description
2011
+ * Fired when the state transition **begins**. You can use `event.preventDefault()`
2012
+ * to prevent the transition from happening and then the transition promise will be
2013
+ * rejected with a `'transition prevented'` value.
2014
+ *
2015
+ * @param {Object} event Event object.
2016
+ * @param {State} toState The state being transitioned to.
2017
+ * @param {Object} toParams The params supplied to the `toState`.
2018
+ * @param {State} fromState The current state, pre-transition.
2019
+ * @param {Object} fromParams The params supplied to the `fromState`.
2020
+ *
2021
+ * @example
2022
+ *
2023
+ * <pre>
2024
+ * $rootScope.$on('$stateChangeStart',
2025
+ * function(event, toState, toParams, fromState, fromParams){
2026
+ * event.preventDefault();
2027
+ * // transitionTo() promise will be rejected with
2028
+ * // a 'transition prevented' error
2029
+ * })
2030
+ * </pre>
2031
+ */
1222
2032
  evt = $rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams);
1223
2033
  if (evt.defaultPrevented) {
1224
2034
  syncUrl();
@@ -1287,6 +2097,20 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1287
2097
  }
1288
2098
 
1289
2099
  if (options.notify) {
2100
+ /**
2101
+ * @ngdoc event
2102
+ * @name ui.router.state.$state#$stateChangeSuccess
2103
+ * @eventOf ui.router.state.$state
2104
+ * @eventType broadcast on root scope
2105
+ * @description
2106
+ * Fired once the state transition is **complete**.
2107
+ *
2108
+ * @param {Object} event Event object.
2109
+ * @param {State} toState The state being transitioned to.
2110
+ * @param {Object} toParams The params supplied to the `toState`.
2111
+ * @param {State} fromState The current state, pre-transition.
2112
+ * @param {Object} fromParams The params supplied to the `fromState`.
2113
+ */
1290
2114
  $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams);
1291
2115
  }
1292
2116
  currentLocation = $location.url();
@@ -1296,6 +2120,24 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1296
2120
  if ($state.transition !== transition) return TransitionSuperseded;
1297
2121
 
1298
2122
  $state.transition = null;
2123
+ /**
2124
+ * @ngdoc event
2125
+ * @name ui.router.state.$state#$stateChangeError
2126
+ * @eventOf ui.router.state.$state
2127
+ * @eventType broadcast on root scope
2128
+ * @description
2129
+ * Fired when an **error occurs** during transition. It's important to note that if you
2130
+ * have any errors in your resolve functions (javascript errors, non-existent services, etc)
2131
+ * they will not throw traditionally. You must listen for this $stateChangeError event to
2132
+ * catch **ALL** errors.
2133
+ *
2134
+ * @param {Object} event Event object.
2135
+ * @param {State} toState The state being transitioned to.
2136
+ * @param {Object} toParams The params supplied to the `toState`.
2137
+ * @param {State} fromState The current state, pre-transition.
2138
+ * @param {Object} fromParams The params supplied to the `fromState`.
2139
+ * @param {Error} error The resolve error object.
2140
+ */
1299
2141
  $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error);
1300
2142
  syncUrl();
1301
2143
 
@@ -1305,6 +2147,30 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1305
2147
  return transition;
1306
2148
  };
1307
2149
 
2150
+ /**
2151
+ * @ngdoc function
2152
+ * @name ui.router.state.$state#is
2153
+ * @methodOf ui.router.state.$state
2154
+ *
2155
+ * @description
2156
+ * Similar to {@link ui.router.state.$state#methods_includes $state.includes},
2157
+ * but only checks for the full state name. If params is supplied then it will be
2158
+ * tested for strict equality against the current active params object, so all params
2159
+ * must match with none missing and no extras.
2160
+ *
2161
+ * @example
2162
+ * <pre>
2163
+ * $state.is('contact.details.item'); // returns true
2164
+ * $state.is(contactDetailItemStateObject); // returns true
2165
+ *
2166
+ * // everything else would return false
2167
+ * </pre>
2168
+ *
2169
+ * @param {string|object} stateName The state name or state object you'd like to check.
2170
+ * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like
2171
+ * to test against the current active state.
2172
+ * @returns {boolean} Returns true if it is the state.
2173
+ */
1308
2174
  $state.is = function is(stateOrName, params) {
1309
2175
  var state = findState(stateOrName);
1310
2176
 
@@ -1316,10 +2182,61 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1316
2182
  return false;
1317
2183
  }
1318
2184
 
1319
- return isDefined(params) ? angular.equals($stateParams, params) : true;
2185
+ return isDefined(params) && params !== null ? angular.equals($stateParams, params) : true;
1320
2186
  };
1321
2187
 
2188
+ /**
2189
+ * @ngdoc function
2190
+ * @name ui.router.state.$state#includes
2191
+ * @methodOf ui.router.state.$state
2192
+ *
2193
+ * @description
2194
+ * A method to determine if the current active state is equal to or is the child of the
2195
+ * state stateName. If any params are passed then they will be tested for a match as well.
2196
+ * Not all the parameters need to be passed, just the ones you'd like to test for equality.
2197
+ *
2198
+ * @example
2199
+ * <pre>
2200
+ * $state.$current.name = 'contacts.details.item';
2201
+ *
2202
+ * $state.includes("contacts"); // returns true
2203
+ * $state.includes("contacts.details"); // returns true
2204
+ * $state.includes("contacts.details.item"); // returns true
2205
+ * $state.includes("contacts.list"); // returns false
2206
+ * $state.includes("about"); // returns false
2207
+ * </pre>
2208
+ *
2209
+ * @description
2210
+ * Basic globing patterns will also work.
2211
+ *
2212
+ * @example
2213
+ * <pre>
2214
+ * $state.$current.name = 'contacts.details.item.url';
2215
+ *
2216
+ * $state.includes("*.details.*.*"); // returns true
2217
+ * $state.includes("*.details.**"); // returns true
2218
+ * $state.includes("**.item.**"); // returns true
2219
+ * $state.includes("*.details.item.url"); // returns true
2220
+ * $state.includes("*.details.*.url"); // returns true
2221
+ * $state.includes("*.details.*"); // returns false
2222
+ * $state.includes("item.**"); // returns false
2223
+ * </pre>
2224
+ *
2225
+ * @param {string} stateOrName A partial name to be searched for within the current state name.
2226
+ * @param {object} params A param object, e.g. `{sectionId: section.id}`,
2227
+ * that you'd like to test against the current active state.
2228
+ * @returns {boolean} Returns true if it does include the state
2229
+ */
2230
+
1322
2231
  $state.includes = function includes(stateOrName, params) {
2232
+ if (isString(stateOrName) && isGlob(stateOrName)) {
2233
+ if (doesStateMatchGlob(stateOrName)) {
2234
+ stateOrName = $state.$current.name;
2235
+ } else {
2236
+ return false;
2237
+ }
2238
+ }
2239
+
1323
2240
  var state = findState(stateOrName);
1324
2241
  if (!isDefined(state)) {
1325
2242
  return undefined;
@@ -1338,6 +2255,34 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1338
2255
  return validParams;
1339
2256
  };
1340
2257
 
2258
+
2259
+ /**
2260
+ * @ngdoc function
2261
+ * @name ui.router.state.$state#href
2262
+ * @methodOf ui.router.state.$state
2263
+ *
2264
+ * @description
2265
+ * A url generation method that returns the compiled url for the given state populated with the given params.
2266
+ *
2267
+ * @example
2268
+ * <pre>
2269
+ * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob");
2270
+ * </pre>
2271
+ *
2272
+ * @param {string|object} stateOrName The state name or state object you'd like to generate a url from.
2273
+ * @param {object=} params An object of parameter values to fill the state's required parameters.
2274
+ * @param {object=} options Options object. The options are:
2275
+ *
2276
+ * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the
2277
+ * first parameter, then the constructed href url will be built from the first navigable ancestor (aka
2278
+ * ancestor with a valid url).
2279
+ * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url.
2280
+ * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'),
2281
+ * defines which state to be relative from.
2282
+ * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl".
2283
+ *
2284
+ * @returns {string} compiled state url
2285
+ */
1341
2286
  $state.href = function href(stateOrName, params, options) {
1342
2287
  options = extend({ lossy: true, inherit: false, absolute: false, relative: $state.$current }, options || {});
1343
2288
  var state = findState(stateOrName, options.relative);
@@ -1349,6 +2294,15 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1349
2294
  if (!$locationProvider.html5Mode() && url) {
1350
2295
  url = "#" + $locationProvider.hashPrefix() + url;
1351
2296
  }
2297
+
2298
+ if (baseHref !== '/') {
2299
+ if ($locationProvider.html5Mode()) {
2300
+ url = baseHref.slice(0, -1) + url;
2301
+ } else if (options.absolute){
2302
+ url = baseHref.slice(1) + url;
2303
+ }
2304
+ }
2305
+
1352
2306
  if (options.absolute && url) {
1353
2307
  url = $location.protocol() + '://' +
1354
2308
  $location.host() +
@@ -1359,6 +2313,18 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1359
2313
  return url;
1360
2314
  };
1361
2315
 
2316
+ /**
2317
+ * @ngdoc function
2318
+ * @name ui.router.state.$state#get
2319
+ * @methodOf ui.router.state.$state
2320
+ *
2321
+ * @description
2322
+ * Returns the state configuration object for any specific state or all states.
2323
+ *
2324
+ * @param {string|object=} stateOrName If provided, will only get the config for
2325
+ * the requested state. If not provided, returns an array of ALL state configs.
2326
+ * @returns {object|array} State configuration object or array of all objects.
2327
+ */
1362
2328
  $state.get = function (stateOrName, context) {
1363
2329
  if (!isDefined(stateOrName)) {
1364
2330
  var list = [];
@@ -1404,6 +2370,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1404
2370
  }
1405
2371
  // Provide access to the state itself for internal use
1406
2372
  result.$$state = state;
2373
+ result.$$controllerAs = view.controllerAs;
1407
2374
  dst[name] = result;
1408
2375
  }));
1409
2376
  });
@@ -1433,10 +2400,30 @@ $ViewProvider.$inject = [];
1433
2400
  function $ViewProvider() {
1434
2401
 
1435
2402
  this.$get = $get;
2403
+ /**
2404
+ * @ngdoc object
2405
+ * @name ui.router.state.$view
2406
+ *
2407
+ * @requires ui.router.util.$templateFactory
2408
+ * @requires $rootScope
2409
+ *
2410
+ * @description
2411
+ *
2412
+ */
1436
2413
  $get.$inject = ['$rootScope', '$templateFactory'];
1437
2414
  function $get( $rootScope, $templateFactory) {
1438
2415
  return {
1439
2416
  // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... })
2417
+ /**
2418
+ * @ngdoc function
2419
+ * @name ui.router.state.$view#load
2420
+ * @methodOf ui.router.state.$view
2421
+ *
2422
+ * @description
2423
+ *
2424
+ * @param {string} name name
2425
+ * @param {object} options option object.
2426
+ */
1440
2427
  load: function load(name, options) {
1441
2428
  var result, defaults = {
1442
2429
  template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {}
@@ -1447,6 +2434,29 @@ function $ViewProvider() {
1447
2434
  result = $templateFactory.fromConfig(options.view, options.params, options.locals);
1448
2435
  }
1449
2436
  if (result && options.notify) {
2437
+ /**
2438
+ * @ngdoc event
2439
+ * @name ui.router.state.$state#$viewContentLoading
2440
+ * @eventOf ui.router.state.$view
2441
+ * @eventType broadcast on root scope
2442
+ * @description
2443
+ *
2444
+ * Fired once the view **begins loading**, *before* the DOM is rendered.
2445
+ *
2446
+ * @param {Object} event Event object.
2447
+ * @param {Object} viewConfig The view config properties (template, controller, etc).
2448
+ *
2449
+ * @example
2450
+ *
2451
+ * <pre>
2452
+ * $scope.$on('$viewContentLoading',
2453
+ * function(event, viewConfig){
2454
+ * // Access to all the view config properties.
2455
+ * // and one special property 'targetView'
2456
+ * // viewConfig.targetView
2457
+ * });
2458
+ * </pre>
2459
+ */
1450
2460
  $rootScope.$broadcast('$viewContentLoading', options);
1451
2461
  }
1452
2462
  return result;
@@ -1457,123 +2467,349 @@ function $ViewProvider() {
1457
2467
 
1458
2468
  angular.module('ui.router.state').provider('$view', $ViewProvider);
1459
2469
 
2470
+ /**
2471
+ * @ngdoc object
2472
+ * @name ui.router.state.$uiViewScrollProvider
2473
+ *
2474
+ * @description
2475
+ * Provider that returns the {@link ui.router.state.$uiViewScroll} service function.
2476
+ */
2477
+ function $ViewScrollProvider() {
2478
+
2479
+ var useAnchorScroll = false;
1460
2480
 
1461
- $ViewDirective.$inject = ['$state', '$compile', '$controller', '$injector', '$anchorScroll'];
1462
- function $ViewDirective( $state, $compile, $controller, $injector, $anchorScroll) {
1463
- var $animator = $injector.has('$animator') ? $injector.get('$animator') : false;
1464
- var viewIsUpdating = false;
2481
+ /**
2482
+ * @ngdoc function
2483
+ * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll
2484
+ * @methodOf ui.router.state.$uiViewScrollProvider
2485
+ *
2486
+ * @description
2487
+ * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for
2488
+ * scrolling based on the url anchor.
2489
+ */
2490
+ this.useAnchorScroll = function () {
2491
+ useAnchorScroll = true;
2492
+ };
2493
+
2494
+ /**
2495
+ * @ngdoc object
2496
+ * @name ui.router.state.$uiViewScroll
2497
+ *
2498
+ * @requires $anchorScroll
2499
+ * @requires $timeout
2500
+ *
2501
+ * @description
2502
+ * When called with a jqLite element, it scrolls the element into view (after a
2503
+ * `$timeout` so the DOM has time to refresh).
2504
+ *
2505
+ * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor,
2506
+ * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}.
2507
+ */
2508
+ this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) {
2509
+ if (useAnchorScroll) {
2510
+ return $anchorScroll;
2511
+ }
2512
+
2513
+ return function ($element) {
2514
+ $timeout(function () {
2515
+ $element[0].scrollIntoView();
2516
+ }, 0, false);
2517
+ };
2518
+ }];
2519
+ }
2520
+
2521
+ angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider);
2522
+
2523
+ /**
2524
+ * @ngdoc directive
2525
+ * @name ui.router.state.directive:ui-view
2526
+ *
2527
+ * @requires ui.router.state.$state
2528
+ * @requires $compile
2529
+ * @requires $controller
2530
+ * @requires $injector
2531
+ * @requires ui.router.state.$uiViewScroll
2532
+ * @requires $document
2533
+ *
2534
+ * @restrict ECA
2535
+ *
2536
+ * @description
2537
+ * The ui-view directive tells $state where to place your templates.
2538
+ *
2539
+ * @param {string=} ui-view A view name. The name should be unique amongst the other views in the
2540
+ * same state. You can have views of the same name that live in different states.
2541
+ *
2542
+ * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window
2543
+ * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll
2544
+ * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you
2545
+ * scroll ui-view elements into view when they are populated during a state activation.
2546
+ *
2547
+ * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll)
2548
+ * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.*
2549
+ *
2550
+ * @param {string=} onload Expression to evaluate whenever the view updates.
2551
+ *
2552
+ * @example
2553
+ * A view can be unnamed or named.
2554
+ * <pre>
2555
+ * <!-- Unnamed -->
2556
+ * <div ui-view></div>
2557
+ *
2558
+ * <!-- Named -->
2559
+ * <div ui-view="viewName"></div>
2560
+ * </pre>
2561
+ *
2562
+ * You can only have one unnamed view within any template (or root html). If you are only using a
2563
+ * single view and it is unnamed then you can populate it like so:
2564
+ * <pre>
2565
+ * <div ui-view></div>
2566
+ * $stateProvider.state("home", {
2567
+ * template: "<h1>HELLO!</h1>"
2568
+ * })
2569
+ * </pre>
2570
+ *
2571
+ * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`}
2572
+ * config property, by name, in this case an empty name:
2573
+ * <pre>
2574
+ * $stateProvider.state("home", {
2575
+ * views: {
2576
+ * "": {
2577
+ * template: "<h1>HELLO!</h1>"
2578
+ * }
2579
+ * }
2580
+ * })
2581
+ * </pre>
2582
+ *
2583
+ * But typically you'll only use the views property if you name your view or have more than one view
2584
+ * in the same template. There's not really a compelling reason to name a view if its the only one,
2585
+ * but you could if you wanted, like so:
2586
+ * <pre>
2587
+ * <div ui-view="main"></div>
2588
+ * </pre>
2589
+ * <pre>
2590
+ * $stateProvider.state("home", {
2591
+ * views: {
2592
+ * "main": {
2593
+ * template: "<h1>HELLO!</h1>"
2594
+ * }
2595
+ * }
2596
+ * })
2597
+ * </pre>
2598
+ *
2599
+ * Really though, you'll use views to set up multiple views:
2600
+ * <pre>
2601
+ * <div ui-view></div>
2602
+ * <div ui-view="chart"></div>
2603
+ * <div ui-view="data"></div>
2604
+ * </pre>
2605
+ *
2606
+ * <pre>
2607
+ * $stateProvider.state("home", {
2608
+ * views: {
2609
+ * "": {
2610
+ * template: "<h1>HELLO!</h1>"
2611
+ * },
2612
+ * "chart": {
2613
+ * template: "<chart_thing/>"
2614
+ * },
2615
+ * "data": {
2616
+ * template: "<data_thing/>"
2617
+ * }
2618
+ * }
2619
+ * })
2620
+ * </pre>
2621
+ *
2622
+ * Examples for `autoscroll`:
2623
+ *
2624
+ * <pre>
2625
+ * <!-- If autoscroll present with no expression,
2626
+ * then scroll ui-view into view -->
2627
+ * <ui-view autoscroll/>
2628
+ *
2629
+ * <!-- If autoscroll present with valid expression,
2630
+ * then scroll ui-view into view if expression evaluates to true -->
2631
+ * <ui-view autoscroll='true'/>
2632
+ * <ui-view autoscroll='false'/>
2633
+ * <ui-view autoscroll='scopeVariable'/>
2634
+ * </pre>
2635
+ */
2636
+ $ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll'];
2637
+ function $ViewDirective( $state, $injector, $uiViewScroll) {
2638
+
2639
+ function getService() {
2640
+ return ($injector.has) ? function(service) {
2641
+ return $injector.has(service) ? $injector.get(service) : null;
2642
+ } : function(service) {
2643
+ try {
2644
+ return $injector.get(service);
2645
+ } catch (e) {
2646
+ return null;
2647
+ }
2648
+ };
2649
+ }
2650
+
2651
+ var service = getService(),
2652
+ $animator = service('$animator'),
2653
+ $animate = service('$animate');
2654
+
2655
+ // Returns a set of DOM manipulation functions based on which Angular version
2656
+ // it should use
2657
+ function getRenderer(attrs, scope) {
2658
+ var statics = function() {
2659
+ return {
2660
+ enter: function (element, target, cb) { target.after(element); cb(); },
2661
+ leave: function (element, cb) { element.remove(); cb(); }
2662
+ };
2663
+ };
2664
+
2665
+ if ($animate) {
2666
+ return {
2667
+ enter: function(element, target, cb) { $animate.enter(element, null, target, cb); },
2668
+ leave: function(element, cb) { $animate.leave(element, cb); }
2669
+ };
2670
+ }
2671
+
2672
+ if ($animator) {
2673
+ var animate = $animator && $animator(scope, attrs);
2674
+
2675
+ return {
2676
+ enter: function(element, target, cb) {animate.enter(element, null, target); cb(); },
2677
+ leave: function(element, cb) { animate.leave(element); cb(); }
2678
+ };
2679
+ }
2680
+
2681
+ return statics();
2682
+ }
1465
2683
 
1466
2684
  var directive = {
1467
2685
  restrict: 'ECA',
1468
2686
  terminal: true,
1469
- priority: 1000,
1470
- transclude: true,
1471
- compile: function (element, attr, transclude) {
1472
- return function(scope, element, attr) {
1473
- var viewScope, viewLocals,
1474
- name = attr[directive.name] || attr.name || '',
1475
- onloadExp = attr.onload || '',
1476
- animate = $animator && $animator(scope, attr),
1477
- initialView = transclude(scope);
1478
-
1479
- // Returns a set of DOM manipulation functions based on whether animation
1480
- // should be performed
1481
- var renderer = function(doAnimate) {
1482
- return ({
1483
- "true": {
1484
- remove: function(element) { animate.leave(element.contents(), element); },
1485
- restore: function(compiled, element) { animate.enter(compiled, element); },
1486
- populate: function(template, element) {
1487
- var contents = angular.element('<div></div>').html(template).contents();
1488
- animate.enter(contents, element);
1489
- return contents;
1490
- }
1491
- },
1492
- "false": {
1493
- remove: function(element) { element.html(''); },
1494
- restore: function(compiled, element) { element.append(compiled); },
1495
- populate: function(template, element) {
1496
- element.html(template);
1497
- return element.contents();
1498
- }
1499
- }
1500
- })[doAnimate.toString()];
1501
- };
2687
+ priority: 400,
2688
+ transclude: 'element',
2689
+ compile: function (tElement, tAttrs, $transclude) {
2690
+ return function (scope, $element, attrs) {
2691
+ var previousEl, currentEl, currentScope, latestLocals,
2692
+ onloadExp = attrs.onload || '',
2693
+ autoScrollExp = attrs.autoscroll,
2694
+ renderer = getRenderer(attrs, scope);
2695
+
2696
+ scope.$on('$stateChangeSuccess', function() {
2697
+ updateView(false);
2698
+ });
2699
+ scope.$on('$viewContentLoading', function() {
2700
+ updateView(false);
2701
+ });
1502
2702
 
1503
- // Put back the compiled initial view
1504
- element.append(initialView);
2703
+ updateView(true);
1505
2704
 
1506
- // Find the details of the parent view directive (if any) and use it
1507
- // to derive our own qualified view name, then hang our own details
1508
- // off the DOM so child directives can find it.
1509
- var parent = element.parent().inheritedData('$uiView');
1510
- if (name.indexOf('@') < 0) name = name + '@' + (parent ? parent.state.name : '');
1511
- var view = { name: name, state: null };
1512
- element.data('$uiView', view);
2705
+ function cleanupLastView() {
2706
+ if (previousEl) {
2707
+ previousEl.remove();
2708
+ previousEl = null;
2709
+ }
2710
+
2711
+ if (currentScope) {
2712
+ currentScope.$destroy();
2713
+ currentScope = null;
2714
+ }
1513
2715
 
1514
- var eventHook = function() {
1515
- if (viewIsUpdating) return;
1516
- viewIsUpdating = true;
2716
+ if (currentEl) {
2717
+ renderer.leave(currentEl, function() {
2718
+ previousEl = null;
2719
+ });
1517
2720
 
1518
- try { updateView(true); } catch (e) {
1519
- viewIsUpdating = false;
1520
- throw e;
2721
+ previousEl = currentEl;
2722
+ currentEl = null;
1521
2723
  }
1522
- viewIsUpdating = false;
1523
- };
2724
+ }
1524
2725
 
1525
- scope.$on('$stateChangeSuccess', eventHook);
1526
- scope.$on('$viewContentLoading', eventHook);
1527
- updateView(false);
2726
+ function updateView(firstTime) {
2727
+ var newScope = scope.$new(),
2728
+ name = currentEl && currentEl.data('$uiViewName'),
2729
+ previousLocals = name && $state.$current && $state.$current.locals[name];
1528
2730
 
1529
- function updateView(doAnimate) {
1530
- var locals = $state.$current && $state.$current.locals[name];
1531
- if (locals === viewLocals) return; // nothing to do
1532
- var render = renderer(animate && doAnimate);
2731
+ if (!firstTime && previousLocals === latestLocals) return; // nothing to do
1533
2732
 
1534
- // Remove existing content
1535
- render.remove(element);
2733
+ var clone = $transclude(newScope, function(clone) {
2734
+ renderer.enter(clone, $element, function onUiViewEnter() {
2735
+ if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) {
2736
+ $uiViewScroll(clone);
2737
+ }
2738
+ });
2739
+ cleanupLastView();
2740
+ });
1536
2741
 
1537
- // Destroy previous view scope
1538
- if (viewScope) {
1539
- viewScope.$destroy();
1540
- viewScope = null;
1541
- }
2742
+ latestLocals = $state.$current.locals[clone.data('$uiViewName')];
2743
+
2744
+ currentEl = clone;
2745
+ currentScope = newScope;
2746
+ /**
2747
+ * @ngdoc event
2748
+ * @name ui.router.state.directive:ui-view#$viewContentLoaded
2749
+ * @eventOf ui.router.state.directive:ui-view
2750
+ * @eventType emits on ui-view directive scope
2751
+ * @description *
2752
+ * Fired once the view is **loaded**, *after* the DOM is rendered.
2753
+ *
2754
+ * @param {Object} event Event object.
2755
+ */
2756
+ currentScope.$emit('$viewContentLoaded');
2757
+ currentScope.$eval(onloadExp);
2758
+ }
2759
+ };
2760
+ }
2761
+ };
1542
2762
 
1543
- if (!locals) {
1544
- viewLocals = null;
1545
- view.state = null;
2763
+ return directive;
2764
+ }
1546
2765
 
1547
- // Restore the initial view
1548
- return render.restore(initialView, element);
1549
- }
2766
+ $ViewDirectiveFill.$inject = ['$compile', '$controller', '$state'];
2767
+ function $ViewDirectiveFill ($compile, $controller, $state) {
2768
+ return {
2769
+ restrict: 'ECA',
2770
+ priority: -400,
2771
+ compile: function (tElement) {
2772
+ var initial = tElement.html();
2773
+ return function (scope, $element, attrs) {
2774
+ var name = attrs.uiView || attrs.name || '',
2775
+ inherited = $element.inheritedData('$uiView');
2776
+
2777
+ if (name.indexOf('@') < 0) {
2778
+ name = name + '@' + (inherited ? inherited.state.name : '');
2779
+ }
1550
2780
 
1551
- viewLocals = locals;
1552
- view.state = locals.$$state;
2781
+ $element.data('$uiViewName', name);
1553
2782
 
1554
- var link = $compile(render.populate(locals.$template, element));
1555
- viewScope = scope.$new();
2783
+ var current = $state.$current,
2784
+ locals = current && current.locals[name];
1556
2785
 
1557
- if (locals.$$controller) {
1558
- locals.$scope = viewScope;
1559
- var controller = $controller(locals.$$controller, locals);
1560
- element.children().data('$ngControllerController', controller);
1561
- }
1562
- link(viewScope);
1563
- viewScope.$emit('$viewContentLoaded');
1564
- if (onloadExp) viewScope.$eval(onloadExp);
2786
+ if (! locals) {
2787
+ return;
2788
+ }
2789
+
2790
+ $element.data('$uiView', { name: name, state: locals.$$state });
2791
+ $element.html(locals.$template ? locals.$template : initial);
2792
+
2793
+ var link = $compile($element.contents());
1565
2794
 
1566
- // TODO: This seems strange, shouldn't $anchorScroll listen for $viewContentLoaded if necessary?
1567
- // $anchorScroll might listen on event...
1568
- $anchorScroll();
2795
+ if (locals.$$controller) {
2796
+ locals.$scope = scope;
2797
+ var controller = $controller(locals.$$controller, locals);
2798
+ if (locals.$$controllerAs) {
2799
+ scope[locals.$$controllerAs] = controller;
2800
+ }
2801
+ $element.data('$ngControllerController', controller);
2802
+ $element.children().data('$ngControllerController', controller);
1569
2803
  }
2804
+
2805
+ link(scope);
1570
2806
  };
1571
2807
  }
1572
2808
  };
1573
- return directive;
1574
2809
  }
1575
2810
 
1576
2811
  angular.module('ui.router.state').directive('uiView', $ViewDirective);
2812
+ angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill);
1577
2813
 
1578
2814
  function parseStateRef(ref) {
1579
2815
  var parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/);
@@ -1589,8 +2825,72 @@ function stateContext(el) {
1589
2825
  }
1590
2826
  }
1591
2827
 
2828
+ /**
2829
+ * @ngdoc directive
2830
+ * @name ui.router.state.directive:ui-sref
2831
+ *
2832
+ * @requires ui.router.state.$state
2833
+ * @requires $timeout
2834
+ *
2835
+ * @restrict A
2836
+ *
2837
+ * @description
2838
+ * A directive that binds a link (`<a>` tag) to a state. If the state has an associated
2839
+ * URL, the directive will automatically generate & update the `href` attribute via
2840
+ * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking
2841
+ * the link will trigger a state transition with optional parameters.
2842
+ *
2843
+ * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be
2844
+ * handled natively by the browser.
2845
+ *
2846
+ * You can also use relative state paths within ui-sref, just like the relative
2847
+ * paths passed to `$state.go()`. You just need to be aware that the path is relative
2848
+ * to the state that the link lives in, in other words the state that loaded the
2849
+ * template containing the link.
2850
+ *
2851
+ * You can specify options to pass to {@link ui.router.state.$state#go $state.go()}
2852
+ * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`,
2853
+ * and `reload`.
2854
+ *
2855
+ * @example
2856
+ * Here's an example of how you'd use ui-sref and how it would compile. If you have the
2857
+ * following template:
2858
+ * <pre>
2859
+ * <a ui-sref="home">Home</a> | <a ui-sref="about">About</a>
2860
+ *
2861
+ * <ul>
2862
+ * <li ng-repeat="contact in contacts">
2863
+ * <a ui-sref="contacts.detail({ id: contact.id })">{{ contact.name }}</a>
2864
+ * </li>
2865
+ * </ul>
2866
+ * </pre>
2867
+ *
2868
+ * Then the compiled html would be (assuming Html5Mode is off):
2869
+ * <pre>
2870
+ * <a href="#/home" ui-sref="home">Home</a> | <a href="#/about" ui-sref="about">About</a>
2871
+ *
2872
+ * <ul>
2873
+ * <li ng-repeat="contact in contacts">
2874
+ * <a href="#/contacts/1" ui-sref="contacts.detail({ id: contact.id })">Joe</a>
2875
+ * </li>
2876
+ * <li ng-repeat="contact in contacts">
2877
+ * <a href="#/contacts/2" ui-sref="contacts.detail({ id: contact.id })">Alice</a>
2878
+ * </li>
2879
+ * <li ng-repeat="contact in contacts">
2880
+ * <a href="#/contacts/3" ui-sref="contacts.detail({ id: contact.id })">Bob</a>
2881
+ * </li>
2882
+ * </ul>
2883
+ *
2884
+ * <a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
2885
+ * </pre>
2886
+ *
2887
+ * @param {string} ui-sref 'stateName' can be any valid absolute or relative state
2888
+ * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()}
2889
+ */
1592
2890
  $StateRefDirective.$inject = ['$state', '$timeout'];
1593
2891
  function $StateRefDirective($state, $timeout) {
2892
+ var allowedOptions = ['location', 'inherit', 'reload'];
2893
+
1594
2894
  return {
1595
2895
  restrict: 'A',
1596
2896
  require: '?^uiSrefActive',
@@ -1600,20 +2900,30 @@ function $StateRefDirective($state, $timeout) {
1600
2900
  var isForm = element[0].nodeName === "FORM";
1601
2901
  var attr = isForm ? "action" : "href", nav = true;
1602
2902
 
2903
+ var options = {
2904
+ relative: base
2905
+ };
2906
+ var optionsOverride = scope.$eval(attrs.uiSrefOpts) || {};
2907
+ angular.forEach(allowedOptions, function(option) {
2908
+ if (option in optionsOverride) {
2909
+ options[option] = optionsOverride[option];
2910
+ }
2911
+ });
2912
+
1603
2913
  var update = function(newVal) {
1604
2914
  if (newVal) params = newVal;
1605
2915
  if (!nav) return;
1606
2916
 
1607
- var newHref = $state.href(ref.state, params, { relative: base });
2917
+ var newHref = $state.href(ref.state, params, options);
1608
2918
 
2919
+ if (uiSrefActive) {
2920
+ uiSrefActive.$$setStateInfo(ref.state, params);
2921
+ }
1609
2922
  if (!newHref) {
1610
2923
  nav = false;
1611
2924
  return false;
1612
2925
  }
1613
2926
  element[0][attr] = newHref;
1614
- if (uiSrefActive) {
1615
- uiSrefActive.$$setStateInfo(ref.state, params);
1616
- }
1617
2927
  };
1618
2928
 
1619
2929
  if (ref.paramExpr) {
@@ -1628,13 +2938,10 @@ function $StateRefDirective($state, $timeout) {
1628
2938
 
1629
2939
  element.bind("click", function(e) {
1630
2940
  var button = e.which || e.button;
1631
-
1632
- if ((button === 0 || button == 1) && !e.ctrlKey && !e.metaKey && !e.shiftKey) {
2941
+ if ( !(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr('target')) ) {
1633
2942
  // HACK: This is to allow ng-clicks to be processed before the transition is initiated:
1634
2943
  $timeout(function() {
1635
- scope.$apply(function() {
1636
- $state.go(ref.state, params, { relative: base });
1637
- });
2944
+ $state.go(ref.state, params, options);
1638
2945
  });
1639
2946
  e.preventDefault();
1640
2947
  }
@@ -1643,11 +2950,60 @@ function $StateRefDirective($state, $timeout) {
1643
2950
  };
1644
2951
  }
1645
2952
 
2953
+ /**
2954
+ * @ngdoc directive
2955
+ * @name ui.router.state.directive:ui-sref-active
2956
+ *
2957
+ * @requires ui.router.state.$state
2958
+ * @requires ui.router.state.$stateParams
2959
+ * @requires $interpolate
2960
+ *
2961
+ * @restrict A
2962
+ *
2963
+ * @description
2964
+ * A directive working alongside ui-sref to add classes to an element when the
2965
+ * related ui-sref directive's state is active, and removing them when it is inactive.
2966
+ * The primary use-case is to simplify the special appearance of navigation menus
2967
+ * relying on `ui-sref`, by having the "active" state's menu button appear different,
2968
+ * distinguishing it from the inactive menu items.
2969
+ *
2970
+ * @example
2971
+ * Given the following template:
2972
+ * <pre>
2973
+ * <ul>
2974
+ * <li ui-sref-active="active" class="item">
2975
+ * <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
2976
+ * </li>
2977
+ * </ul>
2978
+ * </pre>
2979
+ *
2980
+ * When the app state is "app.user", and contains the state parameter "user" with value "bilbobaggins",
2981
+ * the resulting HTML will appear as (note the 'active' class):
2982
+ * <pre>
2983
+ * <ul>
2984
+ * <li ui-sref-active="active" class="item active">
2985
+ * <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a>
2986
+ * </li>
2987
+ * </ul>
2988
+ * </pre>
2989
+ *
2990
+ * The class name is interpolated **once** during the directives link time (any further changes to the
2991
+ * interpolated value are ignored).
2992
+ *
2993
+ * Multiple classes may be specified in a space-separated format:
2994
+ * <pre>
2995
+ * <ul>
2996
+ * <li ui-sref-active='class1 class2 class3'>
2997
+ * <a ui-sref="app.user">link</a>
2998
+ * </li>
2999
+ * </ul>
3000
+ * </pre>
3001
+ */
1646
3002
  $StateActiveDirective.$inject = ['$state', '$stateParams', '$interpolate'];
1647
3003
  function $StateActiveDirective($state, $stateParams, $interpolate) {
1648
3004
  return {
1649
3005
  restrict: "A",
1650
- controller: function($scope, $element, $attrs) {
3006
+ controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
1651
3007
  var state, params, activeClass;
1652
3008
 
1653
3009
  // There probably isn't much point in $observing this
@@ -1674,7 +3030,7 @@ function $StateActiveDirective($state, $stateParams, $interpolate) {
1674
3030
  function matchesParams() {
1675
3031
  return !params || equalForKeys(params, $stateParams);
1676
3032
  }
1677
- }
3033
+ }]
1678
3034
  };
1679
3035
  }
1680
3036
 
@@ -1682,6 +3038,60 @@ angular.module('ui.router.state')
1682
3038
  .directive('uiSref', $StateRefDirective)
1683
3039
  .directive('uiSrefActive', $StateActiveDirective);
1684
3040
 
3041
+ /**
3042
+ * @ngdoc filter
3043
+ * @name ui.router.state.filter:isState
3044
+ *
3045
+ * @requires ui.router.state.$state
3046
+ *
3047
+ * @description
3048
+ * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}.
3049
+ */
3050
+ $IsStateFilter.$inject = ['$state'];
3051
+ function $IsStateFilter($state) {
3052
+ return function(state) {
3053
+ return $state.is(state);
3054
+ };
3055
+ }
3056
+
3057
+ /**
3058
+ * @ngdoc filter
3059
+ * @name ui.router.state.filter:includedByState
3060
+ *
3061
+ * @requires ui.router.state.$state
3062
+ *
3063
+ * @description
3064
+ * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}.
3065
+ */
3066
+ $IncludedByStateFilter.$inject = ['$state'];
3067
+ function $IncludedByStateFilter($state) {
3068
+ return function(state) {
3069
+ return $state.includes(state);
3070
+ };
3071
+ }
3072
+
3073
+ angular.module('ui.router.state')
3074
+ .filter('isState', $IsStateFilter)
3075
+ .filter('includedByState', $IncludedByStateFilter);
3076
+
3077
+ /*
3078
+ * @ngdoc object
3079
+ * @name ui.router.compat.$routeProvider
3080
+ *
3081
+ * @requires ui.router.state.$stateProvider
3082
+ * @requires ui.router.router.$urlRouterProvider
3083
+ *
3084
+ * @description
3085
+ * `$routeProvider` of the `ui.router.compat` module overwrites the existing
3086
+ * `routeProvider` from the core. This is done to provide compatibility between
3087
+ * the UI Router and the core router.
3088
+ *
3089
+ * It also provides a `when()` method to register routes that map to certain urls.
3090
+ * Behind the scenes it actually delegates either to
3091
+ * {@link ui.router.router.$urlRouterProvider $urlRouterProvider} or to the
3092
+ * {@link ui.router.state.$stateProvider $stateProvider} to postprocess the given
3093
+ * router definition object.
3094
+ */
1685
3095
  $RouteProvider.$inject = ['$stateProvider', '$urlRouterProvider'];
1686
3096
  function $RouteProvider( $stateProvider, $urlRouterProvider) {
1687
3097
 
@@ -1701,6 +3111,32 @@ function $RouteProvider( $stateProvider, $urlRouterProvider) {
1701
3111
  }
1702
3112
 
1703
3113
  this.when = when;
3114
+ /*
3115
+ * @ngdoc function
3116
+ * @name ui.router.compat.$routeProvider#when
3117
+ * @methodOf ui.router.compat.$routeProvider
3118
+ *
3119
+ * @description
3120
+ * Registers a route with a given route definition object. The route definition
3121
+ * object has the same interface the angular core route definition object has.
3122
+ *
3123
+ * @example
3124
+ * <pre>
3125
+ * var app = angular.module('app', ['ui.router.compat']);
3126
+ *
3127
+ * app.config(function ($routeProvider) {
3128
+ * $routeProvider.when('home', {
3129
+ * controller: function () { ... },
3130
+ * templateUrl: 'path/to/template'
3131
+ * });
3132
+ * });
3133
+ * </pre>
3134
+ *
3135
+ * @param {string} url URL as string
3136
+ * @param {object} route Route definition object
3137
+ *
3138
+ * @return {object} $routeProvider - $routeProvider instance
3139
+ */
1704
3140
  function when(url, route) {
1705
3141
  /*jshint validthis: true */
1706
3142
  if (route.redirectTo != null) {
@@ -1731,6 +3167,24 @@ function $RouteProvider( $stateProvider, $urlRouterProvider) {
1731
3167
  return this;
1732
3168
  }
1733
3169
 
3170
+ /*
3171
+ * @ngdoc object
3172
+ * @name ui.router.compat.$route
3173
+ *
3174
+ * @requires ui.router.state.$state
3175
+ * @requires $rootScope
3176
+ * @requires $routeParams
3177
+ *
3178
+ * @property {object} routes - Array of registered routes.
3179
+ * @property {object} params - Current route params as object.
3180
+ * @property {string} current - Name of the current route.
3181
+ *
3182
+ * @description
3183
+ * The `$route` service provides interfaces to access defined routes. It also let's
3184
+ * you access route params through `$routeParams` service, so you have fully
3185
+ * control over all the stuff you would actually get from angular's core `$route`
3186
+ * service.
3187
+ */
1734
3188
  this.$get = $get;
1735
3189
  $get.$inject = ['$state', '$rootScope', '$routeParams'];
1736
3190
  function $get( $state, $rootScope, $routeParams) {
@@ -1766,4 +3220,4 @@ function $RouteProvider( $stateProvider, $urlRouterProvider) {
1766
3220
  angular.module('ui.router.compat')
1767
3221
  .provider('$route', $RouteProvider)
1768
3222
  .directive('ngView', $ViewDirective);
1769
- })(window, window.angular);
3223
+ })(window, window.angular);