houston-core 0.8.4 → 0.9.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (225) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +72 -78
  4. data/app/assets/javascripts/houston/app/models/role.coffee +4 -0
  5. data/app/assets/javascripts/houston/app/views/nested_resources.coffee +44 -0
  6. data/app/assets/javascripts/houston/app/views/team_roles_view.coffee +10 -0
  7. data/app/assets/javascripts/houston/application.js +3 -1
  8. data/app/assets/javascripts/houston/core/ajax_helpers.coffee +26 -0
  9. data/app/assets/javascripts/houston/core/app.coffee +0 -45
  10. data/app/assets/javascripts/houston/core/errors.coffee +1 -12
  11. data/app/assets/javascripts/houston/core/handlebars_helpers.coffee +8 -70
  12. data/app/assets/javascripts/houston/core/jquery_extensions.coffee +0 -138
  13. data/app/assets/javascripts/houston/core/timeline_helpers.coffee +44 -0
  14. data/app/assets/javascripts/houston/core/uploader_helpers.coffee +99 -0
  15. data/app/assets/javascripts/houston/vendor.js +26 -9
  16. data/app/assets/stylesheets/houston/application/actions.scss +22 -0
  17. data/app/assets/stylesheets/houston/application/navigation.scss +2 -2
  18. data/app/assets/stylesheets/houston/application/{freight_train.css.scss → nested_resources.scss} +1 -0
  19. data/app/assets/stylesheets/houston/core/alerts.scss +0 -4
  20. data/app/assets/stylesheets/houston/core/timeline.scss +204 -0
  21. data/app/assets/templates/houston/teams/roles/index.hbs +1 -0
  22. data/app/assets/templates/houston/teams/roles/show.hbs +19 -0
  23. data/app/channels/events_channel.rb +1 -1
  24. data/app/concerns/houston/props.rb +3 -2
  25. data/app/controllers/actions_controller.rb +8 -3
  26. data/app/controllers/application_controller.rb +9 -12
  27. data/app/controllers/authorizations_controller.rb +41 -14
  28. data/app/controllers/errors_controller.rb +3 -3
  29. data/app/controllers/project_follows_controller.rb +23 -0
  30. data/app/controllers/project_options_controller.rb +1 -1
  31. data/app/controllers/user_options_controller.rb +1 -1
  32. data/app/helpers/actions_helper.rb +12 -0
  33. data/app/helpers/application_helper.rb +0 -10
  34. data/app/helpers/layout_helper.rb +20 -0
  35. data/app/helpers/markdown_helper.rb +2 -10
  36. data/app/helpers/navigation_helper.rb +5 -5
  37. data/app/helpers/project_helper.rb +6 -0
  38. data/app/helpers/url_helper.rb +4 -4
  39. data/app/helpers/view_extensions_helper.rb +20 -0
  40. data/app/models/action.rb +61 -44
  41. data/app/models/authorization.rb +55 -10
  42. data/app/models/follow.rb +6 -0
  43. data/app/models/persistent_trigger.rb +11 -1
  44. data/app/models/project.rb +5 -27
  45. data/app/models/user.rb +15 -59
  46. data/app/presenters/project_presenter.rb +2 -2
  47. data/app/views/actions/_actions.html.erb +8 -5
  48. data/app/views/actions/index.html.erb +1 -1
  49. data/app/views/actions/running.html.erb +9 -15
  50. data/app/views/actions/show.html.erb +6 -3
  51. data/app/views/actions/unqueued.html.erb +41 -0
  52. data/app/views/authorizations/_form.html.erb +28 -16
  53. data/app/views/authorizations/index.html.erb +9 -4
  54. data/app/views/{oauth/providers/edit.html.erb → authorizations/oauth2_callback.html.erb} +3 -2
  55. data/app/views/devise/sessions/new.html.erb +0 -8
  56. data/app/views/errors/index.html.erb +9 -5
  57. data/app/views/layouts/_navigation.html.erb +9 -0
  58. data/app/views/layouts/application.html.erb +11 -6
  59. data/app/views/layouts/dashboard.html.erb +9 -0
  60. data/app/views/projects/_form.html.erb +7 -18
  61. data/app/views/projects/_header.html.erb +2 -6
  62. data/app/views/projects/index.html.erb +4 -4
  63. data/app/views/teams/_form.html.erb +7 -17
  64. data/app/views/teams/index.html.erb +1 -1
  65. data/app/views/users/_form.html.erb +1 -38
  66. data/config/application.rb +8 -5
  67. data/config/initializers/devise.rb +0 -14
  68. data/config/initializers/secret_token.rb +8 -13
  69. data/config/routes.rb +12 -28
  70. data/db/migrate/20130706141443_drop_deprecated_project_roles.rb +5 -1
  71. data/db/migrate/20170118005958_remove_antecedents_from_versions_of_tickets.rb +1 -1
  72. data/db/migrate/20170130011016_drop_users_environments_subscribed_to.rb +9 -0
  73. data/db/migrate/20170205004452_drop_settings.rb +12 -0
  74. data/db/migrate/20170206002030_drop_extension_hstore.rb +9 -0
  75. data/db/migrate/20170206002732_drop_legacy_columns_from_users.rb +10 -0
  76. data/db/migrate/20170209022159_rename_projects_color_to_color_name.rb +5 -0
  77. data/db/migrate/20170213001453_change_providers_from_models_to_extensions.rb +27 -0
  78. data/db/migrate/20170215012012_add_props_to_authorizations.rb +5 -0
  79. data/db/migrate/20170216041034_add_user_to_persistent_triggers.rb +5 -0
  80. data/db/migrate/20170226201504_create_follows.rb +20 -0
  81. data/db/migrate/20170301014051_drop_name_from_authorizations.rb +9 -0
  82. data/db/migrate/20170307032041_add_created_at_to_actions.rb +11 -0
  83. data/db/migrate/20170307035755_allow_actions_started_at_to_be_null.rb +5 -0
  84. data/db/migrate/20170310024505_replace_authorizations_provider_name_with_type.rb +12 -0
  85. data/db/migrate/20170329030329_drop_consumer_tokens.rb +9 -0
  86. data/db/structure.sql +187 -212
  87. data/houston-core.gemspec +10 -13
  88. data/lib/houston/boot.rb +1 -4
  89. data/lib/houston/boot/actions.rb +24 -21
  90. data/lib/houston/boot/configuration.rb +46 -113
  91. data/lib/houston/boot/extensions.rb +54 -341
  92. data/lib/houston/boot/extensions/deprecated.rb +194 -0
  93. data/lib/houston/boot/extensions/dsl.rb +99 -0
  94. data/lib/houston/boot/extensions/events.rb +81 -0
  95. data/lib/houston/boot/extensions/features.rb +42 -0
  96. data/lib/houston/boot/extensions/layout.rb +70 -0
  97. data/lib/houston/boot/extensions/navigation.rb +42 -0
  98. data/lib/houston/boot/extensions/oauth.rb +62 -0
  99. data/lib/houston/boot/extensions/serializers.rb +29 -0
  100. data/lib/houston/boot/extensions/view.rb +34 -0
  101. data/lib/houston/boot/observer.rb +10 -5
  102. data/{app/models/oauth → lib/houston/boot}/provider.rb +7 -5
  103. data/lib/houston/boot/running_as.rb +0 -5
  104. data/lib/houston/boot/serializer.rb +12 -6
  105. data/lib/houston/boot/{active_record_serializer.rb → serializers/active_record_serializer.rb} +0 -2
  106. data/lib/houston/boot/{readonly_hash_serializer.rb → serializers/readonly_hash_serializer.rb} +0 -2
  107. data/lib/houston/boot/timer.rb +10 -0
  108. data/lib/houston/boot/triggers.rb +27 -8
  109. data/lib/houston/version.rb +1 -1
  110. data/templates/new-instance/.gitignore +0 -4
  111. data/templates/new-instance/config/main.rb +8 -10
  112. data/templates/new-module/test/dummy/houston.rb +1 -0
  113. data/test/acceptance/layout_test.rb +58 -0
  114. data/test/acceptance/updating_props_test.rb +72 -0
  115. data/test/support/config.rb +1 -0
  116. data/test/unit/extensions/events_extension_test.rb +33 -0
  117. data/test/unit/extensions/layout_extension_test.rb +74 -0
  118. data/test/unit/extensions/navigation_extension_test.rb +62 -0
  119. data/test/unit/extensions/oauth_extension_test.rb +91 -0
  120. data/test/unit/extensions/project_features_extension_test.rb +79 -0
  121. data/test/unit/extensions/serializers_extension_test.rb +47 -0
  122. data/test/unit/extensions/view_extension_test.rb +98 -0
  123. data/test/unit/models/actions_test.rb +11 -5
  124. data/test/unit/models/configuration_test.rb +0 -8
  125. data/test/unit/models/observer_test.rb +16 -0
  126. data/test/unit/models/persistent_trigger_test.rb +29 -2
  127. data/test/unit/models/serializer_test.rb +6 -0
  128. data/test/unit/models/timer_test.rb +88 -0
  129. metadata +87 -168
  130. data/app/assets/font/octicons.eot +0 -0
  131. data/app/assets/font/octicons.svg +0 -198
  132. data/app/assets/font/octicons.ttf +0 -0
  133. data/app/assets/font/octicons.woff +0 -0
  134. data/app/assets/font/roboto-black-webfont.eot +0 -0
  135. data/app/assets/font/roboto-black-webfont.svg +0 -675
  136. data/app/assets/font/roboto-black-webfont.ttf +0 -0
  137. data/app/assets/font/roboto-black-webfont.woff +0 -0
  138. data/app/assets/font/roboto-blackitalic-webfont.eot +0 -0
  139. data/app/assets/font/roboto-blackitalic-webfont.svg +0 -677
  140. data/app/assets/font/roboto-blackitalic-webfont.ttf +0 -0
  141. data/app/assets/font/roboto-blackitalic-webfont.woff +0 -0
  142. data/app/assets/font/roboto-bold-webfont.eot +0 -0
  143. data/app/assets/font/roboto-bold-webfont.svg +0 -675
  144. data/app/assets/font/roboto-bold-webfont.ttf +0 -0
  145. data/app/assets/font/roboto-bold-webfont.woff +0 -0
  146. data/app/assets/font/roboto-bolditalic-webfont.eot +0 -0
  147. data/app/assets/font/roboto-bolditalic-webfont.svg +0 -677
  148. data/app/assets/font/roboto-bolditalic-webfont.ttf +0 -0
  149. data/app/assets/font/roboto-bolditalic-webfont.woff +0 -0
  150. data/app/assets/font/roboto-italic-webfont.eot +0 -0
  151. data/app/assets/font/roboto-italic-webfont.svg +0 -668
  152. data/app/assets/font/roboto-italic-webfont.ttf +0 -0
  153. data/app/assets/font/roboto-italic-webfont.woff +0 -0
  154. data/app/assets/font/roboto-light-webfont.eot +0 -0
  155. data/app/assets/font/roboto-light-webfont.svg +0 -666
  156. data/app/assets/font/roboto-light-webfont.ttf +0 -0
  157. data/app/assets/font/roboto-light-webfont.woff +0 -0
  158. data/app/assets/font/roboto-lightitalic-webfont.eot +0 -0
  159. data/app/assets/font/roboto-lightitalic-webfont.svg +0 -668
  160. data/app/assets/font/roboto-lightitalic-webfont.ttf +0 -0
  161. data/app/assets/font/roboto-lightitalic-webfont.woff +0 -0
  162. data/app/assets/font/roboto-medium-webfont.eot +0 -0
  163. data/app/assets/font/roboto-medium-webfont.svg +0 -675
  164. data/app/assets/font/roboto-medium-webfont.ttf +0 -0
  165. data/app/assets/font/roboto-medium-webfont.woff +0 -0
  166. data/app/assets/font/roboto-mediumitalic-webfont.eot +0 -0
  167. data/app/assets/font/roboto-mediumitalic-webfont.svg +0 -677
  168. data/app/assets/font/roboto-mediumitalic-webfont.ttf +0 -0
  169. data/app/assets/font/roboto-mediumitalic-webfont.woff +0 -0
  170. data/app/assets/font/roboto-regular-webfont.eot +0 -0
  171. data/app/assets/font/roboto-regular-webfont.svg +0 -666
  172. data/app/assets/font/roboto-regular-webfont.ttf +0 -0
  173. data/app/assets/font/roboto-regular-webfont.woff +0 -0
  174. data/app/assets/font/roboto-thin-webfont.eot +0 -0
  175. data/app/assets/font/roboto-thin-webfont.svg +0 -666
  176. data/app/assets/font/roboto-thin-webfont.ttf +0 -0
  177. data/app/assets/font/roboto-thin-webfont.woff +0 -0
  178. data/app/assets/font/roboto-thinitalic-webfont.eot +0 -0
  179. data/app/assets/font/roboto-thinitalic-webfont.svg +0 -668
  180. data/app/assets/font/roboto-thinitalic-webfont.ttf +0 -0
  181. data/app/assets/font/roboto-thinitalic-webfont.woff +0 -0
  182. data/app/assets/images/bug-fixed-128.png +0 -0
  183. data/app/assets/images/bug-fixed-32.png +0 -0
  184. data/app/assets/images/bug-fixed-48.png +0 -0
  185. data/app/assets/images/bug-new-128.png +0 -0
  186. data/app/assets/images/bug-new-32.png +0 -0
  187. data/app/assets/images/bug-new-48.png +0 -0
  188. data/app/assets/images/bug-open-32.png +0 -0
  189. data/app/assets/images/bug-zero-128.png +0 -0
  190. data/app/assets/images/bug-zero-48.png +0 -0
  191. data/app/assets/images/drag-grip.png +0 -0
  192. data/app/assets/javascripts/houston/core/burndown_chart.coffee +0 -111
  193. data/app/assets/javascripts/houston/core/stacked_area_graph.coffee +0 -113
  194. data/app/assets/javascripts/houston/core/stacked_bar_graph.coffee +0 -108
  195. data/app/assets/stylesheets/houston/application/project_tiles.scss +0 -26
  196. data/app/assets/stylesheets/houston/application/tips.scss +0 -5
  197. data/app/assets/stylesheets/houston/core/octicons-icons.scss +0 -221
  198. data/app/assets/stylesheets/houston/core/octicons.scss.erb +0 -9
  199. data/app/assets/stylesheets/houston/core/roboto.scss.erb +0 -131
  200. data/app/concerns/historical_weekly_stats.rb +0 -15
  201. data/app/concerns/nosync.rb +0 -21
  202. data/app/controllers/oauth/providers_controller.rb +0 -45
  203. data/app/controllers/project_roles_controller.rb +0 -22
  204. data/app/controllers/settings_controller.rb +0 -14
  205. data/app/controllers/tester_bar_controller.rb +0 -12
  206. data/app/controllers/user_credentials_controller.rb +0 -24
  207. data/app/models/role.rb +0 -33
  208. data/app/models/setting.rb +0 -10
  209. data/app/models/settings.rb +0 -38
  210. data/app/models/slackdown.rb +0 -23
  211. data/app/models/user_credentials.rb +0 -27
  212. data/app/views/errors/_actions.html.erb +0 -17
  213. data/app/views/layouts/_tester_bar.html.erb +0 -6
  214. data/app/views/layouts/minimal.html.erb +0 -50
  215. data/app/views/layouts/naked.html.erb +0 -47
  216. data/app/views/layouts/naked_dashboard.html.erb +0 -50
  217. data/app/views/oauth/providers/_form.html.erb +0 -54
  218. data/app/views/oauth/providers/index.html.erb +0 -41
  219. data/app/views/oauth/providers/new.html.erb +0 -7
  220. data/config/initializers/add_navigation_renderers.rb +0 -5
  221. data/config/initializers/vestal_versions.rb +0 -9
  222. data/db/migrate/20130519163615_create_user_credentials.rb +0 -18
  223. data/lib/houston/boot/events.rb +0 -10
  224. data/lib/tasks/keypair.rake +0 -17
  225. data/vendor/assets/javascripts/jquery.pjax.js +0 -817
@@ -1,17 +0,0 @@
1
- <% @actions.each do |action| %>
2
- <tr class="action-error" data-timestamp="<%= action.finished_at.iso8601 %>">
3
- <td class="table-margin"></td>
4
- <td class="action-time"><%= format_time action.finished_at %></td>
5
- <td class="action-name"><%= link_to action[:name], action_path(slug: action[:name]) %></td>
6
- <td class="action-trigger"><%= action.trigger %></td>
7
- <td class="action-params"><%= format_action_params action.params %></td>
8
- <td class="action-error-message">
9
- <% unless action.error.type.blank? %>
10
- <b><%= action.error.type %></b>:
11
- <% end %>
12
- <%= action.error.message %>
13
- </td>
14
- <td class="action-retry"><%= button_to "Retry", retry_action_path(action), class: "btn-retry btn btn-mini btn-default" %></td>
15
- <td class="table-margin"></td>
16
- </tr>
17
- <% end %>
@@ -1,6 +0,0 @@
1
- <div style="position: fixed; left: 0; right: 0; bottom: 0; height: 42px; line-height: 36px; background: black; padding-left: 4px; z-index: 100;">
2
- <form action="/tester_bar/login_as">
3
- <%= select_tag "email", options_for_select(User.unretired.map { |u| [u.role == "Member" ? u.name : "#{u.name} (#{u.role})", u.email] }, current_user.try(:email)), :style => "margin-bottom: 0" %>
4
- <button class="btn btn-primary" type="submit" title="Log in as any user">Login</button>
5
- </form>
6
- </div>
@@ -1,50 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title><%= title %></title>
7
- <%= csrf_meta_tags %>
8
- <%= action_cable_meta_tag %>
9
- <meta name="relative_url_root" content="<%= main_app.root_url %>" />
10
- <meta name="revision" content="<%= revision %>" />
11
- <meta name="env" content="<%= Rails.env %>" />
12
- <%= yield :meta %>
13
-
14
- <!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
15
- <!--[if lt IE 9]>
16
- <script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
17
- <![endif]-->
18
-
19
- <!-- Le styles -->
20
- <%= stylesheet_link_tag "houston/vendor", media: "all" %>
21
- <%= stylesheet_link_tag "houston/application", media: "all" %>
22
- <%= stylesheet_link_tag "houston/print", media: "print" %>
23
- <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
24
- <%= yield :stylesheets %><%# so that Engines can hook in and add styles %>
25
-
26
- <!-- Le fav and touch icons -->
27
- <% unless unfurling? %>
28
- <link rel="icon" type="image/x-icon" href="<%= ENV['RAILS_RELATIVE_URL_ROOT'] %>/favicon.png" />
29
- <% end %>
30
- </head>
31
- <body>
32
-
33
- <%= render "layouts/navigation" %>
34
-
35
- <div class="container">
36
- <%= yield -%>
37
-
38
- <%= render partial: "layouts/tester_bar" if Rails.env.development? -%>
39
- </div> <!-- /container -->
40
-
41
- <!-- Le javascript
42
- ================================================== -->
43
- <!-- Placed at the end of the document so the pages load faster -->
44
- <%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" %>
45
- <%= javascript_include_tag "houston/vendor" %>
46
- <%= javascript_include_tag "houston/application" %>
47
- <%= yield :javascripts %><%# so that Engines can hook in and add scripts %>
48
- <%= google_analytics_script_tag %>
49
- </body>
50
- </html>
@@ -1,47 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title><%= title %></title>
7
- <%= csrf_meta_tags %>
8
- <%= action_cable_meta_tag %>
9
- <meta name="relative_url_root" content="<%= main_app.root_url %>" />
10
- <meta name="revision" content="<%= revision %>" />
11
- <meta name="env" content="<%= Rails.env %>" />
12
- <%= yield :meta %>
13
-
14
- <!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
15
- <!--[if lt IE 9]>
16
- <script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
17
- <![endif]-->
18
-
19
- <!-- Le styles -->
20
- <%= stylesheet_link_tag "houston/vendor", media: "all" %>
21
- <%= stylesheet_link_tag "houston/application", media: "all" %>
22
- <%= stylesheet_link_tag "houston/print", media: "print" %>
23
- <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
24
- <%= yield :stylesheets %><%# so that Engines can hook in and add styles %>
25
-
26
- <!-- Le fav and touch icons -->
27
- <% unless unfurling? %>
28
- <link rel="icon" type="image/x-icon" href="<%= ENV['RAILS_RELATIVE_URL_ROOT'] %>/favicon.png" />
29
- <% end %>
30
- </head>
31
- <body>
32
- <div class="container">
33
- <%= yield -%>
34
-
35
- <%= render partial: "layouts/tester_bar" if Rails.env.development? -%>
36
- </div> <!-- /container -->
37
-
38
- <!-- Le javascript
39
- ================================================== -->
40
- <!-- Placed at the end of the document so the pages load faster -->
41
- <%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" %>
42
- <%= javascript_include_tag "houston/vendor" %>
43
- <%= javascript_include_tag "houston/application" %>
44
- <%= yield :javascripts %><%# so that Engines can hook in and add scripts %>
45
- <%= google_analytics_script_tag %>
46
- </body>
47
- </html>
@@ -1,50 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title><%= title %></title>
7
- <%= csrf_meta_tags %>
8
- <%= action_cable_meta_tag %>
9
- <meta name="relative_url_root" content="<%= main_app.root_url %>" />
10
- <meta name="revision" content="<%= revision %>" />
11
-
12
- <!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
13
- <!--[if lt IE 9]>
14
- <script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
15
- <![endif]-->
16
-
17
- <!-- Le styles -->
18
- <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
19
- <%= stylesheet_link_tag "houston/vendor", media: "all" %>
20
- <%= stylesheet_link_tag "houston/dashboard", media: "all" %>
21
- <%= yield :stylesheets %><%# so that Engines can hook in and add styles %>
22
-
23
- <!-- Le fav and touch icons -->
24
- <% unless unfurling? %>
25
- <link rel="icon" type="image/x-icon" href="<%= ENV['RAILS_RELATIVE_URL_ROOT'] %>/favicon.png" />
26
- <% end %>
27
- </head>
28
- <body class="dashboard">
29
- <div id="container" <% if params[:zoom].to_f > 0 %> style="transform: scale(<%= params[:zoom].to_f %>); transform-origin: 50% 0; -webkit-transform: scale(<%= params[:zoom].to_f %>); -webkit-transform-origin: 50% 0; -moz-transform: scale(<%= params[:zoom].to_f %>); -moz-transform-origin: 50% 0;" <% end %>>
30
- <%= yield -%>
31
- </div>
32
-
33
- <!-- Le javascript
34
- ================================================== -->
35
- <!-- Placed at the end of the document so the pages load faster -->
36
- <%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" %>
37
- <%= javascript_include_tag "houston/vendor" %>
38
- <%= javascript_include_tag "houston/dashboard" %>
39
- <%= yield :javascripts %><%# so that Engines can hook in and add scripts %>
40
- <%= google_analytics_script_tag %>
41
-
42
- <!--
43
- Play silence continually
44
- This keeps the audio channel open over HDMI (at least on
45
- our Raspberry PIs). Otherwise the first second of a sound
46
- effect is swallowed.
47
- -->
48
- <audio src="/sounds/silence.mp3" autoplay loop></audio>
49
- </body>
50
- </html>
@@ -1,54 +0,0 @@
1
- <%= form_for @provider, html: {class: "form-horizontal"} do |f| %>
2
- <fieldset>
3
- <div class="control-group">
4
- <%= f.label :name, class: "control-label" %>
5
- <div class="controls">
6
- <%= f.text_field :name, class: "text_field" %>
7
- </div>
8
- </div>
9
-
10
- <div class="control-group">
11
- <%= f.label :site, class: "control-label" %>
12
- <div class="controls">
13
- <%= f.text_field :site, class: "text_field" %>
14
- </div>
15
- </div>
16
-
17
- <div class="control-group">
18
- <%= f.label :authorize_path, class: "control-label" %>
19
- <div class="controls">
20
- <%= f.text_field :authorize_path, class: "text_field" %>
21
- </div>
22
- </div>
23
-
24
- <div class="control-group">
25
- <%= f.label :token_path, class: "control-label" %>
26
- <div class="controls">
27
- <%= f.text_field :token_path, class: "text_field" %>
28
- </div>
29
- </div>
30
- </fieldset>
31
-
32
- <hr />
33
-
34
- <fieldset>
35
- <div class="control-group">
36
- <%= f.label :client_id, class: "control-label" %>
37
- <div class="controls">
38
- <%= f.text_field :client_id, class: "text_field" %>
39
- </div>
40
- </div>
41
-
42
- <div class="control-group">
43
- <%= f.label :client_secret, class: "control-label" %>
44
- <div class="controls">
45
- <%= f.text_field :client_secret, class: "text_field" %>
46
- </div>
47
- </div>
48
- </fieldset>
49
-
50
- <div class="form-actions">
51
- <%= f.submit nil, class: "btn btn-primary" %>
52
- <%= link_to "Cancel", oauth_providers_path, class: "btn" %>
53
- </div>
54
- <% end %>
@@ -1,41 +0,0 @@
1
- <% content_for :title do %>
2
- <h1 class="project-banner space-below">
3
- Providers
4
-
5
- <%= link_to "New Provider", new_oauth_provider_path, class: "btn btn-primary" if can?(:create, Oauth::Provider) %>
6
- </h1>
7
- <% end %>
8
-
9
- <div class="nomargin">
10
- <table id="providers" class="table table-sortable table-striped">
11
- <thead>
12
- <tr>
13
- <td class="table-margin"></td>
14
- <th class="provider-name">Name</th>
15
- <th class="provider-site">Site</th>
16
- <th class="provider-client-id">Client ID</th>
17
- <td class="table-margin"></td>
18
- </tr>
19
- </thead>
20
- <tbody>
21
- <% @providers.each do |provider| %>
22
- <tr class="provider">
23
- <td class="table-margin"></td>
24
- <td class="provider-name"><%= link_to provider.name, edit_oauth_provider_path(provider) %></td>
25
- <td class="provider-site"><%= provider.site %></td>
26
- <td class="provider-client-id"><%= provider.client_id %></td>
27
- <td class="table-margin"></td>
28
- </tr>
29
- <% end %>
30
- </tbody>
31
- </table>
32
- </div>
33
-
34
-
35
- <% content_for :javascripts do %>
36
- <script type="text/javascript">
37
- $(function() {
38
- $('#providers').tablesorter();
39
- });
40
- </script>
41
- <% end %>
@@ -1,7 +0,0 @@
1
- <% content_for :title do %>
2
- <h1 class="project-banner space-below">
3
- New Provider
4
- </h1>
5
- <% end %>
6
-
7
- <%= render "form" %>
@@ -1,5 +0,0 @@
1
- Houston.add_project_feature :settings do
2
- name "Settings"
3
- path { |project| Houston::Application.routes.url_helpers.edit_project_path(project) }
4
- ability { |ability, project| ability.can?(:update, project) }
5
- end
@@ -1,9 +0,0 @@
1
- VestalVersions.configure do |config|
2
- # Place any global options here. For example, in order to specify your own version model to use
3
- # throughout the application, simply specify:
4
- #
5
- # config.class_name = "MyCustomVersion"
6
- #
7
- # Any options passed to the "versioned" method in the model itself will override this global
8
- # configuration.
9
- end
@@ -1,18 +0,0 @@
1
- class CreateUserCredentials < ActiveRecord::Migration
2
- def up
3
- create_table :user_credentials do |t|
4
- t.references :user
5
- t.string :service
6
- t.string :login
7
- t.binary :password
8
- t.binary :password_key
9
- t.binary :password_iv
10
-
11
- t.timestamps
12
- end
13
- end
14
-
15
- def down
16
- drop_table :user_credentials
17
- end
18
- end
@@ -1,10 +0,0 @@
1
- Houston.register_events {{
2
-
3
- "daemon:{type}:start" => desc("Daemon {type} has started"),
4
- "daemon:{type}:restart" => desc("Daemon {type} has restarted"),
5
- "daemon:{type}:stop" => desc("Daemon {type} has stopped"),
6
-
7
- "hooks:{type}" => params("params").desc("/hooks/{type} was invoked"),
8
- "hooks:project:{type}" => params("project", "params").desc("/hooks/project/:slug/{type} was invoked")
9
-
10
- }}
@@ -1,17 +0,0 @@
1
- require "shellwords"
2
-
3
- namespace :keypair do
4
- task :generate do |t|
5
- if File.exists?(Houston.config.keypair)
6
- puts "#{Houston.config.keypair} exists"
7
- exit
8
- end
9
-
10
- tmp = Houston.root.to_s
11
-
12
- `openssl genrsa -des3 -passout pass:#{Shellwords.escape Houston.config.passphrase} -out #{tmp}/config/private.pem 2048`
13
- `openssl rsa -in #{tmp}/config/private.pem -passin pass:#{Shellwords.escape Houston.config.passphrase} -out #{tmp}/config/public.pem -outform PEM -pubout`
14
- `cat #{tmp}/config/private.pem #{tmp}/config/public.pem >> #{Houston.config.keypair}`
15
- `rm #{tmp}/config/private.pem #{tmp}/config/public.pem`
16
- end
17
- end
@@ -1,817 +0,0 @@
1
- // jquery.pjax.js
2
- // copyright chris wanstrath
3
- // https://github.com/defunkt/jquery-pjax
4
-
5
- (function($){
6
-
7
- // When called on a container with a selector, fetches the href with
8
- // ajax into the container or with the data-pjax attribute on the link
9
- // itself.
10
- //
11
- // Tries to make sure the back button and ctrl+click work the way
12
- // you'd expect.
13
- //
14
- // Exported as $.fn.pjax
15
- //
16
- // Accepts a jQuery ajax options object that may include these
17
- // pjax specific options:
18
- //
19
- //
20
- // container - Where to stick the response body. Usually a String selector.
21
- // $(container).html(xhr.responseBody)
22
- // (default: current jquery context)
23
- // push - Whether to pushState the URL. Defaults to true (of course).
24
- // replace - Want to use replaceState instead? That's cool.
25
- //
26
- // For convenience the second parameter can be either the container or
27
- // the options object.
28
- //
29
- // Returns the jQuery object
30
- function fnPjax(selector, container, options) {
31
- var context = this
32
- return this.on('click.pjax', selector, function(event) {
33
- var opts = $.extend({}, optionsFor(container, options))
34
- if (!opts.container)
35
- opts.container = $(this).attr('data-pjax') || context
36
- handleClick(event, opts)
37
- })
38
- }
39
-
40
- // Public: pjax on click handler
41
- //
42
- // Exported as $.pjax.click.
43
- //
44
- // event - "click" jQuery.Event
45
- // options - pjax options
46
- //
47
- // Examples
48
- //
49
- // $(document).on('click', 'a', $.pjax.click)
50
- // // is the same as
51
- // $(document).pjax('a')
52
- //
53
- // $(document).on('click', 'a', function(event) {
54
- // var container = $(this).closest('[data-pjax-container]')
55
- // $.pjax.click(event, container)
56
- // })
57
- //
58
- // Returns nothing.
59
- function handleClick(event, container, options) {
60
- options = optionsFor(container, options)
61
-
62
- var link = event.currentTarget
63
-
64
- if (link.tagName.toUpperCase() !== 'A')
65
- throw "$.fn.pjax or $.pjax.click requires an anchor element"
66
-
67
- // Middle click, cmd click, and ctrl click should open
68
- // links in a new tab as normal.
69
- if ( event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey )
70
- return
71
-
72
- // Ignore cross origin links
73
- if ( location.protocol !== link.protocol || location.hostname !== link.hostname )
74
- return
75
-
76
- // Ignore anchors on the same page
77
- if (link.hash && link.href.replace(link.hash, '') ===
78
- location.href.replace(location.hash, ''))
79
- return
80
-
81
- // Ignore empty anchor "foo.html#"
82
- if (link.href === location.href + '#')
83
- return
84
-
85
- var defaults = {
86
- url: link.href,
87
- container: $(link).attr('data-pjax'),
88
- target: link,
89
- fragment: null
90
- }
91
-
92
- var opts = $.extend({}, defaults, options)
93
- var clickEvent = $.Event('pjax:click')
94
- $(link).trigger(clickEvent, [opts])
95
-
96
- if (!clickEvent.isDefaultPrevented()) {
97
- pjax(opts)
98
- event.preventDefault()
99
- }
100
- }
101
-
102
- // Public: pjax on form submit handler
103
- //
104
- // Exported as $.pjax.submit
105
- //
106
- // event - "click" jQuery.Event
107
- // options - pjax options
108
- //
109
- // Examples
110
- //
111
- // $(document).on('submit', 'form', function(event) {
112
- // var container = $(this).closest('[data-pjax-container]')
113
- // $.pjax.submit(event, container)
114
- // })
115
- //
116
- // Returns nothing.
117
- function handleSubmit(event, container, options) {
118
- options = optionsFor(container, options)
119
-
120
- var form = event.currentTarget
121
-
122
- if (form.tagName.toUpperCase() !== 'FORM')
123
- throw "$.pjax.submit requires a form element"
124
-
125
- var defaults = {
126
- type: form.method.toUpperCase(),
127
- url: form.action,
128
- data: $(form).serializeArray(),
129
- container: $(form).attr('data-pjax'),
130
- target: form,
131
- fragment: null
132
- }
133
-
134
- pjax($.extend({}, defaults, options))
135
-
136
- event.preventDefault()
137
- }
138
-
139
- // Loads a URL with ajax, puts the response body inside a container,
140
- // then pushState()'s the loaded URL.
141
- //
142
- // Works just like $.ajax in that it accepts a jQuery ajax
143
- // settings object (with keys like url, type, data, etc).
144
- //
145
- // Accepts these extra keys:
146
- //
147
- // container - Where to stick the response body.
148
- // $(container).html(xhr.responseBody)
149
- // push - Whether to pushState the URL. Defaults to true (of course).
150
- // replace - Want to use replaceState instead? That's cool.
151
- //
152
- // Use it just like $.ajax:
153
- //
154
- // var xhr = $.pjax({ url: this.href, container: '#main' })
155
- // console.log( xhr.readyState )
156
- //
157
- // Returns whatever $.ajax returns.
158
- function pjax(options) {
159
- options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)
160
-
161
- if ($.isFunction(options.url)) {
162
- options.url = options.url()
163
- }
164
-
165
- var target = options.target
166
-
167
- var hash = parseURL(options.url).hash
168
-
169
- var context = options.context = findContainerFor(options.container)
170
-
171
- // We want the browser to maintain two separate internal caches: one
172
- // for pjax'd partial page loads and one for normal page loads.
173
- // Without adding this secret parameter, some browsers will often
174
- // confuse the two.
175
- if (!options.data) options.data = {}
176
- options.data._pjax = context.selector
177
-
178
- function fire(type, args) {
179
- var event = $.Event(type, { relatedTarget: target })
180
- context.trigger(event, args)
181
- return !event.isDefaultPrevented()
182
- }
183
-
184
- var timeoutTimer
185
-
186
- options.beforeSend = function(xhr, settings) {
187
- // No timeout for non-GET requests
188
- // Its not safe to request the resource again with a fallback method.
189
- if (settings.type !== 'GET') {
190
- settings.timeout = 0
191
- }
192
-
193
- xhr.setRequestHeader('X-PJAX', 'true')
194
- xhr.setRequestHeader('X-PJAX-Container', context.selector)
195
-
196
- if (!fire('pjax:beforeSend', [xhr, settings]))
197
- return false
198
-
199
- if (settings.timeout > 0) {
200
- timeoutTimer = setTimeout(function() {
201
- if (fire('pjax:timeout', [xhr, options]))
202
- xhr.abort('timeout')
203
- }, settings.timeout)
204
-
205
- // Clear timeout setting so jquerys internal timeout isn't invoked
206
- settings.timeout = 0
207
- }
208
-
209
- options.requestUrl = parseURL(settings.url).href
210
- }
211
-
212
- options.complete = function(xhr, textStatus) {
213
- if (timeoutTimer)
214
- clearTimeout(timeoutTimer)
215
-
216
- fire('pjax:complete', [xhr, textStatus, options])
217
-
218
- fire('pjax:end', [xhr, options])
219
- }
220
-
221
- options.error = function(xhr, textStatus, errorThrown) {
222
- var container = extractContainer("", xhr, options)
223
-
224
- var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])
225
- if (options.type == 'GET' && textStatus !== 'abort' && allowed) {
226
- locationReplace(container.url)
227
- }
228
- }
229
-
230
- options.success = function(data, status, xhr) {
231
- // If $.pjax.defaults.version is a function, invoke it first.
232
- // Otherwise it can be a static string.
233
- var currentVersion = (typeof $.pjax.defaults.version === 'function') ?
234
- $.pjax.defaults.version() :
235
- $.pjax.defaults.version
236
-
237
- var latestVersion = xhr.getResponseHeader('X-PJAX-Version')
238
-
239
- var container = extractContainer(data, xhr, options)
240
-
241
- // If there is a layout version mismatch, hard load the new url
242
- if (currentVersion && latestVersion && currentVersion !== latestVersion) {
243
- locationReplace(container.url)
244
- return
245
- }
246
-
247
- // If the new response is missing a body, hard load the page
248
- if (!container.contents) {
249
- locationReplace(container.url)
250
- return
251
- }
252
-
253
- pjax.state = {
254
- id: options.id || uniqueId(),
255
- url: container.url,
256
- title: container.title,
257
- container: context.selector,
258
- fragment: options.fragment,
259
- timeout: options.timeout
260
- }
261
-
262
- if (options.push || options.replace) {
263
- window.history.replaceState(pjax.state, container.title, container.url)
264
- }
265
-
266
- if (container.title) document.title = container.title
267
- context.html(container.contents)
268
- executeScriptTags(container.scripts)
269
-
270
- // Scroll to top by default
271
- if (typeof options.scrollTo === 'number')
272
- $(window).scrollTop(options.scrollTo)
273
-
274
- // If the URL has a hash in it, make sure the browser
275
- // knows to navigate to the hash.
276
- if ( hash !== '' ) {
277
- // Avoid using simple hash set here. Will add another history
278
- // entry. Replace the url with replaceState and scroll to target
279
- // by hand.
280
- //
281
- // window.location.hash = hash
282
- var url = parseURL(container.url)
283
- url.hash = hash
284
-
285
- pjax.state.url = url.href
286
- window.history.replaceState(pjax.state, container.title, url.href)
287
-
288
- var target = $(url.hash)
289
- if (target.length) $(window).scrollTop(target.offset().top)
290
- }
291
-
292
- fire('pjax:success', [data, status, xhr, options])
293
- }
294
-
295
-
296
- // Initialize pjax.state for the initial page load. Assume we're
297
- // using the container and options of the link we're loading for the
298
- // back button to the initial page. This ensures good back button
299
- // behavior.
300
- if (!pjax.state) {
301
- pjax.state = {
302
- id: uniqueId(),
303
- url: window.location.href,
304
- title: document.title,
305
- container: context.selector,
306
- fragment: options.fragment,
307
- timeout: options.timeout
308
- }
309
- window.history.replaceState(pjax.state, document.title)
310
- }
311
-
312
- // Cancel the current request if we're already pjaxing
313
- var xhr = pjax.xhr
314
- if ( xhr && xhr.readyState < 4) {
315
- xhr.onreadystatechange = $.noop
316
- xhr.abort()
317
- }
318
-
319
- pjax.options = options
320
- var xhr = pjax.xhr = $.ajax(options)
321
-
322
- if (xhr.readyState > 0) {
323
- if (options.push && !options.replace) {
324
- // Cache current container element before replacing it
325
- cachePush(pjax.state.id, context.clone().contents())
326
-
327
- window.history.pushState(null, "", stripPjaxParam(options.requestUrl))
328
- }
329
-
330
- fire('pjax:start', [xhr, options])
331
- fire('pjax:send', [xhr, options])
332
- }
333
-
334
- return pjax.xhr
335
- }
336
-
337
- // Public: Reload current page with pjax.
338
- //
339
- // Returns whatever $.pjax returns.
340
- function pjaxReload(container, options) {
341
- var defaults = {
342
- url: window.location.href,
343
- push: false,
344
- replace: true,
345
- scrollTo: false
346
- }
347
-
348
- return pjax($.extend(defaults, optionsFor(container, options)))
349
- }
350
-
351
- // Internal: Hard replace current state with url.
352
- //
353
- // Work for around WebKit
354
- // https://bugs.webkit.org/show_bug.cgi?id=93506
355
- //
356
- // Returns nothing.
357
- function locationReplace(url) {
358
- window.history.replaceState(null, "", "#")
359
- window.location.replace(url)
360
- }
361
-
362
-
363
- var initialPop = true
364
- var initialURL = window.location.href
365
- var initialState = window.history.state
366
-
367
- // Initialize $.pjax.state if possible
368
- // Happens when reloading a page and coming forward from a different
369
- // session history.
370
- if (initialState && initialState.container) {
371
- pjax.state = initialState
372
- }
373
-
374
- // popstate handler takes care of the back and forward buttons
375
- //
376
- // You probably shouldn't use pjax on pages with other pushState
377
- // stuff yet.
378
- function onPjaxPopstate(event) {
379
- var state = event.state
380
-
381
- if (state && state.container) {
382
- // When coming forward from a seperate history session, will get an
383
- // initial pop with a state we are already at. Skip reloading the current
384
- // page.
385
- if (initialPop && initialURL == state.url) return
386
-
387
- var container = $(state.container)
388
- if (container.length) {
389
- var direction, contents = cacheMapping[state.id]
390
-
391
- if (pjax.state) {
392
- // Since state ids always increase, we can deduce the history
393
- // direction from the previous state.
394
- direction = pjax.state.id < state.id ? 'forward' : 'back'
395
-
396
- // Cache current container before replacement and inform the
397
- // cache which direction the history shifted.
398
- cachePop(direction, pjax.state.id, container.clone().contents())
399
- }
400
-
401
- var popstateEvent = $.Event('pjax:popstate', {
402
- state: state,
403
- direction: direction
404
- })
405
- container.trigger(popstateEvent)
406
-
407
- var options = {
408
- id: state.id,
409
- url: state.url,
410
- container: container,
411
- push: false,
412
- fragment: state.fragment,
413
- timeout: state.timeout,
414
- scrollTo: false
415
- }
416
-
417
- if (contents) {
418
- container.trigger('pjax:start', [null, options])
419
-
420
- if (state.title) document.title = state.title
421
- container.html(contents)
422
- pjax.state = state
423
-
424
- container.trigger('pjax:end', [null, options])
425
- } else {
426
- pjax(options)
427
- }
428
-
429
- // Force reflow/relayout before the browser tries to restore the
430
- // scroll position.
431
- container[0].offsetHeight
432
- } else {
433
- locationReplace(location.href)
434
- }
435
- }
436
- initialPop = false
437
- }
438
-
439
- // Fallback version of main pjax function for browsers that don't
440
- // support pushState.
441
- //
442
- // Returns nothing since it retriggers a hard form submission.
443
- function fallbackPjax(options) {
444
- var url = $.isFunction(options.url) ? options.url() : options.url,
445
- method = options.type ? options.type.toUpperCase() : 'GET'
446
-
447
- var form = $('<form>', {
448
- method: method === 'GET' ? 'GET' : 'POST',
449
- action: url,
450
- style: 'display:none'
451
- })
452
-
453
- if (method !== 'GET' && method !== 'POST') {
454
- form.append($('<input>', {
455
- type: 'hidden',
456
- name: '_method',
457
- value: method.toLowerCase()
458
- }))
459
- }
460
-
461
- var data = options.data
462
- if (typeof data === 'string') {
463
- $.each(data.split('&'), function(index, value) {
464
- var pair = value.split('=')
465
- form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
466
- })
467
- } else if (typeof data === 'object') {
468
- for (key in data)
469
- form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
470
- }
471
-
472
- $(document.body).append(form)
473
- form.submit()
474
- }
475
-
476
- // Internal: Generate unique id for state object.
477
- //
478
- // Use a timestamp instead of a counter since ids should still be
479
- // unique across page loads.
480
- //
481
- // Returns Number.
482
- function uniqueId() {
483
- return (new Date).getTime()
484
- }
485
-
486
- // Internal: Strips _pjax param from url
487
- //
488
- // url - String
489
- //
490
- // Returns String.
491
- function stripPjaxParam(url) {
492
- return url
493
- .replace(/\?_pjax=[^&]+&?/, '?')
494
- .replace(/_pjax=[^&]+&?/, '')
495
- .replace(/[\?&]$/, '')
496
- }
497
-
498
- // Internal: Parse URL components and returns a Locationish object.
499
- //
500
- // url - String URL
501
- //
502
- // Returns HTMLAnchorElement that acts like Location.
503
- function parseURL(url) {
504
- var a = document.createElement('a')
505
- a.href = url
506
- return a
507
- }
508
-
509
- // Internal: Build options Object for arguments.
510
- //
511
- // For convenience the first parameter can be either the container or
512
- // the options object.
513
- //
514
- // Examples
515
- //
516
- // optionsFor('#container')
517
- // // => {container: '#container'}
518
- //
519
- // optionsFor('#container', {push: true})
520
- // // => {container: '#container', push: true}
521
- //
522
- // optionsFor({container: '#container', push: true})
523
- // // => {container: '#container', push: true}
524
- //
525
- // Returns options Object.
526
- function optionsFor(container, options) {
527
- // Both container and options
528
- if ( container && options )
529
- options.container = container
530
-
531
- // First argument is options Object
532
- else if ( $.isPlainObject(container) )
533
- options = container
534
-
535
- // Only container
536
- else
537
- options = {container: container}
538
-
539
- // Find and validate container
540
- if (options.container)
541
- options.container = findContainerFor(options.container)
542
-
543
- return options
544
- }
545
-
546
- // Internal: Find container element for a variety of inputs.
547
- //
548
- // Because we can't persist elements using the history API, we must be
549
- // able to find a String selector that will consistently find the Element.
550
- //
551
- // container - A selector String, jQuery object, or DOM Element.
552
- //
553
- // Returns a jQuery object whose context is `document` and has a selector.
554
- function findContainerFor(container) {
555
- container = $(container)
556
-
557
- if ( !container.length ) {
558
- throw "no pjax container for " + container.selector
559
- } else if ( container.selector !== '' && container.context === document ) {
560
- return container
561
- } else if ( container.attr('id') ) {
562
- return $('#' + container.attr('id'))
563
- } else {
564
- throw "cant get selector for pjax container!"
565
- }
566
- }
567
-
568
- // Internal: Filter and find all elements matching the selector.
569
- //
570
- // Where $.fn.find only matches descendants, findAll will test all the
571
- // top level elements in the jQuery object as well.
572
- //
573
- // elems - jQuery object of Elements
574
- // selector - String selector to match
575
- //
576
- // Returns a jQuery object.
577
- function findAll(elems, selector) {
578
- return elems.filter(selector).add(elems.find(selector));
579
- }
580
-
581
- function parseHTML(html) {
582
- return $.parseHTML(html, document, true)
583
- }
584
-
585
- // Internal: Extracts container and metadata from response.
586
- //
587
- // 1. Extracts X-PJAX-URL header if set
588
- // 2. Extracts inline <title> tags
589
- // 3. Builds response Element and extracts fragment if set
590
- //
591
- // data - String response data
592
- // xhr - XHR response
593
- // options - pjax options Object
594
- //
595
- // Returns an Object with url, title, and contents keys.
596
- function extractContainer(data, xhr, options) {
597
- var obj = {}
598
-
599
- // Prefer X-PJAX-URL header if it was set, otherwise fallback to
600
- // using the original requested url.
601
- obj.url = stripPjaxParam(xhr.getResponseHeader('X-PJAX-URL') || options.requestUrl)
602
-
603
- // Attempt to parse response html into elements
604
- if (/<html/i.test(data)) {
605
- var $head = $(parseHTML(data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0]))
606
- var $body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]))
607
- } else {
608
- var $head = $body = $(parseHTML(data))
609
- }
610
-
611
- // If response data is empty, return fast
612
- if ($body.length === 0)
613
- return obj
614
-
615
- // If there's a <title> tag in the header, use it as
616
- // the page's title.
617
- obj.title = findAll($head, 'title').last().text()
618
-
619
- if (options.fragment) {
620
- // If they specified a fragment, look for it in the response
621
- // and pull it out.
622
- if (options.fragment === 'body') {
623
- var $fragment = $body
624
- } else {
625
- var $fragment = findAll($body, options.fragment).first()
626
- }
627
-
628
- if ($fragment.length) {
629
- obj.contents = $fragment.contents()
630
-
631
- // If there's no title, look for data-title and title attributes
632
- // on the fragment
633
- if (!obj.title)
634
- obj.title = $fragment.attr('title') || $fragment.data('title')
635
- }
636
-
637
- } else if (!/<html/i.test(data)) {
638
- obj.contents = $body
639
- }
640
-
641
- // Clean up any <title> tags
642
- if (obj.contents) {
643
- // Remove any parent title elements
644
- obj.contents = obj.contents.not(function() { return $(this).is('title') })
645
-
646
- // Then scrub any titles from their descendents
647
- obj.contents.find('title').remove()
648
-
649
- // Gather all script[src] elements
650
- obj.scripts = findAll(obj.contents, 'script[src]').remove()
651
- obj.contents = obj.contents.not(obj.scripts)
652
- }
653
-
654
- // Trim any whitespace off the title
655
- if (obj.title) obj.title = $.trim(obj.title)
656
-
657
- return obj
658
- }
659
-
660
- // Load an execute scripts using standard script request.
661
- //
662
- // Avoids jQuery's traditional $.getScript which does a XHR request and
663
- // globalEval.
664
- //
665
- // scripts - jQuery object of script Elements
666
- //
667
- // Returns nothing.
668
- function executeScriptTags(scripts) {
669
- if (!scripts) return
670
-
671
- var existingScripts = $('script[src]')
672
-
673
- scripts.each(function() {
674
- var src = this.src
675
- var matchedScripts = existingScripts.filter(function() {
676
- return this.src === src
677
- })
678
- if (matchedScripts.length) return
679
-
680
- var script = document.createElement('script')
681
- script.type = $(this).attr('type')
682
- script.src = $(this).attr('src')
683
- document.head.appendChild(script)
684
- })
685
- }
686
-
687
- // Internal: History DOM caching class.
688
- var cacheMapping = {}
689
- var cacheForwardStack = []
690
- var cacheBackStack = []
691
-
692
- // Push previous state id and container contents into the history
693
- // cache. Should be called in conjunction with `pushState` to save the
694
- // previous container contents.
695
- //
696
- // id - State ID Number
697
- // value - DOM Element to cache
698
- //
699
- // Returns nothing.
700
- function cachePush(id, value) {
701
- cacheMapping[id] = value
702
- cacheBackStack.push(id)
703
-
704
- // Remove all entires in forward history stack after pushing
705
- // a new page.
706
- while (cacheForwardStack.length)
707
- delete cacheMapping[cacheForwardStack.shift()]
708
-
709
- // Trim back history stack to max cache length.
710
- while (cacheBackStack.length > pjax.defaults.maxCacheLength)
711
- delete cacheMapping[cacheBackStack.shift()]
712
- }
713
-
714
- // Shifts cache from directional history cache. Should be
715
- // called on `popstate` with the previous state id and container
716
- // contents.
717
- //
718
- // direction - "forward" or "back" String
719
- // id - State ID Number
720
- // value - DOM Element to cache
721
- //
722
- // Returns nothing.
723
- function cachePop(direction, id, value) {
724
- var pushStack, popStack
725
- cacheMapping[id] = value
726
-
727
- if (direction === 'forward') {
728
- pushStack = cacheBackStack
729
- popStack = cacheForwardStack
730
- } else {
731
- pushStack = cacheForwardStack
732
- popStack = cacheBackStack
733
- }
734
-
735
- pushStack.push(id)
736
- if (id = popStack.pop())
737
- delete cacheMapping[id]
738
- }
739
-
740
- // Public: Find version identifier for the initial page load.
741
- //
742
- // Returns String version or undefined.
743
- function findVersion() {
744
- return $('meta').filter(function() {
745
- var name = $(this).attr('http-equiv')
746
- return name && name.toUpperCase() === 'X-PJAX-VERSION'
747
- }).attr('content')
748
- }
749
-
750
- // Install pjax functions on $.pjax to enable pushState behavior.
751
- //
752
- // Does nothing if already enabled.
753
- //
754
- // Examples
755
- //
756
- // $.pjax.enable()
757
- //
758
- // Returns nothing.
759
- function enable() {
760
- $.fn.pjax = fnPjax
761
- $.pjax = pjax
762
- $.pjax.enable = $.noop
763
- $.pjax.disable = disable
764
- $.pjax.click = handleClick
765
- $.pjax.submit = handleSubmit
766
- $.pjax.reload = pjaxReload
767
- $.pjax.defaults = {
768
- timeout: 650,
769
- push: true,
770
- replace: false,
771
- type: 'GET',
772
- dataType: 'html',
773
- scrollTo: 0,
774
- maxCacheLength: 20,
775
- version: findVersion
776
- }
777
- $(window).bind('popstate.pjax', onPjaxPopstate)
778
- }
779
-
780
- // Disable pushState behavior.
781
- //
782
- // This is the case when a browser doesn't support pushState. It is
783
- // sometimes useful to disable pushState for debugging on a modern
784
- // browser.
785
- //
786
- // Examples
787
- //
788
- // $.pjax.disable()
789
- //
790
- // Returns nothing.
791
- function disable() {
792
- $.fn.pjax = function() { return this }
793
- $.pjax = fallbackPjax
794
- $.pjax.enable = enable
795
- $.pjax.disable = $.noop
796
- $.pjax.click = $.noop
797
- $.pjax.submit = $.noop
798
- $.pjax.reload = function() { window.location.reload() }
799
-
800
- $(window).unbind('popstate.pjax', onPjaxPopstate)
801
- }
802
-
803
-
804
- // Add the state property to jQuery's event object so we can use it in
805
- // $(window).bind('popstate')
806
- if ( $.inArray('state', $.event.props) < 0 )
807
- $.event.props.push('state')
808
-
809
- // Is pjax supported by this browser?
810
- $.support.pjax =
811
- window.history && window.history.pushState && window.history.replaceState &&
812
- // pushState isn't reliable on iOS until 5.
813
- !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/)
814
-
815
- $.support.pjax ? enable() : disable()
816
-
817
- })(jQuery);