praxis 0.16.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (399) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +0 -1
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +2 -1
  5. data/CHANGELOG.md +41 -0
  6. data/CONTRIBUTING.md +3 -0
  7. data/lib/api_browser/Gruntfile.js +20 -4
  8. data/lib/api_browser/app/bower_components/angular-mocks/.bower.json +6 -6
  9. data/lib/api_browser/app/bower_components/angular-mocks/README.md +11 -5
  10. data/lib/api_browser/app/bower_components/angular-mocks/angular-mocks.js +475 -216
  11. data/lib/api_browser/app/bower_components/angular-mocks/bower.json +2 -2
  12. data/lib/api_browser/app/bower_components/angular-mocks/ngAnimateMock.js +2 -0
  13. data/lib/api_browser/app/bower_components/angular-mocks/ngMock.js +2 -0
  14. data/lib/api_browser/app/bower_components/angular-mocks/ngMockE2E.js +2 -0
  15. data/lib/api_browser/app/bower_components/angular-mocks/package.json +1 -1
  16. data/lib/api_browser/app/bower_components/angular-sanitize/.bower.json +8 -8
  17. data/lib/api_browser/app/bower_components/angular-sanitize/README.md +19 -5
  18. data/lib/api_browser/app/bower_components/angular-sanitize/angular-sanitize.js +186 -127
  19. data/lib/api_browser/app/bower_components/angular-sanitize/angular-sanitize.min.js +12 -10
  20. data/lib/api_browser/app/bower_components/angular-sanitize/angular-sanitize.min.js.map +3 -3
  21. data/lib/api_browser/app/bower_components/angular-sanitize/bower.json +3 -2
  22. data/lib/api_browser/app/bower_components/angular-sanitize/index.js +2 -0
  23. data/lib/api_browser/app/bower_components/angular-sanitize/package.json +26 -0
  24. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/.bower.json +15 -8
  25. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/bower.json +11 -3
  26. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-csp.css +6 -0
  27. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.js +1177 -453
  28. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.min.js +4 -4
  29. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap.js +1066 -404
  30. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap.min.js +3 -3
  31. data/lib/api_browser/app/bower_components/angular-ui-router/.bower.json +5 -6
  32. data/lib/api_browser/app/bower_components/angular-ui-router/CHANGELOG.md +208 -3
  33. data/lib/api_browser/app/bower_components/angular-ui-router/CONTRIBUTING.md +65 -0
  34. data/lib/api_browser/app/bower_components/angular-ui-router/LICENSE +1 -1
  35. data/lib/api_browser/app/bower_components/angular-ui-router/README.md +36 -71
  36. data/lib/api_browser/app/bower_components/angular-ui-router/api/angular-ui-router.d.ts +126 -0
  37. data/lib/api_browser/app/bower_components/angular-ui-router/bower.json +1 -1
  38. data/lib/api_browser/app/bower_components/angular-ui-router/release/angular-ui-router.js +1902 -755
  39. data/lib/api_browser/app/bower_components/angular-ui-router/release/angular-ui-router.min.js +2 -2
  40. data/lib/api_browser/app/bower_components/angular-ui-router/src/common.js +69 -23
  41. data/lib/api_browser/app/bower_components/angular-ui-router/src/resolve.js +15 -5
  42. data/lib/api_browser/app/bower_components/angular-ui-router/src/state.js +556 -295
  43. data/lib/api_browser/app/bower_components/angular-ui-router/src/stateDirectives.js +101 -42
  44. data/lib/api_browser/app/bower_components/angular-ui-router/src/stateFilters.js +6 -2
  45. data/lib/api_browser/app/bower_components/angular-ui-router/src/templateFactory.js +2 -2
  46. data/lib/api_browser/app/bower_components/angular-ui-router/src/urlMatcherFactory.js +822 -97
  47. data/lib/api_browser/app/bower_components/angular-ui-router/src/urlRouter.js +274 -120
  48. data/lib/api_browser/app/bower_components/angular-ui-router/src/viewDirective.js +33 -20
  49. data/lib/api_browser/app/bower_components/angular-ui-router/src/viewScroll.js +1 -1
  50. data/lib/api_browser/app/bower_components/angular/.bower.json +5 -5
  51. data/lib/api_browser/app/bower_components/angular/README.md +2 -5
  52. data/lib/api_browser/app/bower_components/angular/angular-csp.css +5 -8
  53. data/lib/api_browser/app/bower_components/angular/angular.js +12975 -6996
  54. data/lib/api_browser/app/bower_components/angular/angular.min.js +285 -213
  55. data/lib/api_browser/app/bower_components/angular/angular.min.js.gzip +0 -0
  56. data/lib/api_browser/app/bower_components/angular/angular.min.js.map +3 -3
  57. data/lib/api_browser/app/bower_components/angular/bower.json +1 -1
  58. data/lib/api_browser/app/bower_components/angular/index.js +2 -0
  59. data/lib/api_browser/app/bower_components/angular/package.json +2 -2
  60. data/lib/api_browser/app/bower_components/bootstrap-sass/.bower.json +31 -16
  61. data/lib/api_browser/app/bower_components/bootstrap-sass/CHANGELOG.md +108 -0
  62. data/lib/api_browser/app/bower_components/bootstrap-sass/CONTRIBUTING.md +55 -37
  63. data/lib/api_browser/app/bower_components/bootstrap-sass/README.md +147 -206
  64. data/lib/api_browser/app/bower_components/bootstrap-sass/bower.json +19 -8
  65. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.eot +0 -0
  66. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.svg +0 -0
  67. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.ttf +0 -0
  68. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.woff +0 -0
  69. data/lib/api_browser/app/bower_components/bootstrap-sass/vendor/assets/javascripts/bootstrap.js +12 -0
  70. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/affix.js +1 -1
  71. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/alert.js +1 -1
  72. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/button.js +11 -5
  73. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/carousel.js +5 -5
  74. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/collapse.js +1 -1
  75. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/dropdown.js +5 -5
  76. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/modal.js +1 -1
  77. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/popover.js +1 -1
  78. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/scrollspy.js +2 -2
  79. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/tab.js +1 -1
  80. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/tooltip.js +1 -1
  81. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/transition.js +1 -1
  82. data/lib/api_browser/app/bower_components/bootstrap-sass/vendor/assets/stylesheets/bootstrap.scss +1 -0
  83. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_alerts.scss +0 -0
  84. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_badges.scss +6 -6
  85. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_breadcrumbs.scss +0 -0
  86. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_button-groups.scss +7 -33
  87. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_buttons.scss +2 -5
  88. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_carousel.scss +1 -0
  89. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_close.scss +0 -0
  90. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_code.scss +0 -0
  91. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_component-animations.scss +0 -0
  92. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_dropdowns.scss +3 -8
  93. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_forms.scss +11 -0
  94. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_glyphicons.scss +5 -5
  95. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_grid.scss +12 -26
  96. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_input-groups.scss +1 -1
  97. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_jumbotron.scss +8 -2
  98. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_labels.scss +6 -0
  99. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_list-group.scss +0 -0
  100. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_media.scss +0 -0
  101. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_mixins.scss +38 -51
  102. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_modals.scss +2 -5
  103. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_navbar.scss +41 -53
  104. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_navs.scss +0 -20
  105. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_normalize.scss +0 -0
  106. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_pager.scss +0 -0
  107. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_pagination.scss +0 -0
  108. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_panels.scss +11 -1
  109. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_popovers.scss +0 -0
  110. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_print.scss +0 -0
  111. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_progress-bars.scss +0 -12
  112. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_responsive-utilities.scss +0 -0
  113. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_scaffolding.scss +0 -0
  114. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_tables.scss +5 -18
  115. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_theme.scss +2 -2
  116. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_thumbnails.scss +9 -3
  117. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_tooltip.scss +0 -0
  118. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_type.scss +54 -52
  119. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_utilities.scss +0 -0
  120. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_variables.scss +20 -11
  121. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_wells.scss +0 -0
  122. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/bootstrap.scss +0 -0
  123. data/lib/api_browser/app/bower_components/lodash/.bower.json +9 -13
  124. data/lib/api_browser/app/bower_components/lodash/LICENSE.txt +3 -3
  125. data/lib/api_browser/app/bower_components/lodash/bower.json +4 -7
  126. data/lib/api_browser/app/bower_components/lodash/lodash.js +12235 -0
  127. data/lib/api_browser/app/bower_components/lodash/lodash.min.js +98 -0
  128. data/lib/api_browser/app/index.html +0 -1
  129. data/lib/api_browser/app/js/app.js +2 -5
  130. data/lib/api_browser/app/js/controllers/action.js +21 -37
  131. data/lib/api_browser/app/js/controllers/controller.js +23 -1
  132. data/lib/api_browser/app/js/controllers/menu.js +46 -14
  133. data/lib/api_browser/app/js/controllers/type.js +2 -9
  134. data/lib/api_browser/app/js/directives/attribute_description.js +15 -5
  135. data/lib/api_browser/app/js/directives/attribute_table.js +6 -6
  136. data/lib/api_browser/app/js/directives/fixed_if_fits.js +20 -0
  137. data/lib/api_browser/app/js/directives/no_container.js +6 -6
  138. data/lib/api_browser/app/js/directives/type_placeholder.js +21 -0
  139. data/lib/api_browser/app/js/factories/Configuration.js +13 -0
  140. data/lib/api_browser/app/js/factories/Documentation.js +0 -3
  141. data/lib/api_browser/app/js/factories/normalize_attributes.js +19 -0
  142. data/lib/api_browser/app/js/factories/template_for.js +113 -0
  143. data/lib/api_browser/app/sass/modules/_body.scss +26 -4
  144. data/lib/api_browser/app/sass/modules/_sidebar.scss +68 -1
  145. data/lib/api_browser/app/sass/praxis.scss +1 -5
  146. data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +13 -4
  147. data/lib/api_browser/app/views/action.html +13 -17
  148. data/lib/api_browser/app/views/controller.html +32 -4
  149. data/lib/api_browser/app/views/directives/attribute_description.html +1 -1
  150. data/lib/api_browser/app/views/directives/attribute_description/{_default.html → default.html} +0 -0
  151. data/lib/api_browser/app/views/directives/attribute_description/example.html +13 -0
  152. data/lib/api_browser/app/views/directives/attribute_description/headers.html +8 -0
  153. data/lib/api_browser/app/views/directives/attribute_description/member_options.html +4 -0
  154. data/lib/api_browser/app/views/directives/attribute_description/values.html +14 -0
  155. data/lib/api_browser/app/views/directives/attribute_table.html +2 -2
  156. data/lib/api_browser/app/views/home.html +1 -3
  157. data/lib/api_browser/app/views/layout.html +3 -36
  158. data/lib/api_browser/app/views/menu.html +45 -0
  159. data/lib/api_browser/app/views/navbar.html +1 -1
  160. data/lib/api_browser/app/views/type.html +2 -2
  161. data/lib/api_browser/app/views/type/{_details.html → details.html} +6 -6
  162. data/lib/api_browser/app/views/types/embedded/default.html +10 -0
  163. data/lib/api_browser/app/views/types/embedded/links.html +11 -0
  164. data/lib/api_browser/app/views/types/embedded/struct.html +2 -0
  165. data/lib/api_browser/app/views/types/label/link.html +1 -0
  166. data/lib/api_browser/app/views/types/label/primitive.html +1 -0
  167. data/lib/api_browser/app/views/types/label/primitive_collection.html +1 -0
  168. data/lib/api_browser/app/views/types/label/type.html +1 -0
  169. data/lib/api_browser/app/views/types/label/type_collection.html +1 -0
  170. data/lib/api_browser/app/views/{directives/request_body/_default.html → types/standalone/default.html} +1 -1
  171. data/lib/api_browser/app/views/types/standalone/struct.html +1 -0
  172. data/lib/api_browser/bower.json +9 -9
  173. data/lib/api_browser/package.json +1 -1
  174. data/lib/praxis.rb +10 -4
  175. data/lib/praxis/action_definition.rb +16 -4
  176. data/lib/praxis/action_definition/headers_dsl_compiler.rb +5 -2
  177. data/lib/praxis/api_definition.rb +3 -1
  178. data/lib/praxis/api_general_info.rb +49 -5
  179. data/lib/praxis/application.rb +12 -4
  180. data/lib/praxis/bootloader.rb +1 -0
  181. data/lib/praxis/bootloader_stages/environment.rb +2 -0
  182. data/lib/praxis/bootloader_stages/routing.rb +1 -1
  183. data/lib/praxis/bootloader_stages/subgroup_loader.rb +1 -0
  184. data/lib/praxis/exceptions/validation.rb +7 -0
  185. data/lib/praxis/handlers/plain.rb +16 -0
  186. data/lib/praxis/handlers/xml.rb +4 -4
  187. data/lib/praxis/links.rb +13 -3
  188. data/lib/praxis/media_type_identifier.rb +3 -0
  189. data/lib/praxis/multipart/parser.rb +41 -48
  190. data/lib/praxis/multipart/part.rb +196 -3
  191. data/lib/praxis/request.rb +14 -11
  192. data/lib/praxis/request_stages/request_stage.rb +4 -0
  193. data/lib/praxis/request_stages/response.rb +10 -9
  194. data/lib/praxis/request_stages/validate.rb +1 -7
  195. data/lib/praxis/request_stages/validate_params_and_headers.rb +30 -5
  196. data/lib/praxis/request_stages/validate_payload.rb +14 -5
  197. data/lib/praxis/resource_definition.rb +117 -15
  198. data/lib/praxis/response.rb +6 -5
  199. data/lib/praxis/response_definition.rb +51 -5
  200. data/lib/praxis/responses/http.rb +5 -0
  201. data/lib/praxis/responses/multipart_ok.rb +51 -0
  202. data/lib/praxis/responses/validation_error.rb +7 -7
  203. data/lib/praxis/restful_doc_generator.rb +9 -4
  204. data/lib/praxis/route.rb +3 -2
  205. data/lib/praxis/router.rb +26 -16
  206. data/lib/praxis/router/rack.rb +51 -0
  207. data/lib/praxis/router/simple.rb +146 -0
  208. data/lib/praxis/routing_config.rb +2 -2
  209. data/lib/praxis/trait.rb +1 -1
  210. data/lib/praxis/types/fuzzy_hash.rb +49 -0
  211. data/lib/praxis/types/media_type_common.rb +1 -1
  212. data/lib/praxis/types/multipart.rb +47 -12
  213. data/lib/praxis/types/multipart_array.rb +320 -0
  214. data/lib/praxis/types/multipart_array/part_definition.rb +52 -0
  215. data/lib/praxis/validation_handler.rb +10 -0
  216. data/lib/praxis/version.rb +2 -2
  217. data/praxis.gemspec +3 -3
  218. data/spec/api_browser/directives/type_placeholder_spec.js +134 -0
  219. data/spec/api_browser/factories/normalize_attributes_spec.js +97 -0
  220. data/spec/api_browser/factories/template_for_spec.js +67 -0
  221. data/spec/functional_spec.rb +111 -45
  222. data/spec/praxis/action_definition_spec.rb +31 -7
  223. data/spec/praxis/api_definition_spec.rb +2 -2
  224. data/spec/praxis/api_general_info_spec.rb +25 -0
  225. data/spec/praxis/application_spec.rb +24 -11
  226. data/spec/praxis/handlers/xml_spec.rb +55 -33
  227. data/spec/praxis/links_spec.rb +18 -1
  228. data/spec/praxis/media_type_collection_spec.rb +1 -1
  229. data/spec/praxis/media_type_spec.rb +2 -2
  230. data/spec/praxis/multipart/parser_spec.rb +21 -13
  231. data/spec/praxis/plugins/praxis_mapper_plugin_spec.rb +1 -1
  232. data/spec/praxis/request_spec.rb +52 -24
  233. data/spec/praxis/{request_stages_action_spec.rb → request_stages/action_spec.rb} +1 -1
  234. data/spec/praxis/{request_stage_spec.rb → request_stages/request_stage_spec.rb} +0 -0
  235. data/spec/praxis/{request_stages_validate_spec.rb → request_stages/validate_spec.rb} +1 -1
  236. data/spec/praxis/resource_definition_spec.rb +30 -4
  237. data/spec/praxis/response_definition_spec.rb +60 -19
  238. data/spec/praxis/response_spec.rb +2 -2
  239. data/spec/praxis/responses/validation_error_spec.rb +33 -16
  240. data/spec/praxis/route_spec.rb +4 -2
  241. data/spec/praxis/router_spec.rb +28 -12
  242. data/spec/praxis/routing_config_spec.rb +11 -5
  243. data/spec/praxis/types/collection_spec.rb +1 -1
  244. data/spec/praxis/types/fuzzy_hash_spec.rb +20 -0
  245. data/spec/praxis/types/multipart_array/part_definition_spec.rb +5 -0
  246. data/spec/praxis/types/multipart_array_spec.rb +334 -0
  247. data/spec/praxis/types/multipart_spec.rb +14 -5
  248. data/spec/spec_app/app/controllers/instances.rb +20 -10
  249. data/spec/spec_app/app/controllers/volumes.rb +8 -4
  250. data/spec/spec_app/app/responses/bulk_response.rb +0 -6
  251. data/spec/spec_app/config/environment.rb +13 -0
  252. data/spec/spec_app/design/api.rb +7 -10
  253. data/spec/spec_app/design/media_types/instance.rb +3 -1
  254. data/spec/spec_app/design/resources/instances.rb +50 -41
  255. data/spec/spec_app/design/resources/volume_snapshots.rb +39 -0
  256. data/spec/spec_app/design/resources/volumes.rb +11 -6
  257. data/spec/spec_helper.rb +3 -1
  258. metadata +125 -218
  259. data/lib/api_browser/app/bower_components/angular-ui-router/src/compat.js +0 -146
  260. data/lib/api_browser/app/bower_components/bootstrap-sass/CNAME +0 -1
  261. data/lib/api_browser/app/bower_components/bootstrap-sass/DOCS-LICENSE +0 -319
  262. data/lib/api_browser/app/bower_components/bootstrap-sass/Gemfile +0 -5
  263. data/lib/api_browser/app/bower_components/bootstrap-sass/Gemfile.lock +0 -14
  264. data/lib/api_browser/app/bower_components/bootstrap-sass/Gruntfile.js +0 -244
  265. data/lib/api_browser/app/bower_components/bootstrap-sass/LICENSE +0 -176
  266. data/lib/api_browser/app/bower_components/bootstrap-sass/LICENSE-MIT +0 -21
  267. data/lib/api_browser/app/bower_components/bootstrap-sass/Rakefile +0 -44
  268. data/lib/api_browser/app/bower_components/bootstrap-sass/_config.yml +0 -25
  269. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/ads.html +0 -1
  270. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/footer.html +0 -34
  271. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/header.html +0 -42
  272. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-about.html +0 -12
  273. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-components.html +0 -137
  274. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-css.html +0 -99
  275. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-customize.html +0 -40
  276. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-getting-started.html +0 -44
  277. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-javascript.html +0 -88
  278. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-main.html +0 -37
  279. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/old-bs-docs.html +0 -8
  280. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/social-buttons.html +0 -16
  281. data/lib/api_browser/app/bower_components/bootstrap-sass/_layouts/default.html +0 -79
  282. data/lib/api_browser/app/bower_components/bootstrap-sass/_layouts/home.html +0 -47
  283. data/lib/api_browser/app/bower_components/bootstrap-sass/about.html +0 -93
  284. data/lib/api_browser/app/bower_components/bootstrap-sass/browserstack.json +0 -37
  285. data/lib/api_browser/app/bower_components/bootstrap-sass/components.html +0 -3689
  286. data/lib/api_browser/app/bower_components/bootstrap-sass/composer.json +0 -28
  287. data/lib/api_browser/app/bower_components/bootstrap-sass/css.html +0 -2674
  288. data/lib/api_browser/app/bower_components/bootstrap-sass/customize.html +0 -1715
  289. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap-theme.css +0 -427
  290. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap-theme.min.css +0 -1
  291. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap.css +0 -6350
  292. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap.min.css +0 -1
  293. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/js/bootstrap.js +0 -2002
  294. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/js/bootstrap.min.js +0 -9
  295. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/css/docs.css +0 -1195
  296. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/css/pygments-manni.css +0 -66
  297. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/ico/apple-touch-icon-144-precomposed.png +0 -0
  298. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/ico/favicon.png +0 -0
  299. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/application.js +0 -103
  300. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/customizer.js +0 -332
  301. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/filesaver.js +0 -169
  302. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/holder.js +0 -404
  303. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/ie8-responsive-file-warning.js +0 -12
  304. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/jszip.js +0 -1467
  305. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/less.js +0 -9
  306. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/raw-files.js +0 -3
  307. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/uglify.js +0 -14
  308. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/carousel/carousel.css +0 -148
  309. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/carousel/index.html +0 -206
  310. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/grid/grid.css +0 -28
  311. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/grid/index.html +0 -148
  312. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron-narrow/index.html +0 -82
  313. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron-narrow/jumbotron-narrow.css +0 -79
  314. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron/index.html +0 -99
  315. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron/jumbotron.css +0 -5
  316. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/justified-nav/index.html +0 -83
  317. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/justified-nav/justified-nav.css +0 -88
  318. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-fixed-top/index.html +0 -91
  319. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-fixed-top/navbar-fixed-top.css +0 -4
  320. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-static-top/index.html +0 -92
  321. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-static-top/navbar-static-top.css +0 -7
  322. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar/index.html +0 -88
  323. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar/navbar.css +0 -8
  324. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/non-responsive/index.html +0 -101
  325. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/non-responsive/non-responsive.css +0 -116
  326. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/offcanvas/index.html +0 -130
  327. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/offcanvas/offcanvas.css +0 -50
  328. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/offcanvas/offcanvas.js +0 -5
  329. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/carousel.jpg +0 -0
  330. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/grid.jpg +0 -0
  331. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/jumbotron-narrow.jpg +0 -0
  332. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/jumbotron.jpg +0 -0
  333. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/justified-nav.jpg +0 -0
  334. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/navbar-fixed.jpg +0 -0
  335. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/navbar-static.jpg +0 -0
  336. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/navbar.jpg +0 -0
  337. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/non-responsive.jpg +0 -0
  338. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/offcanvas.jpg +0 -0
  339. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/sign-in.jpg +0 -0
  340. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/starter-template.jpg +0 -0
  341. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/sticky-footer-navbar.jpg +0 -0
  342. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/sticky-footer.jpg +0 -0
  343. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/theme.jpg +0 -0
  344. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/signin/index.html +0 -50
  345. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/signin/signin.css +0 -40
  346. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/starter-template/index.html +0 -68
  347. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/starter-template/starter-template.css +0 -7
  348. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer-navbar/index.html +0 -91
  349. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer-navbar/sticky-footer-navbar.css +0 -45
  350. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer/index.html +0 -55
  351. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer/sticky-footer.css +0 -38
  352. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/theme/index.html +0 -384
  353. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/theme/theme.css +0 -14
  354. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.eot +0 -0
  355. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.svg +0 -229
  356. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.ttf +0 -0
  357. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.woff +0 -0
  358. data/lib/api_browser/app/bower_components/bootstrap-sass/getting-started.html +0 -1021
  359. data/lib/api_browser/app/bower_components/bootstrap-sass/index.html +0 -16
  360. data/lib/api_browser/app/bower_components/bootstrap-sass/javascript.html +0 -1983
  361. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/index.html +0 -52
  362. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/affix.js +0 -25
  363. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/alert.js +0 -62
  364. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/button.js +0 -116
  365. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/carousel.js +0 -87
  366. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/collapse.js +0 -164
  367. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/dropdown.js +0 -219
  368. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/modal.js +0 -196
  369. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/phantom.js +0 -69
  370. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/popover.js +0 -133
  371. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/scrollspy.js +0 -37
  372. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/tab.js +0 -86
  373. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/tooltip.js +0 -437
  374. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/transition.js +0 -13
  375. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/vendor/jquery.js +0 -6
  376. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/vendor/qunit.css +0 -232
  377. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/vendor/qunit.js +0 -1510
  378. data/lib/api_browser/app/bower_components/bootstrap-sass/package.json +0 -40
  379. data/lib/api_browser/app/bower_components/lodash/dist/lodash.compat.js +0 -7157
  380. data/lib/api_browser/app/bower_components/lodash/dist/lodash.compat.min.js +0 -61
  381. data/lib/api_browser/app/bower_components/lodash/dist/lodash.js +0 -6785
  382. data/lib/api_browser/app/bower_components/lodash/dist/lodash.min.js +0 -56
  383. data/lib/api_browser/app/bower_components/lodash/dist/lodash.underscore.js +0 -4979
  384. data/lib/api_browser/app/bower_components/lodash/dist/lodash.underscore.min.js +0 -39
  385. data/lib/api_browser/app/js/directives/attribute_table_row.js +0 -17
  386. data/lib/api_browser/app/js/directives/request_body.js +0 -25
  387. data/lib/api_browser/app/js/directives/request_headers.js +0 -17
  388. data/lib/api_browser/app/js/directives/request_parameters.js +0 -17
  389. data/lib/api_browser/app/js/directives/type_label.js +0 -52
  390. data/lib/api_browser/app/js/factories/PayloadTemplates.js +0 -10
  391. data/lib/api_browser/app/js/factories/TemplateProvider.js +0 -45
  392. data/lib/api_browser/app/js/factories/TypeTemplates.js +0 -11
  393. data/lib/api_browser/app/views/directives/attribute_description/_example.html +0 -13
  394. data/lib/api_browser/app/views/directives/attribute_description/_headers.html +0 -8
  395. data/lib/api_browser/app/views/directives/attribute_table_row/_default.html +0 -10
  396. data/lib/api_browser/app/views/directives/attribute_table_row/_links.html +0 -11
  397. data/lib/api_browser/app/views/directives/attribute_table_row/_struct.html +0 -2
  398. data/lib/api_browser/app/views/directives/request_body/_struct.html +0 -1
  399. data/lib/api_browser/app/views/resource/_actions.html +0 -27
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * State-based routing for AngularJS
3
- * @version v0.2.10
3
+ * @version v0.2.15
4
4
  * @link http://angular-ui.github.com/
5
5
  * @license MIT License, http://www.opensource.org/licenses/MIT
6
6
  */
7
- "undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return I(new(I(function(){},{prototype:a})),b)}function e(a){return H(arguments,function(b){b!==a&&H(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path){if(a.path[d]!==b.path[d])break;c.push(a.path[d])}return c}function g(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function h(a,b,c,d){var e,h=f(c,d),i={},j=[];for(var k in h)if(h[k].params&&h[k].params.length){e=h[k].params;for(var l in e)g(j,e[l])>=0||(j.push(e[l]),i[e[l]]=a[e[l]])}return I({},i,b)}function i(a,b){var c={};return H(a,function(a){var d=b[a];c[a]=null!=d?String(d):null}),c}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e<c.length;e++){var f=c[e];if(a[f]!=b[f])return!1}return!0}function k(a,b){var c={};return H(a,function(a){c[a]=b[a]}),c}function l(a,b){var d=1,f=2,g={},h=[],i=g,j=I(a.when(g),{$$promises:g,$$values:g});this.study=function(g){function k(a,c){if(o[c]!==f){if(n.push(c),o[c]===d)throw n.splice(0,n.indexOf(c)),new Error("Cyclic dependency: "+n.join(" -> "));if(o[c]=d,E(a))m.push(c,[function(){return b.get(a)}],h);else{var e=b.annotate(a);H(e,function(a){a!==c&&g.hasOwnProperty(a)&&k(g[a],a)}),m.push(c,a,e)}n.pop(),o[c]=f}}function l(a){return F(a)&&a.then&&a.$$promises}if(!F(g))throw new Error("'invocables' must be an object");var m=[],n=[],o={};return H(g,k),g=n=o=null,function(d,f,g){function h(){--s||(t||e(r,f.$$values),p.$$values=r,p.$$promises=!0,o.resolve(r))}function k(a){p.$$failure=a,o.reject(a)}function n(c,e,f){function i(a){l.reject(a),k(a)}function j(){if(!C(p.$$failure))try{l.resolve(b.invoke(e,g,r)),l.promise.then(function(a){r[c]=a,h()},i)}catch(a){i(a)}}var l=a.defer(),m=0;H(f,function(a){q.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,q[a].then(function(b){r[a]=b,--m||j()},i))}),m||j(),q[c]=l.promise}if(l(d)&&g===c&&(g=f,f=d,d=null),d){if(!F(d))throw new Error("'locals' must be an object")}else d=i;if(f){if(!l(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=j;var o=a.defer(),p=o.promise,q=p.$$promises={},r=I({},d),s=1+m.length/3,t=!1;if(C(f.$$failure))return k(f.$$failure),p;f.$$values?(t=e(r,f.$$values),h()):(I(q,f.$$promises),f.then(h,k));for(var u=0,v=m.length;v>u;u+=3)d.hasOwnProperty(m[u])?h():n(m[u],m[u+1],m[u+2]);return p}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function m(a,b,c){this.fromConfig=function(a,b,c){return C(a.template)?this.fromString(a.template,b):C(a.templateUrl)?this.fromUrl(a.templateUrl,b):C(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return D(a)?a(b):a},this.fromUrl=function(c,d){return D(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function n(a){function b(b){if(!/^\w+(-+\w+)*$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(f[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");f[b]=!0,j.push(b)}function c(a){return a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&")}var d,e=/([:*])(\w+)|\{(\w+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,f={},g="^",h=0,i=this.segments=[],j=this.params=[];this.source=a;for(var k,l,m;(d=e.exec(a))&&(k=d[2]||d[3],l=d[4]||("*"==d[1]?".*":"[^/]*"),m=a.substring(h,d.index),!(m.indexOf("?")>=0));)g+=c(m)+"("+l+")",b(k),i.push(m),h=e.lastIndex;m=a.substring(h);var n=m.indexOf("?");if(n>=0){var o=this.sourceSearch=m.substring(n);m=m.substring(0,n),this.sourcePath=a.substring(0,h+n),H(o.substring(1).split(/[&?]/),b)}else this.sourcePath=a,this.sourceSearch="";g+=c(m)+"$",i.push(m),this.regexp=new RegExp(g),this.prefix=i[0]}function o(){this.compile=function(a){return new n(a)},this.isMatcher=function(a){return F(a)&&D(a.exec)&&D(a.format)&&D(a.concat)},this.$get=function(){return this}}function p(a){function b(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function c(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function d(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return C(d)?d:!0}var e=[],f=null;this.rule=function(a){if(!D(a))throw new Error("'rule' must be a function");return e.push(a),this},this.otherwise=function(a){if(E(a)){var b=a;a=function(){return b}}else if(!D(a))throw new Error("'rule' must be a function");return f=a,this},this.when=function(e,f){var g,h=E(f);if(E(e)&&(e=a.compile(e)),!h&&!D(f)&&!G(f))throw new Error("invalid 'handler' in when()");var i={matcher:function(b,c){return h&&(g=a.compile(c),c=["$match",function(a){return g.format(a)}]),I(function(a,e){return d(a,c,b.exec(e.path(),e.search()))},{prefix:E(b.prefix)?b.prefix:""})},regex:function(a,e){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(g=e,e=["$match",function(a){return c(g,a)}]),I(function(b,c){return d(b,e,a.exec(c.path()))},{prefix:b(a)})}},j={matcher:a.isMatcher(e),regex:e instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](e,f));throw new Error("invalid 'what' in when()")},this.$get=["$location","$rootScope","$injector",function(a,b,c){function d(b){function d(b){var d=b(c,a);return d?(E(d)&&a.replace().url(d),!0):!1}if(!b||!b.defaultPrevented){var g,h=e.length;for(g=0;h>g;g++)if(d(e[g]))return;f&&d(f)}}return b.$on("$locationChangeSuccess",d),{sync:function(){d()}}}]}function q(a,e,f){function g(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function l(a,b){var d=E(a),e=d?a:a.name,f=g(e);if(f){if(!b)throw new Error("No reference point given for path '"+e+"'");for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=w[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function m(a,b){x[a]||(x[a]=[]),x[a].push(b)}function n(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!E(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(w.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):E(b.parent)?b.parent:"";if(e&&!w[e])return m(e,b.self);for(var f in z)D(z[f])&&(b[f]=z[f](b,z.$delegates[f]));if(w[c]=b,!b[y]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){v.$current.navigable==b&&j(a,c)||v.transitionTo(b,a,{location:!1})}]),x[c])for(var g=0;g<x[c].length;g++)n(x[c][g]);return b}function o(a){return a.indexOf("*")>-1}function p(a){var b=a.split("."),c=v.$current.name.split(".");if("**"===b[0]&&(c=c.slice(c.indexOf(b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(c.indexOf(b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length)return!1;for(var d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return c.join("")===b.join("")}function q(a,b){return E(a)&&!C(b)?z[a]:D(b)&&E(a)?(z[a]&&!z.$delegates[a]&&(z.$delegates[a]=z[a]),z[a]=b,this):this}function r(a,b){return F(a)?b=a:b.name=a,n(b),this}function s(a,e,g,m,n,q,r,s,x){function z(){r.url()!==M&&(r.url(M),r.replace())}function A(a,c,d,f,h){var i=d?c:k(a.params,c),j={$stateParams:i};h.resolve=n.resolve(a.resolve,j,h.resolve,a);var l=[h.resolve.then(function(a){h.globals=a})];return f&&l.push(f),H(a.views,function(c,d){var e=c.resolve&&c.resolve!==a.resolve?c.resolve:{};e.$template=[function(){return g.load(d,{view:c,locals:j,params:i,notify:!1})||""}],l.push(n.resolve(e,j,h.resolve,a).then(function(f){if(D(c.controllerProvider)||G(c.controllerProvider)){var g=b.extend({},e,j);f.$$controller=m.invoke(c.controllerProvider,null,g)}else f.$$controller=c.controller;f.$$state=a,f.$$controllerAs=c.controllerAs,h[d]=f}))}),e.all(l).then(function(){return h})}var B=e.reject(new Error("transition superseded")),F=e.reject(new Error("transition prevented")),K=e.reject(new Error("transition aborted")),L=e.reject(new Error("transition failed")),M=r.url(),N=x.baseHref();return u.locals={resolve:null,globals:{$stateParams:{}}},v={params:{},current:u.self,$current:u,transition:null},v.reload=function(){v.transitionTo(v.current,q,{reload:!0,inherit:!1,notify:!1})},v.go=function(a,b,c){return this.transitionTo(a,b,I({inherit:!0,relative:v.$current},c))},v.transitionTo=function(b,c,f){c=c||{},f=I({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,k=v.$current,n=v.params,o=k.path,p=l(b,f.relative);if(!C(p)){var s={to:b,toParams:c,options:f};if(g=a.$broadcast("$stateNotFound",s,k.self,n),g.defaultPrevented)return z(),K;if(g.retry){if(f.$retry)return z(),L;var w=v.transition=e.when(g.retry);return w.then(function(){return w!==v.transition?B:(s.options.$retry=!0,v.transitionTo(s.to,s.toParams,s.options))},function(){return K}),z(),w}if(b=s.to,c=s.toParams,f=s.options,p=l(b,f.relative),!C(p)){if(f.relative)throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'");throw new Error("No such state '"+b+"'")}}if(p[y])throw new Error("Cannot transition to abstract state '"+b+"'");f.inherit&&(c=h(q,c||{},v.$current,p)),b=p;var x,D,E=b.path,G=u.locals,H=[];for(x=0,D=E[x];D&&D===o[x]&&j(c,n,D.ownParams)&&!f.reload;x++,D=E[x])G=H[x]=D.locals;if(t(b,k,G,f))return b.self.reloadOnSearch!==!1&&z(),v.transition=null,e.when(v.current);if(c=i(b.params,c||{}),f.notify&&(g=a.$broadcast("$stateChangeStart",b.self,c,k.self,n),g.defaultPrevented))return z(),F;for(var N=e.when(G),O=x;O<E.length;O++,D=E[O])G=H[O]=d(G),N=A(D,c,D===b,N,G);var P=v.transition=N.then(function(){var d,e,g;if(v.transition!==P)return B;for(d=o.length-1;d>=x;d--)g=o[d],g.self.onExit&&m.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=x;d<E.length;d++)e=E[d],e.locals=H[d],e.self.onEnter&&m.invoke(e.self.onEnter,e.self,e.locals.globals);if(v.transition!==P)return B;v.$current=b,v.current=b.self,v.params=c,J(v.params,q),v.transition=null;var h=b.navigable;return f.location&&h&&(r.url(h.url.format(h.locals.globals.$stateParams)),"replace"===f.location&&r.replace()),f.notify&&a.$broadcast("$stateChangeSuccess",b.self,c,k.self,n),M=r.url(),v.current},function(d){return v.transition!==P?B:(v.transition=null,a.$broadcast("$stateChangeError",b.self,c,k.self,n,d),z(),e.reject(d))});return P},v.is=function(a,d){var e=l(a);return C(e)?v.$current!==e?!1:C(d)&&null!==d?b.equals(q,d):!0:c},v.includes=function(a,d){if(E(a)&&o(a)){if(!p(a))return!1;a=v.$current.name}var e=l(a);if(!C(e))return c;if(!C(v.$current.includes[e.name]))return!1;var f=!0;return b.forEach(d,function(a,b){C(q[b])&&q[b]===a||(f=!1)}),f},v.href=function(a,b,c){c=I({lossy:!0,inherit:!1,absolute:!1,relative:v.$current},c||{});var d=l(a,c.relative);if(!C(d))return null;b=h(q,b||{},v.$current,d);var e=d&&c.lossy?d.navigable:d,g=e&&e.url?e.url.format(i(d.params,b||{})):null;return!f.html5Mode()&&g&&(g="#"+f.hashPrefix()+g),"/"!==N&&(f.html5Mode()?g=N.slice(0,-1)+g:c.absolute&&(g=N.slice(1)+g)),c.absolute&&g&&(g=r.protocol()+"://"+r.host()+(80==r.port()||443==r.port()?"":":"+r.port())+(!f.html5Mode()&&g?"/":"")+g),g},v.get=function(a,b){if(!C(a)){var c=[];return H(w,function(a){c.push(a.self)}),c}var d=l(a,b);return d&&d.self?d.self:null},v}function t(a,b,c,d){return a!==b||(c!==b.locals||d.reload)&&a.self.reloadOnSearch!==!1?void 0:!0}var u,v,w={},x={},y="abstract",z={parent:function(a){if(C(a.parent)&&a.parent)return l(a.parent);var b=/^(.+)\.[^.]+$/.exec(a.name);return b?l(b[1]):u},data:function(a){return a.parent&&a.parent.data&&(a.data=a.self.data=I({},a.parent.data,a.data)),a.data},url:function(a){var b=a.url;if(E(b))return"^"==b.charAt(0)?e.compile(b.substring(1)):(a.parent.navigable||u).url.concat(b);if(e.isMatcher(b)||null==b)return b;throw new Error("Invalid url '"+b+"' in state '"+a+"'")},navigable:function(a){return a.url?a:a.parent?a.parent.navigable:null},params:function(a){if(!a.params)return a.url?a.url.parameters():a.parent.params;if(!G(a.params))throw new Error("Invalid params in state '"+a+"'");if(a.url)throw new Error("Both params and url specicified in state '"+a+"'");return a.params},views:function(a){var b={};return H(C(a.views)?a.views:{"":a},function(c,d){d.indexOf("@")<0&&(d+="@"+a.parent.name),b[d]=c}),b},ownParams:function(a){if(!a.parent)return a.params;var b={};H(a.params,function(a){b[a]=!0}),H(a.parent.params,function(c){if(!b[c])throw new Error("Missing required parameter '"+c+"' in state '"+a.name+"'");b[c]=!1});var c=[];return H(b,function(a,b){a&&c.push(b)}),c},path:function(a){return a.parent?a.parent.path.concat(a):[]},includes:function(a){var b=a.parent?I({},a.parent.includes):{};return b[a.name]=!0,b},$delegates:{}};u=n({name:"",url:"^",views:null,"abstract":!0}),u.navigable=null,this.decorator=q,this.state=r,this.$get=s,s.$inject=["$rootScope","$q","$view","$injector","$resolve","$stateParams","$location","$urlRouter","$browser"]}function r(){function a(a,b){return{load:function(c,d){var e,f={template:null,controller:null,view:null,locals:null,notify:!0,async:!0,params:{}};return d=I(f,d),d.view&&(e=b.fromConfig(d.view,d.params,d.locals)),e&&d.notify&&a.$broadcast("$viewContentLoading",d),e}}}this.$get=a,a.$inject=["$rootScope","$templateFactory"]}function s(){var a=!1;this.useAnchorScroll=function(){a=!0},this.$get=["$anchorScroll","$timeout",function(b,c){return a?b:function(a){c(function(){a[0].scrollIntoView()},0,!1)}}]}function t(a,c,d){function e(){return c.has?function(a){return c.has(a)?c.get(a):null}:function(a){try{return c.get(a)}catch(b){return null}}}function f(a,b){var c=function(){return{enter:function(a,b,c){b.after(a),c()},leave:function(a,b){a.remove(),b()}}};if(i)return{enter:function(a,b,c){i.enter(a,null,b,c)},leave:function(a,b){i.leave(a,b)}};if(h){var d=h&&h(b,a);return{enter:function(a,b,c){d.enter(a,null,b),c()},leave:function(a,b){d.leave(a),b()}}}return c()}var g=e(),h=g("$animator"),i=g("$animate"),j={restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(c,e,g){return function(c,e,h){function i(){k&&(k.remove(),k=null),m&&(m.$destroy(),m=null),l&&(q.leave(l,function(){k=null}),k=l,l=null)}function j(f){var h=c.$new(),j=l&&l.data("$uiViewName"),k=j&&a.$current&&a.$current.locals[j];if(f||k!==n){var r=g(h,function(a){q.enter(a,e,function(){(b.isDefined(p)&&!p||c.$eval(p))&&d(a)}),i()});n=a.$current.locals[r.data("$uiViewName")],l=r,m=h,m.$emit("$viewContentLoaded"),m.$eval(o)}}var k,l,m,n,o=h.onload||"",p=h.autoscroll,q=f(h,c);c.$on("$stateChangeSuccess",function(){j(!1)}),c.$on("$viewContentLoading",function(){j(!1)}),j(!0)}}};return j}function u(a,b,c){return{restrict:"ECA",priority:-400,compile:function(d){var e=d.html();return function(d,f,g){var h=g.uiView||g.name||"",i=f.inheritedData("$uiView");h.indexOf("@")<0&&(h=h+"@"+(i?i.state.name:"")),f.data("$uiViewName",h);var j=c.$current,k=j&&j.locals[h];if(k){f.data("$uiView",{name:h,state:k.$$state}),f.html(k.$template?k.$template:e);var l=a(f.contents());if(k.$$controller){k.$scope=d;var m=b(k.$$controller,k);k.$$controllerAs&&(d[k.$$controllerAs]=m),f.data("$ngControllerController",m),f.children().data("$ngControllerController",m)}l(d)}}}}}function v(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function w(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function x(a,c){var d=["location","inherit","reload"];return{restrict:"A",require:"?^uiSrefActive",link:function(e,f,g,h){var i=v(g.uiSref),j=null,k=w(f)||a.$current,l="FORM"===f[0].nodeName,m=l?"action":"href",n=!0,o={relative:k},p=e.$eval(g.uiSrefOpts)||{};b.forEach(d,function(a){a in p&&(o[a]=p[a])});var q=function(b){if(b&&(j=b),n){var c=a.href(i.state,j,o);return h&&h.$$setStateInfo(i.state,j),c?void(f[0][m]=c):(n=!1,!1)}};i.paramExpr&&(e.$watch(i.paramExpr,function(a){a!==j&&q(a)},!0),j=e.$eval(i.paramExpr)),q(),l||f.bind("click",function(b){var d=b.which||b.button;d>1||b.ctrlKey||b.metaKey||b.shiftKey||f.attr("target")||(c(function(){a.go(i.state,j,o)}),b.preventDefault())})}}}function y(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs",function(d,e,f){function g(){a.$current.self===i&&h()?e.addClass(l):e.removeClass(l)}function h(){return!k||j(k,b)}var i,k,l;l=c(f.uiSrefActive||"",!1)(d),this.$$setStateInfo=function(b,c){i=a.get(b,w(e)),k=c,g()},d.$on("$stateChangeSuccess",g)}]}}function z(a){return function(b){return a.is(b)}}function A(a){return function(b){return a.includes(b)}}function B(a,b){function e(a){this.locals=a.locals.globals,this.params=this.locals.$stateParams}function f(){this.locals=null,this.params=null}function g(c,g){if(null!=g.redirectTo){var h,j=g.redirectTo;if(E(j))h=j;else{if(!D(j))throw new Error("Invalid 'redirectTo' in when()");h=function(a,b){return j(a,b.path(),b.search())}}b.when(c,h)}else a.state(d(g,{parent:null,name:"route:"+encodeURIComponent(c),url:c,onEnter:e,onExit:f}));return i.push(g),this}function h(a,b,d){function e(a){return""!==a.name?a:c}var f={routes:i,params:d,current:c};return b.$on("$stateChangeStart",function(a,c,d,f){b.$broadcast("$routeChangeStart",e(c),e(f))}),b.$on("$stateChangeSuccess",function(a,c,d,g){f.current=e(c),b.$broadcast("$routeChangeSuccess",e(c),e(g)),J(d,f.params)}),b.$on("$stateChangeError",function(a,c,d,f,g,h){b.$broadcast("$routeChangeError",e(c),e(f),h)}),f}var i=[];e.$inject=["$$state"],this.when=g,this.$get=h,h.$inject=["$state","$rootScope","$routeParams"]}var C=b.isDefined,D=b.isFunction,E=b.isString,F=b.isObject,G=b.isArray,H=b.forEach,I=b.extend,J=b.copy;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),l.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",l),m.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",m),n.prototype.concat=function(a){return new n(this.sourcePath+a+this.sourceSearch)},n.prototype.toString=function(){return this.source},n.prototype.exec=function(a,b){var c=this.regexp.exec(a);if(!c)return null;var d,e=this.params,f=e.length,g=this.segments.length-1,h={};if(g!==c.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");for(d=0;g>d;d++)h[e[d]]=c[d+1];for(;f>d;d++)h[e[d]]=b[e[d]];return h},n.prototype.parameters=function(){return this.params},n.prototype.format=function(a){var b=this.segments,c=this.params;if(!a)return b.join("");var d,e,f,g=b.length-1,h=c.length,i=b[0];for(d=0;g>d;d++)f=a[c[d]],null!=f&&(i+=encodeURIComponent(f)),i+=b[d+1];for(;h>d;d++)f=a[c[d]],null!=f&&(i+=(e?"&":"?")+c[d]+"="+encodeURIComponent(f),e=!0);return i},b.module("ui.router.util").provider("$urlMatcherFactory",o),p.$inject=["$urlMatcherFactoryProvider"],b.module("ui.router.router").provider("$urlRouter",p),q.$inject=["$urlRouterProvider","$urlMatcherFactoryProvider","$locationProvider"],b.module("ui.router.state").value("$stateParams",{}).provider("$state",q),r.$inject=[],b.module("ui.router.state").provider("$view",r),b.module("ui.router.state").provider("$uiViewScroll",s),t.$inject=["$state","$injector","$uiViewScroll"],u.$inject=["$compile","$controller","$state"],b.module("ui.router.state").directive("uiView",t),b.module("ui.router.state").directive("uiView",u),x.$inject=["$state","$timeout"],y.$inject=["$state","$stateParams","$interpolate"],b.module("ui.router.state").directive("uiSref",x).directive("uiSrefActive",y),z.$inject=["$state"],A.$inject=["$state"],b.module("ui.router.state").filter("isState",z).filter("includedByState",A),B.$inject=["$stateProvider","$urlRouterProvider"],b.module("ui.router.compat").provider("$route",B).directive("ngView",t)}(window,window.angular);
7
+ "undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return N(new(N(function(){},{prototype:a})),b)}function e(a){return M(arguments,function(b){b!==a&&M(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path){if(a.path[d]!==b.path[d])break;c.push(a.path[d])}return c}function g(a){if(Object.keys)return Object.keys(a);var b=[];return M(a,function(a,c){b.push(c)}),b}function h(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function i(a,b,c,d){var e,i=f(c,d),j={},k=[];for(var l in i)if(i[l].params&&(e=g(i[l].params),e.length))for(var m in e)h(k,e[m])>=0||(k.push(e[m]),j[e[m]]=a[e[m]]);return N({},j,b)}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e<c.length;e++){var f=c[e];if(a[f]!=b[f])return!1}return!0}function k(a,b){var c={};return M(a,function(a){c[a]=b[a]}),c}function l(a){var b={},c=Array.prototype.concat.apply(Array.prototype,Array.prototype.slice.call(arguments,1));return M(c,function(c){c in a&&(b[c]=a[c])}),b}function m(a){var b={},c=Array.prototype.concat.apply(Array.prototype,Array.prototype.slice.call(arguments,1));for(var d in a)-1==h(c,d)&&(b[d]=a[d]);return b}function n(a,b){var c=L(a),d=c?[]:{};return M(a,function(a,e){b(a,e)&&(d[c?d.length:e]=a)}),d}function o(a,b){var c=L(a)?[]:{};return M(a,function(a,d){c[d]=b(a,d)}),c}function p(a,b){var d=1,f=2,i={},j=[],k=i,l=N(a.when(i),{$$promises:i,$$values:i});this.study=function(i){function n(a,c){if(s[c]!==f){if(r.push(c),s[c]===d)throw r.splice(0,h(r,c)),new Error("Cyclic dependency: "+r.join(" -> "));if(s[c]=d,J(a))q.push(c,[function(){return b.get(a)}],j);else{var e=b.annotate(a);M(e,function(a){a!==c&&i.hasOwnProperty(a)&&n(i[a],a)}),q.push(c,a,e)}r.pop(),s[c]=f}}function o(a){return K(a)&&a.then&&a.$$promises}if(!K(i))throw new Error("'invocables' must be an object");var p=g(i||{}),q=[],r=[],s={};return M(i,n),i=r=s=null,function(d,f,g){function h(){--u||(v||e(t,f.$$values),r.$$values=t,r.$$promises=r.$$promises||!0,delete r.$$inheritedValues,n.resolve(t))}function i(a){r.$$failure=a,n.reject(a)}function j(c,e,f){function j(a){l.reject(a),i(a)}function k(){if(!H(r.$$failure))try{l.resolve(b.invoke(e,g,t)),l.promise.then(function(a){t[c]=a,h()},j)}catch(a){j(a)}}var l=a.defer(),m=0;M(f,function(a){s.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,s[a].then(function(b){t[a]=b,--m||k()},j))}),m||k(),s[c]=l.promise}if(o(d)&&g===c&&(g=f,f=d,d=null),d){if(!K(d))throw new Error("'locals' must be an object")}else d=k;if(f){if(!o(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=l;var n=a.defer(),r=n.promise,s=r.$$promises={},t=N({},d),u=1+q.length/3,v=!1;if(H(f.$$failure))return i(f.$$failure),r;f.$$inheritedValues&&e(t,m(f.$$inheritedValues,p)),N(s,f.$$promises),f.$$values?(v=e(t,m(f.$$values,p)),r.$$inheritedValues=m(f.$$values,p),h()):(f.$$inheritedValues&&(r.$$inheritedValues=m(f.$$inheritedValues,p)),f.then(h,i));for(var w=0,x=q.length;x>w;w+=3)d.hasOwnProperty(q[w])?h():j(q[w],q[w+1],q[w+2]);return r}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function q(a,b,c){this.fromConfig=function(a,b,c){return H(a.template)?this.fromString(a.template,b):H(a.templateUrl)?this.fromUrl(a.templateUrl,b):H(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return I(a)?a(b):a},this.fromUrl=function(c,d){return I(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b,headers:{Accept:"text/html"}}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function r(a,b,e){function f(b,c,d,e){if(q.push(b),o[b])return o[b];if(!/^\w+(-+\w+)*(?:\[\])?$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(p[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");return p[b]=new P.Param(b,c,d,e),p[b]}function g(a,b,c,d){var e=["",""],f=a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!b)return f;switch(c){case!1:e=["(",")"+(d?"?":"")];break;case!0:e=["?(",")?"];break;default:e=["("+c+"|",")?"]}return f+e[0]+b+e[1]}function h(e,f){var g,h,i,j,k;return g=e[2]||e[3],k=b.params[g],i=a.substring(m,e.index),h=f?e[4]:e[4]||("*"==e[1]?".*":null),j=P.type(h||"string")||d(P.type("string"),{pattern:new RegExp(h,b.caseInsensitive?"i":c)}),{id:g,regexp:h,segment:i,type:j,cfg:k}}b=N({params:{}},K(b)?b:{});var i,j=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,k=/([:]?)([\w\[\]-]+)|\{([\w\[\]-]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,l="^",m=0,n=this.segments=[],o=e?e.params:{},p=this.params=e?e.params.$$new():new P.ParamSet,q=[];this.source=a;for(var r,s,t;(i=j.exec(a))&&(r=h(i,!1),!(r.segment.indexOf("?")>=0));)s=f(r.id,r.type,r.cfg,"path"),l+=g(r.segment,s.type.pattern.source,s.squash,s.isOptional),n.push(r.segment),m=j.lastIndex;t=a.substring(m);var u=t.indexOf("?");if(u>=0){var v=this.sourceSearch=t.substring(u);if(t=t.substring(0,u),this.sourcePath=a.substring(0,m+u),v.length>0)for(m=0;i=k.exec(v);)r=h(i,!0),s=f(r.id,r.type,r.cfg,"search"),m=j.lastIndex}else this.sourcePath=a,this.sourceSearch="";l+=g(t)+(b.strict===!1?"/?":"")+"$",n.push(t),this.regexp=new RegExp(l,b.caseInsensitive?"i":c),this.prefix=n[0],this.$$paramNames=q}function s(a){N(this,a)}function t(){function a(a){return null!=a?a.toString().replace(/\//g,"%2F"):a}function e(a){return null!=a?a.toString().replace(/%2F/g,"/"):a}function f(){return{strict:p,caseInsensitive:m}}function i(a){return I(a)||L(a)&&I(a[a.length-1])}function j(){for(;w.length;){var a=w.shift();if(a.pattern)throw new Error("You cannot override a type's .pattern at runtime.");b.extend(u[a.name],l.invoke(a.def))}}function k(a){N(this,a||{})}P=this;var l,m=!1,p=!0,q=!1,u={},v=!0,w=[],x={string:{encode:a,decode:e,is:function(a){return null==a||!H(a)||"string"==typeof a},pattern:/[^/]*/},"int":{encode:a,decode:function(a){return parseInt(a,10)},is:function(a){return H(a)&&this.decode(a.toString())===a},pattern:/\d+/},bool:{encode:function(a){return a?1:0},decode:function(a){return 0!==parseInt(a,10)},is:function(a){return a===!0||a===!1},pattern:/0|1/},date:{encode:function(a){return this.is(a)?[a.getFullYear(),("0"+(a.getMonth()+1)).slice(-2),("0"+a.getDate()).slice(-2)].join("-"):c},decode:function(a){if(this.is(a))return a;var b=this.capture.exec(a);return b?new Date(b[1],b[2]-1,b[3]):c},is:function(a){return a instanceof Date&&!isNaN(a.valueOf())},equals:function(a,b){return this.is(a)&&this.is(b)&&a.toISOString()===b.toISOString()},pattern:/[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,capture:/([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/},json:{encode:b.toJson,decode:b.fromJson,is:b.isObject,equals:b.equals,pattern:/[^/]*/},any:{encode:b.identity,decode:b.identity,equals:b.equals,pattern:/.*/}};t.$$getDefaultValue=function(a){if(!i(a.value))return a.value;if(!l)throw new Error("Injectable functions cannot be called at configuration time");return l.invoke(a.value)},this.caseInsensitive=function(a){return H(a)&&(m=a),m},this.strictMode=function(a){return H(a)&&(p=a),p},this.defaultSquashPolicy=function(a){if(!H(a))return q;if(a!==!0&&a!==!1&&!J(a))throw new Error("Invalid squash policy: "+a+". Valid policies: false, true, arbitrary-string");return q=a,a},this.compile=function(a,b){return new r(a,N(f(),b))},this.isMatcher=function(a){if(!K(a))return!1;var b=!0;return M(r.prototype,function(c,d){I(c)&&(b=b&&H(a[d])&&I(a[d]))}),b},this.type=function(a,b,c){if(!H(b))return u[a];if(u.hasOwnProperty(a))throw new Error("A type named '"+a+"' has already been defined.");return u[a]=new s(N({name:a},b)),c&&(w.push({name:a,def:c}),v||j()),this},M(x,function(a,b){u[b]=new s(N({name:b},a))}),u=d(u,{}),this.$get=["$injector",function(a){return l=a,v=!1,j(),M(x,function(a,b){u[b]||(u[b]=new s(a))}),this}],this.Param=function(a,b,d,e){function f(a){var b=K(a)?g(a):[],c=-1===h(b,"value")&&-1===h(b,"type")&&-1===h(b,"squash")&&-1===h(b,"array");return c&&(a={value:a}),a.$$fn=i(a.value)?a.value:function(){return a.value},a}function j(b,c,d){if(b.type&&c)throw new Error("Param '"+a+"' has two type configurations.");return c?c:b.type?b.type instanceof s?b.type:new s(b.type):"config"===d?u.any:u.string}function k(){var b={array:"search"===e?"auto":!1},c=a.match(/\[\]$/)?{array:!0}:{};return N(b,c,d).array}function m(a,b){var c=a.squash;if(!b||c===!1)return!1;if(!H(c)||null==c)return q;if(c===!0||J(c))return c;throw new Error("Invalid squash policy: '"+c+"'. Valid policies: false, true, or arbitrary string")}function p(a,b,d,e){var f,g,i=[{from:"",to:d||b?c:""},{from:null,to:d||b?c:""}];return f=L(a.replace)?a.replace:[],J(e)&&f.push({from:e,to:c}),g=o(f,function(a){return a.from}),n(i,function(a){return-1===h(g,a.from)}).concat(f)}function r(){if(!l)throw new Error("Injectable functions cannot be called at configuration time");var a=l.invoke(d.$$fn);if(null!==a&&a!==c&&!w.type.is(a))throw new Error("Default value ("+a+") for parameter '"+w.id+"' is not an instance of Type ("+w.type.name+")");return a}function t(a){function b(a){return function(b){return b.from===a}}function c(a){var c=o(n(w.replace,b(a)),function(a){return a.to});return c.length?c[0]:a}return a=c(a),H(a)?w.type.$normalize(a):r()}function v(){return"{Param:"+a+" "+b+" squash: '"+z+"' optional: "+y+"}"}var w=this;d=f(d),b=j(d,b,e);var x=k();b=x?b.$asArray(x,"search"===e):b,"string"!==b.name||x||"path"!==e||d.value!==c||(d.value="");var y=d.value!==c,z=m(d,y),A=p(d,x,y,z);N(this,{id:a,type:b,location:e,array:x,squash:z,replace:A,isOptional:y,value:t,dynamic:c,config:d,toString:v})},k.prototype={$$new:function(){return d(this,N(new k,{$$parent:this}))},$$keys:function(){for(var a=[],b=[],c=this,d=g(k.prototype);c;)b.push(c),c=c.$$parent;return b.reverse(),M(b,function(b){M(g(b),function(b){-1===h(a,b)&&-1===h(d,b)&&a.push(b)})}),a},$$values:function(a){var b={},c=this;return M(c.$$keys(),function(d){b[d]=c[d].value(a&&a[d])}),b},$$equals:function(a,b){var c=!0,d=this;return M(d.$$keys(),function(e){var f=a&&a[e],g=b&&b[e];d[e].type.equals(f,g)||(c=!1)}),c},$$validates:function(a){var d,e,f,g,h,i=this.$$keys();for(d=0;d<i.length&&(e=this[i[d]],f=a[i[d]],f!==c&&null!==f||!e.isOptional);d++){if(g=e.type.$normalize(f),!e.type.is(g))return!1;if(h=e.type.encode(g),b.isString(h)&&!e.type.pattern.exec(h))return!1}return!0},$$parent:c},this.ParamSet=k}function u(a,d){function e(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function f(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function g(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return H(d)?d:!0}function h(d,e,f,g){function h(a,b,c){return"/"===p?a:b?p.slice(0,-1)+a:c?p.slice(1)+a:a}function m(a){function b(a){var b=a(f,d);return b?(J(b)&&d.replace().url(b),!0):!1}if(!a||!a.defaultPrevented){o&&d.url()===o;o=c;var e,g=j.length;for(e=0;g>e;e++)if(b(j[e]))return;k&&b(k)}}function n(){return i=i||e.$on("$locationChangeSuccess",m)}var o,p=g.baseHref(),q=d.url();return l||n(),{sync:function(){m()},listen:function(){return n()},update:function(a){return a?void(q=d.url()):void(d.url()!==q&&(d.url(q),d.replace()))},push:function(a,b,e){var f=a.format(b||{});null!==f&&b&&b["#"]&&(f+="#"+b["#"]),d.url(f),o=e&&e.$$avoidResync?d.url():c,e&&e.replace&&d.replace()},href:function(c,e,f){if(!c.validates(e))return null;var g=a.html5Mode();b.isObject(g)&&(g=g.enabled);var i=c.format(e);if(f=f||{},g||null===i||(i="#"+a.hashPrefix()+i),null!==i&&e&&e["#"]&&(i+="#"+e["#"]),i=h(i,g,f.absolute),!f.absolute||!i)return i;var j=!g&&i?"/":"",k=d.port();return k=80===k||443===k?"":":"+k,[d.protocol(),"://",d.host(),k,j,i].join("")}}}var i,j=[],k=null,l=!1;this.rule=function(a){if(!I(a))throw new Error("'rule' must be a function");return j.push(a),this},this.otherwise=function(a){if(J(a)){var b=a;a=function(){return b}}else if(!I(a))throw new Error("'rule' must be a function");return k=a,this},this.when=function(a,b){var c,h=J(b);if(J(a)&&(a=d.compile(a)),!h&&!I(b)&&!L(b))throw new Error("invalid 'handler' in when()");var i={matcher:function(a,b){return h&&(c=d.compile(b),b=["$match",function(a){return c.format(a)}]),N(function(c,d){return g(c,b,a.exec(d.path(),d.search()))},{prefix:J(a.prefix)?a.prefix:""})},regex:function(a,b){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(c=b,b=["$match",function(a){return f(c,a)}]),N(function(c,d){return g(c,b,a.exec(d.path()))},{prefix:e(a)})}},j={matcher:d.isMatcher(a),regex:a instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](a,b));throw new Error("invalid 'what' in when()")},this.deferIntercept=function(a){a===c&&(a=!0),l=a},this.$get=h,h.$inject=["$location","$rootScope","$injector","$browser"]}function v(a,e){function f(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function m(a,b){if(!a)return c;var d=J(a),e=d?a:a.name,g=f(e);if(g){if(!b)throw new Error("No reference point given for path '"+e+"'");b=m(b);for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=z[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function n(a,b){A[a]||(A[a]=[]),A[a].push(b)}function p(a){for(var b=A[a]||[];b.length;)q(b.shift())}function q(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!J(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(z.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):J(b.parent)?b.parent:K(b.parent)&&J(b.parent.name)?b.parent.name:"";if(e&&!z[e])return n(e,b.self);for(var f in C)I(C[f])&&(b[f]=C[f](b,C.$delegates[f]));return z[c]=b,!b[B]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){y.$current.navigable==b&&j(a,c)||y.transitionTo(b,a,{inherit:!0,location:!1})}]),p(c),b}function r(a){return a.indexOf("*")>-1}function s(a){for(var b=a.split("."),c=y.$current.name.split("."),d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return"**"===b[0]&&(c=c.slice(h(c,b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(h(c,b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length?!1:c.join("")===b.join("")}function t(a,b){return J(a)&&!H(b)?C[a]:I(b)&&J(a)?(C[a]&&!C.$delegates[a]&&(C.$delegates[a]=C[a]),C[a]=b,this):this}function u(a,b){return K(a)?b=a:b.name=a,q(b),this}function v(a,e,f,h,l,n,p,q,t){function u(b,c,d,f){var g=a.$broadcast("$stateNotFound",b,c,d);if(g.defaultPrevented)return p.update(),D;if(!g.retry)return null;if(f.$retry)return p.update(),E;var h=y.transition=e.when(g.retry);return h.then(function(){return h!==y.transition?A:(b.options.$retry=!0,y.transitionTo(b.to,b.toParams,b.options))},function(){return D}),p.update(),h}function v(a,c,d,g,i,j){function m(){var c=[];return M(a.views,function(d,e){var g=d.resolve&&d.resolve!==a.resolve?d.resolve:{};g.$template=[function(){return f.load(e,{view:d,locals:i.globals,params:n,notify:j.notify})||""}],c.push(l.resolve(g,i.globals,i.resolve,a).then(function(c){if(I(d.controllerProvider)||L(d.controllerProvider)){var f=b.extend({},g,i.globals);c.$$controller=h.invoke(d.controllerProvider,null,f)}else c.$$controller=d.controller;c.$$state=a,c.$$controllerAs=d.controllerAs,i[e]=c}))}),e.all(c).then(function(){return i.globals})}var n=d?c:k(a.params.$$keys(),c),o={$stateParams:n};i.resolve=l.resolve(a.resolve,o,i.resolve,a);var p=[i.resolve.then(function(a){i.globals=a})];return g&&p.push(g),e.all(p).then(m).then(function(a){return i})}var A=e.reject(new Error("transition superseded")),C=e.reject(new Error("transition prevented")),D=e.reject(new Error("transition aborted")),E=e.reject(new Error("transition failed"));return x.locals={resolve:null,globals:{$stateParams:{}}},y={params:{},current:x.self,$current:x,transition:null},y.reload=function(a){return y.transitionTo(y.current,n,{reload:a||!0,inherit:!1,notify:!0})},y.go=function(a,b,c){return y.transitionTo(a,b,N({inherit:!0,relative:y.$current},c))},y.transitionTo=function(b,c,f){c=c||{},f=N({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,j=y.$current,l=y.params,o=j.path,q=m(b,f.relative),r=c["#"];if(!H(q)){var s={to:b,toParams:c,options:f},t=u(s,j.self,l,f);if(t)return t;if(b=s.to,c=s.toParams,f=s.options,q=m(b,f.relative),!H(q)){if(!f.relative)throw new Error("No such state '"+b+"'");throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'")}}if(q[B])throw new Error("Cannot transition to abstract state '"+b+"'");if(f.inherit&&(c=i(n,c||{},y.$current,q)),!q.params.$$validates(c))return E;c=q.params.$$values(c),b=q;var z=b.path,D=0,F=z[D],G=x.locals,I=[];if(f.reload){if(J(f.reload)||K(f.reload)){if(K(f.reload)&&!f.reload.name)throw new Error("Invalid reload state object");var L=f.reload===!0?o[0]:m(f.reload);if(f.reload&&!L)throw new Error("No such reload state '"+(J(f.reload)?f.reload:f.reload.name)+"'");for(;F&&F===o[D]&&F!==L;)G=I[D]=F.locals,D++,F=z[D]}}else for(;F&&F===o[D]&&F.ownParams.$$equals(c,l);)G=I[D]=F.locals,D++,F=z[D];if(w(b,c,j,l,G,f))return r&&(c["#"]=r),y.params=c,O(y.params,n),f.location&&b.navigable&&b.navigable.url&&(p.push(b.navigable.url,c,{$$avoidResync:!0,replace:"replace"===f.location}),p.update(!0)),y.transition=null,e.when(y.current);if(c=k(b.params.$$keys(),c||{}),f.notify&&a.$broadcast("$stateChangeStart",b.self,c,j.self,l).defaultPrevented)return a.$broadcast("$stateChangeCancel",b.self,c,j.self,l),p.update(),C;for(var M=e.when(G),P=D;P<z.length;P++,F=z[P])G=I[P]=d(G),M=v(F,c,F===b,M,G,f);var Q=y.transition=M.then(function(){var d,e,g;if(y.transition!==Q)return A;for(d=o.length-1;d>=D;d--)g=o[d],g.self.onExit&&h.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=D;d<z.length;d++)e=z[d],e.locals=I[d],e.self.onEnter&&h.invoke(e.self.onEnter,e.self,e.locals.globals);return r&&(c["#"]=r),y.transition!==Q?A:(y.$current=b,y.current=b.self,y.params=c,O(y.params,n),y.transition=null,f.location&&b.navigable&&p.push(b.navigable.url,b.navigable.locals.globals.$stateParams,{$$avoidResync:!0,replace:"replace"===f.location}),f.notify&&a.$broadcast("$stateChangeSuccess",b.self,c,j.self,l),p.update(!0),y.current)},function(d){return y.transition!==Q?A:(y.transition=null,g=a.$broadcast("$stateChangeError",b.self,c,j.self,l,d),g.defaultPrevented||p.update(),e.reject(d))});return Q},y.is=function(a,b,d){d=N({relative:y.$current},d||{});var e=m(a,d.relative);return H(e)?y.$current!==e?!1:b?j(e.params.$$values(b),n):!0:c},y.includes=function(a,b,d){if(d=N({relative:y.$current},d||{}),J(a)&&r(a)){if(!s(a))return!1;a=y.$current.name}var e=m(a,d.relative);return H(e)?H(y.$current.includes[e.name])?b?j(e.params.$$values(b),n,g(b)):!0:!1:c},y.href=function(a,b,d){d=N({lossy:!0,inherit:!0,absolute:!1,relative:y.$current},d||{});var e=m(a,d.relative);if(!H(e))return null;d.inherit&&(b=i(n,b||{},y.$current,e));var f=e&&d.lossy?e.navigable:e;return f&&f.url!==c&&null!==f.url?p.href(f.url,k(e.params.$$keys().concat("#"),b||{}),{absolute:d.absolute}):null},y.get=function(a,b){if(0===arguments.length)return o(g(z),function(a){return z[a].self});var c=m(a,b||y.$current);return c&&c.self?c.self:null},y}function w(a,b,c,d,e,f){function g(a,b,c){function d(b){return"search"!=a.params[b].location}var e=a.params.$$keys().filter(d),f=l.apply({},[a.params].concat(e)),g=new P.ParamSet(f);return g.$$equals(b,c)}return!f.reload&&a===c&&(e===c.locals||a.self.reloadOnSearch===!1&&g(c,d,b))?!0:void 0}var x,y,z={},A={},B="abstract",C={parent:function(a){if(H(a.parent)&&a.parent)return m(a.parent);var b=/^(.+)\.[^.]+$/.exec(a.name);return b?m(b[1]):x},data:function(a){return a.parent&&a.parent.data&&(a.data=a.self.data=N({},a.parent.data,a.data)),a.data},url:function(a){var b=a.url,c={params:a.params||{}};if(J(b))return"^"==b.charAt(0)?e.compile(b.substring(1),c):(a.parent.navigable||x).url.concat(b,c);if(!b||e.isMatcher(b))return b;throw new Error("Invalid url '"+b+"' in state '"+a+"'")},navigable:function(a){return a.url?a:a.parent?a.parent.navigable:null},ownParams:function(a){var b=a.url&&a.url.params||new P.ParamSet;return M(a.params||{},function(a,c){b[c]||(b[c]=new P.Param(c,null,a,"config"))}),b},params:function(a){return a.parent&&a.parent.params?N(a.parent.params.$$new(),a.ownParams):new P.ParamSet},views:function(a){var b={};return M(H(a.views)?a.views:{"":a},function(c,d){d.indexOf("@")<0&&(d+="@"+a.parent.name),b[d]=c}),b},path:function(a){return a.parent?a.parent.path.concat(a):[]},includes:function(a){var b=a.parent?N({},a.parent.includes):{};return b[a.name]=!0,b},$delegates:{}};x=q({name:"",url:"^",views:null,"abstract":!0}),x.navigable=null,this.decorator=t,this.state=u,this.$get=v,v.$inject=["$rootScope","$q","$view","$injector","$resolve","$stateParams","$urlRouter","$location","$urlMatcherFactory"]}function w(){function a(a,b){return{load:function(c,d){var e,f={template:null,controller:null,view:null,locals:null,notify:!0,async:!0,params:{}};return d=N(f,d),d.view&&(e=b.fromConfig(d.view,d.params,d.locals)),e&&d.notify&&a.$broadcast("$viewContentLoading",d),e}}}this.$get=a,a.$inject=["$rootScope","$templateFactory"]}function x(){var a=!1;this.useAnchorScroll=function(){a=!0},this.$get=["$anchorScroll","$timeout",function(b,c){return a?b:function(a){return c(function(){a[0].scrollIntoView()},0,!1)}}]}function y(a,c,d,e){function f(){return c.has?function(a){return c.has(a)?c.get(a):null}:function(a){try{return c.get(a)}catch(b){return null}}}function g(a,b){var c=function(){return{enter:function(a,b,c){b.after(a),c()},leave:function(a,b){a.remove(),b()}}};if(j)return{enter:function(a,b,c){var d=j.enter(a,null,b,c);d&&d.then&&d.then(c)},leave:function(a,b){var c=j.leave(a,b);c&&c.then&&c.then(b)}};if(i){var d=i&&i(b,a);return{enter:function(a,b,c){d.enter(a,null,b),c()},leave:function(a,b){d.leave(a),b()}}}return c()}var h=f(),i=h("$animator"),j=h("$animate"),k={restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(c,f,h){return function(c,f,i){function j(){l&&(l.remove(),l=null),n&&(n.$destroy(),n=null),m&&(r.leave(m,function(){l=null}),l=m,m=null)}function k(g){var k,l=A(c,i,f,e),s=l&&a.$current&&a.$current.locals[l];if(g||s!==o){k=c.$new(),o=a.$current.locals[l];var t=h(k,function(a){r.enter(a,f,function(){n&&n.$emit("$viewContentAnimationEnded"),(b.isDefined(q)&&!q||c.$eval(q))&&d(a)}),j()});m=t,n=k,n.$emit("$viewContentLoaded"),n.$eval(p)}}var l,m,n,o,p=i.onload||"",q=i.autoscroll,r=g(i,c);c.$on("$stateChangeSuccess",function(){k(!1)}),c.$on("$viewContentLoading",function(){k(!1)}),k(!0)}}};return k}function z(a,b,c,d){return{restrict:"ECA",priority:-400,compile:function(e){var f=e.html();return function(e,g,h){var i=c.$current,j=A(e,h,g,d),k=i&&i.locals[j];if(k){g.data("$uiView",{name:j,state:k.$$state}),g.html(k.$template?k.$template:f);var l=a(g.contents());if(k.$$controller){k.$scope=e,k.$element=g;var m=b(k.$$controller,k);k.$$controllerAs&&(e[k.$$controllerAs]=m),g.data("$ngControllerController",m),g.children().data("$ngControllerController",m)}l(e)}}}}}function A(a,b,c,d){var e=d(b.uiView||b.name||"")(a),f=c.inheritedData("$uiView");return e.indexOf("@")>=0?e:e+"@"+(f?f.state.name:"")}function B(a,b){var c,d=a.match(/^\s*({[^}]*})\s*$/);if(d&&(a=b+"("+d[1]+")"),c=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!c||4!==c.length)throw new Error("Invalid state ref '"+a+"'");return{state:c[1],paramExpr:c[3]||null}}function C(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function D(a,c){var d=["location","inherit","reload","absolute"];return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(e,f,g,h){var i=B(g.uiSref,a.current.name),j=null,k=C(f)||a.$current,l="[object SVGAnimatedString]"===Object.prototype.toString.call(f.prop("href"))?"xlink:href":"href",m=null,n="A"===f.prop("tagName").toUpperCase(),o="FORM"===f[0].nodeName,p=o?"action":l,q=!0,r={relative:k,inherit:!0},s=e.$eval(g.uiSrefOpts)||{};b.forEach(d,function(a){a in s&&(r[a]=s[a])});var t=function(c){if(c&&(j=b.copy(c)),q){m=a.href(i.state,j,r);var d=h[1]||h[0];return d&&d.$$addStateInfo(i.state,j),null===m?(q=!1,!1):void g.$set(p,m)}};i.paramExpr&&(e.$watch(i.paramExpr,function(a,b){a!==j&&t(a)},!0),j=b.copy(e.$eval(i.paramExpr))),t(),o||f.bind("click",function(b){var d=b.which||b.button;if(!(d>1||b.ctrlKey||b.metaKey||b.shiftKey||f.attr("target"))){var e=c(function(){a.go(i.state,j,r)});b.preventDefault();var g=n&&!m?1:0;b.preventDefault=function(){g--<=0&&c.cancel(e)}}})}}}function E(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs",function(b,d,e){function f(){g()?d.addClass(i):d.removeClass(i)}function g(){for(var a=0;a<j.length;a++)if(h(j[a].state,j[a].params))return!0;return!1}function h(b,c){return"undefined"!=typeof e.uiSrefActiveEq?a.is(b.name,c):a.includes(b.name,c)}var i,j=[];i=c(e.uiSrefActiveEq||e.uiSrefActive||"",!1)(b),this.$$addStateInfo=function(b,c){var e=a.get(b,C(d));j.push({state:e||{name:b},params:c}),f()},b.$on("$stateChangeSuccess",f)}]}}function F(a){var b=function(b){return a.is(b)};return b.$stateful=!0,b}function G(a){var b=function(b){return a.includes(b)};return b.$stateful=!0,b}var H=b.isDefined,I=b.isFunction,J=b.isString,K=b.isObject,L=b.isArray,M=b.forEach,N=b.extend,O=b.copy;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),p.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",p),q.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",q);var P;r.prototype.concat=function(a,b){var c={caseInsensitive:P.caseInsensitive(),strict:P.strictMode(),squash:P.defaultSquashPolicy()};return new r(this.sourcePath+a+this.sourceSearch,N(c,b),this)},r.prototype.toString=function(){return this.source},r.prototype.exec=function(a,b){function c(a){function b(a){return a.split("").reverse().join("")}function c(a){return a.replace(/\\-/g,"-")}var d=b(a).split(/-(?!\\)/),e=o(d,b);return o(e,c).reverse()}var d=this.regexp.exec(a);if(!d)return null;b=b||{};var e,f,g,h=this.parameters(),i=h.length,j=this.segments.length-1,k={};if(j!==d.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");for(e=0;j>e;e++){g=h[e];var l=this.params[g],m=d[e+1];for(f=0;f<l.replace;f++)l.replace[f].from===m&&(m=l.replace[f].to);m&&l.array===!0&&(m=c(m)),k[g]=l.value(m)}for(;i>e;e++)g=h[e],k[g]=this.params[g].value(b[g]);return k},r.prototype.parameters=function(a){return H(a)?this.params[a]||null:this.$$paramNames},r.prototype.validates=function(a){return this.params.$$validates(a)},r.prototype.format=function(a){function b(a){return encodeURIComponent(a).replace(/-/g,function(a){return"%5C%"+a.charCodeAt(0).toString(16).toUpperCase()})}a=a||{};var c=this.segments,d=this.parameters(),e=this.params;if(!this.validates(a))return null;var f,g=!1,h=c.length-1,i=d.length,j=c[0];for(f=0;i>f;f++){var k=h>f,l=d[f],m=e[l],n=m.value(a[l]),p=m.isOptional&&m.type.equals(m.value(),n),q=p?m.squash:!1,r=m.type.encode(n);if(k){var s=c[f+1];if(q===!1)null!=r&&(j+=L(r)?o(r,b).join("-"):encodeURIComponent(r)),j+=s;else if(q===!0){var t=j.match(/\/$/)?/\/?(.*)/:/(.*)/;j+=s.match(t)[1]}else J(q)&&(j+=q+s)}else{if(null==r||p&&q!==!1)continue;L(r)||(r=[r]),r=o(r,encodeURIComponent).join("&"+l+"="),j+=(g?"&":"?")+(l+"="+r),g=!0}}return j},s.prototype.is=function(a,b){return!0},s.prototype.encode=function(a,b){return a},s.prototype.decode=function(a,b){return a},s.prototype.equals=function(a,b){return a==b},s.prototype.$subPattern=function(){var a=this.pattern.toString();return a.substr(1,a.length-2)},s.prototype.pattern=/.*/,s.prototype.toString=function(){return"{Type:"+this.name+"}"},s.prototype.$normalize=function(a){return this.is(a)?a:this.decode(a)},s.prototype.$asArray=function(a,b){function d(a,b){function d(a,b){return function(){return a[b].apply(a,arguments)}}function e(a){return L(a)?a:H(a)?[a]:[]}function f(a){switch(a.length){case 0:return c;case 1:return"auto"===b?a[0]:a;default:return a}}function g(a){return!a}function h(a,b){return function(c){c=e(c);var d=o(c,a);return b===!0?0===n(d,g).length:f(d)}}function i(a){return function(b,c){var d=e(b),f=e(c);if(d.length!==f.length)return!1;for(var g=0;g<d.length;g++)if(!a(d[g],f[g]))return!1;return!0}}this.encode=h(d(a,"encode")),this.decode=h(d(a,"decode")),this.is=h(d(a,"is"),!0),this.equals=i(d(a,"equals")),this.pattern=a.pattern,this.$normalize=h(d(a,"$normalize")),this.name=a.name,this.$arrayMode=b}if(!a)return this;if("auto"===a&&!b)throw new Error("'auto' array mode is for query parameters only");return new d(this,a)},b.module("ui.router.util").provider("$urlMatcherFactory",t),b.module("ui.router.util").run(["$urlMatcherFactory",function(a){}]),u.$inject=["$locationProvider","$urlMatcherFactoryProvider"],b.module("ui.router.router").provider("$urlRouter",u),v.$inject=["$urlRouterProvider","$urlMatcherFactoryProvider"],b.module("ui.router.state").value("$stateParams",{}).provider("$state",v),w.$inject=[],b.module("ui.router.state").provider("$view",w),b.module("ui.router.state").provider("$uiViewScroll",x),y.$inject=["$state","$injector","$uiViewScroll","$interpolate"],z.$inject=["$compile","$controller","$state","$interpolate"],b.module("ui.router.state").directive("uiView",y),b.module("ui.router.state").directive("uiView",z),D.$inject=["$state","$timeout"],E.$inject=["$state","$stateParams","$interpolate"],b.module("ui.router.state").directive("uiSref",D).directive("uiSrefActive",E).directive("uiSrefActiveEq",E),F.$inject=["$state"],G.$inject=["$state"],b.module("ui.router.state").filter("isState",F).filter("includedByState",G)}(window,window.angular);
@@ -49,13 +49,13 @@ function ancestors(first, second) {
49
49
  * @param {Object} object A JavaScript object.
50
50
  * @return {Array} Returns the keys of the object as an array.
51
51
  */
52
- function keys(object) {
52
+ function objectKeys(object) {
53
53
  if (Object.keys) {
54
54
  return Object.keys(object);
55
55
  }
56
56
  var result = [];
57
57
 
58
- angular.forEach(object, function(val, key) {
58
+ forEach(object, function(val, key) {
59
59
  result.push(key);
60
60
  });
61
61
  return result;
@@ -68,7 +68,7 @@ function keys(object) {
68
68
  * @param {*} value A value to search the array for.
69
69
  * @return {Number} Returns the array index value of `value`, or `-1` if not present.
70
70
  */
71
- function arraySearch(array, value) {
71
+ function indexOf(array, value) {
72
72
  if (Array.prototype.indexOf) {
73
73
  return array.indexOf(value, Number(arguments[2]) || 0);
74
74
  }
@@ -96,11 +96,12 @@ function inheritParams(currentParams, newParams, $current, $to) {
96
96
  var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = [];
97
97
 
98
98
  for (var i in parents) {
99
- if (!parents[i].params || !parents[i].params.length) continue;
100
- parentParams = parents[i].params;
99
+ if (!parents[i].params) continue;
100
+ parentParams = objectKeys(parents[i].params);
101
+ if (!parentParams.length) continue;
101
102
 
102
103
  for (var j in parentParams) {
103
- if (arraySearch(inheritList, parentParams[j]) >= 0) continue;
104
+ if (indexOf(inheritList, parentParams[j]) >= 0) continue;
104
105
  inheritList.push(parentParams[j]);
105
106
  inherited[parentParams[j]] = currentParams[parentParams[j]];
106
107
  }
@@ -108,23 +109,6 @@ function inheritParams(currentParams, newParams, $current, $to) {
108
109
  return extend({}, inherited, newParams);
109
110
  }
110
111
 
111
- /**
112
- * Normalizes a set of values to string or `null`, filtering them by a list of keys.
113
- *
114
- * @param {Array} keys The list of keys to normalize/return.
115
- * @param {Object} values An object hash of values to normalize.
116
- * @return {Object} Returns an object hash of normalized string values.
117
- */
118
- function normalize(keys, values) {
119
- var normalized = {};
120
-
121
- forEach(keys, function (name) {
122
- var value = values[name];
123
- normalized[name] = (value != null) ? String(value) : null;
124
- });
125
- return normalized;
126
- }
127
-
128
112
  /**
129
113
  * Performs a non-strict comparison of the subset of two objects, defined by a list of keys.
130
114
  *
@@ -162,6 +146,68 @@ function filterByKeys(keys, values) {
162
146
  });
163
147
  return filtered;
164
148
  }
149
+
150
+ // like _.indexBy
151
+ // when you know that your index values will be unique, or you want last-one-in to win
152
+ function indexBy(array, propName) {
153
+ var result = {};
154
+ forEach(array, function(item) {
155
+ result[item[propName]] = item;
156
+ });
157
+ return result;
158
+ }
159
+
160
+ // extracted from underscore.js
161
+ // Return a copy of the object only containing the whitelisted properties.
162
+ function pick(obj) {
163
+ var copy = {};
164
+ var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
165
+ forEach(keys, function(key) {
166
+ if (key in obj) copy[key] = obj[key];
167
+ });
168
+ return copy;
169
+ }
170
+
171
+ // extracted from underscore.js
172
+ // Return a copy of the object omitting the blacklisted properties.
173
+ function omit(obj) {
174
+ var copy = {};
175
+ var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
176
+ for (var key in obj) {
177
+ if (indexOf(keys, key) == -1) copy[key] = obj[key];
178
+ }
179
+ return copy;
180
+ }
181
+
182
+ function pluck(collection, key) {
183
+ var result = isArray(collection) ? [] : {};
184
+
185
+ forEach(collection, function(val, i) {
186
+ result[i] = isFunction(key) ? key(val) : val[key];
187
+ });
188
+ return result;
189
+ }
190
+
191
+ function filter(collection, callback) {
192
+ var array = isArray(collection);
193
+ var result = array ? [] : {};
194
+ forEach(collection, function(val, i) {
195
+ if (callback(val, i)) {
196
+ result[array ? result.length : i] = val;
197
+ }
198
+ });
199
+ return result;
200
+ }
201
+
202
+ function map(collection, callback) {
203
+ var result = isArray(collection) ? [] : {};
204
+
205
+ forEach(collection, function(val, i) {
206
+ result[i] = callback(val, i);
207
+ });
208
+ return result;
209
+ }
210
+
165
211
  /**
166
212
  * @ngdoc overview
167
213
  * @name ui.router.util
@@ -41,6 +41,7 @@ function $Resolve( $q, $injector) {
41
41
  */
42
42
  this.study = function (invocables) {
43
43
  if (!isObject(invocables)) throw new Error("'invocables' must be an object");
44
+ var invocableKeys = objectKeys(invocables || {});
44
45
 
45
46
  // Perform a topological sort of invocables to build an ordered plan
46
47
  var plan = [], cycle = [], visited = {};
@@ -49,7 +50,7 @@ function $Resolve( $q, $injector) {
49
50
 
50
51
  cycle.push(key);
51
52
  if (visited[key] === VISIT_IN_PROGRESS) {
52
- cycle.splice(0, cycle.indexOf(key));
53
+ cycle.splice(0, indexOf(cycle, key));
53
54
  throw new Error("Cyclic dependency: " + cycle.join(" -> "));
54
55
  }
55
56
  visited[key] = VISIT_IN_PROGRESS;
@@ -101,7 +102,8 @@ function $Resolve( $q, $injector) {
101
102
  if (!--wait) {
102
103
  if (!merged) merge(values, parent.$$values);
103
104
  result.$$values = values;
104
- result.$$promises = true; // keep for isResolve()
105
+ result.$$promises = result.$$promises || true; // keep for isResolve()
106
+ delete result.$$inheritedValues;
105
107
  resolution.resolve(values);
106
108
  }
107
109
  }
@@ -110,20 +112,28 @@ function $Resolve( $q, $injector) {
110
112
  result.$$failure = reason;
111
113
  resolution.reject(reason);
112
114
  }
113
-
115
+
114
116
  // Short-circuit if parent has already failed
115
117
  if (isDefined(parent.$$failure)) {
116
118
  fail(parent.$$failure);
117
119
  return result;
118
120
  }
119
121
 
122
+ if (parent.$$inheritedValues) {
123
+ merge(values, omit(parent.$$inheritedValues, invocableKeys));
124
+ }
125
+
120
126
  // Merge parent values if the parent has already resolved, or merge
121
127
  // parent promises and wait if the parent resolve is still in progress.
128
+ extend(promises, parent.$$promises);
122
129
  if (parent.$$values) {
123
- merged = merge(values, parent.$$values);
130
+ merged = merge(values, omit(parent.$$values, invocableKeys));
131
+ result.$$inheritedValues = omit(parent.$$values, invocableKeys);
124
132
  done();
125
133
  } else {
126
- extend(promises, parent.$$promises);
134
+ if (parent.$$inheritedValues) {
135
+ result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys);
136
+ }
127
137
  parent.then(done, fail);
128
138
  }
129
139
 
@@ -4,7 +4,6 @@
4
4
  *
5
5
  * @requires ui.router.router.$urlRouterProvider
6
6
  * @requires ui.router.util.$urlMatcherFactoryProvider
7
- * @requires $locationProvider
8
7
  *
9
8
  * @description
10
9
  * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely
@@ -20,8 +19,8 @@
20
19
  *
21
20
  * The `$stateProvider` provides interfaces to declare these states for your app.
22
21
  */
23
- $StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider', '$locationProvider'];
24
- function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $locationProvider) {
22
+ $StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider'];
23
+ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
25
24
 
26
25
  var root, states = {}, $state, queue = {}, abstractKey = 'abstract';
27
26
 
@@ -49,18 +48,14 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
49
48
 
50
49
  // Build a URLMatcher if necessary, either via a relative or absolute URL
51
50
  url: function(state) {
52
- var url = state.url;
51
+ var url = state.url, config = { params: state.params || {} };
53
52
 
54
53
  if (isString(url)) {
55
- if (url.charAt(0) == '^') {
56
- return $urlMatcherFactory.compile(url.substring(1));
57
- }
58
- return (state.parent.navigable || root).url.concat(url);
54
+ if (url.charAt(0) == '^') return $urlMatcherFactory.compile(url.substring(1), config);
55
+ return (state.parent.navigable || root).url.concat(url, config);
59
56
  }
60
57
 
61
- if ($urlMatcherFactory.isMatcher(url) || url == null) {
62
- return url;
63
- }
58
+ if (!url || $urlMatcherFactory.isMatcher(url)) return url;
64
59
  throw new Error("Invalid url '" + url + "' in state '" + state + "'");
65
60
  },
66
61
 
@@ -69,14 +64,18 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
69
64
  return state.url ? state : (state.parent ? state.parent.navigable : null);
70
65
  },
71
66
 
67
+ // Own parameters for this state. state.url.params is already built at this point. Create and add non-url params
68
+ ownParams: function(state) {
69
+ var params = state.url && state.url.params || new $$UMFP.ParamSet();
70
+ forEach(state.params || {}, function(config, id) {
71
+ if (!params[id]) params[id] = new $$UMFP.Param(id, null, config, "config");
72
+ });
73
+ return params;
74
+ },
75
+
72
76
  // Derive parameters for this state and ensure they're a super-set of parent's parameters
73
77
  params: function(state) {
74
- if (!state.params) {
75
- return state.url ? state.url.parameters() : state.parent.params;
76
- }
77
- if (!isArray(state.params)) throw new Error("Invalid params in state '" + state + "'");
78
- if (state.url) throw new Error("Both params and url specicified in state '" + state + "'");
79
- return state.params;
78
+ return state.parent && state.parent.params ? extend(state.parent.params.$$new(), state.ownParams) : new $$UMFP.ParamSet();
80
79
  },
81
80
 
82
81
  // If there is no explicit multi-view configuration, make one up so we don't have
@@ -94,26 +93,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
94
93
  return views;
95
94
  },
96
95
 
97
- ownParams: function(state) {
98
- if (!state.parent) {
99
- return state.params;
100
- }
101
- var paramNames = {}; forEach(state.params, function (p) { paramNames[p] = true; });
102
-
103
- forEach(state.parent.params, function (p) {
104
- if (!paramNames[p]) {
105
- throw new Error("Missing required parameter '" + p + "' in state '" + state.name + "'");
106
- }
107
- paramNames[p] = false;
108
- });
109
- var ownParams = [];
110
-
111
- forEach(paramNames, function (own, p) {
112
- if (own) ownParams.push(p);
113
- });
114
- return ownParams;
115
- },
116
-
117
96
  // Keep a full path from the root down to this state as this is needed for state activation.
118
97
  path: function(state) {
119
98
  return state.parent ? state.parent.path.concat(state) : []; // exclude root from path
@@ -134,12 +113,16 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
134
113
  }
135
114
 
136
115
  function findState(stateOrName, base) {
116
+ if (!stateOrName) return undefined;
117
+
137
118
  var isStr = isString(stateOrName),
138
119
  name = isStr ? stateOrName : stateOrName.name,
139
120
  path = isRelative(name);
140
121
 
141
122
  if (path) {
142
123
  if (!base) throw new Error("No reference point given for path '" + name + "'");
124
+ base = findState(base);
125
+
143
126
  var rel = name.split("."), i = 0, pathLength = rel.length, current = base;
144
127
 
145
128
  for (; i < pathLength; i++) {
@@ -172,6 +155,13 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
172
155
  queue[parentName].push(state);
173
156
  }
174
157
 
158
+ function flushQueuedChildren(parentName) {
159
+ var queued = queue[parentName] || [];
160
+ while(queued.length) {
161
+ registerState(queued.shift());
162
+ }
163
+ }
164
+
175
165
  function registerState(state) {
176
166
  // Wrap a new object around the state so we can store our private details easily.
177
167
  state = inherit(state, {
@@ -187,6 +177,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
187
177
  // Get parent name
188
178
  var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.'))
189
179
  : (isString(state.parent)) ? state.parent
180
+ : (isObject(state.parent) && isString(state.parent.name)) ? state.parent.name
190
181
  : '';
191
182
 
192
183
  // If parent is not registered yet, add state to queue and register later
@@ -203,17 +194,13 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
203
194
  if (!state[abstractKey] && state.url) {
204
195
  $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) {
205
196
  if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) {
206
- $state.transitionTo(state, $match, { location: false });
197
+ $state.transitionTo(state, $match, { inherit: true, location: false });
207
198
  }
208
199
  }]);
209
200
  }
210
201
 
211
202
  // Register any queued children
212
- if (queue[name]) {
213
- for (var i = 0; i < queue[name].length; i++) {
214
- registerState(queue[name][i]);
215
- }
216
- }
203
+ flushQueuedChildren(name);
217
204
 
218
205
  return state;
219
206
  }
@@ -228,14 +215,21 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
228
215
  var globSegments = glob.split('.'),
229
216
  segments = $state.$current.name.split('.');
230
217
 
218
+ //match single stars
219
+ for (var i = 0, l = globSegments.length; i < l; i++) {
220
+ if (globSegments[i] === '*') {
221
+ segments[i] = '*';
222
+ }
223
+ }
224
+
231
225
  //match greedy starts
232
226
  if (globSegments[0] === '**') {
233
- segments = segments.slice(segments.indexOf(globSegments[1]));
227
+ segments = segments.slice(indexOf(segments, globSegments[1]));
234
228
  segments.unshift('**');
235
229
  }
236
230
  //match greedy ends
237
231
  if (globSegments[globSegments.length - 1] === '**') {
238
- segments.splice(segments.indexOf(globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE);
232
+ segments.splice(indexOf(segments, globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE);
239
233
  segments.push('**');
240
234
  }
241
235
 
@@ -243,13 +237,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
243
237
  return false;
244
238
  }
245
239
 
246
- //match single stars
247
- for (var i = 0, l = globSegments.length; i < l; i++) {
248
- if (globSegments[i] === '*') {
249
- segments[i] = '*';
250
- }
251
- }
252
-
253
240
  return segments.join('') === globSegments.join('');
254
241
  }
255
242
 
@@ -297,7 +284,8 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
297
284
  * - **parent** `{object}` - returns the parent state object.
298
285
  * - **data** `{object}` - returns state data, including any inherited data that is not
299
286
  * overridden by own values (if any).
300
- * - **url** `{object}` - returns a {link ui.router.util.type:UrlMatcher} or null.
287
+ * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher}
288
+ * or `null`.
301
289
  * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is
302
290
  * navigable).
303
291
  * - **params** `{object}` - returns an array of state params that are ensured to
@@ -313,17 +301,17 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
313
301
  * - **path** `{string}` - returns the full path from the root down to this state.
314
302
  * Needed for state activation.
315
303
  * - **includes** `{object}` - returns an object that includes every state that
316
- * would pass a '$state.includes()' test.
304
+ * would pass a `$state.includes()` test.
317
305
  *
318
306
  * @example
319
307
  * <pre>
320
308
  * // Override the internal 'views' builder with a function that takes the state
321
309
  * // definition, and a reference to the internal function being overridden:
322
- * $stateProvider.decorator('views', function ($state, parent) {
310
+ * $stateProvider.decorator('views', function (state, parent) {
323
311
  * var result = {},
324
312
  * views = parent(state);
325
313
  *
326
- * angular.forEach(view, function (config, name) {
314
+ * angular.forEach(views, function (config, name) {
327
315
  * var autoName = (state.name + '.' + name).replace('.', '/');
328
316
  * config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
329
317
  * result[name] = config;
@@ -379,9 +367,12 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
379
367
  * Registers a state configuration under a given state name. The stateConfig object
380
368
  * has the following acceptable properties.
381
369
  *
370
+ * @param {string} name A unique state name, e.g. "home", "about", "contacts".
371
+ * To create a parent/child state use a dot, e.g. "about.sales", "home.newest".
372
+ * @param {object} stateConfig State configuration object.
373
+ * @param {string|function=} stateConfig.template
382
374
  * <a id='template'></a>
383
- *
384
- * - **`template`** - {string|function=} - html template as a string or a function that returns
375
+ * html template as a string or a function that returns
385
376
  * an html template as a string which should be used by the uiView directives. This property
386
377
  * takes precedence over templateUrl.
387
378
  *
@@ -390,9 +381,17 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
390
381
  * - {array.&lt;object&gt;} - state parameters extracted from the current $location.path() by
391
382
  * applying the current state
392
383
  *
384
+ * <pre>template:
385
+ * "<h1>inline template definition</h1>" +
386
+ * "<div ui-view></div>"</pre>
387
+ * <pre>template: function(params) {
388
+ * return "<h1>generated template</h1>"; }</pre>
389
+ * </div>
390
+ *
391
+ * @param {string|function=} stateConfig.templateUrl
393
392
  * <a id='templateUrl'></a>
394
393
  *
395
- * - **`templateUrl`** - {string|function=} - path or function that returns a path to an html
394
+ * path or function that returns a path to an html
396
395
  * template that should be used by uiView.
397
396
  *
398
397
  * If `templateUrl` is a function, it will be called with the following parameters:
@@ -400,82 +399,261 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
400
399
  * - {array.&lt;object&gt;} - state parameters extracted from the current $location.path() by
401
400
  * applying the current state
402
401
  *
403
- * <a id='templateProvider'></a>
402
+ * <pre>templateUrl: "home.html"</pre>
403
+ * <pre>templateUrl: function(params) {
404
+ * return myTemplates[params.pageId]; }</pre>
404
405
  *
405
- * - **`templateProvider`** - {function=} - Provider function that returns HTML content
406
- * string.
406
+ * @param {function=} stateConfig.templateProvider
407
+ * <a id='templateProvider'></a>
408
+ * Provider function that returns HTML content string.
409
+ * <pre> templateProvider:
410
+ * function(MyTemplateService, params) {
411
+ * return MyTemplateService.getTemplate(params.pageId);
412
+ * }</pre>
407
413
  *
414
+ * @param {string|function=} stateConfig.controller
408
415
  * <a id='controller'></a>
409
416
  *
410
- * - **`controller`** - {string|function=} - Controller fn that should be associated with newly
417
+ * Controller fn that should be associated with newly
411
418
  * related scope or the name of a registered controller if passed as a string.
419
+ * Optionally, the ControllerAs may be declared here.
420
+ * <pre>controller: "MyRegisteredController"</pre>
421
+ * <pre>controller:
422
+ * "MyRegisteredController as fooCtrl"}</pre>
423
+ * <pre>controller: function($scope, MyService) {
424
+ * $scope.data = MyService.getData(); }</pre>
412
425
  *
426
+ * @param {function=} stateConfig.controllerProvider
413
427
  * <a id='controllerProvider'></a>
414
428
  *
415
- * - **`controllerProvider`** - {function=} - Injectable provider function that returns
416
- * the actual controller or string.
429
+ * Injectable provider function that returns the actual controller or string.
430
+ * <pre>controllerProvider:
431
+ * function(MyResolveData) {
432
+ * if (MyResolveData.foo)
433
+ * return "FooCtrl"
434
+ * else if (MyResolveData.bar)
435
+ * return "BarCtrl";
436
+ * else return function($scope) {
437
+ * $scope.baz = "Qux";
438
+ * }
439
+ * }</pre>
417
440
  *
441
+ * @param {string=} stateConfig.controllerAs
418
442
  * <a id='controllerAs'></a>
419
443
  *
420
- * - **`controllerAs`** – {string=} – A controller alias name. If present the controller will be
444
+ * A controller alias name. If present the controller will be
421
445
  * published to scope under the controllerAs name.
446
+ * <pre>controllerAs: "myCtrl"</pre>
447
+ *
448
+ * @param {string|object=} stateConfig.parent
449
+ * <a id='parent'></a>
450
+ * Optionally specifies the parent state of this state.
451
+ *
452
+ * <pre>parent: 'parentState'</pre>
453
+ * <pre>parent: parentState // JS variable</pre>
422
454
  *
455
+ * @param {object=} stateConfig.resolve
423
456
  * <a id='resolve'></a>
424
457
  *
425
- * - **`resolve`** - {object.&lt;string, function&gt;=} - An optional map of dependencies which
458
+ * An optional map&lt;string, function&gt; of dependencies which
426
459
  * should be injected into the controller. If any of these dependencies are promises,
427
- * the router will wait for them all to be resolved or one to be rejected before the
428
- * controller is instantiated. If all the promises are resolved successfully, the values
429
- * of the resolved promises are injected and $stateChangeSuccess event is fired. If any
430
- * of the promises are rejected the $stateChangeError event is fired. The map object is:
460
+ * the router will wait for them all to be resolved before the controller is instantiated.
461
+ * If all the promises are resolved successfully, the $stateChangeSuccess event is fired
462
+ * and the values of the resolved promises are injected into any controllers that reference them.
463
+ * If any of the promises are rejected the $stateChangeError event is fired.
464
+ *
465
+ * The map object is:
431
466
  *
432
467
  * - key - {string}: name of dependency to be injected into controller
433
468
  * - factory - {string|function}: If string then it is alias for service. Otherwise if function,
434
469
  * it is injected and return value it treated as dependency. If result is a promise, it is
435
470
  * resolved before its value is injected into controller.
436
471
  *
472
+ * <pre>resolve: {
473
+ * myResolve1:
474
+ * function($http, $stateParams) {
475
+ * return $http.get("/api/foos/"+stateParams.fooID);
476
+ * }
477
+ * }</pre>
478
+ *
479
+ * @param {string=} stateConfig.url
437
480
  * <a id='url'></a>
438
481
  *
439
- * - **`url`** - {string=} - A url with optional parameters. When a state is navigated or
482
+ * A url fragment with optional parameters. When a state is navigated or
440
483
  * transitioned to, the `$stateParams` service will be populated with any
441
484
  * parameters that were passed.
442
485
  *
443
- * <a id='params'></a>
486
+ * (See {@link ui.router.util.type:UrlMatcher UrlMatcher} `UrlMatcher`} for
487
+ * more details on acceptable patterns )
444
488
  *
445
- * - **`params`** - {object=} - An array of parameter names or regular expressions. Only
446
- * use this within a state if you are not using url. Otherwise you can specify your
447
- * parameters within the url. When a state is navigated or transitioned to, the
448
- * $stateParams service will be populated with any parameters that were passed.
489
+ * examples:
490
+ * <pre>url: "/home"
491
+ * url: "/users/:userid"
492
+ * url: "/books/{bookid:[a-zA-Z_-]}"
493
+ * url: "/books/{categoryid:int}"
494
+ * url: "/books/{publishername:string}/{categoryid:int}"
495
+ * url: "/messages?before&after"
496
+ * url: "/messages?{before:date}&{after:date}"
497
+ * url: "/messages/:mailboxid?{before:date}&{after:date}"
498
+ * </pre>
449
499
  *
500
+ * @param {object=} stateConfig.views
450
501
  * <a id='views'></a>
502
+ * an optional map&lt;string, object&gt; which defined multiple views, or targets views
503
+ * manually/explicitly.
451
504
  *
452
- * - **`views`** - {object=} - Use the views property to set up multiple views or to target views
453
- * manually/explicitly.
505
+ * Examples:
454
506
  *
455
- * <a id='abstract'></a>
507
+ * Targets three named `ui-view`s in the parent state's template
508
+ * <pre>views: {
509
+ * header: {
510
+ * controller: "headerCtrl",
511
+ * templateUrl: "header.html"
512
+ * }, body: {
513
+ * controller: "bodyCtrl",
514
+ * templateUrl: "body.html"
515
+ * }, footer: {
516
+ * controller: "footCtrl",
517
+ * templateUrl: "footer.html"
518
+ * }
519
+ * }</pre>
456
520
  *
457
- * - **`abstract`** - {boolean=} - An abstract state will never be directly activated,
521
+ * Targets named `ui-view="header"` from grandparent state 'top''s template, and named `ui-view="body" from parent state's template.
522
+ * <pre>views: {
523
+ * 'header@top': {
524
+ * controller: "msgHeaderCtrl",
525
+ * templateUrl: "msgHeader.html"
526
+ * }, 'body': {
527
+ * controller: "messagesCtrl",
528
+ * templateUrl: "messages.html"
529
+ * }
530
+ * }</pre>
531
+ *
532
+ * @param {boolean=} [stateConfig.abstract=false]
533
+ * <a id='abstract'></a>
534
+ * An abstract state will never be directly activated,
458
535
  * but can provide inherited properties to its common children states.
536
+ * <pre>abstract: true</pre>
459
537
  *
538
+ * @param {function=} stateConfig.onEnter
460
539
  * <a id='onEnter'></a>
461
540
  *
462
- * - **`onEnter`** - {object=} - Callback function for when a state is entered. Good way
541
+ * Callback function for when a state is entered. Good way
463
542
  * to trigger an action or dispatch an event, such as opening a dialog.
543
+ * If minifying your scripts, make sure to explictly annotate this function,
544
+ * because it won't be automatically annotated by your build tools.
545
+ *
546
+ * <pre>onEnter: function(MyService, $stateParams) {
547
+ * MyService.foo($stateParams.myParam);
548
+ * }</pre>
464
549
  *
550
+ * @param {function=} stateConfig.onExit
465
551
  * <a id='onExit'></a>
466
552
  *
467
- * - **`onExit`** - {object=} - Callback function for when a state is exited. Good way to
553
+ * Callback function for when a state is exited. Good way to
468
554
  * trigger an action or dispatch an event, such as opening a dialog.
555
+ * If minifying your scripts, make sure to explictly annotate this function,
556
+ * because it won't be automatically annotated by your build tools.
469
557
  *
558
+ * <pre>onExit: function(MyService, $stateParams) {
559
+ * MyService.cleanup($stateParams.myParam);
560
+ * }</pre>
561
+ *
562
+ * @param {boolean=} [stateConfig.reloadOnSearch=true]
470
563
  * <a id='reloadOnSearch'></a>
471
564
  *
472
- * - **`reloadOnSearch = true`** - {boolean=} - If `false`, will not retrigger the same state
565
+ * If `false`, will not retrigger the same state
473
566
  * just because a search/query parameter has changed (via $location.search() or $location.hash()).
474
567
  * Useful for when you'd like to modify $location.search() without triggering a reload.
568
+ * <pre>reloadOnSearch: false</pre>
475
569
  *
570
+ * @param {object=} stateConfig.data
476
571
  * <a id='data'></a>
477
572
  *
478
- * - **`data`** - {object=} - Arbitrary data object, useful for custom configuration.
573
+ * Arbitrary data object, useful for custom configuration. The parent state's `data` is
574
+ * prototypally inherited. In other words, adding a data property to a state adds it to
575
+ * the entire subtree via prototypal inheritance.
576
+ *
577
+ * <pre>data: {
578
+ * requiredRole: 'foo'
579
+ * } </pre>
580
+ *
581
+ * @param {object=} stateConfig.params
582
+ * <a id='params'></a>
583
+ *
584
+ * A map which optionally configures parameters declared in the `url`, or
585
+ * defines additional non-url parameters. For each parameter being
586
+ * configured, add a configuration object keyed to the name of the parameter.
587
+ *
588
+ * Each parameter configuration object may contain the following properties:
589
+ *
590
+ * - ** value ** - {object|function=}: specifies the default value for this
591
+ * parameter. This implicitly sets this parameter as optional.
592
+ *
593
+ * When UI-Router routes to a state and no value is
594
+ * specified for this parameter in the URL or transition, the
595
+ * default value will be used instead. If `value` is a function,
596
+ * it will be injected and invoked, and the return value used.
597
+ *
598
+ * *Note*: `undefined` is treated as "no default value" while `null`
599
+ * is treated as "the default value is `null`".
600
+ *
601
+ * *Shorthand*: If you only need to configure the default value of the
602
+ * parameter, you may use a shorthand syntax. In the **`params`**
603
+ * map, instead mapping the param name to a full parameter configuration
604
+ * object, simply set map it to the default parameter value, e.g.:
605
+ *
606
+ * <pre>// define a parameter's default value
607
+ * params: {
608
+ * param1: { value: "defaultValue" }
609
+ * }
610
+ * // shorthand default values
611
+ * params: {
612
+ * param1: "defaultValue",
613
+ * param2: "param2Default"
614
+ * }</pre>
615
+ *
616
+ * - ** array ** - {boolean=}: *(default: false)* If true, the param value will be
617
+ * treated as an array of values. If you specified a Type, the value will be
618
+ * treated as an array of the specified Type. Note: query parameter values
619
+ * default to a special `"auto"` mode.
620
+ *
621
+ * For query parameters in `"auto"` mode, if multiple values for a single parameter
622
+ * are present in the URL (e.g.: `/foo?bar=1&bar=2&bar=3`) then the values
623
+ * are mapped to an array (e.g.: `{ foo: [ '1', '2', '3' ] }`). However, if
624
+ * only one value is present (e.g.: `/foo?bar=1`) then the value is treated as single
625
+ * value (e.g.: `{ foo: '1' }`).
626
+ *
627
+ * <pre>params: {
628
+ * param1: { array: true }
629
+ * }</pre>
630
+ *
631
+ * - ** squash ** - {bool|string=}: `squash` configures how a default parameter value is represented in the URL when
632
+ * the current parameter value is the same as the default value. If `squash` is not set, it uses the
633
+ * configured default squash policy.
634
+ * (See {@link ui.router.util.$urlMatcherFactory#methods_defaultSquashPolicy `defaultSquashPolicy()`})
635
+ *
636
+ * There are three squash settings:
637
+ *
638
+ * - false: The parameter's default value is not squashed. It is encoded and included in the URL
639
+ * - true: The parameter's default value is omitted from the URL. If the parameter is preceeded and followed
640
+ * by slashes in the state's `url` declaration, then one of those slashes are omitted.
641
+ * This can allow for cleaner looking URLs.
642
+ * - `"<arbitrary string>"`: The parameter's default value is replaced with an arbitrary placeholder of your choice.
643
+ *
644
+ * <pre>params: {
645
+ * param1: {
646
+ * value: "defaultId",
647
+ * squash: true
648
+ * } }
649
+ * // squash "defaultValue" to "~"
650
+ * params: {
651
+ * param1: {
652
+ * value: "defaultValue",
653
+ * squash: "~"
654
+ * } }
655
+ * </pre>
656
+ *
479
657
  *
480
658
  * @example
481
659
  * <pre>
@@ -484,7 +662,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
484
662
  * // stateName can be a single top-level name (must be unique).
485
663
  * $stateProvider.state("home", {});
486
664
  *
487
- * // Or it can be a nested state name. This state is a child of the
665
+ * // Or it can be a nested state name. This state is a child of the
488
666
  * // above "home" state.
489
667
  * $stateProvider.state("home.newest", {});
490
668
  *
@@ -498,9 +676,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
498
676
  * .state("contacts", {});
499
677
  * </pre>
500
678
  *
501
- * @param {string} name A unique state name, e.g. "home", "about", "contacts".
502
- * To create a parent/child state use a dot, e.g. "about.sales", "home.newest".
503
- * @param {object} definition State configuration object.
504
679
  */
505
680
  this.state = state;
506
681
  function state(name, definition) {
@@ -521,6 +696,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
521
696
  * @requires $injector
522
697
  * @requires ui.router.util.$resolve
523
698
  * @requires ui.router.state.$stateParams
699
+ * @requires ui.router.router.$urlRouter
524
700
  *
525
701
  * @property {object} params A param object, e.g. {sectionId: section.id)}, that
526
702
  * you'd like to test against the current active state.
@@ -534,26 +710,82 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
534
710
  * between them. It also provides interfaces to ask for current state or even states
535
711
  * you're coming from.
536
712
  */
537
- // $urlRouter is injected just to ensure it gets instantiated
538
713
  this.$get = $get;
539
- $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$location', '$urlRouter', '$browser'];
540
- function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $location, $urlRouter, $browser) {
714
+ $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter', '$location', '$urlMatcherFactory'];
715
+ function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter, $location, $urlMatcherFactory) {
541
716
 
542
717
  var TransitionSuperseded = $q.reject(new Error('transition superseded'));
543
718
  var TransitionPrevented = $q.reject(new Error('transition prevented'));
544
719
  var TransitionAborted = $q.reject(new Error('transition aborted'));
545
720
  var TransitionFailed = $q.reject(new Error('transition failed'));
546
- var currentLocation = $location.url();
547
- var baseHref = $browser.baseHref();
548
721
 
549
- function syncUrl() {
550
- if ($location.url() !== currentLocation) {
551
- $location.url(currentLocation);
552
- $location.replace();
722
+ // Handles the case where a state which is the target of a transition is not found, and the user
723
+ // can optionally retry or defer the transition
724
+ function handleRedirect(redirect, state, params, options) {
725
+ /**
726
+ * @ngdoc event
727
+ * @name ui.router.state.$state#$stateNotFound
728
+ * @eventOf ui.router.state.$state
729
+ * @eventType broadcast on root scope
730
+ * @description
731
+ * Fired when a requested state **cannot be found** using the provided state name during transition.
732
+ * The event is broadcast allowing any handlers a single chance to deal with the error (usually by
733
+ * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler,
734
+ * you can see its three properties in the example. You can use `event.preventDefault()` to abort the
735
+ * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value.
736
+ *
737
+ * @param {Object} event Event object.
738
+ * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties.
739
+ * @param {State} fromState Current state object.
740
+ * @param {Object} fromParams Current state params.
741
+ *
742
+ * @example
743
+ *
744
+ * <pre>
745
+ * // somewhere, assume lazy.state has not been defined
746
+ * $state.go("lazy.state", {a:1, b:2}, {inherit:false});
747
+ *
748
+ * // somewhere else
749
+ * $scope.$on('$stateNotFound',
750
+ * function(event, unfoundState, fromState, fromParams){
751
+ * console.log(unfoundState.to); // "lazy.state"
752
+ * console.log(unfoundState.toParams); // {a:1, b:2}
753
+ * console.log(unfoundState.options); // {inherit:false} + default options
754
+ * })
755
+ * </pre>
756
+ */
757
+ var evt = $rootScope.$broadcast('$stateNotFound', redirect, state, params);
758
+
759
+ if (evt.defaultPrevented) {
760
+ $urlRouter.update();
761
+ return TransitionAborted;
762
+ }
763
+
764
+ if (!evt.retry) {
765
+ return null;
553
766
  }
767
+
768
+ // Allow the handler to return a promise to defer state lookup retry
769
+ if (options.$retry) {
770
+ $urlRouter.update();
771
+ return TransitionFailed;
772
+ }
773
+ var retryTransition = $state.transition = $q.when(evt.retry);
774
+
775
+ retryTransition.then(function() {
776
+ if (retryTransition !== $state.transition) return TransitionSuperseded;
777
+ redirect.options.$retry = true;
778
+ return $state.transitionTo(redirect.to, redirect.toParams, redirect.options);
779
+ }, function() {
780
+ return TransitionAborted;
781
+ });
782
+ $urlRouter.update();
783
+
784
+ return retryTransition;
554
785
  }
555
786
 
556
787
  root.locals = { resolve: null, globals: { $stateParams: {} } };
788
+
557
789
  $state = {
558
790
  params: {},
559
791
  current: root.self,
@@ -567,8 +799,8 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
567
799
  * @methodOf ui.router.state.$state
568
800
  *
569
801
  * @description
570
- * A method that force reloads the current state. All resolves are re-resolved, events are not re-fired,
571
- * and controllers reinstantiated (bug with controllers reinstantiating right now, fixing soon).
802
+ * A method that force reloads the current state. All resolves are re-resolved,
803
+ * controllers reinstantiated, and events re-fired.
572
804
  *
573
805
  * @example
574
806
  * <pre>
@@ -584,12 +816,37 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
584
816
  * `reload()` is just an alias for:
585
817
  * <pre>
586
818
  * $state.transitionTo($state.current, $stateParams, {
587
- * reload: true, inherit: false, notify: false
819
+ * reload: true, inherit: false, notify: true
820
+ * });
821
+ * </pre>
822
+ *
823
+ * @param {string=|object=} state - A state name or a state object, which is the root of the resolves to be re-resolved.
824
+ * @example
825
+ * <pre>
826
+ * //assuming app application consists of 3 states: 'contacts', 'contacts.detail', 'contacts.detail.item'
827
+ * //and current state is 'contacts.detail.item'
828
+ * var app angular.module('app', ['ui.router']);
829
+ *
830
+ * app.controller('ctrl', function ($scope, $state) {
831
+ * $scope.reload = function(){
832
+ * //will reload 'contact.detail' and 'contact.detail.item' states
833
+ * $state.reload('contact.detail');
834
+ * }
835
+ * });
836
+ * </pre>
837
+ *
838
+ * `reload()` is just an alias for:
839
+ * <pre>
840
+ * $state.transitionTo($state.current, $stateParams, {
841
+ * reload: true, inherit: false, notify: true
588
842
  * });
589
843
  * </pre>
844
+
845
+ * @returns {promise} A promise representing the state of the new transition. See
846
+ * {@link ui.router.state.$state#methods_go $state.go}.
590
847
  */
591
- $state.reload = function reload() {
592
- $state.transitionTo($state.current, $stateParams, { reload: true, inherit: false, notify: false });
848
+ $state.reload = function reload(state) {
849
+ return $state.transitionTo($state.current, $stateParams, { reload: state || true, inherit: false, notify: true});
593
850
  };
594
851
 
595
852
  /**
@@ -659,7 +916,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
659
916
  *
660
917
  */
661
918
  $state.go = function go(to, params, options) {
662
- return this.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options));
919
+ return $state.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options));
663
920
  };
664
921
 
665
922
  /**
@@ -693,9 +950,11 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
693
950
  * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'),
694
951
  * defines which state to be relative from.
695
952
  * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.
696
- * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params
953
+ * - **`reload`** (v0.2.5) - {boolean=false|string=|object=}, If `true` will force transition even if the state or params
697
954
  * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd
698
955
  * use this when you want to force a reload when *everything* is the same, including search params.
956
+ * if String, then will reload the state with the name given in reload, and any children.
957
+ * if Object, then a stateObj is expected, will reload the state found in stateObj, and any children.
699
958
  *
700
959
  * @returns {promise} A promise representing the state of the new transition. See
701
960
  * {@link ui.router.state.$state#methods_go $state.go}.
@@ -709,64 +968,15 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
709
968
  var from = $state.$current, fromParams = $state.params, fromPath = from.path;
710
969
  var evt, toState = findState(to, options.relative);
711
970
 
971
+ // Store the hash param for later (since it will be stripped out by various methods)
972
+ var hash = toParams['#'];
973
+
712
974
  if (!isDefined(toState)) {
713
- // Broadcast not found event and abort the transition if prevented
714
975
  var redirect = { to: to, toParams: toParams, options: options };
976
+ var redirectResult = handleRedirect(redirect, from.self, fromParams, options);
715
977
 
716
- /**
717
- * @ngdoc event
718
- * @name ui.router.state.$state#$stateNotFound
719
- * @eventOf ui.router.state.$state
720
- * @eventType broadcast on root scope
721
- * @description
722
- * Fired when a requested state **cannot be found** using the provided state name during transition.
723
- * The event is broadcast allowing any handlers a single chance to deal with the error (usually by
724
- * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler,
725
- * you can see its three properties in the example. You can use `event.preventDefault()` to abort the
726
- * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value.
727
- *
728
- * @param {Object} event Event object.
729
- * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties.
730
- * @param {State} fromState Current state object.
731
- * @param {Object} fromParams Current state params.
732
- *
733
- * @example
734
- *
735
- * <pre>
736
- * // somewhere, assume lazy.state has not been defined
737
- * $state.go("lazy.state", {a:1, b:2}, {inherit:false});
738
- *
739
- * // somewhere else
740
- * $scope.$on('$stateNotFound',
741
- * function(event, unfoundState, fromState, fromParams){
742
- * console.log(unfoundState.to); // "lazy.state"
743
- * console.log(unfoundState.toParams); // {a:1, b:2}
744
- * console.log(unfoundState.options); // {inherit:false} + default options
745
- * })
746
- * </pre>
747
- */
748
- evt = $rootScope.$broadcast('$stateNotFound', redirect, from.self, fromParams);
749
- if (evt.defaultPrevented) {
750
- syncUrl();
751
- return TransitionAborted;
752
- }
753
-
754
- // Allow the handler to return a promise to defer state lookup retry
755
- if (evt.retry) {
756
- if (options.$retry) {
757
- syncUrl();
758
- return TransitionFailed;
759
- }
760
- var retryTransition = $state.transition = $q.when(evt.retry);
761
- retryTransition.then(function() {
762
- if (retryTransition !== $state.transition) return TransitionSuperseded;
763
- redirect.options.$retry = true;
764
- return $state.transitionTo(redirect.to, redirect.toParams, redirect.options);
765
- }, function() {
766
- return TransitionAborted;
767
- });
768
- syncUrl();
769
- return retryTransition;
978
+ if (redirectResult) {
979
+ return redirectResult;
770
980
  }
771
981
 
772
982
  // Always retry once if the $stateNotFound was not prevented
@@ -775,38 +985,68 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
775
985
  toParams = redirect.toParams;
776
986
  options = redirect.options;
777
987
  toState = findState(to, options.relative);
988
+
778
989
  if (!isDefined(toState)) {
779
- if (options.relative) throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'");
780
- throw new Error("No such state '" + to + "'");
990
+ if (!options.relative) throw new Error("No such state '" + to + "'");
991
+ throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'");
781
992
  }
782
993
  }
783
994
  if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'");
784
995
  if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState);
996
+ if (!toState.params.$$validates(toParams)) return TransitionFailed;
997
+
998
+ toParams = toState.params.$$values(toParams);
785
999
  to = toState;
786
1000
 
787
1001
  var toPath = to.path;
788
1002
 
789
1003
  // Starting from the root of the path, keep all levels that haven't changed
790
- var keep, state, locals = root.locals, toLocals = [];
791
- for (keep = 0, state = toPath[keep];
792
- state && state === fromPath[keep] && equalForKeys(toParams, fromParams, state.ownParams) && !options.reload;
793
- keep++, state = toPath[keep]) {
794
- locals = toLocals[keep] = state.locals;
1004
+ var keep = 0, state = toPath[keep], locals = root.locals, toLocals = [];
1005
+
1006
+ if (!options.reload) {
1007
+ while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) {
1008
+ locals = toLocals[keep] = state.locals;
1009
+ keep++;
1010
+ state = toPath[keep];
1011
+ }
1012
+ } else if (isString(options.reload) || isObject(options.reload)) {
1013
+ if (isObject(options.reload) && !options.reload.name) {
1014
+ throw new Error('Invalid reload state object');
1015
+ }
1016
+
1017
+ var reloadState = options.reload === true ? fromPath[0] : findState(options.reload);
1018
+ if (options.reload && !reloadState) {
1019
+ throw new Error("No such reload state '" + (isString(options.reload) ? options.reload : options.reload.name) + "'");
1020
+ }
1021
+
1022
+ while (state && state === fromPath[keep] && state !== reloadState) {
1023
+ locals = toLocals[keep] = state.locals;
1024
+ keep++;
1025
+ state = toPath[keep];
1026
+ }
795
1027
  }
796
1028
 
797
1029
  // If we're going to the same state and all locals are kept, we've got nothing to do.
798
1030
  // But clear 'transition', as we still want to cancel any other pending transitions.
799
- // TODO: We may not want to bump 'transition' if we're called from a location change that we've initiated ourselves,
800
- // because we might accidentally abort a legitimate transition initiated from code?
801
- if (shouldTriggerReload(to, from, locals, options) ) {
802
- if ( to.self.reloadOnSearch !== false )
803
- syncUrl();
1031
+ // TODO: We may not want to bump 'transition' if we're called from a location change
1032
+ // that we've initiated ourselves, because we might accidentally abort a legitimate
1033
+ // transition initiated from code?
1034
+ if (shouldSkipReload(to, toParams, from, fromParams, locals, options)) {
1035
+ if (hash) toParams['#'] = hash;
1036
+ $state.params = toParams;
1037
+ copy($state.params, $stateParams);
1038
+ if (options.location && to.navigable && to.navigable.url) {
1039
+ $urlRouter.push(to.navigable.url, toParams, {
1040
+ $$avoidResync: true, replace: options.location === 'replace'
1041
+ });
1042
+ $urlRouter.update(true);
1043
+ }
804
1044
  $state.transition = null;
805
1045
  return $q.when($state.current);
806
1046
  }
807
1047
 
808
- // Normalize/filter parameters before we pass them to event handlers etc.
809
- toParams = normalize(to.params, toParams || {});
1048
+ // Filter parameters before we pass them to event handlers etc.
1049
+ toParams = filterByKeys(to.params.$$keys(), toParams || {});
810
1050
 
811
1051
  // Broadcast start event and cancel the transition if requested
812
1052
  if (options.notify) {
@@ -837,9 +1077,9 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
837
1077
  * })
838
1078
  * </pre>
839
1079
  */
840
- evt = $rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams);
841
- if (evt.defaultPrevented) {
842
- syncUrl();
1080
+ if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams).defaultPrevented) {
1081
+ $rootScope.$broadcast('$stateChangeCancel', to.self, toParams, from.self, fromParams);
1082
+ $urlRouter.update();
843
1083
  return TransitionPrevented;
844
1084
  }
845
1085
  }
@@ -852,9 +1092,10 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
852
1092
  // empty and gets filled asynchronously. We need to keep track of the promise for the
853
1093
  // (fully resolved) current locals, and pass this down the chain.
854
1094
  var resolved = $q.when(locals);
855
- for (var l=keep; l<toPath.length; l++, state=toPath[l]) {
1095
+
1096
+ for (var l = keep; l < toPath.length; l++, state = toPath[l]) {
856
1097
  locals = toLocals[l] = inherit(locals);
857
- resolved = resolveState(state, toParams, state===to, resolved, locals);
1098
+ resolved = resolveState(state, toParams, state === to, resolved, locals, options);
858
1099
  }
859
1100
 
860
1101
  // Once everything is resolved, we are ready to perform the actual transition
@@ -867,7 +1108,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
867
1108
  if ($state.transition !== transition) return TransitionSuperseded;
868
1109
 
869
1110
  // Exit 'from' states not kept
870
- for (l=fromPath.length-1; l>=keep; l--) {
1111
+ for (l = fromPath.length - 1; l >= keep; l--) {
871
1112
  exiting = fromPath[l];
872
1113
  if (exiting.self.onExit) {
873
1114
  $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals);
@@ -876,7 +1117,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
876
1117
  }
877
1118
 
878
1119
  // Enter 'to' states not kept
879
- for (l=keep; l<toPath.length; l++) {
1120
+ for (l = keep; l < toPath.length; l++) {
880
1121
  entering = toPath[l];
881
1122
  entering.locals = toLocals[l];
882
1123
  if (entering.self.onEnter) {
@@ -884,6 +1125,9 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
884
1125
  }
885
1126
  }
886
1127
 
1128
+ // Re-add the saved hash before we start returning things
1129
+ if (hash) toParams['#'] = hash;
1130
+
887
1131
  // Run it again, to catch any transitions in callbacks
888
1132
  if ($state.transition !== transition) return TransitionSuperseded;
889
1133
 
@@ -894,14 +1138,10 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
894
1138
  copy($state.params, $stateParams);
895
1139
  $state.transition = null;
896
1140
 
897
- // Update $location
898
- var toNav = to.navigable;
899
- if (options.location && toNav) {
900
- $location.url(toNav.url.format(toNav.locals.globals.$stateParams));
901
-
902
- if (options.location === 'replace') {
903
- $location.replace();
904
- }
1141
+ if (options.location && to.navigable) {
1142
+ $urlRouter.push(to.navigable.url, to.navigable.locals.globals.$stateParams, {
1143
+ $$avoidResync: true, replace: options.location === 'replace'
1144
+ });
905
1145
  }
906
1146
 
907
1147
  if (options.notify) {
@@ -921,7 +1161,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
921
1161
  */
922
1162
  $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams);
923
1163
  }
924
- currentLocation = $location.url();
1164
+ $urlRouter.update(true);
925
1165
 
926
1166
  return $state.current;
927
1167
  }, function (error) {
@@ -946,8 +1186,11 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
946
1186
  * @param {Object} fromParams The params supplied to the `fromState`.
947
1187
  * @param {Error} error The resolve error object.
948
1188
  */
949
- $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error);
950
- syncUrl();
1189
+ evt = $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error);
1190
+
1191
+ if (!evt.defaultPrevented) {
1192
+ $urlRouter.update();
1193
+ }
951
1194
 
952
1195
  return $q.reject(error);
953
1196
  });
@@ -962,35 +1205,40 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
962
1205
  *
963
1206
  * @description
964
1207
  * Similar to {@link ui.router.state.$state#methods_includes $state.includes},
965
- * but only checks for the full state name. If params is supplied then it will be
966
- * tested for strict equality against the current active params object, so all params
1208
+ * but only checks for the full state name. If params is supplied then it will be
1209
+ * tested for strict equality against the current active params object, so all params
967
1210
  * must match with none missing and no extras.
968
1211
  *
969
1212
  * @example
970
1213
  * <pre>
1214
+ * $state.$current.name = 'contacts.details.item';
1215
+ *
1216
+ * // absolute name
971
1217
  * $state.is('contact.details.item'); // returns true
972
1218
  * $state.is(contactDetailItemStateObject); // returns true
973
1219
  *
974
- * // everything else would return false
1220
+ * // relative name (. and ^), typically from a template
1221
+ * // E.g. from the 'contacts.details' template
1222
+ * <div ng-class="{highlighted: $state.is('.item')}">Item</div>
975
1223
  * </pre>
976
1224
  *
977
- * @param {string|object} stateName The state name or state object you'd like to check.
978
- * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like
1225
+ * @param {string|object} stateOrName The state name (absolute or relative) or state object you'd like to check.
1226
+ * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like
979
1227
  * to test against the current active state.
1228
+ * @param {object=} options An options object. The options are:
1229
+ *
1230
+ * - **`relative`** - {string|object} - If `stateOrName` is a relative state name and `options.relative` is set, .is will
1231
+ * test relative to `options.relative` state (or name).
1232
+ *
980
1233
  * @returns {boolean} Returns true if it is the state.
981
1234
  */
982
- $state.is = function is(stateOrName, params) {
983
- var state = findState(stateOrName);
984
-
985
- if (!isDefined(state)) {
986
- return undefined;
987
- }
988
-
989
- if ($state.$current !== state) {
990
- return false;
991
- }
1235
+ $state.is = function is(stateOrName, params, options) {
1236
+ options = extend({ relative: $state.$current }, options || {});
1237
+ var state = findState(stateOrName, options.relative);
992
1238
 
993
- return isDefined(params) && params !== null ? angular.equals($stateParams, params) : true;
1239
+ if (!isDefined(state)) { return undefined; }
1240
+ if ($state.$current !== state) { return false; }
1241
+ return params ? equalForKeys(state.params.$$values(params), $stateParams) : true;
994
1242
  };
995
1243
 
996
1244
  /**
@@ -999,25 +1247,28 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
999
1247
  * @methodOf ui.router.state.$state
1000
1248
  *
1001
1249
  * @description
1002
- * A method to determine if the current active state is equal to or is the child of the
1250
+ * A method to determine if the current active state is equal to or is the child of the
1003
1251
  * state stateName. If any params are passed then they will be tested for a match as well.
1004
1252
  * Not all the parameters need to be passed, just the ones you'd like to test for equality.
1005
1253
  *
1006
1254
  * @example
1255
+ * Partial and relative names
1007
1256
  * <pre>
1008
1257
  * $state.$current.name = 'contacts.details.item';
1009
1258
  *
1259
+ * // Using partial names
1010
1260
  * $state.includes("contacts"); // returns true
1011
1261
  * $state.includes("contacts.details"); // returns true
1012
1262
  * $state.includes("contacts.details.item"); // returns true
1013
1263
  * $state.includes("contacts.list"); // returns false
1014
1264
  * $state.includes("about"); // returns false
1015
- * </pre>
1016
1265
  *
1017
- * @description
1018
- * Basic globing patterns will also work.
1266
+ * // Using relative names (. and ^), typically from a template
1267
+ * // E.g. from the 'contacts.details' template
1268
+ * <div ng-class="{highlighted: $state.includes('.item')}">Item</div>
1269
+ * </pre>
1019
1270
  *
1020
- * @example
1271
+ * Basic globbing patterns
1021
1272
  * <pre>
1022
1273
  * $state.$current.name = 'contacts.details.item.url';
1023
1274
  *
@@ -1030,37 +1281,30 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1030
1281
  * $state.includes("item.**"); // returns false
1031
1282
  * </pre>
1032
1283
  *
1033
- * @param {string} stateOrName A partial name to be searched for within the current state name.
1034
- * @param {object} params A param object, e.g. `{sectionId: section.id}`,
1284
+ * @param {string} stateOrName A partial name, relative name, or glob pattern
1285
+ * to be searched for within the current state name.
1286
+ * @param {object=} params A param object, e.g. `{sectionId: section.id}`,
1035
1287
  * that you'd like to test against the current active state.
1288
+ * @param {object=} options An options object. The options are:
1289
+ *
1290
+ * - **`relative`** - {string|object=} - If `stateOrName` is a relative state reference and `options.relative` is set,
1291
+ * .includes will test relative to `options.relative` state (or name).
1292
+ *
1036
1293
  * @returns {boolean} Returns true if it does include the state
1037
1294
  */
1038
-
1039
- $state.includes = function includes(stateOrName, params) {
1295
+ $state.includes = function includes(stateOrName, params, options) {
1296
+ options = extend({ relative: $state.$current }, options || {});
1040
1297
  if (isString(stateOrName) && isGlob(stateOrName)) {
1041
- if (doesStateMatchGlob(stateOrName)) {
1042
- stateOrName = $state.$current.name;
1043
- } else {
1298
+ if (!doesStateMatchGlob(stateOrName)) {
1044
1299
  return false;
1045
1300
  }
1301
+ stateOrName = $state.$current.name;
1046
1302
  }
1047
1303
 
1048
- var state = findState(stateOrName);
1049
- if (!isDefined(state)) {
1050
- return undefined;
1051
- }
1052
-
1053
- if (!isDefined($state.$current.includes[state.name])) {
1054
- return false;
1055
- }
1056
-
1057
- var validParams = true;
1058
- angular.forEach(params, function(value, key) {
1059
- if (!isDefined($stateParams[key]) || $stateParams[key] !== value) {
1060
- validParams = false;
1061
- }
1062
- });
1063
- return validParams;
1304
+ var state = findState(stateOrName, options.relative);
1305
+ if (!isDefined(state)) { return undefined; }
1306
+ if (!isDefined($state.$current.includes[state.name])) { return false; }
1307
+ return params ? equalForKeys(state.params.$$values(params), $stateParams, objectKeys(params)) : true;
1064
1308
  };
1065
1309
 
1066
1310
 
@@ -1084,7 +1328,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1084
1328
  * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the
1085
1329
  * first parameter, then the constructed href url will be built from the first navigable ancestor (aka
1086
1330
  * ancestor with a valid url).
1087
- * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url.
1331
+ * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url.
1088
1332
  * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'),
1089
1333
  * defines which state to be relative from.
1090
1334
  * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl".
@@ -1092,33 +1336,26 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1092
1336
  * @returns {string} compiled state url
1093
1337
  */
1094
1338
  $state.href = function href(stateOrName, params, options) {
1095
- options = extend({ lossy: true, inherit: false, absolute: false, relative: $state.$current }, options || {});
1339
+ options = extend({
1340
+ lossy: true,
1341
+ inherit: true,
1342
+ absolute: false,
1343
+ relative: $state.$current
1344
+ }, options || {});
1345
+
1096
1346
  var state = findState(stateOrName, options.relative);
1097
- if (!isDefined(state)) return null;
1098
1347
 
1099
- params = inheritParams($stateParams, params || {}, $state.$current, state);
1348
+ if (!isDefined(state)) return null;
1349
+ if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, state);
1350
+
1100
1351
  var nav = (state && options.lossy) ? state.navigable : state;
1101
- var url = (nav && nav.url) ? nav.url.format(normalize(state.params, params || {})) : null;
1102
- if (!$locationProvider.html5Mode() && url) {
1103
- url = "#" + $locationProvider.hashPrefix() + url;
1104
- }
1105
1352
 
1106
- if (baseHref !== '/') {
1107
- if ($locationProvider.html5Mode()) {
1108
- url = baseHref.slice(0, -1) + url;
1109
- } else if (options.absolute){
1110
- url = baseHref.slice(1) + url;
1111
- }
1112
- }
1113
-
1114
- if (options.absolute && url) {
1115
- url = $location.protocol() + '://' +
1116
- $location.host() +
1117
- ($location.port() == 80 || $location.port() == 443 ? '' : ':' + $location.port()) +
1118
- (!$locationProvider.html5Mode() && url ? '/' : '') +
1119
- url;
1353
+ if (!nav || nav.url === undefined || nav.url === null) {
1354
+ return null;
1120
1355
  }
1121
- return url;
1356
+ return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys().concat('#'), params || {}), {
1357
+ absolute: options.absolute
1358
+ });
1122
1359
  };
1123
1360
 
1124
1361
  /**
@@ -1129,26 +1366,23 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1129
1366
  * @description
1130
1367
  * Returns the state configuration object for any specific state or all states.
1131
1368
  *
1132
- * @param {string|object=} stateOrName If provided, will only get the config for
1369
+ * @param {string|object=} stateOrName (absolute or relative) If provided, will only get the config for
1133
1370
  * the requested state. If not provided, returns an array of ALL state configs.
1134
- * @returns {object|array} State configuration object or array of all objects.
1371
+ * @param {string|object=} context When stateOrName is a relative state reference, the state will be retrieved relative to context.
1372
+ * @returns {Object|Array} State configuration object or array of all objects.
1135
1373
  */
1136
1374
  $state.get = function (stateOrName, context) {
1137
- if (!isDefined(stateOrName)) {
1138
- var list = [];
1139
- forEach(states, function(state) { list.push(state.self); });
1140
- return list;
1141
- }
1142
- var state = findState(stateOrName, context);
1375
+ if (arguments.length === 0) return map(objectKeys(states), function(name) { return states[name].self; });
1376
+ var state = findState(stateOrName, context || $state.$current);
1143
1377
  return (state && state.self) ? state.self : null;
1144
1378
  };
1145
1379
 
1146
- function resolveState(state, params, paramsAreFiltered, inherited, dst) {
1380
+ function resolveState(state, params, paramsAreFiltered, inherited, dst, options) {
1147
1381
  // Make a restricted $stateParams with only the parameters that apply to this state if
1148
1382
  // necessary. In addition to being available to the controller and onEnter/onExit callbacks,
1149
1383
  // we also need $stateParams to be available for any $injector calls we make during the
1150
1384
  // dependency resolution process.
1151
- var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params, params);
1385
+ var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params);
1152
1386
  var locals = { $stateParams: $stateParams };
1153
1387
 
1154
1388
  // Resolve 'global' dependencies for the state, i.e. those not specific to a view.
@@ -1156,35 +1390,43 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1156
1390
  // to the set that should be visible to the state, and are independent of when we update
1157
1391
  // the global $state and $stateParams values.
1158
1392
  dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state);
1159
- var promises = [ dst.resolve.then(function (globals) {
1393
+ var promises = [dst.resolve.then(function (globals) {
1160
1394
  dst.globals = globals;
1161
- }) ];
1395
+ })];
1162
1396
  if (inherited) promises.push(inherited);
1163
1397
 
1164
- // Resolve template and dependencies for all views.
1165
- forEach(state.views, function (view, name) {
1166
- var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {});
1167
- injectables.$template = [ function () {
1168
- return $view.load(name, { view: view, locals: locals, params: $stateParams, notify: false }) || '';
1169
- }];
1170
-
1171
- promises.push($resolve.resolve(injectables, locals, dst.resolve, state).then(function (result) {
1172
- // References to the controller (only instantiated at link time)
1173
- if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) {
1174
- var injectLocals = angular.extend({}, injectables, locals);
1175
- result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals);
1176
- } else {
1177
- result.$$controller = view.controller;
1178
- }
1179
- // Provide access to the state itself for internal use
1180
- result.$$state = state;
1181
- result.$$controllerAs = view.controllerAs;
1182
- dst[name] = result;
1183
- }));
1184
- });
1398
+ function resolveViews() {
1399
+ var viewsPromises = [];
1400
+
1401
+ // Resolve template and dependencies for all views.
1402
+ forEach(state.views, function (view, name) {
1403
+ var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {});
1404
+ injectables.$template = [ function () {
1405
+ return $view.load(name, { view: view, locals: dst.globals, params: $stateParams, notify: options.notify }) || '';
1406
+ }];
1407
+
1408
+ viewsPromises.push($resolve.resolve(injectables, dst.globals, dst.resolve, state).then(function (result) {
1409
+ // References to the controller (only instantiated at link time)
1410
+ if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) {
1411
+ var injectLocals = angular.extend({}, injectables, dst.globals);
1412
+ result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals);
1413
+ } else {
1414
+ result.$$controller = view.controller;
1415
+ }
1416
+ // Provide access to the state itself for internal use
1417
+ result.$$state = state;
1418
+ result.$$controllerAs = view.controllerAs;
1419
+ dst[name] = result;
1420
+ }));
1421
+ });
1422
+
1423
+ return $q.all(viewsPromises).then(function(){
1424
+ return dst.globals;
1425
+ });
1426
+ }
1185
1427
 
1186
1428
  // Wait for all the promises and then return the activation object
1187
- return $q.all(promises).then(function (values) {
1429
+ return $q.all(promises).then(resolveViews).then(function (values) {
1188
1430
  return dst;
1189
1431
  });
1190
1432
  }
@@ -1192,8 +1434,27 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
1192
1434
  return $state;
1193
1435
  }
1194
1436
 
1195
- function shouldTriggerReload(to, from, locals, options) {
1196
- if ( to === from && ((locals === from.locals && !options.reload) || (to.self.reloadOnSearch === false)) ) {
1437
+ function shouldSkipReload(to, toParams, from, fromParams, locals, options) {
1438
+ // Return true if there are no differences in non-search (path/object) params, false if there are differences
1439
+ function nonSearchParamsEqual(fromAndToState, fromParams, toParams) {
1440
+ // Identify whether all the parameters that differ between `fromParams` and `toParams` were search params.
1441
+ function notSearchParam(key) {
1442
+ return fromAndToState.params[key].location != "search";
1443
+ }
1444
+ var nonQueryParamKeys = fromAndToState.params.$$keys().filter(notSearchParam);
1445
+ var nonQueryParams = pick.apply({}, [fromAndToState.params].concat(nonQueryParamKeys));
1446
+ var nonQueryParamSet = new $$UMFP.ParamSet(nonQueryParams);
1447
+ return nonQueryParamSet.$$equals(fromParams, toParams);
1448
+ }
1449
+
1450
+ // If reload was not explicitly requested
1451
+ // and we're transitioning to the same state we're already in
1452
+ // and the locals didn't change
1453
+ // or they changed in a way that doesn't merit reloading
1454
+ // (reloadOnParams:false, or reloadOnSearch.false and only search params changed)
1455
+ // Then return true.
1456
+ if (!options.reload && to === from &&
1457
+ (locals === from.locals || (to.self.reloadOnSearch === false && nonSearchParamsEqual(from, fromParams, toParams)))) {
1197
1458
  return true;
1198
1459
  }
1199
1460
  }