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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) 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 +32261 -2
  8. package/BookReader/BookReader.js.map +1 -1
  9. package/BookReader/ia-bookreader-bundle.js +15235 -0
  10. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  11. package/BookReader/icons/close-circle-dark.svg +1 -0
  12. package/BookReader/icons/voice.svg +1 -0
  13. package/BookReader/jquery-1.10.1.js +108 -2
  14. package/BookReader/plugins/plugin.archive_analytics.js +170 -1
  15. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  16. package/BookReader/plugins/plugin.autoplay.js +163 -1
  17. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  18. package/BookReader/plugins/plugin.chapters.js +333 -1
  19. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  20. package/BookReader/plugins/plugin.iframe.js +72 -1
  21. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  22. package/BookReader/plugins/plugin.mobile_nav.js +332 -1
  23. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
  24. package/BookReader/plugins/plugin.resume.js +241 -1
  25. package/BookReader/plugins/plugin.resume.js.map +1 -1
  26. package/BookReader/plugins/plugin.search.js +1261 -1
  27. package/BookReader/plugins/plugin.search.js.map +1 -1
  28. package/BookReader/plugins/plugin.text_selection.js +839 -1
  29. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  30. package/BookReader/plugins/plugin.tts.js +9115 -2
  31. package/BookReader/plugins/plugin.tts.js.map +1 -1
  32. package/BookReader/plugins/plugin.url.js +811 -1
  33. package/BookReader/plugins/plugin.url.js.map +1 -1
  34. package/BookReader/plugins/plugin.vendor-fullscreen.js +326 -1
  35. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  36. package/BookReader/webcomponents-bundle.js +412 -0
  37. package/BookReader/webcomponents-bundle.js.map +1 -0
  38. package/BookReaderDemo/BookReaderDemo.css +14 -1
  39. package/BookReaderDemo/IADemoBr.js +107 -0
  40. package/BookReaderDemo/demo-advanced.html +1 -1
  41. package/BookReaderDemo/demo-autoplay.html +1 -0
  42. package/BookReaderDemo/demo-embed-iframe-src.html +1 -0
  43. package/BookReaderDemo/demo-fullscreen-mobile.html +1 -0
  44. package/BookReaderDemo/demo-fullscreen.html +1 -0
  45. package/BookReaderDemo/demo-iiif.html +1 -0
  46. package/BookReaderDemo/demo-internetarchive.html +66 -18
  47. package/BookReaderDemo/demo-multiple.html +1 -0
  48. package/BookReaderDemo/demo-preview-pages.html +1 -0
  49. package/BookReaderDemo/demo-simple.html +1 -0
  50. package/BookReaderDemo/demo-vendor-fullscreen.html +1 -0
  51. package/BookReaderDemo/immersion-1up.html +1 -0
  52. package/BookReaderDemo/immersion-mode.html +1 -0
  53. package/BookReaderDemo/toggle_controls.html +1 -0
  54. package/BookReaderDemo/view_mode.html +1 -0
  55. package/BookReaderDemo/viewmode-cycle.html +1 -2
  56. package/CHANGELOG.md +114 -0
  57. package/babel.config.js +18 -0
  58. package/index.html +3 -0
  59. package/jsconfig.json +19 -0
  60. package/package.json +45 -27
  61. package/src/BookNavigator/assets/button-base.js +8 -1
  62. package/src/BookNavigator/assets/ia-logo.js +17 -0
  63. package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
  64. package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
  65. package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
  66. package/src/BookNavigator/assets/icon_volumes.js +11 -0
  67. package/src/BookNavigator/book-navigator.js +528 -0
  68. package/src/BookNavigator/bookmarks/bookmark-button.js +2 -1
  69. package/src/BookNavigator/bookmarks/bookmark-edit.js +2 -1
  70. package/src/BookNavigator/bookmarks/bookmarks-list.js +1 -0
  71. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +4 -9
  72. package/src/BookNavigator/bookmarks/bookmarks-provider.js +32 -11
  73. package/src/BookNavigator/bookmarks/ia-bookmarks.js +88 -43
  74. package/src/BookNavigator/downloads/downloads-provider.js +22 -16
  75. package/src/BookNavigator/downloads/downloads.js +16 -23
  76. package/src/BookNavigator/search/a-search-result.js +1 -0
  77. package/src/BookNavigator/search/search-provider.js +54 -20
  78. package/src/BookNavigator/search/search-results.js +7 -18
  79. package/src/BookNavigator/sharing.js +27 -0
  80. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +10 -12
  81. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +1 -0
  82. package/src/BookNavigator/volumes/volumes-provider.js +114 -0
  83. package/src/BookNavigator/volumes/volumes.js +189 -0
  84. package/src/BookReader/DebugConsole.js +3 -3
  85. package/src/BookReader/DragScrollable.js +233 -0
  86. package/src/BookReader/Mode1Up.js +50 -351
  87. package/src/BookReader/Mode1UpLit.js +434 -0
  88. package/src/BookReader/Mode2Up.js +94 -72
  89. package/src/BookReader/ModeSmoothZoom.js +177 -0
  90. package/src/BookReader/ModeThumb.js +16 -8
  91. package/src/BookReader/Navbar/Navbar.js +2 -31
  92. package/src/BookReader/PageContainer.js +47 -2
  93. package/src/BookReader/ReduceSet.js +1 -1
  94. package/src/BookReader/Toolbar/Toolbar.js +5 -5
  95. package/src/BookReader/options.js +10 -0
  96. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  97. package/src/BookReader/utils.js +68 -13
  98. package/src/BookReader.js +316 -232
  99. package/src/assets/icons/close-circle-dark.svg +1 -0
  100. package/src/assets/icons/voice.svg +1 -0
  101. package/src/css/BookReader.scss +0 -12
  102. package/src/css/_BRComponent.scss +1 -1
  103. package/src/css/_BRmain.scss +19 -24
  104. package/src/css/_BRnav.scss +4 -26
  105. package/src/css/_BRpages.scss +35 -0
  106. package/src/css/_BRsearch.scss +11 -215
  107. package/src/css/_TextSelection.scss +1 -17
  108. package/src/css/_controls.scss +16 -3
  109. package/src/css/_icons.scss +6 -0
  110. package/src/ia-bookreader/ia-bookreader.js +206 -0
  111. package/src/plugins/plugin.chapters.js +15 -18
  112. package/src/plugins/plugin.mobile_nav.js +11 -10
  113. package/src/plugins/plugin.resume.js +3 -3
  114. package/src/plugins/plugin.text_selection.js +17 -29
  115. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  116. package/src/plugins/search/plugin.search.js +113 -104
  117. package/src/plugins/search/view.js +48 -163
  118. package/src/plugins/tts/AbstractTTSEngine.js +7 -0
  119. package/src/plugins/tts/FestivalTTSEngine.js +2 -2
  120. package/src/plugins/tts/WebTTSEngine.js +5 -0
  121. package/src/plugins/tts/plugin.tts.js +67 -102
  122. package/src/plugins/url/UrlPlugin.js +184 -0
  123. package/src/plugins/url/plugin.url.js +220 -0
  124. package/{src → stat}/BookNavigator/BookModel.js +0 -0
  125. package/{src → stat}/BookNavigator/BookNavigator.js +151 -104
  126. package/stat/BookNavigator/assets/bookmark-colors.js +15 -0
  127. package/stat/BookNavigator/assets/button-base.js +61 -0
  128. package/stat/BookNavigator/assets/ia-logo.js +17 -0
  129. package/stat/BookNavigator/assets/icon_checkmark.js +6 -0
  130. package/stat/BookNavigator/assets/icon_close.js +3 -0
  131. package/stat/BookNavigator/assets/icon_sort_asc.js +5 -0
  132. package/stat/BookNavigator/assets/icon_sort_desc.js +5 -0
  133. package/stat/BookNavigator/assets/icon_sort_neutral.js +5 -0
  134. package/stat/BookNavigator/assets/icon_volumes.js +11 -0
  135. package/stat/BookNavigator/bookmarks/bookmark-button.js +64 -0
  136. package/stat/BookNavigator/bookmarks/bookmark-edit.js +215 -0
  137. package/stat/BookNavigator/bookmarks/bookmarks-list.js +285 -0
  138. package/stat/BookNavigator/bookmarks/bookmarks-loginCTA.js +28 -0
  139. package/stat/BookNavigator/bookmarks/bookmarks-provider.js +56 -0
  140. package/stat/BookNavigator/bookmarks/ia-bookmarks.js +523 -0
  141. package/{src → stat}/BookNavigator/br-fullscreen-mgr.js +1 -2
  142. package/stat/BookNavigator/delete-modal-actions.js +49 -0
  143. package/stat/BookNavigator/downloads/downloads-provider.js +72 -0
  144. package/stat/BookNavigator/downloads/downloads.js +139 -0
  145. package/stat/BookNavigator/provider-config.js +0 -0
  146. package/stat/BookNavigator/search/a-search-result.js +55 -0
  147. package/stat/BookNavigator/search/search-provider.js +180 -0
  148. package/stat/BookNavigator/search/search-results.js +360 -0
  149. package/stat/BookNavigator/sharing.js +31 -0
  150. package/stat/BookNavigator/visual-adjustments/visual-adjustments-provider.js +94 -0
  151. package/stat/BookNavigator/visual-adjustments/visual-adjustments.js +280 -0
  152. package/stat/BookNavigator/volumes/volumes-provider.js +83 -0
  153. package/stat/BookNavigator/volumes/volumes.js +178 -0
  154. package/stat/BookReader/BookModel.js +518 -0
  155. package/stat/BookReader/DebugConsole.js +54 -0
  156. package/stat/BookReader/DragScrollable.js +233 -0
  157. package/stat/BookReader/ImageCache.js +116 -0
  158. package/stat/BookReader/Mode1Up.js +102 -0
  159. package/stat/BookReader/Mode1UpLit.js +434 -0
  160. package/stat/BookReader/Mode2Up.js +1372 -0
  161. package/stat/BookReader/ModeSmoothZoom.js +177 -0
  162. package/stat/BookReader/ModeThumb.js +344 -0
  163. package/stat/BookReader/Navbar/Navbar.js +310 -0
  164. package/stat/BookReader/PageContainer.js +120 -0
  165. package/stat/BookReader/ReduceSet.js +26 -0
  166. package/stat/BookReader/Toolbar/Toolbar.js +384 -0
  167. package/stat/BookReader/events.js +20 -0
  168. package/stat/BookReader/options.js +324 -0
  169. package/stat/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  170. package/stat/BookReader/utils/classes.js +36 -0
  171. package/stat/BookReader/utils.js +240 -0
  172. package/stat/BookReader.js +2550 -0
  173. package/{src → stat}/BookReaderComponent/BookReaderComponent.js +16 -11
  174. package/stat/assets/icons/1up.svg +12 -0
  175. package/stat/assets/icons/2up.svg +15 -0
  176. package/stat/assets/icons/advance.svg +26 -0
  177. package/stat/assets/icons/chevron-right.svg +1 -0
  178. package/stat/assets/icons/close-circle-dark.svg +1 -0
  179. package/stat/assets/icons/close-circle.svg +1 -0
  180. package/stat/assets/icons/fullscreen.svg +17 -0
  181. package/stat/assets/icons/fullscreen_exit.svg +17 -0
  182. package/stat/assets/icons/hamburger.svg +15 -0
  183. package/stat/assets/icons/left-arrow.svg +12 -0
  184. package/stat/assets/icons/magnify-minus.svg +16 -0
  185. package/stat/assets/icons/magnify-plus.svg +17 -0
  186. package/stat/assets/icons/magnify.svg +15 -0
  187. package/stat/assets/icons/pause.svg +23 -0
  188. package/stat/assets/icons/play.svg +22 -0
  189. package/stat/assets/icons/playback-speed.svg +34 -0
  190. package/stat/assets/icons/read-aloud.svg +22 -0
  191. package/stat/assets/icons/review.svg +22 -0
  192. package/stat/assets/icons/thumbnails.svg +17 -0
  193. package/stat/assets/icons/voice.svg +1 -0
  194. package/stat/assets/icons/volume-full.svg +22 -0
  195. package/stat/assets/images/BRicons.png +0 -0
  196. package/stat/assets/images/BRicons.svg +94 -0
  197. package/stat/assets/images/BRicons_ia.png +0 -0
  198. package/stat/assets/images/back_pages.png +0 -0
  199. package/stat/assets/images/book_bottom_icon.png +0 -0
  200. package/stat/assets/images/book_down_icon.png +0 -0
  201. package/stat/assets/images/book_left_icon.png +0 -0
  202. package/stat/assets/images/book_leftmost_icon.png +0 -0
  203. package/stat/assets/images/book_right_icon.png +0 -0
  204. package/stat/assets/images/book_rightmost_icon.png +0 -0
  205. package/stat/assets/images/book_top_icon.png +0 -0
  206. package/stat/assets/images/book_up_icon.png +0 -0
  207. package/stat/assets/images/books_graphic.svg +177 -0
  208. package/stat/assets/images/booksplit.png +0 -0
  209. package/stat/assets/images/control_pause_icon.png +0 -0
  210. package/stat/assets/images/control_play_icon.png +0 -0
  211. package/stat/assets/images/embed_icon.png +0 -0
  212. package/stat/assets/images/icon-home-ia.png +0 -0
  213. package/stat/assets/images/icon_OL-logo-xs.png +0 -0
  214. package/stat/assets/images/icon_alert-xs.png +0 -0
  215. package/stat/assets/images/icon_book.svg +12 -0
  216. package/stat/assets/images/icon_bookmark.svg +12 -0
  217. package/stat/assets/images/icon_close-pop.png +0 -0
  218. package/stat/assets/images/icon_download.png +0 -0
  219. package/stat/assets/images/icon_gear.svg +14 -0
  220. package/stat/assets/images/icon_hamburger.svg +20 -0
  221. package/stat/assets/images/icon_home.png +0 -0
  222. package/stat/assets/images/icon_home.svg +21 -0
  223. package/stat/assets/images/icon_home_ia.png +0 -0
  224. package/stat/assets/images/icon_indicator.png +0 -0
  225. package/stat/assets/images/icon_info.svg +11 -0
  226. package/stat/assets/images/icon_one_page.svg +8 -0
  227. package/stat/assets/images/icon_pause.svg +1 -0
  228. package/stat/assets/images/icon_play.svg +1 -0
  229. package/stat/assets/images/icon_playback-rate.svg +15 -0
  230. package/stat/assets/images/icon_return.png +0 -0
  231. package/stat/assets/images/icon_search_button.svg +8 -0
  232. package/stat/assets/images/icon_share.svg +9 -0
  233. package/stat/assets/images/icon_skip-ahead.svg +6 -0
  234. package/stat/assets/images/icon_skip-back.svg +13 -0
  235. package/stat/assets/images/icon_speaker.svg +18 -0
  236. package/stat/assets/images/icon_speaker_open.svg +10 -0
  237. package/stat/assets/images/icon_thumbnails.svg +12 -0
  238. package/stat/assets/images/icon_toc.svg +5 -0
  239. package/stat/assets/images/icon_two_pages.svg +9 -0
  240. package/stat/assets/images/icon_zoomer.png +0 -0
  241. package/stat/assets/images/loading.gif +0 -0
  242. package/stat/assets/images/logo_icon.png +0 -0
  243. package/stat/assets/images/marker_chap-off.png +0 -0
  244. package/stat/assets/images/marker_chap-off.svg +11 -0
  245. package/stat/assets/images/marker_chap-off_ia.png +0 -0
  246. package/stat/assets/images/marker_chap-on.png +0 -0
  247. package/stat/assets/images/marker_chap-on.svg +11 -0
  248. package/stat/assets/images/marker_srch-on.svg +11 -0
  249. package/stat/assets/images/marker_srchchap-off.png +0 -0
  250. package/stat/assets/images/marker_srchchap-on.png +0 -0
  251. package/stat/assets/images/nav_control-dn.png +0 -0
  252. package/stat/assets/images/nav_control-dn_ia.png +0 -0
  253. package/stat/assets/images/nav_control-up.png +0 -0
  254. package/stat/assets/images/nav_control-up_ia.png +0 -0
  255. package/stat/assets/images/nav_control.png +0 -0
  256. package/stat/assets/images/one_page_mode_icon.png +0 -0
  257. package/stat/assets/images/paper-badge.png +0 -0
  258. package/stat/assets/images/print_icon.png +0 -0
  259. package/stat/assets/images/progressbar.gif +0 -0
  260. package/stat/assets/images/right_edges.png +0 -0
  261. package/stat/assets/images/slider.png +0 -0
  262. package/stat/assets/images/slider_ia.png +0 -0
  263. package/stat/assets/images/thumbnail_mode_icon.png +0 -0
  264. package/stat/assets/images/transparent.png +0 -0
  265. package/stat/assets/images/two_page_mode_icon.png +0 -0
  266. package/stat/assets/images/zoom_in_icon.png +0 -0
  267. package/stat/assets/images/zoom_out_icon.png +0 -0
  268. package/stat/css/BookReader.scss +89 -0
  269. package/stat/css/_BRBookmarks.scss +29 -0
  270. package/stat/css/_BRComponent.scss +13 -0
  271. package/stat/css/_BRfloat.scss +197 -0
  272. package/stat/css/_BRicon.scss +48 -0
  273. package/stat/css/_BRmain.scss +251 -0
  274. package/stat/css/_BRnav.scss +359 -0
  275. package/stat/css/_BRpages.scss +139 -0
  276. package/stat/css/_BRsearch.scss +226 -0
  277. package/stat/css/_BRtoolbar.scss +84 -0
  278. package/stat/css/_BRvendor.scss +5 -0
  279. package/stat/css/_MobileNav.scss +194 -0
  280. package/stat/css/_TextSelection.scss +32 -0
  281. package/stat/css/_colorbox.scss +52 -0
  282. package/stat/css/_controls.scss +253 -0
  283. package/stat/css/_icons.scss +121 -0
  284. package/stat/jquery-wrapper.js +4 -0
  285. package/stat/plugins/plugin.archive_analytics.js +86 -0
  286. package/stat/plugins/plugin.autoplay.js +129 -0
  287. package/stat/plugins/plugin.chapters.js +248 -0
  288. package/stat/plugins/plugin.iframe.js +48 -0
  289. package/stat/plugins/plugin.mobile_nav.js +288 -0
  290. package/stat/plugins/plugin.resume.js +68 -0
  291. package/stat/plugins/plugin.text_selection.js +291 -0
  292. package/{src → stat}/plugins/plugin.url.js +4 -4
  293. package/stat/plugins/plugin.vendor-fullscreen.js +247 -0
  294. package/stat/plugins/search/plugin.search.js +439 -0
  295. package/stat/plugins/search/view.js +439 -0
  296. package/stat/plugins/tts/AbstractTTSEngine.js +249 -0
  297. package/stat/plugins/tts/FestivalTTSEngine.js +169 -0
  298. package/stat/plugins/tts/PageChunk.js +107 -0
  299. package/stat/plugins/tts/PageChunkIterator.js +163 -0
  300. package/stat/plugins/tts/WebTTSEngine.js +357 -0
  301. package/stat/plugins/tts/plugin.tts.js +357 -0
  302. package/stat/plugins/tts/tooltip_dict.js +15 -0
  303. package/stat/plugins/tts/utils.js +91 -0
  304. package/stat/util/browserSniffing.js +30 -0
  305. package/stat/util/debouncer.js +26 -0
  306. package/stat/util/docCookies.js +67 -0
  307. package/stat/util/strings.js +34 -0
  308. package/tests/e2e/README.md +37 -0
  309. package/tests/e2e/autoplay.test.js +2 -2
  310. package/tests/e2e/base.test.js +5 -7
  311. package/tests/e2e/helpers/base.js +8 -3
  312. package/tests/e2e/helpers/debug.js +1 -1
  313. package/tests/e2e/helpers/desktopSearch.js +1 -1
  314. package/tests/e2e/helpers/mobileSearch.js +3 -3
  315. package/tests/e2e/helpers/params.js +17 -0
  316. package/tests/e2e/rightToLeft.test.js +4 -5
  317. package/tests/e2e/viewmode.test.js +30 -31
  318. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +3 -3
  319. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
  320. package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
  321. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  322. package/tests/jest/BookReader/Mode1UpLit.test.js +87 -0
  323. package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +5 -7
  324. package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
  325. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  326. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
  327. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +74 -2
  328. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  329. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  330. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  331. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  332. package/tests/jest/BookReader/utils.test.js +136 -0
  333. package/tests/jest/BookReader.keyboard.test.js +190 -0
  334. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  335. package/tests/{BookReader.test.js → jest/BookReader.test.js} +20 -4
  336. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  337. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +2 -2
  338. package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +8 -8
  339. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  340. package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
  341. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  342. package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +14 -24
  343. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  344. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +12 -5
  345. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +6 -6
  346. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +3 -3
  347. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  348. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  349. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  350. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +1 -1
  351. package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -3
  352. package/tests/jest/plugins/url/UrlPlugin.test.js +175 -0
  353. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
  354. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  355. package/tests/{util → jest/util}/docCookies.test.js +1 -1
  356. package/tests/{util → jest/util}/strings.test.js +1 -1
  357. package/tests/{utils.js → jest/utils.js} +38 -0
  358. package/tests/karma/BookNavigator/book-navigator.test.js +485 -0
  359. package/tests/karma/BookNavigator/bookmarks/bookmark-button.test.js +44 -0
  360. package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +1 -3
  361. package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +1 -2
  362. package/tests/karma/BookNavigator/downloads/downloads-provider.test.js +67 -0
  363. package/tests/karma/BookNavigator/downloads/downloads.test.js +54 -0
  364. package/tests/karma/BookNavigator/search/search-provider.test.js +123 -0
  365. package/tests/karma/BookNavigator/{search-results.test.js → search/search-results.test.js} +1 -4
  366. package/tests/karma/BookNavigator/sharing/sharing-provider.test.js +49 -0
  367. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -2
  368. package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +184 -0
  369. package/tests/karma/BookNavigator/volumes/volumes.test.js +98 -0
  370. package/webpack.config.js +11 -5
  371. package/.babelrc +0 -12
  372. package/.dependabot/config.yml +0 -6
  373. package/.testcaferc.json +0 -5
  374. package/BookReader/BookReader.js.LICENSE.txt +0 -72
  375. package/BookReader/bookreader-component-bundle.js +0 -1450
  376. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  377. package/BookReader/bookreader-component-bundle.js.map +0 -1
  378. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  379. package/BookReader/plugins/plugin.menu_toggle.js +0 -2
  380. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  381. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +0 -27
  382. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  383. package/src/BookNavigator/assets/book-loader.js +0 -27
  384. package/src/ItemNavigator/ItemNavigator.js +0 -372
  385. package/src/ItemNavigator/providers/sharing.js +0 -29
  386. package/src/dragscrollable-br.js +0 -261
  387. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  388. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  389. package/tests/BookReader/Mode1Up.test.js +0 -164
  390. package/tests/BookReader/utils.test.js +0 -109
  391. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -0,0 +1,434 @@
1
+ // @ts-check
2
+ import { customElement, html, LitElement, property, query } from 'lit-element';
3
+ import { styleMap } from 'lit-html/directives/style-map';
4
+ import { ModeSmoothZoom } from './ModeSmoothZoom';
5
+ import { arrChanged, calcScreenDPI, genToArray, sum, throttle } from './utils';
6
+ import { HTMLDimensionsCacher } from "./utils/HTMLDimensionsCacher";
7
+ /** @typedef {import('./BookModel').BookModel} BookModel */
8
+ /** @typedef {import('./BookModel').PageIndex} PageIndex */
9
+ /** @typedef {import('./BookModel').PageModel} PageModel */
10
+ /** @typedef {import('./ModeSmoothZoom').SmoothZoomable} SmoothZoomable */
11
+ /** @typedef {import('./PageContainer').PageContainer} PageContainer */
12
+ /** @typedef {import('../BookReader').default} BookReader */
13
+
14
+ // I _have_ to make this globally public, otherwise it won't let me call
15
+ // it's constructor :/
16
+ /** @implements {SmoothZoomable} */
17
+ @customElement('br-mode-1up')
18
+ export class Mode1UpLit extends LitElement {
19
+ /****************************************/
20
+ /************** PROPERTIES **************/
21
+ /****************************************/
22
+
23
+ /** @type {BookReader} */
24
+ br;
25
+
26
+ /************** BOOK-RELATED PROPERTIES **************/
27
+
28
+ /** @type {BookModel} */
29
+ @property({ type: Object })
30
+ book;
31
+
32
+ /** @type {PageModel[]} */
33
+ @property({ type: Array })
34
+ pages = [];
35
+
36
+ /** @type {Record<PageIndex, number>} in world coordinates (inches) */
37
+ @property({ type: Object })
38
+ pageTops = {};
39
+
40
+ /************** SCALE-RELATED PROPERTIES **************/
41
+
42
+ /** @private */
43
+ screenDPI = calcScreenDPI();
44
+
45
+ /**
46
+ * How much smaller the rendered pages are than the real-world item
47
+ *
48
+ * Mode1Up doesn't use the br.reduce because it is DPI aware. The reduction factor
49
+ * of a given leaf can change (since leaves can have different DPIs), but the real-world
50
+ * reduction is constant throughout.
51
+ */
52
+ realWorldReduce = 1;
53
+
54
+ @property({ type: Number })
55
+ scale = 1;
56
+ /** Position (in unit-less, [0, 1] coordinates) in client to scale around */
57
+ @property({ type: Object })
58
+ scaleCenter = { x: 0.5, y: 0.5 };
59
+
60
+ /************** VIRTUAL-SCROLLING PROPERTIES **************/
61
+
62
+ /** in world coordinates (inches) */
63
+ @property({ type: Object })
64
+ visibleRegion = {
65
+ top: 0,
66
+ left: 0,
67
+ width: 100,
68
+ height: 100,
69
+ };
70
+
71
+ /** @type {PageModel[]} */
72
+ @property({ type: Array, hasChanged: arrChanged })
73
+ visiblePages = [];
74
+
75
+ /** @type {PageModel[]} */
76
+ @property({ type: Array })
77
+ renderedPages = [];
78
+
79
+ /** @type {Record<PageIndex, PageContainer>} position in inches */
80
+ pageContainerCache = {};
81
+
82
+ /************** WORLD-RELATED PROPERTIES **************/
83
+ /**
84
+ * The world is an imaginary giant document that contains all the pages.
85
+ * The "world"'s size is used to determine how long the scroll bar should
86
+ * be, for example.
87
+ */
88
+
89
+ /** @type {HTMLElement} */
90
+ @query('.br-mode-1up__world')
91
+ $world;
92
+
93
+ worldDimensions = { width: 100, height: 100 };
94
+
95
+ get worldStyle() {
96
+ const wToR = this.worldUnitsToRenderedPixels;
97
+ return {
98
+ width: wToR(this.worldDimensions.width) + "px",
99
+ height: wToR(this.worldDimensions.height) + "px",
100
+ };
101
+ }
102
+
103
+ /** @type {HTMLElement} */
104
+ get $container() { return this; }
105
+
106
+ /** @type {HTMLElement} */
107
+ @query('.br-mode-1up__visible-world')
108
+ $visibleWorld;
109
+
110
+ /************** DOM-RELATED PROPERTIES **************/
111
+
112
+ /** @type {HTMLDimensionsCacher} Cache things like clientWidth to reduce repaints */
113
+ htmlDimensionsCacher = new HTMLDimensionsCacher(this);
114
+
115
+ smoothZoomer = new ModeSmoothZoom(this);
116
+
117
+ /************** CONSTANT PROPERTIES **************/
118
+
119
+ /** Vertical space between/around the pages in inches */
120
+ SPACING_IN = 0.2;
121
+
122
+ /** How much to zoom when zoom button pressed */
123
+ ZOOM_FACTOR = 1.1;
124
+
125
+ /****************************************/
126
+ /************** PUBLIC API **************/
127
+ /****************************************/
128
+
129
+ /************** MAIN PUBLIC METHODS **************/
130
+
131
+ /**
132
+ * @param {PageIndex} index
133
+ */
134
+ jumpToIndex(index, { smooth = false } = {}) {
135
+ if (smooth) {
136
+ this.style.scrollBehavior = 'smooth';
137
+ }
138
+ this.scrollTop = this.worldUnitsToVisiblePixels(this.pageTops[index] - this.SPACING_IN / 2);
139
+ // TODO: Also h center?
140
+ if (smooth) {
141
+ setTimeout(() => this.style.scrollBehavior = '', 100);
142
+ }
143
+ }
144
+
145
+ zoomIn() {
146
+ this.scale *= this.ZOOM_FACTOR;
147
+ }
148
+
149
+ zoomOut() {
150
+ this.scale *= 1 / this.ZOOM_FACTOR;
151
+ }
152
+
153
+ /********************************************/
154
+ /************** INTERNAL STUFF **************/
155
+ /********************************************/
156
+
157
+ /************** LIFE CYCLE **************/
158
+
159
+ /**
160
+ * @param {BookModel} book
161
+ * @param {BookReader} br
162
+ */
163
+ constructor(book, br) {
164
+ super();
165
+ this.book = book;
166
+
167
+ /** @type {BookReader} */
168
+ this.br = br;
169
+ }
170
+
171
+ /** @override */
172
+ firstUpdated(changedProps) {
173
+ super.firstUpdated(changedProps);
174
+ this.htmlDimensionsCacher.updateClientSizes();
175
+ this.smoothZoomer.attach();
176
+ }
177
+
178
+ /**
179
+ * @param {PageIndex} startIndex
180
+ */
181
+ initFirstRender(startIndex) {
182
+ const page = this.book.getPage(startIndex);
183
+ this.scale = this.computeDefaultScale(page);
184
+ }
185
+
186
+ /** @override */
187
+ updated(changedProps) {
188
+ // this.X is the new value
189
+ // changedProps.get('X') is the old value
190
+ if (changedProps.has('book')) {
191
+ this.pages = genToArray(this.book.pagesIterator({ combineConsecutiveUnviewables: true }));
192
+ }
193
+ if (changedProps.has('pages')) {
194
+ this.worldDimensions = this.computeWorldDimensions();
195
+ this.pageTops = this.computePageTops(this.pages, this.SPACING_IN);
196
+ }
197
+ if (changedProps.has('visibleRegion')) {
198
+ this.visiblePages = this.computeVisiblePages();
199
+ }
200
+ if (changedProps.has('visiblePages')) {
201
+ this.throttledUpdateRenderedPages();
202
+ this.br.displayedIndices = this.visiblePages.map(p => p.index);
203
+ this.br.updateFirstIndex(this.br.displayedIndices[0]);
204
+ this.br.updateNavIndexThrottled();
205
+ }
206
+ if (changedProps.has('scale')) {
207
+ const oldVal = changedProps.get('scale');
208
+ // Need to set this scale to actually scale the pages
209
+ this.$visibleWorld.style.transform = `scale(${this.scale})`;
210
+ this.updateViewportOnZoom(this.scale, oldVal);
211
+ // Need to set this scale to update the world size, so the scrollbar gets the correct size
212
+ this.$world.style.transform = `scale(${this.scale})`;
213
+ }
214
+ }
215
+
216
+ /** @override */
217
+ connectedCallback() {
218
+ super.connectedCallback();
219
+ this.htmlDimensionsCacher.attachResizeListener();
220
+ this.attachScrollListeners();
221
+ this.smoothZoomer.attach();
222
+ }
223
+
224
+ /** @override */
225
+ disconnectedCallback() {
226
+ this.htmlDimensionsCacher.detachResizeListener();
227
+ this.detachScrollListeners();
228
+ this.smoothZoomer.detach();
229
+ super.disconnectedCallback();
230
+ }
231
+
232
+ /************** LIT CONFIGS **************/
233
+
234
+ /** @override */
235
+ createRenderRoot() {
236
+ // Disable shadow DOM; that would require a huge rejiggering of CSS
237
+ return this;
238
+ }
239
+
240
+ /************** COORDINATE SPACE CONVERTERS **************/
241
+ /**
242
+ * There are a few different "coordinate spaces" at play in BR:
243
+ * (1) World units: i.e. inches. Unless otherwise stated, all computations
244
+ * are done in world units.
245
+ * (2) Rendered Pixels: i.e. img.width = '300'. Note this does _not_ take
246
+ * into account zoom scaling.
247
+ * (3) Visible Pixels: Just rendered pixels, but taking into account scaling.
248
+ */
249
+
250
+ worldUnitsToRenderedPixels = (/** @type {number} */inches) => inches * this.screenDPI / this.realWorldReduce;
251
+ renderedPixelsToWorldUnits = (/** @type {number} */px) => px * this.realWorldReduce / this.screenDPI;
252
+
253
+ renderedPixelsToVisiblePixels = (/** @type {number} */px) => px * this.scale;
254
+ visiblePixelsToRenderedPixels = (/** @type {number} */px) => px / this.scale;
255
+
256
+ worldUnitsToVisiblePixels = (/** @type {number} */px) => this.renderedPixelsToVisiblePixels(this.worldUnitsToRenderedPixels(px));
257
+ visiblePixelsToWorldUnits = (/** @type {number} */px) => this.renderedPixelsToWorldUnits(this.visiblePixelsToRenderedPixels(px));
258
+
259
+ /************** RENDERING **************/
260
+
261
+ /** @override */
262
+ render() {
263
+ return html`
264
+ <div class="br-mode-1up__world" style=${styleMap(this.worldStyle)}></div>
265
+ <div class="br-mode-1up__visible-world">
266
+ ${this.renderedPages.map(p => this.renderPage(p))}
267
+ </div>`;
268
+ }
269
+
270
+ /** @param {PageModel} page */
271
+ createPageContainer = (page) => {
272
+ return this.pageContainerCache[page.index] || (
273
+ this.pageContainerCache[page.index] = (
274
+ // @ts-ignore I know it's protected, TS! But Mode1Up and BookReader are friends.
275
+ this.br._createPageContainer(page.index)
276
+ )
277
+ );
278
+ }
279
+
280
+ /** @param {PageModel} page */
281
+ renderPage = (page) => {
282
+ const wToR = this.worldUnitsToRenderedPixels;
283
+ const wToV = this.worldUnitsToVisiblePixels;
284
+ const containerWidth = this.visiblePixelsToWorldUnits(this.htmlDimensionsCacher.clientWidth);
285
+
286
+ const width = wToR(page.widthInches);
287
+ const height = wToR(page.heightInches);
288
+ const left = Math.max(this.SPACING_IN, (containerWidth - page.widthInches) / 2);
289
+ const top = this.pageTops[page.index];
290
+
291
+ const transform = `translate(${wToR(left)}px, ${wToR(top)}px)`;
292
+ const pageContainerEl = this.createPageContainer(page)
293
+ .update({
294
+ dimensions: {
295
+ width,
296
+ height,
297
+ top: 0,
298
+ left: 0,
299
+ },
300
+ reduce: page.width / wToV(page.widthInches),
301
+ }).$container[0];
302
+
303
+ pageContainerEl.style.transform = transform;
304
+ return pageContainerEl;
305
+ }
306
+
307
+ /************** VIRTUAL SCROLLING LOGIC **************/
308
+
309
+ updateVisibleRegion = () => {
310
+ const { scrollTop, scrollLeft } = this;
311
+ // clientHeight excludes scrollbars, which is good.
312
+ const clientWidth = this.htmlDimensionsCacher.clientWidth;
313
+ const clientHeight = this.htmlDimensionsCacher.clientHeight;
314
+
315
+ // Note: scrollTop, and clientWidth all are in visible space;
316
+ // i.e. they are affects by the CSS transforms.
317
+
318
+ const vToW = this.visiblePixelsToWorldUnits;
319
+ this.visibleRegion = {
320
+ top: vToW(scrollTop),
321
+ height: vToW(clientHeight),
322
+ // TODO: These are very likely wrong
323
+ left: vToW(scrollLeft),
324
+ width: vToW(clientWidth),
325
+ };
326
+ }
327
+
328
+ /**
329
+ * @returns {PageModel[]}
330
+ */
331
+ computeRenderedPages() {
332
+ // Also render 1 page before/after
333
+ // @ts-ignore TS doesn't understand the filtering out of null values
334
+ return [
335
+ this.visiblePages[0]?.prev,
336
+ ...this.visiblePages,
337
+ this.visiblePages[this.visiblePages.length - 1]?.next,
338
+ ]
339
+ .filter(p => p)
340
+ // Never render more than 10 pages! Usually means something is wrong
341
+ .slice(0, 10);
342
+ }
343
+
344
+ throttledUpdateRenderedPages = throttle(() => {
345
+ this.renderedPages = this.computeRenderedPages();
346
+ this.requestUpdate();
347
+ }, 100, null)
348
+
349
+ /**
350
+ * @param {PageModel[]} pages
351
+ * @param {number} spacing
352
+ */
353
+ computePageTops(pages, spacing) {
354
+ /** @type {{ [pageIndex: string]: number }} */
355
+ const result = {};
356
+ let top = spacing;
357
+ for (const page of pages) {
358
+ result[page.index] = top;
359
+ top += page.heightInches + spacing;
360
+ }
361
+ return result;
362
+ }
363
+
364
+ /**
365
+ * @param {PageModel} page
366
+ * @returns {number}
367
+ */
368
+ computeDefaultScale(page) {
369
+ // Default to real size if it fits, otherwise default to full width
370
+ const containerWidthIn = this.visiblePixelsToWorldUnits(this.htmlDimensionsCacher.clientWidth);
371
+ return Math.min(1, containerWidthIn / (page.widthInches + 2 * this.SPACING_IN)) || 1;
372
+ }
373
+
374
+ computeWorldDimensions() {
375
+ return {
376
+ width: Math.max(...this.pages.map(p => p.widthInches)) + 2 * this.SPACING_IN,
377
+ height:
378
+ sum(this.pages.map(p => p.heightInches)) +
379
+ (this.pages.length + 1) * this.SPACING_IN,
380
+ };
381
+ }
382
+
383
+ computeVisiblePages() {
384
+ return this.pages.filter(page => {
385
+ const PT = this.pageTops[page.index];
386
+ const PB = PT + page.heightInches;
387
+
388
+ const VT = this.visibleRegion.top;
389
+ const VB = VT + this.visibleRegion.height;
390
+ return PT <= VB && PB >= VT;
391
+ });
392
+ }
393
+
394
+ /************** ZOOMING LOGIC **************/
395
+
396
+ /**
397
+ * @param {number} newScale
398
+ * @param {number} oldScale
399
+ */
400
+ updateViewportOnZoom(newScale, oldScale) {
401
+ const container = this;
402
+ const { scrollTop: T, scrollLeft: L } = container;
403
+ const W = this.htmlDimensionsCacher.clientWidth;
404
+ const H = this.htmlDimensionsCacher.clientHeight;
405
+
406
+ // Scale factor change
407
+ const F = newScale / oldScale;
408
+
409
+ // Where in the viewport the zoom is centered on
410
+ const XPOS = this.scaleCenter.x;
411
+ const YPOS = this.scaleCenter.y;
412
+ const oldCenter = {
413
+ x: L + XPOS * W,
414
+ y: T + YPOS * H,
415
+ };
416
+ const newCenter = {
417
+ x: F * oldCenter.x,
418
+ y: F * oldCenter.y,
419
+ };
420
+ container.scrollTop = newCenter.y - YPOS * H;
421
+ container.scrollLeft = newCenter.x - XPOS * W;
422
+ this.updateVisibleRegion();
423
+ }
424
+
425
+ /************** INPUT HANDLERS **************/
426
+
427
+ attachScrollListeners = () => {
428
+ this.addEventListener("scroll", this.updateVisibleRegion, { passive: true });
429
+ }
430
+
431
+ detachScrollListeners = () => {
432
+ this.removeEventListener("scroll", this.updateVisibleRegion);
433
+ }
434
+ }
@@ -1,16 +1,20 @@
1
1
  // @ts-check
2
2
  // effect.js gives acces to extra easing function (e.g. easeInSine)
3
3
  import 'jquery-ui/ui/effect.js';
4
- import '../dragscrollable-br.js';
5
4
  import { clamp } from './utils.js';
6
5
  import { EVENTS } from './events.js';
6
+ import { ModeSmoothZoom } from "./ModeSmoothZoom.js";
7
+ import { HTMLDimensionsCacher } from './utils/HTMLDimensionsCacher.js';
8
+ import { DragScrollable } from './DragScrollable.js';
7
9
 
8
10
  /** @typedef {import('../BookReader.js').default} BookReader */
9
11
  /** @typedef {import('./BookModel.js').BookModel} BookModel */
10
12
  /** @typedef {import('./BookModel.js').PageIndex} PageIndex */
11
13
  /** @typedef {import('./options.js').BookReaderOptions} BookReaderOptions */
12
14
  /** @typedef {import('./PageContainer.js').PageContainer} PageContainer */
15
+ /** @typedef {import('./ModeSmoothZoom').SmoothZoomable} SmoothZoomable */
13
16
 
17
+ /** @implements {SmoothZoomable} */
14
18
  export class Mode2Up {
15
19
  /**
16
20
  * @param {BookReader} br
@@ -27,6 +31,25 @@ export class Mode2Up {
27
31
 
28
32
  /** @type {{ [index: number]: PageContainer }} */
29
33
  this.pageContainers = {};
34
+
35
+ /** @type {ModeSmoothZoom} */
36
+ this.smoothZoomer = null;
37
+ this._scale = 1;
38
+ this.scaleCenter = { x: 0.5, y: 0.5 };
39
+ }
40
+
41
+ get $container() {
42
+ return this.br.refs.$brContainer[0];
43
+ }
44
+ get $visibleWorld() {
45
+ return this.br.refs.$brTwoPageView?.[0];
46
+ }
47
+
48
+ get scale() { return this._scale; }
49
+ set scale(newVal) {
50
+ this.$visibleWorld.style.transform = `scale(${newVal})`;
51
+ this.updateViewportOnZoom(newVal, this._scale);
52
+ this._scale = newVal;
30
53
  }
31
54
 
32
55
  /**
@@ -42,18 +65,6 @@ export class Mode2Up {
42
65
  }
43
66
  }
44
67
 
45
- /**
46
- * @template T
47
- * @param {HTMLElement} element
48
- * @param {T} data
49
- * @param {function(HTMLElement, { data: T }): void} handler
50
- */
51
- setClickHandler(element, data, handler) {
52
- $(element).unbind('mouseup').bind('mouseup', data, function(e) {
53
- handler(this, e);
54
- });
55
- }
56
-
57
68
  /**
58
69
  * Draws book spread,
59
70
  * sets event handlers,
@@ -74,7 +85,6 @@ export class Mode2Up {
74
85
  .appendTo($twoPageViewEl);
75
86
 
76
87
  this.displayedIndices = [this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR];
77
- this.setMouseHandlers();
78
88
  this.br.displayedIndices = this.displayedIndices;
79
89
  this.br.updateToolbarZoom(this.br.reduce);
80
90
  this.br.trigger('pageChanged');
@@ -176,13 +186,22 @@ export class Mode2Up {
176
186
 
177
187
  // Add the two page view
178
188
  // $$$ Can we get everything set up and then append?
179
- const $twoPageViewEl = $('<div class="BRtwopageview"></div>');
180
- this.br.refs.$brTwoPageView = $twoPageViewEl;
189
+ this.br.refs.$brTwoPageView = this.br.refs.$brTwoPageView || $('<div class="BRtwopageview"></div>');
190
+ const $twoPageViewEl = this.br.refs.$brTwoPageView;
191
+ $twoPageViewEl.empty();
192
+ $twoPageViewEl[0].style.transformOrigin = '0 0';
181
193
  this.br.refs.$brContainer.append($twoPageViewEl);
182
194
 
183
195
  // Attaches to first child, so must come after we add the page view
184
- this.br.refs.$brContainer.dragscrollable({preventDefault:true});
185
- this.br.bindGestures(this.br.refs.$brContainer);
196
+ this.dragScrollable = this.dragScrollable || new DragScrollable(this.br.refs.$brContainer[0], {
197
+ preventDefault: true,
198
+ // Only handle mouse events; let browser/HammerJS handle touch
199
+ dragstart: 'mousedown',
200
+ dragcontinue: 'mousemove',
201
+ dragend: 'mouseup',
202
+ });
203
+
204
+ this.attachMouseHandlers();
186
205
 
187
206
  // $$$ calculate container size first
188
207
  this.br.refs?.$brTwoPageView.css(this.mainContainerCss);
@@ -219,13 +238,50 @@ export class Mode2Up {
219
238
 
220
239
  this.drawLeafs();
221
240
  this.br.updateToolbarZoom(this.br.reduce);
241
+ this.br.updateBrClasses();
222
242
 
223
- if (this.br.enableSearch) {
224
- this.br.removeSearchHilites();
225
- this.br.updateSearchHilites();
226
- }
243
+ this.smoothZoomer = this.smoothZoomer || new ModeSmoothZoom(this);
244
+ this.smoothZoomer.attach();
227
245
 
228
- this.br.updateBrClasses();
246
+ this.htmlDimensionsCacher = this.htmlDimensionsCacher || new HTMLDimensionsCacher(this.$container);
247
+ }
248
+
249
+ unprepare() {
250
+ // Mode2Up attaches these listeners to the main BR container, so we need to
251
+ // detach these or it will cause issues for the other modes.
252
+ this.smoothZoomer.detach();
253
+ }
254
+
255
+ /**
256
+ * @param {number} newScale
257
+ * @param {number} oldScale
258
+ */
259
+ updateViewportOnZoom(newScale, oldScale) {
260
+ const container = this.br.refs.$brContainer[0];
261
+ const { scrollTop: T, scrollLeft: L } = container;
262
+ const W = this.htmlDimensionsCacher.clientWidth;
263
+ const H = this.htmlDimensionsCacher.clientHeight;
264
+
265
+ // Scale factor change
266
+ const F = newScale / oldScale;
267
+
268
+ // Where in the viewport the zoom is centered on
269
+ const XPOS = this.scaleCenter.x;
270
+ const YPOS = this.scaleCenter.y;
271
+ const oldCenter = {
272
+ x: L + XPOS * W,
273
+ y: T + YPOS * H,
274
+ };
275
+ const newCenter = {
276
+ x: F * oldCenter.x,
277
+ y: F * oldCenter.y,
278
+ };
279
+ container.scrollTop = newCenter.y - YPOS * H;
280
+ container.scrollLeft = newCenter.x - XPOS * W;
281
+
282
+ // Also update the visible page containers to load in highres if necessary
283
+ this.pageContainers[this.br.twoPage.currentIndexL]?.update({ reduce: this.br.reduce / newScale });
284
+ this.pageContainers[this.br.twoPage.currentIndexR]?.update({ reduce: this.br.reduce / newScale });
229
285
  }
230
286
 
231
287
  prunePageContainers() {
@@ -616,8 +672,6 @@ export class Mode2Up {
616
672
 
617
673
  $(this.br.leafEdgeTmp).animate({left: gutter}, this.br.flipSpeed, 'easeInSine');
618
674
 
619
- if (this.br.enableSearch) this.br.removeSearchHilites();
620
-
621
675
  this.pageContainers[leftLeaf].$container.animate({width: '0px'}, this.br.flipSpeed, 'easeInSine', () => {
622
676
 
623
677
  $(this.br.leafEdgeTmp).animate({left: `${gutter + newWidthR}px`}, this.br.flipSpeed, 'easeOutSine');
@@ -663,10 +717,6 @@ export class Mode2Up {
663
717
 
664
718
  this.resizeSpread();
665
719
 
666
- if (this.br.enableSearch) this.br.updateSearchHilites();
667
-
668
- this.setMouseHandlers();
669
-
670
720
  if (this.br.animationFinishedCallback) {
671
721
  this.br.animationFinishedCallback();
672
722
  this.br.animationFinishedCallback = null;
@@ -690,11 +740,11 @@ export class Mode2Up {
690
740
  /**
691
741
  * @param {PageIndex} index
692
742
  */
693
- createPageContainer(index, fetch = false) {
743
+ createPageContainer(index) {
694
744
  if (!this.pageContainers[index]) {
695
745
  this.pageContainers[index] = this.br._createPageContainer(index);
696
746
  }
697
- this.pageContainers[index].update({ reduce: this.br.reduce });
747
+ this.pageContainers[index].update({ reduce: this.br.reduce / this.scale });
698
748
  return this.pageContainers[index];
699
749
  }
700
750
 
@@ -778,8 +828,6 @@ export class Mode2Up {
778
828
  $(this.leafEdgeR).css({width: `${newLeafEdgeWidthR}px`, left: `${gutter + newWidthR}px` });
779
829
  const speed = this.br.flipSpeed;
780
830
 
781
- if (this.br.enableSearch) this.br.removeSearchHilites();
782
-
783
831
  $(this.br.leafEdgeTmp).animate({left: gutter}, speed, 'easeInSine');
784
832
  this.pageContainers[this.br.twoPage.currentIndexR].$container.animate({width: '0px'}, speed, 'easeInSine', () => {
785
833
  this.br.$('BRgutter').css({left: `${gutter - this.br.twoPage.bookSpineDivWidth * 0.5}px`});
@@ -814,10 +862,6 @@ export class Mode2Up {
814
862
 
815
863
  this.resizeSpread();
816
864
 
817
- if (this.br.enableSearch) this.br.updateSearchHilites();
818
-
819
- this.setMouseHandlers();
820
-
821
865
  if (this.br.animationFinishedCallback) {
822
866
  this.br.animationFinishedCallback();
823
867
  this.br.animationFinishedCallback = null;
@@ -837,40 +881,18 @@ export class Mode2Up {
837
881
  });
838
882
  }
839
883
 
840
- setMouseHandlers() {
841
- /**
842
- * @param {HTMLElement} element
843
- * @param {JQuery.MouseDownEvent<HTMLElement, { self: Mode2Up, direction: 'R' | 'L'}>} e
844
- */
845
- const handler = function(element, e) {
846
- if (e.which == 3) {
847
- // right click
848
- return !e.data.self.br.protected;
849
- }
850
- e.data.self.br.trigger(EVENTS.stop);
851
- e.data.self.br[e.data.direction === 'L' ? 'left' : 'right']();
852
-
853
- // Removed event handler for mouse movement, seems not to be needed
854
- /*
855
- // Changes per WEBDEV-2737
856
- BookReader: zoomed-in 2 page view, clicking page should change the page
857
- $(element)
858
- .mousemove(function() {
859
- e.preventDefault();
860
- })
861
- */
862
- }
884
+ attachMouseHandlers() {
885
+ this.br.refs.$brTwoPageView
886
+ .off('mouseup').on('mouseup', ev => {
887
+ if (ev.which == 3) {
888
+ // right click
889
+ return !this.br.protected;
890
+ }
863
891
 
864
- this.setClickHandler(
865
- this.pageContainers[this.br.twoPage.currentIndexR].$container[0],
866
- { self: this, direction: 'R' },
867
- handler
868
- );
869
- this.setClickHandler(
870
- this.pageContainers[this.br.twoPage.currentIndexL].$container[0],
871
- { self: this, direction: 'L' },
872
- handler
873
- );
892
+ const $page = $(ev.target).closest('.BRpagecontainer');
893
+ if ($page.data('side') == 'L') this.br.left();
894
+ else if ($page.data('side') == 'R') this.br.right();
895
+ });
874
896
  }
875
897
 
876
898
  /**
@@ -1248,7 +1270,7 @@ export class Mode2Up {
1248
1270
  ...this.heightCss,
1249
1271
  left: `${this.br.twoPage.gutter - this.br.twoPage.scaledWL}px`,
1250
1272
  width: `${this.br.twoPage.scaledWL}px`,
1251
- }
1273
+ };
1252
1274
  }
1253
1275
 
1254
1276
  /** Left side book thickness */
@@ -1269,7 +1291,7 @@ export class Mode2Up {
1269
1291
  ...this.heightCss,
1270
1292
  left: `${this.br.twoPage.gutter}px`,
1271
1293
  width: `${this.br.twoPage.scaledWR}px`,
1272
- }
1294
+ };
1273
1295
  }
1274
1296
 
1275
1297
  /** Right side book thickness */