faalis 0.7.0

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