commonwealth-vlr-engine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (361) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +91 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +20 -0
  5. data/LICENSE +202 -0
  6. data/README.md +38 -0
  7. data/Rakefile +43 -0
  8. data/app/assets/images/commonwealth-vlr-engine/bplLoginButton.png +0 -0
  9. data/app/assets/images/commonwealth-vlr-engine/dc_audio-icon.png +0 -0
  10. data/app/assets/images/commonwealth-vlr-engine/dc_collection-icon.png +0 -0
  11. data/app/assets/images/commonwealth-vlr-engine/dc_image-icon.png +0 -0
  12. data/app/assets/images/commonwealth-vlr-engine/dc_institution-icon.png +0 -0
  13. data/app/assets/images/commonwealth-vlr-engine/dc_moving-image-icon.png +0 -0
  14. data/app/assets/images/commonwealth-vlr-engine/dc_text-icon.png +0 -0
  15. data/app/assets/images/commonwealth-vlr-engine/facebookLoginButton.png +0 -0
  16. data/app/assets/images/commonwealth-vlr-engine/loading-wdl-grid.gif +0 -0
  17. data/app/assets/images/commonwealth-vlr-engine/loading-wdl.gif +0 -0
  18. data/app/assets/images/commonwealth-vlr-engine/loading.gif +0 -0
  19. data/app/assets/images/commonwealth-vlr-engine/openseadragon/fullpage_grouphover.png +0 -0
  20. data/app/assets/images/commonwealth-vlr-engine/openseadragon/fullpage_hover.png +0 -0
  21. data/app/assets/images/commonwealth-vlr-engine/openseadragon/fullpage_pressed.png +0 -0
  22. data/app/assets/images/commonwealth-vlr-engine/openseadragon/fullpage_rest.png +0 -0
  23. data/app/assets/images/commonwealth-vlr-engine/openseadragon/home_grouphover.png +0 -0
  24. data/app/assets/images/commonwealth-vlr-engine/openseadragon/home_hover.png +0 -0
  25. data/app/assets/images/commonwealth-vlr-engine/openseadragon/home_pressed.png +0 -0
  26. data/app/assets/images/commonwealth-vlr-engine/openseadragon/home_rest.png +0 -0
  27. data/app/assets/images/commonwealth-vlr-engine/openseadragon/next_grouphover.png +0 -0
  28. data/app/assets/images/commonwealth-vlr-engine/openseadragon/next_hover.png +0 -0
  29. data/app/assets/images/commonwealth-vlr-engine/openseadragon/next_pressed.png +0 -0
  30. data/app/assets/images/commonwealth-vlr-engine/openseadragon/next_rest.png +0 -0
  31. data/app/assets/images/commonwealth-vlr-engine/openseadragon/previous_grouphover.png +0 -0
  32. data/app/assets/images/commonwealth-vlr-engine/openseadragon/previous_hover.png +0 -0
  33. data/app/assets/images/commonwealth-vlr-engine/openseadragon/previous_pressed.png +0 -0
  34. data/app/assets/images/commonwealth-vlr-engine/openseadragon/previous_rest.png +0 -0
  35. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateleft_grouphover.png +0 -0
  36. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateleft_hover.png +0 -0
  37. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateleft_pressed.png +0 -0
  38. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateleft_rest.png +0 -0
  39. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateright_grouphover.png +0 -0
  40. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateright_hover.png +0 -0
  41. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateright_pressed.png +0 -0
  42. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateright_rest.png +0 -0
  43. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomin_grouphover.png +0 -0
  44. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomin_hover.png +0 -0
  45. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomin_pressed.png +0 -0
  46. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomin_rest.png +0 -0
  47. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomout_grouphover.png +0 -0
  48. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomout_hover.png +0 -0
  49. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomout_pressed.png +0 -0
  50. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomout_rest.png +0 -0
  51. data/app/assets/images/commonwealth-vlr-engine/vlr_logo_img.png +0 -0
  52. data/app/assets/javascripts/blacklight_gallery.js +1 -0
  53. data/app/assets/javascripts/blacklight_google_analytics/blacklight_google_analytics.js.erb +165 -0
  54. data/app/assets/javascripts/bootstrap-accessibility-plugin/bootstrap-accessibility.js +586 -0
  55. data/app/assets/javascripts/commonwealth-vlr-engine.js +22 -0
  56. data/app/assets/javascripts/commonwealth-vlr-engine/collection_facets.js +5 -0
  57. data/app/assets/javascripts/commonwealth-vlr-engine/disable_dropdown_nav.js +21 -0
  58. data/app/assets/javascripts/commonwealth-vlr-engine/feedback_alerts.js.erb +19 -0
  59. data/app/assets/javascripts/commonwealth-vlr-engine/folder_tools.js +26 -0
  60. data/app/assets/javascripts/commonwealth-vlr-engine/multi_img_viewer.js.erb +20 -0
  61. data/app/assets/javascripts/commonwealth-vlr-engine/ocr_search_utils.js.erb +32 -0
  62. data/app/assets/javascripts/commonwealth-vlr-engine/volumes_list.js +5 -0
  63. data/app/assets/javascripts/openseadragon.js +2 -0
  64. data/app/assets/javascripts/respond/respond.min.js +6 -0
  65. data/app/assets/javascripts/wdl-viewer/fd-slider.js +1303 -0
  66. data/app/assets/javascripts/wdl-viewer/jquery-deparam.js +113 -0
  67. data/app/assets/javascripts/wdl-viewer/jquery.ba-throttle-debounce.min.js +9 -0
  68. data/app/assets/javascripts/wdl-viewer/jquery.hammer.min.js +7 -0
  69. data/app/assets/javascripts/wdl-viewer/modernizr-wdl.min.js +3 -0
  70. data/app/assets/javascripts/wdl-viewer/wdl-search.js +33 -0
  71. data/app/assets/javascripts/wdl-viewer/wdl-viewer_commonwealth.js +1147 -0
  72. data/app/assets/stylesheets/blacklight_advanced_search.css +5 -0
  73. data/app/assets/stylesheets/blacklight_gallery.css +1 -0
  74. data/app/assets/stylesheets/blacklight_maps.css +1 -0
  75. data/app/assets/stylesheets/bootstrap-accessibility-plugin/bootstrap-accessibility.css +105 -0
  76. data/app/assets/stylesheets/commonwealth-vlr-engine/advanced_search.scss +139 -0
  77. data/app/assets/stylesheets/commonwealth-vlr-engine/basic_search.scss +47 -0
  78. data/app/assets/stylesheets/commonwealth-vlr-engine/book_viewer.scss +576 -0
  79. data/app/assets/stylesheets/commonwealth-vlr-engine/carousel.scss +94 -0
  80. data/app/assets/stylesheets/commonwealth-vlr-engine/cmmnwlth_defaults.scss +45 -0
  81. data/app/assets/stylesheets/commonwealth-vlr-engine/cmmnwlth_shared.scss +75 -0
  82. data/app/assets/stylesheets/commonwealth-vlr-engine/collections.scss +563 -0
  83. data/app/assets/stylesheets/commonwealth-vlr-engine/commonwealth-vlr-engine.css +32 -0
  84. data/app/assets/stylesheets/commonwealth-vlr-engine/facets.scss +111 -0
  85. data/app/assets/stylesheets/commonwealth-vlr-engine/feedback.scss +10 -0
  86. data/app/assets/stylesheets/commonwealth-vlr-engine/folders.scss +276 -0
  87. data/app/assets/stylesheets/commonwealth-vlr-engine/footer.scss +47 -0
  88. data/app/assets/stylesheets/commonwealth-vlr-engine/header.scss +329 -0
  89. data/app/assets/stylesheets/commonwealth-vlr-engine/home.scss +269 -0
  90. data/app/assets/stylesheets/commonwealth-vlr-engine/index.scss +580 -0
  91. data/app/assets/stylesheets/commonwealth-vlr-engine/institutions.scss +246 -0
  92. data/app/assets/stylesheets/commonwealth-vlr-engine/pages.scss +31 -0
  93. data/app/assets/stylesheets/commonwealth-vlr-engine/search_inside.scss +172 -0
  94. data/app/assets/stylesheets/commonwealth-vlr-engine/searches.scss +55 -0
  95. data/app/assets/stylesheets/commonwealth-vlr-engine/show.scss +840 -0
  96. data/app/assets/stylesheets/commonwealth-vlr-engine/signin.scss +43 -0
  97. data/app/assets/stylesheets/commonwealth-vlr-engine/users.scss +18 -0
  98. data/app/assets/stylesheets/commonwealth-vlr-engine/vlr_dependencies.css +8 -0
  99. data/app/assets/stylesheets/ie_fixes.css +16 -0
  100. data/app/assets/stylesheets/openseadragon.css +1 -0
  101. data/app/assets/stylesheets/wdl-viewer/fd-slider.min.css +2 -0
  102. data/app/controllers/blacklight_advanced_search/advanced_controller.rb +66 -0
  103. data/app/controllers/bookmarks_controller.rb +38 -0
  104. data/app/controllers/collections_controller.rb +128 -0
  105. data/app/controllers/commonwealth_vlr_engine/application_controller.rb +8 -0
  106. data/app/controllers/feedback_controller.rb +39 -0
  107. data/app/controllers/folder_items_actions_controller.rb +72 -0
  108. data/app/controllers/folder_items_controller.rb +90 -0
  109. data/app/controllers/folders_controller.rb +132 -0
  110. data/app/controllers/iiif_manifest_controller.rb +74 -0
  111. data/app/controllers/image_viewer_controller.rb +34 -0
  112. data/app/controllers/institutions_controller.rb +62 -0
  113. data/app/controllers/ocr_search_controller.rb +78 -0
  114. data/app/controllers/pages_controller.rb +5 -0
  115. data/app/controllers/users/omniauth_callbacks_controller.rb +10 -0
  116. data/app/controllers/users/registrations_controller.rb +3 -0
  117. data/app/controllers/users/sessions_controller.rb +3 -0
  118. data/app/controllers/users_controller.rb +27 -0
  119. data/app/helpers/blacklight_maps_helper.rb +3 -0
  120. data/app/helpers/collections_helper.rb +3 -0
  121. data/app/helpers/commonwealth_vlr_engine/application_helper.rb +200 -0
  122. data/app/helpers/commonwealth_vlr_engine/blacklight_helper.rb +35 -0
  123. data/app/helpers/commonwealth_vlr_engine/blacklight_url_helper.rb +53 -0
  124. data/app/helpers/commonwealth_vlr_engine/catalog_helper.rb +414 -0
  125. data/app/helpers/commonwealth_vlr_engine/collections_helper_behavior.rb +19 -0
  126. data/app/helpers/commonwealth_vlr_engine/component_helper.rb +22 -0
  127. data/app/helpers/commonwealth_vlr_engine/facets_helper.rb +20 -0
  128. data/app/helpers/commonwealth_vlr_engine/feedback_helper_behavior.rb +14 -0
  129. data/app/helpers/commonwealth_vlr_engine/folders_helper_behavior.rb +9 -0
  130. data/app/helpers/commonwealth_vlr_engine/image_viewer_helper_behavior.rb +14 -0
  131. data/app/helpers/commonwealth_vlr_engine/institutions_helper_behavior.rb +31 -0
  132. data/app/helpers/commonwealth_vlr_engine/layout_helper.rb +22 -0
  133. data/app/helpers/commonwealth_vlr_engine/ocr_search_helper_behavior.rb +48 -0
  134. data/app/helpers/commonwealth_vlr_engine/pages_helper_behavior.rb +38 -0
  135. data/app/helpers/commonwealth_vlr_engine/vlr_blacklight_maps_helper_behavior.rb +59 -0
  136. data/app/helpers/feedback_helper.rb +3 -0
  137. data/app/helpers/folders_helper.rb +3 -0
  138. data/app/helpers/image_viewer_helper.rb +3 -0
  139. data/app/helpers/institutions_helper.rb +3 -0
  140. data/app/helpers/ocr_search_helper.rb +3 -0
  141. data/app/helpers/pages_helper.rb +3 -0
  142. data/app/mailers/notifier.rb +5 -0
  143. data/app/models/carousel_slide.rb +7 -0
  144. data/app/models/record_mailer.rb +18 -0
  145. data/app/models/user.rb +15 -0
  146. data/app/views/advanced/_advanced_search_date.html.erb +23 -0
  147. data/app/views/advanced/_advanced_search_facets.html.erb +5 -0
  148. data/app/views/advanced/_advanced_search_fields.html.erb +39 -0
  149. data/app/views/advanced/_advanced_search_form.html.erb +51 -0
  150. data/app/views/advanced/_advanced_search_help.html.erb +13 -0
  151. data/app/views/advanced/_facet_layout.html.erb +9 -0
  152. data/app/views/advanced/_facet_limit.html.erb +15 -0
  153. data/app/views/advanced/index.html.erb +29 -0
  154. data/app/views/blacklight_advanced_search/_facet_limit.html.erb +12 -0
  155. data/app/views/bookmarks/_tools.html.erb +25 -0
  156. data/app/views/bookmarks/index.html.erb +64 -0
  157. data/app/views/bookmarks/update.js.erb +1 -0
  158. data/app/views/bpluser/folders/_folder.html.erb +36 -0
  159. data/app/views/catalog/_add_this.html.erb +10 -0
  160. data/app/views/catalog/_az_links.html.erb +15 -0
  161. data/app/views/catalog/_basic_search.html.erb +67 -0
  162. data/app/views/catalog/_citation.html.erb +50 -0
  163. data/app/views/catalog/_constraints.html.erb +26 -0
  164. data/app/views/catalog/_document_collections_gallery.html.erb +7 -0
  165. data/app/views/catalog/_facet_limit_series.html.erb +21 -0
  166. data/app/views/catalog/_facets.html.erb +31 -0
  167. data/app/views/catalog/_facets_series.html.erb +4 -0
  168. data/app/views/catalog/_folder_item_control.html.erb +64 -0
  169. data/app/views/catalog/_index_collections_gallery.html.erb +12 -0
  170. data/app/views/catalog/_index_gallery.html.erb +11 -0
  171. data/app/views/catalog/_index_header_default.html.erb +22 -0
  172. data/app/views/catalog/_index_list_collection.html.erb +33 -0
  173. data/app/views/catalog/_index_list_default.html.erb +13 -0
  174. data/app/views/catalog/_index_map_institutions.html.erb +10 -0
  175. data/app/views/catalog/_index_masonry.html.erb +8 -0
  176. data/app/views/catalog/_index_slideshow.html.erb +18 -0
  177. data/app/views/catalog/_more_like_this.html.erb +9 -0
  178. data/app/views/catalog/_opengraph.html.erb +16 -0
  179. data/app/views/catalog/_previous_next_doc.html.erb +22 -0
  180. data/app/views/catalog/_results_pagination.html.erb +9 -0
  181. data/app/views/catalog/_search_form.html.erb +23 -0
  182. data/app/views/catalog/_search_header.html.erb +5 -0
  183. data/app/views/catalog/_show_default.html.erb +75 -0
  184. data/app/views/catalog/_show_main_content.html.erb +27 -0
  185. data/app/views/catalog/_show_more_like_this.html.erb +15 -0
  186. data/app/views/catalog/_show_partials/_show_book_viewer_link.html.erb +25 -0
  187. data/app/views/catalog/_show_partials/_show_default_img.html.erb +32 -0
  188. data/app/views/catalog/_show_partials/_show_default_metadata.html.erb +486 -0
  189. data/app/views/catalog/_show_partials/_show_default_simple_img_viewer.html.erb +45 -0
  190. data/app/views/catalog/_show_partials/_show_downloads.html.erb +14 -0
  191. data/app/views/catalog/_show_partials/_show_flagged_notice.html.erb +29 -0
  192. data/app/views/catalog/_show_partials/_show_multi_img.html.erb +42 -0
  193. data/app/views/catalog/_show_partials/_show_multi_img_pagination.html.erb +20 -0
  194. data/app/views/catalog/_show_partials/_show_oai_item_img.html.erb +5 -0
  195. data/app/views/catalog/_show_partials/_show_oai_item_link.html.erb +8 -0
  196. data/app/views/catalog/_show_partials/_show_prev_next_carousel_links.html.erb +17 -0
  197. data/app/views/catalog/_show_partials/_show_volumes.html.erb +52 -0
  198. data/app/views/catalog/_show_sidebar.html.erb +1 -0
  199. data/app/views/catalog/_show_tools.html.erb +42 -0
  200. data/app/views/catalog/_zero_results.html.erb +20 -0
  201. data/app/views/catalog/email.html.erb +6 -0
  202. data/app/views/catalog/index.html.erb +17 -0
  203. data/app/views/catalog/metadata_view.html.erb +7 -0
  204. data/app/views/catalog/show.html.erb +13 -0
  205. data/app/views/collections/_search_form_collection.html.erb +23 -0
  206. data/app/views/collections/index.html.erb +30 -0
  207. data/app/views/collections/show.html.erb +116 -0
  208. data/app/views/devise/confirmations/new.html.erb +14 -0
  209. data/app/views/devise/mailer/reset_password_instructions.html.erb +13 -0
  210. data/app/views/devise/passwords/edit.html.erb +33 -0
  211. data/app/views/devise/passwords/new.html.erb +31 -0
  212. data/app/views/devise/registrations/edit.html.erb +83 -0
  213. data/app/views/devise/registrations/new.html.erb +53 -0
  214. data/app/views/devise/sessions/new.html.erb +75 -0
  215. data/app/views/devise/shared/_links.erb +29 -0
  216. data/app/views/feedback/complete.html.erb +9 -0
  217. data/app/views/feedback/show.html.erb +61 -0
  218. data/app/views/folder_items/create.js.erb +1 -0
  219. data/app/views/folder_items/destroy.js.erb +1 -0
  220. data/app/views/folder_items/item_actions.js.erb +2 -0
  221. data/app/views/folder_items/update.js.erb +1 -0
  222. data/app/views/folders/_in_folder.html.erb +2 -0
  223. data/app/views/folders/_new_edit_form_fields.html.erb +36 -0
  224. data/app/views/folders/edit.html.erb +25 -0
  225. data/app/views/folders/index.html.erb +73 -0
  226. data/app/views/folders/new.html.erb +27 -0
  227. data/app/views/folders/public_list.html.erb +44 -0
  228. data/app/views/folders/show.html.erb +98 -0
  229. data/app/views/image_viewer/_book_viewer_help.html.erb +125 -0
  230. data/app/views/image_viewer/_render_book_viewer.html.erb +185 -0
  231. data/app/views/image_viewer/book_viewer.html.erb +57 -0
  232. data/app/views/image_viewer/show.js.erb +19 -0
  233. data/app/views/institutions/_intro_text.html.erb +1 -0
  234. data/app/views/institutions/_map_institutions_search.html.erb +9 -0
  235. data/app/views/institutions/_search_form_institution.html.erb +24 -0
  236. data/app/views/institutions/index.html.erb +31 -0
  237. data/app/views/institutions/show.html.erb +104 -0
  238. data/app/views/layouts/_google_analytics.html.erb +9 -0
  239. data/app/views/layouts/book_viewer.html.erb +37 -0
  240. data/app/views/layouts/commonwealth-vlr-engine.html.erb +59 -0
  241. data/app/views/notifier/feedback.text.erb +6 -0
  242. data/app/views/ocr_search/_index_ocr_list.html.erb +17 -0
  243. data/app/views/ocr_search/_search_form_ocr.html.erb +23 -0
  244. data/app/views/ocr_search/_snippets_more.html.erb +15 -0
  245. data/app/views/ocr_search/_zero_results_ocr.html.erb +9 -0
  246. data/app/views/ocr_search/index.html.erb +49 -0
  247. data/app/views/pages/_carousel.html.erb +46 -0
  248. data/app/views/pages/_home_partials/_banner.html.erb +23 -0
  249. data/app/views/pages/_home_partials/_browse.html.erb +55 -0
  250. data/app/views/pages/_home_partials/_context.html.erb +24 -0
  251. data/app/views/pages/_home_partials/_home_content.html.erb +14 -0
  252. data/app/views/pages/about.html.erb +10 -0
  253. data/app/views/pages/about_site.html.erb +6 -0
  254. data/app/views/pages/explore.html.erb +32 -0
  255. data/app/views/pages/home.html.erb +3 -0
  256. data/app/views/record_mailer/email_record.text.erb +7 -0
  257. data/app/views/saved_searches/index.html.erb +60 -0
  258. data/app/views/search_history/index.html.erb +59 -0
  259. data/app/views/shared/_error_messages.html.erb +9 -0
  260. data/app/views/shared/_flash_msg_maintenance.html.erb +6 -0
  261. data/app/views/shared/_folder_item_actions.html.erb +66 -0
  262. data/app/views/shared/_folder_tools.html.erb +4 -0
  263. data/app/views/shared/_footer.html.erb +14 -0
  264. data/app/views/shared/_header_navbar.html.erb +34 -0
  265. data/app/views/shared/_nav_links.html.erb +58 -0
  266. data/app/views/shared/_search_form_header.html.erb +16 -0
  267. data/app/views/shared/_tools.html.erb +14 -0
  268. data/app/views/shared/_user_util_links.html.erb +43 -0
  269. data/app/views/users/show.html.erb +33 -0
  270. data/commonwealth-vlr-engine.gemspec +47 -0
  271. data/config/initializers/patch_blacklight_advanced_search.rb +74 -0
  272. data/config/initializers/patch_blacklight_maps.rb +20 -0
  273. data/config/jetty.yml +7 -0
  274. data/config/locales/commonwealth-vlr-engine.en.yml +463 -0
  275. data/config/routes.rb +92 -0
  276. data/lib/commonwealth-vlr-engine.rb +55 -0
  277. data/lib/commonwealth-vlr-engine/commonwealth_search_builder.rb +66 -0
  278. data/lib/commonwealth-vlr-engine/controller.rb +69 -0
  279. data/lib/commonwealth-vlr-engine/controller_override.rb +238 -0
  280. data/lib/commonwealth-vlr-engine/engine.rb +40 -0
  281. data/lib/commonwealth-vlr-engine/finder.rb +285 -0
  282. data/lib/commonwealth-vlr-engine/iiif_manifest.rb +189 -0
  283. data/lib/commonwealth-vlr-engine/notifier.rb +33 -0
  284. data/lib/commonwealth-vlr-engine/pages.rb +33 -0
  285. data/lib/commonwealth-vlr-engine/render_constraints_override.rb +57 -0
  286. data/lib/commonwealth-vlr-engine/route_sets.rb +49 -0
  287. data/lib/commonwealth-vlr-engine/routes.rb +21 -0
  288. data/lib/commonwealth-vlr-engine/version.rb +3 -0
  289. data/lib/generators/commonwealth_vlr_engine/controller_generator.rb +92 -0
  290. data/lib/generators/commonwealth_vlr_engine/environment_generator.rb +49 -0
  291. data/lib/generators/commonwealth_vlr_engine/install_generator.rb +57 -0
  292. data/lib/generators/commonwealth_vlr_engine/localassets_generator.rb +29 -0
  293. data/lib/generators/commonwealth_vlr_engine/model_generator.rb +65 -0
  294. data/lib/generators/commonwealth_vlr_engine/routes_generator.rb +39 -0
  295. data/lib/generators/commonwealth_vlr_engine/templates/commonwealth_vlr_engine.css.scss +4 -0
  296. data/lib/generators/commonwealth_vlr_engine/templates/config/contact_emails.yml.sample +13 -0
  297. data/lib/generators/commonwealth_vlr_engine/templates/config/fedora.yml.sample +6 -0
  298. data/lib/generators/commonwealth_vlr_engine/templates/config/geojson_static_file.yml.sample +11 -0
  299. data/lib/generators/commonwealth_vlr_engine/templates/config/google_analytics.yml.sample +10 -0
  300. data/lib/generators/commonwealth_vlr_engine/templates/config/iiif_server.yml.sample +10 -0
  301. data/lib/generators/commonwealth_vlr_engine/templates/config/initializers/a_load_commonwealth_vlr_configs.rb +14 -0
  302. data/lib/generators/commonwealth_vlr_engine/templates/config/initializers/devise.rb +269 -0
  303. data/lib/generators/commonwealth_vlr_engine/templates/config/initializers/secret_token.rb +8 -0
  304. data/lib/generators/commonwealth_vlr_engine/templates/config/locales/blacklight.en.yml +44 -0
  305. data/lib/generators/commonwealth_vlr_engine/templates/config/locales/devise.en.yml +12 -0
  306. data/lib/generators/commonwealth_vlr_engine/templates/config/omniauth-facebook.yml.sample +14 -0
  307. data/lib/generators/commonwealth_vlr_engine/templates/config/omniauth-polaris.yml.sample +20 -0
  308. data/lib/generators/commonwealth_vlr_engine/templates/config/vlr.yml +13 -0
  309. data/lib/generators/commonwealth_vlr_engine/yml_generator.rb +29 -0
  310. data/lib/railties/commonwealth_vlr_engine.rake +6 -0
  311. data/solr_conf/conf/schema.xml +476 -0
  312. data/solr_conf/conf/solrconfig.xml +286 -0
  313. data/spec/controllers/catalog_controller_spec.rb +67 -0
  314. data/spec/controllers/collections_controller_spec.rb +127 -0
  315. data/spec/controllers/feedback_controller_spec.rb +51 -0
  316. data/spec/controllers/folder_items_actions_controller_spec.rb +99 -0
  317. data/spec/controllers/folder_items_controller_spec.rb +90 -0
  318. data/spec/controllers/folders_controller_spec.rb +368 -0
  319. data/spec/controllers/iiif_manifest_controller_spec.rb +85 -0
  320. data/spec/controllers/image_viewer_controller_spec.rb +50 -0
  321. data/spec/controllers/institutions_controller_spec.rb +64 -0
  322. data/spec/controllers/ocr_search_controller_spec.rb +71 -0
  323. data/spec/controllers/pages_controller_spec.rb +58 -0
  324. data/spec/controllers/users_controller_spec.rb +62 -0
  325. data/spec/features/catalog/_az_links_spec.rb +27 -0
  326. data/spec/features/catalog/_show_partials/_show_book_viewer_link_spec.rb +47 -0
  327. data/spec/features/catalog/_show_partials/_show_default_simple_img_viewer_spec.rb +19 -0
  328. data/spec/features/catalog/_show_partials/_show_flagged_notice_spec.rb +23 -0
  329. data/spec/features/catalog/_show_partials/_show_multi_img_spec.rb +18 -0
  330. data/spec/features/catalog/_show_partials/_show_volumes_spec.rb +24 -0
  331. data/spec/features/collections/index_spec.rb +35 -0
  332. data/spec/features/feedback/show_spec.rb +47 -0
  333. data/spec/features/image_viewer/book_viewer_spec.rb +67 -0
  334. data/spec/features/institutions/index_spec.rb +31 -0
  335. data/spec/features/institutions/map_view_spec.rb +37 -0
  336. data/spec/features/more_like_this_search_spec.rb +23 -0
  337. data/spec/features/ocr_search/index_spec.rb +89 -0
  338. data/spec/fixtures/sample_rss_feed.xml +56 -0
  339. data/spec/fixtures/sample_solr_documents.yml +2748 -0
  340. data/spec/helpers/application_helper_spec.rb +114 -0
  341. data/spec/helpers/catalog_helper_spec.rb +386 -0
  342. data/spec/helpers/collections_helper_spec.rb +28 -0
  343. data/spec/helpers/component_helper_spec.rb +34 -0
  344. data/spec/helpers/folders_helper_spec.rb +31 -0
  345. data/spec/helpers/image_viewer_helper_spec.rb +15 -0
  346. data/spec/helpers/institutions_helper_spec.rb +53 -0
  347. data/spec/helpers/ocr_search_helper_spec.rb +70 -0
  348. data/spec/helpers/pages_helper_spec.rb +21 -0
  349. data/spec/lib/commonwealth-vlr-engine/commonwealth_search_builder_spec.rb +101 -0
  350. data/spec/lib/commonwealth-vlr-engine/controller_override_spec.rb +41 -0
  351. data/spec/lib/commonwealth-vlr-engine/controller_spec.rb +33 -0
  352. data/spec/lib/commonwealth-vlr-engine/finder_spec.rb +140 -0
  353. data/spec/lib/commonwealth-vlr-engine/iiif_manifest_spec.rb +157 -0
  354. data/spec/lib/commonwealth-vlr-engine/render_constraints_override_spec.rb +97 -0
  355. data/spec/mailers/notifier_spec.rb +31 -0
  356. data/spec/models/carousel_slide_spec.rb +38 -0
  357. data/spec/spec_helper.rb +40 -0
  358. data/spec/tasks/vlr_engine_rake_spec.rb +28 -0
  359. data/spec/test_app_templates/lib/generators/test_app_generator.rb +23 -0
  360. data/tasks/vlr_engine.rake +46 -0
  361. metadata +788 -0
@@ -0,0 +1 @@
1
+ //= require blacklight_gallery/default
@@ -0,0 +1,165 @@
1
+ /* Blacklight-centric event tracking for link clicks, form submissions, etc. */
2
+
3
+ $(function() {
4
+
5
+ BlacklightGoogleAnalytics = {}
6
+
7
+ BlacklightGoogleAnalytics.console_log_error = function(err, values){
8
+ <% if Rails.env == 'development' %>
9
+ // good place to log in development
10
+ console.log(err);
11
+ console.log(values);
12
+ <% end %>
13
+ };
14
+
15
+ BlacklightGoogleAnalytics.this_or_parent_id = function(that){
16
+ if (that.get(0).id.length > 0){
17
+ var identifier = that.get(0).id;
18
+ } else {
19
+ var identifier = that.parents('[id]:first').get(0).id;
20
+ }
21
+ return identifier;
22
+ };
23
+
24
+ var category = $('body').attr('class').split(' ')[1].toString().replace(/blacklight-/,'').replace(/-/,'#');
25
+
26
+ // generic link tracking
27
+ $('a').click(function () {
28
+ try {
29
+ var action = BlacklightGoogleAnalytics.this_or_parent_id($(this));
30
+ var label = ($(this).text() || $(this).children('img:first').attr('alt'));
31
+ if (action === 'facets-collapse') { // for facets, make the action the facet heading
32
+ var action = 'facet_' + $(this).parents("div:first").find("h5:first").text().trim();
33
+ } else if (action === 'documents') { // search results
34
+ var action = 'result_' + $(this).parents("div:first").attr('class');
35
+ if ($(this).data('counter')) {
36
+ var label = $(this).data('counter');
37
+ }
38
+ } else if (action === 'item_metadata') { // catalog#show metadata links
39
+ var label = $(this).parent().prev("dt").text().replace(/:/,'');
40
+ } else if (action === 'item_breadcrumb') { // catalog#show breadcrumb
41
+ var label = $(this).attr('class');
42
+ } else if (action === 'institution_site_link') { // institutions#show external site URL
43
+ var label = $('img.institution_img_show').attr('alt');
44
+ }
45
+
46
+ ga('send', 'event', category, action, label);
47
+ } catch (err) {
48
+ BlacklightGoogleAnalytics.console_log_error(err, [category, action, label]);
49
+ }
50
+ //BlacklightGoogleAnalytics.pause();
51
+ });
52
+
53
+ // "more" facet ajax-modal clicks
54
+ BlacklightGoogleAnalytics.track_modal_facet_clicks = function () {
55
+ $("#ajax-modal").find('a').click(function () {
56
+ try {
57
+ var action = 'facet_' + $('div.modal-header').find('h3').text();
58
+ var label = $(this).text();
59
+ ga('send', 'event', category, action, label);
60
+ } catch (err) {
61
+ BlacklightGoogleAnalytics.console_log_error(err, [category, action, label]);
62
+ }
63
+ });
64
+ };
65
+
66
+ // modal form submission
67
+ BlacklightGoogleAnalytics.track_modal_form = function () {
68
+ $("#ajax-modal").find('form').submit(function () {
69
+ try{
70
+ var action = 'submit_' + BlacklightGoogleAnalytics.this_or_parent_id($(this));
71
+ ga('send', 'event', category, action);
72
+ } catch(err) {
73
+ BlacklightGoogleAnalytics.console_log_error(err, [category, action]);
74
+ }
75
+ });
76
+ };
77
+
78
+ // OAI item clicks
79
+ $("#oai_img_show_container").find("a").off("click").click(function(){
80
+ try{
81
+ var action = 'oai_item_link';
82
+ var label = $('#item_breadcrumb').find("a.institution_breadcrumb").text();
83
+ ga('send', 'event', category, action, label);
84
+ } catch(err) {
85
+ BlacklightGoogleAnalytics.console_log_error(err, [category, action, label]);
86
+ }
87
+ });
88
+
89
+ // saved searches clicks
90
+ $("#searches_content").find("a").off("click").click(function(){
91
+ try{
92
+ if ($(this).attr('class')) {
93
+ var action = $(this).attr('class');
94
+ } else {
95
+ var action = 'link_to_saved_search';
96
+ }
97
+ ga('send', 'event', category, action);
98
+ } catch(err) {
99
+ BlacklightGoogleAnalytics.console_log_error(err, [category, action]);
100
+ }
101
+ });
102
+
103
+ // search history clicks
104
+ $("#searches_list").find("a").off("click").click(function(){
105
+ try{
106
+ var action = 'link_to_previous_search';
107
+ ga('send', 'event', category, action);
108
+ } catch(err) {
109
+ BlacklightGoogleAnalytics.console_log_error(err, [category, action]);
110
+ }
111
+ });
112
+
113
+ // collections#show series clicks
114
+ $("#series_wrapper").find("a").off("click").click(function(){
115
+ try{
116
+ var action = 'series_' + $(this).parents("div:first").attr('class');
117
+ var label = ($(this).text() || $(this).children('img:first').attr('alt'));
118
+ ga('send', 'event', category, action, label);
119
+ } catch(err) {
120
+ BlacklightGoogleAnalytics.console_log_error(err, [category, action, label]);
121
+ }
122
+ });
123
+
124
+ // institutions#show collection clicks
125
+ $("#institution_collections").find("a").off("click").click(function(){
126
+ try{
127
+ var action = 'collections_' + $(this).parents("div:first").attr('class');
128
+ var label = ($(this).text() || $(this).children('img:first').attr('alt'));
129
+ ga('send', 'event', category, action, label);
130
+ } catch(err) {
131
+ BlacklightGoogleAnalytics.console_log_error(err, [category, action, label]);
132
+ }
133
+ });
134
+
135
+ // form submissions
136
+ $("form").submit(function(){
137
+ try{
138
+ var action = BlacklightGoogleAnalytics.this_or_parent_id($(this));
139
+ var label = "";
140
+ if (action === "folder_item_toggle") { // add item to bookmarks
141
+ var label = "Bookmarks";
142
+ } else if (action === "item_actions_form") { // bookmarks/folders item delete
143
+ var action = "removeLink";
144
+ var label = "Remove"
145
+ } else if (action === "hero_search_form") { // home page search
146
+ var label = $("#search_field").val();
147
+ }
148
+ ga('send', 'event', category, action, label);
149
+ } catch(err) {
150
+ BlacklightGoogleAnalytics.console_log_error(err, [category, action, label]);
151
+ }
152
+ });
153
+
154
+ // image_viewer#book_viewer button clicks
155
+ $("#viewer").find("button").click(function(){
156
+ try{
157
+ var action = BlacklightGoogleAnalytics.this_or_parent_id($(this));
158
+ var label = '';
159
+ ga('send', 'event', category, action, label);
160
+ } catch(err) {
161
+ BlacklightGoogleAnalytics.console_log_error(err, [category, action, label]);
162
+ }
163
+ })
164
+
165
+ });
@@ -0,0 +1,586 @@
1
+ /* modified to remove code relating to Bootstrap JS components not used by
2
+ Blacklight or CommonwealthVLREngine (tab)
3
+ otherwise default version of this script throws errors like:
4
+ "Uncaught TypeError: Cannot read property 'Constructor' of undefined" about tab
5
+ */
6
+ /* ========================================================================
7
+ * Extends Bootstrap v3.1.1
8
+
9
+ * Copyright (c) <2015> PayPal
10
+
11
+ * All rights reserved.
12
+
13
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
14
+
15
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
16
+
17
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
18
+
19
+ * Neither the name of PayPal or any of its subsidiaries or affiliates nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
20
+
21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
+
23
+ * ======================================================================== */
24
+
25
+
26
+ (function($) {
27
+ "use strict";
28
+
29
+ // GENERAL UTILITY FUNCTIONS
30
+ // ===============================
31
+
32
+ var uniqueId = function(prefix) {
33
+ return (prefix || 'ui-id') + '-' + Math.floor((Math.random()*1000)+1)
34
+ }
35
+
36
+
37
+ var removeMultiValAttributes = function (el, attr, val) {
38
+ var describedby = (el.attr( attr ) || "").split( /\s+/ )
39
+ , index = $.inArray(val, describedby)
40
+ if ( index !== -1 ) {
41
+ describedby.splice( index, 1 )
42
+ }
43
+ describedby = $.trim( describedby.join( " " ) )
44
+ if (describedby ) {
45
+ el.attr( attr, describedby )
46
+ } else {
47
+ el.removeAttr( attr )
48
+ }
49
+ }
50
+
51
+ // selectors Courtesy: https://github.com/jquery/jquery-ui/blob/master/ui/core.js
52
+ var focusable = function ( element, isTabIndexNotNaN ) {
53
+ var map, mapName, img,
54
+ nodeName = element.nodeName.toLowerCase();
55
+ if ( "area" === nodeName ) {
56
+ map = element.parentNode;
57
+ mapName = map.name;
58
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
59
+ return false;
60
+ }
61
+ img = $( "img[usemap='#" + mapName + "']" )[ 0 ];
62
+ return !!img && visible( img );
63
+ }
64
+ return ( /input|select|textarea|button|object/.test( nodeName ) ?
65
+ !element.disabled :
66
+ "a" === nodeName ?
67
+ element.href || isTabIndexNotNaN :isTabIndexNotNaN) && visible( element ); // the element and all of its ancestors must be visible
68
+ }
69
+ var visible = function ( element ) {
70
+ return $.expr.filters.visible( element ) &&
71
+ !$( element ).parents().addBack().filter(function() {
72
+ return $.css( this, "visibility" ) === "hidden";
73
+ }).length;
74
+ }
75
+
76
+ $.extend( $.expr[ ":" ], {
77
+ data: $.expr.createPseudo ?
78
+ $.expr.createPseudo(function( dataName ) {
79
+ return function( elem ) {
80
+ return !!$.data( elem, dataName );
81
+ };
82
+ }) :
83
+ // support: jQuery <1.8
84
+ function( elem, i, match ) {
85
+ return !!$.data( elem, match[ 3 ] );
86
+ },
87
+
88
+ focusable: function( element ) {
89
+ return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
90
+ },
91
+
92
+ tabbable: function( element ) {
93
+ var tabIndex = $.attr( element, "tabindex" ),
94
+ isTabIndexNaN = isNaN( tabIndex );
95
+ return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
96
+ }
97
+ });
98
+
99
+ // Modal Extension
100
+ // ===============================
101
+
102
+ $('.modal-dialog').attr( {'role' : 'document'})
103
+ var modalhide = $.fn.modal.Constructor.prototype.hide
104
+ $.fn.modal.Constructor.prototype.hide = function(){
105
+ modalhide.apply(this, arguments)
106
+ $(document).off('keydown.bs.modal')
107
+ }
108
+
109
+ var modalfocus = $.fn.modal.Constructor.prototype.enforceFocus
110
+ $.fn.modal.Constructor.prototype.enforceFocus = function(){
111
+ var focEls = this.$element.find(":tabbable")
112
+ , lastEl = focEls[focEls.length-1]
113
+ $(document).on('keydown.bs.modal', $.proxy(function (ev) {
114
+ if(!this.$element.has(ev.target).length && ev.shiftKey && ev.keyCode === 9) {
115
+ lastEl.focus()
116
+ ev.preventDefault();
117
+ }
118
+ }, this))
119
+
120
+ modalfocus.apply(this, arguments)
121
+ }
122
+
123
+ // DROPDOWN Extension
124
+ // ===============================
125
+
126
+ var toggle = '[data-toggle=dropdown]'
127
+ , $par
128
+ , firstItem
129
+ , focusDelay = 200
130
+ , menus = $(toggle).parent().find('ul').attr('role','menu')
131
+ , lis = menus.find('li').attr('role','presentation')
132
+
133
+ lis.find('a').attr({'role':'menuitem', 'tabIndex':'-1'})
134
+ $(toggle).attr({ 'aria-haspopup':'true', 'aria-expanded': 'false'})
135
+
136
+ $(toggle).parent().on('shown.bs.dropdown',function(e){
137
+ $par = $(this)
138
+ var $toggle = $par.find(toggle)
139
+ $toggle.attr('aria-expanded','true')
140
+ $toggle.on('keydown.bs.dropdown', $.proxy(function (ev) {
141
+ setTimeout(function(){
142
+ firstItem = $('.dropdown-menu [role=menuitem]:visible', $par)[0]
143
+ try{ firstItem.focus()} catch(ex) {}
144
+ }, focusDelay)
145
+ }, this))
146
+
147
+ })
148
+
149
+ $(toggle).parent().on('hidden.bs.dropdown',function(e){
150
+ $par = $(this)
151
+ var $toggle = $par.find(toggle)
152
+ $toggle.attr('aria-expanded','false')
153
+ })
154
+
155
+ $(document)
156
+ .on('focusout.dropdown.data-api', '.dropdown-menu', function(e){
157
+ var $this = $(this)
158
+ , that = this
159
+ setTimeout(function() {
160
+ if(!$.contains(that, document.activeElement)){
161
+ $this.parent().removeClass('open')
162
+ $this.parent().find('[data-toggle=dropdown]').attr('aria-expanded','false')
163
+ }
164
+ }, 150)
165
+ })
166
+ .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , $.fn.dropdown.Constructor.prototype.keydown)
167
+
168
+ // Collapse Extension
169
+ // ===============================
170
+
171
+ var $colltabs = $('[data-toggle="collapse"]')
172
+ $colltabs.each(function( index ) {
173
+ var colltab = $(this)
174
+ , collpanel = (colltab.attr('data-target')) ? $(colltab.attr('data-target')) : $(colltab.attr('href'))
175
+ , parent = colltab.attr('data-parent')
176
+ , collparent = parent && $(parent)
177
+ , collid = colltab.attr('id') || uniqueId('ui-collapse')
178
+
179
+ colltab.attr('id', collid)
180
+
181
+ if(collparent){
182
+ colltab.attr({ 'role':'tab', 'aria-selected':'false', 'aria-expanded':'false' })
183
+ $(collparent).find('div:not(.collapse,.panel-body), h4').attr('role','presentation')
184
+ collparent.attr({ 'role' : 'tablist', 'aria-multiselectable' : 'true' })
185
+
186
+ if(collpanel.hasClass('in')){
187
+ colltab.attr({ 'aria-controls': collpanel.attr('id'), 'aria-selected':'true', 'aria-expanded':'true', 'tabindex':'0' })
188
+ collpanel.attr({ 'role':'tabpanel', 'tabindex':'0', 'aria-labelledby':collid, 'aria-hidden':'false' })
189
+ }else{
190
+ colltab.attr({'aria-controls' : collpanel.attr('id'), 'tabindex':'-1' })
191
+ collpanel.attr({ 'role':'tabpanel', 'tabindex':'-1', 'aria-labelledby':collid, 'aria-hidden':'true' })
192
+ }
193
+ }
194
+ })
195
+
196
+ var collToggle = $.fn.collapse.Constructor.prototype.toggle
197
+ $.fn.collapse.Constructor.prototype.toggle = function(){
198
+ var prevTab = this.$parent && this.$parent.find('[aria-expanded="true"]') , href
199
+
200
+ if(prevTab){
201
+ var prevPanel = prevTab.attr('data-target') || (href = prevTab.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')
202
+ , $prevPanel = $(prevPanel)
203
+ , $curPanel = this.$element
204
+ , par = this.$parent
205
+ , curTab
206
+
207
+ if (this.$parent) curTab = this.$parent.find('[data-toggle=collapse][href="#' + this.$element.attr('id') + '"]')
208
+
209
+ collToggle.apply(this, arguments)
210
+
211
+ if ($.support.transition) {
212
+ this.$element.one($.support.transition.end, function(){
213
+
214
+ prevTab.attr({ 'aria-selected':'false','aria-expanded':'false', 'tabIndex':'-1' })
215
+ $prevPanel.attr({ 'aria-hidden' : 'true','tabIndex' : '-1'})
216
+
217
+ curTab.attr({ 'aria-selected':'true','aria-expanded':'true', 'tabIndex':'0' })
218
+
219
+ if($curPanel.hasClass('in')){
220
+ $curPanel.attr({ 'aria-hidden' : 'false','tabIndex' : '0' })
221
+ }else{
222
+ curTab.attr({ 'aria-selected':'false','aria-expanded':'false'})
223
+ $curPanel.attr({ 'aria-hidden' : 'true','tabIndex' : '-1' })
224
+ }
225
+ })
226
+ }
227
+ }else{
228
+ collToggle.apply(this, arguments)
229
+ }
230
+ }
231
+
232
+ $.fn.collapse.Constructor.prototype.keydown = function (e) {
233
+ var $this = $(this)
234
+ , $items
235
+ , $tablist = $this.closest('div[role=tablist] ')
236
+ , index
237
+ , k = e.which || e.keyCode
238
+
239
+ $this = $(this)
240
+ if (!/(32|37|38|39|40)/.test(k)) return
241
+ if(k==32) $this.click()
242
+
243
+ $items = $tablist.find('[role=tab]')
244
+ index = $items.index($items.filter(':focus'))
245
+
246
+ if (k == 38 || k == 37) index-- // up & left
247
+ if (k == 39 || k == 40) index++ // down & right
248
+ if(index < 0) index = $items.length -1
249
+ if(index == $items.length) index = 0
250
+
251
+ $items.eq(index).focus()
252
+
253
+ e.preventDefault()
254
+ e.stopPropagation()
255
+
256
+ }
257
+
258
+ $(document).on('keydown.collapse.data-api','[data-toggle="collapse"]' , $.fn.collapse.Constructor.prototype.keydown)
259
+
260
+ // Carousel Extension
261
+ // ===============================
262
+
263
+ $('.carousel').each(function (index) {
264
+
265
+ // This function positions a highlight box around the tabs in the tablist to use in focus styling
266
+
267
+ function setTablistHighlightBox() {
268
+
269
+ var $tab
270
+ , offset
271
+ , height
272
+ , width
273
+ , highlightBox = {}
274
+
275
+ highlightBox.top = 0
276
+ highlightBox.left = 32000
277
+ highlightBox.height = 0
278
+ highlightBox.width = 0
279
+
280
+ for (var i = 0; i < $tabs.length; i++) {
281
+ $tab = $tabs[i]
282
+ offset = $($tab).offset()
283
+ height = $($tab).height()
284
+ width = $($tab).width()
285
+
286
+ // console.log(" Top: " + offset.top + " Left: " + offset.left + " Height: " + height + " Width: " + width)
287
+
288
+ if (highlightBox.top < offset.top) {
289
+ highlightBox.top = Math.round(offset.top)
290
+ }
291
+
292
+ if (highlightBox.height < height) {
293
+ highlightBox.height = Math.round(height)
294
+ }
295
+
296
+ if (highlightBox.left > offset.left) {
297
+ highlightBox.left = Math.round(offset.left)
298
+ }
299
+
300
+ var w = (offset.left - highlightBox.left) + Math.round(width)
301
+
302
+ if (highlightBox.width < w) {
303
+ highlightBox.width = w
304
+ }
305
+
306
+ } // end for
307
+
308
+ // console.log("[HIGHLIGHT] Top: " + highlightBox.top + " Left: " + highlightBox.left + " Height: " + highlightBox.height + " Width: " + highlightBox.width)
309
+
310
+ $tablistHighlight.style.top = (highlightBox.top - 2) + 'px'
311
+ $tablistHighlight.style.left = (highlightBox.left - 2) + 'px'
312
+ $tablistHighlight.style.height = (highlightBox.height + 7) + 'px'
313
+ $tablistHighlight.style.width = (highlightBox.width + 8) + 'px'
314
+
315
+ } // end function
316
+
317
+ var $this = $(this)
318
+ , $prev = $this.find('[data-slide="prev"]')
319
+ , $next = $this.find('[data-slide="next"]')
320
+ , $tablist = $this.find('.carousel-indicators')
321
+ , $tabs = $this.find('.carousel-indicators li')
322
+ , $tabpanels = $this.find('.item')
323
+ , $tabpanel
324
+ , $tablistHighlight
325
+ , $pauseCarousel
326
+ , $complementaryLandmark
327
+ , $tab
328
+ , $is_paused = false
329
+ , offset
330
+ , height
331
+ , width
332
+ , i
333
+ , id_title = 'id_title'
334
+ , id_desc = 'id_desc'
335
+
336
+
337
+ $tablist.attr('role', 'tablist')
338
+
339
+ $tabs.focus(function() {
340
+ $this.carousel('pause')
341
+ $is_paused = true
342
+ $pauseCarousel.innerHTML = "Play Carousel"
343
+ $(this).parent().addClass('active');
344
+ // $(this).addClass('focus')
345
+ setTablistHighlightBox()
346
+ $($tablistHighlight).addClass('focus')
347
+ $(this).parents('.carousel').addClass('contrast')
348
+ })
349
+
350
+ $tabs.blur(function(event) {
351
+ $(this).parent().removeClass('active');
352
+ // $(this).removeClass('focus')
353
+ $($tablistHighlight).removeClass('focus')
354
+ $(this).parents('.carousel').removeClass('contrast')
355
+ })
356
+
357
+
358
+ for (i = 0; i < $tabpanels.length; i++) {
359
+ $tabpanel = $tabpanels[i]
360
+ $tabpanel.setAttribute('role', 'tabpanel')
361
+ $tabpanel.setAttribute('id', 'tabpanel-' + index + '-' + i)
362
+ $tabpanel.setAttribute('aria-labelledby', 'tab-' + index + '-' + i)
363
+ }
364
+
365
+ if (typeof $this.attr('role') !== 'string') {
366
+ $this.attr('role', 'complementary');
367
+ $this.attr('aria-labelledby', id_title);
368
+ $this.attr('aria-describedby', id_desc);
369
+ $this.prepend('<p id="' + id_desc + '" class="sr-only">A carousel is a rotating set of images, rotation stops on keyboard focus on carousel tab controls or hovering the mouse pointer over images. Use the tabs or the previous and next buttons to change the displayed slide.</p>')
370
+ $this.prepend('<h2 id="' + id_title + '" class="sr-only">Carousel content with ' + $tabpanels.length + ' slides.</h2>')
371
+ }
372
+
373
+
374
+ for (i = 0; i < $tabs.length; i++) {
375
+ $tab = $tabs[i]
376
+
377
+ $tab.setAttribute('role', 'tab')
378
+ $tab.setAttribute('id', 'tab-' + index + '-' + i)
379
+ $tab.setAttribute('aria-controls', 'tabpanel-' + index + '-' + i)
380
+
381
+ var tpId = '#tabpanel-' + index + '-' + i
382
+ var caption = $this.find(tpId).find('h1').text()
383
+
384
+ if ((typeof caption !== 'string') || (caption.length === 0)) caption = $this.find(tpId).text()
385
+ if ((typeof caption !== 'string') || (caption.length === 0)) caption = $this.find(tpId).find('h3').text()
386
+ if ((typeof caption !== 'string') || (caption.length === 0)) caption = $this.find(tpId).find('h4').text()
387
+ if ((typeof caption !== 'string') || (caption.length === 0)) caption = $this.find(tpId).find('h5').text()
388
+ if ((typeof caption !== 'string') || (caption.length === 0)) caption = $this.find(tpId).find('h6').text()
389
+ if ((typeof caption !== 'string') || (caption.length === 0)) caption = "no title";
390
+
391
+ // console.log("CAPTION: " + caption )
392
+
393
+ var tabName = document.createElement('span')
394
+ tabName.setAttribute('class', 'sr-only')
395
+ tabName.innerHTML='Slide ' + (i+1)
396
+ if (caption) tabName.innerHTML += ": " + caption
397
+ $tab.appendChild(tabName)
398
+
399
+ }
400
+
401
+ // create div for focus styling of tablist
402
+ $tablistHighlight = document.createElement('div')
403
+ $tablistHighlight.className = 'carousel-tablist-highlight'
404
+ document.body.appendChild($tablistHighlight)
405
+
406
+ // create button for screen reader users to stop rotation of carousel
407
+
408
+ // create button for screen reader users to pause carousel for virtual mode review
409
+ $complementaryLandmark = document.createElement('aside')
410
+ $complementaryLandmark.setAttribute('aria-label', 'carousel pause/play control')
411
+ $(document.body).prepend($complementaryLandmark)
412
+
413
+ $pauseCarousel = document.createElement('button')
414
+ $pauseCarousel.className = "carousel-pause-button"
415
+ $pauseCarousel.innerHTML = "Pause Carousel"
416
+ $pauseCarousel.setAttribute('title', "Pause/Play carousel button can be used by screen reader users to stop carousel animations")
417
+ $($complementaryLandmark).append($pauseCarousel)
418
+
419
+ $($pauseCarousel).click(function() {
420
+ if ($is_paused) {
421
+ $pauseCarousel.innerHTML = "Pause Carousel"
422
+ $this.carousel('cycle')
423
+ $is_paused = false
424
+ }
425
+ else {
426
+ $pauseCarousel.innerHTML = "Play Carousel"
427
+ $this.carousel('pause')
428
+ $is_paused = true
429
+ }
430
+ })
431
+ $($pauseCarousel).focus(function() {
432
+ $(this).addClass('focus')
433
+ })
434
+
435
+ $($pauseCarousel).blur(function() {
436
+ $(this).removeClass('focus')
437
+ })
438
+
439
+ setTablistHighlightBox()
440
+
441
+ $( window ).resize(function() {
442
+ setTablistHighlightBox()
443
+ })
444
+
445
+ // Add space bar behavior to prev and next buttons for SR compatibility
446
+ $prev.attr('aria-label', 'Previous Slide')
447
+ $prev.keydown(function(e) {
448
+ var k = e.which || e.keyCode
449
+ if (/(13|32)/.test(k)) {
450
+ e.preventDefault()
451
+ e.stopPropagation()
452
+ $prev.trigger('click');
453
+ }
454
+ });
455
+
456
+ $prev.focus(function() {
457
+ $(this).parents('.carousel').addClass('contrast')
458
+ })
459
+
460
+ $prev.blur(function() {
461
+ $(this).parents('.carousel').removeClass('contrast')
462
+ })
463
+
464
+ $next.attr('aria-label', 'Next Slide')
465
+ $next.keydown(function(e) {
466
+ var k = e.which || e.keyCode
467
+ if (/(13|32)/.test(k)) {
468
+ e.preventDefault()
469
+ e.stopPropagation()
470
+ $next.trigger('click');
471
+ }
472
+ });
473
+
474
+ $next.focus(function() {
475
+ $(this).parents('.carousel').addClass('contrast')
476
+ })
477
+
478
+ $next.blur(function() {
479
+ $(this).parents('.carousel').removeClass('contrast')
480
+ })
481
+
482
+ $('.carousel-inner a').focus(function() {
483
+ $(this).parents('.carousel').addClass('contrast')
484
+ })
485
+
486
+ $('.carousel-inner a').blur(function() {
487
+ $(this).parents('.carousel').removeClass('contrast')
488
+ })
489
+
490
+ $tabs.each(function () {
491
+ var item = $(this)
492
+ if(item.hasClass('active')) {
493
+ item.attr({ 'aria-selected': 'true', 'tabindex' : '0' })
494
+ }else{
495
+ item.attr({ 'aria-selected': 'false', 'tabindex' : '-1' })
496
+ }
497
+ })
498
+ })
499
+
500
+ var slideCarousel = $.fn.carousel.Constructor.prototype.slide
501
+ $.fn.carousel.Constructor.prototype.slide = function (type, next) {
502
+ var $element = this.$element
503
+ , $active = $element.find('[role=tabpanel].active')
504
+ , $next = next || $active[type]()
505
+ , $tab
506
+ , $tab_count = $element.find('[role=tabpanel]').size()
507
+ , $prev_side = $element.find('[data-slide="prev"]')
508
+ , $next_side = $element.find('[data-slide="next"]')
509
+ , $index = 0
510
+ , $prev_index = $tab_count -1
511
+ , $next_index = 1
512
+ , $id
513
+
514
+ if ($next && $next.attr('id')) {
515
+ $id = $next.attr('id')
516
+ $index = $id.lastIndexOf("-")
517
+ if ($index >= 0) $index = parseInt($id.substring($index+1), 10)
518
+
519
+ $prev_index = $index - 1
520
+ if ($prev_index < 1) $prev_index = $tab_count - 1
521
+
522
+ $next_index = $index + 1
523
+ if ($next_index >= $tab_count) $next_index = 0
524
+ }
525
+
526
+ $prev_side.attr('aria-label', 'Show slide ' + ($prev_index+1) + ' of ' + $tab_count)
527
+ $next_side.attr('aria-label', 'Show slide ' + ($next_index+1) + ' of ' + $tab_count)
528
+
529
+
530
+ slideCarousel.apply(this, arguments)
531
+
532
+ $active
533
+ .one('bsTransitionEnd', function () {
534
+ var $tab
535
+
536
+ $tab = $element.find('li[aria-controls="' + $active.attr('id') + '"]')
537
+ if ($tab) $tab.attr({'aria-selected':false, 'tabIndex': '-1'})
538
+
539
+ $tab = $element.find('li[aria-controls="' + $next.attr('id') + '"]')
540
+ if ($tab) $tab.attr({'aria-selected': true, 'tabIndex': '0'})
541
+
542
+ })
543
+ }
544
+
545
+ var $this;
546
+ $.fn.carousel.Constructor.prototype.keydown = function (e) {
547
+
548
+ $this = $this || $(this)
549
+ if(this instanceof Node) $this = $(this)
550
+
551
+ function selectTab(index) {
552
+ if (index >= $tabs.length) return
553
+ if (index < 0) return
554
+
555
+ $carousel.carousel(index)
556
+ setTimeout(function () {
557
+ $tabs[index].focus()
558
+ // $this.prev().focus()
559
+ }, 150)
560
+ }
561
+
562
+ var $carousel = $(e.target).closest('.carousel')
563
+ , $tabs = $carousel.find('[role=tab]')
564
+ , k = e.which || e.keyCode
565
+ , index
566
+
567
+ if (!/(37|38|39|40)/.test(k)) return
568
+
569
+ index = $tabs.index($tabs.filter('.active'))
570
+ if (k == 37 || k == 38) { // Up
571
+ index--
572
+ selectTab(index);
573
+ }
574
+
575
+ if (k == 39 || k == 40) { // Down
576
+ index++
577
+ selectTab(index);
578
+ }
579
+
580
+ e.preventDefault()
581
+ e.stopPropagation()
582
+ }
583
+ $(document).on('keydown.carousel.data-api', 'li[role=tab]', $.fn.carousel.Constructor.prototype.keydown)
584
+
585
+
586
+ })(jQuery);