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
@@ -2,9 +2,9 @@
2
2
  * angular-ui-bootstrap
3
3
  * http://angular-ui.github.io/bootstrap/
4
4
 
5
- * Version: 0.11.0 - 2014-05-01
5
+ * Version: 0.13.0 - 2015-05-02
6
6
  * License: MIT
7
7
  */
8
- angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(a){return{link:function(b,c,d){function e(b){function d(){j===e&&(j=void 0)}var e=a(c,b);return j&&j.cancel(),j=e,e.then(d,d),e}function f(){k?(k=!1,g()):(c.removeClass("collapse").addClass("collapsing"),e({height:c[0].scrollHeight+"px"}).then(g))}function g(){c.removeClass("collapsing"),c.addClass("collapse in"),c.css({height:"auto"})}function h(){if(k)k=!1,i(),c.css({height:0});else{c.css({height:c[0].scrollHeight+"px"});{c[0].offsetWidth}c.removeClass("collapse in").addClass("collapsing"),e({height:0}).then(i)}}function i(){c.removeClass("collapsing"),c.addClass("collapse")}var j,k=!0;b.$watch(d.collapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,function(){}))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$transition",function(a,b,c){function d(){e();var c=+a.interval;!isNaN(c)&&c>=0&&(g=b(f,c))}function e(){g&&(b.cancel(g),g=null)}function f(){h?(a.next(),d()):a.pause()}var g,h,i=this,j=i.slides=a.slides=[],k=-1;i.currentSlide=null;var l=!1;i.select=a.select=function(e,f){function g(){if(!l){if(i.currentSlide&&angular.isString(f)&&!a.noTransition&&e.$element){e.$element.addClass(f);{e.$element[0].offsetWidth}angular.forEach(j,function(a){angular.extend(a,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(e,{direction:f,active:!0,entering:!0}),angular.extend(i.currentSlide||{},{direction:f,leaving:!0}),a.$currentTransition=c(e.$element,{}),function(b,c){a.$currentTransition.then(function(){h(b,c)},function(){h(b,c)})}(e,i.currentSlide)}else h(e,i.currentSlide);i.currentSlide=e,k=m,d()}}function h(b,c){angular.extend(b,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(c||{},{direction:"",active:!1,leaving:!1,entering:!1}),a.$currentTransition=null}var m=j.indexOf(e);void 0===f&&(f=m>k?"next":"prev"),e&&e!==i.currentSlide&&(a.$currentTransition?(a.$currentTransition.cancel(),b(g)):g())},a.$on("$destroy",function(){l=!0}),i.indexOfSlide=function(a){return j.indexOf(a)},a.next=function(){var b=(k+1)%j.length;return a.$currentTransition?void 0:i.select(j[b],"next")},a.prev=function(){var b=0>k-1?j.length-1:k-1;return a.$currentTransition?void 0:i.select(j[b],"prev")},a.isActive=function(a){return i.currentSlide===a},a.$watch("interval",d),a.$on("$destroy",e),a.play=function(){h||(h=!0,d())},a.pause=function(){a.noPause||(h=!1,e())},i.addSlide=function(b,c){b.$element=c,j.push(b),1===j.length||b.active?(i.select(j[j.length-1]),1==j.length&&a.play()):b.active=!1},i.removeSlide=function(a){var b=j.indexOf(a);j.splice(b,1),j.length>0&&a.active?i.select(b>=j.length?j[b-1]:j[b]):k>b&&k--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a,b,c){return 1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}this.parsers={};var d={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")}};this.createParser=function(a){var c=[],e=a.split("");return angular.forEach(d,function(b,d){var f=a.indexOf(d);if(f>-1){a=a.split(""),e[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+d.length;h>g;g++)e[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+e.join("")+"$"),map:b(c,"index")}},this.parse=function(b,d){if(!angular.isString(b))return b;d=a.DATETIME_FORMATS[d]||d,this.parsers[d]||(this.parsers[d]=this.createParser(d));var e=this.parsers[d],f=e.regex,g=e.map,h=b.match(f);if(h&&h.length){for(var i,j={year:1900,month:0,date:1,hours:0},k=1,l=h.length;l>k;k++){var m=g[k-1];m.apply&&m.apply.call(j,h[k])}return c(j.year,j.month,j.date)&&(i=new Date(j.year,j.month,j.date,j.hours)),i}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),this.activeDate=angular.isDefined(b.initDate)?a.$parent.$eval(b.initDate):new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$modelValue){var a=new Date(j.$modelValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$modelValue?new Date(j.$modelValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$modelValue?new Date(j.$modelValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$modelValue?new Date(j.$modelValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=h(b.rows[0][0].date),p=b.rows.length;b.weekNumbers.push(o++)<p;);}},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},e.handleKeyDown=function(a){var b=e.activeDate.getDate();if("left"===a)b-=1;else if("up"===a)b-=7;else if("right"===a)b+=1;else if("down"===a)b+=7;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getMonth()+("pageup"===a?-1:1);e.activeDate.setMonth(c,1),b=Math.min(f(e.activeDate.getFullYear(),e.activeDate.getMonth()),b)}else"home"===a?b=1:"end"===a&&(b=f(e.activeDate.getFullYear(),e.activeDate.getMonth()));e.activeDate.setDate(b)},e.refreshView()}}}]).directive("monthpicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/month.html",require:"^datepicker",link:function(b,c,d,e){e.step={years:1},e.element=c,e._refreshView=function(){for(var c=new Array(12),d=e.activeDate.getFullYear(),f=0;12>f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(a){if(angular.isDate(a)&&!isNaN(a))return k.$setValidity("date",!0),a;if(angular.isString(a)){var b=f.parse(a,n)||new Date(a);return isNaN(b)?void k.$setValidity("date",!1):(k.$setValidity("date",!0),b)}return void k.$setValidity("date",!1)}return k.$setValidity("date",!0),null}var n,o=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,p=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]},j.$observe("datepickerPopup",function(a){n=a||g.datepickerPopup,k.$render()});var q=angular.element("<div datepicker-popup-wrap><div datepicker></div></div>");q.attr({"ng-model":"date","ng-change":"dateSelection()"});var r=angular.element(q.children()[0]);j.datepickerOptions&&angular.forEach(h.$parent.$eval(j.datepickerOptions),function(a,b){r.attr(l(b),a)}),angular.forEach(["minDate","maxDate"],function(a){j[a]&&(h.$parent.$watch(b(j[a]),function(b){h[a]=b}),r.attr(l(a),a))}),j.dateDisabled&&r.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),k.$parsers.unshift(m),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a),k.$setViewValue(h.date),k.$render(),o&&(h.isOpen=!1,i[0].focus())},i.bind("input change keyup",function(){h.$apply(function(){h.date=k.$modelValue})}),k.$render=function(){var a=k.$viewValue?e(k.$viewValue,n):"";i.val(a),h.date=m(k.$modelValue)};var s=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},t=function(a){h.keydown(a)};i.bind("keydown",t),h.keydown=function(a){27===a.which?(a.preventDefault(),a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=p?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",s)):c.unbind("click",s)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(k.$modelValue)?(a=new Date(k.$modelValue),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var u=a(q)(h);p?c.find("body").append(u):i.after(u),h.$on("$destroy",function(){u.remove(),i.unbind("keydown",t),c.unbind("click",s)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",[]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document",function(a){var b=null;this.open=function(e){b||(a.bind("click",c),a.bind("keydown",d)),b&&b!==e&&(b.isOpen=!1),b=e},this.close=function(e){b===e&&(b=null,a.unbind("click",c),a.unbind("keydown",d))};var c=function(a){a&&a.isDefaultPrevented()||b.$apply(function(){b.isOpen=!1})},d=function(a){27===a.which&&(b.focusToggleElement(),c())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate",function(a,b,c,d,e,f){var g,h=this,i=a.$new(),j=d.openClass,k=angular.noop,l=b.onToggle?c(b.onToggle):angular.noop;this.init=function(d){h.$element=d,b.isOpen&&(g=c(b.isOpen),k=g.assign,a.$watch(g,function(a){i.isOpen=!!a}))},this.toggle=function(a){return i.isOpen=arguments.length?!!a:!i.isOpen},this.isOpen=function(){return i.isOpen},i.focusToggleElement=function(){h.toggleElement&&h.toggleElement[0].focus()},i.$watch("isOpen",function(b,c){f[b?"addClass":"removeClass"](h.$element,j),b?(i.focusToggleElement(),e.open(i)):e.close(i),k(a,b),angular.isDefined(b)&&b!==c&&l(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){i.isOpen=!1}),a.$on("$destroy",function(){i.$destroy()})}]).directive("dropdown",function(){return{restrict:"CA",controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownToggle",function(){return{restrict:"CA",require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b==a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b==a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.splice(a.length-1,1)[0]},length:function(){return a.length}}}}}).directive("modalBackdrop",["$timeout",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/modal/backdrop.html",link:function(b){b.animate=!1,a(function(){b.animate=!0})}}}]).directive("modalWindow",["$modalStack","$timeout",function(a,b){return{restrict:"EA",scope:{index:"@",animate:"="},replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/modal/window.html"},link:function(c,d,e){d.addClass(e.windowClass||""),c.size=e.size,b(function(){c.animate=!0,d[0].focus()}),c.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!=c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))}}}}]).factory("$modalStack",["$transition","$timeout","$document","$compile","$rootScope","$$stackedMap",function(a,b,c,d,e,f){function g(){for(var a=-1,b=n.keys(),c=0;c<b.length;c++)n.get(b[c]).value.backdrop&&(a=c);return a}function h(a){var b=c.find("body").eq(0),d=n.get(a).value;n.remove(a),j(d.modalDomEl,d.modalScope,300,function(){d.modalScope.$destroy(),b.toggleClass(m,n.length()>0),i()})}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g,0)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){o.dismiss(b.key,"escape key press")})))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("body").eq(0),h=g();h>=0&&!k&&(l=e.$new(!0),l.index=h,k=d("<div modal-backdrop></div>")(l),f.append(k));var i=angular.element("<div modal-window></div>");i.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:n.length()-1,animate:"animate"}).html(b.content);var j=d(i)(b.scope);n.top().value.modalDomEl=j,f.append(j),f.addClass(m)},o.close=function(a,b){var c=n.get(a).value;c&&(c.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a).value;c&&(c.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(f,g){e=f,this.config=g,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=g.itemsPerPage},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b){a.page!==b&&b>0&&b<=a.totalPages&&(e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages},a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";
9
- return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$parse","$document","$position","$interpolate",function(e,f,g,h,i,j,k){return function(e,l,m){function n(a){var b=a||o.trigger||m,d=c[b]||b;return{show:b,hide:d}}var o=angular.extend({},b,d),p=a(e),q=k.startSymbol(),r=k.endSymbol(),s="<div "+p+'-popup title="'+q+"tt_title"+r+'" content="'+q+"tt_content"+r+'" placement="'+q+"tt_placement"+r+'" animation="tt_animation" is-open="tt_isOpen"></div>';return{restrict:"EA",scope:!0,compile:function(){var a=f(s);return function(b,c,d){function f(){b.tt_isOpen?m():k()}function k(){(!y||b.$eval(d[l+"Enable"]))&&(b.tt_popupDelay?v||(v=g(p,b.tt_popupDelay,!1),v.then(function(a){a()})):p()())}function m(){b.$apply(function(){q()})}function p(){return v=null,u&&(g.cancel(u),u=null),b.tt_content?(r(),t.css({top:0,left:0,display:"block"}),w?i.find("body").append(t):c.after(t),z(),b.tt_isOpen=!0,b.$digest(),z):angular.noop}function q(){b.tt_isOpen=!1,g.cancel(v),v=null,b.tt_animation?u||(u=g(s,500)):s()}function r(){t&&s(),t=a(b,function(){}),b.$digest()}function s(){u=null,t&&(t.remove(),t=null)}var t,u,v,w=angular.isDefined(o.appendToBody)?o.appendToBody:!1,x=n(void 0),y=angular.isDefined(d[l+"Enable"]),z=function(){var a=j.positionElements(c,t,b.tt_placement,w);a.top+="px",a.left+="px",t.css(a)};b.tt_isOpen=!1,d.$observe(e,function(a){b.tt_content=a,!a&&b.tt_isOpen&&q()}),d.$observe(l+"Title",function(a){b.tt_title=a}),d.$observe(l+"Placement",function(a){b.tt_placement=angular.isDefined(a)?a:o.placement}),d.$observe(l+"PopupDelay",function(a){var c=parseInt(a,10);b.tt_popupDelay=isNaN(c)?o.popupDelay:c});var A=function(){c.unbind(x.show,k),c.unbind(x.hide,m)};d.$observe(l+"Trigger",function(a){A(),x=n(a),x.show===x.hide?c.bind(x.show,f):(c.bind(x.show,k),c.bind(x.hide,m))});var B=b.$eval(d[l+"Animation"]);b.tt_animation=angular.isDefined(B)?!!B:o.animation,d.$observe(l+"AppendToBody",function(a){w=angular.isDefined(a)?h(a)(b):w}),w&&b.$on("$locationChangeSuccess",function(){b.tt_isOpen&&q()}),b.$on("$destroy",function(){g.cancel(u),g.cancel(v),A(),s()})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(a){return a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length?a.active=!0:a.active&&b.select(a)},b.removeTab=function(a){var d=c.indexOf(a);if(a.active&&c.length>1){var e=d==c.length-1?d-1:d+1;b.select(c[e])}c.splice(d,1)}}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){b.$watch("active",function(a){a&&f.select(b)}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),a.minutes="m"===b?d:i(d),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render;var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$modelValue?new Date(o.$modelValue):null;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=b(k.ngModel).assign,v=g.parse(k.typeahead),w=i.$new();i.$on("$destroy",function(){w.$destroy()});var x="typeahead-"+w.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":x});var y=angular.element("<div typeahead-popup></div>");y.attr({id:x,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&y.attr("template-url",k.typeaheadTemplateUrl);var z=function(){w.matches=[],w.activeIdx=-1,j.attr("aria-expanded",!1)},A=function(a){return x+"-option-"+a};w.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",A(a))});var B=function(a){var b={$viewValue:a};q(i,!0),c.when(v.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c.length>0){w.activeIdx=0,w.matches.length=0;for(var e=0;e<c.length;e++)b[v.itemName]=c[e],w.matches.push({id:A(e),label:v.viewMapper(w,b),model:c[e]});w.query=a,w.position=t?f.offset(j):f.position(j),w.position.top=w.position.top+j.prop("offsetHeight"),j.attr("aria-expanded",!0)}else z();d&&q(i,!1)},function(){z(),q(i,!1)})};z(),w.query=void 0;var C;l.$parsers.unshift(function(a){return m=!0,a&&a.length>=n?o>0?(C&&d.cancel(C),C=d(function(){B(a)},o)):B(a):(q(i,!1),z()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return s?(d.$model=a,s(i,d)):(d[v.itemName]=a,b=v.viewMapper(i,d),d[v.itemName]=void 0,c=v.viewMapper(i,d),b!==c?b:a)}),w.select=function(a){var b,c,e={};e[v.itemName]=c=w.matches[a].model,b=v.modelMapper(i,e),u(i,b),l.$setValidity("editable",!0),r(i,{$item:c,$model:b,$label:v.viewMapper(i,e)}),z(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==w.matches.length&&-1!==h.indexOf(a.which)&&(a.preventDefault(),40===a.which?(w.activeIdx=(w.activeIdx+1)%w.matches.length,w.$digest()):38===a.which?(w.activeIdx=(w.activeIdx?w.activeIdx:w.matches.length)-1,w.$digest()):13===a.which||9===a.which?w.$apply(function(){w.select(w.activeIdx)}):27===a.which&&(a.stopPropagation(),z(),w.$digest()))}),j.bind("blur",function(){m=!1});var D=function(a){j[0]!==a.target&&(z(),w.$digest())};e.bind("click",D),i.$on("$destroy",function(){e.unbind("click",D)});var E=a(y)(w);t?e.find("body").append(E):j.after(E)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(a,b,c,d){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(e,f,g){var h=d(g.templateUrl)(e.$parent)||"template/typeahead/typeahead-match.html";a.get(h,{cache:b}).success(function(a){f.replaceWith(c(a.trim())(e))})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"<strong>$&</strong>"):b}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'<div class="panel panel-default">\n <div class="panel-heading">\n <h4 class="panel-title">\n <a class="accordion-toggle" ng-click="toggleOpen()" accordion-transclude="heading"><span ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n </h4>\n </div>\n <div class="panel-collapse" collapse="!isOpen">\n <div class="panel-body" ng-transclude></div>\n </div>\n</div>')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'<div class="panel-group" ng-transclude></div>')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'<div class="alert" ng-class="{\'alert-{{type || \'warning\'}}\': true, \'alert-dismissable\': closeable}" role="alert">\n <button ng-show="closeable" type="button" class="close" ng-click="close()">\n <span aria-hidden="true">&times;</span>\n <span class="sr-only">Close</span>\n </button>\n <div ng-transclude></div>\n</div>\n')}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel" ng-swipe-right="prev()" ng-swipe-left="next()">\n <ol class="carousel-indicators" ng-show="slides.length > 1">\n <li ng-repeat="slide in slides track by $index" ng-class="{active: isActive(slide)}" ng-click="select(slide)"></li>\n </ol>\n <div class="carousel-inner" ng-transclude></div>\n <a class="left carousel-control" ng-click="prev()" ng-show="slides.length > 1"><span class="glyphicon glyphicon-chevron-left"></span></a>\n <a class="right carousel-control" ng-click="next()" ng-show="slides.length > 1"><span class="glyphicon glyphicon-chevron-right"></span></a>\n</div>\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html","<div ng-class=\"{\n 'active': leaving || (active && !entering),\n 'prev': (next || active) && direction=='prev',\n 'next': (next || active) && direction=='next',\n 'right': direction=='prev',\n 'left': direction=='next'\n }\" class=\"item text-center\" ng-transclude></div>\n")}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'<div ng-switch="datepickerMode" role="application" ng-keydown="keydown($event)">\n <daypicker ng-switch-when="day" tabindex="0"></daypicker>\n <monthpicker ng-switch-when="month" tabindex="0"></monthpicker>\n <yearpicker ng-switch-when="year" tabindex="0"></yearpicker>\n</div>')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n <th colspan="{{5 + showWeeks}}"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n </tr>\n <tr>\n <th ng-show="showWeeks" class="text-center"></th>\n <th ng-repeat="label in labels track by $index" class="text-center"><small aria-label="{{label.full}}">{{label.abbr}}</small></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="row in rows track by $index">\n <td ng-show="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td>\n <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n <button type="button" style="width:100%;" class="btn btn-default btn-sm" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-muted\': dt.secondary, \'text-info\': dt.current}">{{dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n <th><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="row in rows track by $index">\n <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n <button type="button" style="width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-info\': dt.current}">{{dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'<ul class="dropdown-menu" ng-style="{display: (isOpen && \'block\') || \'none\', top: position.top+\'px\', left: position.left+\'px\'}" ng-keydown="keydown($event)">\n <li ng-transclude></li>\n <li ng-if="showButtonBar" style="padding:10px 9px 2px">\n <span class="btn-group">\n <button type="button" class="btn btn-sm btn-info" ng-click="select(\'today\')">{{ getText(\'current\') }}</button>\n <button type="button" class="btn btn-sm btn-danger" ng-click="select(null)">{{ getText(\'clear\') }}</button>\n </span>\n <button type="button" class="btn btn-sm btn-success pull-right" ng-click="close()">{{ getText(\'close\') }}</button>\n </li>\n</ul>\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n <th colspan="3"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="row in rows track by $index">\n <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n <button type="button" style="width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-info\': dt.current}">{{dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'<div class="modal-backdrop fade"\n ng-class="{in: animate}"\n ng-style="{\'z-index\': 1040 + (index && 1 || 0) + index*10}"\n></div>\n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'<div tabindex="-1" role="dialog" class="modal fade" ng-class="{in: animate}" ng-style="{\'z-index\': 1050 + index*10, display: \'block\'}" ng-click="close($event)">\n <div class="modal-dialog" ng-class="{\'modal-sm\': size == \'sm\', \'modal-lg\': size == \'lg\'}"><div class="modal-content" ng-transclude></div></div>\n</div>')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'<ul class="pager">\n <li ng-class="{disabled: noPrevious(), previous: align}"><a href ng-click="selectPage(page - 1)">{{getText(\'previous\')}}</a></li>\n <li ng-class="{disabled: noNext(), next: align}"><a href ng-click="selectPage(page + 1)">{{getText(\'next\')}}</a></li>\n</ul>')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'<ul class="pagination">\n <li ng-if="boundaryLinks" ng-class="{disabled: noPrevious()}"><a href ng-click="selectPage(1)">{{getText(\'first\')}}</a></li>\n <li ng-if="directionLinks" ng-class="{disabled: noPrevious()}"><a href ng-click="selectPage(page - 1)">{{getText(\'previous\')}}</a></li>\n <li ng-repeat="page in pages track by $index" ng-class="{active: page.active}"><a href ng-click="selectPage(page.number)">{{page.text}}</a></li>\n <li ng-if="directionLinks" ng-class="{disabled: noNext()}"><a href ng-click="selectPage(page + 1)">{{getText(\'next\')}}</a></li>\n <li ng-if="boundaryLinks" ng-class="{disabled: noNext()}"><a href ng-click="selectPage(totalPages)">{{getText(\'last\')}}</a></li>\n</ul>')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-unsafe-popup.html",'<div class="tooltip {{placement}}" ng-class="{ in: isOpen(), fade: animation() }">\n <div class="tooltip-arrow"></div>\n <div class="tooltip-inner" bind-html-unsafe="content"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'<div class="tooltip {{placement}}" ng-class="{ in: isOpen(), fade: animation() }">\n <div class="tooltip-arrow"></div>\n <div class="tooltip-inner" ng-bind="content"></div>\n</div>\n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'<div class="popover {{placement}}" ng-class="{ in: isOpen(), fade: animation() }">\n <div class="arrow"></div>\n\n <div class="popover-inner">\n <h3 class="popover-title" ng-bind="title" ng-show="title"></h3>\n <div class="popover-content" ng-bind="content"></div>\n </div>\n</div>\n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'<div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: percent + \'%\'}" aria-valuetext="{{percent | number:0}}%" ng-transclude></div>')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'<div class="progress" ng-transclude></div>')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'<div class="progress">\n <div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: percent + \'%\'}" aria-valuetext="{{percent | number:0}}%" ng-transclude></div>\n</div>')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'<span ng-mouseleave="reset()" ng-keydown="onKeydown($event)" tabindex="0" role="slider" aria-valuemin="0" aria-valuemax="{{range.length}}" aria-valuenow="{{value}}">\n <i ng-repeat="r in range track by $index" ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || \'glyphicon-star\') || (r.stateOff || \'glyphicon-star-empty\')">\n <span class="sr-only">({{ $index < value ? \'*\' : \' \' }})</span>\n </i>\n</span>')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'<li ng-class="{active: active, disabled: disabled}">\n <a ng-click="select()" tab-heading-transclude>{{heading}}</a>\n</li>\n')}]),angular.module("template/tabs/tabset-titles.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset-titles.html","<ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical}\">\n</ul>\n")}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'\n<div>\n <ul class="nav nav-{{type || \'tabs\'}}" ng-class="{\'nav-stacked\': vertical, \'nav-justified\': justified}" ng-transclude></ul>\n <div class="tab-content">\n <div class="tab-pane" \n ng-repeat="tab in tabs" \n ng-class="{active: tab.active}"\n tab-content-transclude="tab">\n </div>\n </div>\n</div>\n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'<table>\n <tbody>\n <tr class="text-center">\n <td><a ng-click="incrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n <td>&nbsp;</td>\n <td><a ng-click="incrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n <td ng-show="showMeridian"></td>\n </tr>\n <tr>\n <td style="width:50px;" class="form-group" ng-class="{\'has-error\': invalidHours}">\n <input type="text" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-mousewheel="incrementHours()" ng-readonly="readonlyInput" maxlength="2">\n </td>\n <td>:</td>\n <td style="width:50px;" class="form-group" ng-class="{\'has-error\': invalidMinutes}">\n <input type="text" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2">\n </td>\n <td ng-show="showMeridian"><button type="button" class="btn btn-default text-center" ng-click="toggleMeridian()">{{meridian}}</button></td>\n </tr>\n <tr class="text-center">\n <td><a ng-click="decrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n <td>&nbsp;</td>\n <td><a ng-click="decrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n <td ng-show="showMeridian"></td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'<a tabindex="-1" bind-html-unsafe="match.label | typeaheadHighlight:query"></a>')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'<ul class="dropdown-menu" ng-if="isOpen()" ng-style="{top: position.top+\'px\', left: position.left+\'px\'}" style="display: block;" role="listbox" aria-hidden="{{!isOpen()}}">\n <li ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)" role="option" id="{{match.id}}">\n <div typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>\n </li>\n</ul>')
10
- }]);
8
+ angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.transition","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-popup.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/tooltip/tooltip-template-popup.html","template/popover/popover-template.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.collapse",[]).directive("collapse",["$animate",function(a){return{link:function(b,c,d){function e(){c.removeClass("collapse").addClass("collapsing"),a.addClass(c,"in",{to:{height:c[0].scrollHeight+"px"}}).then(f)}function f(){c.removeClass("collapsing"),c.css({height:"auto"})}function g(){c.css({height:c[0].scrollHeight+"px"}).removeClass("collapse").addClass("collapsing"),a.removeClass(c,"in",{to:{height:"0"}}).then(h)}function h(){c.css({height:"0"}),c.removeClass("collapsing"),c.addClass("collapse")}b.$watch(d.collapse,function(a){a?g():e()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,angular.noop))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b,this.close=a.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(a){return{require:"alert",link:function(b,c,d,e){a(function(){e.close()},parseInt(d.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",[]).controller("CarouselController",["$scope","$interval","$animate",function(a,b,c){function d(a){if(angular.isUndefined(k[a].index))return k[a];{var b;k.length}for(b=0;b<k.length;++b)if(k[b].index==a)return k[b]}function e(){f();var c=+a.interval;!isNaN(c)&&c>0&&(h=b(g,c))}function f(){h&&(b.cancel(h),h=null)}function g(){var b=+a.interval;i&&!isNaN(b)&&b>0?a.next():a.pause()}var h,i,j=this,k=j.slides=a.slides=[],l=-1;j.currentSlide=null;var m=!1;j.select=a.select=function(b,d){function f(){m||(angular.extend(b,{direction:d,active:!0}),angular.extend(j.currentSlide||{},{direction:d,active:!1}),c.enabled()&&!a.noTransition&&b.$element&&(a.$currentTransition=!0,b.$element.one("$animate:close",function(){a.$currentTransition=null})),j.currentSlide=b,l=g,e())}var g=j.indexOfSlide(b);void 0===d&&(d=g>j.getCurrentIndex()?"next":"prev"),b&&b!==j.currentSlide&&f()},a.$on("$destroy",function(){m=!0}),j.getCurrentIndex=function(){return j.currentSlide&&angular.isDefined(j.currentSlide.index)?+j.currentSlide.index:l},j.indexOfSlide=function(a){return angular.isDefined(a.index)?+a.index:k.indexOf(a)},a.next=function(){var b=(j.getCurrentIndex()+1)%k.length;return a.$currentTransition?void 0:j.select(d(b),"next")},a.prev=function(){var b=j.getCurrentIndex()-1<0?k.length-1:j.getCurrentIndex()-1;return a.$currentTransition?void 0:j.select(d(b),"prev")},a.isActive=function(a){return j.currentSlide===a},a.$watch("interval",e),a.$on("$destroy",f),a.play=function(){i||(i=!0,e())},a.pause=function(){a.noPause||(i=!1,f())},j.addSlide=function(b,c){b.$element=c,k.push(b),1===k.length||b.active?(j.select(k[k.length-1]),1==k.length&&a.play()):b.active=!1},j.removeSlide=function(a){angular.isDefined(a.index)&&k.sort(function(a,b){return+a.index>+b.index});var b=k.indexOf(a);k.splice(b,1),k.length>0&&a.active?j.select(b>=k.length?k[b-1]:k[b]):l>b&&l--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?",index:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}).animation(".item",["$animate",function(a){return{beforeAddClass:function(b,c,d){if("active"==c&&b.parent()&&!b.parent().scope().noTransition){var e=!1,f=b.isolateScope().direction,g="next"==f?"left":"right";return b.addClass(f),a.addClass(b,g).then(function(){e||b.removeClass(g+" "+f),d()}),function(){e=!0}}d()},beforeRemoveClass:function(b,c,d){if("active"==c&&b.parent()&&!b.parent().scope().noTransition){var e=!1,f=b.isolateScope().direction,g="next"==f?"left":"right";return a.addClass(b,g).then(function(){e||b.removeClass(g),d()}),function(){e=!0}}d()}}}]),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a){var c=[],d=a.split("");return angular.forEach(f,function(b,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:b(c,"index")}}function d(a,b,c){return 1>c?!1:1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}var e=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;this.parsers={};var f={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")},HH:{regex:"(?:0|1)[0-9]|2[0-3]",apply:function(a){this.hours=+a}},H:{regex:"1?[0-9]|2[0-3]",apply:function(a){this.hours=+a}},mm:{regex:"[0-5][0-9]",apply:function(a){this.minutes=+a}},m:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.minutes=+a}},sss:{regex:"[0-9][0-9][0-9]",apply:function(a){this.milliseconds=+a}},ss:{regex:"[0-5][0-9]",apply:function(a){this.seconds=+a}},s:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.seconds=+a}}};this.parse=function(b,f,g){if(!angular.isString(b)||!f)return b;f=a.DATETIME_FORMATS[f]||f,f=f.replace(e,"\\$&"),this.parsers[f]||(this.parsers[f]=c(f));var h=this.parsers[f],i=h.regex,j=h.map,k=b.match(i);if(k&&k.length){var l,m;l=g?{year:g.getFullYear(),month:g.getMonth(),date:g.getDate(),hours:g.getHours(),minutes:g.getMinutes(),seconds:g.getSeconds(),milliseconds:g.getMilliseconds()}:{year:1900,month:0,date:1,hours:0,minutes:0,seconds:0,milliseconds:0};for(var n=1,o=k.length;o>n;n++){var p=j[n-1];p.apply&&p.apply.call(l,k[n])}return d(l.year,l.month,l.date)&&(m=new Date(l.year,l.month,l.date,l.hours,l.minutes,l.seconds,l.milliseconds||0)),m}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null,shortcutPropagation:!1}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange","shortcutPropagation"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.maxMode=i.maxMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),angular.isDefined(b.initDate)?(this.activeDate=a.$parent.$eval(b.initDate)||new Date,a.$parent.$watch(b.initDate,function(a){a&&(j.$isEmpty(j.$modelValue)||j.$invalid)&&(i.activeDate=a,i.refreshView())})):this.activeDate=new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$viewValue){var a=new Date(j.$viewValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$viewValue?new Date(j.$viewValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$viewValue?new Date(j.$viewValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date),customClass:this.customClass(a)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$viewValue?new Date(j.$viewValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),i.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&",customClass:"&",shortcutPropagation:"&?"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=(11-e.startingDay)%7,p=b.rows.length,q=0;p>q;q++)b.weekNumbers.push(h(b.rows[q][o].date))}},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},e.handleKeyDown=function(a){var b=e.activeDate.getDate();if("left"===a)b-=1;else if("up"===a)b-=7;else if("right"===a)b+=1;else if("down"===a)b+=7;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getMonth()+("pageup"===a?-1:1);e.activeDate.setMonth(c,1),b=Math.min(f(e.activeDate.getFullYear(),e.activeDate.getMonth()),b)}else"home"===a?b=1:"end"===a&&(b=f(e.activeDate.getFullYear(),e.activeDate.getMonth()));e.activeDate.setDate(b)},e.refreshView()}}}]).directive("monthpicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/month.html",require:"^datepicker",link:function(b,c,d,e){e.step={years:1},e.element=c,e._refreshView=function(){for(var c=new Array(12),d=e.activeDate.getFullYear(),f=0;12>f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",html5Types:{date:"yyyy-MM-dd","datetime-local":"yyyy-MM-ddTHH:mm:ss.sss",month:"yyyy-MM"},currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&",customClass:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(angular.isNumber(a)&&(a=new Date(a)),a){if(angular.isDate(a)&&!isNaN(a))return a;if(angular.isString(a)){var b=f.parse(a,o,h.date)||new Date(a);return isNaN(b)?void 0:b}return void 0}return null}function n(a,b){var c=a||b;if(angular.isNumber(c)&&(c=new Date(c)),c){if(angular.isDate(c)&&!isNaN(c))return!0;if(angular.isString(c)){var d=f.parse(c,o)||new Date(c);return!isNaN(d)}return!1}return!0}var o,p=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,q=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]};var r=!1;if(g.html5Types[j.type]?(o=g.html5Types[j.type],r=!0):(o=j.datepickerPopup||g.datepickerPopup,j.$observe("datepickerPopup",function(a){var b=a||g.datepickerPopup;if(b!==o&&(o=b,k.$modelValue=null,!o))throw new Error("datepickerPopup must have a date format specified.")})),!o)throw new Error("datepickerPopup must have a date format specified.");if(r&&j.datepickerPopup)throw new Error("HTML5 date input types do not support custom formats.");var s=angular.element("<div datepicker-popup-wrap><div datepicker></div></div>");s.attr({"ng-model":"date","ng-change":"dateSelection()"});var t=angular.element(s.children()[0]);if(r&&"month"==j.type&&(t.attr("datepicker-mode",'"month"'),t.attr("min-mode","month")),j.datepickerOptions){var u=h.$parent.$eval(j.datepickerOptions);u.initDate&&(h.initDate=u.initDate,t.attr("init-date","initDate"),delete u.initDate),angular.forEach(u,function(a,b){t.attr(l(b),a)})}h.watchData={},angular.forEach(["minDate","maxDate","datepickerMode","initDate","shortcutPropagation"],function(a){if(j[a]){var c=b(j[a]);if(h.$parent.$watch(c,function(b){h.watchData[a]=b}),t.attr(l(a),"watchData."+a),"datepickerMode"===a){var d=c.assign;h.$watch("watchData."+a,function(a,b){a!==b&&d(h.$parent,a)})}}}),j.dateDisabled&&t.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),j.showWeeks&&t.attr("show-weeks",j.showWeeks),j.customClass&&t.attr("custom-class","customClass({ date: date, mode: mode })"),r?k.$formatters.push(function(a){return h.date=a,a}):(k.$$parserName="date",k.$validators.date=n,k.$parsers.unshift(m),k.$formatters.push(function(a){return h.date=a,k.$isEmpty(a)?a:e(a,o)})),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a);var b=h.date?e(h.date,o):"";i.val(b),k.$setViewValue(b),p&&(h.isOpen=!1,i[0].focus())},k.$viewChangeListeners.push(function(){h.date=f.parse(k.$viewValue,o,h.date)||new Date(k.$viewValue)});var v=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},w=function(a){h.keydown(a)};i.bind("keydown",w),h.keydown=function(a){27===a.which?(a.preventDefault(),h.isOpen&&a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=q?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",v)):c.unbind("click",v)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(h.date)?(a=new Date(h.date),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var x=a(s)(h);s.remove(),q?c.find("body").append(x):i.after(x),h.$on("$destroy",function(){x.remove(),i.unbind("keydown",w),c.unbind("click",v)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",["ui.bootstrap.position"]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document","$rootScope",function(a,b){var c=null;this.open=function(b){c||(a.bind("click",d),a.bind("keydown",e)),c&&c!==b&&(c.isOpen=!1),c=b},this.close=function(b){c===b&&(c=null,a.unbind("click",d),a.unbind("keydown",e))};var d=function(a){if(c&&(!a||"disabled"!==c.getAutoClose())){var d=c.getToggleElement();if(!(a&&d&&d[0].contains(a.target))){var e=c.getElement();a&&"outsideClick"===c.getAutoClose()&&e&&e[0].contains(a.target)||(c.isOpen=!1,b.$$phase||c.$apply())}}},e=function(a){27===a.which&&(c.focusToggleElement(),d())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate","$position","$document",function(a,b,c,d,e,f,g,h){var i,j=this,k=a.$new(),l=d.openClass,m=angular.noop,n=b.onToggle?c(b.onToggle):angular.noop,o=!1;this.init=function(d){j.$element=d,b.isOpen&&(i=c(b.isOpen),m=i.assign,a.$watch(i,function(a){k.isOpen=!!a})),o=angular.isDefined(b.dropdownAppendToBody),o&&j.dropdownMenu&&(h.find("body").append(j.dropdownMenu),d.on("$destroy",function(){j.dropdownMenu.remove()}))},this.toggle=function(a){return k.isOpen=arguments.length?!!a:!k.isOpen},this.isOpen=function(){return k.isOpen},k.getToggleElement=function(){return j.toggleElement},k.getAutoClose=function(){return b.autoClose||"always"},k.getElement=function(){return j.$element},k.focusToggleElement=function(){j.toggleElement&&j.toggleElement[0].focus()},k.$watch("isOpen",function(b,c){if(o&&j.dropdownMenu){var d=g.positionElements(j.$element,j.dropdownMenu,"bottom-left",!0);j.dropdownMenu.css({top:d.top+"px",left:d.left+"px",display:b?"block":"none"})}f[b?"addClass":"removeClass"](j.$element,l),b?(k.focusToggleElement(),e.open(k)):e.close(k),m(a,b),angular.isDefined(b)&&b!==c&&n(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){k.isOpen=!1}),a.$on("$destroy",function(){k.$destroy()})}]).directive("dropdown",function(){return{controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownMenu",function(){return{restrict:"AC",require:"?^dropdown",link:function(a,b,c,d){d&&(d.dropdownMenu=b)}}}).directive("dropdownToggle",function(){return{require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",[]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b==a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b==a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.splice(a.length-1,1)[0]},length:function(){return a.length}}}}}).directive("modalBackdrop",["$timeout",function(a){function b(b){b.animate=!1,a(function(){b.animate=!0})}return{restrict:"EA",replace:!0,templateUrl:"template/modal/backdrop.html",compile:function(a,c){return a.addClass(c.backdropClass),b}}}]).directive("modalWindow",["$modalStack","$q",function(a,b){return{restrict:"EA",scope:{index:"@",animate:"="},replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/modal/window.html"},link:function(c,d,e){d.addClass(e.windowClass||""),c.size=e.size,c.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!=c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))},c.$isRendered=!0;var f=b.defer();e.$observe("modalRender",function(a){"true"==a&&f.resolve()}),f.promise.then(function(){c.animate=!0;var b=d[0].querySelectorAll("[autofocus]");b.length?b[0].focus():d[0].focus();var e=a.getTop();e&&a.modalRendered(e.key)})}}}]).directive("modalAnimationClass",[function(){return{compile:function(a,b){b.modalAnimation&&a.addClass(b.modalAnimationClass)}}}]).directive("modalTransclude",function(){return{link:function(a,b,c,d,e){e(a.$parent,function(a){b.empty(),b.append(a)})}}}).factory("$modalStack",["$animate","$timeout","$document","$compile","$rootScope","$$stackedMap",function(a,b,c,d,e,f){function g(){for(var a=-1,b=o.keys(),c=0;c<b.length;c++)o.get(b[c]).value.backdrop&&(a=c);return a}function h(a){var b=c.find("body").eq(0),d=o.get(a).value;o.remove(a),j(d.modalDomEl,d.modalScope,function(){b.toggleClass(n,o.length()>0),i()})}function i(){if(l&&-1==g()){var a=m;j(l,m,function(){a=null}),l=void 0,m=void 0}}function j(c,d,f){function g(){g.done||(g.done=!0,c.remove(),d.$destroy(),f&&f())}d.animate=!1,c.attr("modal-animation")&&a.enabled()?c.one("$animate:close",function(){e.$evalAsync(g)}):b(g)}function k(a,b,c){return!a.value.modalScope.$broadcast("modal.closing",b,c).defaultPrevented}var l,m,n="modal-open",o=f.createNew(),p={};return e.$watch(g,function(a){m&&(m.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=o.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){p.dismiss(b.key,"escape key press")})))}),p.open=function(a,b){var f=c[0].activeElement;o.add(a,{deferred:b.deferred,renderDeferred:b.renderDeferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var h=c.find("body").eq(0),i=g();if(i>=0&&!l){m=e.$new(!0),m.index=i;var j=angular.element('<div modal-backdrop="modal-backdrop"></div>');j.attr("backdrop-class",b.backdropClass),b.animation&&j.attr("modal-animation","true"),l=d(j)(m),h.append(l)}var k=angular.element('<div modal-window="modal-window"></div>');k.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:o.length()-1,animate:"animate"}).html(b.content),b.animation&&k.attr("modal-animation","true");var p=d(k)(b.scope);o.top().value.modalDomEl=p,o.top().value.modalOpener=f,h.append(p),h.addClass(n)},p.close=function(a,b){var c=o.get(a);return c&&k(c,b,!0)?(c.value.deferred.resolve(b),h(a),c.value.modalOpener.focus(),!0):!c},p.dismiss=function(a,b){var c=o.get(a);return c&&k(c,b,!1)?(c.value.deferred.reject(b),h(a),c.value.modalOpener.focus(),!0):!c},p.dismissAll=function(a){for(var b=this.getTop();b&&this.dismiss(b.key,a);)b=this.getTop()},p.getTop=function(){return o.top()},p.modalRendered=function(a){var b=o.get(a);b&&b.value.renderDeferred.resolve()},p}]).provider("$modal",function(){var a={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$templateRequest","$controller","$modalStack",function(b,c,d,e,f,g){function h(a){return a.template?d.when(a.template):e(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl)}function i(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))
9
+ }),c}var j={};return j.open=function(b){var e=d.defer(),j=d.defer(),k=d.defer(),l={result:e.promise,opened:j.promise,rendered:k.promise,close:function(a){return g.close(l,a)},dismiss:function(a){return g.dismiss(l,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var m=d.all([h(b)].concat(i(b.resolve)));return m.then(function(a){var d=(b.scope||c).$new();d.$close=l.close,d.$dismiss=l.dismiss;var h,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=l,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),h=f(b.controller,i),b.controllerAs&&(d[b.controllerAs]=h)),g.open(l,{scope:d,deferred:e,renderDeferred:k,content:a[0],animation:b.animation,backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),m.then(function(){j.resolve(!0)},function(a){j.reject(a)}),l},j}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(g,h){e=g,this.config=h,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=h.itemsPerPage,a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b,c){a.page!==b&&b>0&&b<=a.totalPages&&(c&&c.target&&c.target.blur(),e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages}}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0,useContentExp:!1},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(e,f,g,h,i,j){return function(e,k,l,m){function n(a){var b=a||m.trigger||l,d=c[b]||b;return{show:b,hide:d}}m=angular.extend({},b,d,m);var o=a(e),p=j.startSymbol(),q=j.endSymbol(),r="<div "+o+'-popup title="'+p+"title"+q+'" '+(m.useContentExp?'content-exp="contentExp()" ':'content="'+p+"content"+q+'" ')+'placement="'+p+"placement"+q+'" popup-class="'+p+"popupClass"+q+'" animation="animation" is-open="isOpen"origin-scope="origScope" ></div>';return{restrict:"EA",compile:function(){var a=f(r);return function(b,c,d){function f(){E.isOpen?l():j()}function j(){(!D||b.$eval(d[k+"Enable"]))&&(s(),E.popupDelay?A||(A=g(o,E.popupDelay,!1),A.then(function(a){a()})):o()())}function l(){b.$apply(function(){p()})}function o(){return A=null,z&&(g.cancel(z),z=null),(m.useContentExp?E.contentExp():E.content)?(q(),x.css({top:0,left:0,display:"block"}),E.$digest(),F(),E.isOpen=!0,E.$apply(),F):angular.noop}function p(){E.isOpen=!1,g.cancel(A),A=null,E.animation?z||(z=g(r,500)):r()}function q(){x&&r(),y=E.$new(),x=a(y,function(a){B?h.find("body").append(a):c.after(a)}),y.$watch(function(){g(F,0,!1)}),m.useContentExp&&y.$watch("contentExp()",function(a){!a&&E.isOpen&&p()})}function r(){z=null,x&&(x.remove(),x=null),y&&(y.$destroy(),y=null)}function s(){t(),u(),v()}function t(){E.popupClass=d[k+"Class"]}function u(){var a=d[k+"Placement"];E.placement=angular.isDefined(a)?a:m.placement}function v(){var a=d[k+"PopupDelay"],b=parseInt(a,10);E.popupDelay=isNaN(b)?m.popupDelay:b}function w(){var a=d[k+"Trigger"];G(),C=n(a),C.show===C.hide?c.bind(C.show,f):(c.bind(C.show,j),c.bind(C.hide,l))}var x,y,z,A,B=angular.isDefined(m.appendToBody)?m.appendToBody:!1,C=n(void 0),D=angular.isDefined(d[k+"Enable"]),E=b.$new(!0),F=function(){if(x){var a=i.positionElements(c,x,E.placement,B);a.top+="px",a.left+="px",x.css(a)}};E.origScope=b,E.isOpen=!1,E.contentExp=function(){return b.$eval(d[e])},m.useContentExp||d.$observe(e,function(a){E.content=a,!a&&E.isOpen&&p()}),d.$observe("disabled",function(a){a&&E.isOpen&&p()}),d.$observe(k+"Title",function(a){E.title=a});var G=function(){c.unbind(C.show,j),c.unbind(C.hide,l)};w();var H=b.$eval(d[k+"Animation"]);E.animation=angular.isDefined(H)?!!H:m.animation;var I=b.$eval(d[k+"AppendToBody"]);B=angular.isDefined(I)?I:B,B&&b.$on("$locationChangeSuccess",function(){E.isOpen&&p()}),b.$on("$destroy",function(){g.cancel(z),g.cancel(A),G(),r(),E=null})}}}}}]}).directive("tooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest",function(a,b,c,d){return{link:function(e,f,g){var h,i,j,k=e.$eval(g.tooltipTemplateTranscludeScope),l=0,m=function(){i&&(i.remove(),i=null),h&&(h.$destroy(),h=null),j&&(a.leave(j).then(function(){i=null}),i=j,j=null)};e.$watch(b.parseAsResourceUrl(g.tooltipTemplateTransclude),function(b){var g=++l;b?(d(b,!0).then(function(d){if(g===l){var e=k.$new(),i=d,n=c(i)(e,function(b){m(),a.enter(b,f)});h=e,j=n,h.$emit("$includeContentLoaded",b)}},function(){g===l&&(m(),e.$emit("$includeContentError",b))}),e.$emit("$includeContentRequested",b)):m()}),e.$on("$destroy",m)}}}]).directive("tooltipClasses",function(){return{restrict:"A",link:function(a,b,c){a.placement&&b.addClass(a.placement),a.popupClass&&b.addClass(a.popupClass),a.animation()&&b.addClass(c.tooltipAnimationClass)}}}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipTemplatePopup",function(){return{restrict:"EA",replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/tooltip/tooltip-template-popup.html"}}).directive("tooltipTemplate",["$tooltip",function(a){return a("tooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("tooltipHtmlPopup",function(){return{restrict:"EA",replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-popup.html"}}).directive("tooltipHtml",["$tooltip",function(a){return a("tooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).value("tooltipHtmlUnsafeSuppressDeprecated",!1).directive("tooltipHtmlUnsafe",["$tooltip","tooltipHtmlUnsafeSuppressDeprecated","$log",function(a,b,c){return b||c.warn("tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead."),a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverTemplatePopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/popover/popover-template.html"}}).directive("popoverTemplate",["$tooltip",function(a){return a("popoverTemplate","popover","click",{useContentExp:!0})}]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(a.max)?a.max:c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,d.$formatters.push(function(a){return angular.isNumber(a)&&a<<0!==a&&(a=Math.round(a)),a}),this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length&&a.active!==!1?a.active=!0:a.active?b.select(a):a.active=!1},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse","$log",function(a,b){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(c,d,e){return function(c,d,f,g){c.$watch("active",function(a){a&&g.select(c)}),c.disabled=!1,f.disable&&c.$parent.$watch(a(f.disable),function(a){c.disabled=!!a}),f.disabled&&(b.warn('Use of "disabled" attribute has been deprecated, please use "disable"'),c.$parent.$watch(a(f.disabled),function(a){c.disabled=!!a})),c.select=function(){c.disabled||(c.active=!0)},g.addTab(c),c.$on("$destroy",function(){g.removeTab(c)}),c.$transcludeFn=e}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0,arrowkeys:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a.toString()}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),"m"!==b&&(a.minutes=i(d)),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render,o.$formatters.unshift(function(a){return a?new Date(a):null});var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g);var i=angular.isDefined(b.arrowkeys)?a.$parent.$eval(b.arrowkeys):f.arrowkeys;i&&this.setupArrowkeyEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupArrowkeyEvents=function(b,c){b.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementHours(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementHours(),a.$apply())}),c.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementMinutes(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementMinutes(),a.$apply())})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$viewValue;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.transition",[]).value("$transitionSuppressDeprecated",!1).factory("$transition",["$q","$timeout","$rootScope","$log","$transitionSuppressDeprecated",function(a,b,c,d,e){function f(a){for(var b in a)if(void 0!==h.style[b])return a[b]}e||d.warn("$transition is now deprecated. Use $animate from ngAnimate instead.");var g=function(d,e,f){f=f||{};var h=a.defer(),i=g[f.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(e)?d.addClass(e):angular.isFunction(e)?e(d):angular.isObject(e)&&d.css(e),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},h=document.createElement("trans"),i={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},j={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return g.transitionEndEventName=f(i),g.animationEndEventName=f(j),g}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=i.$eval(k.typeaheadFocusFirst)!==!1,v=b(k.ngModel).assign,w=g.parse(k.typeahead),x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y="typeahead-"+x.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":y});var z=angular.element("<div typeahead-popup></div>");z.attr({id:y,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&z.attr("template-url",k.typeaheadTemplateUrl);var A=function(){x.matches=[],x.activeIdx=-1,j.attr("aria-expanded",!1)},B=function(a){return y+"-option-"+a};x.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",B(a))});var C=function(a){var b={$viewValue:a};q(i,!0),c.when(w.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c&&c.length>0){x.activeIdx=u?0:-1,x.matches.length=0;for(var e=0;e<c.length;e++)b[w.itemName]=c[e],x.matches.push({id:B(e),label:w.viewMapper(x,b),model:c[e]});x.query=a,x.position=t?f.offset(j):f.position(j),x.position.top=x.position.top+j.prop("offsetHeight"),j.attr("aria-expanded",!0)}else A();d&&q(i,!1)},function(){A(),q(i,!1)})};A(),x.query=void 0;var D,E=function(a){D=d(function(){C(a)},o)},F=function(){D&&d.cancel(D)};l.$parsers.unshift(function(a){return m=!0,a&&a.length>=n?o>0?(F(),E(a)):C(a):(q(i,!1),F(),A()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return p||l.$setValidity("editable",!0),s?(d.$model=a,s(i,d)):(d[w.itemName]=a,b=w.viewMapper(i,d),d[w.itemName]=void 0,c=w.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,e={};e[w.itemName]=c=x.matches[a].model,b=w.modelMapper(i,e),v(i,b),l.$setValidity("editable",!0),l.$setValidity("parse",!0),r(i,{$item:c,$model:b,$label:w.viewMapper(i,e)}),A(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(-1!=x.activeIdx||13!==a.which&&9!==a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx>0?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),A(),x.$digest()))}),j.bind("blur",function(){m=!1});var G=function(a){j[0]!==a.target&&(A(),x.$digest())};e.bind("click",G),i.$on("$destroy",function(){e.unbind("click",G),t&&H.remove(),z.remove()});var H=a(z)(x);t?e.find("body").append(H):j.after(H)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$templateRequest","$compile","$parse",function(a,b,c){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(d,e,f){var g=c(f.templateUrl)(d.$parent)||"template/typeahead/typeahead-match.html";a(g).then(function(a){b(a.trim())(d,function(a){e.replaceWith(a)})})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"<strong>$&</strong>"):b}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'<div class="panel panel-default">\n <div class="panel-heading">\n <h4 class="panel-title">\n <a href="javascript:void(0)" tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" accordion-transclude="heading"><span ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n </h4>\n </div>\n <div class="panel-collapse collapse" collapse="!isOpen">\n <div class="panel-body" ng-transclude></div>\n </div>\n</div>\n')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'<div class="panel-group" ng-transclude></div>')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'<div class="alert" ng-class="[\'alert-\' + (type || \'warning\'), closeable ? \'alert-dismissable\' : null]" role="alert">\n <button ng-show="closeable" type="button" class="close" ng-click="close()">\n <span aria-hidden="true">&times;</span>\n <span class="sr-only">Close</span>\n </button>\n <div ng-transclude></div>\n</div>\n')}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel" ng-swipe-right="prev()" ng-swipe-left="next()">\n <ol class="carousel-indicators" ng-show="slides.length > 1">\n <li ng-repeat="slide in slides | orderBy:\'index\' track by $index" ng-class="{active: isActive(slide)}" ng-click="select(slide)"></li>\n </ol>\n <div class="carousel-inner" ng-transclude></div>\n <a class="left carousel-control" ng-click="prev()" ng-show="slides.length > 1"><span class="glyphicon glyphicon-chevron-left"></span></a>\n <a class="right carousel-control" ng-click="next()" ng-show="slides.length > 1"><span class="glyphicon glyphicon-chevron-right"></span></a>\n</div>\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html",'<div ng-class="{\n \'active\': active\n }" class="item text-center" ng-transclude></div>\n')}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'<div ng-switch="datepickerMode" role="application" ng-keydown="keydown($event)">\n <daypicker ng-switch-when="day" tabindex="0"></daypicker>\n <monthpicker ng-switch-when="month" tabindex="0"></monthpicker>\n <yearpicker ng-switch-when="year" tabindex="0"></yearpicker>\n</div>')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n <th colspan="{{5 + showWeeks}}"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n </tr>\n <tr>\n <th ng-show="showWeeks" class="text-center"></th>\n <th ng-repeat="label in labels track by $index" class="text-center"><small aria-label="{{label.full}}">{{label.abbr}}</small></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="row in rows track by $index">\n <td ng-show="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td>\n <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}" ng-class="dt.customClass">\n <button type="button" style="width:100%;" class="btn btn-default btn-sm" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-muted\': dt.secondary, \'text-info\': dt.current}">{{dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n <th><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="row in rows track by $index">\n <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n <button type="button" style="width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-info\': dt.current}">{{dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'<ul class="dropdown-menu" ng-style="{display: (isOpen && \'block\') || \'none\', top: position.top+\'px\', left: position.left+\'px\'}" ng-keydown="keydown($event)">\n <li ng-transclude></li>\n <li ng-if="showButtonBar" style="padding:10px 9px 2px">\n <span class="btn-group pull-left">\n <button type="button" class="btn btn-sm btn-info" ng-click="select(\'today\')">{{ getText(\'current\') }}</button>\n <button type="button" class="btn btn-sm btn-danger" ng-click="select(null)">{{ getText(\'clear\') }}</button>\n </span>\n <button type="button" class="btn btn-sm btn-success pull-right" ng-click="close()">{{ getText(\'close\') }}</button>\n </li>\n</ul>\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n <th colspan="3"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="row in rows track by $index">\n <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n <button type="button" style="width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-info\': dt.current}">{{dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')
10
+ }]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'<div class="modal-backdrop"\n modal-animation-class="fade"\n ng-class="{in: animate}"\n ng-style="{\'z-index\': 1040 + (index && 1 || 0) + index*10}"\n></div>\n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'<div modal-render="{{$isRendered}}" tabindex="-1" role="dialog" class="modal"\n modal-animation-class="fade"\n ng-class="{in: animate}" ng-style="{\'z-index\': 1050 + index*10, display: \'block\'}" ng-click="close($event)">\n <div class="modal-dialog" ng-class="size ? \'modal-\' + size : \'\'"><div class="modal-content" modal-transclude></div></div>\n</div>\n')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'<ul class="pager">\n <li ng-class="{disabled: noPrevious(), previous: align}"><a href ng-click="selectPage(page - 1, $event)">{{getText(\'previous\')}}</a></li>\n <li ng-class="{disabled: noNext(), next: align}"><a href ng-click="selectPage(page + 1, $event)">{{getText(\'next\')}}</a></li>\n</ul>')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'<ul class="pagination">\n <li ng-if="boundaryLinks" ng-class="{disabled: noPrevious()}"><a href ng-click="selectPage(1, $event)">{{getText(\'first\')}}</a></li>\n <li ng-if="directionLinks" ng-class="{disabled: noPrevious()}"><a href ng-click="selectPage(page - 1, $event)">{{getText(\'previous\')}}</a></li>\n <li ng-repeat="page in pages track by $index" ng-class="{active: page.active}"><a href ng-click="selectPage(page.number, $event)">{{page.text}}</a></li>\n <li ng-if="directionLinks" ng-class="{disabled: noNext()}"><a href ng-click="selectPage(page + 1, $event)">{{getText(\'next\')}}</a></li>\n <li ng-if="boundaryLinks" ng-class="{disabled: noNext()}"><a href ng-click="selectPage(totalPages, $event)">{{getText(\'last\')}}</a></li>\n</ul>')}]),angular.module("template/tooltip/tooltip-html-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-popup.html",'<div class="tooltip"\n tooltip-animation-class="fade"\n tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="tooltip-arrow"></div>\n <div class="tooltip-inner" ng-bind-html="contentExp()"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-unsafe-popup.html",'<div class="tooltip"\n tooltip-animation-class="fade"\n tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="tooltip-arrow"></div>\n <div class="tooltip-inner" bind-html-unsafe="content"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'<div class="tooltip"\n tooltip-animation-class="fade"\n tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="tooltip-arrow"></div>\n <div class="tooltip-inner" ng-bind="content"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-template-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-template-popup.html",'<div class="tooltip"\n tooltip-animation-class="fade"\n tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="tooltip-arrow"></div>\n <div class="tooltip-inner"\n tooltip-template-transclude="contentExp()"\n tooltip-template-transclude-scope="originScope()"></div>\n</div>\n')}]),angular.module("template/popover/popover-template.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover-template.html",'<div class="popover"\n tooltip-animation-class="fade"\n tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="arrow"></div>\n\n <div class="popover-inner">\n <h3 class="popover-title" ng-bind="title" ng-if="title"></h3>\n <div class="popover-content"\n tooltip-template-transclude="contentExp()"\n tooltip-template-transclude-scope="originScope()"></div>\n </div>\n</div>\n')}]),angular.module("template/popover/popover-window.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover-window.html",'<div class="popover {{placement}}" ng-class="{ in: isOpen, fade: animation }">\n <div class="arrow"></div>\n\n <div class="popover-inner">\n <h3 class="popover-title" ng-bind="title" ng-show="title"></h3>\n <div class="popover-content" tooltip-template-transclude></div>\n </div>\n</div>\n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'<div class="popover"\n tooltip-animation-class="fade"\n tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="arrow"></div>\n\n <div class="popover-inner">\n <h3 class="popover-title" ng-bind="title" ng-if="title"></h3>\n <div class="popover-content" ng-bind="content"></div>\n </div>\n</div>\n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'<div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + \'%\'}" aria-valuetext="{{percent | number:0}}%" ng-transclude></div>\n')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'<div class="progress" ng-transclude></div>')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'<div class="progress">\n <div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + \'%\'}" aria-valuetext="{{percent | number:0}}%" ng-transclude></div>\n</div>\n')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'<span ng-mouseleave="reset()" ng-keydown="onKeydown($event)" tabindex="0" role="slider" aria-valuemin="0" aria-valuemax="{{range.length}}" aria-valuenow="{{value}}">\n <i ng-repeat="r in range track by $index" ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || \'glyphicon-star\') || (r.stateOff || \'glyphicon-star-empty\')">\n <span class="sr-only">({{ $index < value ? \'*\' : \' \' }})</span>\n </i>\n</span>')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'<li ng-class="{active: active, disabled: disabled}">\n <a href ng-click="select()" tab-heading-transclude>{{heading}}</a>\n</li>\n')}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'<div>\n <ul class="nav nav-{{type || \'tabs\'}}" ng-class="{\'nav-stacked\': vertical, \'nav-justified\': justified}" ng-transclude></ul>\n <div class="tab-content">\n <div class="tab-pane" \n ng-repeat="tab in tabs" \n ng-class="{active: tab.active}"\n tab-content-transclude="tab">\n </div>\n </div>\n</div>\n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'<table>\n <tbody>\n <tr class="text-center">\n <td><a ng-click="incrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n <td>&nbsp;</td>\n <td><a ng-click="incrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n <td ng-show="showMeridian"></td>\n </tr>\n <tr>\n <td class="form-group" ng-class="{\'has-error\': invalidHours}">\n <input style="width:50px;" type="text" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2">\n </td>\n <td>:</td>\n <td class="form-group" ng-class="{\'has-error\': invalidMinutes}">\n <input style="width:50px;" type="text" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2">\n </td>\n <td ng-show="showMeridian"><button type="button" class="btn btn-default text-center" ng-click="toggleMeridian()">{{meridian}}</button></td>\n </tr>\n <tr class="text-center">\n <td><a ng-click="decrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n <td>&nbsp;</td>\n <td><a ng-click="decrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n <td ng-show="showMeridian"></td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'<a tabindex="-1" bind-html-unsafe="match.label | typeaheadHighlight:query"></a>')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'<ul class="dropdown-menu" ng-show="isOpen()" ng-style="{top: position.top+\'px\', left: position.left+\'px\'}" style="display: block;" role="listbox" aria-hidden="{{!isOpen()}}">\n <li ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)" role="option" id="{{match.id}}">\n <div typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>\n </li>\n</ul>\n')}]),!angular.$$csp()&&angular.element(document).find("head").prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>');
@@ -2,154 +2,46 @@
2
2
  * angular-ui-bootstrap
3
3
  * http://angular-ui.github.io/bootstrap/
4
4
 
5
- * Version: 0.11.0 - 2014-05-01
5
+ * Version: 0.13.0 - 2015-05-02
6
6
  * License: MIT
7
7
  */
8
- angular.module("ui.bootstrap", ["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]);
9
- angular.module('ui.bootstrap.transition', [])
10
-
11
- /**
12
- * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.
13
- * @param {DOMElement} element The DOMElement that will be animated.
14
- * @param {string|object|function} trigger The thing that will cause the transition to start:
15
- * - As a string, it represents the css class to be added to the element.
16
- * - As an object, it represents a hash of style attributes to be applied to the element.
17
- * - As a function, it represents a function to be called that will cause the transition to occur.
18
- * @return {Promise} A promise that is resolved when the transition finishes.
19
- */
20
- .factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {
21
-
22
- var $transition = function(element, trigger, options) {
23
- options = options || {};
24
- var deferred = $q.defer();
25
- var endEventName = $transition[options.animation ? 'animationEndEventName' : 'transitionEndEventName'];
26
-
27
- var transitionEndHandler = function(event) {
28
- $rootScope.$apply(function() {
29
- element.unbind(endEventName, transitionEndHandler);
30
- deferred.resolve(element);
31
- });
32
- };
8
+ angular.module("ui.bootstrap", ["ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.transition","ui.bootstrap.typeahead"]);
9
+ angular.module('ui.bootstrap.collapse', [])
33
10
 
34
- if (endEventName) {
35
- element.bind(endEventName, transitionEndHandler);
36
- }
37
-
38
- // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
39
- $timeout(function() {
40
- if ( angular.isString(trigger) ) {
41
- element.addClass(trigger);
42
- } else if ( angular.isFunction(trigger) ) {
43
- trigger(element);
44
- } else if ( angular.isObject(trigger) ) {
45
- element.css(trigger);
46
- }
47
- //If browser does not support transitions, instantly resolve
48
- if ( !endEventName ) {
49
- deferred.resolve(element);
50
- }
51
- });
52
-
53
- // Add our custom cancel function to the promise that is returned
54
- // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
55
- // i.e. it will therefore never raise a transitionEnd event for that transition
56
- deferred.promise.cancel = function() {
57
- if ( endEventName ) {
58
- element.unbind(endEventName, transitionEndHandler);
59
- }
60
- deferred.reject('Transition cancelled');
61
- };
62
-
63
- return deferred.promise;
64
- };
65
-
66
- // Work out the name of the transitionEnd event
67
- var transElement = document.createElement('trans');
68
- var transitionEndEventNames = {
69
- 'WebkitTransition': 'webkitTransitionEnd',
70
- 'MozTransition': 'transitionend',
71
- 'OTransition': 'oTransitionEnd',
72
- 'transition': 'transitionend'
73
- };
74
- var animationEndEventNames = {
75
- 'WebkitTransition': 'webkitAnimationEnd',
76
- 'MozTransition': 'animationend',
77
- 'OTransition': 'oAnimationEnd',
78
- 'transition': 'animationend'
79
- };
80
- function findEndEventName(endEventNames) {
81
- for (var name in endEventNames){
82
- if (transElement.style[name] !== undefined) {
83
- return endEventNames[name];
84
- }
85
- }
86
- }
87
- $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
88
- $transition.animationEndEventName = findEndEventName(animationEndEventNames);
89
- return $transition;
90
- }]);
91
-
92
- angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition'])
93
-
94
- .directive('collapse', ['$transition', function ($transition) {
11
+ .directive('collapse', ['$animate', function ($animate) {
95
12
 
96
13
  return {
97
14
  link: function (scope, element, attrs) {
98
-
99
- var initialAnimSkip = true;
100
- var currentTransition;
101
-
102
- function doTransition(change) {
103
- var newTransition = $transition(element, change);
104
- if (currentTransition) {
105
- currentTransition.cancel();
106
- }
107
- currentTransition = newTransition;
108
- newTransition.then(newTransitionDone, newTransitionDone);
109
- return newTransition;
110
-
111
- function newTransitionDone() {
112
- // Make sure it's this transition, otherwise, leave it alone.
113
- if (currentTransition === newTransition) {
114
- currentTransition = undefined;
115
- }
116
- }
117
- }
118
-
119
15
  function expand() {
120
- if (initialAnimSkip) {
121
- initialAnimSkip = false;
122
- expandDone();
123
- } else {
124
- element.removeClass('collapse').addClass('collapsing');
125
- doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone);
126
- }
16
+ element.removeClass('collapse').addClass('collapsing');
17
+ $animate.addClass(element, 'in', {
18
+ to: { height: element[0].scrollHeight + 'px' }
19
+ }).then(expandDone);
127
20
  }
128
21
 
129
22
  function expandDone() {
130
23
  element.removeClass('collapsing');
131
- element.addClass('collapse in');
132
24
  element.css({height: 'auto'});
133
25
  }
134
26
 
135
27
  function collapse() {
136
- if (initialAnimSkip) {
137
- initialAnimSkip = false;
138
- collapseDone();
139
- element.css({height: 0});
140
- } else {
141
- // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value
142
- element.css({ height: element[0].scrollHeight + 'px' });
143
- //trigger reflow so a browser realizes that height was updated from auto to a specific value
144
- var x = element[0].offsetWidth;
145
-
146
- element.removeClass('collapse in').addClass('collapsing');
147
-
148
- doTransition({ height: 0 }).then(collapseDone);
149
- }
28
+ element
29
+ // IMPORTANT: The height must be set before adding "collapsing" class.
30
+ // Otherwise, the browser attempts to animate from height 0 (in
31
+ // collapsing class) to the given height here.
32
+ .css({height: element[0].scrollHeight + 'px'})
33
+ // initially all panel collapse have the collapse class, this removal
34
+ // prevents the animation from jumping to collapsed state
35
+ .removeClass('collapse')
36
+ .addClass('collapsing');
37
+
38
+ $animate.removeClass(element, 'in', {
39
+ to: {height: '0'}
40
+ }).then(collapseDone);
150
41
  }
151
42
 
152
43
  function collapseDone() {
44
+ element.css({height: '0'}); // Required so that collapse works when animation is disabled
153
45
  element.removeClass('collapsing');
154
46
  element.addClass('collapse');
155
47
  }
@@ -271,7 +163,7 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
271
163
  // Pass the heading to the accordion-group controller
272
164
  // so that it can be transcluded into the right place in the template
273
165
  // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
274
- accordionGroupCtrl.setHeading(transclude(scope, function() {}));
166
+ accordionGroupCtrl.setHeading(transclude(scope, angular.noop));
275
167
  }
276
168
  };
277
169
  })
@@ -294,12 +186,15 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
294
186
  });
295
187
  }
296
188
  };
297
- });
189
+ })
190
+
191
+ ;
298
192
 
299
193
  angular.module('ui.bootstrap.alert', [])
300
194
 
301
195
  .controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) {
302
196
  $scope.closeable = 'close' in $attrs;
197
+ this.close = $scope.close;
303
198
  }])
304
199
 
305
200
  .directive('alert', function () {
@@ -314,7 +209,18 @@ angular.module('ui.bootstrap.alert', [])
314
209
  close: '&'
315
210
  }
316
211
  };
317
- });
212
+ })
213
+
214
+ .directive('dismissOnTimeout', ['$timeout', function($timeout) {
215
+ return {
216
+ require: 'alert',
217
+ link: function(scope, element, attrs, alertCtrl) {
218
+ $timeout(function(){
219
+ alertCtrl.close();
220
+ }, parseInt(attrs.dismissOnTimeout, 10));
221
+ }
222
+ };
223
+ }]);
318
224
 
319
225
  angular.module('ui.bootstrap.bindHtml', [])
320
226
 
@@ -409,93 +315,87 @@ angular.module('ui.bootstrap.buttons', [])
409
315
  * AngularJS version of an image carousel.
410
316
  *
411
317
  */
412
- angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
413
- .controller('CarouselController', ['$scope', '$timeout', '$transition', function ($scope, $timeout, $transition) {
318
+ angular.module('ui.bootstrap.carousel', [])
319
+ .controller('CarouselController', ['$scope', '$interval', '$animate', function ($scope, $interval, $animate) {
414
320
  var self = this,
415
321
  slides = self.slides = $scope.slides = [],
416
322
  currentIndex = -1,
417
- currentTimeout, isPlaying;
323
+ currentInterval, isPlaying;
418
324
  self.currentSlide = null;
419
325
 
420
326
  var destroyed = false;
421
327
  /* direction: "prev" or "next" */
422
328
  self.select = $scope.select = function(nextSlide, direction) {
423
- var nextIndex = slides.indexOf(nextSlide);
329
+ var nextIndex = self.indexOfSlide(nextSlide);
424
330
  //Decide direction if it's not given
425
331
  if (direction === undefined) {
426
- direction = nextIndex > currentIndex ? 'next' : 'prev';
332
+ direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
427
333
  }
428
334
  if (nextSlide && nextSlide !== self.currentSlide) {
429
- if ($scope.$currentTransition) {
430
- $scope.$currentTransition.cancel();
431
- //Timeout so ng-class in template has time to fix classes for finished slide
432
- $timeout(goNext);
433
- } else {
434
- goNext();
435
- }
335
+ goNext();
436
336
  }
437
337
  function goNext() {
438
338
  // Scope has been destroyed, stop here.
439
339
  if (destroyed) { return; }
440
- //If we have a slide to transition from and we have a transition type and we're allowed, go
441
- if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) {
442
- //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime
443
- nextSlide.$element.addClass(direction);
444
- var reflow = nextSlide.$element[0].offsetWidth; //force reflow
445
-
446
- //Set all other slides to stop doing their stuff for the new transition
447
- angular.forEach(slides, function(slide) {
448
- angular.extend(slide, {direction: '', entering: false, leaving: false, active: false});
340
+
341
+ angular.extend(nextSlide, {direction: direction, active: true});
342
+ angular.extend(self.currentSlide || {}, {direction: direction, active: false});
343
+ if ($animate.enabled() && !$scope.noTransition && nextSlide.$element) {
344
+ $scope.$currentTransition = true;
345
+ nextSlide.$element.one('$animate:close', function closeFn() {
346
+ $scope.$currentTransition = null;
449
347
  });
450
- angular.extend(nextSlide, {direction: direction, active: true, entering: true});
451
- angular.extend(self.currentSlide||{}, {direction: direction, leaving: true});
452
-
453
- $scope.$currentTransition = $transition(nextSlide.$element, {});
454
- //We have to create new pointers inside a closure since next & current will change
455
- (function(next,current) {
456
- $scope.$currentTransition.then(
457
- function(){ transitionDone(next, current); },
458
- function(){ transitionDone(next, current); }
459
- );
460
- }(nextSlide, self.currentSlide));
461
- } else {
462
- transitionDone(nextSlide, self.currentSlide);
463
348
  }
349
+
464
350
  self.currentSlide = nextSlide;
465
351
  currentIndex = nextIndex;
466
352
  //every time you change slides, reset the timer
467
353
  restartTimer();
468
354
  }
469
- function transitionDone(next, current) {
470
- angular.extend(next, {direction: '', active: true, leaving: false, entering: false});
471
- angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false});
472
- $scope.$currentTransition = null;
473
- }
474
355
  };
475
356
  $scope.$on('$destroy', function () {
476
357
  destroyed = true;
477
358
  });
478
359
 
360
+ function getSlideByIndex(index) {
361
+ if (angular.isUndefined(slides[index].index)) {
362
+ return slides[index];
363
+ }
364
+ var i, len = slides.length;
365
+ for (i = 0; i < slides.length; ++i) {
366
+ if (slides[i].index == index) {
367
+ return slides[i];
368
+ }
369
+ }
370
+ }
371
+
372
+ self.getCurrentIndex = function() {
373
+ if (self.currentSlide && angular.isDefined(self.currentSlide.index)) {
374
+ return +self.currentSlide.index;
375
+ }
376
+ return currentIndex;
377
+ };
378
+
479
379
  /* Allow outside people to call indexOf on slides array */
480
380
  self.indexOfSlide = function(slide) {
481
- return slides.indexOf(slide);
381
+ return angular.isDefined(slide.index) ? +slide.index : slides.indexOf(slide);
482
382
  };
483
383
 
484
384
  $scope.next = function() {
485
- var newIndex = (currentIndex + 1) % slides.length;
385
+ var newIndex = (self.getCurrentIndex() + 1) % slides.length;
486
386
 
487
387
  //Prevent this user-triggered transition from occurring if there is already one in progress
488
388
  if (!$scope.$currentTransition) {
489
- return self.select(slides[newIndex], 'next');
389
+ return self.select(getSlideByIndex(newIndex), 'next');
490
390
  }
491
391
  };
492
392
 
493
393
  $scope.prev = function() {
494
- var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1;
394
+ var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1;
495
395
 
496
396
  //Prevent this user-triggered transition from occurring if there is already one in progress
497
397
  if (!$scope.$currentTransition) {
498
- return self.select(slides[newIndex], 'prev');
398
+ return self.select(getSlideByIndex(newIndex), 'prev');
499
399
  }
500
400
  };
501
401
 
@@ -509,22 +409,22 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
509
409
  function restartTimer() {
510
410
  resetTimer();
511
411
  var interval = +$scope.interval;
512
- if (!isNaN(interval) && interval>=0) {
513
- currentTimeout = $timeout(timerFn, interval);
412
+ if (!isNaN(interval) && interval > 0) {
413
+ currentInterval = $interval(timerFn, interval);
514
414
  }
515
415
  }
516
416
 
517
417
  function resetTimer() {
518
- if (currentTimeout) {
519
- $timeout.cancel(currentTimeout);
520
- currentTimeout = null;
418
+ if (currentInterval) {
419
+ $interval.cancel(currentInterval);
420
+ currentInterval = null;
521
421
  }
522
422
  }
523
423
 
524
424
  function timerFn() {
525
- if (isPlaying) {
425
+ var interval = +$scope.interval;
426
+ if (isPlaying && !isNaN(interval) && interval > 0) {
526
427
  $scope.next();
527
- restartTimer();
528
428
  } else {
529
429
  $scope.pause();
530
430
  }
@@ -558,6 +458,11 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
558
458
  };
559
459
 
560
460
  self.removeSlide = function(slide) {
461
+ if (angular.isDefined(slide.index)) {
462
+ slides.sort(function(a, b) {
463
+ return +a.index > +b.index;
464
+ });
465
+ }
561
466
  //get the index of the slide inside the carousel
562
467
  var index = slides.indexOf(slide);
563
468
  slides.splice(index, 1);
@@ -637,13 +542,14 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
637
542
  * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}. Must be placed as a child of a carousel element.
638
543
  *
639
544
  * @param {boolean=} active Model binding, whether or not this slide is currently active.
545
+ * @param {number=} index The index of the slide. The slides will be sorted by this parameter.
640
546
  *
641
547
  * @example
642
548
  <example module="ui.bootstrap">
643
549
  <file name="index.html">
644
550
  <div ng-controller="CarouselDemoCtrl">
645
551
  <carousel>
646
- <slide ng-repeat="slide in slides" active="slide.active">
552
+ <slide ng-repeat="slide in slides" active="slide.active" index="$index">
647
553
  <img ng-src="{{slide.image}}" style="margin:auto;">
648
554
  <div class="carousel-caption">
649
555
  <h4>Slide {{$index}}</h4>
@@ -677,7 +583,8 @@ function CarouselDemoCtrl($scope) {
677
583
  replace: true,
678
584
  templateUrl: 'template/carousel/slide.html',
679
585
  scope: {
680
- active: '=?'
586
+ active: '=?',
587
+ index: '=?'
681
588
  },
682
589
  link: function (scope, element, attrs, carouselCtrl) {
683
590
  carouselCtrl.addSlide(scope, element);
@@ -693,11 +600,64 @@ function CarouselDemoCtrl($scope) {
693
600
  });
694
601
  }
695
602
  };
696
- });
603
+ })
604
+
605
+ .animation('.item', [
606
+ '$animate',
607
+ function ($animate) {
608
+ return {
609
+ beforeAddClass: function (element, className, done) {
610
+ // Due to transclusion, noTransition property is on parent's scope
611
+ if (className == 'active' && element.parent() &&
612
+ !element.parent().scope().noTransition) {
613
+ var stopped = false;
614
+ var direction = element.isolateScope().direction;
615
+ var directionClass = direction == 'next' ? 'left' : 'right';
616
+ element.addClass(direction);
617
+ $animate.addClass(element, directionClass).then(function () {
618
+ if (!stopped) {
619
+ element.removeClass(directionClass + ' ' + direction);
620
+ }
621
+ done();
622
+ });
623
+
624
+ return function () {
625
+ stopped = true;
626
+ };
627
+ }
628
+ done();
629
+ },
630
+ beforeRemoveClass: function (element, className, done) {
631
+ // Due to transclusion, noTransition property is on parent's scope
632
+ if (className == 'active' && element.parent() &&
633
+ !element.parent().scope().noTransition) {
634
+ var stopped = false;
635
+ var direction = element.isolateScope().direction;
636
+ var directionClass = direction == 'next' ? 'left' : 'right';
637
+ $animate.addClass(element, directionClass).then(function () {
638
+ if (!stopped) {
639
+ element.removeClass(directionClass);
640
+ }
641
+ done();
642
+ });
643
+ return function () {
644
+ stopped = true;
645
+ };
646
+ }
647
+ done();
648
+ }
649
+ };
650
+
651
+ }])
652
+
653
+
654
+ ;
697
655
 
698
656
  angular.module('ui.bootstrap.dateparser', [])
699
657
 
700
658
  .service('dateParser', ['$locale', 'orderByFilter', function($locale, orderByFilter) {
659
+ // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js
660
+ var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
701
661
 
702
662
  this.parsers = {};
703
663
 
@@ -743,10 +703,38 @@ angular.module('ui.bootstrap.dateparser', [])
743
703
  },
744
704
  'EEE': {
745
705
  regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|')
706
+ },
707
+ 'HH': {
708
+ regex: '(?:0|1)[0-9]|2[0-3]',
709
+ apply: function(value) { this.hours = +value; }
710
+ },
711
+ 'H': {
712
+ regex: '1?[0-9]|2[0-3]',
713
+ apply: function(value) { this.hours = +value; }
714
+ },
715
+ 'mm': {
716
+ regex: '[0-5][0-9]',
717
+ apply: function(value) { this.minutes = +value; }
718
+ },
719
+ 'm': {
720
+ regex: '[0-9]|[1-5][0-9]',
721
+ apply: function(value) { this.minutes = +value; }
722
+ },
723
+ 'sss': {
724
+ regex: '[0-9][0-9][0-9]',
725
+ apply: function(value) { this.milliseconds = +value; }
726
+ },
727
+ 'ss': {
728
+ regex: '[0-5][0-9]',
729
+ apply: function(value) { this.seconds = +value; }
730
+ },
731
+ 's': {
732
+ regex: '[0-9]|[1-5][0-9]',
733
+ apply: function(value) { this.seconds = +value; }
746
734
  }
747
735
  };
748
736
 
749
- this.createParser = function(format) {
737
+ function createParser(format) {
750
738
  var map = [], regex = format.split('');
751
739
 
752
740
  angular.forEach(formatCodeToRegex, function(data, code) {
@@ -771,17 +759,18 @@ angular.module('ui.bootstrap.dateparser', [])
771
759
  regex: new RegExp('^' + regex.join('') + '$'),
772
760
  map: orderByFilter(map, 'index')
773
761
  };
774
- };
762
+ }
775
763
 
776
- this.parse = function(input, format) {
777
- if ( !angular.isString(input) ) {
764
+ this.parse = function(input, format, baseDate) {
765
+ if ( !angular.isString(input) || !format ) {
778
766
  return input;
779
767
  }
780
768
 
781
769
  format = $locale.DATETIME_FORMATS[format] || format;
770
+ format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\$&');
782
771
 
783
772
  if ( !this.parsers[format] ) {
784
- this.parsers[format] = this.createParser(format);
773
+ this.parsers[format] = createParser(format);
785
774
  }
786
775
 
787
776
  var parser = this.parsers[format],
@@ -790,7 +779,20 @@ angular.module('ui.bootstrap.dateparser', [])
790
779
  results = input.match(regex);
791
780
 
792
781
  if ( results && results.length ) {
793
- var fields = { year: 1900, month: 0, date: 1, hours: 0 }, dt;
782
+ var fields, dt;
783
+ if (baseDate) {
784
+ fields = {
785
+ year: baseDate.getFullYear(),
786
+ month: baseDate.getMonth(),
787
+ date: baseDate.getDate(),
788
+ hours: baseDate.getHours(),
789
+ minutes: baseDate.getMinutes(),
790
+ seconds: baseDate.getSeconds(),
791
+ milliseconds: baseDate.getMilliseconds()
792
+ };
793
+ } else {
794
+ fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };
795
+ }
794
796
 
795
797
  for( var i = 1, n = results.length; i < n; i++ ) {
796
798
  var mapper = map[i-1];
@@ -800,7 +802,8 @@ angular.module('ui.bootstrap.dateparser', [])
800
802
  }
801
803
 
802
804
  if ( isValid(fields.year, fields.month, fields.date) ) {
803
- dt = new Date( fields.year, fields.month, fields.date, fields.hours);
805
+ dt = new Date(fields.year, fields.month, fields.date, fields.hours, fields.minutes, fields.seconds,
806
+ fields.milliseconds || 0);
804
807
  }
805
808
 
806
809
  return dt;
@@ -810,6 +813,10 @@ angular.module('ui.bootstrap.dateparser', [])
810
813
  // Check if date is valid for specific month (and year for February).
811
814
  // Month: 0 = Jan, 1 = Feb, etc
812
815
  function isValid(year, month, date) {
816
+ if (date < 1) {
817
+ return false;
818
+ }
819
+
813
820
  if ( month === 1 && date > 28) {
814
821
  return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);
815
822
  }
@@ -991,7 +998,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
991
998
  startingDay: 0,
992
999
  yearRange: 20,
993
1000
  minDate: null,
994
- maxDate: null
1001
+ maxDate: null,
1002
+ shortcutPropagation: false
995
1003
  })
996
1004
 
997
1005
  .controller('DatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$timeout', '$log', 'dateFilter', 'datepickerConfig', function($scope, $attrs, $parse, $interpolate, $timeout, $log, dateFilter, datepickerConfig) {
@@ -1003,11 +1011,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1003
1011
 
1004
1012
  // Configuration attributes
1005
1013
  angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle',
1006
- 'minMode', 'maxMode', 'showWeeks', 'startingDay', 'yearRange'], function( key, index ) {
1014
+ 'minMode', 'maxMode', 'showWeeks', 'startingDay', 'yearRange', 'shortcutPropagation'], function( key, index ) {
1007
1015
  self[key] = angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key];
1008
1016
  });
1009
1017
 
1010
- // Watchable attributes
1018
+ // Watchable date attributes
1011
1019
  angular.forEach(['minDate', 'maxDate'], function( key ) {
1012
1020
  if ( $attrs[key] ) {
1013
1021
  $scope.$parent.$watch($parse($attrs[key]), function(value) {
@@ -1020,8 +1028,20 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1020
1028
  });
1021
1029
 
1022
1030
  $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode;
1031
+ $scope.maxMode = self.maxMode;
1023
1032
  $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);
1024
- this.activeDate = angular.isDefined($attrs.initDate) ? $scope.$parent.$eval($attrs.initDate) : new Date();
1033
+
1034
+ if(angular.isDefined($attrs.initDate)) {
1035
+ this.activeDate = $scope.$parent.$eval($attrs.initDate) || new Date();
1036
+ $scope.$parent.$watch($attrs.initDate, function(initDate){
1037
+ if(initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)){
1038
+ self.activeDate = initDate;
1039
+ self.refreshView();
1040
+ }
1041
+ });
1042
+ } else {
1043
+ this.activeDate = new Date();
1044
+ }
1025
1045
 
1026
1046
  $scope.isActive = function(dateObject) {
1027
1047
  if (self.compare(dateObject.date, self.activeDate) === 0) {
@@ -1040,8 +1060,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1040
1060
  };
1041
1061
 
1042
1062
  this.render = function() {
1043
- if ( ngModelCtrl.$modelValue ) {
1044
- var date = new Date( ngModelCtrl.$modelValue ),
1063
+ if ( ngModelCtrl.$viewValue ) {
1064
+ var date = new Date( ngModelCtrl.$viewValue ),
1045
1065
  isValid = !isNaN(date);
1046
1066
 
1047
1067
  if ( isValid ) {
@@ -1058,19 +1078,20 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1058
1078
  if ( this.element ) {
1059
1079
  this._refreshView();
1060
1080
 
1061
- var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null;
1081
+ var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
1062
1082
  ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date)));
1063
1083
  }
1064
1084
  };
1065
1085
 
1066
1086
  this.createDateObject = function(date, format) {
1067
- var model = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null;
1087
+ var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
1068
1088
  return {
1069
1089
  date: date,
1070
1090
  label: dateFilter(date, format),
1071
1091
  selected: model && this.compare(date, model) === 0,
1072
1092
  disabled: this.isDisabled(date),
1073
- current: this.compare(date, new Date()) === 0
1093
+ current: this.compare(date, new Date()) === 0,
1094
+ customClass: this.customClass(date)
1074
1095
  };
1075
1096
  };
1076
1097
 
@@ -1078,6 +1099,10 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1078
1099
  return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode})));
1079
1100
  };
1080
1101
 
1102
+ this.customClass = function( date ) {
1103
+ return $scope.customClass({date: date, mode: $scope.datepickerMode});
1104
+ };
1105
+
1081
1106
  // Split array into smaller arrays
1082
1107
  this.split = function(arr, size) {
1083
1108
  var arrays = [];
@@ -1089,7 +1114,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1089
1114
 
1090
1115
  $scope.select = function( date ) {
1091
1116
  if ( $scope.datepickerMode === self.minMode ) {
1092
- var dt = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0);
1117
+ var dt = ngModelCtrl.$viewValue ? new Date( ngModelCtrl.$viewValue ) : new Date(0, 0, 0, 0, 0, 0, 0);
1093
1118
  dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() );
1094
1119
  ngModelCtrl.$setViewValue( dt );
1095
1120
  ngModelCtrl.$render();
@@ -1136,7 +1161,9 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1136
1161
  }
1137
1162
 
1138
1163
  evt.preventDefault();
1139
- evt.stopPropagation();
1164
+ if(!self.shortcutPropagation){
1165
+ evt.stopPropagation();
1166
+ }
1140
1167
 
1141
1168
  if (key === 'enter' || key === 'space') {
1142
1169
  if ( self.isDisabled(self.activeDate)) {
@@ -1161,7 +1188,9 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1161
1188
  templateUrl: 'template/datepicker/datepicker.html',
1162
1189
  scope: {
1163
1190
  datepickerMode: '=?',
1164
- dateDisabled: '&'
1191
+ dateDisabled: '&',
1192
+ customClass: '&',
1193
+ shortcutPropagation: '&?'
1165
1194
  },
1166
1195
  require: ['datepicker', '?^ngModel'],
1167
1196
  controller: 'DatepickerController',
@@ -1236,9 +1265,12 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1236
1265
 
1237
1266
  if ( scope.showWeeks ) {
1238
1267
  scope.weekNumbers = [];
1239
- var weekNumber = getISO8601WeekNumber( scope.rows[0][0].date ),
1268
+ var thursdayIndex = (4 + 7 - ctrl.startingDay) % 7,
1240
1269
  numWeeks = scope.rows.length;
1241
- while( scope.weekNumbers.push(weekNumber++) < numWeeks ) {}
1270
+ for (var curWeek = 0; curWeek < numWeeks; curWeek++) {
1271
+ scope.weekNumbers.push(
1272
+ getISO8601WeekNumber( scope.rows[curWeek][thursdayIndex].date ));
1273
+ }
1242
1274
  }
1243
1275
  };
1244
1276
 
@@ -1399,6 +1431,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
1399
1431
 
1400
1432
  .constant('datepickerPopupConfig', {
1401
1433
  datepickerPopup: 'yyyy-MM-dd',
1434
+ html5Types: {
1435
+ date: 'yyyy-MM-dd',
1436
+ 'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',
1437
+ 'month': 'yyyy-MM'
1438
+ },
1402
1439
  currentText: 'Today',
1403
1440
  clearText: 'Clear',
1404
1441
  closeText: 'Done',
@@ -1417,7 +1454,8 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1417
1454
  currentText: '@',
1418
1455
  clearText: '@',
1419
1456
  closeText: '@',
1420
- dateDisabled: '&'
1457
+ dateDisabled: '&',
1458
+ customClass: '&'
1421
1459
  },
1422
1460
  link: function(scope, element, attrs, ngModel) {
1423
1461
  var dateFormat,
@@ -1430,10 +1468,34 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1430
1468
  return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
1431
1469
  };
1432
1470
 
1433
- attrs.$observe('datepickerPopup', function(value) {
1434
- dateFormat = value || datepickerPopupConfig.datepickerPopup;
1435
- ngModel.$render();
1436
- });
1471
+ var isHtml5DateInput = false;
1472
+ if (datepickerPopupConfig.html5Types[attrs.type]) {
1473
+ dateFormat = datepickerPopupConfig.html5Types[attrs.type];
1474
+ isHtml5DateInput = true;
1475
+ } else {
1476
+ dateFormat = attrs.datepickerPopup || datepickerPopupConfig.datepickerPopup;
1477
+ attrs.$observe('datepickerPopup', function(value, oldValue) {
1478
+ var newDateFormat = value || datepickerPopupConfig.datepickerPopup;
1479
+ // Invalidate the $modelValue to ensure that formatters re-run
1480
+ // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764
1481
+ if (newDateFormat !== dateFormat) {
1482
+ dateFormat = newDateFormat;
1483
+ ngModel.$modelValue = null;
1484
+
1485
+ if (!dateFormat) {
1486
+ throw new Error('datepickerPopup must have a date format specified.');
1487
+ }
1488
+ }
1489
+ });
1490
+ }
1491
+
1492
+ if (!dateFormat) {
1493
+ throw new Error('datepickerPopup must have a date format specified.');
1494
+ }
1495
+
1496
+ if (isHtml5DateInput && attrs.datepickerPopup) {
1497
+ throw new Error('HTML5 date input types do not support custom formats.');
1498
+ }
1437
1499
 
1438
1500
  // popup element used to display calendar
1439
1501
  var popupEl = angular.element('<div datepicker-popup-wrap><div datepicker></div></div>');
@@ -1448,54 +1510,121 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1448
1510
 
1449
1511
  // datepicker element
1450
1512
  var datepickerEl = angular.element(popupEl.children()[0]);
1513
+ if (isHtml5DateInput) {
1514
+ if (attrs.type == 'month') {
1515
+ datepickerEl.attr('datepicker-mode', '"month"');
1516
+ datepickerEl.attr('min-mode', 'month');
1517
+ }
1518
+ }
1519
+
1451
1520
  if ( attrs.datepickerOptions ) {
1452
- angular.forEach(scope.$parent.$eval(attrs.datepickerOptions), function( value, option ) {
1521
+ var options = scope.$parent.$eval(attrs.datepickerOptions);
1522
+ if(options.initDate) {
1523
+ scope.initDate = options.initDate;
1524
+ datepickerEl.attr( 'init-date', 'initDate' );
1525
+ delete options.initDate;
1526
+ }
1527
+ angular.forEach(options, function( value, option ) {
1453
1528
  datepickerEl.attr( cameltoDash(option), value );
1454
1529
  });
1455
1530
  }
1456
1531
 
1457
- angular.forEach(['minDate', 'maxDate'], function( key ) {
1532
+ scope.watchData = {};
1533
+ angular.forEach(['minDate', 'maxDate', 'datepickerMode', 'initDate', 'shortcutPropagation'], function( key ) {
1458
1534
  if ( attrs[key] ) {
1459
- scope.$parent.$watch($parse(attrs[key]), function(value){
1460
- scope[key] = value;
1535
+ var getAttribute = $parse(attrs[key]);
1536
+ scope.$parent.$watch(getAttribute, function(value){
1537
+ scope.watchData[key] = value;
1461
1538
  });
1462
- datepickerEl.attr(cameltoDash(key), key);
1539
+ datepickerEl.attr(cameltoDash(key), 'watchData.' + key);
1540
+
1541
+ // Propagate changes from datepicker to outside
1542
+ if ( key === 'datepickerMode' ) {
1543
+ var setAttribute = getAttribute.assign;
1544
+ scope.$watch('watchData.' + key, function(value, oldvalue) {
1545
+ if ( value !== oldvalue ) {
1546
+ setAttribute(scope.$parent, value);
1547
+ }
1548
+ });
1549
+ }
1463
1550
  }
1464
1551
  });
1465
1552
  if (attrs.dateDisabled) {
1466
1553
  datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })');
1467
1554
  }
1468
1555
 
1556
+ if (attrs.showWeeks) {
1557
+ datepickerEl.attr('show-weeks', attrs.showWeeks);
1558
+ }
1559
+
1560
+ if (attrs.customClass){
1561
+ datepickerEl.attr('custom-class', 'customClass({ date: date, mode: mode })');
1562
+ }
1563
+
1469
1564
  function parseDate(viewValue) {
1565
+ if (angular.isNumber(viewValue)) {
1566
+ // presumably timestamp to date object
1567
+ viewValue = new Date(viewValue);
1568
+ }
1569
+
1470
1570
  if (!viewValue) {
1471
- ngModel.$setValidity('date', true);
1472
1571
  return null;
1473
1572
  } else if (angular.isDate(viewValue) && !isNaN(viewValue)) {
1474
- ngModel.$setValidity('date', true);
1475
1573
  return viewValue;
1476
1574
  } else if (angular.isString(viewValue)) {
1477
- var date = dateParser.parse(viewValue, dateFormat) || new Date(viewValue);
1575
+ var date = dateParser.parse(viewValue, dateFormat, scope.date) || new Date(viewValue);
1478
1576
  if (isNaN(date)) {
1479
- ngModel.$setValidity('date', false);
1480
1577
  return undefined;
1481
1578
  } else {
1482
- ngModel.$setValidity('date', true);
1483
1579
  return date;
1484
1580
  }
1485
1581
  } else {
1486
- ngModel.$setValidity('date', false);
1487
1582
  return undefined;
1488
1583
  }
1489
1584
  }
1490
- ngModel.$parsers.unshift(parseDate);
1585
+
1586
+ function validator(modelValue, viewValue) {
1587
+ var value = modelValue || viewValue;
1588
+ if (angular.isNumber(value)) {
1589
+ value = new Date(value);
1590
+ }
1591
+ if (!value) {
1592
+ return true;
1593
+ } else if (angular.isDate(value) && !isNaN(value)) {
1594
+ return true;
1595
+ } else if (angular.isString(value)) {
1596
+ var date = dateParser.parse(value, dateFormat) || new Date(value);
1597
+ return !isNaN(date);
1598
+ } else {
1599
+ return false;
1600
+ }
1601
+ }
1602
+
1603
+ if (!isHtml5DateInput) {
1604
+ // Internal API to maintain the correct ng-invalid-[key] class
1605
+ ngModel.$$parserName = 'date';
1606
+ ngModel.$validators.date = validator;
1607
+ ngModel.$parsers.unshift(parseDate);
1608
+ ngModel.$formatters.push(function (value) {
1609
+ scope.date = value;
1610
+ return ngModel.$isEmpty(value) ? value : dateFilter(value, dateFormat);
1611
+ });
1612
+ }
1613
+ else {
1614
+ ngModel.$formatters.push(function (value) {
1615
+ scope.date = value;
1616
+ return value;
1617
+ });
1618
+ }
1491
1619
 
1492
1620
  // Inner change
1493
1621
  scope.dateSelection = function(dt) {
1494
1622
  if (angular.isDefined(dt)) {
1495
1623
  scope.date = dt;
1496
1624
  }
1497
- ngModel.$setViewValue(scope.date);
1498
- ngModel.$render();
1625
+ var date = scope.date ? dateFilter(scope.date, dateFormat) : '';
1626
+ element.val(date);
1627
+ ngModel.$setViewValue(date);
1499
1628
 
1500
1629
  if ( closeOnDateSelection ) {
1501
1630
  scope.isOpen = false;
@@ -1503,19 +1632,11 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1503
1632
  }
1504
1633
  };
1505
1634
 
1506
- element.bind('input change keyup', function() {
1507
- scope.$apply(function() {
1508
- scope.date = ngModel.$modelValue;
1509
- });
1635
+ // Detect changes in the view from the text box
1636
+ ngModel.$viewChangeListeners.push(function () {
1637
+ scope.date = dateParser.parse(ngModel.$viewValue, dateFormat, scope.date) || new Date(ngModel.$viewValue);
1510
1638
  });
1511
1639
 
1512
- // Outter change
1513
- ngModel.$render = function() {
1514
- var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';
1515
- element.val(date);
1516
- scope.date = parseDate( ngModel.$modelValue );
1517
- };
1518
-
1519
1640
  var documentClickBind = function(event) {
1520
1641
  if (scope.isOpen && event.target !== element[0]) {
1521
1642
  scope.$apply(function() {
@@ -1532,7 +1653,9 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1532
1653
  scope.keydown = function(evt) {
1533
1654
  if (evt.which === 27) {
1534
1655
  evt.preventDefault();
1535
- evt.stopPropagation();
1656
+ if (scope.isOpen) {
1657
+ evt.stopPropagation();
1658
+ }
1536
1659
  scope.close();
1537
1660
  } else if (evt.which === 40 && !scope.isOpen) {
1538
1661
  scope.isOpen = true;
@@ -1554,8 +1677,8 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1554
1677
  scope.select = function( date ) {
1555
1678
  if (date === 'today') {
1556
1679
  var today = new Date();
1557
- if (angular.isDate(ngModel.$modelValue)) {
1558
- date = new Date(ngModel.$modelValue);
1680
+ if (angular.isDate(scope.date)) {
1681
+ date = new Date(scope.date);
1559
1682
  date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
1560
1683
  } else {
1561
1684
  date = new Date(today.setHours(0, 0, 0, 0));
@@ -1570,6 +1693,9 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1570
1693
  };
1571
1694
 
1572
1695
  var $popup = $compile(popupEl)(scope);
1696
+ // Prevent jQuery cache memory leak (template is now redundant after linking)
1697
+ popupEl.remove();
1698
+
1573
1699
  if ( appendToBody ) {
1574
1700
  $document.find('body').append($popup);
1575
1701
  } else {
@@ -1600,13 +1726,13 @@ function ($compile, $parse, $document, $position, dateFilter, dateParser, datepi
1600
1726
  };
1601
1727
  });
1602
1728
 
1603
- angular.module('ui.bootstrap.dropdown', [])
1729
+ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
1604
1730
 
1605
1731
  .constant('dropdownConfig', {
1606
1732
  openClass: 'open'
1607
1733
  })
1608
1734
 
1609
- .service('dropdownService', ['$document', function($document) {
1735
+ .service('dropdownService', ['$document', '$rootScope', function($document, $rootScope) {
1610
1736
  var openScope = null;
1611
1737
 
1612
1738
  this.open = function( dropdownScope ) {
@@ -1631,13 +1757,27 @@ angular.module('ui.bootstrap.dropdown', [])
1631
1757
  };
1632
1758
 
1633
1759
  var closeDropdown = function( evt ) {
1634
- if (evt && evt.isDefaultPrevented()) {
1760
+ // This method may still be called during the same mouse event that
1761
+ // unbound this event handler. So check openScope before proceeding.
1762
+ if (!openScope) { return; }
1763
+
1764
+ if( evt && openScope.getAutoClose() === 'disabled' ) { return ; }
1765
+
1766
+ var toggleElement = openScope.getToggleElement();
1767
+ if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) {
1635
1768
  return;
1636
1769
  }
1637
1770
 
1638
- openScope.$apply(function() {
1639
- openScope.isOpen = false;
1640
- });
1771
+ var $element = openScope.getElement();
1772
+ if( evt && openScope.getAutoClose() === 'outsideClick' && $element && $element[0].contains(evt.target) ) {
1773
+ return;
1774
+ }
1775
+
1776
+ openScope.isOpen = false;
1777
+
1778
+ if (!$rootScope.$$phase) {
1779
+ openScope.$apply();
1780
+ }
1641
1781
  };
1642
1782
 
1643
1783
  var escapeKeyBind = function( evt ) {
@@ -1648,13 +1788,14 @@ angular.module('ui.bootstrap.dropdown', [])
1648
1788
  };
1649
1789
  }])
1650
1790
 
1651
- .controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate) {
1791
+ .controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', '$document', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document) {
1652
1792
  var self = this,
1653
1793
  scope = $scope.$new(), // create a child scope so we are not polluting original one
1654
1794
  openClass = dropdownConfig.openClass,
1655
1795
  getIsOpen,
1656
1796
  setIsOpen = angular.noop,
1657
- toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop;
1797
+ toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,
1798
+ appendToBody = false;
1658
1799
 
1659
1800
  this.init = function( element ) {
1660
1801
  self.$element = element;
@@ -1667,6 +1808,15 @@ angular.module('ui.bootstrap.dropdown', [])
1667
1808
  scope.isOpen = !!value;
1668
1809
  });
1669
1810
  }
1811
+
1812
+ appendToBody = angular.isDefined($attrs.dropdownAppendToBody);
1813
+
1814
+ if ( appendToBody && self.dropdownMenu ) {
1815
+ $document.find('body').append( self.dropdownMenu );
1816
+ element.on('$destroy', function handleDestroyEvent() {
1817
+ self.dropdownMenu.remove();
1818
+ });
1819
+ }
1670
1820
  };
1671
1821
 
1672
1822
  this.toggle = function( open ) {
@@ -1678,6 +1828,18 @@ angular.module('ui.bootstrap.dropdown', [])
1678
1828
  return scope.isOpen;
1679
1829
  };
1680
1830
 
1831
+ scope.getToggleElement = function() {
1832
+ return self.toggleElement;
1833
+ };
1834
+
1835
+ scope.getAutoClose = function() {
1836
+ return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled'
1837
+ };
1838
+
1839
+ scope.getElement = function() {
1840
+ return self.$element;
1841
+ };
1842
+
1681
1843
  scope.focusToggleElement = function() {
1682
1844
  if ( self.toggleElement ) {
1683
1845
  self.toggleElement[0].focus();
@@ -1685,6 +1847,15 @@ angular.module('ui.bootstrap.dropdown', [])
1685
1847
  };
1686
1848
 
1687
1849
  scope.$watch('isOpen', function( isOpen, wasOpen ) {
1850
+ if ( appendToBody && self.dropdownMenu ) {
1851
+ var pos = $position.positionElements(self.$element, self.dropdownMenu, 'bottom-left', true);
1852
+ self.dropdownMenu.css({
1853
+ top: pos.top + 'px',
1854
+ left: pos.left + 'px',
1855
+ display: isOpen ? 'block' : 'none'
1856
+ });
1857
+ }
1858
+
1688
1859
  $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass);
1689
1860
 
1690
1861
  if ( isOpen ) {
@@ -1711,7 +1882,6 @@ angular.module('ui.bootstrap.dropdown', [])
1711
1882
 
1712
1883
  .directive('dropdown', function() {
1713
1884
  return {
1714
- restrict: 'CA',
1715
1885
  controller: 'DropdownController',
1716
1886
  link: function(scope, element, attrs, dropdownCtrl) {
1717
1887
  dropdownCtrl.init( element );
@@ -1719,9 +1889,21 @@ angular.module('ui.bootstrap.dropdown', [])
1719
1889
  };
1720
1890
  })
1721
1891
 
1892
+ .directive('dropdownMenu', function() {
1893
+ return {
1894
+ restrict: 'AC',
1895
+ require: '?^dropdown',
1896
+ link: function(scope, element, attrs, dropdownCtrl) {
1897
+ if ( !dropdownCtrl ) {
1898
+ return;
1899
+ }
1900
+ dropdownCtrl.dropdownMenu = element;
1901
+ }
1902
+ };
1903
+ })
1904
+
1722
1905
  .directive('dropdownToggle', function() {
1723
1906
  return {
1724
- restrict: 'CA',
1725
1907
  require: '?^dropdown',
1726
1908
  link: function(scope, element, attrs, dropdownCtrl) {
1727
1909
  if ( !dropdownCtrl ) {
@@ -1755,7 +1937,7 @@ angular.module('ui.bootstrap.dropdown', [])
1755
1937
  };
1756
1938
  });
1757
1939
 
1758
- angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1940
+ angular.module('ui.bootstrap.modal', [])
1759
1941
 
1760
1942
  /**
1761
1943
  * A helper, internal data structure that acts as a map but also allows getting / removing
@@ -1819,19 +2001,23 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1819
2001
  restrict: 'EA',
1820
2002
  replace: true,
1821
2003
  templateUrl: 'template/modal/backdrop.html',
1822
- link: function (scope) {
1823
-
1824
- scope.animate = false;
1825
-
1826
- //trigger CSS transitions
1827
- $timeout(function () {
1828
- scope.animate = true;
1829
- });
2004
+ compile: function (tElement, tAttrs) {
2005
+ tElement.addClass(tAttrs.backdropClass);
2006
+ return linkFn;
1830
2007
  }
1831
2008
  };
2009
+
2010
+ function linkFn(scope, element, attrs) {
2011
+ scope.animate = false;
2012
+
2013
+ //trigger CSS transitions
2014
+ $timeout(function () {
2015
+ scope.animate = true;
2016
+ });
2017
+ }
1832
2018
  }])
1833
2019
 
1834
- .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) {
2020
+ .directive('modalWindow', ['$modalStack', '$q', function ($modalStack, $q) {
1835
2021
  return {
1836
2022
  restrict: 'EA',
1837
2023
  scope: {
@@ -1847,13 +2033,6 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1847
2033
  element.addClass(attrs.windowClass || '');
1848
2034
  scope.size = attrs.size;
1849
2035
 
1850
- $timeout(function () {
1851
- // trigger CSS transitions
1852
- scope.animate = true;
1853
- // focus a freshly-opened modal
1854
- element[0].focus();
1855
- });
1856
-
1857
2036
  scope.close = function (evt) {
1858
2037
  var modal = $modalStack.getTop();
1859
2038
  if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) {
@@ -1862,12 +2041,75 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1862
2041
  $modalStack.dismiss(modal.key, 'backdrop click');
1863
2042
  }
1864
2043
  };
2044
+
2045
+ // This property is only added to the scope for the purpose of detecting when this directive is rendered.
2046
+ // We can detect that by using this property in the template associated with this directive and then use
2047
+ // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.
2048
+ scope.$isRendered = true;
2049
+
2050
+ // Deferred object that will be resolved when this modal is render.
2051
+ var modalRenderDeferObj = $q.defer();
2052
+ // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready.
2053
+ // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template.
2054
+ attrs.$observe('modalRender', function (value) {
2055
+ if (value == 'true') {
2056
+ modalRenderDeferObj.resolve();
2057
+ }
2058
+ });
2059
+
2060
+ modalRenderDeferObj.promise.then(function () {
2061
+ // trigger CSS transitions
2062
+ scope.animate = true;
2063
+
2064
+ var inputsWithAutofocus = element[0].querySelectorAll('[autofocus]');
2065
+ /**
2066
+ * Auto-focusing of a freshly-opened modal element causes any child elements
2067
+ * with the autofocus attribute to lose focus. This is an issue on touch
2068
+ * based devices which will show and then hide the onscreen keyboard.
2069
+ * Attempts to refocus the autofocus element via JavaScript will not reopen
2070
+ * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
2071
+ * the modal element if the modal does not contain an autofocus element.
2072
+ */
2073
+ if (inputsWithAutofocus.length) {
2074
+ inputsWithAutofocus[0].focus();
2075
+ } else {
2076
+ element[0].focus();
2077
+ }
2078
+
2079
+ // Notify {@link $modalStack} that modal is rendered.
2080
+ var modal = $modalStack.getTop();
2081
+ if (modal) {
2082
+ $modalStack.modalRendered(modal.key);
2083
+ }
2084
+ });
1865
2085
  }
1866
2086
  };
1867
2087
  }])
1868
2088
 
1869
- .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
1870
- function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {
2089
+ .directive('modalAnimationClass', [
2090
+ function () {
2091
+ return {
2092
+ compile: function (tElement, tAttrs) {
2093
+ if (tAttrs.modalAnimation) {
2094
+ tElement.addClass(tAttrs.modalAnimationClass);
2095
+ }
2096
+ }
2097
+ };
2098
+ }])
2099
+
2100
+ .directive('modalTransclude', function () {
2101
+ return {
2102
+ link: function($scope, $element, $attrs, controller, $transclude) {
2103
+ $transclude($scope.$parent, function(clone) {
2104
+ $element.empty();
2105
+ $element.append(clone);
2106
+ });
2107
+ }
2108
+ };
2109
+ })
2110
+
2111
+ .factory('$modalStack', ['$animate', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
2112
+ function ($animate, $timeout, $document, $compile, $rootScope, $$stackedMap) {
1871
2113
 
1872
2114
  var OPENED_MODAL_CLASS = 'modal-open';
1873
2115
 
@@ -1901,8 +2143,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1901
2143
  openedWindows.remove(modalInstance);
1902
2144
 
1903
2145
  //remove window DOM element
1904
- removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, function() {
1905
- modalWindow.modalScope.$destroy();
2146
+ removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {
1906
2147
  body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
1907
2148
  checkRemoveBackdrop();
1908
2149
  });
@@ -1912,8 +2153,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1912
2153
  //remove backdrop if no longer needed
1913
2154
  if (backdropDomEl && backdropIndex() == -1) {
1914
2155
  var backdropScopeRef = backdropScope;
1915
- removeAfterAnimate(backdropDomEl, backdropScope, 150, function () {
1916
- backdropScopeRef.$destroy();
2156
+ removeAfterAnimate(backdropDomEl, backdropScope, function () {
1917
2157
  backdropScopeRef = null;
1918
2158
  });
1919
2159
  backdropDomEl = undefined;
@@ -1921,23 +2161,18 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1921
2161
  }
1922
2162
  }
1923
2163
 
1924
- function removeAfterAnimate(domEl, scope, emulateTime, done) {
2164
+ function removeAfterAnimate(domEl, scope, done) {
1925
2165
  // Closing animation
1926
2166
  scope.animate = false;
1927
2167
 
1928
- var transitionEndEventName = $transition.transitionEndEventName;
1929
- if (transitionEndEventName) {
2168
+ if (domEl.attr('modal-animation') && $animate.enabled()) {
1930
2169
  // transition out
1931
- var timeout = $timeout(afterAnimating, emulateTime);
1932
-
1933
- domEl.bind(transitionEndEventName, function () {
1934
- $timeout.cancel(timeout);
1935
- afterAnimating();
1936
- scope.$apply();
2170
+ domEl.one('$animate:close', function closeFn() {
2171
+ $rootScope.$evalAsync(afterAnimating);
1937
2172
  });
1938
2173
  } else {
1939
2174
  // Ensure this call is async
1940
- $timeout(afterAnimating, 0);
2175
+ $timeout(afterAnimating);
1941
2176
  }
1942
2177
 
1943
2178
  function afterAnimating() {
@@ -1947,6 +2182,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1947
2182
  afterAnimating.done = true;
1948
2183
 
1949
2184
  domEl.remove();
2185
+ scope.$destroy();
1950
2186
  if (done) {
1951
2187
  done();
1952
2188
  }
@@ -1969,8 +2205,11 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1969
2205
 
1970
2206
  $modalStack.open = function (modalInstance, modal) {
1971
2207
 
2208
+ var modalOpener = $document[0].activeElement;
2209
+
1972
2210
  openedWindows.add(modalInstance, {
1973
2211
  deferred: modal.deferred,
2212
+ renderDeferred: modal.renderDeferred,
1974
2213
  modalScope: modal.scope,
1975
2214
  backdrop: modal.backdrop,
1976
2215
  keyboard: modal.keyboard
@@ -1982,11 +2221,16 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1982
2221
  if (currBackdropIndex >= 0 && !backdropDomEl) {
1983
2222
  backdropScope = $rootScope.$new(true);
1984
2223
  backdropScope.index = currBackdropIndex;
1985
- backdropDomEl = $compile('<div modal-backdrop></div>')(backdropScope);
2224
+ var angularBackgroundDomEl = angular.element('<div modal-backdrop="modal-backdrop"></div>');
2225
+ angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass);
2226
+ if (modal.animation) {
2227
+ angularBackgroundDomEl.attr('modal-animation', 'true');
2228
+ }
2229
+ backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);
1986
2230
  body.append(backdropDomEl);
1987
2231
  }
1988
2232
 
1989
- var angularDomEl = angular.element('<div modal-window></div>');
2233
+ var angularDomEl = angular.element('<div modal-window="modal-window"></div>');
1990
2234
  angularDomEl.attr({
1991
2235
  'template-url': modal.windowTemplateUrl,
1992
2236
  'window-class': modal.windowClass,
@@ -1994,33 +2238,46 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
1994
2238
  'index': openedWindows.length() - 1,
1995
2239
  'animate': 'animate'
1996
2240
  }).html(modal.content);
2241
+ if (modal.animation) {
2242
+ angularDomEl.attr('modal-animation', 'true');
2243
+ }
1997
2244
 
1998
2245
  var modalDomEl = $compile(angularDomEl)(modal.scope);
1999
2246
  openedWindows.top().value.modalDomEl = modalDomEl;
2247
+ openedWindows.top().value.modalOpener = modalOpener;
2000
2248
  body.append(modalDomEl);
2001
2249
  body.addClass(OPENED_MODAL_CLASS);
2002
2250
  };
2003
2251
 
2252
+ function broadcastClosing(modalWindow, resultOrReason, closing) {
2253
+ return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
2254
+ }
2255
+
2004
2256
  $modalStack.close = function (modalInstance, result) {
2005
- var modalWindow = openedWindows.get(modalInstance).value;
2006
- if (modalWindow) {
2007
- modalWindow.deferred.resolve(result);
2257
+ var modalWindow = openedWindows.get(modalInstance);
2258
+ if (modalWindow && broadcastClosing(modalWindow, result, true)) {
2259
+ modalWindow.value.deferred.resolve(result);
2008
2260
  removeModalWindow(modalInstance);
2261
+ modalWindow.value.modalOpener.focus();
2262
+ return true;
2009
2263
  }
2264
+ return !modalWindow;
2010
2265
  };
2011
2266
 
2012
2267
  $modalStack.dismiss = function (modalInstance, reason) {
2013
- var modalWindow = openedWindows.get(modalInstance).value;
2014
- if (modalWindow) {
2015
- modalWindow.deferred.reject(reason);
2268
+ var modalWindow = openedWindows.get(modalInstance);
2269
+ if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
2270
+ modalWindow.value.deferred.reject(reason);
2016
2271
  removeModalWindow(modalInstance);
2272
+ modalWindow.value.modalOpener.focus();
2273
+ return true;
2017
2274
  }
2275
+ return !modalWindow;
2018
2276
  };
2019
2277
 
2020
2278
  $modalStack.dismissAll = function (reason) {
2021
2279
  var topModal = this.getTop();
2022
- while (topModal) {
2023
- this.dismiss(topModal.key, reason);
2280
+ while (topModal && this.dismiss(topModal.key, reason)) {
2024
2281
  topModal = this.getTop();
2025
2282
  }
2026
2283
  };
@@ -2029,6 +2286,13 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2029
2286
  return openedWindows.top();
2030
2287
  };
2031
2288
 
2289
+ $modalStack.modalRendered = function (modalInstance) {
2290
+ var modalWindow = openedWindows.get(modalInstance);
2291
+ if (modalWindow) {
2292
+ modalWindow.value.renderDeferred.resolve();
2293
+ }
2294
+ };
2295
+
2032
2296
  return $modalStack;
2033
2297
  }])
2034
2298
 
@@ -2036,24 +2300,23 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2036
2300
 
2037
2301
  var $modalProvider = {
2038
2302
  options: {
2039
- backdrop: true, //can be also false or 'static'
2303
+ animation: true,
2304
+ backdrop: true, //can also be false or 'static'
2040
2305
  keyboard: true
2041
2306
  },
2042
- $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',
2043
- function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {
2307
+ $get: ['$injector', '$rootScope', '$q', '$templateRequest', '$controller', '$modalStack',
2308
+ function ($injector, $rootScope, $q, $templateRequest, $controller, $modalStack) {
2044
2309
 
2045
2310
  var $modal = {};
2046
2311
 
2047
2312
  function getTemplatePromise(options) {
2048
2313
  return options.template ? $q.when(options.template) :
2049
- $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
2050
- return result.data;
2051
- });
2314
+ $templateRequest(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl);
2052
2315
  }
2053
2316
 
2054
2317
  function getResolvePromises(resolves) {
2055
2318
  var promisesArr = [];
2056
- angular.forEach(resolves, function (value, key) {
2319
+ angular.forEach(resolves, function (value) {
2057
2320
  if (angular.isFunction(value) || angular.isArray(value)) {
2058
2321
  promisesArr.push($q.when($injector.invoke(value)));
2059
2322
  }
@@ -2065,16 +2328,18 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2065
2328
 
2066
2329
  var modalResultDeferred = $q.defer();
2067
2330
  var modalOpenedDeferred = $q.defer();
2331
+ var modalRenderDeferred = $q.defer();
2068
2332
 
2069
2333
  //prepare an instance of a modal to be injected into controllers and returned to a caller
2070
2334
  var modalInstance = {
2071
2335
  result: modalResultDeferred.promise,
2072
2336
  opened: modalOpenedDeferred.promise,
2337
+ rendered: modalRenderDeferred.promise,
2073
2338
  close: function (result) {
2074
- $modalStack.close(modalInstance, result);
2339
+ return $modalStack.close(modalInstance, result);
2075
2340
  },
2076
2341
  dismiss: function (reason) {
2077
- $modalStack.dismiss(modalInstance, reason);
2342
+ return $modalStack.dismiss(modalInstance, reason);
2078
2343
  }
2079
2344
  };
2080
2345
 
@@ -2109,14 +2374,20 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2109
2374
  });
2110
2375
 
2111
2376
  ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
2377
+ if (modalOptions.controllerAs) {
2378
+ modalScope[modalOptions.controllerAs] = ctrlInstance;
2379
+ }
2112
2380
  }
2113
2381
 
2114
2382
  $modalStack.open(modalInstance, {
2115
2383
  scope: modalScope,
2116
2384
  deferred: modalResultDeferred,
2385
+ renderDeferred: modalRenderDeferred,
2117
2386
  content: tplAndVars[0],
2387
+ animation: modalOptions.animation,
2118
2388
  backdrop: modalOptions.backdrop,
2119
2389
  keyboard: modalOptions.keyboard,
2390
+ backdropClass: modalOptions.backdropClass,
2120
2391
  windowClass: modalOptions.windowClass,
2121
2392
  windowTemplateUrl: modalOptions.windowTemplateUrl,
2122
2393
  size: modalOptions.size
@@ -2128,8 +2399,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
2128
2399
 
2129
2400
  templateAndResolvePromise.then(function () {
2130
2401
  modalOpenedDeferred.resolve(true);
2131
- }, function () {
2132
- modalOpenedDeferred.reject(false);
2402
+ }, function (reason) {
2403
+ modalOpenedDeferred.reject(reason);
2133
2404
  });
2134
2405
 
2135
2406
  return modalInstance;
@@ -2165,6 +2436,20 @@ angular.module('ui.bootstrap.pagination', [])
2165
2436
  } else {
2166
2437
  this.itemsPerPage = config.itemsPerPage;
2167
2438
  }
2439
+
2440
+ $scope.$watch('totalItems', function() {
2441
+ $scope.totalPages = self.calculateTotalPages();
2442
+ });
2443
+
2444
+ $scope.$watch('totalPages', function(value) {
2445
+ setNumPages($scope.$parent, value); // Readonly variable
2446
+
2447
+ if ( $scope.page > value ) {
2448
+ $scope.selectPage(value);
2449
+ } else {
2450
+ ngModelCtrl.$render();
2451
+ }
2452
+ });
2168
2453
  };
2169
2454
 
2170
2455
  this.calculateTotalPages = function() {
@@ -2176,8 +2461,11 @@ angular.module('ui.bootstrap.pagination', [])
2176
2461
  $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1;
2177
2462
  };
2178
2463
 
2179
- $scope.selectPage = function(page) {
2464
+ $scope.selectPage = function(page, evt) {
2180
2465
  if ( $scope.page !== page && page > 0 && page <= $scope.totalPages) {
2466
+ if (evt && evt.target) {
2467
+ evt.target.blur();
2468
+ }
2181
2469
  ngModelCtrl.$setViewValue(page);
2182
2470
  ngModelCtrl.$render();
2183
2471
  }
@@ -2192,20 +2480,6 @@ angular.module('ui.bootstrap.pagination', [])
2192
2480
  $scope.noNext = function() {
2193
2481
  return $scope.page === $scope.totalPages;
2194
2482
  };
2195
-
2196
- $scope.$watch('totalItems', function() {
2197
- $scope.totalPages = self.calculateTotalPages();
2198
- });
2199
-
2200
- $scope.$watch('totalPages', function(value) {
2201
- setNumPages($scope.$parent, value); // Readonly variable
2202
-
2203
- if ( $scope.page > value ) {
2204
- $scope.selectPage(value);
2205
- } else {
2206
- ngModelCtrl.$render();
2207
- }
2208
- });
2209
2483
  }])
2210
2484
 
2211
2485
  .constant('paginationConfig', {
@@ -2373,7 +2647,8 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2373
2647
  var defaultOptions = {
2374
2648
  placement: 'top',
2375
2649
  animation: true,
2376
- popupDelay: 0
2650
+ popupDelay: 0,
2651
+ useContentExp: false
2377
2652
  };
2378
2653
 
2379
2654
  // Default hide triggers for each show trigger
@@ -2423,9 +2698,9 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2423
2698
  * Returns the actual instance of the $tooltip service.
2424
2699
  * TODO support multiple triggers
2425
2700
  */
2426
- this.$get = [ '$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $parse, $document, $position, $interpolate ) {
2427
- return function $tooltip ( type, prefix, defaultTriggerShow ) {
2428
- var options = angular.extend( {}, defaultOptions, globalOptions );
2701
+ this.$get = [ '$window', '$compile', '$timeout', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $document, $position, $interpolate ) {
2702
+ return function $tooltip ( type, prefix, defaultTriggerShow, options ) {
2703
+ options = angular.extend( {}, defaultOptions, globalOptions, options );
2429
2704
 
2430
2705
  /**
2431
2706
  * Returns an object of show and hide triggers.
@@ -2456,31 +2731,37 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2456
2731
  var endSym = $interpolate.endSymbol();
2457
2732
  var template =
2458
2733
  '<div '+ directiveName +'-popup '+
2459
- 'title="'+startSym+'tt_title'+endSym+'" '+
2460
- 'content="'+startSym+'tt_content'+endSym+'" '+
2461
- 'placement="'+startSym+'tt_placement'+endSym+'" '+
2462
- 'animation="tt_animation" '+
2463
- 'is-open="tt_isOpen"'+
2734
+ 'title="'+startSym+'title'+endSym+'" '+
2735
+ (options.useContentExp ?
2736
+ 'content-exp="contentExp()" ' :
2737
+ 'content="'+startSym+'content'+endSym+'" ') +
2738
+ 'placement="'+startSym+'placement'+endSym+'" '+
2739
+ 'popup-class="'+startSym+'popupClass'+endSym+'" '+
2740
+ 'animation="animation" '+
2741
+ 'is-open="isOpen"'+
2742
+ 'origin-scope="origScope" '+
2464
2743
  '>'+
2465
2744
  '</div>';
2466
2745
 
2467
2746
  return {
2468
2747
  restrict: 'EA',
2469
- scope: true,
2470
2748
  compile: function (tElem, tAttrs) {
2471
2749
  var tooltipLinker = $compile( template );
2472
2750
 
2473
- return function link ( scope, element, attrs ) {
2751
+ return function link ( scope, element, attrs, tooltipCtrl ) {
2474
2752
  var tooltip;
2753
+ var tooltipLinkedScope;
2475
2754
  var transitionTimeout;
2476
2755
  var popupTimeout;
2477
2756
  var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;
2478
2757
  var triggers = getTriggers( undefined );
2479
2758
  var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);
2759
+ var ttScope = scope.$new(true);
2480
2760
 
2481
2761
  var positionTooltip = function () {
2762
+ if (!tooltip) { return; }
2482
2763
 
2483
- var ttPosition = $position.positionElements(element, tooltip, scope.tt_placement, appendToBody);
2764
+ var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);
2484
2765
  ttPosition.top += 'px';
2485
2766
  ttPosition.left += 'px';
2486
2767
 
@@ -2488,12 +2769,15 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2488
2769
  tooltip.css( ttPosition );
2489
2770
  };
2490
2771
 
2772
+ // Set up the correct scope to allow transclusion later
2773
+ ttScope.origScope = scope;
2774
+
2491
2775
  // By default, the tooltip is not open.
2492
2776
  // TODO add ability to start tooltip opened
2493
- scope.tt_isOpen = false;
2777
+ ttScope.isOpen = false;
2494
2778
 
2495
2779
  function toggleTooltipBind () {
2496
- if ( ! scope.tt_isOpen ) {
2780
+ if ( ! ttScope.isOpen ) {
2497
2781
  showTooltipBind();
2498
2782
  } else {
2499
2783
  hideTooltipBind();
@@ -2505,11 +2789,14 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2505
2789
  if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) {
2506
2790
  return;
2507
2791
  }
2508
- if ( scope.tt_popupDelay ) {
2792
+
2793
+ prepareTooltip();
2794
+
2795
+ if ( ttScope.popupDelay ) {
2509
2796
  // Do nothing if the tooltip was already scheduled to pop-up.
2510
2797
  // This happens if show is triggered multiple times before any hide is triggered.
2511
2798
  if (!popupTimeout) {
2512
- popupTimeout = $timeout( show, scope.tt_popupDelay, false );
2799
+ popupTimeout = $timeout( show, ttScope.popupDelay, false );
2513
2800
  popupTimeout.then(function(reposition){reposition();});
2514
2801
  }
2515
2802
  } else {
@@ -2536,7 +2823,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2536
2823
  }
2537
2824
 
2538
2825
  // Don't show empty tooltips.
2539
- if ( ! scope.tt_content ) {
2826
+ if ( !(options.useContentExp ? ttScope.contentExp() : ttScope.content) ) {
2540
2827
  return angular.noop;
2541
2828
  }
2542
2829
 
@@ -2544,20 +2831,13 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2544
2831
 
2545
2832
  // Set the initial positioning.
2546
2833
  tooltip.css({ top: 0, left: 0, display: 'block' });
2547
-
2548
- // Now we add it to the DOM because need some info about it. But it's not
2549
- // visible yet anyway.
2550
- if ( appendToBody ) {
2551
- $document.find( 'body' ).append( tooltip );
2552
- } else {
2553
- element.after( tooltip );
2554
- }
2834
+ ttScope.$digest();
2555
2835
 
2556
2836
  positionTooltip();
2557
2837
 
2558
2838
  // And show the tooltip.
2559
- scope.tt_isOpen = true;
2560
- scope.$digest(); // digest required as $apply is not called
2839
+ ttScope.isOpen = true;
2840
+ ttScope.$apply(); // digest required as $apply is not called
2561
2841
 
2562
2842
  // Return positioning function as promise callback for correct
2563
2843
  // positioning after draw.
@@ -2567,16 +2847,16 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2567
2847
  // Hide the tooltip popup element.
2568
2848
  function hide() {
2569
2849
  // First things first: we don't show it anymore.
2570
- scope.tt_isOpen = false;
2850
+ ttScope.isOpen = false;
2571
2851
 
2572
2852
  //if tooltip is going to be shown after delay, we must cancel this
2573
2853
  $timeout.cancel( popupTimeout );
2574
2854
  popupTimeout = null;
2575
2855
 
2576
- // And now we remove it from the DOM. However, if we have animation, we
2856
+ // And now we remove it from the DOM. However, if we have animation, we
2577
2857
  // need to wait for it to expire beforehand.
2578
2858
  // FIXME: this is a placeholder for a port of the transitions library.
2579
- if ( scope.tt_animation ) {
2859
+ if ( ttScope.animation ) {
2580
2860
  if (!transitionTimeout) {
2581
2861
  transitionTimeout = $timeout(removeTooltip, 500);
2582
2862
  }
@@ -2590,10 +2870,26 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2590
2870
  if (tooltip) {
2591
2871
  removeTooltip();
2592
2872
  }
2593
- tooltip = tooltipLinker(scope, function () {});
2873
+ tooltipLinkedScope = ttScope.$new();
2874
+ tooltip = tooltipLinker(tooltipLinkedScope, function (tooltip) {
2875
+ if ( appendToBody ) {
2876
+ $document.find( 'body' ).append( tooltip );
2877
+ } else {
2878
+ element.after( tooltip );
2879
+ }
2880
+ });
2881
+
2882
+ tooltipLinkedScope.$watch(function () {
2883
+ $timeout(positionTooltip, 0, false);
2884
+ });
2594
2885
 
2595
- // Get contents rendered into the tooltip
2596
- scope.$digest();
2886
+ if (options.useContentExp) {
2887
+ tooltipLinkedScope.$watch('contentExp()', function (val) {
2888
+ if (!val && ttScope.isOpen ) {
2889
+ hide();
2890
+ }
2891
+ });
2892
+ }
2597
2893
  }
2598
2894
 
2599
2895
  function removeTooltip() {
@@ -2602,38 +2898,67 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2602
2898
  tooltip.remove();
2603
2899
  tooltip = null;
2604
2900
  }
2901
+ if (tooltipLinkedScope) {
2902
+ tooltipLinkedScope.$destroy();
2903
+ tooltipLinkedScope = null;
2904
+ }
2905
+ }
2906
+
2907
+ function prepareTooltip() {
2908
+ prepPopupClass();
2909
+ prepPlacement();
2910
+ prepPopupDelay();
2605
2911
  }
2606
2912
 
2913
+ ttScope.contentExp = function () {
2914
+ return scope.$eval(attrs[type]);
2915
+ };
2916
+
2607
2917
  /**
2608
2918
  * Observe the relevant attributes.
2609
2919
  */
2610
- attrs.$observe( type, function ( val ) {
2611
- scope.tt_content = val;
2920
+ if (!options.useContentExp) {
2921
+ attrs.$observe( type, function ( val ) {
2922
+ ttScope.content = val;
2923
+
2924
+ if (!val && ttScope.isOpen ) {
2925
+ hide();
2926
+ }
2927
+ });
2928
+ }
2612
2929
 
2613
- if (!val && scope.tt_isOpen ) {
2930
+ attrs.$observe( 'disabled', function ( val ) {
2931
+ if (val && ttScope.isOpen ) {
2614
2932
  hide();
2615
2933
  }
2616
2934
  });
2617
2935
 
2618
2936
  attrs.$observe( prefix+'Title', function ( val ) {
2619
- scope.tt_title = val;
2937
+ ttScope.title = val;
2620
2938
  });
2621
2939
 
2622
- attrs.$observe( prefix+'Placement', function ( val ) {
2623
- scope.tt_placement = angular.isDefined( val ) ? val : options.placement;
2624
- });
2940
+ function prepPopupClass() {
2941
+ ttScope.popupClass = attrs[prefix + 'Class'];
2942
+ }
2943
+
2944
+ function prepPlacement() {
2945
+ var val = attrs[ prefix + 'Placement' ];
2946
+ ttScope.placement = angular.isDefined( val ) ? val : options.placement;
2947
+ }
2625
2948
 
2626
- attrs.$observe( prefix+'PopupDelay', function ( val ) {
2949
+ function prepPopupDelay() {
2950
+ var val = attrs[ prefix + 'PopupDelay' ];
2627
2951
  var delay = parseInt( val, 10 );
2628
- scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
2629
- });
2952
+ ttScope.popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
2953
+ }
2630
2954
 
2631
2955
  var unregisterTriggers = function () {
2632
2956
  element.unbind(triggers.show, showTooltipBind);
2633
2957
  element.unbind(triggers.hide, hideTooltipBind);
2634
2958
  };
2635
2959
 
2636
- attrs.$observe( prefix+'Trigger', function ( val ) {
2960
+ function prepTriggers() {
2961
+ var val = attrs[ prefix + 'Trigger' ];
2637
2962
  unregisterTriggers();
2638
2963
 
2639
2964
  triggers = getTriggers( val );
@@ -2644,21 +2969,21 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2644
2969
  element.bind( triggers.show, showTooltipBind );
2645
2970
  element.bind( triggers.hide, hideTooltipBind );
2646
2971
  }
2647
- });
2972
+ }
2973
+ prepTriggers();
2648
2974
 
2649
2975
  var animation = scope.$eval(attrs[prefix + 'Animation']);
2650
- scope.tt_animation = angular.isDefined(animation) ? !!animation : options.animation;
2976
+ ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;
2651
2977
 
2652
- attrs.$observe( prefix+'AppendToBody', function ( val ) {
2653
- appendToBody = angular.isDefined( val ) ? $parse( val )( scope ) : appendToBody;
2654
- });
2978
+ var appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']);
2979
+ appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;
2655
2980
 
2656
2981
  // if a tooltip is attached to <body> we need to remove it on
2657
2982
  // location change as its parent scope will probably not be destroyed
2658
2983
  // by the change.
2659
2984
  if ( appendToBody ) {
2660
2985
  scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () {
2661
- if ( scope.tt_isOpen ) {
2986
+ if ( ttScope.isOpen ) {
2662
2987
  hide();
2663
2988
  }
2664
2989
  });
@@ -2670,6 +2995,7 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2670
2995
  $timeout.cancel( popupTimeout );
2671
2996
  unregisterTriggers();
2672
2997
  removeTooltip();
2998
+ ttScope = null;
2673
2999
  });
2674
3000
  };
2675
3001
  }
@@ -2678,11 +3004,101 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2678
3004
  }];
2679
3005
  })
2680
3006
 
3007
+ // This is mostly ngInclude code but with a custom scope
3008
+ .directive( 'tooltipTemplateTransclude', [
3009
+ '$animate', '$sce', '$compile', '$templateRequest',
3010
+ function ($animate , $sce , $compile , $templateRequest) {
3011
+ return {
3012
+ link: function ( scope, elem, attrs ) {
3013
+ var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);
3014
+
3015
+ var changeCounter = 0,
3016
+ currentScope,
3017
+ previousElement,
3018
+ currentElement;
3019
+
3020
+ var cleanupLastIncludeContent = function() {
3021
+ if (previousElement) {
3022
+ previousElement.remove();
3023
+ previousElement = null;
3024
+ }
3025
+ if (currentScope) {
3026
+ currentScope.$destroy();
3027
+ currentScope = null;
3028
+ }
3029
+ if (currentElement) {
3030
+ $animate.leave(currentElement).then(function() {
3031
+ previousElement = null;
3032
+ });
3033
+ previousElement = currentElement;
3034
+ currentElement = null;
3035
+ }
3036
+ };
3037
+
3038
+ scope.$watch($sce.parseAsResourceUrl(attrs.tooltipTemplateTransclude), function (src) {
3039
+ var thisChangeId = ++changeCounter;
3040
+
3041
+ if (src) {
3042
+ //set the 2nd param to true to ignore the template request error so that the inner
3043
+ //contents and scope can be cleaned up.
3044
+ $templateRequest(src, true).then(function(response) {
3045
+ if (thisChangeId !== changeCounter) { return; }
3046
+ var newScope = origScope.$new();
3047
+ var template = response;
3048
+
3049
+ var clone = $compile(template)(newScope, function(clone) {
3050
+ cleanupLastIncludeContent();
3051
+ $animate.enter(clone, elem);
3052
+ });
3053
+
3054
+ currentScope = newScope;
3055
+ currentElement = clone;
3056
+
3057
+ currentScope.$emit('$includeContentLoaded', src);
3058
+ }, function() {
3059
+ if (thisChangeId === changeCounter) {
3060
+ cleanupLastIncludeContent();
3061
+ scope.$emit('$includeContentError', src);
3062
+ }
3063
+ });
3064
+ scope.$emit('$includeContentRequested', src);
3065
+ } else {
3066
+ cleanupLastIncludeContent();
3067
+ }
3068
+ });
3069
+
3070
+ scope.$on('$destroy', cleanupLastIncludeContent);
3071
+ }
3072
+ };
3073
+ }])
3074
+
3075
+ /**
3076
+ * Note that it's intentional that these classes are *not* applied through $animate.
3077
+ * They must not be animated as they're expected to be present on the tooltip on
3078
+ * initialization.
3079
+ */
3080
+ .directive('tooltipClasses', function () {
3081
+ return {
3082
+ restrict: 'A',
3083
+ link: function (scope, element, attrs) {
3084
+ if (scope.placement) {
3085
+ element.addClass(scope.placement);
3086
+ }
3087
+ if (scope.popupClass) {
3088
+ element.addClass(scope.popupClass);
3089
+ }
3090
+ if (scope.animation()) {
3091
+ element.addClass(attrs.tooltipAnimationClass);
3092
+ }
3093
+ }
3094
+ };
3095
+ })
3096
+
2681
3097
  .directive( 'tooltipPopup', function () {
2682
3098
  return {
2683
3099
  restrict: 'EA',
2684
3100
  replace: true,
2685
- scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
3101
+ scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
2686
3102
  templateUrl: 'template/tooltip/tooltip-popup.html'
2687
3103
  };
2688
3104
  })
@@ -2691,16 +3107,56 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2691
3107
  return $tooltip( 'tooltip', 'tooltip', 'mouseenter' );
2692
3108
  }])
2693
3109
 
3110
+ .directive( 'tooltipTemplatePopup', function () {
3111
+ return {
3112
+ restrict: 'EA',
3113
+ replace: true,
3114
+ scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',
3115
+ originScope: '&' },
3116
+ templateUrl: 'template/tooltip/tooltip-template-popup.html'
3117
+ };
3118
+ })
3119
+
3120
+ .directive( 'tooltipTemplate', [ '$tooltip', function ( $tooltip ) {
3121
+ return $tooltip('tooltipTemplate', 'tooltip', 'mouseenter', {
3122
+ useContentExp: true
3123
+ });
3124
+ }])
3125
+
3126
+ .directive( 'tooltipHtmlPopup', function () {
3127
+ return {
3128
+ restrict: 'EA',
3129
+ replace: true,
3130
+ scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
3131
+ templateUrl: 'template/tooltip/tooltip-html-popup.html'
3132
+ };
3133
+ })
3134
+
3135
+ .directive( 'tooltipHtml', [ '$tooltip', function ( $tooltip ) {
3136
+ return $tooltip('tooltipHtml', 'tooltip', 'mouseenter', {
3137
+ useContentExp: true
3138
+ });
3139
+ }])
3140
+
3141
+ /*
3142
+ Deprecated
3143
+ */
2694
3144
  .directive( 'tooltipHtmlUnsafePopup', function () {
2695
3145
  return {
2696
3146
  restrict: 'EA',
2697
3147
  replace: true,
2698
- scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
3148
+ scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
2699
3149
  templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html'
2700
3150
  };
2701
3151
  })
2702
3152
 
2703
- .directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) {
3153
+ .value('tooltipHtmlUnsafeSuppressDeprecated', false)
3154
+ .directive( 'tooltipHtmlUnsafe', [
3155
+ '$tooltip', 'tooltipHtmlUnsafeSuppressDeprecated', '$log',
3156
+ function ( $tooltip , tooltipHtmlUnsafeSuppressDeprecated , $log) {
3157
+ if (!tooltipHtmlUnsafeSuppressDeprecated) {
3158
+ $log.warn('tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead.');
3159
+ }
2704
3160
  return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' );
2705
3161
  }]);
2706
3162
 
@@ -2711,11 +3167,27 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
2711
3167
  */
2712
3168
  angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] )
2713
3169
 
3170
+ .directive( 'popoverTemplatePopup', function () {
3171
+ return {
3172
+ restrict: 'EA',
3173
+ replace: true,
3174
+ scope: { title: '@', contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',
3175
+ originScope: '&' },
3176
+ templateUrl: 'template/popover/popover-template.html'
3177
+ };
3178
+ })
3179
+
3180
+ .directive( 'popoverTemplate', [ '$tooltip', function ( $tooltip ) {
3181
+ return $tooltip( 'popoverTemplate', 'popover', 'click', {
3182
+ useContentExp: true
3183
+ } );
3184
+ }])
3185
+
2714
3186
  .directive( 'popoverPopup', function () {
2715
3187
  return {
2716
3188
  restrict: 'EA',
2717
3189
  replace: true,
2718
- scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
3190
+ scope: { title: '@', content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
2719
3191
  templateUrl: 'template/popover/popover.html'
2720
3192
  };
2721
3193
  })
@@ -2736,7 +3208,7 @@ angular.module('ui.bootstrap.progressbar', [])
2736
3208
  animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;
2737
3209
 
2738
3210
  this.bars = [];
2739
- $scope.max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max;
3211
+ $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max;
2740
3212
 
2741
3213
  this.addBar = function(bar, element) {
2742
3214
  if ( !animate ) {
@@ -2780,6 +3252,7 @@ angular.module('ui.bootstrap.progressbar', [])
2780
3252
  require: '^progress',
2781
3253
  scope: {
2782
3254
  value: '=',
3255
+ max: '=?',
2783
3256
  type: '@'
2784
3257
  },
2785
3258
  templateUrl: 'template/progressbar/bar.html',
@@ -2797,6 +3270,7 @@ angular.module('ui.bootstrap.progressbar', [])
2797
3270
  controller: 'ProgressController',
2798
3271
  scope: {
2799
3272
  value: '=',
3273
+ max: '=?',
2800
3274
  type: '@'
2801
3275
  },
2802
3276
  templateUrl: 'template/progressbar/progressbar.html',
@@ -2805,6 +3279,7 @@ angular.module('ui.bootstrap.progressbar', [])
2805
3279
  }
2806
3280
  };
2807
3281
  });
3282
+
2808
3283
  angular.module('ui.bootstrap.rating', [])
2809
3284
 
2810
3285
  .constant('ratingConfig', {
@@ -2820,6 +3295,13 @@ angular.module('ui.bootstrap.rating', [])
2820
3295
  ngModelCtrl = ngModelCtrl_;
2821
3296
  ngModelCtrl.$render = this.render;
2822
3297
 
3298
+ ngModelCtrl.$formatters.push(function(value) {
3299
+ if (angular.isNumber(value) && value << 0 !== value) {
3300
+ value = Math.round(value);
3301
+ }
3302
+ return value;
3303
+ });
3304
+
2823
3305
  this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;
2824
3306
  this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;
2825
3307
 
@@ -2881,10 +3363,7 @@ angular.module('ui.bootstrap.rating', [])
2881
3363
  replace: true,
2882
3364
  link: function(scope, element, attrs, ctrls) {
2883
3365
  var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];
2884
-
2885
- if ( ngModelCtrl ) {
2886
- ratingCtrl.init( ngModelCtrl );
2887
- }
3366
+ ratingCtrl.init( ngModelCtrl );
2888
3367
  }
2889
3368
  };
2890
3369
  });
@@ -2918,23 +3397,31 @@ angular.module('ui.bootstrap.tabs', [])
2918
3397
  tabs.push(tab);
2919
3398
  // we can't run the select function on the first tab
2920
3399
  // since that would select it twice
2921
- if (tabs.length === 1) {
3400
+ if (tabs.length === 1 && tab.active !== false) {
2922
3401
  tab.active = true;
2923
3402
  } else if (tab.active) {
2924
3403
  ctrl.select(tab);
2925
3404
  }
3405
+ else {
3406
+ tab.active = false;
3407
+ }
2926
3408
  };
2927
3409
 
2928
3410
  ctrl.removeTab = function removeTab(tab) {
2929
3411
  var index = tabs.indexOf(tab);
2930
- //Select a new tab if the tab to be removed is selected
2931
- if (tab.active && tabs.length > 1) {
3412
+ //Select a new tab if the tab to be removed is selected and not destroyed
3413
+ if (tab.active && tabs.length > 1 && !destroyed) {
2932
3414
  //If this is the last tab, select the previous tab. else, the next tab.
2933
3415
  var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1;
2934
3416
  ctrl.select(tabs[newActiveIndex]);
2935
3417
  }
2936
3418
  tabs.splice(index, 1);
2937
3419
  };
3420
+
3421
+ var destroyed;
3422
+ $scope.$on('$destroy', function() {
3423
+ destroyed = true;
3424
+ });
2938
3425
  }])
2939
3426
 
2940
3427
  /**
@@ -3064,7 +3551,7 @@ angular.module('ui.bootstrap.tabs', [])
3064
3551
  </file>
3065
3552
  </example>
3066
3553
  */
3067
- .directive('tab', ['$parse', function($parse) {
3554
+ .directive('tab', ['$parse', '$log', function($parse, $log) {
3068
3555
  return {
3069
3556
  require: '^tabset',
3070
3557
  restrict: 'EA',
@@ -3090,7 +3577,18 @@ angular.module('ui.bootstrap.tabs', [])
3090
3577
  });
3091
3578
 
3092
3579
  scope.disabled = false;
3580
+ if ( attrs.disable ) {
3581
+ scope.$parent.$watch($parse(attrs.disable), function(value) {
3582
+ scope.disabled = !! value;
3583
+ });
3584
+ }
3585
+
3586
+ // Deprecation support of "disabled" parameter
3587
+ // fix(tab): IE9 disabled attr renders grey text on enabled tab #2677
3588
+ // This code is duplicated from the lines above to make it easy to remove once
3589
+ // the feature has been completely deprecated
3093
3590
  if ( attrs.disabled ) {
3591
+ $log.warn('Use of "disabled" attribute has been deprecated, please use "disable"');
3094
3592
  scope.$parent.$watch($parse(attrs.disabled), function(value) {
3095
3593
  scope.disabled = !! value;
3096
3594
  });
@@ -3171,7 +3669,8 @@ angular.module('ui.bootstrap.timepicker', [])
3171
3669
  showMeridian: true,
3172
3670
  meridians: null,
3173
3671
  readonlyInput: false,
3174
- mousewheel: true
3672
+ mousewheel: true,
3673
+ arrowkeys: true
3175
3674
  })
3176
3675
 
3177
3676
  .controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) {
@@ -3183,6 +3682,10 @@ angular.module('ui.bootstrap.timepicker', [])
3183
3682
  ngModelCtrl = ngModelCtrl_;
3184
3683
  ngModelCtrl.$render = this.render;
3185
3684
 
3685
+ ngModelCtrl.$formatters.unshift(function (modelValue) {
3686
+ return modelValue ? new Date( modelValue ) : null;
3687
+ });
3688
+
3186
3689
  var hoursInputEl = inputs.eq(0),
3187
3690
  minutesInputEl = inputs.eq(1);
3188
3691
 
@@ -3191,6 +3694,11 @@ angular.module('ui.bootstrap.timepicker', [])
3191
3694
  this.setupMousewheelEvents( hoursInputEl, minutesInputEl );
3192
3695
  }
3193
3696
 
3697
+ var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys;
3698
+ if (arrowkeys) {
3699
+ this.setupArrowkeyEvents( hoursInputEl, minutesInputEl );
3700
+ }
3701
+
3194
3702
  $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;
3195
3703
  this.setupInputEvents( hoursInputEl, minutesInputEl );
3196
3704
  };
@@ -3253,7 +3761,7 @@ angular.module('ui.bootstrap.timepicker', [])
3253
3761
  }
3254
3762
 
3255
3763
  function pad( value ) {
3256
- return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value;
3764
+ return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value.toString();
3257
3765
  }
3258
3766
 
3259
3767
  // Respond on mousewheel spin
@@ -3279,6 +3787,35 @@ angular.module('ui.bootstrap.timepicker', [])
3279
3787
 
3280
3788
  };
3281
3789
 
3790
+ // Respond on up/down arrowkeys
3791
+ this.setupArrowkeyEvents = function( hoursInputEl, minutesInputEl ) {
3792
+ hoursInputEl.bind('keydown', function(e) {
3793
+ if ( e.which === 38 ) { // up
3794
+ e.preventDefault();
3795
+ $scope.incrementHours();
3796
+ $scope.$apply();
3797
+ }
3798
+ else if ( e.which === 40 ) { // down
3799
+ e.preventDefault();
3800
+ $scope.decrementHours();
3801
+ $scope.$apply();
3802
+ }
3803
+ });
3804
+
3805
+ minutesInputEl.bind('keydown', function(e) {
3806
+ if ( e.which === 38 ) { // up
3807
+ e.preventDefault();
3808
+ $scope.incrementMinutes();
3809
+ $scope.$apply();
3810
+ }
3811
+ else if ( e.which === 40 ) { // down
3812
+ e.preventDefault();
3813
+ $scope.decrementMinutes();
3814
+ $scope.$apply();
3815
+ }
3816
+ });
3817
+ };
3818
+
3282
3819
  this.setupInputEvents = function( hoursInputEl, minutesInputEl ) {
3283
3820
  if ( $scope.readonlyInput ) {
3284
3821
  $scope.updateHours = angular.noop;
@@ -3338,7 +3875,7 @@ angular.module('ui.bootstrap.timepicker', [])
3338
3875
  };
3339
3876
 
3340
3877
  this.render = function() {
3341
- var date = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : null;
3878
+ var date = ngModelCtrl.$viewValue;
3342
3879
 
3343
3880
  if ( isNaN(date) ) {
3344
3881
  ngModelCtrl.$setValidity('time', false);
@@ -3373,7 +3910,9 @@ angular.module('ui.bootstrap.timepicker', [])
3373
3910
  }
3374
3911
 
3375
3912
  $scope.hours = keyboardChange === 'h' ? hours : pad(hours);
3376
- $scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes);
3913
+ if (keyboardChange !== 'm') {
3914
+ $scope.minutes = pad(minutes);
3915
+ }
3377
3916
  $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
3378
3917
  }
3379
3918
 
@@ -3418,6 +3957,96 @@ angular.module('ui.bootstrap.timepicker', [])
3418
3957
  };
3419
3958
  });
3420
3959
 
3960
+ angular.module('ui.bootstrap.transition', [])
3961
+
3962
+ .value('$transitionSuppressDeprecated', false)
3963
+ /**
3964
+ * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.
3965
+ * @param {DOMElement} element The DOMElement that will be animated.
3966
+ * @param {string|object|function} trigger The thing that will cause the transition to start:
3967
+ * - As a string, it represents the css class to be added to the element.
3968
+ * - As an object, it represents a hash of style attributes to be applied to the element.
3969
+ * - As a function, it represents a function to be called that will cause the transition to occur.
3970
+ * @return {Promise} A promise that is resolved when the transition finishes.
3971
+ */
3972
+ .factory('$transition', [
3973
+ '$q', '$timeout', '$rootScope', '$log', '$transitionSuppressDeprecated',
3974
+ function($q , $timeout , $rootScope , $log , $transitionSuppressDeprecated) {
3975
+
3976
+ if (!$transitionSuppressDeprecated) {
3977
+ $log.warn('$transition is now deprecated. Use $animate from ngAnimate instead.');
3978
+ }
3979
+
3980
+ var $transition = function(element, trigger, options) {
3981
+ options = options || {};
3982
+ var deferred = $q.defer();
3983
+ var endEventName = $transition[options.animation ? 'animationEndEventName' : 'transitionEndEventName'];
3984
+
3985
+ var transitionEndHandler = function(event) {
3986
+ $rootScope.$apply(function() {
3987
+ element.unbind(endEventName, transitionEndHandler);
3988
+ deferred.resolve(element);
3989
+ });
3990
+ };
3991
+
3992
+ if (endEventName) {
3993
+ element.bind(endEventName, transitionEndHandler);
3994
+ }
3995
+
3996
+ // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
3997
+ $timeout(function() {
3998
+ if ( angular.isString(trigger) ) {
3999
+ element.addClass(trigger);
4000
+ } else if ( angular.isFunction(trigger) ) {
4001
+ trigger(element);
4002
+ } else if ( angular.isObject(trigger) ) {
4003
+ element.css(trigger);
4004
+ }
4005
+ //If browser does not support transitions, instantly resolve
4006
+ if ( !endEventName ) {
4007
+ deferred.resolve(element);
4008
+ }
4009
+ });
4010
+
4011
+ // Add our custom cancel function to the promise that is returned
4012
+ // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
4013
+ // i.e. it will therefore never raise a transitionEnd event for that transition
4014
+ deferred.promise.cancel = function() {
4015
+ if ( endEventName ) {
4016
+ element.unbind(endEventName, transitionEndHandler);
4017
+ }
4018
+ deferred.reject('Transition cancelled');
4019
+ };
4020
+
4021
+ return deferred.promise;
4022
+ };
4023
+
4024
+ // Work out the name of the transitionEnd event
4025
+ var transElement = document.createElement('trans');
4026
+ var transitionEndEventNames = {
4027
+ 'WebkitTransition': 'webkitTransitionEnd',
4028
+ 'MozTransition': 'transitionend',
4029
+ 'OTransition': 'oTransitionEnd',
4030
+ 'transition': 'transitionend'
4031
+ };
4032
+ var animationEndEventNames = {
4033
+ 'WebkitTransition': 'webkitAnimationEnd',
4034
+ 'MozTransition': 'animationend',
4035
+ 'OTransition': 'oAnimationEnd',
4036
+ 'transition': 'animationend'
4037
+ };
4038
+ function findEndEventName(endEventNames) {
4039
+ for (var name in endEventNames){
4040
+ if (transElement.style[name] !== undefined) {
4041
+ return endEventNames[name];
4042
+ }
4043
+ }
4044
+ }
4045
+ $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
4046
+ $transition.animationEndEventName = findEndEventName(animationEndEventNames);
4047
+ return $transition;
4048
+ }]);
4049
+
3421
4050
  angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml'])
3422
4051
 
3423
4052
  /**
@@ -3427,7 +4056,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3427
4056
  .factory('typeaheadParser', ['$parse', function ($parse) {
3428
4057
 
3429
4058
  // 00000111000000000000022200000000000000003333333333333330000000000044000
3430
- var TYPEAHEAD_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;
4059
+ var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;
3431
4060
 
3432
4061
  return {
3433
4062
  parse:function (input) {
@@ -3463,7 +4092,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3463
4092
  //minimal no of characters that needs to be entered before typeahead kicks-in
3464
4093
  var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;
3465
4094
 
3466
- //minimal wait time after last character typed before typehead kicks-in
4095
+ //minimal wait time after last character typed before typeahead kicks-in
3467
4096
  var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;
3468
4097
 
3469
4098
  //should it restrict model values to the ones selected from the popup only?
@@ -3479,6 +4108,8 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3479
4108
 
3480
4109
  var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;
3481
4110
 
4111
+ var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;
4112
+
3482
4113
  //INTERNAL VARIABLES
3483
4114
 
3484
4115
  //model setter executed upon match selection
@@ -3549,9 +4180,9 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3549
4180
  //but we are interested only in responses that correspond to the current view value
3550
4181
  var onCurrentRequest = (inputValue === modelCtrl.$viewValue);
3551
4182
  if (onCurrentRequest && hasFocus) {
3552
- if (matches.length > 0) {
4183
+ if (matches && matches.length > 0) {
3553
4184
 
3554
- scope.activeIdx = 0;
4185
+ scope.activeIdx = focusFirst ? 0 : -1;
3555
4186
  scope.matches.length = 0;
3556
4187
 
3557
4188
  //transform labels
@@ -3590,9 +4221,21 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3590
4221
  //we need to propagate user's query so we can higlight matches
3591
4222
  scope.query = undefined;
3592
4223
 
3593
- //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
4224
+ //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
3594
4225
  var timeoutPromise;
3595
4226
 
4227
+ var scheduleSearchWithTimeout = function(inputValue) {
4228
+ timeoutPromise = $timeout(function () {
4229
+ getMatchesAsync(inputValue);
4230
+ }, waitTime);
4231
+ };
4232
+
4233
+ var cancelPreviousTimeout = function() {
4234
+ if (timeoutPromise) {
4235
+ $timeout.cancel(timeoutPromise);
4236
+ }
4237
+ };
4238
+
3596
4239
  //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM
3597
4240
  //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue
3598
4241
  modelCtrl.$parsers.unshift(function (inputValue) {
@@ -3601,17 +4244,14 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3601
4244
 
3602
4245
  if (inputValue && inputValue.length >= minSearch) {
3603
4246
  if (waitTime > 0) {
3604
- if (timeoutPromise) {
3605
- $timeout.cancel(timeoutPromise);//cancel previous timeout
3606
- }
3607
- timeoutPromise = $timeout(function () {
3608
- getMatchesAsync(inputValue);
3609
- }, waitTime);
4247
+ cancelPreviousTimeout();
4248
+ scheduleSearchWithTimeout(inputValue);
3610
4249
  } else {
3611
4250
  getMatchesAsync(inputValue);
3612
4251
  }
3613
4252
  } else {
3614
4253
  isLoadingSetter(originalScope, false);
4254
+ cancelPreviousTimeout();
3615
4255
  resetMatches();
3616
4256
  }
3617
4257
 
@@ -3634,9 +4274,16 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3634
4274
  var candidateViewValue, emptyViewValue;
3635
4275
  var locals = {};
3636
4276
 
4277
+ // The validity may be set to false via $parsers (see above) if
4278
+ // the model is restricted to selected values. If the model
4279
+ // is set manually it is considered to be valid.
4280
+ if (!isEditable) {
4281
+ modelCtrl.$setValidity('editable', true);
4282
+ }
4283
+
3637
4284
  if (inputFormatter) {
3638
4285
 
3639
- locals['$model'] = modelValue;
4286
+ locals.$model = modelValue;
3640
4287
  return inputFormatter(originalScope, locals);
3641
4288
 
3642
4289
  } else {
@@ -3661,6 +4308,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3661
4308
  model = parserResult.modelMapper(originalScope, locals);
3662
4309
  $setModelValue(originalScope, model);
3663
4310
  modelCtrl.$setValidity('editable', true);
4311
+ modelCtrl.$setValidity('parse', true);
3664
4312
 
3665
4313
  onSelectCallback(originalScope, {
3666
4314
  $item: item,
@@ -3683,6 +4331,11 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3683
4331
  return;
3684
4332
  }
3685
4333
 
4334
+ // if there's nothing selected (i.e. focusFirst) and enter is hit, don't do anything
4335
+ if (scope.activeIdx == -1 && (evt.which === 13 || evt.which === 9)) {
4336
+ return;
4337
+ }
4338
+
3686
4339
  evt.preventDefault();
3687
4340
 
3688
4341
  if (evt.which === 40) {
@@ -3690,7 +4343,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3690
4343
  scope.$digest();
3691
4344
 
3692
4345
  } else if (evt.which === 38) {
3693
- scope.activeIdx = (scope.activeIdx ? scope.activeIdx : scope.matches.length) - 1;
4346
+ scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
3694
4347
  scope.$digest();
3695
4348
 
3696
4349
  } else if (evt.which === 13 || evt.which === 9) {
@@ -3722,10 +4375,16 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3722
4375
 
3723
4376
  originalScope.$on('$destroy', function(){
3724
4377
  $document.unbind('click', dismissClickHandler);
4378
+ if (appendToBody) {
4379
+ $popup.remove();
4380
+ }
4381
+ // Prevent jQuery cache memory leak
4382
+ popUpEl.remove();
3725
4383
  });
3726
4384
 
3727
4385
  var $popup = $compile(popUpEl)(scope);
3728
- if ( appendToBody ) {
4386
+
4387
+ if (appendToBody) {
3729
4388
  $document.find('body').append($popup);
3730
4389
  } else {
3731
4390
  element.after($popup);
@@ -3770,7 +4429,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3770
4429
  };
3771
4430
  })
3772
4431
 
3773
- .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) {
4432
+ .directive('typeaheadMatch', ['$templateRequest', '$compile', '$parse', function ($templateRequest, $compile, $parse) {
3774
4433
  return {
3775
4434
  restrict:'EA',
3776
4435
  scope:{
@@ -3780,8 +4439,10 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3780
4439
  },
3781
4440
  link:function (scope, element, attrs) {
3782
4441
  var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html';
3783
- $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){
3784
- element.replaceWith($compile(tplContent.trim())(scope));
4442
+ $templateRequest(tplUrl).then(function(tplContent) {
4443
+ $compile(tplContent.trim())(scope, function(clonedElement){
4444
+ element.replaceWith(clonedElement);
4445
+ });
3785
4446
  });
3786
4447
  }
3787
4448
  };
@@ -3797,3 +4458,4 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
3797
4458
  return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem;
3798
4459
  };
3799
4460
  });
4461
+ !angular.$$csp() && angular.element(document).find('head').prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>');