@internetarchive/bookreader 5.0.0-95 → 5.0.0-97

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 (330) hide show
  1. package/BookReader/474.js +2 -0
  2. package/BookReader/474.js.map +1 -0
  3. package/BookReader/BookReader.css +2257 -0
  4. package/BookReader/BookReader.js +3 -0
  5. package/BookReader/BookReader.js.LICENSE.txt +72 -0
  6. package/BookReader/BookReader.js.map +1 -0
  7. package/BookReader/bergamot-translator-worker.js +2966 -0
  8. package/BookReader/bergamot-translator-worker.wasm +0 -0
  9. package/BookReader/hypothesis/LICENSE +50 -0
  10. package/BookReader/hypothesis/README.md +55 -0
  11. package/BookReader/hypothesis/build/boot.js +1 -0
  12. package/BookReader/hypothesis/build/manifest.json +20 -0
  13. package/BookReader/hypothesis/build/scripts/annotator.bundle.js +184 -0
  14. package/BookReader/hypothesis/build/scripts/annotator.bundle.js.map +1 -0
  15. package/BookReader/hypothesis/build/scripts/sidebar.bundle.js +798 -0
  16. package/BookReader/hypothesis/build/scripts/sidebar.bundle.js.map +1 -0
  17. package/BookReader/hypothesis/build/scripts/ui-playground.bundle.js +711 -0
  18. package/BookReader/hypothesis/build/scripts/ui-playground.bundle.js.map +1 -0
  19. package/BookReader/hypothesis/build/styles/annotator.css +2235 -0
  20. package/BookReader/hypothesis/build/styles/annotator.css.map +1 -0
  21. package/BookReader/hypothesis/build/styles/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  22. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  23. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  24. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  25. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  26. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Bold.woff2 +0 -0
  27. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  28. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Italic.woff2 +0 -0
  29. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Regular.woff2 +0 -0
  30. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  31. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Math-Italic.woff2 +0 -0
  32. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  33. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  34. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  35. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Script-Regular.woff2 +0 -0
  36. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  37. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  38. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  39. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  40. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  41. package/BookReader/hypothesis/build/styles/highlights.css +2 -0
  42. package/BookReader/hypothesis/build/styles/highlights.css.map +1 -0
  43. package/BookReader/hypothesis/build/styles/katex.min.css +2 -0
  44. package/BookReader/hypothesis/build/styles/katex.min.css.map +1 -0
  45. package/BookReader/hypothesis/build/styles/pdfjs-overrides.css +2 -0
  46. package/BookReader/hypothesis/build/styles/pdfjs-overrides.css.map +1 -0
  47. package/BookReader/hypothesis/build/styles/sidebar.css +2731 -0
  48. package/BookReader/hypothesis/build/styles/sidebar.css.map +1 -0
  49. package/BookReader/hypothesis/build/styles/ui-playground.css +2659 -0
  50. package/BookReader/hypothesis/build/styles/ui-playground.css.map +1 -0
  51. package/BookReader/hypothesis/package.json +126 -0
  52. package/BookReader/ia-bookreader-bundle.js +1782 -0
  53. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -0
  54. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  55. package/BookReader/icons/1up.svg +1 -0
  56. package/BookReader/icons/2up.svg +1 -0
  57. package/BookReader/icons/advance.svg +3 -0
  58. package/BookReader/icons/chevron-right.svg +1 -0
  59. package/BookReader/icons/close-circle-dark.svg +1 -0
  60. package/BookReader/icons/close-circle.svg +1 -0
  61. package/BookReader/icons/fullscreen.svg +1 -0
  62. package/BookReader/icons/fullscreen_exit.svg +1 -0
  63. package/BookReader/icons/hamburger.svg +1 -0
  64. package/BookReader/icons/left-arrow.svg +1 -0
  65. package/BookReader/icons/magnify-minus.svg +1 -0
  66. package/BookReader/icons/magnify-plus.svg +1 -0
  67. package/BookReader/icons/magnify.svg +1 -0
  68. package/BookReader/icons/pause.svg +1 -0
  69. package/BookReader/icons/play.svg +1 -0
  70. package/BookReader/icons/playback-speed.svg +1 -0
  71. package/BookReader/icons/read-aloud.svg +1 -0
  72. package/BookReader/icons/review.svg +3 -0
  73. package/BookReader/icons/thumbnails.svg +1 -0
  74. package/BookReader/icons/voice.svg +1 -0
  75. package/BookReader/icons/volume-full.svg +1 -0
  76. package/BookReader/images/BRicons.png +0 -0
  77. package/BookReader/images/BRicons.svg +5 -0
  78. package/BookReader/images/BRicons_ia.png +0 -0
  79. package/BookReader/images/back_pages.png +0 -0
  80. package/BookReader/images/book_bottom_icon.png +0 -0
  81. package/BookReader/images/book_down_icon.png +0 -0
  82. package/BookReader/images/book_left_icon.png +0 -0
  83. package/BookReader/images/book_leftmost_icon.png +0 -0
  84. package/BookReader/images/book_right_icon.png +0 -0
  85. package/BookReader/images/book_rightmost_icon.png +0 -0
  86. package/BookReader/images/book_top_icon.png +0 -0
  87. package/BookReader/images/book_up_icon.png +0 -0
  88. package/BookReader/images/books_graphic.svg +1 -0
  89. package/BookReader/images/booksplit.png +0 -0
  90. package/BookReader/images/control_pause_icon.png +0 -0
  91. package/BookReader/images/control_play_icon.png +0 -0
  92. package/BookReader/images/embed_icon.png +0 -0
  93. package/BookReader/images/hypothesis.ico +0 -0
  94. package/BookReader/images/icon-home-ia.png +0 -0
  95. package/BookReader/images/icon_OL-logo-xs.png +0 -0
  96. package/BookReader/images/icon_alert-xs.png +0 -0
  97. package/BookReader/images/icon_book.svg +1 -0
  98. package/BookReader/images/icon_bookmark.svg +1 -0
  99. package/BookReader/images/icon_close-pop.png +0 -0
  100. package/BookReader/images/icon_download.png +0 -0
  101. package/BookReader/images/icon_experiment.svg +1 -0
  102. package/BookReader/images/icon_gear.svg +1 -0
  103. package/BookReader/images/icon_hamburger.svg +1 -0
  104. package/BookReader/images/icon_home.png +0 -0
  105. package/BookReader/images/icon_home.svg +1 -0
  106. package/BookReader/images/icon_home_ia.png +0 -0
  107. package/BookReader/images/icon_indicator.png +0 -0
  108. package/BookReader/images/icon_info.svg +1 -0
  109. package/BookReader/images/icon_one_page.svg +1 -0
  110. package/BookReader/images/icon_pause.svg +1 -0
  111. package/BookReader/images/icon_play.svg +1 -0
  112. package/BookReader/images/icon_playback-rate.svg +1 -0
  113. package/BookReader/images/icon_return.png +0 -0
  114. package/BookReader/images/icon_search_button.svg +1 -0
  115. package/BookReader/images/icon_share.svg +1 -0
  116. package/BookReader/images/icon_skip-ahead.svg +1 -0
  117. package/BookReader/images/icon_skip-back.svg +2 -0
  118. package/BookReader/images/icon_speaker.svg +1 -0
  119. package/BookReader/images/icon_speaker_open.svg +1 -0
  120. package/BookReader/images/icon_thumbnails.svg +1 -0
  121. package/BookReader/images/icon_toc.svg +1 -0
  122. package/BookReader/images/icon_two_pages.svg +1 -0
  123. package/BookReader/images/icon_zoomer.png +0 -0
  124. package/BookReader/images/loading.gif +0 -0
  125. package/BookReader/images/logo_icon.png +0 -0
  126. package/BookReader/images/marker_chap-off.png +0 -0
  127. package/BookReader/images/marker_chap-off.svg +1 -0
  128. package/BookReader/images/marker_chap-off_ia.png +0 -0
  129. package/BookReader/images/marker_chap-on.png +0 -0
  130. package/BookReader/images/marker_chap-on.svg +1 -0
  131. package/BookReader/images/marker_srch-on.svg +1 -0
  132. package/BookReader/images/marker_srchchap-off.png +0 -0
  133. package/BookReader/images/marker_srchchap-on.png +0 -0
  134. package/BookReader/images/nav_control-dn.png +0 -0
  135. package/BookReader/images/nav_control-dn_ia.png +0 -0
  136. package/BookReader/images/nav_control-up.png +0 -0
  137. package/BookReader/images/nav_control-up_ia.png +0 -0
  138. package/BookReader/images/nav_control.png +0 -0
  139. package/BookReader/images/one_page_mode_icon.png +0 -0
  140. package/BookReader/images/paper-badge.png +0 -0
  141. package/BookReader/images/print_icon.png +0 -0
  142. package/BookReader/images/progressbar.gif +0 -0
  143. package/BookReader/images/right_edges.png +0 -0
  144. package/BookReader/images/slider.png +0 -0
  145. package/BookReader/images/slider_ia.png +0 -0
  146. package/BookReader/images/thumbnail_mode_icon.png +0 -0
  147. package/BookReader/images/translate.svg +1 -0
  148. package/BookReader/images/transparent.png +0 -0
  149. package/BookReader/images/two_page_mode_icon.png +0 -0
  150. package/BookReader/images/unviewable_page.png +0 -0
  151. package/BookReader/images/zoom_in_icon.png +0 -0
  152. package/BookReader/images/zoom_out_icon.png +0 -0
  153. package/BookReader/jquery-3.js +2 -0
  154. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  155. package/BookReader/plugins/plugin.archive_analytics.js +2 -0
  156. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -0
  157. package/BookReader/plugins/plugin.autoplay.js +2 -0
  158. package/BookReader/plugins/plugin.autoplay.js.map +1 -0
  159. package/BookReader/plugins/plugin.chapters.js +26 -0
  160. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
  161. package/BookReader/plugins/plugin.chapters.js.map +1 -0
  162. package/BookReader/plugins/plugin.experiments.js +3 -0
  163. package/BookReader/plugins/plugin.experiments.js.LICENSE.txt +1 -0
  164. package/BookReader/plugins/plugin.experiments.js.map +1 -0
  165. package/BookReader/plugins/plugin.iframe.js +2 -0
  166. package/BookReader/plugins/plugin.iframe.js.map +1 -0
  167. package/BookReader/plugins/plugin.iiif.js +2 -0
  168. package/BookReader/plugins/plugin.iiif.js.map +1 -0
  169. package/BookReader/plugins/plugin.resume.js +2 -0
  170. package/BookReader/plugins/plugin.resume.js.map +1 -0
  171. package/BookReader/plugins/plugin.search.js +3 -0
  172. package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
  173. package/BookReader/plugins/plugin.search.js.map +1 -0
  174. package/BookReader/plugins/plugin.text_selection.js +3 -0
  175. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
  176. package/BookReader/plugins/plugin.text_selection.js.map +1 -0
  177. package/BookReader/plugins/plugin.translate.js +3 -0
  178. package/BookReader/plugins/plugin.translate.js.LICENSE.txt +1 -0
  179. package/BookReader/plugins/plugin.translate.js.map +1 -0
  180. package/BookReader/plugins/plugin.tts.js +3 -0
  181. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +29 -0
  182. package/BookReader/plugins/plugin.tts.js.map +1 -0
  183. package/BookReader/plugins/plugin.url.js +2 -0
  184. package/BookReader/plugins/plugin.url.js.map +1 -0
  185. package/BookReader/plugins/plugin.vendor-fullscreen.js +2 -0
  186. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -0
  187. package/BookReader/plugins/translator-worker.js +2 -0
  188. package/BookReader/plugins/translator-worker.js.map +1 -0
  189. package/BookReader/translator-worker.js +475 -0
  190. package/BookReader/webcomponents-bundle.js +3 -0
  191. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  192. package/BookReader/webcomponents-bundle.js.map +1 -0
  193. package/package.json +11 -3
  194. package/src/BookNavigator/book-navigator.js +1 -0
  195. package/src/BookReader/BookModel.js +564 -0
  196. package/src/BookReader/DragScrollable.js +233 -0
  197. package/src/BookReader/ImageCache.js +149 -0
  198. package/src/BookReader/Mode1Up.js +110 -0
  199. package/src/BookReader/Mode1UpLit.js +393 -0
  200. package/src/BookReader/Mode2Up.js +107 -0
  201. package/src/BookReader/Mode2UpLit.js +787 -0
  202. package/src/BookReader/ModeCoordinateSpace.js +29 -0
  203. package/src/BookReader/ModeSmoothZoom.js +312 -0
  204. package/src/BookReader/ModeThumb.js +344 -0
  205. package/src/BookReader/Navbar/Navbar.js +416 -0
  206. package/src/BookReader/PageContainer.js +172 -0
  207. package/src/BookReader/ReduceSet.js +26 -0
  208. package/src/BookReader/Toolbar/Toolbar.js +362 -0
  209. package/src/BookReader/events.js +19 -0
  210. package/src/BookReader/options.js +387 -0
  211. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  212. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  213. package/src/BookReader/utils/SelectionObserver.js +45 -0
  214. package/src/BookReader/utils/classes.js +36 -0
  215. package/src/BookReader/utils.js +313 -0
  216. package/src/BookReader.js +22 -139
  217. package/src/assets/images/icon_experiment.svg +1 -0
  218. package/src/assets/images/translate.svg +1 -0
  219. package/src/css/_BRnav.scss +0 -24
  220. package/src/css/_BRsearch.scss +0 -5
  221. package/src/css/_TextSelection.scss +32 -1
  222. package/src/plugins/plugin.experiments.js +34 -9
  223. package/src/plugins/plugin.text_selection.js +8 -20
  224. package/src/plugins/translate/TranslationManager.js +167 -0
  225. package/src/plugins/translate/plugin.translate.js +414 -0
  226. package/src/plugins/tts/utils.js +9 -20
  227. package/src/util/cache.js +20 -0
  228. package/.eslintrc.cjs +0 -51
  229. package/.gitattributes +0 -2
  230. package/.github/ISSUE_TEMPLATE/bug.md +0 -32
  231. package/.github/ISSUE_TEMPLATE/feature-request.md +0 -30
  232. package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -15
  233. package/.github/workflows/node.js.yml +0 -102
  234. package/.github/workflows/npm-publish.yml +0 -23
  235. package/.testcaferc.cjs +0 -10
  236. package/BookReaderDemo/BookReaderDemo.css +0 -40
  237. package/BookReaderDemo/BookReaderJSAdvanced.js +0 -112
  238. package/BookReaderDemo/BookReaderJSSimple.js +0 -56
  239. package/BookReaderDemo/IADemoBr.js +0 -149
  240. package/BookReaderDemo/assets/v5/Bookreader-logo-cool-grad.svg +0 -1
  241. package/BookReaderDemo/assets/v5/Bookreader-logo-flat.svg +0 -1
  242. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-cool-grad.png +0 -0
  243. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-flat.png +0 -0
  244. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.png +0 -0
  245. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.svg +0 -1
  246. package/BookReaderDemo/assets/v5/Bookreader-logo-warm.svg +0 -1
  247. package/BookReaderDemo/assets/v5/bookreader-logo-renders@1x.png +0 -0
  248. package/BookReaderDemo/assets/v5/bookreader-logo-renders@2x.png +0 -0
  249. package/BookReaderDemo/assets/v5/bookreader-v5-screenshot.png +0 -0
  250. package/BookReaderDemo/demo-advanced.html +0 -33
  251. package/BookReaderDemo/demo-embed-iframe-src.html +0 -85
  252. package/BookReaderDemo/demo-embed.html +0 -26
  253. package/BookReaderDemo/demo-fullscreen-mobile.html +0 -34
  254. package/BookReaderDemo/demo-fullscreen.html +0 -31
  255. package/BookReaderDemo/demo-iiif.html +0 -121
  256. package/BookReaderDemo/demo-internetarchive.html +0 -271
  257. package/BookReaderDemo/demo-multiple.html +0 -44
  258. package/BookReaderDemo/demo-preview-pages.html +0 -1093
  259. package/BookReaderDemo/demo-simple.html +0 -35
  260. package/BookReaderDemo/demo-vendor-fullscreen.html +0 -34
  261. package/BookReaderDemo/ia-multiple-volumes-manifest.js +0 -169
  262. package/BookReaderDemo/immersion-1up.html +0 -64
  263. package/BookReaderDemo/immersion-mode.html +0 -33
  264. package/BookReaderDemo/toggle_controls.html +0 -54
  265. package/BookReaderDemo/view_mode.html +0 -40
  266. package/BookReaderDemo/viewmode-cycle.html +0 -40
  267. package/CHANGELOG.md +0 -1087
  268. package/CONTRIBUTING.md +0 -7
  269. package/babel.config.cjs +0 -20
  270. package/codecov.yml +0 -23
  271. package/index.html +0 -34
  272. package/netlify.toml +0 -9
  273. package/renovate.json +0 -52
  274. package/screenshot.png +0 -0
  275. package/scripts/postversion.js +0 -11
  276. package/scripts/preversion.js +0 -15
  277. package/scripts/version.js +0 -24
  278. package/tests/e2e/README.md +0 -112
  279. package/tests/e2e/autoplay.test.js +0 -16
  280. package/tests/e2e/base.test.js +0 -27
  281. package/tests/e2e/helpers/base.js +0 -263
  282. package/tests/e2e/helpers/debug.js +0 -13
  283. package/tests/e2e/helpers/mockSearch.js +0 -90
  284. package/tests/e2e/helpers/params.js +0 -17
  285. package/tests/e2e/helpers/rightToLeft.js +0 -23
  286. package/tests/e2e/helpers/search.js +0 -73
  287. package/tests/e2e/models/BookReader.js +0 -11
  288. package/tests/e2e/models/Navigation.js +0 -39
  289. package/tests/e2e/rightToLeft.test.js +0 -19
  290. package/tests/e2e/viewmode.test.js +0 -44
  291. package/tests/jest/BookNavigator/book-navigator.test.js +0 -653
  292. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +0 -43
  293. package/tests/jest/BookNavigator/bookmarks/bookmark-edit.test.js +0 -132
  294. package/tests/jest/BookNavigator/bookmarks/bookmarks-list.test.js +0 -221
  295. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +0 -45
  296. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +0 -67
  297. package/tests/jest/BookNavigator/downloads/downloads.test.js +0 -53
  298. package/tests/jest/BookNavigator/search/search-provider.test.js +0 -179
  299. package/tests/jest/BookNavigator/search/search-results.test.js +0 -289
  300. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +0 -49
  301. package/tests/jest/BookNavigator/viewable-files/viewable-files-provider.test.js +0 -80
  302. package/tests/jest/BookNavigator/visual-adjustments.test.js +0 -200
  303. package/tests/jest/BookReader.keyboard.test.js +0 -190
  304. package/tests/jest/BookReader.options.test.js +0 -47
  305. package/tests/jest/BookReader.test.js +0 -316
  306. package/tests/jest/plugins/plugin.archive_analytics.test.js +0 -20
  307. package/tests/jest/plugins/plugin.autoplay.test.js +0 -35
  308. package/tests/jest/plugins/plugin.chapters.test.js +0 -193
  309. package/tests/jest/plugins/plugin.iframe.test.js +0 -42
  310. package/tests/jest/plugins/plugin.resume.test.js +0 -85
  311. package/tests/jest/plugins/plugin.text_selection.test.js +0 -447
  312. package/tests/jest/plugins/plugin.vendor-fullscreen.test.js +0 -65
  313. package/tests/jest/plugins/search/plugin.search.test.js +0 -120
  314. package/tests/jest/plugins/search/plugin.search.view.test.js +0 -131
  315. package/tests/jest/plugins/search/utils.js +0 -25
  316. package/tests/jest/plugins/search/utils.test.js +0 -29
  317. package/tests/jest/plugins/tts/AbstractTTSEngine.test.js +0 -173
  318. package/tests/jest/plugins/tts/FestivalTTSEngine.test.js +0 -59
  319. package/tests/jest/plugins/tts/PageChunk.test.js +0 -57
  320. package/tests/jest/plugins/tts/PageChunkIterator.test.js +0 -179
  321. package/tests/jest/plugins/tts/WebTTSEngine.test.js +0 -178
  322. package/tests/jest/plugins/tts/utils.test.js +0 -74
  323. package/tests/jest/plugins/url/UrlPlugin.test.js +0 -198
  324. package/tests/jest/plugins/url/plugin.url.test.js +0 -168
  325. package/tests/jest/setup.js +0 -3
  326. package/tests/jest/util/browserSniffing.test.js +0 -62
  327. package/tests/jest/util/docCookies.test.js +0 -24
  328. package/tests/jest/util/strings.test.js +0 -63
  329. package/tests/jest/utils.js +0 -83
  330. package/webpack.config.js +0 -97
@@ -0,0 +1,416 @@
1
+ // @ts-check
2
+ /** @typedef {import("../../BookReader.js").default} BookReader */
3
+
4
+ import 'jquery-ui/ui/widget.js';
5
+ import 'jquery-ui/ui/widgets/mouse.js';
6
+ import 'jquery-ui/ui/widgets/slider.js';
7
+ import { EVENTS } from '../events.js';
8
+ import { throttle } from '../utils.js';
9
+
10
+ export class Navbar {
11
+ /**
12
+ * @param {BookReader} br
13
+ */
14
+ constructor(br) {
15
+ this.br = br;
16
+
17
+ /** @type {JQuery} */
18
+ this.$root = null;
19
+ /** @type {JQuery} */
20
+ this.$nav = null;
21
+ /** @type {number} */
22
+ this.maxPageNum = null;
23
+
24
+ /** @type {Object} controls will be switch over "this.maximumControls" */
25
+ this.minimumControls = [
26
+ 'viewmode',
27
+ ];
28
+ /** @type {Object} controls will be switch over "this.minimumControls" */
29
+ this.maximumControls = [
30
+ 'book_left', 'book_right', 'zoom_in', 'zoom_out', 'onepg', 'twopg', 'thumb',
31
+ ];
32
+
33
+ this.updateNavIndexThrottled = throttle(this.updateNavIndex.bind(this), 250, false);
34
+ }
35
+
36
+ controlFor(controlName) {
37
+ const option = this.br.options.controls[controlName];
38
+ if (!option.visible) { return ''; }
39
+ if (option.template) {
40
+ return `<li>${option.template(this.br)}</li>`;
41
+ }
42
+ return `<li>
43
+ <button class="BRicon ${option.className}" title="${option.label}">
44
+ <div class="icon icon-${option.iconClassName}"></div>
45
+ <span class="BRtooltip">${option.label}</span>
46
+ </button>
47
+ </li>`;
48
+ }
49
+
50
+ /** @private */
51
+ _renderControls() {
52
+ return [
53
+ 'bookLeft',
54
+ 'bookRight',
55
+ 'onePage',
56
+ 'twoPage',
57
+ 'thumbnail',
58
+ 'viewmode',
59
+ 'zoomOut',
60
+ 'zoomIn',
61
+ 'fullScreen',
62
+ ].map((mode) => (
63
+ this.controlFor(mode)
64
+ )).join('');
65
+ }
66
+
67
+ /** @private */
68
+ _bindViewModeButton() {
69
+ const { br } = this;
70
+ const viewModeOptions = br.options.controls.viewmode;
71
+ const viewModes = [{
72
+ mode: br.constMode1up,
73
+ className: 'onepg',
74
+ title: 'One-page view',
75
+ }, {
76
+ mode: br.constMode2up,
77
+ className: 'twopg',
78
+ title: 'Two-page view',
79
+ }, {
80
+ mode: br.constModeThumb,
81
+ className: 'thumb',
82
+ title: 'Thumbnail view',
83
+ }].filter((mode) => (
84
+ !viewModeOptions.excludedModes.includes(mode.mode)
85
+ ));
86
+ const viewModeOrder = viewModes.map((m) => m.mode);
87
+
88
+ if (viewModeOptions.excludedModes.includes(br.mode)) {
89
+ br.switchMode(viewModeOrder[0]);
90
+ }
91
+
92
+ // Reorder the viewModeOrder so the current view mode is at the end
93
+ const currentModeIndex = viewModeOrder.indexOf(br.mode);
94
+ for (let i = 0; i <= currentModeIndex; i++) {
95
+ viewModeOrder.push(viewModeOrder.shift());
96
+ }
97
+
98
+ if (viewModes.length < 2) {
99
+ this.$nav.find(`.${viewModeOptions.className}`).remove();
100
+ }
101
+
102
+ this.br.bind(EVENTS.PostInit, () => {
103
+ const $button = this.$nav.find(`.${viewModeOptions.className}`)
104
+ .off('.bindNavigationHandlers')
105
+ .on('click', (e) => {
106
+ const nextModeID = viewModeOrder.shift();
107
+ const newViewMode = viewModes.find((m) => m.mode === nextModeID);
108
+ const nextViewMode = viewModes.find((m) => m.mode === viewModeOrder[0]);
109
+
110
+ viewModeOrder.push(nextModeID);
111
+ br.viewModeOrder = viewModeOrder;
112
+ this.updateViewModeButton($(e.currentTarget), nextViewMode.className, nextViewMode.title);
113
+ br.switchMode(newViewMode.mode);
114
+ });
115
+ const currentViewModeButton = viewModes.find((m) => m.mode === viewModeOrder[0]);
116
+ this.updateViewModeButton(
117
+ $button,
118
+ currentViewModeButton.className,
119
+ currentViewModeButton.title,
120
+ );
121
+ });
122
+ }
123
+
124
+ bindControlClickHandlers() {
125
+ const jIcons = this.$nav.find('.BRicon');
126
+
127
+ // Map of jIcon class -> click handler
128
+ const navigationControls = {
129
+ book_left: () => {
130
+ this.br.trigger(EVENTS.stop);
131
+ this.br.left();
132
+ },
133
+ book_right: () => {
134
+ this.br.trigger(EVENTS.stop);
135
+ this.br.right();
136
+ },
137
+ book_top: this.br.first.bind(this.br),
138
+ book_bottom: this.br.last.bind(this.br),
139
+ book_leftmost: this.br.leftmost.bind(this.br),
140
+ book_rightmost: this.br.rightmost.bind(this.br),
141
+ onepg: () => {
142
+ this.br.switchMode('1up');
143
+ },
144
+ thumb: () => {
145
+ this.br.switchMode('thumb');
146
+ },
147
+ twopg: () => {
148
+ this.br.switchMode('2up');
149
+ },
150
+ zoom_in: () => {
151
+ this.br.trigger(EVENTS.stop);
152
+ this.br.zoom(1);
153
+ this.br.trigger(EVENTS.zoomIn);
154
+ },
155
+ zoom_out: () => {
156
+ this.br.trigger(EVENTS.stop);
157
+ this.br.zoom(-1);
158
+ this.br.trigger(EVENTS.zoomOut);
159
+ },
160
+ full: () => {
161
+ if (this.br.ui == 'embed') {
162
+ const url = this.br.$('.BRembedreturn a').attr('href');
163
+ window.open(url);
164
+ } else {
165
+ this.br.toggleFullscreen();
166
+ }
167
+ },
168
+ };
169
+
170
+ // custom event for auto-loan-renew in ia-book-actions
171
+ // - to know if user is actively reading
172
+ this.$nav.find('nav.BRcontrols li button').on('click', () => {
173
+ this.br.trigger(EVENTS.userAction);
174
+ });
175
+
176
+ for (const control in navigationControls) {
177
+ jIcons.filter(`.${control}`).on('click.bindNavigationHandlers', () => {
178
+ navigationControls[control]();
179
+ return false;
180
+ });
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Toggle viewmode button to change page view
186
+ */
187
+ updateViewModeButton($button, iconClass, tooltipText) {
188
+ $button
189
+ .attr('title', tooltipText)
190
+ .find('.icon')
191
+ .removeClass()
192
+ .addClass(`icon icon-${iconClass}`)
193
+ .end()
194
+ .find('.BRtooltip')
195
+ .text(tooltipText);
196
+ }
197
+
198
+ /**
199
+ * Switch navbar controls on mobile and desktop
200
+ */
201
+ switchNavbarControls() {
202
+ if (this.br.refs.$brContainer.prop('clientWidth') < 640) {
203
+ this.showMinimumNavPageNum();
204
+ // we don't want navbar controls switching with liner-notes
205
+ if (this.br.options.bookType !== 'linerNotes') {
206
+ this.showMinimumNavbarControls();
207
+ }
208
+ } else {
209
+ this.showMaximumNavPageNum();
210
+ // we don't want navbar controls switching with liner-notes
211
+ if (this.br.options.bookType !== 'linerNotes') {
212
+ this.showMaximumNavbarControls();
213
+ }
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Switch Book Nav page number display to minimum/mobile
219
+ */
220
+ showMinimumNavPageNum() {
221
+ const minElement = document.querySelector('.BRcurrentpage.BRmin');
222
+ const maxElement = document.querySelector('.BRcurrentpage.BRmax');
223
+
224
+ if (minElement) minElement.classList.remove('hide');
225
+ if (maxElement) maxElement.classList.add('hide');
226
+ }
227
+
228
+ /**
229
+ * Switch Book Nav page number display to maximum/desktop
230
+ */
231
+ showMaximumNavPageNum() {
232
+ const minElement = document.querySelector('.BRcurrentpage.BRmin');
233
+ const maxElement = document.querySelector('.BRcurrentpage.BRmax');
234
+
235
+ if (minElement) minElement.classList.add('hide');
236
+ if (maxElement) maxElement.classList.remove('hide');
237
+ }
238
+
239
+ /**
240
+ * Switch Book Navbar controls to minimised
241
+ * NOTE: only `this.minimumControls` and `this.maximumControls` switch on resize
242
+ */
243
+ showMinimumNavbarControls() {
244
+ this.minimumControls.forEach((control) => {
245
+ const element = document.querySelector(`.controls .${control}`);
246
+ if (element) element.classList.remove('hide');
247
+ });
248
+ this.maximumControls.forEach((control) => {
249
+ const element = document.querySelector(`.controls .${control}`);
250
+ if (element) element.classList.add('hide');
251
+ });
252
+ }
253
+
254
+ /**
255
+ * Switch Book Navbar controls to maximized
256
+ * NOTE: only `this.minimumControls` and `this.maximumControls` switch on resize
257
+ */
258
+ showMaximumNavbarControls() {
259
+ this.maximumControls.forEach((control) => {
260
+ const element = document.querySelector(`.controls .${control}`);
261
+ if (element) element.classList.remove('hide');
262
+ });
263
+ this.minimumControls.forEach((control) => {
264
+ const element = document.querySelector(`.controls .${control}`);
265
+ if (element) element.classList.add('hide');
266
+ });
267
+ }
268
+
269
+ /**
270
+ * Initialize the navigation bar (bottom)
271
+ * @return {JQuery}
272
+ */
273
+ init() {
274
+ const { br } = this;
275
+ const { navbarTitle: title } = br.options;
276
+ const isRTL = br.pageProgression === 'rl';
277
+ const bookFlipLeft = isRTL ? 'book_flip_next' : 'book_flip_prev';
278
+ const bookFlipRight = isRTL ? 'book_flip_prev' : 'book_flip_next';
279
+
280
+ this.br.options.controls['bookLeft'].className = `book_left ${bookFlipLeft}`;
281
+ this.br.options.controls['bookRight'].className = `book_right ${bookFlipRight}`;
282
+
283
+ br.refs.$BRfooter = this.$root = $(`<div class="BRfooter"></div>`);
284
+ br.refs.$BRnav = this.$nav = $(
285
+ `<div class="BRnav BRnavDesktop">
286
+ ${title ? `<div class="BRnavTitle">${title}</div>` : ''}
287
+ <nav class="BRcontrols">
288
+ <ul class="controls">
289
+ <li class="scrubber">
290
+ <div class="BRnavpos">
291
+ <div class="BRpager"></div>
292
+ <div class="BRnavline"></div>
293
+ </div>
294
+ <p>
295
+ <span class="BRcurrentpage BRmax"></span>
296
+ <span class="BRcurrentpage BRmin"></span>
297
+ </p>
298
+ </li>
299
+ ${this._renderControls()}
300
+ </ul>
301
+ </nav>
302
+ </div>`);
303
+
304
+ this.$root.append(this.$nav);
305
+ br.refs.$br.append(this.$root);
306
+
307
+ const $slider = this.$root.find('.BRpager').slider({
308
+ animate: true,
309
+ min: 0,
310
+ max: br.book.getNumLeafs() - 1,
311
+ value: br.currentIndex(),
312
+ range: "min",
313
+ });
314
+
315
+ $slider.on('slide', (event, ui) => {
316
+ this.updateNavPageNum(ui.value);
317
+ return true;
318
+ });
319
+
320
+ $slider.on('slidechange', (event, ui) => {
321
+ this.updateNavPageNum(ui.value);
322
+ // recursion prevention for jumpToIndex
323
+ if ($slider.data('swallowchange')) {
324
+ $slider.data('swallowchange', false);
325
+ } else {
326
+ br.jumpToIndex(ui.value);
327
+ }
328
+ return true;
329
+ });
330
+
331
+ br.options.controls.viewmode.visible && this._bindViewModeButton();
332
+ this.updateNavPageNum(br.currentIndex());
333
+
334
+ return this.$nav;
335
+ }
336
+
337
+ /**
338
+ * Returns the textual representation of the current page for the navbar
339
+ * @param {number} index
340
+ * @param {boolean} [useMaxFormat = false]
341
+ * @return {string}
342
+ */
343
+ getNavPageNumString(index, useMaxFormat = false) {
344
+ const { br } = this;
345
+ // Accessible index starts at 0 (alas) so we add 1 to make human
346
+ const pageNum = br.book.getPageNum(index);
347
+ const pageType = br.book.getPageProp(index, 'pageType');
348
+ const numLeafs = br.book.getNumLeafs();
349
+
350
+ if (!this.maxPageNum) {
351
+ // Calculate Max page num (used for pagination display)
352
+ let maxPageNum = 0;
353
+ let pageNumVal;
354
+ for (let i = 0; i < numLeafs; i++) {
355
+ pageNumVal = parseFloat(br.book.getPageNum(i));
356
+ if (!isNaN(pageNumVal) && pageNumVal > maxPageNum) {
357
+ maxPageNum = pageNumVal;
358
+ }
359
+ }
360
+ this.maxPageNum = maxPageNum;
361
+ }
362
+
363
+ return getNavPageNumHtml(index, numLeafs, pageNum, pageType, this.maxPageNum, useMaxFormat);
364
+
365
+ }
366
+
367
+ /**
368
+ * Renders the navbar string to the DOM
369
+ * @param {number} index
370
+ */
371
+ updateNavPageNum(index) {
372
+ this.$root.find('.BRcurrentpage.BRmax').html(this.getNavPageNumString(index, true));
373
+ this.$root.find('.BRcurrentpage.BRmin').html(this.getNavPageNumString(index));
374
+ }
375
+
376
+ /**
377
+ * Update the nav bar display - does not cause navigation.
378
+ * @param {number} index
379
+ */
380
+ updateNavIndex(index) {
381
+ // We want to update the value, but normally moving the slider
382
+ // triggers jumpToIndex which triggers this method
383
+ index = index !== undefined ? index : this.br.currentIndex();
384
+ this.$root.find('.BRpager').data('swallowchange', true).slider('value', index);
385
+ }
386
+ }
387
+
388
+ /**
389
+ * Renders the html for the page string
390
+ * @param {number} index
391
+ * @param {number} numLeafs
392
+ * @param {number|string} pageNum
393
+ * @param {*} pageType - Deprecated
394
+ * @param {number} maxPageNum
395
+ * @param {boolean} [useMaxFormat = false]
396
+ * @return {string}
397
+ */
398
+ export function getNavPageNumHtml(index, numLeafs, pageNum, pageType, maxPageNum, useMaxFormat = false) {
399
+ const pageIsAsserted = pageNum[0] != 'n';
400
+ const pageIndex = index + 1;
401
+
402
+ if (!pageIsAsserted) {
403
+ pageNum = '—';
404
+ }
405
+
406
+ if (useMaxFormat === true) {
407
+ return `Page ${pageNum} (${pageIndex}/${numLeafs})`;
408
+ }
409
+
410
+ if (!pageIsAsserted) {
411
+ return `(${pageIndex} of ${numLeafs})`;
412
+ }
413
+
414
+ const bookLengthLabel = (maxPageNum && parseFloat(pageNum)) ? ` of ${maxPageNum}` : '';
415
+ return `${pageNum}${bookLengthLabel}`;
416
+ }
@@ -0,0 +1,172 @@
1
+ // @ts-check
2
+ /** @typedef {import('./BookModel.js').PageModel} PageModel */
3
+ /** @typedef {import('./ImageCache.js').ImageCache} ImageCache */
4
+
5
+ import { sleep } from './utils.js';
6
+
7
+
8
+ export class PageContainer {
9
+ /**
10
+ * @param {PageModel} page
11
+ * @param {object} opts
12
+ * @param {boolean} opts.isProtected Whether we're in a protected book
13
+ * @param {ImageCache} opts.imageCache
14
+ */
15
+ constructor(page, {isProtected, imageCache}) {
16
+ this.page = page;
17
+ this.imageCache = imageCache;
18
+ this.$container = $('<div />', {
19
+ 'class': `BRpagecontainer ${page ? `pagediv${page.index}` : 'BRemptypage'}`,
20
+ css: { position: 'absolute' },
21
+ })
22
+ .attr('data-side', page?.pageSide)
23
+ .attr('data-index', page?.index)
24
+ .attr('data-page-num', page?.getPageNum());
25
+
26
+ if (isProtected) {
27
+ this.$container.append($('<div class="BRscreen" />'));
28
+ this.$container.addClass('protected');
29
+ }
30
+
31
+ /** @type {JQuery<HTMLImageElement>} The main book page image */
32
+ this.$img = null;
33
+ }
34
+
35
+ /**
36
+ * @param {object} param0
37
+ * @param {{ width: number, height: number, top: number, left: number }} [param0.dimensions]
38
+ * @param {number} param0.reduce
39
+ */
40
+ update({dimensions = null, reduce = null}) {
41
+ if (dimensions) {
42
+ this.$container.css(dimensions);
43
+ }
44
+
45
+ if (reduce == null || !this.page) {
46
+ return;
47
+ }
48
+
49
+ const finalReduce = this.imageCache.getFinalReduce(this.page.index, reduce);
50
+ const newImageURI = this.page.getURI(finalReduce, 0);
51
+
52
+ // Note: These must be computed _before_ we call .image()
53
+ const alreadyLoaded = this.imageCache.imageLoaded(this.page.index, finalReduce);
54
+ const nextBestLoadedReduce = this.imageCache.getBestLoadedReduce(this.page.index, reduce);
55
+
56
+ // Avoid removing/re-adding the image if it's already there
57
+ // This can be called quite a bit, so we need to be fast
58
+ if (this.$img?.data('src') == newImageURI) {
59
+ return this;
60
+ }
61
+
62
+ let $oldImg = this.$img;
63
+ this.$img = this.imageCache.image(this.page.index, finalReduce);
64
+ if ($oldImg) {
65
+ this.$img.insertAfter($oldImg);
66
+ } else {
67
+ this.$img.prependTo(this.$container);
68
+ }
69
+
70
+ if (!alreadyLoaded) {
71
+ this.$container.addClass('BRpageloading');
72
+ }
73
+
74
+ if (!alreadyLoaded && nextBestLoadedReduce) {
75
+ // If we have a slightly lower quality image loaded, use that as the background
76
+ // while the higher res one loads
77
+ const nextBestUri = this.page.getURI(nextBestLoadedReduce, 0);
78
+ if ($oldImg) {
79
+ if ($oldImg.data('src') == nextBestUri) {
80
+ // Do nothing! It's already showing the right thing
81
+ } else {
82
+ // We have a different src, need to update the src
83
+ this.imageCache.image(this.page.index, nextBestLoadedReduce, $oldImg[0]);
84
+ }
85
+ } else {
86
+ // We don't have an old <img>, so we need to create a new one
87
+ $oldImg = this.imageCache.image(this.page.index, nextBestLoadedReduce);
88
+ $oldImg.prependTo(this.$container);
89
+ }
90
+ }
91
+
92
+ this.$img
93
+ .one('load', async (ev) => {
94
+ this.$container.removeClass('BRpageloading');
95
+ // `load` can fire a little early, so wait a spell before removing the old image
96
+ // to avoid flicker
97
+ await sleep(100);
98
+ $oldImg?.remove();
99
+ });
100
+
101
+ return this;
102
+ }
103
+ }
104
+
105
+
106
+ /**
107
+ * @param {PageModel} page
108
+ * @param {string} className
109
+ */
110
+ export function createSVGPageLayer(page, className) {
111
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
112
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
113
+ svg.setAttribute("viewBox", `0 0 ${page.width} ${page.height}`);
114
+ svg.setAttribute('class', `BRPageLayer ${className}`);
115
+ svg.setAttribute('preserveAspectRatio', 'none');
116
+ return svg;
117
+ }
118
+
119
+ /**
120
+ * @param {PageModel} page
121
+ * @param {string} className
122
+ */
123
+ export function createDIVPageLayer(page, className) {
124
+ const div = document.createElement("div");
125
+ div.style.width = `${page.width}px`;
126
+ div.style.height = `${page.height}px`;
127
+ div.setAttribute('class', `BRPageLayer ${className}`);
128
+ return div;
129
+ }
130
+
131
+ /**
132
+ * @param {{ l: number, r: number, b: number, t: number }} box
133
+ */
134
+ export function boxToSVGRect({ l: left, r: right, b: bottom, t: top }) {
135
+ const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
136
+ rect.setAttribute("x", left.toString());
137
+ rect.setAttribute("y", top.toString());
138
+ rect.setAttribute("width", (right - left).toString());
139
+ rect.setAttribute("height", (bottom - top).toString());
140
+
141
+ // Some style; corner radius 4px. Can't set this in CSS yet
142
+ rect.setAttribute("rx", "4");
143
+ rect.setAttribute("ry", "4");
144
+ return rect;
145
+ }
146
+
147
+ /**
148
+ * @param {string} layerClass
149
+ * @param {Array<{ l: number, r: number, b: number, t: number }>} boxes
150
+ * @param {PageModel} page
151
+ * @param {HTMLElement} containerEl
152
+ * @param {string[]} [rectClasses] CSS classes to add to the rects
153
+ */
154
+ export function renderBoxesInPageContainerLayer(layerClass, boxes, page, containerEl, rectClasses = null) {
155
+ const mountedSvg = containerEl.querySelector(`.${layerClass}`);
156
+ // Create the layer if it's not there
157
+ const svg = mountedSvg || createSVGPageLayer(page, layerClass);
158
+ if (!mountedSvg) {
159
+ // Insert after the image if the image is already loaded.
160
+ const imgEl = containerEl.querySelector('.BRpageimage');
161
+ if (imgEl) $(svg).insertAfter(imgEl);
162
+ else $(svg).prependTo(containerEl);
163
+ }
164
+
165
+ for (const [i, box] of boxes.entries()) {
166
+ const rect = boxToSVGRect(box);
167
+ if (rectClasses) {
168
+ rect.setAttribute('class', rectClasses[i]);
169
+ }
170
+ svg.appendChild(rect);
171
+ }
172
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @typedef {object} ReduceSet Set of valid numbers for a reduce variable.
3
+ * @property {(n: number) => number} floor
4
+ * @property {(n: number) => number} decr Return the predecessor of the given element
5
+ */
6
+
7
+ /** @type {ReduceSet} */
8
+ export const IntegerReduceSet = {
9
+ floor: Math.floor,
10
+ decr(n) { return n - 1; },
11
+ };
12
+
13
+ /** @type {ReduceSet} */
14
+ export const Pow2ReduceSet = {
15
+ floor(n) {
16
+ return 2 ** (Math.floor(Math.log2(Math.max(1, n))));
17
+ },
18
+ decr(n) {
19
+ return 2 ** (Math.log2(n) - 1);
20
+ },
21
+ };
22
+
23
+ export const NAMED_REDUCE_SETS = {
24
+ pow2: Pow2ReduceSet,
25
+ integer: IntegerReduceSet,
26
+ };