@internetarchive/bookreader 5.0.0-3 → 5.0.0-30-a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (389) hide show
  1. package/.eslintrc.js +17 -5
  2. package/.github/dependabot.yml +8 -0
  3. package/.github/workflows/node.js.yml +10 -1
  4. package/.husky/_/husky.sh +30 -0
  5. package/.testcaferc.js +10 -0
  6. package/BookReader/BookReader.css +75 -323
  7. package/BookReader/BookReader.js +1 -1
  8. package/BookReader/BookReader.js.LICENSE.txt +45 -0
  9. package/BookReader/BookReader.js.map +1 -1
  10. package/BookReader/ia-bookreader-bundle.js +1458 -0
  11. package/BookReader/{bookreader-component-bundle.js.LICENSE.txt → ia-bookreader-bundle.js.LICENSE.txt} +10 -9
  12. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  13. package/BookReader/icons/close-circle-dark.svg +1 -0
  14. package/BookReader/icons/voice.svg +1 -0
  15. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  16. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  17. package/BookReader/plugins/plugin.autoplay.js +1 -1
  18. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  19. package/BookReader/plugins/plugin.chapters.js +1 -1
  20. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  21. package/BookReader/plugins/plugin.iframe.js +1 -1
  22. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  23. package/BookReader/plugins/plugin.mobile_nav.js +1 -1
  24. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
  25. package/BookReader/plugins/plugin.resume.js +1 -1
  26. package/BookReader/plugins/plugin.resume.js.map +1 -1
  27. package/BookReader/plugins/plugin.search.js +1 -1
  28. package/BookReader/plugins/plugin.search.js.map +1 -1
  29. package/BookReader/plugins/plugin.text_selection.js +1 -1
  30. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  31. package/BookReader/plugins/plugin.tts.js +1 -1
  32. package/BookReader/plugins/plugin.tts.js.map +1 -1
  33. package/BookReader/plugins/plugin.url.js +1 -1
  34. package/BookReader/plugins/plugin.url.js.map +1 -1
  35. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  36. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  37. package/BookReader/webcomponents-bundle.js +3 -0
  38. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  39. package/BookReader/webcomponents-bundle.js.map +1 -0
  40. package/BookReaderDemo/BookReaderDemo.css +14 -1
  41. package/BookReaderDemo/IADemoBr.js +107 -0
  42. package/BookReaderDemo/demo-advanced.html +1 -1
  43. package/BookReaderDemo/demo-autoplay.html +1 -0
  44. package/BookReaderDemo/demo-embed-iframe-src.html +1 -0
  45. package/BookReaderDemo/demo-fullscreen-mobile.html +1 -0
  46. package/BookReaderDemo/demo-fullscreen.html +1 -0
  47. package/BookReaderDemo/demo-iiif.html +1 -0
  48. package/BookReaderDemo/demo-internetarchive.html +66 -18
  49. package/BookReaderDemo/demo-multiple.html +1 -0
  50. package/BookReaderDemo/demo-preview-pages.html +1 -0
  51. package/BookReaderDemo/demo-simple.html +1 -0
  52. package/BookReaderDemo/demo-vendor-fullscreen.html +1 -0
  53. package/BookReaderDemo/immersion-1up.html +1 -0
  54. package/BookReaderDemo/immersion-mode.html +1 -0
  55. package/BookReaderDemo/toggle_controls.html +1 -0
  56. package/BookReaderDemo/view_mode.html +1 -0
  57. package/BookReaderDemo/viewmode-cycle.html +1 -2
  58. package/CHANGELOG.md +114 -0
  59. package/babel.config.js +18 -0
  60. package/index.html +3 -0
  61. package/jsconfig.json +19 -0
  62. package/package.json +45 -27
  63. package/src/BookNavigator/assets/button-base.js +8 -1
  64. package/src/BookNavigator/assets/ia-logo.js +17 -0
  65. package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
  66. package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
  67. package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
  68. package/src/BookNavigator/assets/icon_volumes.js +11 -0
  69. package/src/BookNavigator/book-navigator.js +528 -0
  70. package/src/BookNavigator/bookmarks/bookmark-button.js +2 -1
  71. package/src/BookNavigator/bookmarks/bookmark-edit.js +2 -1
  72. package/src/BookNavigator/bookmarks/bookmarks-list.js +1 -0
  73. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +4 -9
  74. package/src/BookNavigator/bookmarks/bookmarks-provider.js +32 -11
  75. package/src/BookNavigator/bookmarks/ia-bookmarks.js +88 -43
  76. package/src/BookNavigator/downloads/downloads-provider.js +22 -16
  77. package/src/BookNavigator/downloads/downloads.js +16 -23
  78. package/src/BookNavigator/search/a-search-result.js +1 -0
  79. package/src/BookNavigator/search/search-provider.js +54 -20
  80. package/src/BookNavigator/search/search-results.js +7 -18
  81. package/src/BookNavigator/sharing.js +27 -0
  82. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +10 -12
  83. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +1 -0
  84. package/src/BookNavigator/volumes/volumes-provider.js +114 -0
  85. package/src/BookNavigator/volumes/volumes.js +189 -0
  86. package/src/BookReader/DebugConsole.js +3 -3
  87. package/src/BookReader/DragScrollable.js +233 -0
  88. package/src/BookReader/Mode1Up.js +50 -351
  89. package/src/BookReader/Mode1UpLit.js +434 -0
  90. package/src/BookReader/Mode2Up.js +94 -72
  91. package/src/BookReader/ModeSmoothZoom.js +177 -0
  92. package/src/BookReader/ModeThumb.js +16 -8
  93. package/src/BookReader/Navbar/Navbar.js +2 -31
  94. package/src/BookReader/PageContainer.js +47 -2
  95. package/src/BookReader/ReduceSet.js +1 -1
  96. package/src/BookReader/Toolbar/Toolbar.js +5 -5
  97. package/src/BookReader/options.js +10 -0
  98. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  99. package/src/BookReader/utils.js +68 -13
  100. package/src/BookReader.js +316 -232
  101. package/src/assets/icons/close-circle-dark.svg +1 -0
  102. package/src/assets/icons/voice.svg +1 -0
  103. package/src/css/BookReader.scss +0 -12
  104. package/src/css/_BRComponent.scss +1 -1
  105. package/src/css/_BRmain.scss +19 -24
  106. package/src/css/_BRnav.scss +4 -26
  107. package/src/css/_BRpages.scss +35 -0
  108. package/src/css/_BRsearch.scss +11 -215
  109. package/src/css/_TextSelection.scss +1 -17
  110. package/src/css/_controls.scss +16 -3
  111. package/src/css/_icons.scss +6 -0
  112. package/src/ia-bookreader/ia-bookreader.js +205 -0
  113. package/src/plugins/plugin.chapters.js +15 -18
  114. package/src/plugins/plugin.mobile_nav.js +11 -10
  115. package/src/plugins/plugin.resume.js +3 -3
  116. package/src/plugins/plugin.text_selection.js +17 -29
  117. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  118. package/src/plugins/search/plugin.search.js +113 -104
  119. package/src/plugins/search/view.js +48 -163
  120. package/src/plugins/tts/AbstractTTSEngine.js +7 -0
  121. package/src/plugins/tts/FestivalTTSEngine.js +2 -2
  122. package/src/plugins/tts/WebTTSEngine.js +5 -0
  123. package/src/plugins/tts/plugin.tts.js +67 -102
  124. package/src/plugins/url/UrlPlugin.js +184 -0
  125. package/src/plugins/url/plugin.url.js +220 -0
  126. package/{src → stat}/BookNavigator/BookModel.js +0 -0
  127. package/{src → stat}/BookNavigator/BookNavigator.js +151 -104
  128. package/stat/BookNavigator/assets/bookmark-colors.js +15 -0
  129. package/stat/BookNavigator/assets/button-base.js +61 -0
  130. package/stat/BookNavigator/assets/ia-logo.js +17 -0
  131. package/stat/BookNavigator/assets/icon_checkmark.js +6 -0
  132. package/stat/BookNavigator/assets/icon_close.js +3 -0
  133. package/stat/BookNavigator/assets/icon_sort_asc.js +5 -0
  134. package/stat/BookNavigator/assets/icon_sort_desc.js +5 -0
  135. package/stat/BookNavigator/assets/icon_sort_neutral.js +5 -0
  136. package/stat/BookNavigator/assets/icon_volumes.js +11 -0
  137. package/stat/BookNavigator/bookmarks/bookmark-button.js +64 -0
  138. package/stat/BookNavigator/bookmarks/bookmark-edit.js +215 -0
  139. package/stat/BookNavigator/bookmarks/bookmarks-list.js +285 -0
  140. package/stat/BookNavigator/bookmarks/bookmarks-loginCTA.js +28 -0
  141. package/stat/BookNavigator/bookmarks/bookmarks-provider.js +56 -0
  142. package/stat/BookNavigator/bookmarks/ia-bookmarks.js +523 -0
  143. package/{src → stat}/BookNavigator/br-fullscreen-mgr.js +1 -2
  144. package/stat/BookNavigator/delete-modal-actions.js +49 -0
  145. package/stat/BookNavigator/downloads/downloads-provider.js +72 -0
  146. package/stat/BookNavigator/downloads/downloads.js +139 -0
  147. package/stat/BookNavigator/provider-config.js +0 -0
  148. package/stat/BookNavigator/search/a-search-result.js +55 -0
  149. package/stat/BookNavigator/search/search-provider.js +180 -0
  150. package/stat/BookNavigator/search/search-results.js +360 -0
  151. package/stat/BookNavigator/sharing.js +31 -0
  152. package/stat/BookNavigator/visual-adjustments/visual-adjustments-provider.js +94 -0
  153. package/stat/BookNavigator/visual-adjustments/visual-adjustments.js +280 -0
  154. package/stat/BookNavigator/volumes/volumes-provider.js +83 -0
  155. package/stat/BookNavigator/volumes/volumes.js +178 -0
  156. package/stat/BookReader/BookModel.js +518 -0
  157. package/stat/BookReader/DebugConsole.js +54 -0
  158. package/stat/BookReader/DragScrollable.js +233 -0
  159. package/stat/BookReader/ImageCache.js +116 -0
  160. package/stat/BookReader/Mode1Up.js +102 -0
  161. package/stat/BookReader/Mode1UpLit.js +434 -0
  162. package/stat/BookReader/Mode2Up.js +1372 -0
  163. package/stat/BookReader/ModeSmoothZoom.js +177 -0
  164. package/stat/BookReader/ModeThumb.js +344 -0
  165. package/stat/BookReader/Navbar/Navbar.js +310 -0
  166. package/stat/BookReader/PageContainer.js +120 -0
  167. package/stat/BookReader/ReduceSet.js +26 -0
  168. package/stat/BookReader/Toolbar/Toolbar.js +384 -0
  169. package/stat/BookReader/events.js +20 -0
  170. package/stat/BookReader/options.js +324 -0
  171. package/stat/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  172. package/stat/BookReader/utils/classes.js +36 -0
  173. package/stat/BookReader/utils.js +240 -0
  174. package/stat/BookReader.js +2550 -0
  175. package/{src → stat}/BookReaderComponent/BookReaderComponent.js +16 -11
  176. package/stat/assets/icons/1up.svg +12 -0
  177. package/stat/assets/icons/2up.svg +15 -0
  178. package/stat/assets/icons/advance.svg +26 -0
  179. package/stat/assets/icons/chevron-right.svg +1 -0
  180. package/stat/assets/icons/close-circle-dark.svg +1 -0
  181. package/stat/assets/icons/close-circle.svg +1 -0
  182. package/stat/assets/icons/fullscreen.svg +17 -0
  183. package/stat/assets/icons/fullscreen_exit.svg +17 -0
  184. package/stat/assets/icons/hamburger.svg +15 -0
  185. package/stat/assets/icons/left-arrow.svg +12 -0
  186. package/stat/assets/icons/magnify-minus.svg +16 -0
  187. package/stat/assets/icons/magnify-plus.svg +17 -0
  188. package/stat/assets/icons/magnify.svg +15 -0
  189. package/stat/assets/icons/pause.svg +23 -0
  190. package/stat/assets/icons/play.svg +22 -0
  191. package/stat/assets/icons/playback-speed.svg +34 -0
  192. package/stat/assets/icons/read-aloud.svg +22 -0
  193. package/stat/assets/icons/review.svg +22 -0
  194. package/stat/assets/icons/thumbnails.svg +17 -0
  195. package/stat/assets/icons/voice.svg +1 -0
  196. package/stat/assets/icons/volume-full.svg +22 -0
  197. package/stat/assets/images/BRicons.png +0 -0
  198. package/stat/assets/images/BRicons.svg +94 -0
  199. package/stat/assets/images/BRicons_ia.png +0 -0
  200. package/stat/assets/images/back_pages.png +0 -0
  201. package/stat/assets/images/book_bottom_icon.png +0 -0
  202. package/stat/assets/images/book_down_icon.png +0 -0
  203. package/stat/assets/images/book_left_icon.png +0 -0
  204. package/stat/assets/images/book_leftmost_icon.png +0 -0
  205. package/stat/assets/images/book_right_icon.png +0 -0
  206. package/stat/assets/images/book_rightmost_icon.png +0 -0
  207. package/stat/assets/images/book_top_icon.png +0 -0
  208. package/stat/assets/images/book_up_icon.png +0 -0
  209. package/stat/assets/images/books_graphic.svg +177 -0
  210. package/stat/assets/images/booksplit.png +0 -0
  211. package/stat/assets/images/control_pause_icon.png +0 -0
  212. package/stat/assets/images/control_play_icon.png +0 -0
  213. package/stat/assets/images/embed_icon.png +0 -0
  214. package/stat/assets/images/icon-home-ia.png +0 -0
  215. package/stat/assets/images/icon_OL-logo-xs.png +0 -0
  216. package/stat/assets/images/icon_alert-xs.png +0 -0
  217. package/stat/assets/images/icon_book.svg +12 -0
  218. package/stat/assets/images/icon_bookmark.svg +12 -0
  219. package/stat/assets/images/icon_close-pop.png +0 -0
  220. package/stat/assets/images/icon_download.png +0 -0
  221. package/stat/assets/images/icon_gear.svg +14 -0
  222. package/stat/assets/images/icon_hamburger.svg +20 -0
  223. package/stat/assets/images/icon_home.png +0 -0
  224. package/stat/assets/images/icon_home.svg +21 -0
  225. package/stat/assets/images/icon_home_ia.png +0 -0
  226. package/stat/assets/images/icon_indicator.png +0 -0
  227. package/stat/assets/images/icon_info.svg +11 -0
  228. package/stat/assets/images/icon_one_page.svg +8 -0
  229. package/stat/assets/images/icon_pause.svg +1 -0
  230. package/stat/assets/images/icon_play.svg +1 -0
  231. package/stat/assets/images/icon_playback-rate.svg +15 -0
  232. package/stat/assets/images/icon_return.png +0 -0
  233. package/stat/assets/images/icon_search_button.svg +8 -0
  234. package/stat/assets/images/icon_share.svg +9 -0
  235. package/stat/assets/images/icon_skip-ahead.svg +6 -0
  236. package/stat/assets/images/icon_skip-back.svg +13 -0
  237. package/stat/assets/images/icon_speaker.svg +18 -0
  238. package/stat/assets/images/icon_speaker_open.svg +10 -0
  239. package/stat/assets/images/icon_thumbnails.svg +12 -0
  240. package/stat/assets/images/icon_toc.svg +5 -0
  241. package/stat/assets/images/icon_two_pages.svg +9 -0
  242. package/stat/assets/images/icon_zoomer.png +0 -0
  243. package/stat/assets/images/loading.gif +0 -0
  244. package/stat/assets/images/logo_icon.png +0 -0
  245. package/stat/assets/images/marker_chap-off.png +0 -0
  246. package/stat/assets/images/marker_chap-off.svg +11 -0
  247. package/stat/assets/images/marker_chap-off_ia.png +0 -0
  248. package/stat/assets/images/marker_chap-on.png +0 -0
  249. package/stat/assets/images/marker_chap-on.svg +11 -0
  250. package/stat/assets/images/marker_srch-on.svg +11 -0
  251. package/stat/assets/images/marker_srchchap-off.png +0 -0
  252. package/stat/assets/images/marker_srchchap-on.png +0 -0
  253. package/stat/assets/images/nav_control-dn.png +0 -0
  254. package/stat/assets/images/nav_control-dn_ia.png +0 -0
  255. package/stat/assets/images/nav_control-up.png +0 -0
  256. package/stat/assets/images/nav_control-up_ia.png +0 -0
  257. package/stat/assets/images/nav_control.png +0 -0
  258. package/stat/assets/images/one_page_mode_icon.png +0 -0
  259. package/stat/assets/images/paper-badge.png +0 -0
  260. package/stat/assets/images/print_icon.png +0 -0
  261. package/stat/assets/images/progressbar.gif +0 -0
  262. package/stat/assets/images/right_edges.png +0 -0
  263. package/stat/assets/images/slider.png +0 -0
  264. package/stat/assets/images/slider_ia.png +0 -0
  265. package/stat/assets/images/thumbnail_mode_icon.png +0 -0
  266. package/stat/assets/images/transparent.png +0 -0
  267. package/stat/assets/images/two_page_mode_icon.png +0 -0
  268. package/stat/assets/images/zoom_in_icon.png +0 -0
  269. package/stat/assets/images/zoom_out_icon.png +0 -0
  270. package/stat/css/BookReader.scss +89 -0
  271. package/stat/css/_BRBookmarks.scss +29 -0
  272. package/stat/css/_BRComponent.scss +13 -0
  273. package/stat/css/_BRfloat.scss +197 -0
  274. package/stat/css/_BRicon.scss +48 -0
  275. package/stat/css/_BRmain.scss +251 -0
  276. package/stat/css/_BRnav.scss +359 -0
  277. package/stat/css/_BRpages.scss +139 -0
  278. package/stat/css/_BRsearch.scss +226 -0
  279. package/stat/css/_BRtoolbar.scss +84 -0
  280. package/stat/css/_BRvendor.scss +5 -0
  281. package/stat/css/_MobileNav.scss +194 -0
  282. package/stat/css/_TextSelection.scss +32 -0
  283. package/stat/css/_colorbox.scss +52 -0
  284. package/stat/css/_controls.scss +253 -0
  285. package/stat/css/_icons.scss +121 -0
  286. package/stat/jquery-wrapper.js +4 -0
  287. package/stat/plugins/plugin.archive_analytics.js +86 -0
  288. package/stat/plugins/plugin.autoplay.js +129 -0
  289. package/stat/plugins/plugin.chapters.js +248 -0
  290. package/stat/plugins/plugin.iframe.js +48 -0
  291. package/stat/plugins/plugin.mobile_nav.js +288 -0
  292. package/stat/plugins/plugin.resume.js +68 -0
  293. package/stat/plugins/plugin.text_selection.js +291 -0
  294. package/{src → stat}/plugins/plugin.url.js +4 -4
  295. package/stat/plugins/plugin.vendor-fullscreen.js +247 -0
  296. package/stat/plugins/search/plugin.search.js +439 -0
  297. package/stat/plugins/search/view.js +439 -0
  298. package/stat/plugins/tts/AbstractTTSEngine.js +249 -0
  299. package/stat/plugins/tts/FestivalTTSEngine.js +169 -0
  300. package/stat/plugins/tts/PageChunk.js +107 -0
  301. package/stat/plugins/tts/PageChunkIterator.js +163 -0
  302. package/stat/plugins/tts/WebTTSEngine.js +357 -0
  303. package/stat/plugins/tts/plugin.tts.js +357 -0
  304. package/stat/plugins/tts/tooltip_dict.js +15 -0
  305. package/stat/plugins/tts/utils.js +91 -0
  306. package/stat/util/browserSniffing.js +30 -0
  307. package/stat/util/debouncer.js +26 -0
  308. package/stat/util/docCookies.js +67 -0
  309. package/stat/util/strings.js +34 -0
  310. package/tests/e2e/README.md +37 -0
  311. package/tests/e2e/autoplay.test.js +2 -2
  312. package/tests/e2e/base.test.js +5 -7
  313. package/tests/e2e/helpers/base.js +8 -3
  314. package/tests/e2e/helpers/debug.js +1 -1
  315. package/tests/e2e/helpers/desktopSearch.js +1 -1
  316. package/tests/e2e/helpers/mobileSearch.js +3 -3
  317. package/tests/e2e/helpers/params.js +17 -0
  318. package/tests/e2e/rightToLeft.test.js +4 -5
  319. package/tests/e2e/viewmode.test.js +30 -31
  320. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +3 -3
  321. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
  322. package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
  323. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  324. package/tests/jest/BookReader/Mode1UpLit.test.js +87 -0
  325. package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +5 -7
  326. package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
  327. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  328. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
  329. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +74 -2
  330. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  331. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  332. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  333. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  334. package/tests/jest/BookReader/utils.test.js +136 -0
  335. package/tests/jest/BookReader.keyboard.test.js +190 -0
  336. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  337. package/tests/{BookReader.test.js → jest/BookReader.test.js} +20 -4
  338. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  339. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +2 -2
  340. package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +8 -8
  341. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  342. package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
  343. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  344. package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +14 -24
  345. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  346. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +12 -5
  347. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +6 -6
  348. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +3 -3
  349. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  350. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  351. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  352. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +1 -1
  353. package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -3
  354. package/tests/jest/plugins/url/UrlPlugin.test.js +175 -0
  355. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
  356. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  357. package/tests/{util → jest/util}/docCookies.test.js +1 -1
  358. package/tests/{util → jest/util}/strings.test.js +1 -1
  359. package/tests/{utils.js → jest/utils.js} +38 -0
  360. package/tests/karma/BookNavigator/book-navigator.test.js +485 -0
  361. package/tests/karma/BookNavigator/bookmarks/bookmark-button.test.js +44 -0
  362. package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +1 -3
  363. package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +1 -2
  364. package/tests/karma/BookNavigator/downloads/downloads-provider.test.js +67 -0
  365. package/tests/karma/BookNavigator/downloads/downloads.test.js +54 -0
  366. package/tests/karma/BookNavigator/search/search-provider.test.js +123 -0
  367. package/tests/karma/BookNavigator/{search-results.test.js → search/search-results.test.js} +1 -4
  368. package/tests/karma/BookNavigator/sharing/sharing-provider.test.js +49 -0
  369. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -2
  370. package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +184 -0
  371. package/tests/karma/BookNavigator/volumes/volumes.test.js +98 -0
  372. package/webpack.config.js +10 -4
  373. package/.babelrc +0 -12
  374. package/.dependabot/config.yml +0 -6
  375. package/.testcaferc.json +0 -5
  376. package/BookReader/bookreader-component-bundle.js +0 -1450
  377. package/BookReader/bookreader-component-bundle.js.map +0 -1
  378. package/BookReader/plugins/plugin.menu_toggle.js +0 -2
  379. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  380. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  381. package/src/BookNavigator/assets/book-loader.js +0 -27
  382. package/src/ItemNavigator/ItemNavigator.js +0 -372
  383. package/src/ItemNavigator/providers/sharing.js +0 -29
  384. package/src/dragscrollable-br.js +0 -261
  385. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  386. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  387. package/tests/BookReader/Mode1Up.test.js +0 -164
  388. package/tests/BookReader/utils.test.js +0 -109
  389. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
package/src/BookReader.js CHANGED
@@ -27,7 +27,6 @@ import 'jquery-ui/ui/widget.js';
27
27
  import 'jquery-ui/ui/widgets/mouse.js';
28
28
  import 'jquery-ui-touch-punch';
29
29
 
30
- import './dragscrollable-br.js';
31
30
  import PACKAGE_JSON from '../package.json';
32
31
  import * as utils from './BookReader/utils.js';
33
32
  import { exposeOverrideable } from './BookReader/utils/classes.js';
@@ -179,7 +178,7 @@ BookReader.prototype.setup = function(options) {
179
178
  */
180
179
  this.firstIndex = null;
181
180
  this.lastDisplayableIndex2up = null;
182
- this.isFullscreenActive = false;
181
+ this.isFullscreenActive = options.startFullscreen || false;
183
182
  this.lastScroll = null;
184
183
 
185
184
  this.showLogo = options.showLogo;
@@ -265,8 +264,52 @@ BookReader.prototype.setup = function(options) {
265
264
  useSrcSet: this.options.useSrcSet,
266
265
  reduceSet: this.reduceSet,
267
266
  });
267
+
268
+ /**
269
+ * Flag if BookReader has "focus" for keyboard shortcuts
270
+ * Initially true, set to false when:
271
+ * - BookReader scrolled out of view
272
+ * Set to true when:
273
+ * - BookReader scrolled into view
274
+ */
275
+ this.hasKeyFocus = true;
276
+ };
277
+
278
+ /**
279
+ * Get all the HTML Elements that are being/can be rendered.
280
+ * Includes cached elements which might be rendered again.
281
+ */
282
+ BookReader.prototype.getActivePageContainerElements = function() {
283
+ let containerEls = Object.values(this._modes.mode2Up.pageContainers).map(pc => pc.$container[0])
284
+ .concat(Object.values(this._modes.mode1Up.mode1UpLit.pageContainerCache).map(pc => pc.$container[0]));
285
+ if (this.mode == this.constModeThumb) {
286
+ containerEls = containerEls.concat(this.$('.BRpagecontainer').toArray());
287
+ }
288
+ return containerEls;
289
+ };
290
+
291
+ /**
292
+ * Get the HTML Elements for the rendered page. Note there can be more than one, since
293
+ * (at least as of writing) different modes can maintain different caches.
294
+ * @param {PageIndex} pageIndex
295
+ */
296
+ BookReader.prototype.getActivePageContainerElementsForIndex = function(pageIndex) {
297
+ return [
298
+ this._modes.mode2Up.pageContainers[pageIndex]?.$container?.[0],
299
+ this._modes.mode1Up.mode1UpLit.pageContainerCache[pageIndex]?.$container?.[0],
300
+ ...(this.mode == this.constModeThumb ? this.$(`.pagediv${pageIndex}`).toArray() : [])
301
+ ].filter(x => x);
268
302
  };
269
303
 
304
+ Object.defineProperty(BookReader.prototype, 'activeMode', {
305
+ /** @return {Mode1Up | Mode2Up | ModeThumb} */
306
+ get() { return {
307
+ 1: this._modes.mode1Up,
308
+ 2: this._modes.mode2Up,
309
+ 3: this._modes.modeThumb,
310
+ }[this.mode]; },
311
+ });
312
+
270
313
  /** @deprecated unused outside Mode2Up */
271
314
  Object.defineProperty(BookReader.prototype, 'leafEdgeL', {
272
315
  get() { return this._modes.mode2Up.leafEdgeL; },
@@ -298,7 +341,7 @@ BookReader.prototype.extendParams = function(params, newParams) {
298
341
  delete modifiedNewParams.page;
299
342
  }
300
343
  $.extend(params, modifiedNewParams);
301
- }
344
+ };
302
345
 
303
346
  /**
304
347
  * Parses params from from various initialization contexts (url, cookie, options)
@@ -377,7 +420,7 @@ BookReader.prototype.initParams = function() {
377
420
  // Check for Search plugin
378
421
  if (this.options.enableSearch) {
379
422
  // Go to first result only if no default or URL page
380
- this.goToFirstResult = !params.pageFound
423
+ this.options.goToFirstResult = !params.pageFound;
381
424
 
382
425
  // If initialSearchTerm not set
383
426
  if (!this.options.initialSearchTerm) {
@@ -389,7 +432,7 @@ BookReader.prototype.initParams = function() {
389
432
  } else {
390
433
  // If we have a query string: q=[term]
391
434
  const searchParams = new URLSearchParams(this.readQueryString());
392
- const searchTerm = searchParams.get('q')
435
+ const searchTerm = searchParams.get('q');
393
436
  if (searchTerm) {
394
437
  this.options.initialSearchTerm = utils.decodeURIComponentPlus(searchTerm);
395
438
  }
@@ -401,21 +444,21 @@ BookReader.prototype.initParams = function() {
401
444
  this.suppressFragmentChange = !params.fragmentChange;
402
445
 
403
446
  return params;
404
- }
447
+ };
405
448
 
406
449
  /**
407
450
  * Allow mocking of window.location.search
408
451
  */
409
452
  BookReader.prototype.getLocationSearch = function () {
410
453
  return window.location.search;
411
- }
454
+ };
412
455
 
413
456
  /**
414
457
  * Allow mocking of window.location.hash
415
458
  */
416
459
  BookReader.prototype.getLocationHash = function () {
417
460
  return window.location.hash;
418
- }
461
+ };
419
462
 
420
463
  /**
421
464
  * Return URL or fragment querystring
@@ -428,7 +471,7 @@ BookReader.prototype.readQueryString = function() {
428
471
  const hash = this.getLocationHash();
429
472
  const found = hash.search(/\?\w+=/);
430
473
  return found > -1 ? hash.slice(found) : '';
431
- }
474
+ };
432
475
 
433
476
  /**
434
477
  * Determines the initial mode for starting if a mode is not already
@@ -443,7 +486,6 @@ BookReader.prototype.getInitialMode = function(params) {
443
486
  if ('undefined' != typeof(params.mode)) {
444
487
  nextMode = params.mode;
445
488
  } else if (this.ui == 'full'
446
- && this.enableMobileNav
447
489
  && this.isFullscreenActive
448
490
  && windowWidth <= this.onePageMinBreakpoint
449
491
  ) {
@@ -497,15 +539,12 @@ BookReader.prototype.init = function() {
497
539
  // Explicitly ensure this.mode exists for initNavbar() below
498
540
  this.mode = params.mode;
499
541
 
500
- if (this.ui == "embed" && this.options.showNavbar) {
501
- this.initEmbedNavbar();
502
- } else {
503
- if (this.options.showToolbar) {
504
- this.initToolbar(this.mode, this.ui); // Build inside of toolbar div
505
- }
506
- if (this.options.showNavbar) {
507
- this.initNavbar();
508
- }
542
+ // Display Navigation
543
+ if (this.options.showToolbar) {
544
+ this.initToolbar(this.mode, this.ui); // Build inside of toolbar div
545
+ }
546
+ if (this.options.showNavbar) { // default navigation
547
+ this.initNavbar();
509
548
  }
510
549
 
511
550
  // Switch navbar controls on mobile/desktop
@@ -521,17 +560,17 @@ BookReader.prototype.init = function() {
521
560
  this.setupKeyListeners();
522
561
 
523
562
  this.lastScroll = (new Date().getTime());
524
- this.refs.$brContainer.bind('scroll', this, function(e) {
563
+ this.refs.$brContainer.on('scroll', this, function(e) {
525
564
  // Note, this scroll event fires for both user, and js generated calls
526
565
  // It is functioning in some cases as the primary triggerer for rendering
527
566
  e.data.lastScroll = (new Date().getTime());
528
- if (e.data.constMode2up != e.data.mode) {
567
+ if (e.data.constModeThumb == e.data.mode) {
529
568
  e.data.drawLeafsThrottled();
530
569
  }
531
570
  });
532
571
 
533
572
  if (this.options.autoResize) {
534
- $(window).bind('resize', this, function(e) {
573
+ $(window).on('resize', this, function(e) {
535
574
  e.data.resize();
536
575
  });
537
576
  $(window).on("orientationchange", this, function(e) {
@@ -548,15 +587,17 @@ BookReader.prototype.init = function() {
548
587
  this.suppressFragmentChange = false;
549
588
  }
550
589
 
590
+ if (this.options.startFullscreen) {
591
+ this.enterFullscreen(true);
592
+ }
593
+
551
594
  this.init.initComplete = true;
552
595
  this.trigger(BookReader.eventNames.PostInit);
553
596
 
554
597
  // Must be called after this.init.initComplete set to true to allow
555
598
  // BookReader.prototype.resize to run.
556
- if (this.options.startFullscreen) {
557
- this.toggleFullscreen();
558
- }
559
- }
599
+
600
+ };
560
601
 
561
602
  /**
562
603
  * @param {EVENTS} name
@@ -564,7 +605,6 @@ BookReader.prototype.init = function() {
564
605
  */
565
606
  BookReader.prototype.trigger = function(name, props = this) {
566
607
  const eventName = 'BookReader:' + name;
567
- $(document).trigger(eventName, props);
568
608
 
569
609
  utils.polyfillCustomEvent(window);
570
610
  window.dispatchEvent(new CustomEvent(eventName, {
@@ -572,14 +612,15 @@ BookReader.prototype.trigger = function(name, props = this) {
572
612
  composed: true,
573
613
  detail: { props },
574
614
  }));
615
+ $(document).trigger(eventName, props);
575
616
  };
576
617
 
577
618
  BookReader.prototype.bind = function(name, callback) {
578
- $(document).bind('BookReader:' + name, callback);
619
+ $(document).on('BookReader:' + name, callback);
579
620
  };
580
621
 
581
622
  BookReader.prototype.unbind = function(name, callback) {
582
- $(document).unbind('BookReader:' + name, callback);
623
+ $(document).off('BookReader:' + name, callback);
583
624
  };
584
625
 
585
626
  /**
@@ -597,11 +638,9 @@ BookReader.prototype.resize = function() {
597
638
  if (this.onePage.autofit != 'none') {
598
639
  this.resizePageView1up();
599
640
  this.centerPageView();
600
- if (this.enableSearch) this.updateSearchHilites(); //deletes highlights but does not call remove()
601
641
  } else {
602
642
  this.centerPageView();
603
643
  this.displayedIndices = [];
604
- if (this.enableSearch) this.updateSearchHilites(); //deletes highlights but does not call remove()
605
644
  this.drawLeafsThrottled();
606
645
  }
607
646
  } else if (this.constModeThumb == this.mode) {
@@ -633,89 +672,124 @@ BookReader.prototype.resize = function() {
633
672
  };
634
673
 
635
674
  /**
636
- * Binds keyboard event listeners
675
+ * Binds keyboard and keyboard focus event listeners
637
676
  */
638
- BookReader.prototype.setupKeyListeners = function() {
639
- var self = this;
677
+ BookReader.prototype.setupKeyListeners = function () {
640
678
 
641
- var KEY_PGUP = 33;
642
- var KEY_PGDOWN = 34;
643
- var KEY_END = 35;
644
- var KEY_HOME = 36;
645
-
646
- var KEY_LEFT = 37;
647
- var KEY_UP = 38;
648
- var KEY_RIGHT = 39;
649
- var KEY_DOWN = 40;
650
- // The minus(-) and equal(=) keys have different mappings for different browsers
651
- var KEY_MINUS = 189; // Chrome
652
- var KEY_MINUS_F = 173; // Firefox
653
- var KEY_NUMPAD_SUBTRACT = 109;
654
- var KEY_EQUAL = 187; // Chrome
655
- var KEY_EQUAL_F = 61; // Firefox
656
- var KEY_NUMPAD_ADD = 107;
657
-
658
- // We use document here instead of window to avoid a bug in jQuery on IE7
659
- $(document).keydown(function(e) {
660
-
661
- // Keyboard navigation
662
- if (!self.keyboardNavigationIsDisabled(e)) {
663
- switch (e.keyCode) {
664
- case KEY_PGUP:
665
- case KEY_UP:
666
- // In 1up mode page scrolling is handled by browser
667
- if (self.constMode2up == self.mode) {
668
- e.preventDefault();
669
- self.prev();
670
- }
671
- break;
672
- case KEY_DOWN:
673
- case KEY_PGDOWN:
674
- if (self.constMode2up == self.mode) {
675
- e.preventDefault();
676
- self.next();
679
+ // Keyboard focus by BookReader in viewport
680
+ //
681
+ // Intersection observer and callback sets BookReader keyboard
682
+ // "focus" flag off when the BookReader is not in the viewport.
683
+ if (window.IntersectionObserver) {
684
+ const observer = new IntersectionObserver((entries) => {
685
+ entries.forEach((entry) => {
686
+ if (entry.intersectionRatio === 0) {
687
+ this.hasKeyFocus = false;
688
+ } else {
689
+ this.hasKeyFocus = true;
677
690
  }
678
- break;
679
- case KEY_END:
691
+ });
692
+ }, {
693
+ root: null,
694
+ rootMargin: '0px',
695
+ threshold: [0, 0.05, 1],
696
+ });
697
+ observer.observe(this.refs.$br[0]);
698
+ }
699
+
700
+ // Keyboard listeners
701
+ document.addEventListener('keydown', (e) => {
702
+
703
+ // Ignore if BookReader "focus" flag not set
704
+ if (!this.hasKeyFocus) {
705
+ return;
706
+ }
707
+
708
+ // Ignore if modifiers are active.
709
+ if (e.getModifierState('Control') ||
710
+ e.getModifierState('Alt') ||
711
+ e.getModifierState('Meta') ||
712
+ e.getModifierState('Win') /* hack for IE */) {
713
+ return;
714
+ }
715
+
716
+ // Ignore in input elements
717
+ if (utils.isInputActive()) {
718
+ return;
719
+ }
720
+
721
+ // KeyboardEvent code values:
722
+ // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
723
+ switch (e.key) {
724
+
725
+ // Page navigation
726
+ case "Home":
727
+ e.preventDefault();
728
+ this.first();
729
+ break;
730
+ case "End":
731
+ e.preventDefault();
732
+ this.last();
733
+ break;
734
+ case "ArrowDown":
735
+ case "PageDown":
736
+ case "Down": // hack for IE and old Gecko
737
+ // In 1up and thumb mode page scrolling handled by browser
738
+ if (this.constMode2up === this.mode) {
680
739
  e.preventDefault();
681
- self.last();
682
- break;
683
- case KEY_HOME:
740
+ this.next();
741
+ }
742
+ break;
743
+ case "ArrowUp":
744
+ case "PageUp":
745
+ case "Up": // hack for IE and old Gecko
746
+ // In 1up and thumb mode page scrolling handled by browser
747
+ if (this.constMode2up === this.mode) {
684
748
  e.preventDefault();
685
- self.first();
686
- break;
687
- case KEY_LEFT:
688
- if (self.constModeThumb != self.mode) {
689
- e.preventDefault();
690
- self.left();
691
- }
692
- break;
693
- case KEY_RIGHT:
694
- if (self.constModeThumb != self.mode) {
695
- e.preventDefault();
696
- self.right();
697
- }
698
- break;
699
- case KEY_MINUS:
700
- case KEY_MINUS_F:
701
- case KEY_NUMPAD_SUBTRACT:
749
+ this.prev();
750
+ }
751
+ break;
752
+ case "ArrowLeft":
753
+ case "Left": // hack for IE and old Gecko
754
+ // No y-scrolling in thumb mode
755
+ if (this.constModeThumb != this.mode) {
702
756
  e.preventDefault();
703
- self.zoom(-1);
704
- break;
705
- case KEY_EQUAL:
706
- case KEY_EQUAL_F:
707
- case KEY_NUMPAD_ADD:
757
+ this.left();
758
+ }
759
+ break;
760
+ case "ArrowRight":
761
+ case "Right": // hack for IE and old Gecko
762
+ // No y-scrolling in thumb mode
763
+ if (this.constModeThumb != this.mode) {
708
764
  e.preventDefault();
709
- self.zoom(+1);
710
- break;
765
+ this.right();
711
766
  }
767
+ break;
768
+ // Zoom
769
+ case '-':
770
+ case 'Subtract':
771
+ e.preventDefault();
772
+ this.zoom(-1);
773
+ break;
774
+ case '+':
775
+ case '=':
776
+ case 'Add':
777
+ e.preventDefault();
778
+ this.zoom(1);
779
+ break;
780
+ // Fullscreen
781
+ case 'F':
782
+ case 'f':
783
+ e.preventDefault();
784
+ this.toggleFullscreen();
785
+ break;
712
786
  }
713
787
  });
714
788
  };
715
789
 
716
790
  BookReader.prototype.drawLeafs = function() {
717
791
  if (this.constMode1up == this.mode) {
718
- this.drawLeafsOnePage();
792
+ // Not needed for Mode1Up anymore
719
793
  } else if (this.constModeThumb == this.mode) {
720
794
  this.drawLeafsThumbnail();
721
795
  } else {
@@ -794,29 +868,11 @@ BookReader.prototype.drawLeafsThrottled = utils.throttle(
794
868
  * @param {number} direction Pass 1 to zoom in, anything else to zoom out
795
869
  */
796
870
  BookReader.prototype.zoom = function(direction) {
797
- switch (this.mode) {
798
- case this.constMode1up:
799
- if (direction == 1) {
800
- // XXX other cases
801
- this.zoom1up('in');
802
- } else {
803
- this.zoom1up('out');
804
- }
805
- break
806
- case this.constMode2up:
807
- if (direction == 1) {
808
- // XXX other cases
809
- this.zoom2up('in');
810
- } else {
811
- this.zoom2up('out');
812
- }
813
- break
814
- case this.constModeThumb:
815
- // XXX update zoomThumb for named directions
816
- this.zoomThumb(direction);
817
- break
871
+ if (direction == 1) {
872
+ this.activeMode.zoom('in');
873
+ } else {
874
+ this.activeMode.zoom('out');
818
875
  }
819
-
820
876
  this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
821
877
  return;
822
878
  };
@@ -842,7 +898,7 @@ BookReader.prototype.resizeBRcontainer = function(animate) {
842
898
  bottom: this.getFooterHeight()
843
899
  });
844
900
  }
845
- }
901
+ };
846
902
 
847
903
  BookReader.prototype.centerPageView = function() {
848
904
  var scrollWidth = this.refs.$brContainer.prop('scrollWidth');
@@ -954,7 +1010,7 @@ BookReader.prototype._isIndexDisplayed = function(index) {
954
1010
  return this.constMode1up == this.mode ? this.displayedIndices.slice(1, -1).includes(index) :
955
1011
  this.displayedIndices ? this.displayedIndices.includes(index) :
956
1012
  this.currentIndex() == index;
957
- }
1013
+ };
958
1014
 
959
1015
  /**
960
1016
  * Changes the current page
@@ -996,7 +1052,7 @@ BookReader.prototype.getPrevReadMode = function(mode) {
996
1052
  // Initial thumb, return 1up
997
1053
  return BookReader.constMode1up;
998
1054
  }
999
- }
1055
+ };
1000
1056
 
1001
1057
  /**
1002
1058
  * Switches the mode (eg 1up 2up thumb)
@@ -1024,10 +1080,13 @@ BookReader.prototype.switchMode = function(
1024
1080
  }
1025
1081
 
1026
1082
  this.trigger(BookReader.eventNames.stop);
1027
- if (this.enableSearch) this.removeSearchHilites();
1028
1083
 
1029
1084
  this.prevReadMode = this.getPrevReadMode(this.mode);
1030
1085
 
1086
+ if (this.mode != mode) {
1087
+ this.activeMode.unprepare?.();
1088
+ }
1089
+
1031
1090
  this.mode = mode;
1032
1091
 
1033
1092
  // reinstate scale if moving from thumbnail view
@@ -1040,8 +1099,6 @@ BookReader.prototype.switchMode = function(
1040
1099
 
1041
1100
  // XXX maybe better to preserve zoom in each mode
1042
1101
  if (this.constMode1up == mode) {
1043
- this.onePageCalculateReductionFactors();
1044
- this.reduce = this.quantizeReduce(this.reduce, this.onePage.reductionFactors);
1045
1102
  this.prepareOnePageView();
1046
1103
  } else if (this.constModeThumb == mode) {
1047
1104
  this.reduce = this.quantizeReduce(this.reduce, this.reductionFactors);
@@ -1095,11 +1152,11 @@ BookReader.prototype.isFullscreen = function() {
1095
1152
  * Toggles fullscreen
1096
1153
  * @param { boolean } bindKeyboardControls
1097
1154
  */
1098
- BookReader.prototype.toggleFullscreen = function(bindKeyboardControls = true) {
1155
+ BookReader.prototype.toggleFullscreen = async function(bindKeyboardControls = true) {
1099
1156
  if (this.isFullscreen()) {
1100
- this.exitFullScreen();
1157
+ await this.exitFullScreen();
1101
1158
  } else {
1102
- this.enterFullscreen(bindKeyboardControls);
1159
+ await this.enterFullscreen(bindKeyboardControls);
1103
1160
  }
1104
1161
  };
1105
1162
 
@@ -1111,7 +1168,7 @@ BookReader.prototype.toggleFullscreen = function(bindKeyboardControls = true) {
1111
1168
  * - fires custom event
1112
1169
  * @param { boolean } bindKeyboardControls
1113
1170
  */
1114
- BookReader.prototype.enterFullscreen = function(bindKeyboardControls = true) {
1171
+ BookReader.prototype.enterFullscreen = async function(bindKeyboardControls = true) {
1115
1172
  const currentIndex = this.currentIndex();
1116
1173
  this.refs.$brContainer.css('opacity', 0);
1117
1174
 
@@ -1119,7 +1176,7 @@ BookReader.prototype.enterFullscreen = function(bindKeyboardControls = true) {
1119
1176
  this._fullscreenCloseHandler = (e) => {
1120
1177
  if (e.keyCode === 27) this.toggleFullscreen();
1121
1178
  };
1122
- $(document).keyup(this._fullscreenCloseHandler);
1179
+ $(document).on("keyup", this._fullscreenCloseHandler);
1123
1180
  }
1124
1181
 
1125
1182
  const windowWidth = $(window).width();
@@ -1128,14 +1185,29 @@ BookReader.prototype.enterFullscreen = function(bindKeyboardControls = true) {
1128
1185
  }
1129
1186
 
1130
1187
  this.isFullscreenActive = true;
1131
-
1132
- this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear',() => {
1133
- this.resize();
1134
- this.jumpToIndex(currentIndex);
1135
- });
1188
+ // prioritize class updates so CSS can propagate
1189
+ this.updateBrClasses();
1190
+ this.animating = true;
1191
+ await new Promise(res => this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear', res));
1192
+ if (this.activeMode instanceof Mode1Up) {
1193
+ this.activeMode.mode1UpLit.scale = this.activeMode.mode1UpLit.computeDefaultScale(this._models.book.getPage(currentIndex));
1194
+ // Need the new scale to be applied before calling jumpToIndex
1195
+ await this.activeMode.mode1UpLit.requestUpdate();
1196
+ }
1197
+ this.jumpToIndex(currentIndex);
1198
+ this.animating = false;
1136
1199
 
1137
1200
  this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
1201
+ // Add "?view=theater"
1202
+ this.trigger(BookReader.eventNames.fragmentChange);
1203
+ // trigger event here, so that animations,
1204
+ // class updates happen before book-nav relays to web components
1138
1205
  this.trigger(BookReader.eventNames.fullscreenToggled);
1206
+
1207
+ setTimeout(() => {
1208
+ // resize book after all events & css updates
1209
+ this.resize();
1210
+ }, 0);
1139
1211
  };
1140
1212
 
1141
1213
  /**
@@ -1145,10 +1217,10 @@ BookReader.prototype.enterFullscreen = function(bindKeyboardControls = true) {
1145
1217
  * - fires custom event
1146
1218
  * @param { boolean } bindKeyboardControls
1147
1219
  */
1148
- BookReader.prototype.exitFullScreen = function() {
1220
+ BookReader.prototype.exitFullScreen = async function () {
1149
1221
  this.refs.$brContainer.css('opacity', 0);
1150
1222
 
1151
- $(document).unbind('keyup', this._fullscreenCloseHandler);
1223
+ $(document).off('keyup', this._fullscreenCloseHandler);
1152
1224
 
1153
1225
  var windowWidth = $(window).width();
1154
1226
 
@@ -1158,13 +1230,25 @@ BookReader.prototype.exitFullScreen = function() {
1158
1230
  }
1159
1231
 
1160
1232
  this.isFullscreenActive = false;
1233
+ // Trigger fullscreen event immediately
1234
+ // so that book-nav can relay to web components
1235
+ this.trigger(BookReader.eventNames.fullscreenToggled);
1236
+
1161
1237
  this.updateBrClasses();
1238
+ this.animating = true;
1239
+ await new Promise((res => this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear', res)));
1240
+ this.resize();
1241
+
1242
+ if (this.activeMode instanceof Mode1Up) {
1243
+ this.activeMode.mode1UpLit.scale = this.activeMode.mode1UpLit.computeDefaultScale(this._models.book.getPage(this.currentIndex()));
1244
+ await this.activeMode.mode1UpLit.requestUpdate();
1245
+ }
1246
+
1247
+ this.animating = false;
1162
1248
 
1163
- this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear', () => {
1164
- this.resize();
1165
- });
1166
1249
  this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
1167
- this.trigger(BookReader.eventNames.fullscreenToggled);
1250
+ // Remove "?view=theater"
1251
+ this.trigger(BookReader.eventNames.fragmentChange);
1168
1252
  };
1169
1253
 
1170
1254
  /**
@@ -1195,11 +1279,9 @@ BookReader.prototype.updateFirstIndex = function(
1195
1279
  index,
1196
1280
  { suppressFragmentChange = false } = {}
1197
1281
  ) {
1198
- // Called multiple times when defaults contains "mode/1up",
1199
- // including after init(). Skip fragment change if no index change
1200
- if (this.firstIndex === index) {
1201
- suppressFragmentChange = true;
1202
- }
1282
+ // If there's no change, do nothing
1283
+ if (this.firstIndex === index) return;
1284
+
1203
1285
  this.firstIndex = index;
1204
1286
  if (!(this.suppressFragmentChange || suppressFragmentChange)) {
1205
1287
  this.trigger(BookReader.eventNames.fragmentChange);
@@ -1364,35 +1446,14 @@ BookReader.prototype.pruneUnusedImgs = function() {
1364
1446
  BookReader.prototype.prepareOnePageView = Mode1Up.prototype.prepare;
1365
1447
  exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'prepare', 'prepareOnePageView');
1366
1448
  /** @deprecated not used outside BookReader */
1367
- BookReader.prototype.drawLeafsOnePage = Mode1Up.prototype.drawLeafs;
1368
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'drawLeafs', 'drawLeafsOnePage');
1369
- /** @deprecated not used outside BookReader */
1370
1449
  BookReader.prototype.zoom1up = Mode1Up.prototype.zoom;
1371
1450
  exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'zoom', 'zoom1up');
1372
- /** @deprecated not used outside Mode1Up */
1373
- BookReader.prototype.onePageGetAutofitWidth = Mode1Up.prototype.getAutofitWidth;
1374
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'getAutofitWidth', 'onePageGetAutofitWidth');
1375
- /** @deprecated not used outside Mode1Up, BookReader */
1376
- BookReader.prototype.onePageGetAutofitHeight = Mode1Up.prototype.getAutofitHeight;
1377
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'getAutofitHeight', 'onePageGetAutofitHeight');
1378
- /** @deprecated not used outside Mode1Up, BookReader */
1379
- BookReader.prototype.onePageGetPageTop = Mode1Up.prototype.getPageTop;
1380
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'getPageTop', 'onePageGetPageTop');
1381
- /** @deprecated not used outside Mode1Up, BookReader */
1382
- BookReader.prototype.onePageCalculateReductionFactors = Mode1Up.prototype.calculateReductionFactors;
1383
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'calculateReductionFactors', 'onePageCalculateReductionFactors');
1384
1451
  /** @deprecated not used outside Mode1Up, BookReader */
1385
1452
  BookReader.prototype.resizePageView1up = Mode1Up.prototype.resizePageView;
1386
1453
  exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'resizePageView', 'resizePageView1up');
1387
1454
  /** @deprecated not used outside Mode1Up */
1388
1455
  BookReader.prototype.onePageCalculateViewDimensions = Mode1Up.prototype.calculateViewDimensions;
1389
1456
  exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'calculateViewDimensions', 'onePageCalculateViewDimensions');
1390
- /** @deprecated not used outside Mode1Up */
1391
- BookReader.prototype.centerX1up = Mode1Up.prototype.centerX;
1392
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'centerX', 'centerX1up');
1393
- /** @deprecated not used outside Mode1Up */
1394
- BookReader.prototype.centerY1up = Mode1Up.prototype.centerY;
1395
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'centerY', 'centerY1up');
1396
1457
 
1397
1458
  /************************/
1398
1459
  /** Mode2Up extensions **/
@@ -1409,9 +1470,6 @@ exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipFwdToIndex', 'flipFwdTo
1409
1470
  BookReader.prototype.setHilightCss2UP = Mode2Up.prototype.setHilightCss;
1410
1471
  exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setHilightCss', 'setHilightCss2UP');
1411
1472
  /** @deprecated not used outside Mode2Up */
1412
- BookReader.prototype.setClickHandler2UP = Mode2Up.prototype.setClickHandler;
1413
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setClickHandler', 'setClickHandler2UP');
1414
- /** @deprecated not used outside Mode2Up */
1415
1473
  BookReader.prototype.drawLeafsTwoPage = Mode2Up.prototype.drawLeafs;
1416
1474
  exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'drawLeafs', 'drawLeafsTwoPage');
1417
1475
  /** @deprecated not used outside BookReader */
@@ -1444,9 +1502,6 @@ exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipLeftToRight', 'flipLeft
1444
1502
  /** @deprecated unused outside BookReader, Mode2Up */
1445
1503
  BookReader.prototype.flipRightToLeft = Mode2Up.prototype.flipRightToLeft;
1446
1504
  exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipRightToLeft', 'flipRightToLeft');
1447
- /** @deprecated unused outside Mode2Up */
1448
- BookReader.prototype.setMouseHandlers2UP = Mode2Up.prototype.setMouseHandlers;
1449
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setMouseHandlers', 'setMouseHandlers2UP');
1450
1505
  /** @deprecated unused outside BookReader, Mode2Up */
1451
1506
  BookReader.prototype.prepareFlipLeftToRight = Mode2Up.prototype.prepareFlipLeftToRight;
1452
1507
  exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'prepareFlipLeftToRight', 'prepareFlipLeftToRight');
@@ -1527,15 +1582,6 @@ BookReader.prototype.stopFlipAnimations = function() {
1527
1582
  });
1528
1583
  };
1529
1584
 
1530
- /**
1531
- * Returns true if keyboard navigation should be disabled for the event
1532
- * @param {Event}
1533
- * @return {boolean}
1534
- */
1535
- BookReader.prototype.keyboardNavigationIsDisabled = function(event) {
1536
- return event.target.tagName == "INPUT";
1537
- };
1538
-
1539
1585
  /**
1540
1586
  * @template TClass extends { br: BookReader }
1541
1587
  * Helper method to expose a method onto BookReader from a composed class.
@@ -1566,9 +1612,6 @@ BookReader.prototype.updateViewModeButton = Navbar.prototype.updateViewModeButto
1566
1612
  exposeOverrideableMethod(Navbar, '_components.navbar', 'updateViewModeButton');
1567
1613
  BookReader.prototype.getNavPageNumString = Navbar.prototype.getNavPageNumString;
1568
1614
  exposeOverrideableMethod(Navbar, '_components.navbar', 'getNavPageNumString');
1569
- /** @deprecated */
1570
- BookReader.prototype.initEmbedNavbar = Navbar.prototype.initEmbed;
1571
- exposeOverrideableMethod(Navbar, '_components.navbar', 'initEmbed', 'initEmbedNavbar');
1572
1615
  /** @deprecated unused */
1573
1616
  BookReader.prototype.getNavPageNumHtml = getNavPageNumHtml;
1574
1617
  /** @deprecated unused outside this file */
@@ -1677,7 +1720,7 @@ BookReader.prototype.bindNavigationHandlers = function() {
1677
1720
 
1678
1721
  for (const control in navigationControls) {
1679
1722
  jIcons.filter(`.${control}`).on('click.bindNavigationHandlers', () => {
1680
- navigationControls[control]()
1723
+ navigationControls[control]();
1681
1724
  return false;
1682
1725
  });
1683
1726
  }
@@ -1707,7 +1750,7 @@ BookReader.prototype.bindNavigationHandlers = function() {
1707
1750
  $brNavCntlBtmEl.addClass('BRdn').removeClass('BRup');
1708
1751
  $brNavCntlTopEl.addClass('BRup').removeClass('BRdn');
1709
1752
  self.$('.BRnavCntlBtm.BRnavCntl').animate({height:'30px'});
1710
- self.$('.BRvavCntl').animate({opacity:1})
1753
+ self.$('.BRvavCntl').animate({opacity:1});
1711
1754
  }
1712
1755
  $.when.apply($, promises).done(function() {
1713
1756
  // Only do full resize in auto mode and need to recalc. size
@@ -1725,24 +1768,28 @@ BookReader.prototype.bindNavigationHandlers = function() {
1725
1768
  });
1726
1769
  }
1727
1770
  );
1728
- $brNavCntlBtmEl.mouseover(function() {
1729
- if ($(this).hasClass('BRup')) {
1730
- self.$('.BRnavCntl').animate({opacity:1},250);
1731
- }
1732
- }).mouseleave(function() {
1733
- if ($(this).hasClass('BRup')) {
1734
- self.$('.BRnavCntl').animate({opacity:.75},250);
1735
- }
1736
- });
1737
- $brNavCntlTopEl.mouseover(function() {
1738
- if ($(this).hasClass('BRdn')) {
1739
- self.$('.BRnavCntl').animate({opacity:1},250);
1740
- }
1741
- }).mouseleave(function() {
1742
- if ($(this).hasClass('BRdn')) {
1743
- self.$('.BRnavCntl').animate({opacity:.75},250);
1744
- }
1745
- });
1771
+ $brNavCntlBtmEl
1772
+ .on("mouseover", function() {
1773
+ if ($(this).hasClass('BRup')) {
1774
+ self.$('.BRnavCntl').animate({opacity:1},250);
1775
+ }
1776
+ })
1777
+ .on("mouseleave", function() {
1778
+ if ($(this).hasClass('BRup')) {
1779
+ self.$('.BRnavCntl').animate({opacity:.75},250);
1780
+ }
1781
+ });
1782
+ $brNavCntlTopEl
1783
+ .on("mouseover", function() {
1784
+ if ($(this).hasClass('BRdn')) {
1785
+ self.$('.BRnavCntl').animate({opacity:1},250);
1786
+ }
1787
+ })
1788
+ .on("mouseleave", function() {
1789
+ if ($(this).hasClass('BRdn')) {
1790
+ self.$('.BRnavCntl').animate({opacity:.75},250);
1791
+ }
1792
+ });
1746
1793
 
1747
1794
  this.initSwipeData();
1748
1795
 
@@ -1807,7 +1854,7 @@ BookReader.prototype.initSwipeData = function(clientX, clientY) {
1807
1854
  deltaX: 0,
1808
1855
  deltaY: 0,
1809
1856
  deltaT: 0
1810
- }
1857
+ };
1811
1858
  };
1812
1859
 
1813
1860
  BookReader.prototype.swipeMousedownHandler = function(event) {
@@ -1819,13 +1866,13 @@ BookReader.prototype.swipeMousedownHandler = function(event) {
1819
1866
  return !self.protected;
1820
1867
  }
1821
1868
 
1822
- $(event.target).bind('mouseout.swipe',
1869
+ $(event.target).on('mouseout.swipe',
1823
1870
  { 'br': self},
1824
1871
  self.swipeMouseupHandler
1825
- ).bind('mouseup.swipe',
1872
+ ).on('mouseup.swipe',
1826
1873
  { 'br': self},
1827
1874
  self.swipeMouseupHandler
1828
- ).bind('mousemove.swipe',
1875
+ ).on('mousemove.swipe',
1829
1876
  { 'br': self },
1830
1877
  self.swipeMousemoveHandler
1831
1878
  );
@@ -1895,7 +1942,7 @@ BookReader.prototype.swipeMouseupHandler = function(event) {
1895
1942
  _swipe.mightBeSwiping = false;
1896
1943
  _swipe.mightBeDragging = false;
1897
1944
 
1898
- $(event.target).unbind('mouseout.swipe').unbind('mouseup.swipe').unbind('mousemove.swipe');
1945
+ $(event.target).off('mouseout.swipe').off('mouseup.swipe').off('mousemove.swipe');
1899
1946
 
1900
1947
  if (_swipe.didSwipe || _swipe.didDrag) {
1901
1948
  // Swallow event if completed swipe gesture
@@ -1911,17 +1958,18 @@ BookReader.prototype.bindMozTouchHandlers = function() {
1911
1958
  var self = this;
1912
1959
 
1913
1960
  // Currently only want touch handlers in 2up
1914
- this.refs.$br.bind('MozTouchDown', function(event) {
1915
- if (this.mode == self.constMode2up) {
1916
- event.preventDefault();
1917
- }
1918
- })
1919
- .bind('MozTouchMove', function(event) {
1961
+ this.refs.$br
1962
+ .on('MozTouchDown', function(event) {
1920
1963
  if (this.mode == self.constMode2up) {
1921
1964
  event.preventDefault();
1922
1965
  }
1923
1966
  })
1924
- .bind('MozTouchUp', function(event) {
1967
+ .on('MozTouchMove', function(event) {
1968
+ if (this.mode == self.constMode2up) {
1969
+ event.preventDefault();
1970
+ }
1971
+ })
1972
+ .on('MozTouchUp', function(event) {
1925
1973
  if (this.mode == self.constMode2up) {
1926
1974
  event.preventDefault();
1927
1975
  }
@@ -2199,7 +2247,7 @@ BookReader.prototype._getPageURISrcset = function(index, reduce, rotate) {
2199
2247
  }
2200
2248
 
2201
2249
  return page.getURISrcSet(reduce, rotate);
2202
- }
2250
+ };
2203
2251
 
2204
2252
 
2205
2253
  /**
@@ -2225,21 +2273,37 @@ BookReader.prototype._getPageURI = function(index, reduce, rotate) {
2225
2273
  };
2226
2274
 
2227
2275
  /**
2228
- * @param {string}
2276
+ * @param {string} msg
2277
+ * @param {function|undefined} onCloseCallback
2229
2278
  */
2230
- BookReader.prototype.showProgressPopup = function(msg) {
2279
+ BookReader.prototype.showProgressPopup = function(msg, onCloseCallback) {
2231
2280
  if (this.popup) return;
2232
2281
 
2233
2282
  this.popup = document.createElement("div");
2234
2283
  $(this.popup).prop('className', 'BRprogresspopup');
2235
- var bar = document.createElement("div");
2284
+
2285
+ if (typeof(onCloseCallback) === 'function') {
2286
+ const closeButton = document.createElement('button');
2287
+ closeButton.setAttribute('title', 'close');
2288
+ closeButton.setAttribute('class', 'close-popup');
2289
+ const icon = document.createElement('span');
2290
+ icon.setAttribute('class', 'icon icon-close-dark');
2291
+ $(closeButton).append(icon);
2292
+ closeButton.addEventListener('click', () => {
2293
+ onCloseCallback();
2294
+ this.removeProgressPopup();
2295
+ });
2296
+ $(this.popup).append(closeButton);
2297
+ }
2298
+
2299
+ const bar = document.createElement("div");
2236
2300
  $(bar).css({
2237
2301
  height: '20px'
2238
2302
  }).prop('className', 'BRprogressbar');
2239
2303
  $(this.popup).append(bar);
2240
2304
 
2241
2305
  if (msg) {
2242
- var msgdiv = document.createElement("div");
2306
+ const msgdiv = document.createElement("div");
2243
2307
  msgdiv.innerHTML = msg;
2244
2308
  $(this.popup).append(msgdiv);
2245
2309
  }
@@ -2296,7 +2360,7 @@ BookReader.prototype.initUIStrings = function() {
2296
2360
  for (var icon in titles) {
2297
2361
  this.$(icon).prop('title', titles[icon]);
2298
2362
  }
2299
- }
2363
+ };
2300
2364
 
2301
2365
  /**
2302
2366
  * Reloads images. Useful when some images might have failed.
@@ -2327,7 +2391,7 @@ BookReader.prototype.getFooterHeight = function() {
2327
2391
  }
2328
2392
  }
2329
2393
  return 0;
2330
- }
2394
+ };
2331
2395
 
2332
2396
  // Basic Usage built-in Methods (can be overridden through options)
2333
2397
  // This implementation uses options.data value for populating BookReader
@@ -2339,6 +2403,7 @@ BookReader.prototype.getFooterHeight = function() {
2339
2403
  BookReader.prototype.paramsFromCurrent = function() {
2340
2404
  var params = {};
2341
2405
 
2406
+ // Path params
2342
2407
  var index = this.currentIndex();
2343
2408
  var pageNum = this._models.book.getPageNum(index);
2344
2409
  if ((pageNum === 0) || pageNum) {
@@ -2348,10 +2413,17 @@ BookReader.prototype.paramsFromCurrent = function() {
2348
2413
  params.index = index;
2349
2414
  params.mode = this.mode;
2350
2415
 
2416
+ // Unused params
2351
2417
  // $$$ highlight
2352
2418
  // $$$ region
2353
2419
 
2354
- // search
2420
+ // Querystring params
2421
+ // View
2422
+ const fullscreenView = 'theater';
2423
+ if (this.isFullscreenActive) {
2424
+ params.view = fullscreenView;
2425
+ }
2426
+ // Search
2355
2427
  if (this.enableSearch) {
2356
2428
  params.search = this.searchTerm;
2357
2429
  }
@@ -2422,7 +2494,7 @@ BookReader.prototype.paramsFromFragment = function(fragment) {
2422
2494
 
2423
2495
  // $$$ process /theme
2424
2496
  if (urlHash['theme'] != undefined) {
2425
- params.theme = urlHash['theme']
2497
+ params.theme = urlHash['theme'];
2426
2498
  }
2427
2499
  return params;
2428
2500
  };
@@ -2479,6 +2551,9 @@ BookReader.prototype.fragmentFromParams = function(params, urlMode = 'hash') {
2479
2551
  /**
2480
2552
  * Create, update querystring from the params object
2481
2553
  *
2554
+ * Handles:
2555
+ * view=
2556
+ * q=
2482
2557
  * @param {Object} params
2483
2558
  * @param {string} currQueryString
2484
2559
  * @param {string} [urlMode]
@@ -2490,21 +2565,30 @@ BookReader.prototype.queryStringFromParams = function(
2490
2565
  urlMode = 'hash'
2491
2566
  ) {
2492
2567
  const newParams = new URLSearchParams(currQueryString);
2568
+
2569
+ if (params.view) {
2570
+ // Set ?view=theater when fullscreen
2571
+ newParams.set('view', params.view);
2572
+ } else {
2573
+ // Remove
2574
+ newParams.delete('view');
2575
+ }
2576
+
2493
2577
  if (params.search && urlMode === 'history') {
2494
- newParams.set('q', params.search)
2578
+ newParams.set('q', params.search);
2495
2579
  }
2496
2580
  // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/toString
2497
2581
  // Note: This method returns the query string without the question mark.
2498
2582
  const result = newParams.toString();
2499
2583
  return result ? '?' + result : '';
2500
- }
2584
+ };
2501
2585
 
2502
2586
  /**
2503
2587
  * Helper to select within instance's elements
2504
2588
  */
2505
2589
  BookReader.prototype.$ = function(selector) {
2506
2590
  return this.refs.$br.find(selector);
2507
- }
2591
+ };
2508
2592
 
2509
2593
  /**
2510
2594
  * Polyfill for deprecated method