commonwealth-vlr-engine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (361) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +91 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +20 -0
  5. data/LICENSE +202 -0
  6. data/README.md +38 -0
  7. data/Rakefile +43 -0
  8. data/app/assets/images/commonwealth-vlr-engine/bplLoginButton.png +0 -0
  9. data/app/assets/images/commonwealth-vlr-engine/dc_audio-icon.png +0 -0
  10. data/app/assets/images/commonwealth-vlr-engine/dc_collection-icon.png +0 -0
  11. data/app/assets/images/commonwealth-vlr-engine/dc_image-icon.png +0 -0
  12. data/app/assets/images/commonwealth-vlr-engine/dc_institution-icon.png +0 -0
  13. data/app/assets/images/commonwealth-vlr-engine/dc_moving-image-icon.png +0 -0
  14. data/app/assets/images/commonwealth-vlr-engine/dc_text-icon.png +0 -0
  15. data/app/assets/images/commonwealth-vlr-engine/facebookLoginButton.png +0 -0
  16. data/app/assets/images/commonwealth-vlr-engine/loading-wdl-grid.gif +0 -0
  17. data/app/assets/images/commonwealth-vlr-engine/loading-wdl.gif +0 -0
  18. data/app/assets/images/commonwealth-vlr-engine/loading.gif +0 -0
  19. data/app/assets/images/commonwealth-vlr-engine/openseadragon/fullpage_grouphover.png +0 -0
  20. data/app/assets/images/commonwealth-vlr-engine/openseadragon/fullpage_hover.png +0 -0
  21. data/app/assets/images/commonwealth-vlr-engine/openseadragon/fullpage_pressed.png +0 -0
  22. data/app/assets/images/commonwealth-vlr-engine/openseadragon/fullpage_rest.png +0 -0
  23. data/app/assets/images/commonwealth-vlr-engine/openseadragon/home_grouphover.png +0 -0
  24. data/app/assets/images/commonwealth-vlr-engine/openseadragon/home_hover.png +0 -0
  25. data/app/assets/images/commonwealth-vlr-engine/openseadragon/home_pressed.png +0 -0
  26. data/app/assets/images/commonwealth-vlr-engine/openseadragon/home_rest.png +0 -0
  27. data/app/assets/images/commonwealth-vlr-engine/openseadragon/next_grouphover.png +0 -0
  28. data/app/assets/images/commonwealth-vlr-engine/openseadragon/next_hover.png +0 -0
  29. data/app/assets/images/commonwealth-vlr-engine/openseadragon/next_pressed.png +0 -0
  30. data/app/assets/images/commonwealth-vlr-engine/openseadragon/next_rest.png +0 -0
  31. data/app/assets/images/commonwealth-vlr-engine/openseadragon/previous_grouphover.png +0 -0
  32. data/app/assets/images/commonwealth-vlr-engine/openseadragon/previous_hover.png +0 -0
  33. data/app/assets/images/commonwealth-vlr-engine/openseadragon/previous_pressed.png +0 -0
  34. data/app/assets/images/commonwealth-vlr-engine/openseadragon/previous_rest.png +0 -0
  35. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateleft_grouphover.png +0 -0
  36. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateleft_hover.png +0 -0
  37. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateleft_pressed.png +0 -0
  38. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateleft_rest.png +0 -0
  39. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateright_grouphover.png +0 -0
  40. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateright_hover.png +0 -0
  41. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateright_pressed.png +0 -0
  42. data/app/assets/images/commonwealth-vlr-engine/openseadragon/rotateright_rest.png +0 -0
  43. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomin_grouphover.png +0 -0
  44. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomin_hover.png +0 -0
  45. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomin_pressed.png +0 -0
  46. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomin_rest.png +0 -0
  47. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomout_grouphover.png +0 -0
  48. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomout_hover.png +0 -0
  49. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomout_pressed.png +0 -0
  50. data/app/assets/images/commonwealth-vlr-engine/openseadragon/zoomout_rest.png +0 -0
  51. data/app/assets/images/commonwealth-vlr-engine/vlr_logo_img.png +0 -0
  52. data/app/assets/javascripts/blacklight_gallery.js +1 -0
  53. data/app/assets/javascripts/blacklight_google_analytics/blacklight_google_analytics.js.erb +165 -0
  54. data/app/assets/javascripts/bootstrap-accessibility-plugin/bootstrap-accessibility.js +586 -0
  55. data/app/assets/javascripts/commonwealth-vlr-engine.js +22 -0
  56. data/app/assets/javascripts/commonwealth-vlr-engine/collection_facets.js +5 -0
  57. data/app/assets/javascripts/commonwealth-vlr-engine/disable_dropdown_nav.js +21 -0
  58. data/app/assets/javascripts/commonwealth-vlr-engine/feedback_alerts.js.erb +19 -0
  59. data/app/assets/javascripts/commonwealth-vlr-engine/folder_tools.js +26 -0
  60. data/app/assets/javascripts/commonwealth-vlr-engine/multi_img_viewer.js.erb +20 -0
  61. data/app/assets/javascripts/commonwealth-vlr-engine/ocr_search_utils.js.erb +32 -0
  62. data/app/assets/javascripts/commonwealth-vlr-engine/volumes_list.js +5 -0
  63. data/app/assets/javascripts/openseadragon.js +2 -0
  64. data/app/assets/javascripts/respond/respond.min.js +6 -0
  65. data/app/assets/javascripts/wdl-viewer/fd-slider.js +1303 -0
  66. data/app/assets/javascripts/wdl-viewer/jquery-deparam.js +113 -0
  67. data/app/assets/javascripts/wdl-viewer/jquery.ba-throttle-debounce.min.js +9 -0
  68. data/app/assets/javascripts/wdl-viewer/jquery.hammer.min.js +7 -0
  69. data/app/assets/javascripts/wdl-viewer/modernizr-wdl.min.js +3 -0
  70. data/app/assets/javascripts/wdl-viewer/wdl-search.js +33 -0
  71. data/app/assets/javascripts/wdl-viewer/wdl-viewer_commonwealth.js +1147 -0
  72. data/app/assets/stylesheets/blacklight_advanced_search.css +5 -0
  73. data/app/assets/stylesheets/blacklight_gallery.css +1 -0
  74. data/app/assets/stylesheets/blacklight_maps.css +1 -0
  75. data/app/assets/stylesheets/bootstrap-accessibility-plugin/bootstrap-accessibility.css +105 -0
  76. data/app/assets/stylesheets/commonwealth-vlr-engine/advanced_search.scss +139 -0
  77. data/app/assets/stylesheets/commonwealth-vlr-engine/basic_search.scss +47 -0
  78. data/app/assets/stylesheets/commonwealth-vlr-engine/book_viewer.scss +576 -0
  79. data/app/assets/stylesheets/commonwealth-vlr-engine/carousel.scss +94 -0
  80. data/app/assets/stylesheets/commonwealth-vlr-engine/cmmnwlth_defaults.scss +45 -0
  81. data/app/assets/stylesheets/commonwealth-vlr-engine/cmmnwlth_shared.scss +75 -0
  82. data/app/assets/stylesheets/commonwealth-vlr-engine/collections.scss +563 -0
  83. data/app/assets/stylesheets/commonwealth-vlr-engine/commonwealth-vlr-engine.css +32 -0
  84. data/app/assets/stylesheets/commonwealth-vlr-engine/facets.scss +111 -0
  85. data/app/assets/stylesheets/commonwealth-vlr-engine/feedback.scss +10 -0
  86. data/app/assets/stylesheets/commonwealth-vlr-engine/folders.scss +276 -0
  87. data/app/assets/stylesheets/commonwealth-vlr-engine/footer.scss +47 -0
  88. data/app/assets/stylesheets/commonwealth-vlr-engine/header.scss +329 -0
  89. data/app/assets/stylesheets/commonwealth-vlr-engine/home.scss +269 -0
  90. data/app/assets/stylesheets/commonwealth-vlr-engine/index.scss +580 -0
  91. data/app/assets/stylesheets/commonwealth-vlr-engine/institutions.scss +246 -0
  92. data/app/assets/stylesheets/commonwealth-vlr-engine/pages.scss +31 -0
  93. data/app/assets/stylesheets/commonwealth-vlr-engine/search_inside.scss +172 -0
  94. data/app/assets/stylesheets/commonwealth-vlr-engine/searches.scss +55 -0
  95. data/app/assets/stylesheets/commonwealth-vlr-engine/show.scss +840 -0
  96. data/app/assets/stylesheets/commonwealth-vlr-engine/signin.scss +43 -0
  97. data/app/assets/stylesheets/commonwealth-vlr-engine/users.scss +18 -0
  98. data/app/assets/stylesheets/commonwealth-vlr-engine/vlr_dependencies.css +8 -0
  99. data/app/assets/stylesheets/ie_fixes.css +16 -0
  100. data/app/assets/stylesheets/openseadragon.css +1 -0
  101. data/app/assets/stylesheets/wdl-viewer/fd-slider.min.css +2 -0
  102. data/app/controllers/blacklight_advanced_search/advanced_controller.rb +66 -0
  103. data/app/controllers/bookmarks_controller.rb +38 -0
  104. data/app/controllers/collections_controller.rb +128 -0
  105. data/app/controllers/commonwealth_vlr_engine/application_controller.rb +8 -0
  106. data/app/controllers/feedback_controller.rb +39 -0
  107. data/app/controllers/folder_items_actions_controller.rb +72 -0
  108. data/app/controllers/folder_items_controller.rb +90 -0
  109. data/app/controllers/folders_controller.rb +132 -0
  110. data/app/controllers/iiif_manifest_controller.rb +74 -0
  111. data/app/controllers/image_viewer_controller.rb +34 -0
  112. data/app/controllers/institutions_controller.rb +62 -0
  113. data/app/controllers/ocr_search_controller.rb +78 -0
  114. data/app/controllers/pages_controller.rb +5 -0
  115. data/app/controllers/users/omniauth_callbacks_controller.rb +10 -0
  116. data/app/controllers/users/registrations_controller.rb +3 -0
  117. data/app/controllers/users/sessions_controller.rb +3 -0
  118. data/app/controllers/users_controller.rb +27 -0
  119. data/app/helpers/blacklight_maps_helper.rb +3 -0
  120. data/app/helpers/collections_helper.rb +3 -0
  121. data/app/helpers/commonwealth_vlr_engine/application_helper.rb +200 -0
  122. data/app/helpers/commonwealth_vlr_engine/blacklight_helper.rb +35 -0
  123. data/app/helpers/commonwealth_vlr_engine/blacklight_url_helper.rb +53 -0
  124. data/app/helpers/commonwealth_vlr_engine/catalog_helper.rb +414 -0
  125. data/app/helpers/commonwealth_vlr_engine/collections_helper_behavior.rb +19 -0
  126. data/app/helpers/commonwealth_vlr_engine/component_helper.rb +22 -0
  127. data/app/helpers/commonwealth_vlr_engine/facets_helper.rb +20 -0
  128. data/app/helpers/commonwealth_vlr_engine/feedback_helper_behavior.rb +14 -0
  129. data/app/helpers/commonwealth_vlr_engine/folders_helper_behavior.rb +9 -0
  130. data/app/helpers/commonwealth_vlr_engine/image_viewer_helper_behavior.rb +14 -0
  131. data/app/helpers/commonwealth_vlr_engine/institutions_helper_behavior.rb +31 -0
  132. data/app/helpers/commonwealth_vlr_engine/layout_helper.rb +22 -0
  133. data/app/helpers/commonwealth_vlr_engine/ocr_search_helper_behavior.rb +48 -0
  134. data/app/helpers/commonwealth_vlr_engine/pages_helper_behavior.rb +38 -0
  135. data/app/helpers/commonwealth_vlr_engine/vlr_blacklight_maps_helper_behavior.rb +59 -0
  136. data/app/helpers/feedback_helper.rb +3 -0
  137. data/app/helpers/folders_helper.rb +3 -0
  138. data/app/helpers/image_viewer_helper.rb +3 -0
  139. data/app/helpers/institutions_helper.rb +3 -0
  140. data/app/helpers/ocr_search_helper.rb +3 -0
  141. data/app/helpers/pages_helper.rb +3 -0
  142. data/app/mailers/notifier.rb +5 -0
  143. data/app/models/carousel_slide.rb +7 -0
  144. data/app/models/record_mailer.rb +18 -0
  145. data/app/models/user.rb +15 -0
  146. data/app/views/advanced/_advanced_search_date.html.erb +23 -0
  147. data/app/views/advanced/_advanced_search_facets.html.erb +5 -0
  148. data/app/views/advanced/_advanced_search_fields.html.erb +39 -0
  149. data/app/views/advanced/_advanced_search_form.html.erb +51 -0
  150. data/app/views/advanced/_advanced_search_help.html.erb +13 -0
  151. data/app/views/advanced/_facet_layout.html.erb +9 -0
  152. data/app/views/advanced/_facet_limit.html.erb +15 -0
  153. data/app/views/advanced/index.html.erb +29 -0
  154. data/app/views/blacklight_advanced_search/_facet_limit.html.erb +12 -0
  155. data/app/views/bookmarks/_tools.html.erb +25 -0
  156. data/app/views/bookmarks/index.html.erb +64 -0
  157. data/app/views/bookmarks/update.js.erb +1 -0
  158. data/app/views/bpluser/folders/_folder.html.erb +36 -0
  159. data/app/views/catalog/_add_this.html.erb +10 -0
  160. data/app/views/catalog/_az_links.html.erb +15 -0
  161. data/app/views/catalog/_basic_search.html.erb +67 -0
  162. data/app/views/catalog/_citation.html.erb +50 -0
  163. data/app/views/catalog/_constraints.html.erb +26 -0
  164. data/app/views/catalog/_document_collections_gallery.html.erb +7 -0
  165. data/app/views/catalog/_facet_limit_series.html.erb +21 -0
  166. data/app/views/catalog/_facets.html.erb +31 -0
  167. data/app/views/catalog/_facets_series.html.erb +4 -0
  168. data/app/views/catalog/_folder_item_control.html.erb +64 -0
  169. data/app/views/catalog/_index_collections_gallery.html.erb +12 -0
  170. data/app/views/catalog/_index_gallery.html.erb +11 -0
  171. data/app/views/catalog/_index_header_default.html.erb +22 -0
  172. data/app/views/catalog/_index_list_collection.html.erb +33 -0
  173. data/app/views/catalog/_index_list_default.html.erb +13 -0
  174. data/app/views/catalog/_index_map_institutions.html.erb +10 -0
  175. data/app/views/catalog/_index_masonry.html.erb +8 -0
  176. data/app/views/catalog/_index_slideshow.html.erb +18 -0
  177. data/app/views/catalog/_more_like_this.html.erb +9 -0
  178. data/app/views/catalog/_opengraph.html.erb +16 -0
  179. data/app/views/catalog/_previous_next_doc.html.erb +22 -0
  180. data/app/views/catalog/_results_pagination.html.erb +9 -0
  181. data/app/views/catalog/_search_form.html.erb +23 -0
  182. data/app/views/catalog/_search_header.html.erb +5 -0
  183. data/app/views/catalog/_show_default.html.erb +75 -0
  184. data/app/views/catalog/_show_main_content.html.erb +27 -0
  185. data/app/views/catalog/_show_more_like_this.html.erb +15 -0
  186. data/app/views/catalog/_show_partials/_show_book_viewer_link.html.erb +25 -0
  187. data/app/views/catalog/_show_partials/_show_default_img.html.erb +32 -0
  188. data/app/views/catalog/_show_partials/_show_default_metadata.html.erb +486 -0
  189. data/app/views/catalog/_show_partials/_show_default_simple_img_viewer.html.erb +45 -0
  190. data/app/views/catalog/_show_partials/_show_downloads.html.erb +14 -0
  191. data/app/views/catalog/_show_partials/_show_flagged_notice.html.erb +29 -0
  192. data/app/views/catalog/_show_partials/_show_multi_img.html.erb +42 -0
  193. data/app/views/catalog/_show_partials/_show_multi_img_pagination.html.erb +20 -0
  194. data/app/views/catalog/_show_partials/_show_oai_item_img.html.erb +5 -0
  195. data/app/views/catalog/_show_partials/_show_oai_item_link.html.erb +8 -0
  196. data/app/views/catalog/_show_partials/_show_prev_next_carousel_links.html.erb +17 -0
  197. data/app/views/catalog/_show_partials/_show_volumes.html.erb +52 -0
  198. data/app/views/catalog/_show_sidebar.html.erb +1 -0
  199. data/app/views/catalog/_show_tools.html.erb +42 -0
  200. data/app/views/catalog/_zero_results.html.erb +20 -0
  201. data/app/views/catalog/email.html.erb +6 -0
  202. data/app/views/catalog/index.html.erb +17 -0
  203. data/app/views/catalog/metadata_view.html.erb +7 -0
  204. data/app/views/catalog/show.html.erb +13 -0
  205. data/app/views/collections/_search_form_collection.html.erb +23 -0
  206. data/app/views/collections/index.html.erb +30 -0
  207. data/app/views/collections/show.html.erb +116 -0
  208. data/app/views/devise/confirmations/new.html.erb +14 -0
  209. data/app/views/devise/mailer/reset_password_instructions.html.erb +13 -0
  210. data/app/views/devise/passwords/edit.html.erb +33 -0
  211. data/app/views/devise/passwords/new.html.erb +31 -0
  212. data/app/views/devise/registrations/edit.html.erb +83 -0
  213. data/app/views/devise/registrations/new.html.erb +53 -0
  214. data/app/views/devise/sessions/new.html.erb +75 -0
  215. data/app/views/devise/shared/_links.erb +29 -0
  216. data/app/views/feedback/complete.html.erb +9 -0
  217. data/app/views/feedback/show.html.erb +61 -0
  218. data/app/views/folder_items/create.js.erb +1 -0
  219. data/app/views/folder_items/destroy.js.erb +1 -0
  220. data/app/views/folder_items/item_actions.js.erb +2 -0
  221. data/app/views/folder_items/update.js.erb +1 -0
  222. data/app/views/folders/_in_folder.html.erb +2 -0
  223. data/app/views/folders/_new_edit_form_fields.html.erb +36 -0
  224. data/app/views/folders/edit.html.erb +25 -0
  225. data/app/views/folders/index.html.erb +73 -0
  226. data/app/views/folders/new.html.erb +27 -0
  227. data/app/views/folders/public_list.html.erb +44 -0
  228. data/app/views/folders/show.html.erb +98 -0
  229. data/app/views/image_viewer/_book_viewer_help.html.erb +125 -0
  230. data/app/views/image_viewer/_render_book_viewer.html.erb +185 -0
  231. data/app/views/image_viewer/book_viewer.html.erb +57 -0
  232. data/app/views/image_viewer/show.js.erb +19 -0
  233. data/app/views/institutions/_intro_text.html.erb +1 -0
  234. data/app/views/institutions/_map_institutions_search.html.erb +9 -0
  235. data/app/views/institutions/_search_form_institution.html.erb +24 -0
  236. data/app/views/institutions/index.html.erb +31 -0
  237. data/app/views/institutions/show.html.erb +104 -0
  238. data/app/views/layouts/_google_analytics.html.erb +9 -0
  239. data/app/views/layouts/book_viewer.html.erb +37 -0
  240. data/app/views/layouts/commonwealth-vlr-engine.html.erb +59 -0
  241. data/app/views/notifier/feedback.text.erb +6 -0
  242. data/app/views/ocr_search/_index_ocr_list.html.erb +17 -0
  243. data/app/views/ocr_search/_search_form_ocr.html.erb +23 -0
  244. data/app/views/ocr_search/_snippets_more.html.erb +15 -0
  245. data/app/views/ocr_search/_zero_results_ocr.html.erb +9 -0
  246. data/app/views/ocr_search/index.html.erb +49 -0
  247. data/app/views/pages/_carousel.html.erb +46 -0
  248. data/app/views/pages/_home_partials/_banner.html.erb +23 -0
  249. data/app/views/pages/_home_partials/_browse.html.erb +55 -0
  250. data/app/views/pages/_home_partials/_context.html.erb +24 -0
  251. data/app/views/pages/_home_partials/_home_content.html.erb +14 -0
  252. data/app/views/pages/about.html.erb +10 -0
  253. data/app/views/pages/about_site.html.erb +6 -0
  254. data/app/views/pages/explore.html.erb +32 -0
  255. data/app/views/pages/home.html.erb +3 -0
  256. data/app/views/record_mailer/email_record.text.erb +7 -0
  257. data/app/views/saved_searches/index.html.erb +60 -0
  258. data/app/views/search_history/index.html.erb +59 -0
  259. data/app/views/shared/_error_messages.html.erb +9 -0
  260. data/app/views/shared/_flash_msg_maintenance.html.erb +6 -0
  261. data/app/views/shared/_folder_item_actions.html.erb +66 -0
  262. data/app/views/shared/_folder_tools.html.erb +4 -0
  263. data/app/views/shared/_footer.html.erb +14 -0
  264. data/app/views/shared/_header_navbar.html.erb +34 -0
  265. data/app/views/shared/_nav_links.html.erb +58 -0
  266. data/app/views/shared/_search_form_header.html.erb +16 -0
  267. data/app/views/shared/_tools.html.erb +14 -0
  268. data/app/views/shared/_user_util_links.html.erb +43 -0
  269. data/app/views/users/show.html.erb +33 -0
  270. data/commonwealth-vlr-engine.gemspec +47 -0
  271. data/config/initializers/patch_blacklight_advanced_search.rb +74 -0
  272. data/config/initializers/patch_blacklight_maps.rb +20 -0
  273. data/config/jetty.yml +7 -0
  274. data/config/locales/commonwealth-vlr-engine.en.yml +463 -0
  275. data/config/routes.rb +92 -0
  276. data/lib/commonwealth-vlr-engine.rb +55 -0
  277. data/lib/commonwealth-vlr-engine/commonwealth_search_builder.rb +66 -0
  278. data/lib/commonwealth-vlr-engine/controller.rb +69 -0
  279. data/lib/commonwealth-vlr-engine/controller_override.rb +238 -0
  280. data/lib/commonwealth-vlr-engine/engine.rb +40 -0
  281. data/lib/commonwealth-vlr-engine/finder.rb +285 -0
  282. data/lib/commonwealth-vlr-engine/iiif_manifest.rb +189 -0
  283. data/lib/commonwealth-vlr-engine/notifier.rb +33 -0
  284. data/lib/commonwealth-vlr-engine/pages.rb +33 -0
  285. data/lib/commonwealth-vlr-engine/render_constraints_override.rb +57 -0
  286. data/lib/commonwealth-vlr-engine/route_sets.rb +49 -0
  287. data/lib/commonwealth-vlr-engine/routes.rb +21 -0
  288. data/lib/commonwealth-vlr-engine/version.rb +3 -0
  289. data/lib/generators/commonwealth_vlr_engine/controller_generator.rb +92 -0
  290. data/lib/generators/commonwealth_vlr_engine/environment_generator.rb +49 -0
  291. data/lib/generators/commonwealth_vlr_engine/install_generator.rb +57 -0
  292. data/lib/generators/commonwealth_vlr_engine/localassets_generator.rb +29 -0
  293. data/lib/generators/commonwealth_vlr_engine/model_generator.rb +65 -0
  294. data/lib/generators/commonwealth_vlr_engine/routes_generator.rb +39 -0
  295. data/lib/generators/commonwealth_vlr_engine/templates/commonwealth_vlr_engine.css.scss +4 -0
  296. data/lib/generators/commonwealth_vlr_engine/templates/config/contact_emails.yml.sample +13 -0
  297. data/lib/generators/commonwealth_vlr_engine/templates/config/fedora.yml.sample +6 -0
  298. data/lib/generators/commonwealth_vlr_engine/templates/config/geojson_static_file.yml.sample +11 -0
  299. data/lib/generators/commonwealth_vlr_engine/templates/config/google_analytics.yml.sample +10 -0
  300. data/lib/generators/commonwealth_vlr_engine/templates/config/iiif_server.yml.sample +10 -0
  301. data/lib/generators/commonwealth_vlr_engine/templates/config/initializers/a_load_commonwealth_vlr_configs.rb +14 -0
  302. data/lib/generators/commonwealth_vlr_engine/templates/config/initializers/devise.rb +269 -0
  303. data/lib/generators/commonwealth_vlr_engine/templates/config/initializers/secret_token.rb +8 -0
  304. data/lib/generators/commonwealth_vlr_engine/templates/config/locales/blacklight.en.yml +44 -0
  305. data/lib/generators/commonwealth_vlr_engine/templates/config/locales/devise.en.yml +12 -0
  306. data/lib/generators/commonwealth_vlr_engine/templates/config/omniauth-facebook.yml.sample +14 -0
  307. data/lib/generators/commonwealth_vlr_engine/templates/config/omniauth-polaris.yml.sample +20 -0
  308. data/lib/generators/commonwealth_vlr_engine/templates/config/vlr.yml +13 -0
  309. data/lib/generators/commonwealth_vlr_engine/yml_generator.rb +29 -0
  310. data/lib/railties/commonwealth_vlr_engine.rake +6 -0
  311. data/solr_conf/conf/schema.xml +476 -0
  312. data/solr_conf/conf/solrconfig.xml +286 -0
  313. data/spec/controllers/catalog_controller_spec.rb +67 -0
  314. data/spec/controllers/collections_controller_spec.rb +127 -0
  315. data/spec/controllers/feedback_controller_spec.rb +51 -0
  316. data/spec/controllers/folder_items_actions_controller_spec.rb +99 -0
  317. data/spec/controllers/folder_items_controller_spec.rb +90 -0
  318. data/spec/controllers/folders_controller_spec.rb +368 -0
  319. data/spec/controllers/iiif_manifest_controller_spec.rb +85 -0
  320. data/spec/controllers/image_viewer_controller_spec.rb +50 -0
  321. data/spec/controllers/institutions_controller_spec.rb +64 -0
  322. data/spec/controllers/ocr_search_controller_spec.rb +71 -0
  323. data/spec/controllers/pages_controller_spec.rb +58 -0
  324. data/spec/controllers/users_controller_spec.rb +62 -0
  325. data/spec/features/catalog/_az_links_spec.rb +27 -0
  326. data/spec/features/catalog/_show_partials/_show_book_viewer_link_spec.rb +47 -0
  327. data/spec/features/catalog/_show_partials/_show_default_simple_img_viewer_spec.rb +19 -0
  328. data/spec/features/catalog/_show_partials/_show_flagged_notice_spec.rb +23 -0
  329. data/spec/features/catalog/_show_partials/_show_multi_img_spec.rb +18 -0
  330. data/spec/features/catalog/_show_partials/_show_volumes_spec.rb +24 -0
  331. data/spec/features/collections/index_spec.rb +35 -0
  332. data/spec/features/feedback/show_spec.rb +47 -0
  333. data/spec/features/image_viewer/book_viewer_spec.rb +67 -0
  334. data/spec/features/institutions/index_spec.rb +31 -0
  335. data/spec/features/institutions/map_view_spec.rb +37 -0
  336. data/spec/features/more_like_this_search_spec.rb +23 -0
  337. data/spec/features/ocr_search/index_spec.rb +89 -0
  338. data/spec/fixtures/sample_rss_feed.xml +56 -0
  339. data/spec/fixtures/sample_solr_documents.yml +2748 -0
  340. data/spec/helpers/application_helper_spec.rb +114 -0
  341. data/spec/helpers/catalog_helper_spec.rb +386 -0
  342. data/spec/helpers/collections_helper_spec.rb +28 -0
  343. data/spec/helpers/component_helper_spec.rb +34 -0
  344. data/spec/helpers/folders_helper_spec.rb +31 -0
  345. data/spec/helpers/image_viewer_helper_spec.rb +15 -0
  346. data/spec/helpers/institutions_helper_spec.rb +53 -0
  347. data/spec/helpers/ocr_search_helper_spec.rb +70 -0
  348. data/spec/helpers/pages_helper_spec.rb +21 -0
  349. data/spec/lib/commonwealth-vlr-engine/commonwealth_search_builder_spec.rb +101 -0
  350. data/spec/lib/commonwealth-vlr-engine/controller_override_spec.rb +41 -0
  351. data/spec/lib/commonwealth-vlr-engine/controller_spec.rb +33 -0
  352. data/spec/lib/commonwealth-vlr-engine/finder_spec.rb +140 -0
  353. data/spec/lib/commonwealth-vlr-engine/iiif_manifest_spec.rb +157 -0
  354. data/spec/lib/commonwealth-vlr-engine/render_constraints_override_spec.rb +97 -0
  355. data/spec/mailers/notifier_spec.rb +31 -0
  356. data/spec/models/carousel_slide_spec.rb +38 -0
  357. data/spec/spec_helper.rb +40 -0
  358. data/spec/tasks/vlr_engine_rake_spec.rb +28 -0
  359. data/spec/test_app_templates/lib/generators/test_app_generator.rb +23 -0
  360. data/tasks/vlr_engine.rake +46 -0
  361. metadata +788 -0
@@ -0,0 +1,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));