surveillance 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (276) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +42 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/javascripts/surveillance.js +6 -0
  6. data/app/assets/javascripts/surveillance/admin.coffee +4 -0
  7. data/app/assets/javascripts/surveillance/admin/matrix-questions.coffee +18 -0
  8. data/app/assets/javascripts/surveillance/application.js +17 -0
  9. data/app/assets/javascripts/surveillance/collections/branch_rule_collection.coffee +2 -0
  10. data/app/assets/javascripts/surveillance/form.coffee +7 -0
  11. data/app/assets/javascripts/surveillance/manifest.coffee +7 -0
  12. data/app/assets/javascripts/surveillance/models/branch_rule.coffee +21 -0
  13. data/app/assets/javascripts/surveillance/models/question.coffee +19 -0
  14. data/app/assets/javascripts/surveillance/models/questions/choosable_question.coffee +15 -0
  15. data/app/assets/javascripts/surveillance/models/questions/matrix.coffee +19 -0
  16. data/app/assets/javascripts/surveillance/models/questions/matrix_question.coffee +7 -0
  17. data/app/assets/javascripts/surveillance/models/questions/number.coffee +17 -0
  18. data/app/assets/javascripts/surveillance/vendor/backbone.min.js +1 -0
  19. data/app/assets/javascripts/surveillance/vendor/bootstrap.js +2118 -0
  20. data/app/assets/javascripts/surveillance/vendor/jquery-ui-sortable.js +2256 -0
  21. data/app/assets/javascripts/surveillance/vendor/jquery.scrollto.js +210 -0
  22. data/app/assets/javascripts/surveillance/vendor/underscore.min.js +5 -0
  23. data/app/assets/javascripts/surveillance/views/attempt_view.coffee +74 -0
  24. data/app/assets/javascripts/surveillance/views/question_view.coffee +53 -0
  25. data/app/assets/javascripts/surveillance/views/questions/choice_view.coffee +52 -0
  26. data/app/assets/javascripts/surveillance/views/questions/matrix_question_view.coffee +26 -0
  27. data/app/assets/javascripts/surveillance/views/questions/matrix_view.coffee +21 -0
  28. data/app/assets/javascripts/surveillance/views/questions/number_view.coffee +19 -0
  29. data/app/assets/javascripts/surveillance/views/questions/order.coffee +9 -0
  30. data/app/assets/javascripts/surveillance/views/questions/select_matrix_view.coffee +31 -0
  31. data/app/assets/javascripts/surveillance/views/section_view.coffee +54 -0
  32. data/app/assets/stylesheets/surveillance/admin.sass +1 -0
  33. data/app/assets/stylesheets/surveillance/application.css +14 -0
  34. data/app/assets/stylesheets/surveillance/fonts/glyphicons-halflings-regular.eot +0 -0
  35. data/app/assets/stylesheets/surveillance/fonts/glyphicons-halflings-regular.svg +229 -0
  36. data/app/assets/stylesheets/surveillance/fonts/glyphicons-halflings-regular.ttf +0 -0
  37. data/app/assets/stylesheets/surveillance/fonts/glyphicons-halflings-regular.woff +0 -0
  38. data/app/assets/stylesheets/surveillance/overrides.sass +2 -0
  39. data/app/assets/stylesheets/surveillance/vendor/bootstrap.css +6175 -0
  40. data/app/controllers/concerns/surveillance/attempts_management_concern.rb +51 -0
  41. data/app/controllers/concerns/surveillance/base_controller_concern.rb +37 -0
  42. data/app/controllers/surveillance/admin/attempts_controller.rb +38 -0
  43. data/app/controllers/surveillance/admin/base_controller.rb +15 -0
  44. data/app/controllers/surveillance/admin/exports_controller.rb +24 -0
  45. data/app/controllers/surveillance/admin/options_controller.rb +44 -0
  46. data/app/controllers/surveillance/admin/questions_controller.rb +59 -0
  47. data/app/controllers/surveillance/admin/sections_controller.rb +46 -0
  48. data/app/controllers/surveillance/admin/surveys_controller.rb +43 -0
  49. data/app/controllers/surveillance/application_controller.rb +7 -0
  50. data/app/controllers/surveillance/response/attempts_controller.rb +50 -0
  51. data/app/controllers/surveillance/response/base_controller.rb +38 -0
  52. data/app/controllers/surveillance/response/partial_attempts_controller.rb +15 -0
  53. data/app/controllers/surveillance/surveys_controller.rb +6 -0
  54. data/app/helpers/surveillance/admin/exports_helper.rb +37 -0
  55. data/app/helpers/surveillance/application_helper.rb +84 -0
  56. data/app/models/surveillance/answer.rb +56 -0
  57. data/app/models/surveillance/answer_content.rb +7 -0
  58. data/app/models/surveillance/attempt.rb +146 -0
  59. data/app/models/surveillance/branch_rule.rb +52 -0
  60. data/app/models/surveillance/field_setting.rb +6 -0
  61. data/app/models/surveillance/option.rb +18 -0
  62. data/app/models/surveillance/question.rb +50 -0
  63. data/app/models/surveillance/section.rb +16 -0
  64. data/app/models/surveillance/survey.rb +38 -0
  65. data/app/views/layouts/surveillance/application.html.haml +11 -0
  66. data/app/views/surveillance/admin/attempts/index.html.haml +47 -0
  67. data/app/views/surveillance/admin/attempts/list.html.haml +11 -0
  68. data/app/views/surveillance/admin/attempts/overview.html.haml +6 -0
  69. data/app/views/surveillance/admin/attempts/show.html.haml +62 -0
  70. data/app/views/surveillance/admin/exports/show.rxls +39 -0
  71. data/app/views/surveillance/admin/options/_field.html.haml +11 -0
  72. data/app/views/surveillance/admin/options/_form.html.haml +8 -0
  73. data/app/views/surveillance/admin/options/_list.html.haml +10 -0
  74. data/app/views/surveillance/admin/options/_option.html.haml +13 -0
  75. data/app/views/surveillance/admin/options/edit.html.haml +7 -0
  76. data/app/views/surveillance/admin/options/new.html.haml +7 -0
  77. data/app/views/surveillance/admin/questions/_form.html.haml +35 -0
  78. data/app/views/surveillance/admin/questions/_list.html.haml +17 -0
  79. data/app/views/surveillance/admin/questions/_question.html.haml +27 -0
  80. data/app/views/surveillance/admin/questions/edit.html.haml +7 -0
  81. data/app/views/surveillance/admin/questions/new.html.haml +4 -0
  82. data/app/views/surveillance/admin/sections/_form.html.haml +16 -0
  83. data/app/views/surveillance/admin/sections/_list.html.haml +13 -0
  84. data/app/views/surveillance/admin/sections/_section.html.haml +16 -0
  85. data/app/views/surveillance/admin/sections/edit.html.haml +7 -0
  86. data/app/views/surveillance/admin/sections/new.html.haml +4 -0
  87. data/app/views/surveillance/admin/surveys/_form.html.haml +22 -0
  88. data/app/views/surveillance/admin/surveys/_list.html.haml +13 -0
  89. data/app/views/surveillance/admin/surveys/_survey.html.haml +32 -0
  90. data/app/views/surveillance/admin/surveys/edit.html.haml +7 -0
  91. data/app/views/surveillance/admin/surveys/index.html.haml +1 -0
  92. data/app/views/surveillance/admin/surveys/new.html.haml +4 -0
  93. data/app/views/surveillance/field/date/_form.html.haml +5 -0
  94. data/app/views/surveillance/field/date/_overview.html.haml +2 -0
  95. data/app/views/surveillance/field/date/_show.html.haml +10 -0
  96. data/app/views/surveillance/field/matrix/_form.html.haml +40 -0
  97. data/app/views/surveillance/field/matrix/_overview.html.haml +19 -0
  98. data/app/views/surveillance/field/matrix/_questions_fields.html.haml +11 -0
  99. data/app/views/surveillance/field/matrix/_settings.html.haml +18 -0
  100. data/app/views/surveillance/field/matrix/_show.html.haml +22 -0
  101. data/app/views/surveillance/field/multiple_choices/_form.html.haml +18 -0
  102. data/app/views/surveillance/field/multiple_choices/_settings.html.haml +21 -0
  103. data/app/views/surveillance/field/multiple_choices/_show.html.haml +21 -0
  104. data/app/views/surveillance/field/multiple_choices_matrix/_form.html.haml +33 -0
  105. data/app/views/surveillance/field/multiple_choices_matrix/_show.html.haml +1 -0
  106. data/app/views/surveillance/field/number/_form.html.haml +5 -0
  107. data/app/views/surveillance/field/number/_overview.html.haml +2 -0
  108. data/app/views/surveillance/field/number/_settings.html.haml +2 -0
  109. data/app/views/surveillance/field/number/_show.html.haml +10 -0
  110. data/app/views/surveillance/field/order/_form.html.haml +17 -0
  111. data/app/views/surveillance/field/order/_overview.html.haml +22 -0
  112. data/app/views/surveillance/field/order/_settings.html.haml +11 -0
  113. data/app/views/surveillance/field/order/_show.html.haml +8 -0
  114. data/app/views/surveillance/field/select_matrix/_form.html.haml +17 -0
  115. data/app/views/surveillance/field/shared/_rules_form.html.haml +30 -0
  116. data/app/views/surveillance/field/shared/settings/_boolean.html.haml +9 -0
  117. data/app/views/surveillance/field/shared/settings/_number.html.haml +5 -0
  118. data/app/views/surveillance/field/single_choice/_form.html.haml +16 -0
  119. data/app/views/surveillance/field/single_choice/_overview.html.haml +14 -0
  120. data/app/views/surveillance/field/single_choice/_settings.html.haml +2 -0
  121. data/app/views/surveillance/field/single_choice/_show.html.haml +21 -0
  122. data/app/views/surveillance/field/single_select/_form.html.haml +4 -0
  123. data/app/views/surveillance/field/single_select/_overview.html.haml +14 -0
  124. data/app/views/surveillance/field/single_select/_show.html.haml +13 -0
  125. data/app/views/surveillance/field/text/_form.html.haml +5 -0
  126. data/app/views/surveillance/field/text/_overview.html.haml +2 -0
  127. data/app/views/surveillance/field/text/_show.html.haml +10 -0
  128. data/app/views/surveillance/field/text_area/_form.html.haml +5 -0
  129. data/app/views/surveillance/field/text_area/_overview.html.haml +1 -0
  130. data/app/views/surveillance/field/text_area/_show.html.haml +10 -0
  131. data/app/views/surveillance/response/attempts/complete.html.haml +11 -0
  132. data/app/views/surveillance/response/attempts/edit.html.haml +15 -0
  133. data/app/views/surveillance/sections/_section.html.haml +24 -0
  134. data/app/views/surveillance/surveys/_survey.html.haml +4 -0
  135. data/app/views/surveillance/surveys/index.html.haml +8 -0
  136. data/app/views/surveillance/surveys/show.html.haml +15 -0
  137. data/config/locales/surveillance.fr.yml +165 -0
  138. data/config/routes.rb +30 -0
  139. data/db/migrate/20130626115136_create_surveillance_surveys.rb +13 -0
  140. data/db/migrate/20130626115805_create_surveillance_sections.rb +12 -0
  141. data/db/migrate/20130626130351_create_surveillance_questions.rb +14 -0
  142. data/db/migrate/20130702111125_create_surveillance_options.rb +11 -0
  143. data/db/migrate/20130703113456_create_surveillance_attempts.rb +11 -0
  144. data/db/migrate/20130703115649_create_surveillance_answers.rb +11 -0
  145. data/db/migrate/20130703115723_create_surveillance_answer_contents.rb +10 -0
  146. data/db/migrate/20130710151627_create_surveillance_field_settings.rb +11 -0
  147. data/db/migrate/20130711100032_create_surveillance_answers_options_join_table.rb +7 -0
  148. data/db/migrate/20130729143002_create_surveillance_branch_rules.rb +14 -0
  149. data/db/migrate/20140212153506_add_state_to_surveillance_attempts.rb +6 -0
  150. data/db/migrate/20140213101147_add_access_token_to_surveillance_attempts.rb +5 -0
  151. data/db/migrate/20140213133036_add_partial_to_surveillance_questions.rb +5 -0
  152. data/lib/generators/surveillance/install/install_generator.rb +34 -0
  153. data/lib/generators/surveillance/install/templates/initializer.rb +51 -0
  154. data/lib/surveillance.rb +61 -0
  155. data/lib/surveillance/branch_action.rb +5 -0
  156. data/lib/surveillance/branch_condition.rb +5 -0
  157. data/lib/surveillance/engine.rb +13 -0
  158. data/lib/surveillance/field.rb +58 -0
  159. data/lib/surveillance/field/base.rb +149 -0
  160. data/lib/surveillance/field/date.rb +17 -0
  161. data/lib/surveillance/field/matrix.rb +66 -0
  162. data/lib/surveillance/field/matrix_question.rb +13 -0
  163. data/lib/surveillance/field/multiple_choices.rb +29 -0
  164. data/lib/surveillance/field/multiple_choices_matrix.rb +13 -0
  165. data/lib/surveillance/field/number.rb +34 -0
  166. data/lib/surveillance/field/order.rb +40 -0
  167. data/lib/surveillance/field/order_question.rb +22 -0
  168. data/lib/surveillance/field/other_choice.rb +28 -0
  169. data/lib/surveillance/field/select_matrix.rb +13 -0
  170. data/lib/surveillance/field/single_choice.rb +36 -0
  171. data/lib/surveillance/field/single_select.rb +31 -0
  172. data/lib/surveillance/field/text.rb +13 -0
  173. data/lib/surveillance/field/text_area.rb +6 -0
  174. data/lib/surveillance/partials_collection.rb +7 -0
  175. data/lib/surveillance/setting.rb +24 -0
  176. data/lib/surveillance/settings_collection.rb +17 -0
  177. data/lib/surveillance/validators.rb +7 -0
  178. data/lib/surveillance/validators/answer_validator.rb +9 -0
  179. data/lib/surveillance/version.rb +3 -0
  180. data/lib/tasks/surveillance_tasks.rake +4 -0
  181. data/spec/dummy/README.rdoc +28 -0
  182. data/spec/dummy/Rakefile +6 -0
  183. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  184. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  185. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  186. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  187. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  188. data/spec/dummy/bin/bundle +3 -0
  189. data/spec/dummy/bin/rails +4 -0
  190. data/spec/dummy/bin/rake +4 -0
  191. data/spec/dummy/config.ru +4 -0
  192. data/spec/dummy/config/application.rb +28 -0
  193. data/spec/dummy/config/boot.rb +5 -0
  194. data/spec/dummy/config/database.yml +25 -0
  195. data/spec/dummy/config/environment.rb +5 -0
  196. data/spec/dummy/config/environments/development.rb +29 -0
  197. data/spec/dummy/config/environments/production.rb +80 -0
  198. data/spec/dummy/config/environments/test.rb +36 -0
  199. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  200. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  201. data/spec/dummy/config/initializers/inflections.rb +16 -0
  202. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  203. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  204. data/spec/dummy/config/initializers/session_store.rb +3 -0
  205. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  206. data/spec/dummy/config/locales/en.yml +23 -0
  207. data/spec/dummy/config/locales/rails.fr.yml +226 -0
  208. data/spec/dummy/config/routes.rb +3 -0
  209. data/spec/dummy/db/development.sqlite3 +0 -0
  210. data/spec/dummy/db/migrate/20140113224541_create_surveillance_surveys.surveillance.rb +14 -0
  211. data/spec/dummy/db/migrate/20140113224542_create_surveillance_sections.surveillance.rb +13 -0
  212. data/spec/dummy/db/migrate/20140113224543_create_surveillance_questions.surveillance.rb +15 -0
  213. data/spec/dummy/db/migrate/20140113224544_create_surveillance_options.surveillance.rb +12 -0
  214. data/spec/dummy/db/migrate/20140113224545_create_surveillance_attempts.surveillance.rb +12 -0
  215. data/spec/dummy/db/migrate/20140113224546_create_surveillance_answers.surveillance.rb +12 -0
  216. data/spec/dummy/db/migrate/20140113224547_create_surveillance_answer_contents.surveillance.rb +11 -0
  217. data/spec/dummy/db/migrate/20140113224548_create_surveillance_field_settings.surveillance.rb +12 -0
  218. data/spec/dummy/db/migrate/20140113224549_create_surveillance_answers_options_join_table.surveillance.rb +8 -0
  219. data/spec/dummy/db/migrate/20140113224550_create_surveillance_branch_rules.surveillance.rb +15 -0
  220. data/spec/dummy/db/schema.rb +103 -0
  221. data/spec/dummy/log/development.log +38066 -0
  222. data/spec/dummy/public/404.html +58 -0
  223. data/spec/dummy/public/422.html +58 -0
  224. data/spec/dummy/public/500.html +57 -0
  225. data/spec/dummy/public/favicon.ico +0 -0
  226. data/spec/dummy/spec +1 -0
  227. data/spec/dummy/tmp/cache/assets/development/sprockets/0018421aaf29044fbd13363bbdfd8f44 +0 -0
  228. data/spec/dummy/tmp/cache/assets/development/sprockets/017d7a30ec05c0fb0265fb5167c73ee9 +0 -0
  229. data/spec/dummy/tmp/cache/assets/development/sprockets/034b76adeb89d6ca63cd9eea649331f5 +0 -0
  230. data/spec/dummy/tmp/cache/assets/development/sprockets/05de8fbfacab66a0efe4f9790b2ac723 +0 -0
  231. data/spec/dummy/tmp/cache/assets/development/sprockets/0811effcff3b9107d49398bdba7488e5 +0 -0
  232. data/spec/dummy/tmp/cache/assets/development/sprockets/0d45beae32861dc508fc2db09b9d95b3 +0 -0
  233. data/spec/dummy/tmp/cache/assets/development/sprockets/0d4961f3da5a0d5234736a6abbf42226 +0 -0
  234. data/spec/dummy/tmp/cache/assets/development/sprockets/0f491ed240e1a27bbc05e5213afd48bb +0 -0
  235. data/spec/dummy/tmp/cache/assets/development/sprockets/10e2a0dbdbb68c055e8b7ccd6f2906d8 +0 -0
  236. data/spec/dummy/tmp/cache/assets/development/sprockets/1173cdef6c662a55ef590489fe26e8fe +0 -0
  237. data/spec/dummy/tmp/cache/assets/development/sprockets/1b3e93127523ec0f3c93bcd91d4390dc +0 -0
  238. data/spec/dummy/tmp/cache/assets/development/sprockets/1bb56fbf17ccbb14dcbaa4d6d639e620 +0 -0
  239. data/spec/dummy/tmp/cache/assets/development/sprockets/2bd0ba6a1598c9fa67081d8f906db6f8 +0 -0
  240. data/spec/dummy/tmp/cache/assets/development/sprockets/3fbe053f103de46cc1b320f059b99c1f +0 -0
  241. data/spec/dummy/tmp/cache/assets/development/sprockets/4144b095447efb810a548b99e41df9eb +0 -0
  242. data/spec/dummy/tmp/cache/assets/development/sprockets/421d097cb8d88f975d8ccf75c9e5e306 +0 -0
  243. data/spec/dummy/tmp/cache/assets/development/sprockets/474bc1c9055df6cc1cdff58817a6cb41 +0 -0
  244. data/spec/dummy/tmp/cache/assets/development/sprockets/4829d251eeb22cdbd05b27b6ba809538 +0 -0
  245. data/spec/dummy/tmp/cache/assets/development/sprockets/4f584ca3f0c8ec62906e6f03bc5963c2 +0 -0
  246. data/spec/dummy/tmp/cache/assets/development/sprockets/55d647d88e01b91b2a146e7db0481c09 +0 -0
  247. data/spec/dummy/tmp/cache/assets/development/sprockets/62db8b5885b79c5dc0667fab0fbf46bb +0 -0
  248. data/spec/dummy/tmp/cache/assets/development/sprockets/7080a4d265fe784c9704db71f81da832 +0 -0
  249. data/spec/dummy/tmp/cache/assets/development/sprockets/7220af243fd39e3dffd233252e4a8c17 +0 -0
  250. data/spec/dummy/tmp/cache/assets/development/sprockets/7cd0e5bfe12b86ed494d02e8e5b62bbf +0 -0
  251. data/spec/dummy/tmp/cache/assets/development/sprockets/7e37a8ae2a50653b388d57c573d12548 +0 -0
  252. data/spec/dummy/tmp/cache/assets/development/sprockets/8113790dad1da8858c82cfc3eb14ef87 +0 -0
  253. data/spec/dummy/tmp/cache/assets/development/sprockets/83997102fc04f275cd6cd8c1ddb55835 +0 -0
  254. data/spec/dummy/tmp/cache/assets/development/sprockets/8a7b047a16adbc640e03eaabe4a4fe93 +0 -0
  255. data/spec/dummy/tmp/cache/assets/development/sprockets/90b48fb4bfa22ddcd063734065d27086 +0 -0
  256. data/spec/dummy/tmp/cache/assets/development/sprockets/935886b24c90d344752d2a80e3657801 +0 -0
  257. data/spec/dummy/tmp/cache/assets/development/sprockets/9606a6d70af63ce3fea26ded0a69d5c2 +0 -0
  258. data/spec/dummy/tmp/cache/assets/development/sprockets/97db73fdf0bbab24fb92892c61ec7a9b +0 -0
  259. data/spec/dummy/tmp/cache/assets/development/sprockets/a23bb60554e715c228ae3cdfb5d81807 +0 -0
  260. data/spec/dummy/tmp/cache/assets/development/sprockets/ad17e102b9f9288a9e919b0b0a2ab05b +0 -0
  261. data/spec/dummy/tmp/cache/assets/development/sprockets/c26ae1f6640b52c232bd392a6e2f7110 +0 -0
  262. data/spec/dummy/tmp/cache/assets/development/sprockets/c6cb3deca0f08bd9569d00fca09272da +0 -0
  263. data/spec/dummy/tmp/cache/assets/development/sprockets/d39b4eebbd0042342e10497a34fd6378 +0 -0
  264. data/spec/dummy/tmp/cache/assets/development/sprockets/d5ee573b2abdcdc245a830bde2dd76f3 +0 -0
  265. data/spec/dummy/tmp/cache/assets/development/sprockets/d6487e59842ff206d84f6de5e3a7400c +0 -0
  266. data/spec/dummy/tmp/cache/assets/development/sprockets/dafa124ddd0e828d7c5c0a5c4db455ba +0 -0
  267. data/spec/dummy/tmp/cache/assets/development/sprockets/e5bbd03518f9abc3e9bc1373c74fd3f1 +0 -0
  268. data/spec/dummy/tmp/cache/assets/development/sprockets/ed5aa255edff522c2e36e6f0151ff747 +0 -0
  269. data/spec/dummy/tmp/cache/assets/development/sprockets/ee263a426f6530013f86aa860448fa91 +0 -0
  270. data/spec/dummy/tmp/cache/assets/development/sprockets/efa0c4d855d425fdf4b63ab26c45e94c +0 -0
  271. data/spec/dummy/tmp/cache/assets/development/sprockets/f2881259fd5bad1c0a5b1ab5dff97c47 +0 -0
  272. data/spec/dummy/tmp/cache/assets/development/sprockets/f34108e540cff2fbc32036da452ca6ae +0 -0
  273. data/spec/dummy/tmp/cache/assets/development/sprockets/f7e7e00ef8efc13c6a2628e453344440 +0 -0
  274. data/spec/dummy/tmp/cache/assets/development/sprockets/f9a44009076e46b0f35af5e7031a1871 +0 -0
  275. data/spec/spec_helper.rb +87 -0
  276. metadata +598 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4db1967c20eb4e00ac9c3e984de9b7d880047e23
4
+ data.tar.gz: ff2500601aa86de50aa6d227aa9407ecc347cce7
5
+ SHA512:
6
+ metadata.gz: b8ceef7ca622f70da676b0a6784e8d1bf5b10470a86a5d06e756206cd42a18d11ab1d2b93355834209788dc6d0059b29f182b6de43624231c575966b076d78b0
7
+ data.tar.gz: 7624f52a246719e8f73c14e13be23a46c9dcd1491cfbc4ec1e8ced735db296aadffa87b92dd3830f37663dfdb600c6b0f4428adacc6b6274b1f020aac822d5f9
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # Surveillance
2
+
3
+ Survey Rails 4 engine
4
+
5
+ ## Installation
6
+
7
+ Add to Gemfile and bundle :
8
+
9
+ ```ruby
10
+ gem 'surveillance', github: 'vala/surveillance'
11
+ ```
12
+
13
+ Execute install generator :
14
+
15
+ ```bash
16
+ rails generate surveillance:install
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ - Configure with generated initializer
22
+ - Access admin at : `/<mount_path>/admin/surveys`
23
+ - Access surveys at : `/<mount_path>/surveys`
24
+ - Require the javascript lib in your application.js : `//= require surveillance`
25
+
26
+ ### Overriding models or controllers
27
+
28
+ If you need to override a class from the system, e.g. adding a validation or
29
+ method to a model, a `before_action` to a controller or something like that,
30
+ you can use the "decorators" approach the following way :
31
+
32
+ 1. Create a file with the name of the desired class under
33
+ `lib/decorators/surveillance/`, e.g. `lib/decorators/surveillance/attempt.rb`
34
+ 2. Use `.class_eval` to reopen the class and modify it. e.g.
35
+ ```ruby
36
+ # lib/decorators/surveillance/attempt.rb
37
+ Surveillance::Attemp.class_eval do
38
+ def foo
39
+ puts 'bar'
40
+ end
41
+ end
42
+ ```
@@ -0,0 +1,23 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Surveillance'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
@@ -0,0 +1,6 @@
1
+ //= require ./surveillance/vendor/jquery-ui-sortable
2
+ //= require ./surveillance/vendor/jquery.scrollto
3
+ //= require ./surveillance/form
4
+ //= require_tree ./surveillance/models
5
+ //= require_tree ./surveillance/collections
6
+ //= require_tree ./surveillance/views
@@ -0,0 +1,4 @@
1
+ #= require jquery
2
+ #= require jquery_ujs
3
+ #= require ./vendor/bootstrap
4
+ #= require_tree ./admin
@@ -0,0 +1,18 @@
1
+ $ ->
2
+ $("body").on "click", "[data-destroy-field]", (e) ->
3
+ e.preventDefault()
4
+ $link = $(e.currentTarget)
5
+ $link.prev().val("1")
6
+ target = $link.data("parent-target") || "fieldset"
7
+ $target = $link.closest(target)
8
+ $target.fadeOut(300)
9
+
10
+ $("body").on "click", "[data-toggle='new-field']", (e) ->
11
+ e.preventDefault()
12
+ $link = $(e.currentTarget)
13
+ time = new Date().getTime()
14
+ idReplacePattern = new RegExp($link.data("id"), "g")
15
+ html = $link.data("fields").replace(idReplacePattern, time)
16
+ $link.before(html)
17
+
18
+
@@ -0,0 +1,17 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //= require jquery
13
+ //= require jquery_ujs
14
+ //= require ./vendor/underscore.min
15
+ //= require ./vendor/backbone.min
16
+ //= require ./manifest
17
+ //= require_tree ./admin
@@ -0,0 +1,2 @@
1
+ class Surveillance.BranchRuleCollection extends Backbone.Collection
2
+ model: Surveillance.BranchRule
@@ -0,0 +1,7 @@
1
+ # Create Surveillance global namespace
2
+ @Surveillance = {}
3
+
4
+ $ ->
5
+ # Initialize forms if present on page
6
+ if ($forms = $(".surveillance-attempt-form"))
7
+ $forms.each (i, el) -> new Surveillance.AttemptView(el: el)
@@ -0,0 +1,7 @@
1
+ # [DEPRECATED] Here for backwards compatibility
2
+ #
3
+ #= require ./vendor/jquery-ui-sortable
4
+ #= require ./form
5
+ #= require_tree ./models
6
+ #= require_tree ./collections
7
+ #= require_tree ./views
@@ -0,0 +1,21 @@
1
+ class Surveillance.BranchRule extends Backbone.Model
2
+ matches: (@question) ->
3
+ @[@get("condition")]()
4
+
5
+ answers: ->
6
+ @question.answered()
7
+
8
+ doesnt_answer: ->
9
+ !@answers()
10
+
11
+ answers_option: ->
12
+ optionId = @get("option_id")
13
+
14
+ if @question.get("matrix")
15
+ questionId = @get("sub_question_id")
16
+ @question.hasAnswered(questionId, optionId)
17
+ else
18
+ @question.hasAnswered(optionId)
19
+
20
+ doesnt_answer_option: ->
21
+ !@answers_option()
@@ -0,0 +1,19 @@
1
+ class Surveillance.Question extends Backbone.Model
2
+ constructor: (attrs, options) ->
3
+ @rules = new Surveillance.BranchRuleCollection(attrs.rules)
4
+ delete attrs.rules
5
+ super(attrs, options)
6
+
7
+ validate: ->
8
+ return null unless @get("required")
9
+ @processValidations()
10
+
11
+ processValidations: ->
12
+ @get("fields").length < @get("fieldsToFill")
13
+
14
+ answered: ->
15
+ @get("fields").length > 0
16
+
17
+ firstMatchingRule: ->
18
+ for rule in @rules.models
19
+ return rule if rule.matches(this)
@@ -0,0 +1,15 @@
1
+ class Surveillance.ChoosableQuestion extends Surveillance.Question
2
+ processValidations: ->
3
+ otherChoosed = _.include(@get("value"), "other")
4
+ minFieldsToFill = 1
5
+ chooseField = @get("value").length < minFieldsToFill
6
+ fillOtherField = otherChoosed && !@get("other")
7
+
8
+ if chooseField or fillOtherField
9
+ { chooseField: chooseField, fillOtherField: fillOtherField }
10
+ else
11
+ false
12
+
13
+ hasAnswered: (optionId) ->
14
+ _.include(@get("value"), optionId)
15
+
@@ -0,0 +1,19 @@
1
+ class Surveillance.Matrix extends Surveillance.Question
2
+ initialize: (options) ->
3
+ @set(matrix: true)
4
+ @subQuestions = []
5
+
6
+ processValidations: ->
7
+ errors = _.reduce(
8
+ @subQuestions
9
+ (errors, q) ->
10
+ errors.push(q.id) unless q.isValid()
11
+ errors
12
+ []
13
+ )
14
+
15
+ if errors.length then errors else false
16
+
17
+ hasAnswered: (questionId, optionId) ->
18
+ _.any @subQuestions, (subQuestion) ->
19
+ subQuestion.id == questionId and subQuestion.hasAnswered(optionId)
@@ -0,0 +1,7 @@
1
+ class Surveillance.MatrixQuestion extends Backbone.Model
2
+ validate: ->
3
+ @get("value").length == 0
4
+
5
+ hasAnswered: (optionId) ->
6
+ _.include(@get("value"), optionId)
7
+
@@ -0,0 +1,17 @@
1
+ class Surveillance.Number extends Surveillance.Question
2
+ defaults:
3
+ value: null
4
+
5
+ validate: ->
6
+ return null unless @get("required") or @get("value")
7
+ @processValidations()
8
+
9
+ processValidations: ->
10
+ value = @get("value")
11
+ belowMinimum = value and (minimum = @get("minimum")) and value < minimum
12
+ aboveMaximum = value and (maximum = @get("maximum")) and value > maximum
13
+
14
+ !value or belowMinimum or aboveMaximum
15
+
16
+
17
+
@@ -0,0 +1 @@
1
+ (function(){var t=this;var e=t.Backbone;var i=[];var r=i.push;var s=i.slice;var n=i.splice;var a;if(typeof exports!=="undefined"){a=exports}else{a=t.Backbone={}}a.VERSION="1.1.0";var h=t._;if(!h&&typeof require!=="undefined")h=require("underscore");a.$=t.jQuery||t.Zepto||t.ender||t.$;a.noConflict=function(){t.Backbone=e;return this};a.emulateHTTP=false;a.emulateJSON=false;var o=a.Events={on:function(t,e,i){if(!l(this,"on",t,[e,i])||!e)return this;this._events||(this._events={});var r=this._events[t]||(this._events[t]=[]);r.push({callback:e,context:i,ctx:i||this});return this},once:function(t,e,i){if(!l(this,"once",t,[e,i])||!e)return this;var r=this;var s=h.once(function(){r.off(t,s);e.apply(this,arguments)});s._callback=e;return this.on(t,s,i)},off:function(t,e,i){var r,s,n,a,o,u,c,f;if(!this._events||!l(this,"off",t,[e,i]))return this;if(!t&&!e&&!i){this._events={};return this}a=t?[t]:h.keys(this._events);for(o=0,u=a.length;o<u;o++){t=a[o];if(n=this._events[t]){this._events[t]=r=[];if(e||i){for(c=0,f=n.length;c<f;c++){s=n[c];if(e&&e!==s.callback&&e!==s.callback._callback||i&&i!==s.context){r.push(s)}}}if(!r.length)delete this._events[t]}}return this},trigger:function(t){if(!this._events)return this;var e=s.call(arguments,1);if(!l(this,"trigger",t,e))return this;var i=this._events[t];var r=this._events.all;if(i)c(i,e);if(r)c(r,arguments);return this},stopListening:function(t,e,i){var r=this._listeningTo;if(!r)return this;var s=!e&&!i;if(!i&&typeof e==="object")i=this;if(t)(r={})[t._listenId]=t;for(var n in r){t=r[n];t.off(e,i,this);if(s||h.isEmpty(t._events))delete this._listeningTo[n]}return this}};var u=/\s+/;var l=function(t,e,i,r){if(!i)return true;if(typeof i==="object"){for(var s in i){t[e].apply(t,[s,i[s]].concat(r))}return false}if(u.test(i)){var n=i.split(u);for(var a=0,h=n.length;a<h;a++){t[e].apply(t,[n[a]].concat(r))}return false}return true};var c=function(t,e){var i,r=-1,s=t.length,n=e[0],a=e[1],h=e[2];switch(e.length){case 0:while(++r<s)(i=t[r]).callback.call(i.ctx);return;case 1:while(++r<s)(i=t[r]).callback.call(i.ctx,n);return;case 2:while(++r<s)(i=t[r]).callback.call(i.ctx,n,a);return;case 3:while(++r<s)(i=t[r]).callback.call(i.ctx,n,a,h);return;default:while(++r<s)(i=t[r]).callback.apply(i.ctx,e)}};var f={listenTo:"on",listenToOnce:"once"};h.each(f,function(t,e){o[e]=function(e,i,r){var s=this._listeningTo||(this._listeningTo={});var n=e._listenId||(e._listenId=h.uniqueId("l"));s[n]=e;if(!r&&typeof i==="object")r=this;e[t](i,r,this);return this}});o.bind=o.on;o.unbind=o.off;h.extend(a,o);var d=a.Model=function(t,e){var i=t||{};e||(e={});this.cid=h.uniqueId("c");this.attributes={};if(e.collection)this.collection=e.collection;if(e.parse)i=this.parse(i,e)||{};i=h.defaults({},i,h.result(this,"defaults"));this.set(i,e);this.changed={};this.initialize.apply(this,arguments)};h.extend(d.prototype,o,{changed:null,validationError:null,idAttribute:"id",initialize:function(){},toJSON:function(t){return h.clone(this.attributes)},sync:function(){return a.sync.apply(this,arguments)},get:function(t){return this.attributes[t]},escape:function(t){return h.escape(this.get(t))},has:function(t){return this.get(t)!=null},set:function(t,e,i){var r,s,n,a,o,u,l,c;if(t==null)return this;if(typeof t==="object"){s=t;i=e}else{(s={})[t]=e}i||(i={});if(!this._validate(s,i))return false;n=i.unset;o=i.silent;a=[];u=this._changing;this._changing=true;if(!u){this._previousAttributes=h.clone(this.attributes);this.changed={}}c=this.attributes,l=this._previousAttributes;if(this.idAttribute in s)this.id=s[this.idAttribute];for(r in s){e=s[r];if(!h.isEqual(c[r],e))a.push(r);if(!h.isEqual(l[r],e)){this.changed[r]=e}else{delete this.changed[r]}n?delete c[r]:c[r]=e}if(!o){if(a.length)this._pending=true;for(var f=0,d=a.length;f<d;f++){this.trigger("change:"+a[f],this,c[a[f]],i)}}if(u)return this;if(!o){while(this._pending){this._pending=false;this.trigger("change",this,i)}}this._pending=false;this._changing=false;return this},unset:function(t,e){return this.set(t,void 0,h.extend({},e,{unset:true}))},clear:function(t){var e={};for(var i in this.attributes)e[i]=void 0;return this.set(e,h.extend({},t,{unset:true}))},hasChanged:function(t){if(t==null)return!h.isEmpty(this.changed);return h.has(this.changed,t)},changedAttributes:function(t){if(!t)return this.hasChanged()?h.clone(this.changed):false;var e,i=false;var r=this._changing?this._previousAttributes:this.attributes;for(var s in t){if(h.isEqual(r[s],e=t[s]))continue;(i||(i={}))[s]=e}return i},previous:function(t){if(t==null||!this._previousAttributes)return null;return this._previousAttributes[t]},previousAttributes:function(){return h.clone(this._previousAttributes)},fetch:function(t){t=t?h.clone(t):{};if(t.parse===void 0)t.parse=true;var e=this;var i=t.success;t.success=function(r){if(!e.set(e.parse(r,t),t))return false;if(i)i(e,r,t);e.trigger("sync",e,r,t)};M(this,t);return this.sync("read",this,t)},save:function(t,e,i){var r,s,n,a=this.attributes;if(t==null||typeof t==="object"){r=t;i=e}else{(r={})[t]=e}i=h.extend({validate:true},i);if(r&&!i.wait){if(!this.set(r,i))return false}else{if(!this._validate(r,i))return false}if(r&&i.wait){this.attributes=h.extend({},a,r)}if(i.parse===void 0)i.parse=true;var o=this;var u=i.success;i.success=function(t){o.attributes=a;var e=o.parse(t,i);if(i.wait)e=h.extend(r||{},e);if(h.isObject(e)&&!o.set(e,i)){return false}if(u)u(o,t,i);o.trigger("sync",o,t,i)};M(this,i);s=this.isNew()?"create":i.patch?"patch":"update";if(s==="patch")i.attrs=r;n=this.sync(s,this,i);if(r&&i.wait)this.attributes=a;return n},destroy:function(t){t=t?h.clone(t):{};var e=this;var i=t.success;var r=function(){e.trigger("destroy",e,e.collection,t)};t.success=function(s){if(t.wait||e.isNew())r();if(i)i(e,s,t);if(!e.isNew())e.trigger("sync",e,s,t)};if(this.isNew()){t.success();return false}M(this,t);var s=this.sync("delete",this,t);if(!t.wait)r();return s},url:function(){var t=h.result(this,"urlRoot")||h.result(this.collection,"url")||U();if(this.isNew())return t;return t+(t.charAt(t.length-1)==="/"?"":"/")+encodeURIComponent(this.id)},parse:function(t,e){return t},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return this.id==null},isValid:function(t){return this._validate({},h.extend(t||{},{validate:true}))},_validate:function(t,e){if(!e.validate||!this.validate)return true;t=h.extend({},this.attributes,t);var i=this.validationError=this.validate(t,e)||null;if(!i)return true;this.trigger("invalid",this,i,h.extend(e,{validationError:i}));return false}});var p=["keys","values","pairs","invert","pick","omit"];h.each(p,function(t){d.prototype[t]=function(){var e=s.call(arguments);e.unshift(this.attributes);return h[t].apply(h,e)}});var v=a.Collection=function(t,e){e||(e={});if(e.model)this.model=e.model;if(e.comparator!==void 0)this.comparator=e.comparator;this._reset();this.initialize.apply(this,arguments);if(t)this.reset(t,h.extend({silent:true},e))};var g={add:true,remove:true,merge:true};var m={add:true,remove:false};h.extend(v.prototype,o,{model:d,initialize:function(){},toJSON:function(t){return this.map(function(e){return e.toJSON(t)})},sync:function(){return a.sync.apply(this,arguments)},add:function(t,e){return this.set(t,h.extend({merge:false},e,m))},remove:function(t,e){var i=!h.isArray(t);t=i?[t]:h.clone(t);e||(e={});var r,s,n,a;for(r=0,s=t.length;r<s;r++){a=t[r]=this.get(t[r]);if(!a)continue;delete this._byId[a.id];delete this._byId[a.cid];n=this.indexOf(a);this.models.splice(n,1);this.length--;if(!e.silent){e.index=n;a.trigger("remove",a,this,e)}this._removeReference(a)}return i?t[0]:t},set:function(t,e){e=h.defaults({},e,g);if(e.parse)t=this.parse(t,e);var i=!h.isArray(t);t=i?t?[t]:[]:h.clone(t);var r,s,n,a,o,u,l;var c=e.at;var f=this.model;var p=this.comparator&&c==null&&e.sort!==false;var v=h.isString(this.comparator)?this.comparator:null;var m=[],y=[],_={};var w=e.add,b=e.merge,x=e.remove;var E=!p&&w&&x?[]:false;for(r=0,s=t.length;r<s;r++){o=t[r];if(o instanceof d){n=a=o}else{n=o[f.prototype.idAttribute]}if(u=this.get(n)){if(x)_[u.cid]=true;if(b){o=o===a?a.attributes:o;if(e.parse)o=u.parse(o,e);u.set(o,e);if(p&&!l&&u.hasChanged(v))l=true}t[r]=u}else if(w){a=t[r]=this._prepareModel(o,e);if(!a)continue;m.push(a);a.on("all",this._onModelEvent,this);this._byId[a.cid]=a;if(a.id!=null)this._byId[a.id]=a}if(E)E.push(u||a)}if(x){for(r=0,s=this.length;r<s;++r){if(!_[(a=this.models[r]).cid])y.push(a)}if(y.length)this.remove(y,e)}if(m.length||E&&E.length){if(p)l=true;this.length+=m.length;if(c!=null){for(r=0,s=m.length;r<s;r++){this.models.splice(c+r,0,m[r])}}else{if(E)this.models.length=0;var T=E||m;for(r=0,s=T.length;r<s;r++){this.models.push(T[r])}}}if(l)this.sort({silent:true});if(!e.silent){for(r=0,s=m.length;r<s;r++){(a=m[r]).trigger("add",a,this,e)}if(l||E&&E.length)this.trigger("sort",this,e)}return i?t[0]:t},reset:function(t,e){e||(e={});for(var i=0,r=this.models.length;i<r;i++){this._removeReference(this.models[i])}e.previousModels=this.models;this._reset();t=this.add(t,h.extend({silent:true},e));if(!e.silent)this.trigger("reset",this,e);return t},push:function(t,e){return this.add(t,h.extend({at:this.length},e))},pop:function(t){var e=this.at(this.length-1);this.remove(e,t);return e},unshift:function(t,e){return this.add(t,h.extend({at:0},e))},shift:function(t){var e=this.at(0);this.remove(e,t);return e},slice:function(){return s.apply(this.models,arguments)},get:function(t){if(t==null)return void 0;return this._byId[t.id]||this._byId[t.cid]||this._byId[t]},at:function(t){return this.models[t]},where:function(t,e){if(h.isEmpty(t))return e?void 0:[];return this[e?"find":"filter"](function(e){for(var i in t){if(t[i]!==e.get(i))return false}return true})},findWhere:function(t){return this.where(t,true)},sort:function(t){if(!this.comparator)throw new Error("Cannot sort a set without a comparator");t||(t={});if(h.isString(this.comparator)||this.comparator.length===1){this.models=this.sortBy(this.comparator,this)}else{this.models.sort(h.bind(this.comparator,this))}if(!t.silent)this.trigger("sort",this,t);return this},pluck:function(t){return h.invoke(this.models,"get",t)},fetch:function(t){t=t?h.clone(t):{};if(t.parse===void 0)t.parse=true;var e=t.success;var i=this;t.success=function(r){var s=t.reset?"reset":"set";i[s](r,t);if(e)e(i,r,t);i.trigger("sync",i,r,t)};M(this,t);return this.sync("read",this,t)},create:function(t,e){e=e?h.clone(e):{};if(!(t=this._prepareModel(t,e)))return false;if(!e.wait)this.add(t,e);var i=this;var r=e.success;e.success=function(t,e,s){if(s.wait)i.add(t,s);if(r)r(t,e,s)};t.save(null,e);return t},parse:function(t,e){return t},clone:function(){return new this.constructor(this.models)},_reset:function(){this.length=0;this.models=[];this._byId={}},_prepareModel:function(t,e){if(t instanceof d){if(!t.collection)t.collection=this;return t}e=e?h.clone(e):{};e.collection=this;var i=new this.model(t,e);if(!i.validationError)return i;this.trigger("invalid",this,i.validationError,e);return false},_removeReference:function(t){if(this===t.collection)delete t.collection;t.off("all",this._onModelEvent,this)},_onModelEvent:function(t,e,i,r){if((t==="add"||t==="remove")&&i!==this)return;if(t==="destroy")this.remove(e,r);if(e&&t==="change:"+e.idAttribute){delete this._byId[e.previous(e.idAttribute)];if(e.id!=null)this._byId[e.id]=e}this.trigger.apply(this,arguments)}});var y=["forEach","each","map","collect","reduce","foldl","inject","reduceRight","foldr","find","detect","filter","select","reject","every","all","some","any","include","contains","invoke","max","min","toArray","size","first","head","take","initial","rest","tail","drop","last","without","difference","indexOf","shuffle","lastIndexOf","isEmpty","chain"];h.each(y,function(t){v.prototype[t]=function(){var e=s.call(arguments);e.unshift(this.models);return h[t].apply(h,e)}});var _=["groupBy","countBy","sortBy"];h.each(_,function(t){v.prototype[t]=function(e,i){var r=h.isFunction(e)?e:function(t){return t.get(e)};return h[t](this.models,r,i)}});var w=a.View=function(t){this.cid=h.uniqueId("view");t||(t={});h.extend(this,h.pick(t,x));this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()};var b=/^(\S+)\s*(.*)$/;var x=["model","collection","el","id","attributes","className","tagName","events"];h.extend(w.prototype,o,{tagName:"div",$:function(t){return this.$el.find(t)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();this.stopListening();return this},setElement:function(t,e){if(this.$el)this.undelegateEvents();this.$el=t instanceof a.$?t:a.$(t);this.el=this.$el[0];if(e!==false)this.delegateEvents();return this},delegateEvents:function(t){if(!(t||(t=h.result(this,"events"))))return this;this.undelegateEvents();for(var e in t){var i=t[e];if(!h.isFunction(i))i=this[t[e]];if(!i)continue;var r=e.match(b);var s=r[1],n=r[2];i=h.bind(i,this);s+=".delegateEvents"+this.cid;if(n===""){this.$el.on(s,i)}else{this.$el.on(s,n,i)}}return this},undelegateEvents:function(){this.$el.off(".delegateEvents"+this.cid);return this},_ensureElement:function(){if(!this.el){var t=h.extend({},h.result(this,"attributes"));if(this.id)t.id=h.result(this,"id");if(this.className)t["class"]=h.result(this,"className");var e=a.$("<"+h.result(this,"tagName")+">").attr(t);this.setElement(e,false)}else{this.setElement(h.result(this,"el"),false)}}});a.sync=function(t,e,i){var r=T[t];h.defaults(i||(i={}),{emulateHTTP:a.emulateHTTP,emulateJSON:a.emulateJSON});var s={type:r,dataType:"json"};if(!i.url){s.url=h.result(e,"url")||U()}if(i.data==null&&e&&(t==="create"||t==="update"||t==="patch")){s.contentType="application/json";s.data=JSON.stringify(i.attrs||e.toJSON(i))}if(i.emulateJSON){s.contentType="application/x-www-form-urlencoded";s.data=s.data?{model:s.data}:{}}if(i.emulateHTTP&&(r==="PUT"||r==="DELETE"||r==="PATCH")){s.type="POST";if(i.emulateJSON)s.data._method=r;var n=i.beforeSend;i.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",r);if(n)return n.apply(this,arguments)}}if(s.type!=="GET"&&!i.emulateJSON){s.processData=false}if(s.type==="PATCH"&&E){s.xhr=function(){return new ActiveXObject("Microsoft.XMLHTTP")}}var o=i.xhr=a.ajax(h.extend(s,i));e.trigger("request",e,o,i);return o};var E=typeof window!=="undefined"&&!!window.ActiveXObject&&!(window.XMLHttpRequest&&(new XMLHttpRequest).dispatchEvent);var T={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};a.ajax=function(){return a.$.ajax.apply(a.$,arguments)};var k=a.Router=function(t){t||(t={});if(t.routes)this.routes=t.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var S=/\((.*?)\)/g;var $=/(\(\?)?:\w+/g;var H=/\*\w+/g;var A=/[\-{}\[\]+?.,\\\^$|#\s]/g;h.extend(k.prototype,o,{initialize:function(){},route:function(t,e,i){if(!h.isRegExp(t))t=this._routeToRegExp(t);if(h.isFunction(e)){i=e;e=""}if(!i)i=this[e];var r=this;a.history.route(t,function(s){var n=r._extractParameters(t,s);i&&i.apply(r,n);r.trigger.apply(r,["route:"+e].concat(n));r.trigger("route",e,n);a.history.trigger("route",r,e,n)});return this},navigate:function(t,e){a.history.navigate(t,e);return this},_bindRoutes:function(){if(!this.routes)return;this.routes=h.result(this,"routes");var t,e=h.keys(this.routes);while((t=e.pop())!=null){this.route(t,this.routes[t])}},_routeToRegExp:function(t){t=t.replace(A,"\\$&").replace(S,"(?:$1)?").replace($,function(t,e){return e?t:"([^/]+)"}).replace(H,"(.*?)");return new RegExp("^"+t+"$")},_extractParameters:function(t,e){var i=t.exec(e).slice(1);return h.map(i,function(t){return t?decodeURIComponent(t):null})}});var I=a.History=function(){this.handlers=[];h.bindAll(this,"checkUrl");if(typeof window!=="undefined"){this.location=window.location;this.history=window.history}};var N=/^[#\/]|\s+$/g;var O=/^\/+|\/+$/g;var P=/msie [\w.]+/;var C=/\/$/;var j=/[?#].*$/;I.started=false;h.extend(I.prototype,o,{interval:50,getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getFragment:function(t,e){if(t==null){if(this._hasPushState||!this._wantsHashChange||e){t=this.location.pathname;var i=this.root.replace(C,"");if(!t.indexOf(i))t=t.slice(i.length)}else{t=this.getHash()}}return t.replace(N,"")},start:function(t){if(I.started)throw new Error("Backbone.history has already been started");I.started=true;this.options=h.extend({root:"/"},this.options,t);this.root=this.options.root;this._wantsHashChange=this.options.hashChange!==false;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var e=this.getFragment();var i=document.documentMode;var r=P.exec(navigator.userAgent.toLowerCase())&&(!i||i<=7);this.root=("/"+this.root+"/").replace(O,"/");if(r&&this._wantsHashChange){this.iframe=a.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow;this.navigate(e)}if(this._hasPushState){a.$(window).on("popstate",this.checkUrl)}else if(this._wantsHashChange&&"onhashchange"in window&&!r){a.$(window).on("hashchange",this.checkUrl)}else if(this._wantsHashChange){this._checkUrlInterval=setInterval(this.checkUrl,this.interval)}this.fragment=e;var s=this.location;var n=s.pathname.replace(/[^\/]$/,"$&/")===this.root;if(this._wantsHashChange&&this._wantsPushState){if(!this._hasPushState&&!n){this.fragment=this.getFragment(null,true);this.location.replace(this.root+this.location.search+"#"+this.fragment);return true}else if(this._hasPushState&&n&&s.hash){this.fragment=this.getHash().replace(N,"");this.history.replaceState({},document.title,this.root+this.fragment+s.search)}}if(!this.options.silent)return this.loadUrl()},stop:function(){a.$(window).off("popstate",this.checkUrl).off("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);I.started=false},route:function(t,e){this.handlers.unshift({route:t,callback:e})},checkUrl:function(t){var e=this.getFragment();if(e===this.fragment&&this.iframe){e=this.getFragment(this.getHash(this.iframe))}if(e===this.fragment)return false;if(this.iframe)this.navigate(e);this.loadUrl()},loadUrl:function(t){t=this.fragment=this.getFragment(t);return h.any(this.handlers,function(e){if(e.route.test(t)){e.callback(t);return true}})},navigate:function(t,e){if(!I.started)return false;if(!e||e===true)e={trigger:!!e};var i=this.root+(t=this.getFragment(t||""));t=t.replace(j,"");if(this.fragment===t)return;this.fragment=t;if(t===""&&i!=="/")i=i.slice(0,-1);if(this._hasPushState){this.history[e.replace?"replaceState":"pushState"]({},document.title,i)}else if(this._wantsHashChange){this._updateHash(this.location,t,e.replace);if(this.iframe&&t!==this.getFragment(this.getHash(this.iframe))){if(!e.replace)this.iframe.document.open().close();this._updateHash(this.iframe.location,t,e.replace)}}else{return this.location.assign(i)}if(e.trigger)return this.loadUrl(t)},_updateHash:function(t,e,i){if(i){var r=t.href.replace(/(javascript:|#).*$/,"");t.replace(r+"#"+e)}else{t.hash="#"+e}}});a.history=new I;var R=function(t,e){var i=this;var r;if(t&&h.has(t,"constructor")){r=t.constructor}else{r=function(){return i.apply(this,arguments)}}h.extend(r,i,e);var s=function(){this.constructor=r};s.prototype=i.prototype;r.prototype=new s;if(t)h.extend(r.prototype,t);r.__super__=i.prototype;return r};d.extend=v.extend=k.extend=w.extend=I.extend=R;var U=function(){throw new Error('A "url" property or function must be specified')};var M=function(t,e){var i=e.error;e.error=function(r){if(i)i(t,r,e);t.trigger("error",t,r,e)}}}).call(this);
@@ -0,0 +1,2118 @@
1
+ /*!
2
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
3
+ * Copyright 2011-2014 Twitter, Inc.
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5
+ */
6
+
7
+ /*!
8
+ * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=5fd8abcabe46be29123b)
9
+ * Config saved to config.json and https://gist.github.com/5fd8abcabe46be29123b
10
+ */
11
+ if (typeof jQuery === "undefined") { throw new Error("Bootstrap's JavaScript requires jQuery") }
12
+
13
+ /* ========================================================================
14
+ * Bootstrap: alert.js v3.2.0
15
+ * http://getbootstrap.com/javascript/#alerts
16
+ * ========================================================================
17
+ * Copyright 2011-2014 Twitter, Inc.
18
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
19
+ * ======================================================================== */
20
+
21
+
22
+ +function ($) {
23
+ 'use strict';
24
+
25
+ // ALERT CLASS DEFINITION
26
+ // ======================
27
+
28
+ var dismiss = '[data-dismiss="alert"]'
29
+ var Alert = function (el) {
30
+ $(el).on('click', dismiss, this.close)
31
+ }
32
+
33
+ Alert.VERSION = '3.2.0'
34
+
35
+ Alert.prototype.close = function (e) {
36
+ var $this = $(this)
37
+ var selector = $this.attr('data-target')
38
+
39
+ if (!selector) {
40
+ selector = $this.attr('href')
41
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
42
+ }
43
+
44
+ var $parent = $(selector)
45
+
46
+ if (e) e.preventDefault()
47
+
48
+ if (!$parent.length) {
49
+ $parent = $this.hasClass('alert') ? $this : $this.parent()
50
+ }
51
+
52
+ $parent.trigger(e = $.Event('close.bs.alert'))
53
+
54
+ if (e.isDefaultPrevented()) return
55
+
56
+ $parent.removeClass('in')
57
+
58
+ function removeElement() {
59
+ // detach from parent, fire event then clean up data
60
+ $parent.detach().trigger('closed.bs.alert').remove()
61
+ }
62
+
63
+ $.support.transition && $parent.hasClass('fade') ?
64
+ $parent
65
+ .one('bsTransitionEnd', removeElement)
66
+ .emulateTransitionEnd(150) :
67
+ removeElement()
68
+ }
69
+
70
+
71
+ // ALERT PLUGIN DEFINITION
72
+ // =======================
73
+
74
+ function Plugin(option) {
75
+ return this.each(function () {
76
+ var $this = $(this)
77
+ var data = $this.data('bs.alert')
78
+
79
+ if (!data) $this.data('bs.alert', (data = new Alert(this)))
80
+ if (typeof option == 'string') data[option].call($this)
81
+ })
82
+ }
83
+
84
+ var old = $.fn.alert
85
+
86
+ $.fn.alert = Plugin
87
+ $.fn.alert.Constructor = Alert
88
+
89
+
90
+ // ALERT NO CONFLICT
91
+ // =================
92
+
93
+ $.fn.alert.noConflict = function () {
94
+ $.fn.alert = old
95
+ return this
96
+ }
97
+
98
+
99
+ // ALERT DATA-API
100
+ // ==============
101
+
102
+ $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
103
+
104
+ }(jQuery);
105
+
106
+ /* ========================================================================
107
+ * Bootstrap: button.js v3.2.0
108
+ * http://getbootstrap.com/javascript/#buttons
109
+ * ========================================================================
110
+ * Copyright 2011-2014 Twitter, Inc.
111
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
112
+ * ======================================================================== */
113
+
114
+
115
+ +function ($) {
116
+ 'use strict';
117
+
118
+ // BUTTON PUBLIC CLASS DEFINITION
119
+ // ==============================
120
+
121
+ var Button = function (element, options) {
122
+ this.$element = $(element)
123
+ this.options = $.extend({}, Button.DEFAULTS, options)
124
+ this.isLoading = false
125
+ }
126
+
127
+ Button.VERSION = '3.2.0'
128
+
129
+ Button.DEFAULTS = {
130
+ loadingText: 'loading...'
131
+ }
132
+
133
+ Button.prototype.setState = function (state) {
134
+ var d = 'disabled'
135
+ var $el = this.$element
136
+ var val = $el.is('input') ? 'val' : 'html'
137
+ var data = $el.data()
138
+
139
+ state = state + 'Text'
140
+
141
+ if (data.resetText == null) $el.data('resetText', $el[val]())
142
+
143
+ $el[val](data[state] == null ? this.options[state] : data[state])
144
+
145
+ // push to event loop to allow forms to submit
146
+ setTimeout($.proxy(function () {
147
+ if (state == 'loadingText') {
148
+ this.isLoading = true
149
+ $el.addClass(d).attr(d, d)
150
+ } else if (this.isLoading) {
151
+ this.isLoading = false
152
+ $el.removeClass(d).removeAttr(d)
153
+ }
154
+ }, this), 0)
155
+ }
156
+
157
+ Button.prototype.toggle = function () {
158
+ var changed = true
159
+ var $parent = this.$element.closest('[data-toggle="buttons"]')
160
+
161
+ if ($parent.length) {
162
+ var $input = this.$element.find('input')
163
+ if ($input.prop('type') == 'radio') {
164
+ if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
165
+ else $parent.find('.active').removeClass('active')
166
+ }
167
+ if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
168
+ }
169
+
170
+ if (changed) this.$element.toggleClass('active')
171
+ }
172
+
173
+
174
+ // BUTTON PLUGIN DEFINITION
175
+ // ========================
176
+
177
+ function Plugin(option) {
178
+ return this.each(function () {
179
+ var $this = $(this)
180
+ var data = $this.data('bs.button')
181
+ var options = typeof option == 'object' && option
182
+
183
+ if (!data) $this.data('bs.button', (data = new Button(this, options)))
184
+
185
+ if (option == 'toggle') data.toggle()
186
+ else if (option) data.setState(option)
187
+ })
188
+ }
189
+
190
+ var old = $.fn.button
191
+
192
+ $.fn.button = Plugin
193
+ $.fn.button.Constructor = Button
194
+
195
+
196
+ // BUTTON NO CONFLICT
197
+ // ==================
198
+
199
+ $.fn.button.noConflict = function () {
200
+ $.fn.button = old
201
+ return this
202
+ }
203
+
204
+
205
+ // BUTTON DATA-API
206
+ // ===============
207
+
208
+ $(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
209
+ var $btn = $(e.target)
210
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
211
+ Plugin.call($btn, 'toggle')
212
+ e.preventDefault()
213
+ })
214
+
215
+ }(jQuery);
216
+
217
+ /* ========================================================================
218
+ * Bootstrap: carousel.js v3.2.0
219
+ * http://getbootstrap.com/javascript/#carousel
220
+ * ========================================================================
221
+ * Copyright 2011-2014 Twitter, Inc.
222
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
223
+ * ======================================================================== */
224
+
225
+
226
+ +function ($) {
227
+ 'use strict';
228
+
229
+ // CAROUSEL CLASS DEFINITION
230
+ // =========================
231
+
232
+ var Carousel = function (element, options) {
233
+ this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
234
+ this.$indicators = this.$element.find('.carousel-indicators')
235
+ this.options = options
236
+ this.paused =
237
+ this.sliding =
238
+ this.interval =
239
+ this.$active =
240
+ this.$items = null
241
+
242
+ this.options.pause == 'hover' && this.$element
243
+ .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
244
+ .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
245
+ }
246
+
247
+ Carousel.VERSION = '3.2.0'
248
+
249
+ Carousel.DEFAULTS = {
250
+ interval: 5000,
251
+ pause: 'hover',
252
+ wrap: true
253
+ }
254
+
255
+ Carousel.prototype.keydown = function (e) {
256
+ switch (e.which) {
257
+ case 37: this.prev(); break
258
+ case 39: this.next(); break
259
+ default: return
260
+ }
261
+
262
+ e.preventDefault()
263
+ }
264
+
265
+ Carousel.prototype.cycle = function (e) {
266
+ e || (this.paused = false)
267
+
268
+ this.interval && clearInterval(this.interval)
269
+
270
+ this.options.interval
271
+ && !this.paused
272
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
273
+
274
+ return this
275
+ }
276
+
277
+ Carousel.prototype.getItemIndex = function (item) {
278
+ this.$items = item.parent().children('.item')
279
+ return this.$items.index(item || this.$active)
280
+ }
281
+
282
+ Carousel.prototype.to = function (pos) {
283
+ var that = this
284
+ var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
285
+
286
+ if (pos > (this.$items.length - 1) || pos < 0) return
287
+
288
+ if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
289
+ if (activeIndex == pos) return this.pause().cycle()
290
+
291
+ return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
292
+ }
293
+
294
+ Carousel.prototype.pause = function (e) {
295
+ e || (this.paused = true)
296
+
297
+ if (this.$element.find('.next, .prev').length && $.support.transition) {
298
+ this.$element.trigger($.support.transition.end)
299
+ this.cycle(true)
300
+ }
301
+
302
+ this.interval = clearInterval(this.interval)
303
+
304
+ return this
305
+ }
306
+
307
+ Carousel.prototype.next = function () {
308
+ if (this.sliding) return
309
+ return this.slide('next')
310
+ }
311
+
312
+ Carousel.prototype.prev = function () {
313
+ if (this.sliding) return
314
+ return this.slide('prev')
315
+ }
316
+
317
+ Carousel.prototype.slide = function (type, next) {
318
+ var $active = this.$element.find('.item.active')
319
+ var $next = next || $active[type]()
320
+ var isCycling = this.interval
321
+ var direction = type == 'next' ? 'left' : 'right'
322
+ var fallback = type == 'next' ? 'first' : 'last'
323
+ var that = this
324
+
325
+ if (!$next.length) {
326
+ if (!this.options.wrap) return
327
+ $next = this.$element.find('.item')[fallback]()
328
+ }
329
+
330
+ if ($next.hasClass('active')) return (this.sliding = false)
331
+
332
+ var relatedTarget = $next[0]
333
+ var slideEvent = $.Event('slide.bs.carousel', {
334
+ relatedTarget: relatedTarget,
335
+ direction: direction
336
+ })
337
+ this.$element.trigger(slideEvent)
338
+ if (slideEvent.isDefaultPrevented()) return
339
+
340
+ this.sliding = true
341
+
342
+ isCycling && this.pause()
343
+
344
+ if (this.$indicators.length) {
345
+ this.$indicators.find('.active').removeClass('active')
346
+ var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
347
+ $nextIndicator && $nextIndicator.addClass('active')
348
+ }
349
+
350
+ var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
351
+ if ($.support.transition && this.$element.hasClass('slide')) {
352
+ $next.addClass(type)
353
+ $next[0].offsetWidth // force reflow
354
+ $active.addClass(direction)
355
+ $next.addClass(direction)
356
+ $active
357
+ .one('bsTransitionEnd', function () {
358
+ $next.removeClass([type, direction].join(' ')).addClass('active')
359
+ $active.removeClass(['active', direction].join(' '))
360
+ that.sliding = false
361
+ setTimeout(function () {
362
+ that.$element.trigger(slidEvent)
363
+ }, 0)
364
+ })
365
+ .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)
366
+ } else {
367
+ $active.removeClass('active')
368
+ $next.addClass('active')
369
+ this.sliding = false
370
+ this.$element.trigger(slidEvent)
371
+ }
372
+
373
+ isCycling && this.cycle()
374
+
375
+ return this
376
+ }
377
+
378
+
379
+ // CAROUSEL PLUGIN DEFINITION
380
+ // ==========================
381
+
382
+ function Plugin(option) {
383
+ return this.each(function () {
384
+ var $this = $(this)
385
+ var data = $this.data('bs.carousel')
386
+ var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
387
+ var action = typeof option == 'string' ? option : options.slide
388
+
389
+ if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
390
+ if (typeof option == 'number') data.to(option)
391
+ else if (action) data[action]()
392
+ else if (options.interval) data.pause().cycle()
393
+ })
394
+ }
395
+
396
+ var old = $.fn.carousel
397
+
398
+ $.fn.carousel = Plugin
399
+ $.fn.carousel.Constructor = Carousel
400
+
401
+
402
+ // CAROUSEL NO CONFLICT
403
+ // ====================
404
+
405
+ $.fn.carousel.noConflict = function () {
406
+ $.fn.carousel = old
407
+ return this
408
+ }
409
+
410
+
411
+ // CAROUSEL DATA-API
412
+ // =================
413
+
414
+ $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
415
+ var href
416
+ var $this = $(this)
417
+ var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
418
+ if (!$target.hasClass('carousel')) return
419
+ var options = $.extend({}, $target.data(), $this.data())
420
+ var slideIndex = $this.attr('data-slide-to')
421
+ if (slideIndex) options.interval = false
422
+
423
+ Plugin.call($target, options)
424
+
425
+ if (slideIndex) {
426
+ $target.data('bs.carousel').to(slideIndex)
427
+ }
428
+
429
+ e.preventDefault()
430
+ })
431
+
432
+ $(window).on('load', function () {
433
+ $('[data-ride="carousel"]').each(function () {
434
+ var $carousel = $(this)
435
+ Plugin.call($carousel, $carousel.data())
436
+ })
437
+ })
438
+
439
+ }(jQuery);
440
+
441
+ /* ========================================================================
442
+ * Bootstrap: dropdown.js v3.2.0
443
+ * http://getbootstrap.com/javascript/#dropdowns
444
+ * ========================================================================
445
+ * Copyright 2011-2014 Twitter, Inc.
446
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
447
+ * ======================================================================== */
448
+
449
+
450
+ +function ($) {
451
+ 'use strict';
452
+
453
+ // DROPDOWN CLASS DEFINITION
454
+ // =========================
455
+
456
+ var backdrop = '.dropdown-backdrop'
457
+ var toggle = '[data-toggle="dropdown"]'
458
+ var Dropdown = function (element) {
459
+ $(element).on('click.bs.dropdown', this.toggle)
460
+ }
461
+
462
+ Dropdown.VERSION = '3.2.0'
463
+
464
+ Dropdown.prototype.toggle = function (e) {
465
+ var $this = $(this)
466
+
467
+ if ($this.is('.disabled, :disabled')) return
468
+
469
+ var $parent = getParent($this)
470
+ var isActive = $parent.hasClass('open')
471
+
472
+ clearMenus()
473
+
474
+ if (!isActive) {
475
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
476
+ // if mobile we use a backdrop because click events don't delegate
477
+ $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
478
+ }
479
+
480
+ var relatedTarget = { relatedTarget: this }
481
+ $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
482
+
483
+ if (e.isDefaultPrevented()) return
484
+
485
+ $this.trigger('focus')
486
+
487
+ $parent
488
+ .toggleClass('open')
489
+ .trigger('shown.bs.dropdown', relatedTarget)
490
+ }
491
+
492
+ return false
493
+ }
494
+
495
+ Dropdown.prototype.keydown = function (e) {
496
+ if (!/(38|40|27)/.test(e.keyCode)) return
497
+
498
+ var $this = $(this)
499
+
500
+ e.preventDefault()
501
+ e.stopPropagation()
502
+
503
+ if ($this.is('.disabled, :disabled')) return
504
+
505
+ var $parent = getParent($this)
506
+ var isActive = $parent.hasClass('open')
507
+
508
+ if (!isActive || (isActive && e.keyCode == 27)) {
509
+ if (e.which == 27) $parent.find(toggle).trigger('focus')
510
+ return $this.trigger('click')
511
+ }
512
+
513
+ var desc = ' li:not(.divider):visible a'
514
+ var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
515
+
516
+ if (!$items.length) return
517
+
518
+ var index = $items.index($items.filter(':focus'))
519
+
520
+ if (e.keyCode == 38 && index > 0) index-- // up
521
+ if (e.keyCode == 40 && index < $items.length - 1) index++ // down
522
+ if (!~index) index = 0
523
+
524
+ $items.eq(index).trigger('focus')
525
+ }
526
+
527
+ function clearMenus(e) {
528
+ if (e && e.which === 3) return
529
+ $(backdrop).remove()
530
+ $(toggle).each(function () {
531
+ var $parent = getParent($(this))
532
+ var relatedTarget = { relatedTarget: this }
533
+ if (!$parent.hasClass('open')) return
534
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
535
+ if (e.isDefaultPrevented()) return
536
+ $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
537
+ })
538
+ }
539
+
540
+ function getParent($this) {
541
+ var selector = $this.attr('data-target')
542
+
543
+ if (!selector) {
544
+ selector = $this.attr('href')
545
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
546
+ }
547
+
548
+ var $parent = selector && $(selector)
549
+
550
+ return $parent && $parent.length ? $parent : $this.parent()
551
+ }
552
+
553
+
554
+ // DROPDOWN PLUGIN DEFINITION
555
+ // ==========================
556
+
557
+ function Plugin(option) {
558
+ return this.each(function () {
559
+ var $this = $(this)
560
+ var data = $this.data('bs.dropdown')
561
+
562
+ if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
563
+ if (typeof option == 'string') data[option].call($this)
564
+ })
565
+ }
566
+
567
+ var old = $.fn.dropdown
568
+
569
+ $.fn.dropdown = Plugin
570
+ $.fn.dropdown.Constructor = Dropdown
571
+
572
+
573
+ // DROPDOWN NO CONFLICT
574
+ // ====================
575
+
576
+ $.fn.dropdown.noConflict = function () {
577
+ $.fn.dropdown = old
578
+ return this
579
+ }
580
+
581
+
582
+ // APPLY TO STANDARD DROPDOWN ELEMENTS
583
+ // ===================================
584
+
585
+ $(document)
586
+ .on('click.bs.dropdown.data-api', clearMenus)
587
+ .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
588
+ .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
589
+ .on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown)
590
+
591
+ }(jQuery);
592
+
593
+ /* ========================================================================
594
+ * Bootstrap: modal.js v3.2.0
595
+ * http://getbootstrap.com/javascript/#modals
596
+ * ========================================================================
597
+ * Copyright 2011-2014 Twitter, Inc.
598
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
599
+ * ======================================================================== */
600
+
601
+
602
+ +function ($) {
603
+ 'use strict';
604
+
605
+ // MODAL CLASS DEFINITION
606
+ // ======================
607
+
608
+ var Modal = function (element, options) {
609
+ this.options = options
610
+ this.$body = $(document.body)
611
+ this.$element = $(element)
612
+ this.$backdrop =
613
+ this.isShown = null
614
+ this.scrollbarWidth = 0
615
+
616
+ if (this.options.remote) {
617
+ this.$element
618
+ .find('.modal-content')
619
+ .load(this.options.remote, $.proxy(function () {
620
+ this.$element.trigger('loaded.bs.modal')
621
+ }, this))
622
+ }
623
+ }
624
+
625
+ Modal.VERSION = '3.2.0'
626
+
627
+ Modal.DEFAULTS = {
628
+ backdrop: true,
629
+ keyboard: true,
630
+ show: true
631
+ }
632
+
633
+ Modal.prototype.toggle = function (_relatedTarget) {
634
+ return this.isShown ? this.hide() : this.show(_relatedTarget)
635
+ }
636
+
637
+ Modal.prototype.show = function (_relatedTarget) {
638
+ var that = this
639
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
640
+
641
+ this.$element.trigger(e)
642
+
643
+ if (this.isShown || e.isDefaultPrevented()) return
644
+
645
+ this.isShown = true
646
+
647
+ this.checkScrollbar()
648
+ this.$body.addClass('modal-open')
649
+
650
+ this.setScrollbar()
651
+ this.escape()
652
+
653
+ this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
654
+
655
+ this.backdrop(function () {
656
+ var transition = $.support.transition && that.$element.hasClass('fade')
657
+
658
+ if (!that.$element.parent().length) {
659
+ that.$element.appendTo(that.$body) // don't move modals dom position
660
+ }
661
+
662
+ that.$element
663
+ .show()
664
+ .scrollTop(0)
665
+
666
+ if (transition) {
667
+ that.$element[0].offsetWidth // force reflow
668
+ }
669
+
670
+ that.$element
671
+ .addClass('in')
672
+ .attr('aria-hidden', false)
673
+
674
+ that.enforceFocus()
675
+
676
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
677
+
678
+ transition ?
679
+ that.$element.find('.modal-dialog') // wait for modal to slide in
680
+ .one('bsTransitionEnd', function () {
681
+ that.$element.trigger('focus').trigger(e)
682
+ })
683
+ .emulateTransitionEnd(300) :
684
+ that.$element.trigger('focus').trigger(e)
685
+ })
686
+ }
687
+
688
+ Modal.prototype.hide = function (e) {
689
+ if (e) e.preventDefault()
690
+
691
+ e = $.Event('hide.bs.modal')
692
+
693
+ this.$element.trigger(e)
694
+
695
+ if (!this.isShown || e.isDefaultPrevented()) return
696
+
697
+ this.isShown = false
698
+
699
+ this.$body.removeClass('modal-open')
700
+
701
+ this.resetScrollbar()
702
+ this.escape()
703
+
704
+ $(document).off('focusin.bs.modal')
705
+
706
+ this.$element
707
+ .removeClass('in')
708
+ .attr('aria-hidden', true)
709
+ .off('click.dismiss.bs.modal')
710
+
711
+ $.support.transition && this.$element.hasClass('fade') ?
712
+ this.$element
713
+ .one('bsTransitionEnd', $.proxy(this.hideModal, this))
714
+ .emulateTransitionEnd(300) :
715
+ this.hideModal()
716
+ }
717
+
718
+ Modal.prototype.enforceFocus = function () {
719
+ $(document)
720
+ .off('focusin.bs.modal') // guard against infinite focus loop
721
+ .on('focusin.bs.modal', $.proxy(function (e) {
722
+ if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
723
+ this.$element.trigger('focus')
724
+ }
725
+ }, this))
726
+ }
727
+
728
+ Modal.prototype.escape = function () {
729
+ if (this.isShown && this.options.keyboard) {
730
+ this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
731
+ e.which == 27 && this.hide()
732
+ }, this))
733
+ } else if (!this.isShown) {
734
+ this.$element.off('keyup.dismiss.bs.modal')
735
+ }
736
+ }
737
+
738
+ Modal.prototype.hideModal = function () {
739
+ var that = this
740
+ this.$element.hide()
741
+ this.backdrop(function () {
742
+ that.$element.trigger('hidden.bs.modal')
743
+ })
744
+ }
745
+
746
+ Modal.prototype.removeBackdrop = function () {
747
+ this.$backdrop && this.$backdrop.remove()
748
+ this.$backdrop = null
749
+ }
750
+
751
+ Modal.prototype.backdrop = function (callback) {
752
+ var that = this
753
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
754
+
755
+ if (this.isShown && this.options.backdrop) {
756
+ var doAnimate = $.support.transition && animate
757
+
758
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
759
+ .appendTo(this.$body)
760
+
761
+ this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
762
+ if (e.target !== e.currentTarget) return
763
+ this.options.backdrop == 'static'
764
+ ? this.$element[0].focus.call(this.$element[0])
765
+ : this.hide.call(this)
766
+ }, this))
767
+
768
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
769
+
770
+ this.$backdrop.addClass('in')
771
+
772
+ if (!callback) return
773
+
774
+ doAnimate ?
775
+ this.$backdrop
776
+ .one('bsTransitionEnd', callback)
777
+ .emulateTransitionEnd(150) :
778
+ callback()
779
+
780
+ } else if (!this.isShown && this.$backdrop) {
781
+ this.$backdrop.removeClass('in')
782
+
783
+ var callbackRemove = function () {
784
+ that.removeBackdrop()
785
+ callback && callback()
786
+ }
787
+ $.support.transition && this.$element.hasClass('fade') ?
788
+ this.$backdrop
789
+ .one('bsTransitionEnd', callbackRemove)
790
+ .emulateTransitionEnd(150) :
791
+ callbackRemove()
792
+
793
+ } else if (callback) {
794
+ callback()
795
+ }
796
+ }
797
+
798
+ Modal.prototype.checkScrollbar = function () {
799
+ if (document.body.clientWidth >= window.innerWidth) return
800
+ this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar()
801
+ }
802
+
803
+ Modal.prototype.setScrollbar = function () {
804
+ var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
805
+ if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
806
+ }
807
+
808
+ Modal.prototype.resetScrollbar = function () {
809
+ this.$body.css('padding-right', '')
810
+ }
811
+
812
+ Modal.prototype.measureScrollbar = function () { // thx walsh
813
+ var scrollDiv = document.createElement('div')
814
+ scrollDiv.className = 'modal-scrollbar-measure'
815
+ this.$body.append(scrollDiv)
816
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
817
+ this.$body[0].removeChild(scrollDiv)
818
+ return scrollbarWidth
819
+ }
820
+
821
+
822
+ // MODAL PLUGIN DEFINITION
823
+ // =======================
824
+
825
+ function Plugin(option, _relatedTarget) {
826
+ return this.each(function () {
827
+ var $this = $(this)
828
+ var data = $this.data('bs.modal')
829
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
830
+
831
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
832
+ if (typeof option == 'string') data[option](_relatedTarget)
833
+ else if (options.show) data.show(_relatedTarget)
834
+ })
835
+ }
836
+
837
+ var old = $.fn.modal
838
+
839
+ $.fn.modal = Plugin
840
+ $.fn.modal.Constructor = Modal
841
+
842
+
843
+ // MODAL NO CONFLICT
844
+ // =================
845
+
846
+ $.fn.modal.noConflict = function () {
847
+ $.fn.modal = old
848
+ return this
849
+ }
850
+
851
+
852
+ // MODAL DATA-API
853
+ // ==============
854
+
855
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
856
+ var $this = $(this)
857
+ var href = $this.attr('href')
858
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
859
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
860
+
861
+ if ($this.is('a')) e.preventDefault()
862
+
863
+ $target.one('show.bs.modal', function (showEvent) {
864
+ if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
865
+ $target.one('hidden.bs.modal', function () {
866
+ $this.is(':visible') && $this.trigger('focus')
867
+ })
868
+ })
869
+ Plugin.call($target, option, this)
870
+ })
871
+
872
+ }(jQuery);
873
+
874
+ /* ========================================================================
875
+ * Bootstrap: tooltip.js v3.2.0
876
+ * http://getbootstrap.com/javascript/#tooltip
877
+ * Inspired by the original jQuery.tipsy by Jason Frame
878
+ * ========================================================================
879
+ * Copyright 2011-2014 Twitter, Inc.
880
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
881
+ * ======================================================================== */
882
+
883
+
884
+ +function ($) {
885
+ 'use strict';
886
+
887
+ // TOOLTIP PUBLIC CLASS DEFINITION
888
+ // ===============================
889
+
890
+ var Tooltip = function (element, options) {
891
+ this.type =
892
+ this.options =
893
+ this.enabled =
894
+ this.timeout =
895
+ this.hoverState =
896
+ this.$element = null
897
+
898
+ this.init('tooltip', element, options)
899
+ }
900
+
901
+ Tooltip.VERSION = '3.2.0'
902
+
903
+ Tooltip.DEFAULTS = {
904
+ animation: true,
905
+ placement: 'top',
906
+ selector: false,
907
+ template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
908
+ trigger: 'hover focus',
909
+ title: '',
910
+ delay: 0,
911
+ html: false,
912
+ container: false,
913
+ viewport: {
914
+ selector: 'body',
915
+ padding: 0
916
+ }
917
+ }
918
+
919
+ Tooltip.prototype.init = function (type, element, options) {
920
+ this.enabled = true
921
+ this.type = type
922
+ this.$element = $(element)
923
+ this.options = this.getOptions(options)
924
+ this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
925
+
926
+ var triggers = this.options.trigger.split(' ')
927
+
928
+ for (var i = triggers.length; i--;) {
929
+ var trigger = triggers[i]
930
+
931
+ if (trigger == 'click') {
932
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
933
+ } else if (trigger != 'manual') {
934
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
935
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
936
+
937
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
938
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
939
+ }
940
+ }
941
+
942
+ this.options.selector ?
943
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
944
+ this.fixTitle()
945
+ }
946
+
947
+ Tooltip.prototype.getDefaults = function () {
948
+ return Tooltip.DEFAULTS
949
+ }
950
+
951
+ Tooltip.prototype.getOptions = function (options) {
952
+ options = $.extend({}, this.getDefaults(), this.$element.data(), options)
953
+
954
+ if (options.delay && typeof options.delay == 'number') {
955
+ options.delay = {
956
+ show: options.delay,
957
+ hide: options.delay
958
+ }
959
+ }
960
+
961
+ return options
962
+ }
963
+
964
+ Tooltip.prototype.getDelegateOptions = function () {
965
+ var options = {}
966
+ var defaults = this.getDefaults()
967
+
968
+ this._options && $.each(this._options, function (key, value) {
969
+ if (defaults[key] != value) options[key] = value
970
+ })
971
+
972
+ return options
973
+ }
974
+
975
+ Tooltip.prototype.enter = function (obj) {
976
+ var self = obj instanceof this.constructor ?
977
+ obj : $(obj.currentTarget).data('bs.' + this.type)
978
+
979
+ if (!self) {
980
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
981
+ $(obj.currentTarget).data('bs.' + this.type, self)
982
+ }
983
+
984
+ clearTimeout(self.timeout)
985
+
986
+ self.hoverState = 'in'
987
+
988
+ if (!self.options.delay || !self.options.delay.show) return self.show()
989
+
990
+ self.timeout = setTimeout(function () {
991
+ if (self.hoverState == 'in') self.show()
992
+ }, self.options.delay.show)
993
+ }
994
+
995
+ Tooltip.prototype.leave = function (obj) {
996
+ var self = obj instanceof this.constructor ?
997
+ obj : $(obj.currentTarget).data('bs.' + this.type)
998
+
999
+ if (!self) {
1000
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1001
+ $(obj.currentTarget).data('bs.' + this.type, self)
1002
+ }
1003
+
1004
+ clearTimeout(self.timeout)
1005
+
1006
+ self.hoverState = 'out'
1007
+
1008
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
1009
+
1010
+ self.timeout = setTimeout(function () {
1011
+ if (self.hoverState == 'out') self.hide()
1012
+ }, self.options.delay.hide)
1013
+ }
1014
+
1015
+ Tooltip.prototype.show = function () {
1016
+ var e = $.Event('show.bs.' + this.type)
1017
+
1018
+ if (this.hasContent() && this.enabled) {
1019
+ this.$element.trigger(e)
1020
+
1021
+ var inDom = $.contains(document.documentElement, this.$element[0])
1022
+ if (e.isDefaultPrevented() || !inDom) return
1023
+ var that = this
1024
+
1025
+ var $tip = this.tip()
1026
+
1027
+ var tipId = this.getUID(this.type)
1028
+
1029
+ this.setContent()
1030
+ $tip.attr('id', tipId)
1031
+ this.$element.attr('aria-describedby', tipId)
1032
+
1033
+ if (this.options.animation) $tip.addClass('fade')
1034
+
1035
+ var placement = typeof this.options.placement == 'function' ?
1036
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
1037
+ this.options.placement
1038
+
1039
+ var autoToken = /\s?auto?\s?/i
1040
+ var autoPlace = autoToken.test(placement)
1041
+ if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1042
+
1043
+ $tip
1044
+ .detach()
1045
+ .css({ top: 0, left: 0, display: 'block' })
1046
+ .addClass(placement)
1047
+ .data('bs.' + this.type, this)
1048
+
1049
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1050
+
1051
+ var pos = this.getPosition()
1052
+ var actualWidth = $tip[0].offsetWidth
1053
+ var actualHeight = $tip[0].offsetHeight
1054
+
1055
+ if (autoPlace) {
1056
+ var orgPlacement = placement
1057
+ var $parent = this.$element.parent()
1058
+ var parentDim = this.getPosition($parent)
1059
+
1060
+ placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
1061
+ placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
1062
+ placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
1063
+ placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
1064
+ placement
1065
+
1066
+ $tip
1067
+ .removeClass(orgPlacement)
1068
+ .addClass(placement)
1069
+ }
1070
+
1071
+ var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1072
+
1073
+ this.applyPlacement(calculatedOffset, placement)
1074
+
1075
+ var complete = function () {
1076
+ that.$element.trigger('shown.bs.' + that.type)
1077
+ that.hoverState = null
1078
+ }
1079
+
1080
+ $.support.transition && this.$tip.hasClass('fade') ?
1081
+ $tip
1082
+ .one('bsTransitionEnd', complete)
1083
+ .emulateTransitionEnd(150) :
1084
+ complete()
1085
+ }
1086
+ }
1087
+
1088
+ Tooltip.prototype.applyPlacement = function (offset, placement) {
1089
+ var $tip = this.tip()
1090
+ var width = $tip[0].offsetWidth
1091
+ var height = $tip[0].offsetHeight
1092
+
1093
+ // manually read margins because getBoundingClientRect includes difference
1094
+ var marginTop = parseInt($tip.css('margin-top'), 10)
1095
+ var marginLeft = parseInt($tip.css('margin-left'), 10)
1096
+
1097
+ // we must check for NaN for ie 8/9
1098
+ if (isNaN(marginTop)) marginTop = 0
1099
+ if (isNaN(marginLeft)) marginLeft = 0
1100
+
1101
+ offset.top = offset.top + marginTop
1102
+ offset.left = offset.left + marginLeft
1103
+
1104
+ // $.fn.offset doesn't round pixel values
1105
+ // so we use setOffset directly with our own function B-0
1106
+ $.offset.setOffset($tip[0], $.extend({
1107
+ using: function (props) {
1108
+ $tip.css({
1109
+ top: Math.round(props.top),
1110
+ left: Math.round(props.left)
1111
+ })
1112
+ }
1113
+ }, offset), 0)
1114
+
1115
+ $tip.addClass('in')
1116
+
1117
+ // check to see if placing tip in new offset caused the tip to resize itself
1118
+ var actualWidth = $tip[0].offsetWidth
1119
+ var actualHeight = $tip[0].offsetHeight
1120
+
1121
+ if (placement == 'top' && actualHeight != height) {
1122
+ offset.top = offset.top + height - actualHeight
1123
+ }
1124
+
1125
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
1126
+
1127
+ if (delta.left) offset.left += delta.left
1128
+ else offset.top += delta.top
1129
+
1130
+ var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
1131
+ var arrowPosition = delta.left ? 'left' : 'top'
1132
+ var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
1133
+
1134
+ $tip.offset(offset)
1135
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
1136
+ }
1137
+
1138
+ Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
1139
+ this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
1140
+ }
1141
+
1142
+ Tooltip.prototype.setContent = function () {
1143
+ var $tip = this.tip()
1144
+ var title = this.getTitle()
1145
+
1146
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1147
+ $tip.removeClass('fade in top bottom left right')
1148
+ }
1149
+
1150
+ Tooltip.prototype.hide = function () {
1151
+ var that = this
1152
+ var $tip = this.tip()
1153
+ var e = $.Event('hide.bs.' + this.type)
1154
+
1155
+ this.$element.removeAttr('aria-describedby')
1156
+
1157
+ function complete() {
1158
+ if (that.hoverState != 'in') $tip.detach()
1159
+ that.$element.trigger('hidden.bs.' + that.type)
1160
+ }
1161
+
1162
+ this.$element.trigger(e)
1163
+
1164
+ if (e.isDefaultPrevented()) return
1165
+
1166
+ $tip.removeClass('in')
1167
+
1168
+ $.support.transition && this.$tip.hasClass('fade') ?
1169
+ $tip
1170
+ .one('bsTransitionEnd', complete)
1171
+ .emulateTransitionEnd(150) :
1172
+ complete()
1173
+
1174
+ this.hoverState = null
1175
+
1176
+ return this
1177
+ }
1178
+
1179
+ Tooltip.prototype.fixTitle = function () {
1180
+ var $e = this.$element
1181
+ if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
1182
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1183
+ }
1184
+ }
1185
+
1186
+ Tooltip.prototype.hasContent = function () {
1187
+ return this.getTitle()
1188
+ }
1189
+
1190
+ Tooltip.prototype.getPosition = function ($element) {
1191
+ $element = $element || this.$element
1192
+ var el = $element[0]
1193
+ var isBody = el.tagName == 'BODY'
1194
+ return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
1195
+ scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
1196
+ width: isBody ? $(window).width() : $element.outerWidth(),
1197
+ height: isBody ? $(window).height() : $element.outerHeight()
1198
+ }, isBody ? { top: 0, left: 0 } : $element.offset())
1199
+ }
1200
+
1201
+ Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
1202
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1203
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1204
+ placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
1205
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
1206
+
1207
+ }
1208
+
1209
+ Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
1210
+ var delta = { top: 0, left: 0 }
1211
+ if (!this.$viewport) return delta
1212
+
1213
+ var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
1214
+ var viewportDimensions = this.getPosition(this.$viewport)
1215
+
1216
+ if (/right|left/.test(placement)) {
1217
+ var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
1218
+ var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
1219
+ if (topEdgeOffset < viewportDimensions.top) { // top overflow
1220
+ delta.top = viewportDimensions.top - topEdgeOffset
1221
+ } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
1222
+ delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
1223
+ }
1224
+ } else {
1225
+ var leftEdgeOffset = pos.left - viewportPadding
1226
+ var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1227
+ if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1228
+ delta.left = viewportDimensions.left - leftEdgeOffset
1229
+ } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
1230
+ delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1231
+ }
1232
+ }
1233
+
1234
+ return delta
1235
+ }
1236
+
1237
+ Tooltip.prototype.getTitle = function () {
1238
+ var title
1239
+ var $e = this.$element
1240
+ var o = this.options
1241
+
1242
+ title = $e.attr('data-original-title')
1243
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
1244
+
1245
+ return title
1246
+ }
1247
+
1248
+ Tooltip.prototype.getUID = function (prefix) {
1249
+ do prefix += ~~(Math.random() * 1000000)
1250
+ while (document.getElementById(prefix))
1251
+ return prefix
1252
+ }
1253
+
1254
+ Tooltip.prototype.tip = function () {
1255
+ return (this.$tip = this.$tip || $(this.options.template))
1256
+ }
1257
+
1258
+ Tooltip.prototype.arrow = function () {
1259
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
1260
+ }
1261
+
1262
+ Tooltip.prototype.validate = function () {
1263
+ if (!this.$element[0].parentNode) {
1264
+ this.hide()
1265
+ this.$element = null
1266
+ this.options = null
1267
+ }
1268
+ }
1269
+
1270
+ Tooltip.prototype.enable = function () {
1271
+ this.enabled = true
1272
+ }
1273
+
1274
+ Tooltip.prototype.disable = function () {
1275
+ this.enabled = false
1276
+ }
1277
+
1278
+ Tooltip.prototype.toggleEnabled = function () {
1279
+ this.enabled = !this.enabled
1280
+ }
1281
+
1282
+ Tooltip.prototype.toggle = function (e) {
1283
+ var self = this
1284
+ if (e) {
1285
+ self = $(e.currentTarget).data('bs.' + this.type)
1286
+ if (!self) {
1287
+ self = new this.constructor(e.currentTarget, this.getDelegateOptions())
1288
+ $(e.currentTarget).data('bs.' + this.type, self)
1289
+ }
1290
+ }
1291
+
1292
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1293
+ }
1294
+
1295
+ Tooltip.prototype.destroy = function () {
1296
+ clearTimeout(this.timeout)
1297
+ this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
1298
+ }
1299
+
1300
+
1301
+ // TOOLTIP PLUGIN DEFINITION
1302
+ // =========================
1303
+
1304
+ function Plugin(option) {
1305
+ return this.each(function () {
1306
+ var $this = $(this)
1307
+ var data = $this.data('bs.tooltip')
1308
+ var options = typeof option == 'object' && option
1309
+
1310
+ if (!data && option == 'destroy') return
1311
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1312
+ if (typeof option == 'string') data[option]()
1313
+ })
1314
+ }
1315
+
1316
+ var old = $.fn.tooltip
1317
+
1318
+ $.fn.tooltip = Plugin
1319
+ $.fn.tooltip.Constructor = Tooltip
1320
+
1321
+
1322
+ // TOOLTIP NO CONFLICT
1323
+ // ===================
1324
+
1325
+ $.fn.tooltip.noConflict = function () {
1326
+ $.fn.tooltip = old
1327
+ return this
1328
+ }
1329
+
1330
+ }(jQuery);
1331
+
1332
+ /* ========================================================================
1333
+ * Bootstrap: popover.js v3.2.0
1334
+ * http://getbootstrap.com/javascript/#popovers
1335
+ * ========================================================================
1336
+ * Copyright 2011-2014 Twitter, Inc.
1337
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1338
+ * ======================================================================== */
1339
+
1340
+
1341
+ +function ($) {
1342
+ 'use strict';
1343
+
1344
+ // POPOVER PUBLIC CLASS DEFINITION
1345
+ // ===============================
1346
+
1347
+ var Popover = function (element, options) {
1348
+ this.init('popover', element, options)
1349
+ }
1350
+
1351
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1352
+
1353
+ Popover.VERSION = '3.2.0'
1354
+
1355
+ Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1356
+ placement: 'right',
1357
+ trigger: 'click',
1358
+ content: '',
1359
+ template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
1360
+ })
1361
+
1362
+
1363
+ // NOTE: POPOVER EXTENDS tooltip.js
1364
+ // ================================
1365
+
1366
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
1367
+
1368
+ Popover.prototype.constructor = Popover
1369
+
1370
+ Popover.prototype.getDefaults = function () {
1371
+ return Popover.DEFAULTS
1372
+ }
1373
+
1374
+ Popover.prototype.setContent = function () {
1375
+ var $tip = this.tip()
1376
+ var title = this.getTitle()
1377
+ var content = this.getContent()
1378
+
1379
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1380
+ $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events
1381
+ this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1382
+ ](content)
1383
+
1384
+ $tip.removeClass('fade top bottom left right in')
1385
+
1386
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
1387
+ // this manually by checking the contents.
1388
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
1389
+ }
1390
+
1391
+ Popover.prototype.hasContent = function () {
1392
+ return this.getTitle() || this.getContent()
1393
+ }
1394
+
1395
+ Popover.prototype.getContent = function () {
1396
+ var $e = this.$element
1397
+ var o = this.options
1398
+
1399
+ return $e.attr('data-content')
1400
+ || (typeof o.content == 'function' ?
1401
+ o.content.call($e[0]) :
1402
+ o.content)
1403
+ }
1404
+
1405
+ Popover.prototype.arrow = function () {
1406
+ return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
1407
+ }
1408
+
1409
+ Popover.prototype.tip = function () {
1410
+ if (!this.$tip) this.$tip = $(this.options.template)
1411
+ return this.$tip
1412
+ }
1413
+
1414
+
1415
+ // POPOVER PLUGIN DEFINITION
1416
+ // =========================
1417
+
1418
+ function Plugin(option) {
1419
+ return this.each(function () {
1420
+ var $this = $(this)
1421
+ var data = $this.data('bs.popover')
1422
+ var options = typeof option == 'object' && option
1423
+
1424
+ if (!data && option == 'destroy') return
1425
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
1426
+ if (typeof option == 'string') data[option]()
1427
+ })
1428
+ }
1429
+
1430
+ var old = $.fn.popover
1431
+
1432
+ $.fn.popover = Plugin
1433
+ $.fn.popover.Constructor = Popover
1434
+
1435
+
1436
+ // POPOVER NO CONFLICT
1437
+ // ===================
1438
+
1439
+ $.fn.popover.noConflict = function () {
1440
+ $.fn.popover = old
1441
+ return this
1442
+ }
1443
+
1444
+ }(jQuery);
1445
+
1446
+ /* ========================================================================
1447
+ * Bootstrap: tab.js v3.2.0
1448
+ * http://getbootstrap.com/javascript/#tabs
1449
+ * ========================================================================
1450
+ * Copyright 2011-2014 Twitter, Inc.
1451
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1452
+ * ======================================================================== */
1453
+
1454
+
1455
+ +function ($) {
1456
+ 'use strict';
1457
+
1458
+ // TAB CLASS DEFINITION
1459
+ // ====================
1460
+
1461
+ var Tab = function (element) {
1462
+ this.element = $(element)
1463
+ }
1464
+
1465
+ Tab.VERSION = '3.2.0'
1466
+
1467
+ Tab.prototype.show = function () {
1468
+ var $this = this.element
1469
+ var $ul = $this.closest('ul:not(.dropdown-menu)')
1470
+ var selector = $this.data('target')
1471
+
1472
+ if (!selector) {
1473
+ selector = $this.attr('href')
1474
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
1475
+ }
1476
+
1477
+ if ($this.parent('li').hasClass('active')) return
1478
+
1479
+ var previous = $ul.find('.active:last a')[0]
1480
+ var e = $.Event('show.bs.tab', {
1481
+ relatedTarget: previous
1482
+ })
1483
+
1484
+ $this.trigger(e)
1485
+
1486
+ if (e.isDefaultPrevented()) return
1487
+
1488
+ var $target = $(selector)
1489
+
1490
+ this.activate($this.closest('li'), $ul)
1491
+ this.activate($target, $target.parent(), function () {
1492
+ $this.trigger({
1493
+ type: 'shown.bs.tab',
1494
+ relatedTarget: previous
1495
+ })
1496
+ })
1497
+ }
1498
+
1499
+ Tab.prototype.activate = function (element, container, callback) {
1500
+ var $active = container.find('> .active')
1501
+ var transition = callback
1502
+ && $.support.transition
1503
+ && $active.hasClass('fade')
1504
+
1505
+ function next() {
1506
+ $active
1507
+ .removeClass('active')
1508
+ .find('> .dropdown-menu > .active')
1509
+ .removeClass('active')
1510
+
1511
+ element.addClass('active')
1512
+
1513
+ if (transition) {
1514
+ element[0].offsetWidth // reflow for transition
1515
+ element.addClass('in')
1516
+ } else {
1517
+ element.removeClass('fade')
1518
+ }
1519
+
1520
+ if (element.parent('.dropdown-menu')) {
1521
+ element.closest('li.dropdown').addClass('active')
1522
+ }
1523
+
1524
+ callback && callback()
1525
+ }
1526
+
1527
+ transition ?
1528
+ $active
1529
+ .one('bsTransitionEnd', next)
1530
+ .emulateTransitionEnd(150) :
1531
+ next()
1532
+
1533
+ $active.removeClass('in')
1534
+ }
1535
+
1536
+
1537
+ // TAB PLUGIN DEFINITION
1538
+ // =====================
1539
+
1540
+ function Plugin(option) {
1541
+ return this.each(function () {
1542
+ var $this = $(this)
1543
+ var data = $this.data('bs.tab')
1544
+
1545
+ if (!data) $this.data('bs.tab', (data = new Tab(this)))
1546
+ if (typeof option == 'string') data[option]()
1547
+ })
1548
+ }
1549
+
1550
+ var old = $.fn.tab
1551
+
1552
+ $.fn.tab = Plugin
1553
+ $.fn.tab.Constructor = Tab
1554
+
1555
+
1556
+ // TAB NO CONFLICT
1557
+ // ===============
1558
+
1559
+ $.fn.tab.noConflict = function () {
1560
+ $.fn.tab = old
1561
+ return this
1562
+ }
1563
+
1564
+
1565
+ // TAB DATA-API
1566
+ // ============
1567
+
1568
+ $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
1569
+ e.preventDefault()
1570
+ Plugin.call($(this), 'show')
1571
+ })
1572
+
1573
+ }(jQuery);
1574
+
1575
+ /* ========================================================================
1576
+ * Bootstrap: affix.js v3.2.0
1577
+ * http://getbootstrap.com/javascript/#affix
1578
+ * ========================================================================
1579
+ * Copyright 2011-2014 Twitter, Inc.
1580
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1581
+ * ======================================================================== */
1582
+
1583
+
1584
+ +function ($) {
1585
+ 'use strict';
1586
+
1587
+ // AFFIX CLASS DEFINITION
1588
+ // ======================
1589
+
1590
+ var Affix = function (element, options) {
1591
+ this.options = $.extend({}, Affix.DEFAULTS, options)
1592
+
1593
+ this.$target = $(this.options.target)
1594
+ .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
1595
+ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
1596
+
1597
+ this.$element = $(element)
1598
+ this.affixed =
1599
+ this.unpin =
1600
+ this.pinnedOffset = null
1601
+
1602
+ this.checkPosition()
1603
+ }
1604
+
1605
+ Affix.VERSION = '3.2.0'
1606
+
1607
+ Affix.RESET = 'affix affix-top affix-bottom'
1608
+
1609
+ Affix.DEFAULTS = {
1610
+ offset: 0,
1611
+ target: window
1612
+ }
1613
+
1614
+ Affix.prototype.getPinnedOffset = function () {
1615
+ if (this.pinnedOffset) return this.pinnedOffset
1616
+ this.$element.removeClass(Affix.RESET).addClass('affix')
1617
+ var scrollTop = this.$target.scrollTop()
1618
+ var position = this.$element.offset()
1619
+ return (this.pinnedOffset = position.top - scrollTop)
1620
+ }
1621
+
1622
+ Affix.prototype.checkPositionWithEventLoop = function () {
1623
+ setTimeout($.proxy(this.checkPosition, this), 1)
1624
+ }
1625
+
1626
+ Affix.prototype.checkPosition = function () {
1627
+ if (!this.$element.is(':visible')) return
1628
+
1629
+ var scrollHeight = $(document).height()
1630
+ var scrollTop = this.$target.scrollTop()
1631
+ var position = this.$element.offset()
1632
+ var offset = this.options.offset
1633
+ var offsetTop = offset.top
1634
+ var offsetBottom = offset.bottom
1635
+
1636
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
1637
+ if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
1638
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
1639
+
1640
+ var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false :
1641
+ offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
1642
+ offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false
1643
+
1644
+ if (this.affixed === affix) return
1645
+ if (this.unpin != null) this.$element.css('top', '')
1646
+
1647
+ var affixType = 'affix' + (affix ? '-' + affix : '')
1648
+ var e = $.Event(affixType + '.bs.affix')
1649
+
1650
+ this.$element.trigger(e)
1651
+
1652
+ if (e.isDefaultPrevented()) return
1653
+
1654
+ this.affixed = affix
1655
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
1656
+
1657
+ this.$element
1658
+ .removeClass(Affix.RESET)
1659
+ .addClass(affixType)
1660
+ .trigger($.Event(affixType.replace('affix', 'affixed')))
1661
+
1662
+ if (affix == 'bottom') {
1663
+ this.$element.offset({
1664
+ top: scrollHeight - this.$element.height() - offsetBottom
1665
+ })
1666
+ }
1667
+ }
1668
+
1669
+
1670
+ // AFFIX PLUGIN DEFINITION
1671
+ // =======================
1672
+
1673
+ function Plugin(option) {
1674
+ return this.each(function () {
1675
+ var $this = $(this)
1676
+ var data = $this.data('bs.affix')
1677
+ var options = typeof option == 'object' && option
1678
+
1679
+ if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
1680
+ if (typeof option == 'string') data[option]()
1681
+ })
1682
+ }
1683
+
1684
+ var old = $.fn.affix
1685
+
1686
+ $.fn.affix = Plugin
1687
+ $.fn.affix.Constructor = Affix
1688
+
1689
+
1690
+ // AFFIX NO CONFLICT
1691
+ // =================
1692
+
1693
+ $.fn.affix.noConflict = function () {
1694
+ $.fn.affix = old
1695
+ return this
1696
+ }
1697
+
1698
+
1699
+ // AFFIX DATA-API
1700
+ // ==============
1701
+
1702
+ $(window).on('load', function () {
1703
+ $('[data-spy="affix"]').each(function () {
1704
+ var $spy = $(this)
1705
+ var data = $spy.data()
1706
+
1707
+ data.offset = data.offset || {}
1708
+
1709
+ if (data.offsetBottom) data.offset.bottom = data.offsetBottom
1710
+ if (data.offsetTop) data.offset.top = data.offsetTop
1711
+
1712
+ Plugin.call($spy, data)
1713
+ })
1714
+ })
1715
+
1716
+ }(jQuery);
1717
+
1718
+ /* ========================================================================
1719
+ * Bootstrap: collapse.js v3.2.0
1720
+ * http://getbootstrap.com/javascript/#collapse
1721
+ * ========================================================================
1722
+ * Copyright 2011-2014 Twitter, Inc.
1723
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1724
+ * ======================================================================== */
1725
+
1726
+
1727
+ +function ($) {
1728
+ 'use strict';
1729
+
1730
+ // COLLAPSE PUBLIC CLASS DEFINITION
1731
+ // ================================
1732
+
1733
+ var Collapse = function (element, options) {
1734
+ this.$element = $(element)
1735
+ this.options = $.extend({}, Collapse.DEFAULTS, options)
1736
+ this.transitioning = null
1737
+
1738
+ if (this.options.parent) this.$parent = $(this.options.parent)
1739
+ if (this.options.toggle) this.toggle()
1740
+ }
1741
+
1742
+ Collapse.VERSION = '3.2.0'
1743
+
1744
+ Collapse.DEFAULTS = {
1745
+ toggle: true
1746
+ }
1747
+
1748
+ Collapse.prototype.dimension = function () {
1749
+ var hasWidth = this.$element.hasClass('width')
1750
+ return hasWidth ? 'width' : 'height'
1751
+ }
1752
+
1753
+ Collapse.prototype.show = function () {
1754
+ if (this.transitioning || this.$element.hasClass('in')) return
1755
+
1756
+ var startEvent = $.Event('show.bs.collapse')
1757
+ this.$element.trigger(startEvent)
1758
+ if (startEvent.isDefaultPrevented()) return
1759
+
1760
+ var actives = this.$parent && this.$parent.find('> .panel > .in')
1761
+
1762
+ if (actives && actives.length) {
1763
+ var hasData = actives.data('bs.collapse')
1764
+ if (hasData && hasData.transitioning) return
1765
+ Plugin.call(actives, 'hide')
1766
+ hasData || actives.data('bs.collapse', null)
1767
+ }
1768
+
1769
+ var dimension = this.dimension()
1770
+
1771
+ this.$element
1772
+ .removeClass('collapse')
1773
+ .addClass('collapsing')[dimension](0)
1774
+
1775
+ this.transitioning = 1
1776
+
1777
+ var complete = function () {
1778
+ this.$element
1779
+ .removeClass('collapsing')
1780
+ .addClass('collapse in')[dimension]('')
1781
+ this.transitioning = 0
1782
+ this.$element
1783
+ .trigger('shown.bs.collapse')
1784
+ }
1785
+
1786
+ if (!$.support.transition) return complete.call(this)
1787
+
1788
+ var scrollSize = $.camelCase(['scroll', dimension].join('-'))
1789
+
1790
+ this.$element
1791
+ .one('bsTransitionEnd', $.proxy(complete, this))
1792
+ .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
1793
+ }
1794
+
1795
+ Collapse.prototype.hide = function () {
1796
+ if (this.transitioning || !this.$element.hasClass('in')) return
1797
+
1798
+ var startEvent = $.Event('hide.bs.collapse')
1799
+ this.$element.trigger(startEvent)
1800
+ if (startEvent.isDefaultPrevented()) return
1801
+
1802
+ var dimension = this.dimension()
1803
+
1804
+ this.$element[dimension](this.$element[dimension]())[0].offsetHeight
1805
+
1806
+ this.$element
1807
+ .addClass('collapsing')
1808
+ .removeClass('collapse')
1809
+ .removeClass('in')
1810
+
1811
+ this.transitioning = 1
1812
+
1813
+ var complete = function () {
1814
+ this.transitioning = 0
1815
+ this.$element
1816
+ .trigger('hidden.bs.collapse')
1817
+ .removeClass('collapsing')
1818
+ .addClass('collapse')
1819
+ }
1820
+
1821
+ if (!$.support.transition) return complete.call(this)
1822
+
1823
+ this.$element
1824
+ [dimension](0)
1825
+ .one('bsTransitionEnd', $.proxy(complete, this))
1826
+ .emulateTransitionEnd(350)
1827
+ }
1828
+
1829
+ Collapse.prototype.toggle = function () {
1830
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
1831
+ }
1832
+
1833
+
1834
+ // COLLAPSE PLUGIN DEFINITION
1835
+ // ==========================
1836
+
1837
+ function Plugin(option) {
1838
+ return this.each(function () {
1839
+ var $this = $(this)
1840
+ var data = $this.data('bs.collapse')
1841
+ var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
1842
+
1843
+ if (!data && options.toggle && option == 'show') option = !option
1844
+ if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
1845
+ if (typeof option == 'string') data[option]()
1846
+ })
1847
+ }
1848
+
1849
+ var old = $.fn.collapse
1850
+
1851
+ $.fn.collapse = Plugin
1852
+ $.fn.collapse.Constructor = Collapse
1853
+
1854
+
1855
+ // COLLAPSE NO CONFLICT
1856
+ // ====================
1857
+
1858
+ $.fn.collapse.noConflict = function () {
1859
+ $.fn.collapse = old
1860
+ return this
1861
+ }
1862
+
1863
+
1864
+ // COLLAPSE DATA-API
1865
+ // =================
1866
+
1867
+ $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
1868
+ var href
1869
+ var $this = $(this)
1870
+ var target = $this.attr('data-target')
1871
+ || e.preventDefault()
1872
+ || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
1873
+ var $target = $(target)
1874
+ var data = $target.data('bs.collapse')
1875
+ var option = data ? 'toggle' : $this.data()
1876
+ var parent = $this.attr('data-parent')
1877
+ var $parent = parent && $(parent)
1878
+
1879
+ if (!data || !data.transitioning) {
1880
+ if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
1881
+ $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
1882
+ }
1883
+
1884
+ Plugin.call($target, option)
1885
+ })
1886
+
1887
+ }(jQuery);
1888
+
1889
+ /* ========================================================================
1890
+ * Bootstrap: scrollspy.js v3.2.0
1891
+ * http://getbootstrap.com/javascript/#scrollspy
1892
+ * ========================================================================
1893
+ * Copyright 2011-2014 Twitter, Inc.
1894
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1895
+ * ======================================================================== */
1896
+
1897
+
1898
+ +function ($) {
1899
+ 'use strict';
1900
+
1901
+ // SCROLLSPY CLASS DEFINITION
1902
+ // ==========================
1903
+
1904
+ function ScrollSpy(element, options) {
1905
+ var process = $.proxy(this.process, this)
1906
+
1907
+ this.$body = $('body')
1908
+ this.$scrollElement = $(element).is('body') ? $(window) : $(element)
1909
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
1910
+ this.selector = (this.options.target || '') + ' .nav li > a'
1911
+ this.offsets = []
1912
+ this.targets = []
1913
+ this.activeTarget = null
1914
+ this.scrollHeight = 0
1915
+
1916
+ this.$scrollElement.on('scroll.bs.scrollspy', process)
1917
+ this.refresh()
1918
+ this.process()
1919
+ }
1920
+
1921
+ ScrollSpy.VERSION = '3.2.0'
1922
+
1923
+ ScrollSpy.DEFAULTS = {
1924
+ offset: 10
1925
+ }
1926
+
1927
+ ScrollSpy.prototype.getScrollHeight = function () {
1928
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
1929
+ }
1930
+
1931
+ ScrollSpy.prototype.refresh = function () {
1932
+ var offsetMethod = 'offset'
1933
+ var offsetBase = 0
1934
+
1935
+ if (!$.isWindow(this.$scrollElement[0])) {
1936
+ offsetMethod = 'position'
1937
+ offsetBase = this.$scrollElement.scrollTop()
1938
+ }
1939
+
1940
+ this.offsets = []
1941
+ this.targets = []
1942
+ this.scrollHeight = this.getScrollHeight()
1943
+
1944
+ var self = this
1945
+
1946
+ this.$body
1947
+ .find(this.selector)
1948
+ .map(function () {
1949
+ var $el = $(this)
1950
+ var href = $el.data('target') || $el.attr('href')
1951
+ var $href = /^#./.test(href) && $(href)
1952
+
1953
+ return ($href
1954
+ && $href.length
1955
+ && $href.is(':visible')
1956
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
1957
+ })
1958
+ .sort(function (a, b) { return a[0] - b[0] })
1959
+ .each(function () {
1960
+ self.offsets.push(this[0])
1961
+ self.targets.push(this[1])
1962
+ })
1963
+ }
1964
+
1965
+ ScrollSpy.prototype.process = function () {
1966
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
1967
+ var scrollHeight = this.getScrollHeight()
1968
+ var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
1969
+ var offsets = this.offsets
1970
+ var targets = this.targets
1971
+ var activeTarget = this.activeTarget
1972
+ var i
1973
+
1974
+ if (this.scrollHeight != scrollHeight) {
1975
+ this.refresh()
1976
+ }
1977
+
1978
+ if (scrollTop >= maxScroll) {
1979
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
1980
+ }
1981
+
1982
+ if (activeTarget && scrollTop <= offsets[0]) {
1983
+ return activeTarget != (i = targets[0]) && this.activate(i)
1984
+ }
1985
+
1986
+ for (i = offsets.length; i--;) {
1987
+ activeTarget != targets[i]
1988
+ && scrollTop >= offsets[i]
1989
+ && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
1990
+ && this.activate(targets[i])
1991
+ }
1992
+ }
1993
+
1994
+ ScrollSpy.prototype.activate = function (target) {
1995
+ this.activeTarget = target
1996
+
1997
+ $(this.selector)
1998
+ .parentsUntil(this.options.target, '.active')
1999
+ .removeClass('active')
2000
+
2001
+ var selector = this.selector +
2002
+ '[data-target="' + target + '"],' +
2003
+ this.selector + '[href="' + target + '"]'
2004
+
2005
+ var active = $(selector)
2006
+ .parents('li')
2007
+ .addClass('active')
2008
+
2009
+ if (active.parent('.dropdown-menu').length) {
2010
+ active = active
2011
+ .closest('li.dropdown')
2012
+ .addClass('active')
2013
+ }
2014
+
2015
+ active.trigger('activate.bs.scrollspy')
2016
+ }
2017
+
2018
+
2019
+ // SCROLLSPY PLUGIN DEFINITION
2020
+ // ===========================
2021
+
2022
+ function Plugin(option) {
2023
+ return this.each(function () {
2024
+ var $this = $(this)
2025
+ var data = $this.data('bs.scrollspy')
2026
+ var options = typeof option == 'object' && option
2027
+
2028
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
2029
+ if (typeof option == 'string') data[option]()
2030
+ })
2031
+ }
2032
+
2033
+ var old = $.fn.scrollspy
2034
+
2035
+ $.fn.scrollspy = Plugin
2036
+ $.fn.scrollspy.Constructor = ScrollSpy
2037
+
2038
+
2039
+ // SCROLLSPY NO CONFLICT
2040
+ // =====================
2041
+
2042
+ $.fn.scrollspy.noConflict = function () {
2043
+ $.fn.scrollspy = old
2044
+ return this
2045
+ }
2046
+
2047
+
2048
+ // SCROLLSPY DATA-API
2049
+ // ==================
2050
+
2051
+ $(window).on('load.bs.scrollspy.data-api', function () {
2052
+ $('[data-spy="scroll"]').each(function () {
2053
+ var $spy = $(this)
2054
+ Plugin.call($spy, $spy.data())
2055
+ })
2056
+ })
2057
+
2058
+ }(jQuery);
2059
+
2060
+ /* ========================================================================
2061
+ * Bootstrap: transition.js v3.2.0
2062
+ * http://getbootstrap.com/javascript/#transitions
2063
+ * ========================================================================
2064
+ * Copyright 2011-2014 Twitter, Inc.
2065
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2066
+ * ======================================================================== */
2067
+
2068
+
2069
+ +function ($) {
2070
+ 'use strict';
2071
+
2072
+ // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
2073
+ // ============================================================
2074
+
2075
+ function transitionEnd() {
2076
+ var el = document.createElement('bootstrap')
2077
+
2078
+ var transEndEventNames = {
2079
+ WebkitTransition : 'webkitTransitionEnd',
2080
+ MozTransition : 'transitionend',
2081
+ OTransition : 'oTransitionEnd otransitionend',
2082
+ transition : 'transitionend'
2083
+ }
2084
+
2085
+ for (var name in transEndEventNames) {
2086
+ if (el.style[name] !== undefined) {
2087
+ return { end: transEndEventNames[name] }
2088
+ }
2089
+ }
2090
+
2091
+ return false // explicit for ie8 ( ._.)
2092
+ }
2093
+
2094
+ // http://blog.alexmaccaw.com/css-transitions
2095
+ $.fn.emulateTransitionEnd = function (duration) {
2096
+ var called = false
2097
+ var $el = this
2098
+ $(this).one('bsTransitionEnd', function () { called = true })
2099
+ var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
2100
+ setTimeout(callback, duration)
2101
+ return this
2102
+ }
2103
+
2104
+ $(function () {
2105
+ $.support.transition = transitionEnd()
2106
+
2107
+ if (!$.support.transition) return
2108
+
2109
+ $.event.special.bsTransitionEnd = {
2110
+ bindType: $.support.transition.end,
2111
+ delegateType: $.support.transition.end,
2112
+ handle: function (e) {
2113
+ if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
2114
+ }
2115
+ }
2116
+ })
2117
+
2118
+ }(jQuery);