ionic-rails-engine 0.9.26.1 → 0.9.99.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -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);