commonwealth-vlr-engine 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,113 @@
1
+ // https://github.com/AceMetrix/jquery-deparam
2
+ (function(deparam){
3
+ if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
4
+ var jquery = require('jquery');
5
+ module.exports = deparam(jquery);
6
+ } else if (typeof define === 'function' && define.amd){
7
+ define(['jquery'], function(jquery){
8
+ return deparam(jquery);
9
+ });
10
+ } else {
11
+ var global
12
+ try {
13
+ global = (false || eval)('this'); // best cross-browser way to determine global for < ES5
14
+ } catch (e) {
15
+ global = window; // fails only if browser (https://developer.mozilla.org/en-US/docs/Web/Security/CSP/CSP_policy_directives)
16
+ }
17
+ global.deparam = deparam(jQuery); // assume jQuery is in global namespace
18
+ }
19
+ })(function ($) {
20
+ var deparam = function( params, coerce ) {
21
+ var obj = {},
22
+ coerce_types = { 'true': !0, 'false': !1, 'null': null };
23
+
24
+ // Iterate over all name=value pairs.
25
+ params.replace(/\+/g, ' ').split('&').forEach(function(v){
26
+ var param = v.split( '=' ),
27
+ key = decodeURIComponent( param[0] ),
28
+ val,
29
+ cur = obj,
30
+ i = 0,
31
+
32
+ // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it
33
+ // into its component parts.
34
+ keys = key.split( '][' ),
35
+ keys_last = keys.length - 1;
36
+
37
+ // If the first keys part contains [ and the last ends with ], then []
38
+ // are correctly balanced.
39
+ if ( /\[/.test( keys[0] ) && /\]$/.test( keys[ keys_last ] ) ) {
40
+ // Remove the trailing ] from the last keys part.
41
+ keys[ keys_last ] = keys[ keys_last ].replace( /\]$/, '' );
42
+
43
+ // Split first keys part into two parts on the [ and add them back onto
44
+ // the beginning of the keys array.
45
+ keys = keys.shift().split('[').concat( keys );
46
+
47
+ keys_last = keys.length - 1;
48
+ } else {
49
+ // Basic 'foo' style key.
50
+ keys_last = 0;
51
+ }
52
+
53
+ // Are we dealing with a name=value pair, or just a name?
54
+ if ( param.length === 2 ) {
55
+ val = decodeURIComponent( param[1] );
56
+
57
+ // Coerce values.
58
+ if ( coerce ) {
59
+ val = val && !isNaN(val) && ((+val + '') === val) ? +val // number
60
+ : val === 'undefined' ? undefined // undefined
61
+ : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null
62
+ : val; // string
63
+ }
64
+
65
+ if ( keys_last ) {
66
+ // Complex key, build deep object structure based on a few rules:
67
+ // * The 'cur' pointer starts at the object top-level.
68
+ // * [] = array push (n is set to array length), [n] = array if n is
69
+ // numeric, otherwise object.
70
+ // * If at the last keys part, set the value.
71
+ // * For each keys part, if the current level is undefined create an
72
+ // object or array based on the type of the next keys part.
73
+ // * Move the 'cur' pointer to the next level.
74
+ // * Rinse & repeat.
75
+ for ( ; i <= keys_last; i++ ) {
76
+ key = keys[i] === '' ? cur.length : keys[i];
77
+ cur = cur[key] = i < keys_last
78
+ ? cur[key] || ( keys[i+1] && isNaN( keys[i+1] ) ? {} : [] )
79
+ : val;
80
+ }
81
+
82
+ } else {
83
+ // Simple key, even simpler rules, since only scalars and shallow
84
+ // arrays are allowed.
85
+
86
+ if ( Object.prototype.toString.call( obj[key] ) === '[object Array]' ) {
87
+ // val is already an array, so push on the next value.
88
+ obj[key].push( val );
89
+
90
+ } else if ( {}.hasOwnProperty.call(obj, key) ) {
91
+ // val isn't an array, but since a second value has been specified,
92
+ // convert val into an array.
93
+ obj[key] = [ obj[key], val ];
94
+
95
+ } else {
96
+ // val is a scalar.
97
+ obj[key] = val;
98
+ }
99
+ }
100
+
101
+ } else if ( key ) {
102
+ // No value was defined, so set something meaningful.
103
+ obj[key] = coerce
104
+ ? undefined
105
+ : '';
106
+ }
107
+ });
108
+
109
+ return obj;
110
+ };
111
+ $.prototype.deparam = $.deparam = deparam;
112
+ return deparam;
113
+ });
@@ -0,0 +1,9 @@
1
+ /*
2
+ * jQuery throttle / debounce - v1.1 - 3/7/2010
3
+ * http://benalman.com/projects/jquery-throttle-debounce-plugin/
4
+ *
5
+ * Copyright (c) 2010 "Cowboy" Ben Alman
6
+ * Dual licensed under the MIT and GPL licenses.
7
+ * http://benalman.com/about/license/
8
+ */
9
+ (function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this);
@@ -0,0 +1,7 @@
1
+ /*! Hammer.JS - v1.0.5 - 2013-04-07
2
+ * http://eightmedia.github.com/hammer.js
3
+ *
4
+ * Copyright (c) 2013 Jorik Tangelder <j.tangelder@gmail.com>;
5
+ * Licensed under the MIT license */
6
+
7
+ (function(t,e){"use strict";function n(){if(!i.READY){i.event.determineEventTypes();for(var t in i.gestures)i.gestures.hasOwnProperty(t)&&i.detection.register(i.gestures[t]);i.event.onTouch(i.DOCUMENT,i.EVENT_MOVE,i.detection.detect),i.event.onTouch(i.DOCUMENT,i.EVENT_END,i.detection.detect),i.READY=!0}}var i=function(t,e){return new i.Instance(t,e||{})};i.defaults={stop_browser_behavior:{userSelect:"none",touchAction:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},i.HAS_POINTEREVENTS=navigator.pointerEnabled||navigator.msPointerEnabled,i.HAS_TOUCHEVENTS="ontouchstart"in t,i.MOBILE_REGEX=/mobile|tablet|ip(ad|hone|od)|android/i,i.NO_MOUSEEVENTS=i.HAS_TOUCHEVENTS&&navigator.userAgent.match(i.MOBILE_REGEX),i.EVENT_TYPES={},i.DIRECTION_DOWN="down",i.DIRECTION_LEFT="left",i.DIRECTION_UP="up",i.DIRECTION_RIGHT="right",i.POINTER_MOUSE="mouse",i.POINTER_TOUCH="touch",i.POINTER_PEN="pen",i.EVENT_START="start",i.EVENT_MOVE="move",i.EVENT_END="end",i.DOCUMENT=document,i.plugins={},i.READY=!1,i.Instance=function(t,e){var r=this;return n(),this.element=t,this.enabled=!0,this.options=i.utils.extend(i.utils.extend({},i.defaults),e||{}),this.options.stop_browser_behavior&&i.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),i.event.onTouch(t,i.EVENT_START,function(t){r.enabled&&i.detection.startDetect(r,t)}),this},i.Instance.prototype={on:function(t,e){for(var n=t.split(" "),i=0;n.length>i;i++)this.element.addEventListener(n[i],e,!1);return this},off:function(t,e){for(var n=t.split(" "),i=0;n.length>i;i++)this.element.removeEventListener(n[i],e,!1);return this},trigger:function(t,e){var n=i.DOCUMENT.createEvent("Event");n.initEvent(t,!0,!0),n.gesture=e;var r=this.element;return i.utils.hasParent(e.target,r)&&(r=e.target),r.dispatchEvent(n),this},enable:function(t){return this.enabled=t,this}};var r=null,o=!1,s=!1;i.event={bindDom:function(t,e,n){for(var i=e.split(" "),r=0;i.length>r;r++)t.addEventListener(i[r],n,!1)},onTouch:function(t,e,n){var a=this;this.bindDom(t,i.EVENT_TYPES[e],function(c){var u=c.type.toLowerCase();if(!u.match(/mouse/)||!s){(u.match(/touch/)||u.match(/pointerdown/)||u.match(/mouse/)&&1===c.which)&&(o=!0),u.match(/touch|pointer/)&&(s=!0);var h=0;o&&(i.HAS_POINTEREVENTS&&e!=i.EVENT_END?h=i.PointerEvent.updatePointer(e,c):u.match(/touch/)?h=c.touches.length:s||(h=u.match(/up/)?0:1),h>0&&e==i.EVENT_END?e=i.EVENT_MOVE:h||(e=i.EVENT_END),h||null===r?r=c:c=r,n.call(i.detection,a.collectEventData(t,e,c)),i.HAS_POINTEREVENTS&&e==i.EVENT_END&&(h=i.PointerEvent.updatePointer(e,c))),h||(r=null,o=!1,s=!1,i.PointerEvent.reset())}})},determineEventTypes:function(){var t;t=i.HAS_POINTEREVENTS?i.PointerEvent.getEvents():i.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],i.EVENT_TYPES[i.EVENT_START]=t[0],i.EVENT_TYPES[i.EVENT_MOVE]=t[1],i.EVENT_TYPES[i.EVENT_END]=t[2]},getTouchList:function(t){return i.HAS_POINTEREVENTS?i.PointerEvent.getTouchList():t.touches?t.touches:[{identifier:1,pageX:t.pageX,pageY:t.pageY,target:t.target}]},collectEventData:function(t,e,n){var r=this.getTouchList(n,e),o=i.POINTER_TOUCH;return(n.type.match(/mouse/)||i.PointerEvent.matchType(i.POINTER_MOUSE,n))&&(o=i.POINTER_MOUSE),{center:i.utils.getCenter(r),timeStamp:(new Date).getTime(),target:n.target,touches:r,eventType:e,pointerType:o,srcEvent:n,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault&&this.srcEvent.preventDefault()},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return i.detection.stopDetect()}}}},i.PointerEvent={pointers:{},getTouchList:function(){var t=this,e=[];return Object.keys(t.pointers).sort().forEach(function(n){e.push(t.pointers[n])}),e},updatePointer:function(t,e){return t==i.EVENT_END?this.pointers={}:(e.identifier=e.pointerId,this.pointers[e.pointerId]=e),Object.keys(this.pointers).length},matchType:function(t,e){if(!e.pointerType)return!1;var n={};return n[i.POINTER_MOUSE]=e.pointerType==e.MSPOINTER_TYPE_MOUSE||e.pointerType==i.POINTER_MOUSE,n[i.POINTER_TOUCH]=e.pointerType==e.MSPOINTER_TYPE_TOUCH||e.pointerType==i.POINTER_TOUCH,n[i.POINTER_PEN]=e.pointerType==e.MSPOINTER_TYPE_PEN||e.pointerType==i.POINTER_PEN,n[t]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},i.utils={extend:function(t,n,i){for(var r in n)t[r]!==e&&i||(t[r]=n[r]);return t},hasParent:function(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1},getCenter:function(t){for(var e=[],n=[],i=0,r=t.length;r>i;i++)e.push(t[i].pageX),n.push(t[i].pageY);return{pageX:(Math.min.apply(Math,e)+Math.max.apply(Math,e))/2,pageY:(Math.min.apply(Math,n)+Math.max.apply(Math,n))/2}},getVelocity:function(t,e,n){return{x:Math.abs(e/t)||0,y:Math.abs(n/t)||0}},getAngle:function(t,e){var n=e.pageY-t.pageY,i=e.pageX-t.pageX;return 180*Math.atan2(n,i)/Math.PI},getDirection:function(t,e){var n=Math.abs(t.pageX-e.pageX),r=Math.abs(t.pageY-e.pageY);return n>=r?t.pageX-e.pageX>0?i.DIRECTION_LEFT:i.DIRECTION_RIGHT:t.pageY-e.pageY>0?i.DIRECTION_UP:i.DIRECTION_DOWN},getDistance:function(t,e){var n=e.pageX-t.pageX,i=e.pageY-t.pageY;return Math.sqrt(n*n+i*i)},getScale:function(t,e){return t.length>=2&&e.length>=2?this.getDistance(e[0],e[1])/this.getDistance(t[0],t[1]):1},getRotation:function(t,e){return t.length>=2&&e.length>=2?this.getAngle(e[1],e[0])-this.getAngle(t[1],t[0]):0},isVertical:function(t){return t==i.DIRECTION_UP||t==i.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(t,e){var n,i=["webkit","khtml","moz","ms","o",""];if(e&&t.style){for(var r=0;i.length>r;r++)for(var o in e)e.hasOwnProperty(o)&&(n=o,i[r]&&(n=i[r]+n.substring(0,1).toUpperCase()+n.substring(1)),t.style[n]=e[o]);"none"==e.userSelect&&(t.onselectstart=function(){return!1})}}},i.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,e){this.current||(this.stopped=!1,this.current={inst:t,startEvent:i.utils.extend({},e),lastEvent:!1,name:""},this.detect(e))},detect:function(t){if(this.current&&!this.stopped){t=this.extendEventData(t);for(var e=this.current.inst.options,n=0,r=this.gestures.length;r>n;n++){var o=this.gestures[n];if(!this.stopped&&e[o.name]!==!1&&o.handler.call(o,t,this.current.inst)===!1){this.stopDetect();break}}return this.current&&(this.current.lastEvent=t),t.eventType==i.EVENT_END&&!t.touches.length-1&&this.stopDetect(),t}},stopDetect:function(){this.previous=i.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(t){var e=this.current.startEvent;if(e&&(t.touches.length!=e.touches.length||t.touches===e.touches)){e.touches=[];for(var n=0,r=t.touches.length;r>n;n++)e.touches.push(i.utils.extend({},t.touches[n]))}var o=t.timeStamp-e.timeStamp,s=t.center.pageX-e.center.pageX,a=t.center.pageY-e.center.pageY,c=i.utils.getVelocity(o,s,a);return i.utils.extend(t,{deltaTime:o,deltaX:s,deltaY:a,velocityX:c.x,velocityY:c.y,distance:i.utils.getDistance(e.center,t.center),angle:i.utils.getAngle(e.center,t.center),direction:i.utils.getDirection(e.center,t.center),scale:i.utils.getScale(e.touches,t.touches),rotation:i.utils.getRotation(e.touches,t.touches),startEvent:e}),t},register:function(t){var n=t.defaults||{};return n[t.name]===e&&(n[t.name]=!0),i.utils.extend(i.defaults,n,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(t,e){return t.index<e.index?-1:t.index>e.index?1:0}),this.gestures}},i.gestures=i.gestures||{},i.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:1},timer:null,handler:function(t,e){switch(t.eventType){case i.EVENT_START:clearTimeout(this.timer),i.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==i.detection.current.name&&e.trigger("hold",t)},e.options.hold_timeout);break;case i.EVENT_MOVE:t.distance>e.options.hold_threshold&&clearTimeout(this.timer);break;case i.EVENT_END:clearTimeout(this.timer)}}},i.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,tap_always:!0,doubletap_distance:20,doubletap_interval:300},handler:function(t,e){if(t.eventType==i.EVENT_END){var n=i.detection.previous,r=!1;if(t.deltaTime>e.options.tap_max_touchtime||t.distance>e.options.tap_max_distance)return;n&&"tap"==n.name&&t.timeStamp-n.lastEvent.timeStamp<e.options.doubletap_interval&&t.distance<e.options.doubletap_distance&&(e.trigger("doubletap",t),r=!0),(!r||e.options.tap_always)&&(i.detection.current.name="tap",e.trigger(i.detection.current.name,t))}}},i.gestures.Swipe={name:"swipe",index:40,defaults:{swipe_max_touches:1,swipe_velocity:.7},handler:function(t,e){if(t.eventType==i.EVENT_END){if(e.options.swipe_max_touches>0&&t.touches.length>e.options.swipe_max_touches)return;(t.velocityX>e.options.swipe_velocity||t.velocityY>e.options.swipe_velocity)&&(e.trigger(this.name,t),e.trigger(this.name+t.direction,t))}}},i.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,drag_max_touches:1,drag_block_horizontal:!1,drag_block_vertical:!1,drag_lock_to_axis:!1,drag_lock_min_distance:25},triggered:!1,handler:function(t,n){if(i.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),this.triggered=!1,e;if(!(n.options.drag_max_touches>0&&t.touches.length>n.options.drag_max_touches))switch(t.eventType){case i.EVENT_START:this.triggered=!1;break;case i.EVENT_MOVE:if(t.distance<n.options.drag_min_distance&&i.detection.current.name!=this.name)return;i.detection.current.name=this.name,(i.detection.current.lastEvent.drag_locked_to_axis||n.options.drag_lock_to_axis&&n.options.drag_lock_min_distance<=t.distance)&&(t.drag_locked_to_axis=!0);var r=i.detection.current.lastEvent.direction;t.drag_locked_to_axis&&r!==t.direction&&(t.direction=i.utils.isVertical(r)?0>t.deltaY?i.DIRECTION_UP:i.DIRECTION_DOWN:0>t.deltaX?i.DIRECTION_LEFT:i.DIRECTION_RIGHT),this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),n.trigger(this.name+t.direction,t),(n.options.drag_block_vertical&&i.utils.isVertical(t.direction)||n.options.drag_block_horizontal&&!i.utils.isVertical(t.direction))&&t.preventDefault();break;case i.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},i.gestures.Transform={name:"transform",index:45,defaults:{transform_min_scale:.01,transform_min_rotation:1,transform_always_block:!1},triggered:!1,handler:function(t,n){if(i.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),this.triggered=!1,e;if(!(2>t.touches.length))switch(n.options.transform_always_block&&t.preventDefault(),t.eventType){case i.EVENT_START:this.triggered=!1;break;case i.EVENT_MOVE:var r=Math.abs(1-t.scale),o=Math.abs(t.rotation);if(n.options.transform_min_scale>r&&n.options.transform_min_rotation>o)return;i.detection.current.name=this.name,this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),o>n.options.transform_min_rotation&&n.trigger("rotate",t),r>n.options.transform_min_scale&&(n.trigger("pinch",t),n.trigger("pinch"+(1>t.scale?"in":"out"),t));break;case i.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},i.gestures.Touch={name:"touch",index:-1/0,defaults:{prevent_default:!1,prevent_mouseevents:!1},handler:function(t,n){return n.options.prevent_mouseevents&&t.pointerType==i.POINTER_MOUSE?(t.stopDetect(),e):(n.options.prevent_default&&t.preventDefault(),t.eventType==i.EVENT_START&&n.trigger(this.name,t),e)}},i.gestures.Release={name:"release",index:1/0,handler:function(t,e){t.eventType==i.EVENT_END&&e.trigger(this.name,t)}},"object"==typeof module&&"object"==typeof module.exports?module.exports=i:(t.Hammer=i,"function"==typeof t.define&&t.define.amd&&t.define("hammer",[],function(){return i}))})(this),function(t,e){"use strict";t!==e&&(Hammer.event.bindDom=function(n,i,r){t(n).on(i,function(t){var n=t.originalEvent||t;n.pageX===e&&(n.pageX=t.pageX,n.pageY=t.pageY),n.target||(n.target=t.target),n.which===e&&(n.which=n.button),n.preventDefault||(n.preventDefault=t.preventDefault),n.stopPropagation||(n.stopPropagation=t.stopPropagation),r.call(this,n)})},Hammer.Instance.prototype.on=function(e,n){return t(this.element).on(e,n)},Hammer.Instance.prototype.off=function(e,n){return t(this.element).off(e,n)},Hammer.Instance.prototype.trigger=function(e,n){var i=t(this.element);return i.has(n.target).length&&(i=t(n.target)),i.trigger({type:e,gesture:n})},t.fn.hammer=function(e){return this.each(function(){var n=t(this),i=n.data("hammer");i?i&&e&&Hammer.utils.extend(i.options,e):n.data("hammer",new Hammer(this,e||{}))})})}(window.jQuery||window.Zepto);
@@ -0,0 +1,3 @@
1
+ /* custom Modernizr build used on WDL production */
2
+ /* js flexbox flexboxlegacy canvas no-touch history rgba csstransforms fontface video audio localstorage fullscreen */
3
+ window.Modernizr=function(window,document,undefined){var version="2.6.2",Modernizr={},enableClasses=true,docElement=document.documentElement,mod="modernizr",modElem=document.createElement(mod),mStyle=modElem.style,inputElem=document.createElement("input"),smile=":)",toString={}.toString,prefixes=" -webkit- -moz- -o- -ms- ".split(" "),omPrefixes="Webkit Moz O ms",cssomPrefixes=omPrefixes.split(" "),domPrefixes=omPrefixes.toLowerCase().split(" "),tests={},inputs={},attrs={},classes=[],slice=classes.slice,featureName,injectElementWithStyles=function(rule,callback,nodes,testnames){var style,ret,node,docOverflow,div=document.createElement("div"),body=document.body,fakeBody=body||document.createElement("body");if(parseInt(nodes,10)){while(nodes--){node=document.createElement("div");node.id=testnames?testnames[nodes]:mod+(nodes+1);div.appendChild(node)}}style=["&#173;",'<style id="s',mod,'">',rule,"</style>"].join("");div.id=mod;(body?div:fakeBody).innerHTML+=style;fakeBody.appendChild(div);if(!body){fakeBody.style.background="";fakeBody.style.overflow="hidden";docOverflow=docElement.style.overflow;docElement.style.overflow="hidden";docElement.appendChild(fakeBody)}ret=callback(div,rule);if(!body){fakeBody.parentNode.removeChild(fakeBody);docElement.style.overflow=docOverflow}else{div.parentNode.removeChild(div)}return!!ret},_hasOwnProperty={}.hasOwnProperty,hasOwnProp;if(!is(_hasOwnProperty,"undefined")&&!is(_hasOwnProperty.call,"undefined")){hasOwnProp=function(object,property){return _hasOwnProperty.call(object,property)}}else{hasOwnProp=function(object,property){return property in object&&is(object.constructor.prototype[property],"undefined")}}if(!Function.prototype.bind){Function.prototype.bind=function bind(that){var target=this;if(typeof target!="function"){throw new TypeError}var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var F=function(){};F.prototype=target.prototype;var self=new F;var result=target.apply(self,args.concat(slice.call(arguments)));if(Object(result)===result){return result}return self}else{return target.apply(that,args.concat(slice.call(arguments)))}};return bound}}function setCss(str){mStyle.cssText=str}function setCssAll(str1,str2){return setCss(prefixes.join(str1+";")+(str2||""))}function is(obj,type){return typeof obj===type}function contains(str,substr){return!!~(""+str).indexOf(substr)}function testProps(props,prefixed){for(var i in props){var prop=props[i];if(!contains(prop,"-")&&mStyle[prop]!==undefined){return prefixed=="pfx"?prop:true}}return false}function testDOMProps(props,obj,elem){for(var i in props){var item=obj[props[i]];if(item!==undefined){if(elem===false)return props[i];if(is(item,"function")){return item.bind(elem||obj)}return item}}return false}function testPropsAll(prop,prefixed,elem){var ucProp=prop.charAt(0).toUpperCase()+prop.slice(1),props=(prop+" "+cssomPrefixes.join(ucProp+" ")+ucProp).split(" ");if(is(prefixed,"string")||is(prefixed,"undefined")){return testProps(props,prefixed)}else{props=(prop+" "+domPrefixes.join(ucProp+" ")+ucProp).split(" ");return testDOMProps(props,prefixed,elem)}}tests["flexbox"]=function(){return testPropsAll("flexWrap")};tests["flexboxlegacy"]=function(){return testPropsAll("boxDirection")};tests["canvas"]=function(){var elem=document.createElement("canvas");return!!(elem.getContext&&elem.getContext("2d"))};tests["touch"]=function(){var bool;if("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch){bool=true}else{injectElementWithStyles(["@media (",prefixes.join("touch-enabled),("),mod,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(node){bool=node.offsetTop===9})}return bool};tests["history"]=function(){return!!(window.history&&history.pushState)};tests["rgba"]=function(){setCss("background-color:rgba(150,255,150,.5)");return contains(mStyle.backgroundColor,"rgba")};tests["csstransforms"]=function(){return!!testPropsAll("transform")};tests["fontface"]=function(){var bool;injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}',function(node,rule){var style=document.getElementById("smodernizr"),sheet=style.sheet||style.styleSheet,cssText=sheet?sheet.cssRules&&sheet.cssRules[0]?sheet.cssRules[0].cssText:sheet.cssText||"":"";bool=/src/i.test(cssText)&&cssText.indexOf(rule.split(" ")[0])===0});return bool};tests["video"]=function(){var elem=document.createElement("video"),bool=false;try{if(bool=!!elem.canPlayType){bool=new Boolean(bool);bool.ogg=elem.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,"");bool.h264=elem.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,"");bool.webm=elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}}catch(e){}return bool};tests["audio"]=function(){var elem=document.createElement("audio"),bool=false;try{if(bool=!!elem.canPlayType){bool=new Boolean(bool);bool.ogg=elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,"");bool.mp3=elem.canPlayType("audio/mpeg;").replace(/^no$/,"");bool.wav=elem.canPlayType('audio/wav; codecs="1"').replace(/^no$/,"");bool.m4a=(elem.canPlayType("audio/x-m4a;")||elem.canPlayType("audio/aac;")).replace(/^no$/,"")}}catch(e){}return bool};tests["localstorage"]=function(){try{localStorage.setItem(mod,mod);localStorage.removeItem(mod);return true}catch(e){return false}};function webforms(){Modernizr["input"]=function(props){for(var i=0,len=props.length;i<len;i++){attrs[props[i]]=!!(props[i]in inputElem)}if(attrs.list){attrs.list=!!(document.createElement("datalist")&&window.HTMLDataListElement)}return attrs}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" "));Modernizr["inputtypes"]=function(props){for(var i=0,bool,inputElemType,defaultView,len=props.length;i<len;i++){inputElem.setAttribute("type",inputElemType=props[i]);bool=inputElem.type!=="text";if(bool){inputElem.value=smile;inputElem.style.cssText="position:absolute;visibility:hidden;";if(/^range$/.test(inputElemType)&&inputElem.style.WebkitAppearance!==undefined){docElement.appendChild(inputElem);defaultView=document.defaultView;bool=defaultView.getComputedStyle&&defaultView.getComputedStyle(inputElem,null).WebkitAppearance!=="textfield"&&inputElem.offsetHeight!==0;docElement.removeChild(inputElem)}else if(/^(search|tel)$/.test(inputElemType)){}else if(/^(url|email)$/.test(inputElemType)){bool=inputElem.checkValidity&&inputElem.checkValidity()===false}else{bool=inputElem.value!=smile}}inputs[props[i]]=!!bool}return inputs}("search tel url email datetime date month week time datetime-local number range color".split(" "))}for(var feature in tests){if(hasOwnProp(tests,feature)){featureName=feature.toLowerCase();Modernizr[featureName]=tests[feature]();classes.push((Modernizr[featureName]?"":"no-")+featureName)}}Modernizr.input||webforms();Modernizr.addTest=function(feature,test){if(typeof feature=="object"){for(var key in feature){if(hasOwnProp(feature,key)){Modernizr.addTest(key,feature[key])}}}else{feature=feature.toLowerCase();if(Modernizr[feature]!==undefined){return Modernizr}test=typeof test=="function"?test():test;if(typeof enableClasses!=="undefined"&&enableClasses){docElement.className+=" "+(test?"":"no-")+feature}Modernizr[feature]=test}return Modernizr};setCss("");modElem=inputElem=null;(function(window,document){var options=window.html5||{};var reSkip=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;var saveClones=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;var supportsHtml5Styles;var expando="_html5shiv";var expanID=0;var expandoData={};var supportsUnknownElements;(function(){try{var a=document.createElement("a");a.innerHTML="<xyz></xyz>";supportsHtml5Styles="hidden"in a;supportsUnknownElements=a.childNodes.length==1||function(){document.createElement("a");var frag=document.createDocumentFragment();return typeof frag.cloneNode=="undefined"||typeof frag.createDocumentFragment=="undefined"||typeof frag.createElement=="undefined"}()}catch(e){supportsHtml5Styles=true;supportsUnknownElements=true}})();function addStyleSheet(ownerDocument,cssText){var p=ownerDocument.createElement("p"),parent=ownerDocument.getElementsByTagName("head")[0]||ownerDocument.documentElement;p.innerHTML="x<style>"+cssText+"</style>";return parent.insertBefore(p.lastChild,parent.firstChild)}function getElements(){var elements=html5.elements;return typeof elements=="string"?elements.split(" "):elements}function getExpandoData(ownerDocument){var data=expandoData[ownerDocument[expando]];if(!data){data={};expanID++;ownerDocument[expando]=expanID;expandoData[expanID]=data}return data}function createElement(nodeName,ownerDocument,data){if(!ownerDocument){ownerDocument=document}if(supportsUnknownElements){return ownerDocument.createElement(nodeName)}if(!data){data=getExpandoData(ownerDocument)}var node;if(data.cache[nodeName]){node=data.cache[nodeName].cloneNode()}else if(saveClones.test(nodeName)){node=(data.cache[nodeName]=data.createElem(nodeName)).cloneNode()}else{node=data.createElem(nodeName)}return node.canHaveChildren&&!reSkip.test(nodeName)?data.frag.appendChild(node):node}function createDocumentFragment(ownerDocument,data){if(!ownerDocument){ownerDocument=document}if(supportsUnknownElements){return ownerDocument.createDocumentFragment()}data=data||getExpandoData(ownerDocument);var clone=data.frag.cloneNode(),i=0,elems=getElements(),l=elems.length;for(;i<l;i++){clone.createElement(elems[i])}return clone}function shivMethods(ownerDocument,data){if(!data.cache){data.cache={};data.createElem=ownerDocument.createElement;data.createFrag=ownerDocument.createDocumentFragment;data.frag=data.createFrag()}ownerDocument.createElement=function(nodeName){if(!html5.shivMethods){return data.createElem(nodeName)}return createElement(nodeName,ownerDocument,data)};ownerDocument.createDocumentFragment=Function("h,f","return function(){"+"var n=f.cloneNode(),c=n.createElement;"+"h.shivMethods&&("+getElements().join().replace(/\w+/g,function(nodeName){data.createElem(nodeName);data.frag.createElement(nodeName);return'c("'+nodeName+'")'})+");return n}")(html5,data.frag)}function shivDocument(ownerDocument){if(!ownerDocument){ownerDocument=document}var data=getExpandoData(ownerDocument);if(html5.shivCSS&&!supportsHtml5Styles&&!data.hasCSS){data.hasCSS=!!addStyleSheet(ownerDocument,"article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}"+"mark{background:#FF0;color:#000}")}if(!supportsUnknownElements){shivMethods(ownerDocument,data)}return ownerDocument}var html5={elements:options.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:options.shivCSS!==false,supportsUnknownElements:supportsUnknownElements,shivMethods:options.shivMethods!==false,type:"default",shivDocument:shivDocument,createElement:createElement,createDocumentFragment:createDocumentFragment};window.html5=html5;shivDocument(document)})(this,document);Modernizr._version=version;Modernizr._prefixes=prefixes;Modernizr._domPrefixes=domPrefixes;Modernizr._cssomPrefixes=cssomPrefixes;Modernizr.testProp=function(prop){return testProps([prop])};Modernizr.testAllProps=testPropsAll;Modernizr.testStyles=injectElementWithStyles;docElement.className=docElement.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(enableClasses?" js "+classes.join(" "):"");return Modernizr}(this,this.document);(function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}})(this,document);Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};Modernizr.addTest("fullscreen",function(){for(var i=0;i<Modernizr._domPrefixes.length;i++){if(document[Modernizr._domPrefixes[i].toLowerCase()+"CancelFullScreen"])return true}return!!document["cancelFullScreen"]||false});
@@ -0,0 +1,33 @@
1
+ /* functions in the WDL namespace used by WDL-Viewer */
2
+ "undefined" == typeof WDL && (window.WDL = {}), WDL.ajaxRetry = function(e) {
3
+ "use strict";
4
+ return e.dataType = e.dataType || "json", e.tries = 0, e.timeout = e.timeout || 15e3, e.retryLimit = e.retryLimit || 3, e.error = function(e, t) {
5
+ (e.status >= 500 || "timeout" == t) && this.tries++ <= this.retryLimit && jQuery.ajax(this)
6
+ }, jQuery.ajax(e)
7
+ }, WDL.Search = (function () {
8
+ 'use strict';
9
+
10
+ function matchesTerm(haystack, needle) {
11
+ var key = haystack.toLocaleLowerCase();
12
+ return key.indexOf(needle.toLocaleLowerCase()) > -1;
13
+ }
14
+
15
+ function inTerms(a, b) {
16
+ for (var i = 0; i < b.length; i++) {
17
+ if (matchesTerm(a, b[i])) {
18
+ return true;
19
+ }
20
+ }
21
+ return false;
22
+ }
23
+
24
+ function formatPercentage(i) {
25
+ // Take a float between 0.0 and 1.0 a string percentage suitable for CSS:
26
+ return Math.round(100 * i).toString() + '%';
27
+ }
28
+
29
+ return {
30
+ inTerms: inTerms,
31
+ formatPercentage: formatPercentage
32
+ };
33
+ })();
@@ -0,0 +1,1147 @@
1
+ /*global navigator, window, document, Element, Modernizr, jQuery, Image, OpenSeadragon, WDL */
2
+ /* this is a modified version of the wdl-viewer JS */
3
+ /* https://github.com/LibraryOfCongress/wdl-viewer/src/js/wdl-viewer.js */
4
+ /* Thanks to Chris Adams (https://github.com/acdha) for help with adaptation */
5
+ /* all local changes are marked with: *** commonwealth changes *** */
6
+
7
+ (function ($) {
8
+ "use strict";
9
+ var $window = $(window),
10
+ placeholderImage = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
11
+
12
+ var gettext = window.gettext;
13
+ if (typeof(gettext) == "undefined") {
14
+ // intentionally does nothing but avoids breaking if JS I18N dict fails to load
15
+ gettext = function (i) { return i; };
16
+ }
17
+
18
+ function isFullScreen() {
19
+ return ((document.fullScreenElement && document.fullScreenElement !== null) ||
20
+ (!document.mozFullScreen && !document.webkitIsFullScreen));
21
+ }
22
+
23
+ function enterFullscreen() {
24
+ var doc = document.documentElement;
25
+ if (doc.requestFullscreen) {
26
+ doc.requestFullscreen();
27
+ } else if (doc.webkitRequestFullscreen) {
28
+ doc.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
29
+ } else if (doc.mozRequestFullScreen) {
30
+ doc.mozRequestFullScreen();
31
+ }
32
+ }
33
+
34
+ function leaveFullscreen() {
35
+ if (document.exitFullscreen) {
36
+ document.exitFullscreen();
37
+ } else if (document.cancelFullscreen) {
38
+ document.cancelFullscreen();
39
+ } else if (document.mozCancelFullScreen) {
40
+ document.mozCancelFullScreen();
41
+ } else if (document.webkitCancelFullScreen) {
42
+ document.webkitCancelFullScreen();
43
+ }
44
+ }
45
+
46
+ function toggleFullscreen() {
47
+ if (isFullScreen()) {
48
+ enterFullscreen();
49
+ } else {
50
+ leaveFullscreen();
51
+ }
52
+ }
53
+
54
+ $window.on("fullscreenchange mozfullscreenchange webkitfullscreenchange msfullscreenchange", function () {
55
+ $window.trigger("resize");
56
+ });
57
+
58
+ // TODO: Finish refactoring this out of being a jQuery plugin
59
+ $.fn.wdlViewer = function (config) {
60
+ return this.each(function View(idx, elm) {
61
+ return new ViewController(elm, config);
62
+ });
63
+ };
64
+
65
+ function ViewController(elm, config) {
66
+ var controller = this, // Convenience alias for event handlers…
67
+ $viewer = $(elm),
68
+ $header = $viewer.find("header"),
69
+ $footer = $viewer.find("footer"),
70
+ $help = $("#help"),
71
+ $pages = $("#pages"),
72
+ $grid = $('<div id="grid"></div>').hide().insertAfter($pages),
73
+ $seadragon = $('<div id="seadragon"></div>').hide().insertAfter($pages),
74
+ $groupControl = $("#group"),
75
+ $indexControl = $("#index");
76
+
77
+ // We still want to allow custom events and some jQuery convenience, so we'll expose these to views:
78
+ this.viewer = $viewer;
79
+ this.footer = $footer;
80
+ this.header = $header;
81
+
82
+ this.config = config;
83
+ this.rotation = config.viewportRotation || 0;
84
+ this.searchText = null; // *** commonwealth changes ***
85
+
86
+ config.placeholderSrc = config.placeholderSrc || placeholderImage;
87
+ // TODO: Adjust image max size based on the viewport
88
+ config.maxPageEdge = 1024;
89
+ config.maxThumbnailEdge = 256;
90
+
91
+ // These control the state of the overall View (pagination, search, etc.) but not the individual
92
+ // page displays:
93
+ this.currentGroup = parseInt($groupControl.val(), 10) || 1;
94
+ this.currentIndex = parseInt($indexControl.val(), 10) || 1;
95
+ this.maxIndex = config.pageGroups[this.currentGroup] || 1;
96
+
97
+ // Hide the group selection button if we only have one item:
98
+ if ($groupControl.children().length < 2) {
99
+ $groupControl.parent().hide();
100
+ }
101
+
102
+ if ($.isFunction(config.imageUrlTemplate)) {
103
+ this.generateImageUrl = config.imageUrlTemplate;
104
+ }
105
+
106
+ if ($.isFunction(config.pageUrlTemplate)) {
107
+ this.generatePageUrl = config.pageUrlTemplate;
108
+ }
109
+
110
+ if ($.isFunction(config.dziUrlTemplate)) {
111
+ this.generateDziUrl = config.dziUrlTemplate;
112
+ }
113
+
114
+ /* *** commonwealth changes *** */
115
+ if ($.isFunction(config.thumbUrlTemplate)) {
116
+ this.generateThumbUrl = config.thumbUrlTemplate;
117
+ }
118
+ if ($.isFunction(config.wordCoordinatesUrlTemplate)) {
119
+ this.generateWordCoordinatesUrl = config.wordCoordinatesUrlTemplate;
120
+ }
121
+
122
+ this.pageView = new PageView(this, $pages, config);
123
+
124
+ if (config.dziUrlTemplate) {
125
+ this.seadragonView = new SeadragonView(this, $seadragon, config);
126
+ }
127
+
128
+ this.gridView = new GridView(this, $grid, config);
129
+ this.activeView = this.pageView;
130
+
131
+ /* *** commonwealth changes *** */
132
+ /* add classes for bootstrap and font-awesome */
133
+ // Add toolbar features which only work with JavaScript:
134
+ if (this.seadragonView) {
135
+ $('<button id="toggle-seadragon" class="btn btn-link" type="button"><i class="fa fa-plus"></i></button>')
136
+ .attr("title","Zoom")
137
+ .appendTo("footer .toolbar .controls")
138
+ .on("click", $.proxy(function () {
139
+ if ((this.activeView == this.seadragonView) || (this.activeView == this.gridView)) {
140
+ this.openPageView();
141
+ } else {
142
+ this.openSeadragonView();
143
+ }
144
+ }, this));
145
+ }
146
+
147
+ if (Modernizr.canvas || Modernizr.csstransforms) {
148
+ $('<button id="rotate-left" class="requires-rotation btn btn-link" type="button"><i class="fa fa-undo"></i></button>')
149
+ // .text(gettext("Rotate Left"))
150
+ .attr("title","Rotate Left")
151
+ .appendTo("footer .toolbar .controls")
152
+ .on("click", $.proxy(function () {
153
+ this.rotate(true);
154
+ }, this));
155
+
156
+ $('<button id="rotate-right" class="requires-rotation btn btn-link" type="button"><i class="fa fa-repeat"></i></button>')
157
+ //.text(gettext("Rotate Right"))
158
+ .attr("title","Rotate Right")
159
+ .appendTo("footer .toolbar .controls")
160
+ .on("click", $.proxy(function () {
161
+ this.rotate();
162
+ }, this));
163
+ }
164
+
165
+ $('<button id="toggle-grid" class="btn btn-link" type="button"><i class="fa fa-th-large"></i></button>')
166
+ .attr("title","Page List")
167
+ .appendTo("footer .toolbar .controls")
168
+ .on("click", $.proxy(function () {
169
+ if (this.activeView == this.gridView) {
170
+ this.openPageView();
171
+ } else {
172
+ this.openGridView();
173
+ }
174
+ }, this));
175
+
176
+ if ($("html").hasClass("fullscreen")) {
177
+ $('<button id="toggle-fullscreen" class="btn btn-link" type="button"><i class="fa fa-expand"></i></button>')
178
+ .attr("title","Full Screen")
179
+ .appendTo("footer .toolbar .controls")
180
+ .on("click", function () {
181
+ toggleFullscreen();
182
+ });
183
+ }
184
+
185
+ $('<button id="toggle-help" class="btn btn-link" type="button"><i class="fa fa-question"></i></button>')
186
+ .attr("title","Help")
187
+ .appendTo("footer .toolbar .controls")
188
+ .on("click", function () {
189
+ $("#help").toggle();
190
+ });
191
+
192
+ /* ***commonwealth changes (search add)*** */
193
+ if (config.fts) {
194
+ // IE8 doesn't support some methods used in jquery-deparam
195
+ var q = decodeURIComponent(document.location.search.split('ocr_q=')[1]); // $.deparam(document.location.search)['?ocr_q']
196
+
197
+ if (q && (q != 'undefined')) {
198
+ controller.searchText = this.setSearchText(q);
199
+ }
200
+
201
+ var $searchToggle = $('<a id="toggle-search" data-ajax-modal="trigger" class="btn btn-link"><i class="fa fa-search"></i></a>')
202
+ .attr("href", this.setSearchToggleHref())
203
+ .attr("title", "Search this work")
204
+ //.data("ajax_modal", "trigger") // not working!
205
+ .prependTo("footer .toolbar .controls");
206
+ }
207
+
208
+ $groupControl.on("change", function() {
209
+ controller.setGroup(parseInt($groupControl.val(), 10));
210
+ });
211
+
212
+ $indexControl.on("change", function() {
213
+ controller.setIndex(parseInt($indexControl.val(), 10));
214
+ });
215
+
216
+ $viewer.find("input.current-index").on("change", function() {
217
+ // This is actually less painful than trying to get <input type=number> to work cross-browser…
218
+ var val = parseInt(this.value, 10);
219
+ if (val == controller.currentIndex || isNaN(val) || val < 0 || val > controller.maxIndex) {
220
+ this.value = controller.currentIndex;
221
+ return false;
222
+ }
223
+
224
+ controller.setIndex(val);
225
+ });
226
+
227
+ $(document).on("keydown", $.proxy(function (evt) {
228
+ if ($help.is(':visible')) {
229
+ $help.hide();
230
+ return false;
231
+ }
232
+
233
+ // Allow views to override:
234
+ if (this.activeView.onKeydown) {
235
+ var res = this.activeView.onKeydown(evt);
236
+ if (typeof(res) != "undefined") {
237
+ return res;
238
+ }
239
+ }
240
+
241
+ if (evt.metaKey || evt.altKey) {
242
+ if (evt.which == 37 || evt.which == 39) {
243
+ this.rotate(evt.which == 37);
244
+ return false;
245
+ } else {
246
+ // Allow normal handling to avoid interfering with normal browser controls:
247
+ return true;
248
+ }
249
+ }
250
+
251
+ // Global state changes:
252
+ switch (evt.which) {
253
+ case 80: // p
254
+ $("#toggle-grid").trigger("click");
255
+ return false;
256
+ case 81: // q
257
+ $searchToggle.trigger("click");
258
+ return false;
259
+ case 191: // ?
260
+ $help.show();
261
+ return false;
262
+ case 90: // z
263
+ $("#toggle-seadragon").trigger("click");
264
+ return false;
265
+ case 70: // f
266
+ $("#toggle-fullscreen").trigger("click");
267
+ return false;
268
+ case 27: // esc
269
+ leaveFullscreen();
270
+ return false;
271
+ case 32: // Space bar
272
+ if (evt.shiftKey) {
273
+ this.goToPreviousPage();
274
+ } else {
275
+ this.goToNextPage();
276
+ }
277
+ return false;
278
+
279
+ case 74: // j
280
+ case 34: // Page Down
281
+ this.goToNextPage();
282
+ return false;
283
+
284
+ case 75: // k
285
+ case 33: // Page Up
286
+ this.goToPreviousPage();
287
+ return false;
288
+
289
+ case 37: // left arrow
290
+ this.goToPreviousPage();
291
+ return false;
292
+
293
+ case 39: // right arrow
294
+ this.goToNextPage();
295
+ return false;
296
+ }
297
+
298
+ // Fall through to normal browser default handling:
299
+ return true;
300
+ }, this));
301
+
302
+ $help.on("click", function () {
303
+ $help.hide();
304
+ });
305
+
306
+ $viewer.on("goto-next-page", $.proxy(this.goToNextPage, this));
307
+ $viewer.on("goto-previous-page", $.proxy(this.goToPreviousPage, this));
308
+
309
+ $viewer.on("goto-page", function (evt, newGroup, newIndex) {
310
+ controller.setGroup(parseInt(newGroup, 10), parseInt(newIndex, 10));
311
+ });
312
+
313
+ /* *** commonwealth addition *** */
314
+ $viewer.on("goto-page-search", function (evt, newGroup, newIndex, query) {
315
+ controller.searchText = controller.setSearchText(query);
316
+ $searchToggle.attr("href", controller.setSearchToggleHref());
317
+ controller.setGroup(parseInt(newGroup, 10), parseInt(newIndex, 10));
318
+ });
319
+
320
+ /*
321
+ We offer two convenience functions for event handlers which increment the current rotation as
322
+ well as a way to set the current rotation directly:
323
+ */
324
+ $viewer.on("rotate-left", function () {
325
+ controller.rotate(true);
326
+ });
327
+ $viewer.on("rotate-right", function () {
328
+ controller.rotate();
329
+ });
330
+ $viewer.on("set-rotation", function (evt, degrees) {
331
+ controller.setRotation(degrees);
332
+ });
333
+
334
+ $viewer.on("page-changed", $.proxy(function () {
335
+ $groupControl.val(this.currentGroup);
336
+ $indexControl.val(this.currentIndex);
337
+ $viewer.find('input.current-index').attr('max', this.maxIndex).val(this.currentIndex);
338
+ $viewer.find(".max-index").text(this.maxIndex);
339
+ $indexControl.attr("max", this.maxIndex);
340
+ }, this));
341
+
342
+ $viewer.on("prefetch-adjacent-pages", $.proxy(function () {
343
+ this.activeView.prefetch();
344
+ }, this));
345
+
346
+ $window.on("resize", $.proxy(function () {
347
+ this.activeView.onResize();
348
+ }, this));
349
+
350
+ $viewer.on("open-seadragon", $.proxy(function () { this.openSeadragonView(); }, this));
351
+
352
+ // For efficiency we'll expose a variable which event handlers can use to decide whether to make an
353
+ // expensive jQuery call:
354
+
355
+ var headerHidden = false;
356
+ $viewer.on("hide-header", function () {
357
+ if (!headerHidden) {
358
+ headerHidden = true;
359
+ $header.stop(true, true).slideUp();
360
+ }
361
+ });
362
+ $viewer.on("show-header", function () {
363
+ if (headerHidden) {
364
+ headerHidden = false;
365
+ $header.stop(true, true).slideDown();
366
+ }
367
+ });
368
+
369
+ var footerHidden = false;
370
+ $viewer.on("hide-footer", $.proxy(function () {
371
+ // Don't hide the footer when the seadragon view is active as there's no way to restore it
372
+ // without using keyboard shortcuts:
373
+ if (!footerHidden && (this.activeView != this.seadragonView)) {
374
+ footerHidden = true;
375
+ $footer.stop(true, true).slideUp();
376
+ }
377
+ }, this));
378
+
379
+ $viewer.on("show-footer", function () {
380
+ if (footerHidden) {
381
+ footerHidden = false;
382
+ $footer.stop(true, true).slideDown();
383
+ }
384
+ });
385
+
386
+ var headerHeight = $header.height();
387
+
388
+ $viewer.on("mousemove", function (evt) {
389
+ if (evt.pageY < headerHeight * 2) {
390
+ $viewer.trigger("show-header");
391
+ } else if (evt.pageY > headerHeight * 3) {
392
+ $viewer.trigger("hide-header");
393
+ }
394
+ });
395
+
396
+ $viewer.on("hide-chrome", function () {
397
+ $viewer.trigger("hide-header");
398
+ $viewer.trigger("hide-footer");
399
+ });
400
+
401
+ $viewer.on("show-chrome", function () {
402
+ $viewer.trigger("show-header");
403
+ $viewer.trigger("show-footer");
404
+ });
405
+
406
+ $viewer.on("toggle-chrome", function () {
407
+ if (headerHidden || footerHidden) {
408
+ $viewer.trigger("show-chrome");
409
+ } else {
410
+ $viewer.trigger("hide-chrome");
411
+ }
412
+ });
413
+
414
+ $viewer.on("page-changed", function () {
415
+ $viewer.trigger("hide-header");
416
+ });
417
+
418
+ if (config.initialView == "grid") {
419
+ this.openGridView();
420
+ } else if (config.initialView == "seadragon") {
421
+ this.openSeadragonView();
422
+ } else {
423
+ this.openPageView();
424
+ }
425
+
426
+ this.updateViewer();
427
+ }
428
+
429
+ ViewController.prototype = {
430
+ generatePageUrl: function (group, index) {
431
+ // commonwealth changes (search add)
432
+ var url = this.config.pageUrlTemplate.replace('{group}', group).replace('{index}', index);
433
+
434
+ if (this.searchText) {
435
+ return "?ocr_q=" + encodeURIComponent(this.searchText) + url
436
+ } else {
437
+ return url;
438
+ }
439
+ },
440
+ generateWordCoordinatesUrl: function (group, index) {
441
+ return this.config.wordCoordinatesUrlTemplate.replace('{group}', group).replace('{index}', index);
442
+ },
443
+ generateImageUrl: function (group, index, maxEdge) {
444
+ return this.config.imageUrlTemplate.replace(/\{([^}]+)\}/g, function(match, name) {
445
+ switch (name) {
446
+ case "group":
447
+ return group;
448
+ case "index":
449
+ return index;
450
+ case "height":
451
+ case "width":
452
+ return maxEdge;
453
+ }
454
+ });
455
+ },
456
+ generateDziUrl: function (group, index) {
457
+ return this.config.dziUrlTemplate.replace("{group}", group).replace("{index}", index);
458
+ },
459
+ setIndex: function (newIndex) {
460
+ if (newIndex < 1) {
461
+ newIndex = 1;
462
+ } else if (newIndex > this.maxIndex) {
463
+ newIndex = this.maxIndex;
464
+ }
465
+
466
+ if (newIndex == this.currentIndex) {
467
+ return;
468
+ }
469
+
470
+ this.currentIndex = newIndex;
471
+
472
+ this.updateViewer();
473
+ },
474
+ /* ***commonwealth changes*** */
475
+ generateThumbUrl: function (group, index) {
476
+ return this.config.thumbUrlTemplate.replace('{group}', group).replace('{index}', index);
477
+ },
478
+ setGroup: function (newGroup, newIndex) {
479
+ if (newGroup == this.currentGroup && (!newIndex || newIndex == this.currentIndex)) {
480
+ return;
481
+ }
482
+
483
+ this.currentGroup = newGroup;
484
+ this.currentIndex = !!newIndex ? newIndex : 1;
485
+ this.maxIndex = this.config.pageGroups[newGroup];
486
+
487
+ this.updateViewer();
488
+ },
489
+ updateViewer: function () {
490
+ // Update next / previous links:
491
+ if (this.currentIndex < this.maxIndex) {
492
+ $(".toolbar .page.next")
493
+ .removeClass("disabled")
494
+ .attr("href", this.generatePageUrl(this.currentGroup, this.currentIndex + 1));
495
+ } else {
496
+ $(".toolbar .page.next")
497
+ .addClass("disabled")
498
+ .removeAttr("href");
499
+ }
500
+
501
+ if (this.currentIndex > 1) {
502
+ $(".toolbar .page.previous")
503
+ .removeClass("disabled")
504
+ .attr("href", this.generatePageUrl(this.currentGroup, this.currentIndex - 1));
505
+ } else {
506
+ $(".toolbar .page.previous")
507
+ .addClass("disabled")
508
+ .removeAttr("href");
509
+ }
510
+
511
+ this.viewer.data({group: this.currentGroup, index: this.currentIndex});
512
+
513
+ window.history.replaceState(
514
+ {
515
+ group: this.currentGroup,
516
+ index: this.currentIndex
517
+ },
518
+ "Page " + this.currentIndex,
519
+ this.generatePageUrl(this.currentGroup, this.currentIndex)
520
+ );
521
+ this.activeView.update();
522
+ this.viewer.trigger("page-changed");
523
+ this.activeView.prefetch();
524
+ },
525
+ goToNextPage: function () {
526
+ var step = this.activeView.getPageCount(),
527
+ delta = this.maxIndex - this.currentIndex;
528
+
529
+ if (delta > 0) {
530
+ this.setIndex(this.currentIndex + step);
531
+ } else {
532
+ // In case chrome is hidden, display the nav so the user can see they're on the last page:
533
+ this.viewer.trigger("show-chrome");
534
+ }
535
+ },
536
+ goToPreviousPage: function () {
537
+ var step = this.activeView.getPageCount();
538
+
539
+ if (this.currentIndex > 1) {
540
+ this.setIndex(this.currentIndex - step);
541
+ } else {
542
+ // In case chrome is hidden, display the nav so the user can see they're on the first page:
543
+ this.viewer.trigger("show-chrome");
544
+ }
545
+ },
546
+ openPageView: function () {
547
+ if (this.activeView == this.pageView) {
548
+ return;
549
+ } else if (this.activeView) {
550
+ this.activeView.hide();
551
+ }
552
+
553
+ this.activeView = this.pageView;
554
+ this.pageView.show();
555
+ this.viewer.attr("data-active-view", "page").trigger("show-footer");
556
+ },
557
+ openGridView: function () {
558
+ if (this.activeView == this.gridView) {
559
+ return;
560
+ } else if (this.activeView) {
561
+ this.activeView.hide();
562
+ }
563
+ this.activeView = this.gridView;
564
+ this.activeView.show();
565
+ this.viewer.attr("data-active-view", "grid"); // *** commonwealth changes *** .trigger("hide-footer")
566
+ },
567
+ openSeadragonView: function () {
568
+ if (!this.seadragonView || this.activeView == this.seadragonView) {
569
+ return;
570
+ } else if (this.activeView) {
571
+ this.activeView.hide();
572
+ }
573
+
574
+ this.activeView = this.seadragonView;
575
+ this.activeView.show();
576
+ this.viewer.attr("data-active-view", "seadragon").trigger("show-footer");
577
+ },
578
+ rotate: function (reverse) {
579
+ this.setRotation(this.rotation + (reverse ? -90 : 90));
580
+ },
581
+ setRotation: function (degrees) {
582
+ this.rotation = degrees;
583
+ if (this.activeView && this.activeView.setRotation) {
584
+ this.activeView.setRotation(this.rotation);
585
+ }
586
+ },
587
+ /* *** commonwealth changes (search add) -- setSearchText preps ocr_q params for search *** */
588
+ setSearchText: function (text) {
589
+ return decodeURIComponent($.trim(text));
590
+ },
591
+ /* *** commonwealth changes (search add) -- setSearchToggleHref sets target of search control link *** */
592
+ setSearchToggleHref: function () {
593
+ return this.searchText ? this.config.ocrSearchPath + '?ocr_q=' + this.searchText : this.config.ocrSearchPath;
594
+ }
595
+ };
596
+
597
+ function PageView(controller, $container, config) {
598
+ this.controller = controller;
599
+ this.config = config;
600
+
601
+ var $pages = $("#pages"),
602
+ $currentPage = $pages.find(".current img").first(),
603
+ $nextPage = $('<img>'),
604
+ previousImages = [new Image(), new Image(), new Image()],
605
+ nextImages = [new Image(), new Image(), new Image()];
606
+
607
+ $currentPage.parent().clone().empty().removeClass("current").addClass("next")
608
+ .appendTo($pages)
609
+ .append($nextPage);
610
+
611
+ this.hide = function () {
612
+ $container.hide();
613
+ };
614
+
615
+ /* *** commonwealth changes *** */
616
+ this.show = function () {
617
+ var seadragon_toggle = $("#toggle-seadragon");
618
+ seadragon_toggle.attr("title","Zoom");
619
+ seadragon_toggle.find("i").attr("class", "fa fa-plus");
620
+
621
+ $container.show();
622
+ this.update();
623
+ };
624
+
625
+ this.setRotation = function (degrees) {
626
+ // We set this explicitly here rather
627
+ $pages.css({
628
+ '-webkit-transform': 'rotate(' + degrees + 'deg)',
629
+ '-ms-transform': 'rotate(' + degrees + 'deg)',
630
+ 'transform': 'rotate(' + degrees + 'deg)'
631
+ });
632
+
633
+ this.checkViewportConstraints();
634
+ };
635
+
636
+ this.getPageCount = function () {
637
+ return $pages.find("img:visible").length;
638
+ };
639
+
640
+ this.update = function() {
641
+ // Cycle the sources to avoid issues with the load event not firing on cache hits:
642
+ var newSrc = controller.generateImageUrl(controller.currentGroup, controller.currentIndex,
643
+ config.maxPageEdge);
644
+ if (newSrc != $currentPage.attr("src")) {
645
+ $pages.find("img").fadeTo(200, 0.3);
646
+ $currentPage.attr("src", newSrc);
647
+ }
648
+
649
+ /*
650
+ We'll set our own dirty flag because we can't rely on the HTML5 img.complete property
651
+ when an error occurs while loading an image:
652
+
653
+ https://bugs.webkit.org/show_bug.cgi?id=28832
654
+ https://bugzilla.mozilla.org/show_bug.cgi?id=513541
655
+ */
656
+ $nextPage.hide()
657
+ .attr("src", this.config.placeholderSrc)
658
+ .data("dirty", true);
659
+
660
+ if ((controller.maxIndex - controller.currentIndex) > 0) {
661
+ $nextPage.attr("src", controller.generateImageUrl(controller.currentGroup,
662
+ controller.currentIndex + 1,
663
+ config.maxPageEdge));
664
+ } else {
665
+ $nextPage.hide();
666
+ }
667
+
668
+ this.setRotation(this.controller.rotation);
669
+ this.updateSearch();
670
+ };
671
+
672
+ this.checkViewportConstraints = function() {
673
+ if ($nextPage.data("dirty")) {
674
+ return;
675
+ }
676
+
677
+ var lastPage = ((this.controller.maxIndex - this.controller.currentIndex) < 1);
678
+
679
+ /* ***commonwealth changes*** */
680
+ var firstPage = (this.controller.currentIndex == 1);
681
+
682
+ var overflow = false;
683
+
684
+ // CSS transforms rotate display but not the DOM element's height/width:
685
+ if (this.controller.rotation % 180 === 0) {
686
+ overflow = ($nextPage.outerWidth() + $currentPage.outerWidth() + 20 >= $window.width());
687
+ } else {
688
+ overflow = ($nextPage.outerHeight() + $currentPage.outerHeight() + 20 >= $window.height());
689
+ }
690
+
691
+ /* ***commonwealth changes*** */
692
+ /* don't show $nextPage if viewing the first page */
693
+ /* (which is usually the jacket/cover, so this keeps gutter aligned properly) */
694
+ if (firstPage || lastPage || overflow) {
695
+ $nextPage.hide();
696
+ } else {
697
+ $nextPage.show()
698
+ .stop(true, false)
699
+ .fadeTo(200, 1.0);
700
+ }
701
+ };
702
+
703
+ this.onResize = function () {
704
+ return this.checkViewportConstraints();
705
+ };
706
+
707
+ this.prefetch = function () {
708
+ for (var i = 0; i < 3; i++) {
709
+ nextImages[i].src = controller.generateImageUrl(
710
+ controller.currentGroup,
711
+ Math.min(controller.maxIndex, controller.currentIndex + 1 + i),
712
+ config.maxPageEdge
713
+ );
714
+ }
715
+
716
+ for (i = 0; i < 3; i++) {
717
+ previousImages[i].src = controller.generateImageUrl(
718
+ controller.currentGroup,
719
+ Math.max(1, controller.currentIndex - (1 + 1)),
720
+ config.maxPageEdge
721
+ );
722
+ }
723
+ };
724
+
725
+ /* commonwealth changes (search add) */
726
+ this.updateSearch = function () {
727
+ if (!config.fts || !controller.searchText) { // !controller.search || !controller.search.query) {
728
+ return;
729
+ }
730
+
731
+ $pages.find(".highlighted").remove();
732
+
733
+ var terms = this.processTerms(controller.searchText); // controller.search.terms;
734
+
735
+ this.applySearchHighlighting(controller.currentGroup, controller.currentIndex, terms);
736
+ if (controller.currentIndex < controller.maxIndex) {
737
+ this.applySearchHighlighting(controller.currentGroup, controller.currentIndex + 1, terms);
738
+ }
739
+ };
740
+
741
+ this.applySearchHighlighting = function (group, index, terms) {
742
+ WDL.ajaxRetry({
743
+ url: controller.generateWordCoordinatesUrl(group, index, terms),
744
+ success: function (data) {
745
+ if (group != controller.currentGroup ||
746
+ (index != controller.currentIndex && index != controller.currentIndex + 1)) {
747
+ return;
748
+ }
749
+
750
+ var $page = index == controller.currentIndex ? $currentPage : $nextPage;
751
+
752
+ var master_height = data.height,
753
+ master_width = data.width;
754
+
755
+ $.each(data.words, function (k, v) {
756
+ if (!WDL.Search.inTerms(k, terms)) {
757
+ return;
758
+ }
759
+
760
+ // Response format is x1, y1, x2, y2
761
+ for (var i=0; i < v.length; i++) {
762
+ var coords = v[i];
763
+
764
+ $('<div class="highlighted">').css({
765
+ "left": WDL.Search.formatPercentage(coords[0] / master_width),
766
+ "top": WDL.Search.formatPercentage(Math.max(0, (coords[3] / master_height) - 0.01)),
767
+ "right": WDL.Search.formatPercentage(1.0 - coords[2] / master_width),
768
+ "bottom": WDL.Search.formatPercentage(1.0 - Math.min(1.0, (coords[1] / master_height) + 0.01))
769
+ }).insertAfter($page);
770
+ }
771
+ });
772
+ }
773
+ });
774
+ };
775
+
776
+ /* commonwealth changes (search add) - taken from WDL.Search */
777
+ this.processTerms = function (text) {
778
+ var terms = [text];
779
+ var mergeterms = $.merge(terms, $.map(terms[0].split(/\s/), function (i) {
780
+ return $.merge(i, $.map(i.split(/b/), $.trim));
781
+ }));
782
+
783
+ var terms_output = $.grep(mergeterms, function (i) {
784
+ return $.trim(i).length > 0;
785
+ });
786
+ return terms_output;
787
+ };
788
+
789
+ $currentPage.on("load", $.proxy(function () {
790
+ $currentPage.stop(true, false).fadeTo(100, 1.0);
791
+ $window.scrollTop(0);
792
+ this.checkViewportConstraints();
793
+ }, this));
794
+
795
+ $nextPage
796
+ .on("load", $.proxy(function () {
797
+ $nextPage.data("dirty", false);
798
+ this.checkViewportConstraints();
799
+ }, this))
800
+ .on("error", function () {
801
+ // TODO: Consider trying a reload?
802
+ $nextPage.data("dirty", false);
803
+ });
804
+ }
805
+
806
+ function SeadragonView(controller, $container) {
807
+ this.controller = controller;
808
+ this.seadragon = null;
809
+
810
+ this.getPageCount = function () {
811
+ return 1;
812
+ };
813
+
814
+ this.onResize = function () {
815
+ $container.css({
816
+ height: $window.height()
817
+ });
818
+ };
819
+
820
+ /* ***commonwealth changes** */
821
+ this.hide = function () {
822
+ // $("#toggle-seadragon").text(gettext("Zoom"));
823
+ var toggle = $("#toggle-seadragon");
824
+ toggle.attr("title","Zoom");
825
+ toggle.find("i").attr("class", "fa fa-plus");
826
+
827
+ if (this.seadragon) {
828
+ this.seadragon.close();
829
+ this.seadragon.destroy();
830
+ this.seadragon = null;
831
+ }
832
+
833
+ $container.hide();
834
+ $window.off("resize", this.onResize);
835
+ };
836
+
837
+ /* ***commonwealth changes** */
838
+ this.show = function () {
839
+ // $("#toggle-seadragon").text(gettext("Read"));
840
+ var toggle = $("#toggle-seadragon");
841
+ toggle.attr("title","Read");
842
+ toggle.find("i").attr("class", "fa fa-book");
843
+
844
+ if (this.seadragon) {
845
+ this.seadragon.close();
846
+ this.seadragon.destroy();
847
+ this.seadragon = null;
848
+ }
849
+
850
+ // We'll work around Internet Explorer < 11's broken height:100% calculation
851
+ // by displaying now to force the height to match the window:
852
+ $container.show();
853
+ this.onResize();
854
+ $window.on("resize", this.onResize);
855
+ this.update();
856
+ };
857
+
858
+ this.update = function () {
859
+ var dziUrl = this.controller.generateDziUrl(this.controller.currentGroup,
860
+ this.controller.currentIndex);
861
+
862
+ if (!this.seadragon) {
863
+ this.initializeSeadragon(dziUrl);
864
+ } else {
865
+ this.seadragon.open(dziUrl);
866
+ }
867
+ };
868
+
869
+ // TODO: find a better way to consolidate this with the page-turner implementation:
870
+
871
+ this.zoomIn = $.proxy(function () {
872
+ if (!this.seadragon.viewport) {
873
+ return; // IE8
874
+ }
875
+ this.seadragon.viewport.zoomBy(this.seadragon.zoomPerClick / 1.0);
876
+ }, this);
877
+
878
+ this.zoomOut = $.proxy(function () {
879
+ if (!this.seadragon.viewport) {
880
+ return; // IE8
881
+ }
882
+ this.seadragon.viewport.zoomBy(1.0 / this.seadragon.zoomPerClick);
883
+ }, this);
884
+
885
+ this.goHome = $.proxy(function () {
886
+ if (!this.seadragon.viewport) {
887
+ return; // IE8
888
+ }
889
+ this.seadragon.viewport.goHome();
890
+ }, this);
891
+
892
+ this.panViewport = $.proxy(function (direction) {
893
+ if (!this.seadragon.viewport) {
894
+ return; // IE8
895
+ }
896
+
897
+ var bounds = this.seadragon.viewport.getBounds();
898
+ var delta = new OpenSeadragon.Point();
899
+
900
+ switch (direction) {
901
+ case "down":
902
+ delta.y = bounds.height * 0.2;
903
+ break;
904
+ case "up":
905
+ delta.y = bounds.height * -0.2;
906
+ break;
907
+ case "left":
908
+ delta.x = bounds.width * -0.2;
909
+ break;
910
+ case "right":
911
+ delta.x = bounds.width * 0.2;
912
+ break;
913
+ }
914
+
915
+ this.seadragon.viewport.panBy(delta);
916
+ }, this);
917
+
918
+ this.setRotation = $.proxy(function (degrees) {
919
+ if (!this.seadragon || !this.seadragon.viewport) {
920
+ return;
921
+ }
922
+
923
+ // Until https://github.com/openseadragon/openseadragon/issues/194 lands we can't support
924
+ // arbitrary rotation:
925
+ this.seadragon.viewport.setRotation(degrees - (degrees % 90));
926
+ });
927
+
928
+ /* ***commonwealth changes*** */
929
+ this.initializeSeadragon = function (dziUrl) {
930
+ var seadragon = new OpenSeadragon({
931
+ id: $container.attr("id"),
932
+ prefixUrl: this.controller.config.seadragonPrefixUrl,
933
+ navImages: this.controller.config.seadragonNavImages,
934
+ tileSources: dziUrl,
935
+ autoHideControls: false,
936
+ immediateRender: navigator.userAgent.match(/mobile/i),
937
+ showNavigator: true,
938
+ navigatorPosition: 'TOP_RIGHT',
939
+ showNavigationControl: true,
940
+ navigationControlAnchor: OpenSeadragon.ControlAnchor.BOTTOM_RIGHT,
941
+ showFullPageControl: false
942
+ });
943
+
944
+ this.seadragon = seadragon;
945
+
946
+ /* ***commonwealth changes*** prefer to use OpenSeadragon options to set controls */
947
+ /*
948
+ var controlAnchor,
949
+ controls = [
950
+ $("<a>").text(gettext("Zoom In")).addClass("control zoom-in").click(this.zoomIn),
951
+ $("<a>").text(gettext("Zoom Out")).addClass("control zoom-out").click(this.zoomOut),
952
+ $("<a>").text(gettext("Go Home")).addClass("control home").click(this.goHome)
953
+ ];
954
+
955
+ try {
956
+ controlAnchor = this.controller.config.openSeadragon.controlAnchor;
957
+ } catch (e) {
958
+ controlAnchor = OpenSeadragon.ControlAnchor.BOTTOM_RIGHT;
959
+ }
960
+
961
+ for (var i=0; i < controls.length; i++) {
962
+ seadragon.addControl(controls[i].get(0), {anchor: controlAnchor});
963
+ }
964
+ */
965
+ // Make UI transitions more obvious by zooming in when the viewer first loads:
966
+ var initialZoom = $.proxy(function () {
967
+ seadragon.removeHandler("open", initialZoom);
968
+ this.zoomIn();
969
+ }, this);
970
+ seadragon.addHandler("open", initialZoom);
971
+
972
+ seadragon.addHandler("open", $.proxy(function () {
973
+ this.setRotation(this.controller.rotation);
974
+ }, this));
975
+ };
976
+
977
+ this.onKeydown = function (evt) {
978
+ switch (evt.which) {
979
+ case 187: //
980
+ case 61: // for firefox
981
+ this.zoomIn();
982
+ return false;
983
+ case 189: // -
984
+ case 173: // - on Firefox
985
+ this.zoomOut();
986
+ return false;
987
+ case 72: // h
988
+ case 220: // \
989
+ this.goHome();
990
+ return false;
991
+ case 37: // Left Arrow: pan Left
992
+ this.panViewport('left');
993
+ return false;
994
+ case 39: // Right Arrow: pan Right
995
+ this.panViewport('right');
996
+ return false;
997
+ case 38: // Up Arrow: pan Up
998
+ this.panViewport('up');
999
+ return false;
1000
+ case 40: // Down Arrow: pan Down
1001
+ this.panViewport('down');
1002
+ return false;
1003
+ }
1004
+ };
1005
+
1006
+ this.prefetch = function () {};
1007
+ }
1008
+
1009
+ function GridView(controller, $container, config) {
1010
+ var thumbnailUrls = [],
1011
+ // Cache for performance in scroll handler:
1012
+ container = $container.get(0);
1013
+
1014
+ var gridScrollHandler = $.throttle(50, function () {
1015
+ var scrollTop = container.scrollTop,
1016
+ scrollBottom = scrollTop + container.offsetHeight,
1017
+ thumbnails;
1018
+
1019
+ if (container.querySelectorAll) {
1020
+ thumbnails = container.querySelectorAll(".placeholder");
1021
+ } else {
1022
+ thumbnails = container.children;
1023
+ }
1024
+
1025
+ for (var i = thumbnails.length - 1; i >= 0; i--){
1026
+ var thumb = thumbnails[i];
1027
+
1028
+ if ((thumb.offsetTop + thumb.offsetHeight) >= scrollTop && thumb.offsetTop <= scrollBottom) {
1029
+ var idx = thumb.id.replace(/^index-/, '');
1030
+ thumb.style.backgroundImage = "url(" + thumbnailUrls[idx] + ")";
1031
+ thumb.className = thumb.className.replace('placeholder', '');
1032
+ }
1033
+ }
1034
+ });
1035
+
1036
+ /* *** commonwealth changes *** */
1037
+ this.show = function () {
1038
+ var seadragon_toggle = $("#toggle-seadragon");
1039
+ seadragon_toggle.attr("title","Read");
1040
+ seadragon_toggle.find("i").attr("class", "fa fa-book");
1041
+
1042
+ var container = $container.empty().get(0);
1043
+
1044
+ for (var i=1; i <= controller.maxIndex; i++) {
1045
+ var div = document.createElement("div");
1046
+ div.id = "index-" + i;
1047
+ div.className = "placeholder";
1048
+ div.appendChild(document.createTextNode(i));
1049
+ thumbnailUrls[i] = controller.generateThumbUrl(controller.currentGroup,
1050
+ i);
1051
+ div.style.backgroundImage = "url(" + config.placeholderSrc + ")";
1052
+ container.appendChild(div);
1053
+ }
1054
+
1055
+ $container.show();
1056
+ this.update();
1057
+ };
1058
+
1059
+ this.update = function () {
1060
+ var $pages = $container.scrollTop(0).children("div"),
1061
+ // Note switch from page number to zero-based index:
1062
+ $currentPage = $pages.eq(controller.currentIndex - 1);
1063
+
1064
+ /* jshint -W101 */
1065
+ $container.scrollTop($currentPage.offset().top - ($window.height() / 2) + ($currentPage.height() / 2));
1066
+ /* jshint +W101 */
1067
+
1068
+ $pages.not($currentPage).filter(".current").removeClass("current");
1069
+ $currentPage.addClass("current");
1070
+
1071
+ $container.on("scroll", gridScrollHandler);
1072
+
1073
+ $container.trigger("scroll");
1074
+
1075
+ // this.updateSearch(); // not showing search results in grid view for now
1076
+ };
1077
+
1078
+ // not showing search results in grid view for now
1079
+ /*
1080
+ this.updateSearch = function () {
1081
+ if (!config.fts || !controller.search || !controller.search.query) {
1082
+ return;
1083
+ }
1084
+
1085
+ var $pages = $container.children();
1086
+
1087
+ $pages.filter(".hit").removeClass("hit");
1088
+
1089
+ var results = controller.search.results;
1090
+ for (var i = 0; i < results.length; i++) {
1091
+ var result = results[i];
1092
+ if (result[0] == controller.currentGroup) {
1093
+ // Note conversion from page numbers to zero-based index:
1094
+ $pages.eq(result[1] - 1).addClass("hit");
1095
+ }
1096
+ }
1097
+ };
1098
+ */
1099
+
1100
+ this.hide = function () {
1101
+ $container.off("scroll", gridScrollHandler);
1102
+ $container.hide().empty();
1103
+ };
1104
+
1105
+ this.onResize = function () {
1106
+ gridScrollHandler();
1107
+ };
1108
+
1109
+ function scrollDown() {
1110
+ $container.scrollTop($container.scrollTop() + $window.height() / 2);
1111
+ }
1112
+
1113
+ function scrollUp() {
1114
+ $container.scrollTop($container.scrollTop() - $window.height() / 2);
1115
+ }
1116
+
1117
+ this.onKeydown = function (evt) {
1118
+ switch (evt.which) {
1119
+ case 32: // Space bar
1120
+ if (evt.shiftKey) {
1121
+ scrollUp();
1122
+ } else {
1123
+ scrollDown();
1124
+ }
1125
+ return false;
1126
+ case 74: // j
1127
+ case 34: // Page Down
1128
+ scrollDown();
1129
+ return false;
1130
+ case 75: // k
1131
+ case 33: // Page Up
1132
+ scrollUp();
1133
+ return false;
1134
+ }
1135
+ };
1136
+
1137
+ this.prefetch = function () {};
1138
+
1139
+ $container.on("click", "div", function () {
1140
+ var newPage = this.id.match(/^index-(\d+)/);
1141
+ if (newPage) {
1142
+ controller.openPageView();
1143
+ controller.setIndex(parseInt(newPage[1], 10));
1144
+ }
1145
+ });
1146
+ }
1147
+ }(jQuery));