@internetarchive/bookreader 5.0.0-8 → 5.0.0-80

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 (313) hide show
  1. package/.eslintrc.js +17 -15
  2. package/.github/workflows/node.js.yml +73 -10
  3. package/.github/workflows/npm-publish.yml +6 -20
  4. package/.testcaferc.js +10 -0
  5. package/BookReader/BookReader.css +398 -1133
  6. package/BookReader/BookReader.js +1 -1
  7. package/BookReader/BookReader.js.LICENSE.txt +20 -20
  8. package/BookReader/BookReader.js.map +1 -1
  9. package/BookReader/ia-bookreader-bundle.js +1782 -0
  10. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -0
  11. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  12. package/BookReader/icons/1up.svg +1 -1
  13. package/BookReader/icons/2up.svg +1 -1
  14. package/BookReader/icons/advance.svg +1 -1
  15. package/BookReader/icons/chevron-right.svg +1 -1
  16. package/BookReader/icons/close-circle-dark.svg +1 -1
  17. package/BookReader/icons/close-circle.svg +1 -1
  18. package/BookReader/icons/fullscreen.svg +1 -1
  19. package/BookReader/icons/fullscreen_exit.svg +1 -1
  20. package/BookReader/icons/hamburger.svg +1 -1
  21. package/BookReader/icons/left-arrow.svg +1 -1
  22. package/BookReader/icons/magnify-minus.svg +1 -1
  23. package/BookReader/icons/magnify-plus.svg +1 -1
  24. package/BookReader/icons/magnify.svg +1 -1
  25. package/BookReader/icons/pause.svg +1 -1
  26. package/BookReader/icons/play.svg +1 -1
  27. package/BookReader/icons/playback-speed.svg +1 -1
  28. package/BookReader/icons/read-aloud.svg +1 -1
  29. package/BookReader/icons/review.svg +1 -1
  30. package/BookReader/icons/thumbnails.svg +1 -1
  31. package/BookReader/icons/voice.svg +1 -0
  32. package/BookReader/icons/volume-full.svg +1 -1
  33. package/BookReader/images/BRicons.svg +3 -3
  34. package/BookReader/images/books_graphic.svg +1 -1
  35. package/BookReader/images/icon_book.svg +1 -1
  36. package/BookReader/images/icon_bookmark.svg +1 -1
  37. package/BookReader/images/icon_gear.svg +1 -1
  38. package/BookReader/images/icon_hamburger.svg +1 -1
  39. package/BookReader/images/icon_home.svg +1 -1
  40. package/BookReader/images/icon_info.svg +1 -1
  41. package/BookReader/images/icon_one_page.svg +1 -1
  42. package/BookReader/images/icon_pause.svg +1 -1
  43. package/BookReader/images/icon_play.svg +1 -1
  44. package/BookReader/images/icon_playback-rate.svg +1 -1
  45. package/BookReader/images/icon_search_button.svg +1 -1
  46. package/BookReader/images/icon_share.svg +1 -1
  47. package/BookReader/images/icon_skip-ahead.svg +1 -1
  48. package/BookReader/images/icon_skip-back.svg +1 -1
  49. package/BookReader/images/icon_speaker.svg +1 -1
  50. package/BookReader/images/icon_speaker_open.svg +1 -1
  51. package/BookReader/images/icon_thumbnails.svg +1 -1
  52. package/BookReader/images/icon_toc.svg +1 -1
  53. package/BookReader/images/icon_two_pages.svg +1 -1
  54. package/BookReader/images/marker_chap-off.svg +1 -1
  55. package/BookReader/images/marker_chap-on.svg +1 -1
  56. package/BookReader/images/marker_srch-on.svg +1 -1
  57. package/BookReader/jquery-3.js +2 -0
  58. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  59. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  60. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  61. package/BookReader/plugins/plugin.autoplay.js +1 -1
  62. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  63. package/BookReader/plugins/plugin.chapters.js +25 -1
  64. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
  65. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  66. package/BookReader/plugins/plugin.iframe.js +1 -1
  67. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  68. package/BookReader/plugins/plugin.iiif.js +2 -0
  69. package/BookReader/plugins/plugin.iiif.js.map +1 -0
  70. package/BookReader/plugins/plugin.resume.js +1 -1
  71. package/BookReader/plugins/plugin.resume.js.map +1 -1
  72. package/BookReader/plugins/plugin.search.js +2 -1
  73. package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
  74. package/BookReader/plugins/plugin.search.js.map +1 -1
  75. package/BookReader/plugins/plugin.text_selection.js +2 -1
  76. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
  77. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  78. package/BookReader/plugins/plugin.tts.js +1 -1
  79. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +2 -0
  80. package/BookReader/plugins/plugin.tts.js.map +1 -1
  81. package/BookReader/plugins/plugin.url.js +1 -1
  82. package/BookReader/plugins/plugin.url.js.map +1 -1
  83. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  84. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  85. package/BookReader/webcomponents-bundle.js +3 -0
  86. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  87. package/BookReader/webcomponents-bundle.js.map +1 -0
  88. package/BookReaderDemo/BookReaderDemo.css +18 -19
  89. package/BookReaderDemo/BookReaderJSAdvanced.js +0 -3
  90. package/BookReaderDemo/BookReaderJSAutoplay.js +4 -1
  91. package/BookReaderDemo/BookReaderJSSimple.js +1 -0
  92. package/BookReaderDemo/IADemoBr.js +147 -0
  93. package/BookReaderDemo/demo-advanced.html +2 -2
  94. package/BookReaderDemo/demo-autoplay.html +2 -3
  95. package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
  96. package/BookReaderDemo/demo-fullscreen-mobile.html +3 -5
  97. package/BookReaderDemo/demo-fullscreen.html +2 -4
  98. package/BookReaderDemo/demo-iiif.html +99 -12
  99. package/BookReaderDemo/demo-internetarchive.html +214 -18
  100. package/BookReaderDemo/demo-multiple.html +2 -1
  101. package/BookReaderDemo/demo-preview-pages.html +2 -1
  102. package/BookReaderDemo/demo-simple.html +2 -1
  103. package/BookReaderDemo/demo-vendor-fullscreen.html +2 -4
  104. package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
  105. package/BookReaderDemo/immersion-1up.html +2 -2
  106. package/BookReaderDemo/immersion-mode.html +2 -4
  107. package/BookReaderDemo/toggle_controls.html +3 -2
  108. package/BookReaderDemo/view_mode.html +2 -1
  109. package/BookReaderDemo/viewmode-cycle.html +2 -3
  110. package/CHANGELOG.md +536 -33
  111. package/README.md +14 -1
  112. package/babel.config.js +20 -0
  113. package/codecov.yml +6 -0
  114. package/index.html +4 -1
  115. package/jsconfig.json +19 -0
  116. package/netlify.toml +9 -0
  117. package/package.json +70 -60
  118. package/renovate.json +52 -0
  119. package/scripts/preversion.js +0 -1
  120. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  121. package/src/BookNavigator/assets/button-base.js +4 -2
  122. package/src/BookNavigator/assets/ia-logo.js +17 -0
  123. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  124. package/src/BookNavigator/assets/icon_close.js +1 -1
  125. package/src/BookNavigator/book-navigator.js +590 -0
  126. package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
  127. package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
  128. package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
  129. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
  130. package/src/BookNavigator/bookmarks/bookmarks-provider.js +27 -17
  131. package/src/BookNavigator/bookmarks/ia-bookmarks.js +116 -67
  132. package/src/BookNavigator/delete-modal-actions.js +1 -1
  133. package/src/BookNavigator/downloads/downloads-provider.js +36 -21
  134. package/src/BookNavigator/downloads/downloads.js +41 -25
  135. package/src/BookNavigator/search/search-provider.js +49 -27
  136. package/src/BookNavigator/search/search-results.js +23 -9
  137. package/src/BookNavigator/sharing.js +27 -0
  138. package/src/BookNavigator/viewable-files.js +95 -0
  139. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
  140. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
  141. package/src/BookReader/BookModel.js +64 -34
  142. package/src/BookReader/DragScrollable.js +233 -0
  143. package/src/BookReader/Mode1Up.js +56 -351
  144. package/src/BookReader/Mode1UpLit.js +388 -0
  145. package/src/BookReader/Mode2Up.js +73 -1318
  146. package/src/BookReader/Mode2UpLit.js +776 -0
  147. package/src/BookReader/ModeCoordinateSpace.js +29 -0
  148. package/src/BookReader/ModeSmoothZoom.js +312 -0
  149. package/src/BookReader/ModeThumb.js +18 -12
  150. package/src/BookReader/Navbar/Navbar.js +14 -40
  151. package/src/BookReader/PageContainer.js +81 -6
  152. package/src/BookReader/ReduceSet.js +1 -1
  153. package/src/BookReader/Toolbar/Toolbar.js +10 -37
  154. package/src/BookReader/events.js +2 -3
  155. package/src/BookReader/options.js +27 -2
  156. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  157. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  158. package/src/BookReader/utils/SelectionObserver.js +45 -0
  159. package/src/BookReader/utils.js +118 -13
  160. package/src/BookReader.js +427 -1061
  161. package/src/assets/icons/magnify-minus.svg +3 -7
  162. package/src/assets/icons/magnify-plus.svg +3 -7
  163. package/src/assets/icons/voice.svg +1 -0
  164. package/src/css/BookReader.scss +1 -5
  165. package/src/css/_BRBookmarks.scss +1 -1
  166. package/src/css/_BRComponent.scss +1 -1
  167. package/src/css/_BRmain.scss +16 -3
  168. package/src/css/_BRnav.scss +12 -39
  169. package/src/css/_BRpages.scss +149 -40
  170. package/src/css/_BRsearch.scss +68 -25
  171. package/src/css/_BRtoolbar.scss +5 -5
  172. package/src/css/_TextSelection.scss +87 -27
  173. package/src/css/_colorbox.scss +2 -2
  174. package/src/css/_controls.scss +20 -7
  175. package/src/css/_icons.scss +1 -1
  176. package/src/ia-bookreader/ia-bookreader.js +224 -0
  177. package/src/plugins/plugin.archive_analytics.js +3 -3
  178. package/src/plugins/plugin.autoplay.js +5 -11
  179. package/src/plugins/plugin.chapters.js +237 -191
  180. package/src/plugins/plugin.iiif.js +151 -0
  181. package/src/plugins/plugin.resume.js +3 -3
  182. package/src/plugins/plugin.text_selection.js +464 -134
  183. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  184. package/src/plugins/search/plugin.search.js +142 -125
  185. package/src/plugins/search/utils.js +43 -0
  186. package/src/plugins/search/view.js +33 -58
  187. package/src/plugins/tts/AbstractTTSEngine.js +71 -40
  188. package/src/plugins/tts/FestivalTTSEngine.js +13 -14
  189. package/src/plugins/tts/PageChunk.js +15 -21
  190. package/src/plugins/tts/PageChunkIterator.js +8 -12
  191. package/src/plugins/tts/WebTTSEngine.js +87 -71
  192. package/src/plugins/tts/plugin.tts.js +96 -127
  193. package/src/plugins/tts/utils.js +15 -25
  194. package/src/plugins/url/UrlPlugin.js +191 -0
  195. package/src/plugins/{plugin.url.js → url/plugin.url.js} +45 -16
  196. package/src/util/browserSniffing.js +22 -0
  197. package/src/util/docCookies.js +21 -2
  198. package/tests/e2e/README.md +37 -0
  199. package/tests/e2e/autoplay.test.js +2 -2
  200. package/tests/e2e/base.test.js +8 -16
  201. package/tests/e2e/helpers/base.js +53 -48
  202. package/tests/e2e/helpers/debug.js +1 -1
  203. package/tests/e2e/helpers/params.js +17 -0
  204. package/tests/e2e/helpers/rightToLeft.js +8 -14
  205. package/tests/e2e/helpers/search.js +73 -0
  206. package/tests/e2e/models/Navigation.js +20 -37
  207. package/tests/e2e/rightToLeft.test.js +4 -5
  208. package/tests/e2e/viewmode.test.js +40 -33
  209. package/tests/jest/BookNavigator/book-navigator.test.js +661 -0
  210. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
  211. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  212. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  213. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  214. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
  215. package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
  216. package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
  217. package/tests/{karma → jest}/BookNavigator/search/search-results.test.js +109 -60
  218. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
  219. package/tests/jest/BookNavigator/viewable-files/viewable-files-provider.test.js +80 -0
  220. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  221. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +74 -14
  222. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +193 -0
  223. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  224. package/tests/jest/BookReader/Mode1UpLit.test.js +73 -0
  225. package/tests/jest/BookReader/Mode2Up.test.js +98 -0
  226. package/tests/jest/BookReader/Mode2UpLit.test.js +190 -0
  227. package/tests/jest/BookReader/ModeCoordinateSpace.test.js +16 -0
  228. package/tests/jest/BookReader/ModeSmoothZoom.test.js +218 -0
  229. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  230. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +10 -10
  231. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
  232. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  233. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  234. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  235. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  236. package/tests/jest/BookReader/utils/SelectionObserver.test.js +57 -0
  237. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  238. package/tests/jest/BookReader/utils.test.js +229 -0
  239. package/tests/jest/BookReader.keyboard.test.js +190 -0
  240. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  241. package/tests/{BookReader.test.js → jest/BookReader.test.js} +26 -37
  242. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  243. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
  244. package/tests/jest/plugins/plugin.chapters.test.js +195 -0
  245. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  246. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  247. package/tests/jest/plugins/plugin.text_selection.test.js +317 -0
  248. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  249. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +25 -47
  250. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +39 -6
  251. package/tests/jest/plugins/search/utils.js +25 -0
  252. package/tests/jest/plugins/search/utils.test.js +29 -0
  253. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +29 -9
  254. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  255. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  256. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  257. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +47 -1
  258. package/tests/{plugins → jest/plugins}/tts/utils.test.js +1 -60
  259. package/tests/jest/plugins/url/UrlPlugin.test.js +198 -0
  260. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +53 -14
  261. package/tests/jest/setup.js +3 -0
  262. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  263. package/tests/jest/util/docCookies.test.js +24 -0
  264. package/tests/{util → jest/util}/strings.test.js +1 -1
  265. package/tests/{utils.js → jest/utils.js} +38 -0
  266. package/webpack.config.js +12 -6
  267. package/.babelrc +0 -12
  268. package/.dependabot/config.yml +0 -6
  269. package/.testcaferc.json +0 -5
  270. package/BookReader/bookreader-component-bundle.js +0 -1450
  271. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  272. package/BookReader/bookreader-component-bundle.js.map +0 -1
  273. package/BookReader/jquery-1.10.1.js +0 -2
  274. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  275. package/BookReader/plugins/plugin.menu_toggle.js +0 -2
  276. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  277. package/BookReader/plugins/plugin.mobile_nav.js +0 -2
  278. package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
  279. package/BookReaderDemo/IIIFBookReader.js +0 -207
  280. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  281. package/BookReaderDemo/demo-iiif.js +0 -26
  282. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  283. package/karma.conf.js +0 -23
  284. package/src/BookNavigator/BookModel.js +0 -14
  285. package/src/BookNavigator/BookNavigator.js +0 -446
  286. package/src/BookNavigator/assets/book-loader.js +0 -27
  287. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  288. package/src/BookNavigator/search/a-search-result.js +0 -55
  289. package/src/BookReader/DebugConsole.js +0 -54
  290. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  291. package/src/ItemNavigator/ItemNavigator.js +0 -376
  292. package/src/ItemNavigator/providers/sharing.js +0 -29
  293. package/src/css/_MobileNav.scss +0 -194
  294. package/src/dragscrollable-br.js +0 -261
  295. package/src/lit-wrapper.js +0 -2
  296. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  297. package/src/plugins/plugin.mobile_nav.js +0 -287
  298. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  299. package/tests/BookReader/DebugConsole.test.js +0 -25
  300. package/tests/BookReader/Mode1Up.test.js +0 -164
  301. package/tests/BookReader/Mode2Up.test.js +0 -247
  302. package/tests/BookReader/utils.test.js +0 -109
  303. package/tests/e2e/helpers/desktopSearch.js +0 -72
  304. package/tests/e2e/helpers/mobileSearch.js +0 -85
  305. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  306. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  307. package/tests/karma/BookNavigator/search/search-provider.test.js +0 -23
  308. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  309. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
  310. package/tests/plugins/plugin.chapters.test.js +0 -130
  311. package/tests/plugins/plugin.mobile_nav.test.js +0 -66
  312. package/tests/plugins/plugin.text_selection.test.js +0 -203
  313. package/tests/util/docCookies.test.js +0 -15
@@ -1,15 +1,9 @@
1
1
  // @ts-check
2
- // effect.js gives acces to extra easing function (e.g. easeInSine)
3
- import 'jquery-ui/ui/effect.js';
4
- import '../dragscrollable-br.js';
5
- import { clamp } from './utils.js';
6
- import { EVENTS } from './events.js';
7
-
2
+ import { Mode2UpLit } from './Mode2UpLit.js';
3
+ import { DragScrollable } from './DragScrollable.js';
8
4
  /** @typedef {import('../BookReader.js').default} BookReader */
9
5
  /** @typedef {import('./BookModel.js').BookModel} BookModel */
10
6
  /** @typedef {import('./BookModel.js').PageIndex} PageIndex */
11
- /** @typedef {import('./options.js').BookReaderOptions} BookReaderOptions */
12
- /** @typedef {import('./PageContainer.js').PageContainer} PageContainer */
13
7
 
14
8
  export class Mode2Up {
15
9
  /**
@@ -19,1332 +13,93 @@ export class Mode2Up {
19
13
  constructor(br, bookModel) {
20
14
  this.br = br;
21
15
  this.book = bookModel;
22
-
23
- /** @type {HTMLDivElement} */
24
- this.leafEdgeL = null;
25
- /** @type {HTMLDivElement} */
26
- this.leafEdgeR = null;
27
-
28
- /** @type {{ [index: number]: PageContainer }} */
29
- this.pageContainers = {};
30
- }
31
-
32
- /**
33
- * @param {PageIndex} index
34
- */
35
- jumpToIndex(index) {
36
- // By checking against min/max we do nothing if requested index
37
- // is current
38
- if (index < Math.min(this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR)) {
39
- this.flipBackToIndex(index);
40
- } else if (index > Math.max(this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR)) {
41
- this.flipFwdToIndex(index);
42
- }
43
- }
44
-
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
- /**
58
- * Draws book spread,
59
- * sets event handlers,
60
- * sets: `this.br.displayedIndices`
61
- * updates toolbar zoom
62
- * Important: `this.br.refs.$brTwoPageView` parent container must be emptied before calling
63
- */
64
- drawLeafs() {
65
- const $twoPageViewEl = this.br.refs.$brTwoPageView;
66
- const indexL = this.br.twoPage.currentIndexL;
67
- const indexR = this.br.twoPage.currentIndexR;
68
-
69
- this.createPageContainer(indexL).$container
70
- .css(this.leftLeafCss)
71
- .appendTo($twoPageViewEl);
72
- this.createPageContainer(indexR).$container
73
- .css(this.rightLeafCss)
74
- .appendTo($twoPageViewEl);
75
-
76
- this.displayedIndices = [this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR];
77
- this.setMouseHandlers();
78
- this.br.displayedIndices = this.displayedIndices;
79
- this.br.updateToolbarZoom(this.br.reduce);
80
- this.br.trigger('pageChanged');
81
- }
82
-
83
- /**
84
- * @param {1} direction
85
- */
86
- zoom(direction) {
87
- this.br.stopFlipAnimations();
88
-
89
- // Recalculate autofit factors
90
- this.calculateReductionFactors();
91
-
92
- // Get new zoom state
93
- const reductionFactor = this.br.nextReduce(this.br.reduce, direction, this.br.twoPage.reductionFactors);
94
- if ((this.br.reduce == reductionFactor.reduce) && (this.br.twoPage.autofit == reductionFactor.autofit)) {
95
- // Same zoom
96
- return;
97
- }
98
- this.br.twoPage.autofit = reductionFactor.autofit;
99
- this.br.reduce = reductionFactor.reduce;
100
- this.br.pageScale = this.br.reduce; // preserve current reduce
101
-
102
- // Preserve view center position
103
- const oldCenter = this.getViewCenter();
104
-
105
- // Prepare view with new center to minimize visual glitches
106
- const drawNewSpread = true;
107
- this.prepareTwoPageView(oldCenter.percentageX, oldCenter.percentageY, drawNewSpread);
108
- }
109
-
110
- /**
111
- * Resize spread containers, does not prefetch
112
- * uses `this.br.twoPage` properties
113
- */
114
- resizeSpread() {
115
- this.br.resizeBRcontainer(false); // no animation
116
- this.calculateSpreadSize();
117
-
118
- this.br.refs?.$brTwoPageView.css(this.mainContainerCss);
119
- this.centerView(); // let function self adjust
120
-
121
- $(this.br.twoPage.coverDiv).css(this.spreadCoverCss); // click sheath is memoized somehow
122
- const $spreadLayers = this.br.refs.$brTwoPageView;
123
-
124
- $spreadLayers.find('.BRleafEdgeR')?.css(this.leafEdgeRCss);
125
- $spreadLayers.find('.BRleafEdgeL')?.css(this.leafEdgeLCss);
126
- $spreadLayers.find('.BRgutter')?.css(this.spineCss);
127
-
128
- const indexL = this.br.twoPage.currentIndexL;
129
- const indexR = this.br.twoPage.currentIndexR;
130
- this.pageContainers[indexL].$container.css(this.leftLeafCss);
131
- this.pageContainers[indexR].$container.css(this.rightLeafCss);
132
- }
133
-
134
- /**
135
- * @param {number} centerPercentageX
136
- * @param {number} centerPercentageY
137
- * @param {Boolean} drawNewSpread
138
- */
139
- prepareTwoPageView(centerPercentageX, centerPercentageY, drawNewSpread = false) {
140
- // Some decisions about two page view:
141
- //
142
- // Both pages will be displayed at the same height, even if they were different physical/scanned
143
- // sizes. This simplifies the animation (from a design as well as technical standpoint). We
144
- // examine the page aspect ratios (in calculateSpreadSize) and use the page with the most "normal"
145
- // aspect ratio to determine the height.
146
- //
147
- // The two page view div is resized to keep the middle of the book in the middle of the div
148
- // even as the page sizes change. To e.g. keep the middle of the book in the middle of the BRcontent
149
- // div requires adjusting the offset of BRtwpageview and/or scrolling in BRcontent.
150
- const startingReduce = this.br.reduce;
151
- const startingIndices = this.br.displayedIndices;
152
-
153
- this.br.refs.$brContainer.empty();
154
- this.br.refs.$brContainer.css('overflow', 'auto');
155
-
156
- // We want to display two facing pages. We may be missing
157
- // one side of the spread because it is the first/last leaf,
158
- // foldouts, missing pages, etc
159
-
160
- const targetLeaf = clamp(this.br.firstIndex, this.br.firstDisplayableIndex(), this.br.lastDisplayableIndex());
161
- const currentSpreadIndices = this.book.getSpreadIndices(targetLeaf);
162
- this.br.twoPage.currentIndexL = currentSpreadIndices[0];
163
- this.br.twoPage.currentIndexR = currentSpreadIndices[1];
164
-
165
- this.calculateSpreadSize(); //sets this.br.reduce, twoPage.width, twoPage.height and others
166
-
167
- /* check if calculations have changed that warrant a new book draw */
168
- const sameReducer = startingReduce == this.br.reduce;
169
- const sameStart = startingIndices == this.br.displayedIndices;
170
- const hasNewDisplayPagesOrDimensions = !sameStart || (sameStart && !sameReducer);
171
-
172
- if (drawNewSpread || hasNewDisplayPagesOrDimensions) {
173
- this.prunePageContainers();
174
- this.prefetch();
175
- }
176
-
177
- // Add the two page view
178
- // $$$ Can we get everything set up and then append?
179
- const $twoPageViewEl = $('<div class="BRtwopageview"></div>');
180
- this.br.refs.$brTwoPageView = $twoPageViewEl;
181
- this.br.refs.$brContainer.append($twoPageViewEl);
182
-
183
- // 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);
186
-
187
- // $$$ calculate container size first
188
- this.br.refs?.$brTwoPageView.css(this.mainContainerCss);
189
-
190
- // This will trump the incoming coordinates
191
- // in order to center book when zooming out
192
- if (this.br.twoPage.totalWidth < this.br.refs.$brContainer.prop('clientWidth')) {
193
- centerPercentageX = 0.5;
194
- }
195
- if (this.br.twoPage.totalHeight < this.br.refs.$brContainer.prop('clientHeight')) {
196
- centerPercentageY = 0.5;
197
- }
198
-
199
- this.centerView(centerPercentageX, centerPercentageY);
200
-
201
- // then set
202
- this.br.twoPage.coverDiv = document.createElement('div');
203
- $(this.br.twoPage.coverDiv).attr('class', 'BRbookcover').css(this.spreadCoverCss).appendTo(this.br.refs.$brTwoPageView);
204
-
205
- this.leafEdgeR = document.createElement('div');
206
- this.leafEdgeR.className = 'BRleafEdgeR';
207
- $(this.leafEdgeR).css(this.leafEdgeRCss).appendTo(this.br.refs.$brTwoPageView);
208
-
209
- this.leafEdgeL = document.createElement('div');
210
- this.leafEdgeL.className = 'BRleafEdgeL';
211
- $(this.leafEdgeL).css(this.leafEdgeLCss).appendTo(this.br.refs.$brTwoPageView);
212
-
213
- const div = document.createElement('div');
214
- $(div).attr('class', 'BRgutter').css(this.spineCss).appendTo(this.br.refs.$brTwoPageView);
215
-
216
- this.preparePopUp();
217
-
218
- this.br.displayedIndices = [];
219
-
220
- this.drawLeafs();
221
- this.br.updateToolbarZoom(this.br.reduce);
222
-
223
- if (this.br.enableSearch) {
224
- this.br.removeSearchHilites();
225
- this.br.updateSearchHilites();
226
- }
227
-
228
- this.br.updateBrClasses();
229
- }
230
-
231
- prunePageContainers() {
232
- for (const index in this.pageContainers) {
233
- if ((index != this.br.twoPage.currentIndexL) && (index != this.br.twoPage.currentIndexR)) {
234
- $(this.pageContainers[index].$container).remove();
235
- }
236
- if ((index < this.br.twoPage.currentIndexL - 4) || (index > this.br.twoPage.currentIndexR + 4)) {
237
- delete this.pageContainers[index];
238
- }
239
- }
240
- }
241
-
242
- /**
243
- * This function prepares the "View Page n" popup that shows while the mouse is
244
- * over the left/right "stack of sheets" edges. It also binds the mouse
245
- * events for these divs.
246
- */
247
- preparePopUp() {
248
- this.br.twoPagePopUp = document.createElement('div');
249
- this.br.twoPagePopUp.className = 'BRtwoPagePopUp';
250
- $(this.br.twoPagePopUp).css({
251
- zIndex: '1000'
252
- }).appendTo(this.br.refs.$brContainer);
253
- $(this.br.twoPagePopUp).hide();
254
-
255
- const leafEdges = [
256
- {
257
- $leafEdge: $(this.leafEdgeL),
258
- /** @type {function(number): PageIndex} */
259
- jumpIndexForPageX: this.jumpIndexForLeftEdgePageX.bind(this),
260
- leftOffset: () => -$(this.br.twoPagePopUp).width() + 120,
261
- },
262
- {
263
- $leafEdge: $(this.leafEdgeR),
264
- /** @type {function(number): PageIndex} */
265
- jumpIndexForPageX: this.jumpIndexForRightEdgePageX.bind(this),
266
- leftOffset: () => -120,
267
- },
268
- ];
269
-
270
- for (const { $leafEdge, jumpIndexForPageX, leftOffset } of leafEdges) {
271
- $leafEdge.on('mouseenter', () => $(this.br.twoPagePopUp).show());
272
- $leafEdge.on('mouseleave', () => $(this.br.twoPagePopUp).hide());
273
-
274
- $leafEdge.on('click', e => {
275
- this.br.trigger(EVENTS.stop);
276
- this.br.jumpToIndex(jumpIndexForPageX(e.pageX));
277
- });
278
-
279
- $leafEdge.on('mousemove', e => {
280
- const jumpIndex = clamp(jumpIndexForPageX(e.pageX), 0, this.book.getNumLeafs() - 1);
281
- $(this.br.twoPagePopUp).text(`View ${this.book.getPageName(jumpIndex)}`);
282
-
283
- // $$$ TODO: Make sure popup is positioned so that it is in view
284
- // (https://bugs.edge.launchpad.net/gnubook/+bug/327456)
285
- $(this.br.twoPagePopUp).css({
286
- left: `${e.pageX - this.br.refs.$brContainer.offset().left + this.br.refs.$brContainer.scrollLeft() + leftOffset()}px`,
287
- top: `${e.pageY - this.br.refs.$brContainer.offset().top + this.br.refs.$brContainer.scrollTop()}px`
16
+ this.mode2UpLit = new Mode2UpLit(bookModel, br);
17
+ this.mode2UpLit.flipSpeed = br.flipSpeed;
18
+
19
+ /** @private */
20
+ this.$el = $(this.mode2UpLit)
21
+ .attr('autoFit', this.br.options.twoPage.autofit)
22
+ // We CANNOT use `br-mode-2up` as a class, because it's the same
23
+ // as the name of the web component, and the webcomponents polyfill
24
+ // uses the name of component as a class for style scoping 😒
25
+ .addClass('br-mode-2up__root BRmode2up');
26
+
27
+ /** Has mode2up ever been rendered before? */
28
+ this.everShown = false;
29
+ }
30
+
31
+ /**
32
+ * This is called when we switch into this mode
33
+ */
34
+ prepare() {
35
+ const startLeaf = this.br.currentIndex();
36
+ this.br.refs.$brContainer
37
+ .empty()
38
+ .css({ overflow: 'hidden' })
39
+ .append(this.$el);
40
+ this.mode2UpLit.style.opacity = '0';
41
+
42
+ // Need this in a setTimeout so that it happens after the browser has _actually_
43
+ // appended the element to the DOM
44
+ setTimeout(async () => {
45
+ if (!this.everShown) {
46
+ this.mode2UpLit.initFirstRender(startLeaf);
47
+ this.everShown = true;
48
+ this.mode2UpLit.requestUpdate();
49
+ await this.mode2UpLit.updateComplete;
50
+
51
+ new DragScrollable(this.mode2UpLit, {
52
+ preventDefault: true,
53
+ dragSelector: '.br-mode-2up__book',
54
+ // Only handle mouse events; let browser/HammerJS handle touch
55
+ dragstart: 'mousedown',
56
+ dragcontinue: 'mousemove',
57
+ dragend: 'mouseup',
288
58
  });
289
- });
290
- }
291
- }
292
-
293
- setSpreadIndices() {
294
- const targetLeaf = clamp(this.br.firstIndex, this.br.firstDisplayableIndex(), this.br.lastDisplayableIndex());
295
- const currentSpreadIndices = this.book.getSpreadIndices(targetLeaf);
296
- this.br.twoPage.currentIndexL = currentSpreadIndices[0];
297
- this.br.twoPage.currentIndexR = currentSpreadIndices[1];
298
- }
299
-
300
- /**
301
- * Calculates 2-page spread dimensions based on this.br.twoPage.currentIndexL and
302
- * this.br.twoPage.currentIndexR
303
- * This function sets this.br.twoPage.height, twoPage.width
304
- */
305
- calculateSpreadSize() {
306
- const firstIndex = this.br.twoPage.currentIndexL;
307
- const secondIndex = this.br.twoPage.currentIndexR;
308
-
309
- // Calculate page sizes and total leaf width
310
- let spreadSize;
311
- if ( this.br.twoPage.autofit) {
312
- spreadSize = this.getIdealSpreadSize(firstIndex, secondIndex);
313
- } else {
314
- // set based on reduction factor
315
- spreadSize = this.getSpreadSizeFromReduce(firstIndex, secondIndex, this.br.reduce);
316
- }
317
- // Both pages together
318
- this.br.twoPage.height = spreadSize.height || 0;
319
- this.br.twoPage.width = spreadSize.width || 0;
320
-
321
- // Individual pages
322
- this.br.twoPage.scaledWL = this.getPageWidth(firstIndex) || 0;
323
- this.br.twoPage.scaledWR = this.getPageWidth(secondIndex) || 0;
324
-
325
- // Leaf edges
326
- this.br.twoPage.edgeWidth = spreadSize.totalLeafEdgeWidth; // The combined width of both edges
327
- this.br.twoPage.leafEdgeWidthL = this.br.leafEdgeWidth(this.br.twoPage.currentIndexL);
328
- this.br.twoPage.leafEdgeWidthR = this.br.twoPage.edgeWidth - this.br.twoPage.leafEdgeWidthL;
329
-
330
-
331
- // Book cover
332
- // The width of the book cover div. The combined width of both pages, twice the width
333
- // of the book cover internal padding (2*10) and the page edges
334
- this.br.twoPage.bookCoverDivWidth = this.coverWidth(this.br.twoPage.scaledWL + this.br.twoPage.scaledWR);
335
- // The height of the book cover div
336
- this.br.twoPage.bookCoverDivHeight = this.br.twoPage.height + 2 * this.br.twoPage.coverInternalPadding;
337
-
338
-
339
- // We calculate the total width and height for the div so that we can make the book
340
- // spine centered
341
- const leftGutterOffset = this.gutterOffsetForIndex(firstIndex);
342
- const leftWidthFromCenter = this.br.twoPage.scaledWL - leftGutterOffset + this.br.twoPage.leafEdgeWidthL;
343
- const rightWidthFromCenter = this.br.twoPage.scaledWR + leftGutterOffset + this.br.twoPage.leafEdgeWidthR;
344
- const largestWidthFromCenter = Math.max( leftWidthFromCenter, rightWidthFromCenter );
345
- this.br.twoPage.totalWidth = 2 * (largestWidthFromCenter + this.br.twoPage.coverInternalPadding + this.br.twoPage.coverExternalPadding);
346
- this.br.twoPage.totalHeight = this.br.twoPage.height + 2 * (this.br.twoPage.coverInternalPadding + this.br.twoPage.coverExternalPadding);
347
-
348
- // We want to minimize the unused space in two-up mode (maximize the amount of page
349
- // shown). We give width to the leaf edges and these widths change (though the sum
350
- // of the two remains constant) as we flip through the book. With the book
351
- // cover centered and fixed in the BRcontainer div the page images will meet
352
- // at the "gutter" which is generally offset from the center.
353
- this.br.twoPage.middle = this.br.twoPage.totalWidth >> 1;
354
- this.br.twoPage.gutter = this.br.twoPage.middle + this.gutterOffsetForIndex(firstIndex);
355
-
356
- // The left edge of the book cover moves depending on the width of the pages
357
- // $$$ change to getter
358
- this.br.twoPage.bookCoverDivLeft = this.br.twoPage.gutter - this.br.twoPage.scaledWL - this.br.twoPage.leafEdgeWidthL - this.br.twoPage.coverInternalPadding;
359
- // The top edge of the book cover stays a fixed distance from the top
360
- this.br.twoPage.bookCoverDivTop = this.br.twoPage.coverExternalPadding;
361
-
362
- // Book spine
363
- this.br.twoPage.bookSpineDivHeight = this.br.twoPage.height + 2 * this.br.twoPage.coverInternalPadding;
364
- this.br.twoPage.bookSpineDivLeft = this.br.twoPage.middle - (this.br.twoPage.bookSpineDivWidth >> 1);
365
- this.br.twoPage.bookSpineDivTop = this.br.twoPage.bookCoverDivTop;
366
-
367
- this.br.reduce = spreadSize.reduce < 0 ? this.br.reduce : spreadSize.reduce; // $$$ really set this here?
368
- }
369
-
370
- /**
371
- *
372
- * @param {number} firstIndex
373
- * @param {number} secondIndex
374
- * @return {{ width: number, height: number, totalLeafEdgeWidth: number, reduce: number}}
375
- */
376
- getIdealSpreadSize(firstIndex, secondIndex) {
377
- const ideal = {};
378
-
379
- // We check which page is closest to a "normal" page and use that to set the height
380
- // for both pages. This means that foldouts and other odd size pages will be displayed
381
- // smaller than the nominal zoom amount.
382
- const canon5Dratio = 1.5;
383
-
384
- const first = {
385
- height: this.book._getPageHeight(firstIndex),
386
- width: this.book._getPageWidth(firstIndex)
387
- };
388
-
389
- const second = {
390
- height: this.book._getPageHeight(secondIndex),
391
- width: this.book._getPageWidth(secondIndex)
392
- };
393
-
394
- const firstIndexRatio = first.height / first.width;
395
- const secondIndexRatio = second.height / second.width;
396
-
397
- let ratio;
398
- if (Math.abs(firstIndexRatio - canon5Dratio) < Math.abs(secondIndexRatio - canon5Dratio)) {
399
- ratio = firstIndexRatio;
400
- } else {
401
- ratio = secondIndexRatio;
402
- }
403
-
404
- const totalLeafEdgeWidth = Math.floor(this.book.getNumLeafs() * 0.1);
405
- const maxLeafEdgeWidth = Math.floor(this.br.refs.$brContainer.prop('clientWidth') * 0.1);
406
- ideal.totalLeafEdgeWidth = Math.min(totalLeafEdgeWidth, maxLeafEdgeWidth);
407
-
408
- const widthOutsidePages = 2 * (this.br.twoPage.coverInternalPadding + this.br.twoPage.coverExternalPadding) + ideal.totalLeafEdgeWidth;
409
- const heightOutsidePages = 2 * (this.br.twoPage.coverInternalPadding + this.br.twoPage.coverExternalPadding);
410
-
411
- ideal.width = (this.br.refs.$brContainer.width() - widthOutsidePages) >> 1;
412
- ideal.width = ideal.width > 10 ? ideal.width - 10 : 1; // $$$ fudge factor
413
-
414
- ideal.height = this.br.refs.$brContainer.height() - heightOutsidePages;
415
- ideal.height = ideal.height > 15 ? ideal.height - 15 : 1; // $$$ fudge factor
416
-
417
- if (ideal.height / ratio <= ideal.width) {
418
- //use height
419
- ideal.width = Math.floor(ideal.height / ratio) || 1;
420
- } else {
421
- //use width
422
- ideal.height = Math.floor(ideal.width * ratio) || 1;
423
- }
424
-
425
- // $$$ check this logic with large spreads
426
- ideal.reduce = Math.round(((first.height + second.height) / 2) / ideal.height);
427
-
428
- return ideal;
429
- }
430
-
431
- /**
432
- * Returns the spread size calculated from the reduction factor for the given pages
433
- * @param {number} firstIndex
434
- * @param {number} secondIndex
435
- * @return {Object}
436
- */
437
- getSpreadSizeFromReduce(firstIndex, secondIndex, reduce) {
438
- const spreadSize = {};
439
- // $$$ Scale this based on reduce?
440
- const totalLeafEdgeWidth = Math.floor(this.book.getNumLeafs() * 0.1);
441
- // $$$ Assumes leaf edge width constant at all zoom levels
442
- const maxLeafEdgeWidth = Math.floor(this.br.refs.$brContainer.prop('clientWidth') * 0.1);
443
- spreadSize.totalLeafEdgeWidth = Math.min(totalLeafEdgeWidth, maxLeafEdgeWidth);
444
-
445
- // $$$ Possibly incorrect -- we should make height "dominant"
446
- const nativeWidth = this.book._getPageWidth(firstIndex) + this.book._getPageWidth(secondIndex);
447
- const nativeHeight = this.book._getPageHeight(firstIndex) + this.book._getPageHeight(secondIndex);
448
- spreadSize.height = Math.floor( (nativeHeight / 2) / this.br.reduce );
449
- spreadSize.width = Math.floor( (nativeWidth / 2) / this.br.reduce );
450
- spreadSize.reduce = reduce;
451
-
452
- return spreadSize;
453
- }
454
-
455
- /**
456
- * Returns the current ideal reduction factor
457
- * @return {number}
458
- */
459
- getAutofitReduce() {
460
- const spreadSize = this.getIdealSpreadSize(this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR);
461
- return spreadSize.reduce;
462
- }
463
-
464
- /**
465
- * Returns true if the pages extend past the edge of the view
466
- * @deprecated slated for deprecation by v5.0.0
467
- * @return {boolean}
468
- */
469
- isZoomedIn() {
470
- let isZoomedIn = false;
471
- if (this.br.twoPage.autofit != 'auto') {
472
- if (this.br.reduce < this.getAutofitReduce()) {
473
- isZoomedIn = true;
59
+ } else {
60
+ await this.mode2UpLit.jumpToIndex(startLeaf, { smooth: false });
61
+ this.resizePageView();
474
62
  }
475
- }
476
- return isZoomedIn;
477
- }
478
-
479
- calculateReductionFactors() {
480
- this.br.twoPage.reductionFactors = this.br.reductionFactors.concat([
481
- {
482
- reduce: this.getIdealSpreadSize( this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR ).reduce,
483
- autofit: 'auto'
484
- }
485
- ]);
486
- this.br.twoPage.reductionFactors.sort(this.br._reduceSort);
487
- }
488
-
489
- /**
490
- * Set the cursor for two page view
491
- * @deprecated Since version 4.3.3. Will be deleted in version 5.0
492
- */
493
- setCursor() {
494
- console.warn('Call to deprecated method, Mode2Up.setCursor. No-op.');
495
- }
496
-
497
- /**
498
- * @param {Number|null} index to flip back one spread, pass index=null
499
- */
500
- flipBackToIndex(index) {
501
- if (this.br.constMode1up == this.br.mode) return;
502
- if (this.br.animating) return;
503
-
504
- if (null != this.br.leafEdgeTmp) {
505
- alert('error: leafEdgeTmp should be null!');
506
- return;
507
- }
508
-
509
- if (null == index) {
510
- const {currentIndexL, currentIndexR} = this.br.twoPage;
511
- const minDisplayedIndex = Math.min(currentIndexL, currentIndexR);
512
- const prev = this.book.getPage(minDisplayedIndex).findPrev({ combineConsecutiveUnviewables: true });
513
- if (!prev) return;
514
- index = prev.index;
515
- // Can only flip to a left page
516
- // (downstream code handles index = -1, so this is ok I guess)
517
- if (prev.pageSide == 'R') index--;
518
- }
519
-
520
- this.br.updateNavIndexThrottled(index);
521
-
522
- const previousIndices = this.book.getSpreadIndices(index);
523
-
524
- if (previousIndices[0] < this.br.firstDisplayableIndex() || previousIndices[1] < this.br.firstDisplayableIndex()) {
525
- return;
526
- }
527
-
528
- this.br.animating = true;
529
-
530
- if ('rl' != this.br.pageProgression) {
531
- // Assume LTR and we are going backward
532
- this.prepareFlipLeftToRight(previousIndices[0], previousIndices[1]);
533
- this.flipLeftToRight(previousIndices[0], previousIndices[1]);
534
- } else {
535
- // RTL and going backward
536
- this.prepareFlipRightToLeft(previousIndices[0], previousIndices[1]);
537
- this.flipRightToLeft(previousIndices[0], previousIndices[1]);
538
- }
539
- }
540
-
541
- /**
542
- * Flips the page on the left towards the page on the right
543
- * @param {number} newIndexL
544
- * @param {number} newIndexR
545
- */
546
- flipLeftToRight(newIndexL, newIndexR) {
547
- this.br.refs.$brContainer.addClass("BRpageFlipping");
548
- const leftLeaf = this.br.twoPage.currentIndexL;
549
-
550
- const oldLeafEdgeWidthL = this.br.leafEdgeWidth(this.br.twoPage.currentIndexL);
551
- const newLeafEdgeWidthL = this.br.leafEdgeWidth(newIndexL);
552
- const leafEdgeTmpW = oldLeafEdgeWidthL - newLeafEdgeWidthL;
553
-
554
- const currWidthL = this.getPageWidth(leftLeaf);
555
- const newWidthL = this.getPageWidth(newIndexL);
556
- const newWidthR = this.getPageWidth(newIndexR);
557
-
558
- const top = this.top();
559
- const gutter = this.br.twoPage.middle + this.gutterOffsetForIndex(newIndexL);
560
-
561
- //animation strategy:
562
- // 0. remove search highlight, if any.
563
- // 1. create a new div, called leafEdgeTmp to represent the leaf edge between the leftmost edge
564
- // of the left leaf and where the user clicked in the leaf edge.
565
- // Note that if this function was triggered by left() and not a
566
- // mouse click, the width of leafEdgeTmp is very small (zero px).
567
- // 2. animate both leafEdgeTmp to the gutter (without changing its width) and animate
568
- // leftLeaf to width=0.
569
- // 3. When step 2 is finished, animate leafEdgeTmp to right-hand side of new right leaf
570
- // (left=gutter+newWidthR) while also animating the new right leaf from width=0 to
571
- // its new full width.
572
- // 4. After step 3 is finished, do the following:
573
- // - remove leafEdgeTmp from the dom.
574
- // - resize and move the right leaf edge (leafEdgeR) to left=gutter+newWidthR
575
- // and width=twoPage.edgeWidth-newLeafEdgeWidthL.
576
- // - resize and move the left leaf edge (leafEdgeL) to left=gutter-newWidthL-newLeafEdgeWidthL
577
- // and width=newLeafEdgeWidthL.
578
- // - resize the back cover (twoPage.coverDiv) to left=gutter-newWidthL-newLeafEdgeWidthL-10
579
- // and width=newWidthL+newWidthR+twoPage.edgeWidth+20
580
- // - move new left leaf (newIndexL) forward to zindex=2 so it can receive clicks.
581
- // - remove old left and right leafs from the dom [prunePageContainers()].
582
- // - prefetch new adjacent leafs.
583
- // - set up click handlers for both new left and right leafs.
584
- // - redraw the search highlight.
585
- // - update the pagenum box and the url.
586
-
587
- const $twoPageViewEl = this.br.refs.$brTwoPageView;
588
- const leftEdgeTmpLeft = gutter - currWidthL - leafEdgeTmpW;
589
-
590
- this.br.leafEdgeTmp = document.createElement('div');
591
- this.br.leafEdgeTmp.className = 'BRleafEdgeTmp';
592
- $(this.br.leafEdgeTmp).css({
593
- width: `${leafEdgeTmpW}px`,
594
- height: `${this.br.twoPage.height}px`,
595
- left: `${leftEdgeTmpLeft}px`,
596
- top: `${top}px`,
597
- zIndex: 1000,
598
- }).appendTo($twoPageViewEl);
599
-
600
- $(this.leafEdgeL).css({
601
- width: `${newLeafEdgeWidthL}px`,
602
- left: `${gutter - currWidthL - newLeafEdgeWidthL}px`
603
- });
604
-
605
- // Left gets the offset of the current left leaf from the document
606
- const left = this.pageContainers[leftLeaf].$container.offset().left;
607
- // $$$ This seems very similar to the gutter. May be able to consolidate the logic.
608
- const right = `${$twoPageViewEl.prop('clientWidth') - left - this.pageContainers[leftLeaf].$container.width() + $twoPageViewEl.offset().left - 2}px`;
609
-
610
- // We change the left leaf to right positioning
611
- // $$$ This causes animation glitches during resize. See https://bugs.edge.launchpad.net/gnubook/+bug/328327
612
- this.pageContainers[leftLeaf].$container.css({
613
- right,
614
- left: ''
615
- });
616
-
617
- $(this.br.leafEdgeTmp).animate({left: gutter}, this.br.flipSpeed, 'easeInSine');
618
-
619
- if (this.br.enableSearch) this.br.removeSearchHilites();
620
-
621
- this.pageContainers[leftLeaf].$container.animate({width: '0px'}, this.br.flipSpeed, 'easeInSine', () => {
622
-
623
- $(this.br.leafEdgeTmp).animate({left: `${gutter + newWidthR}px`}, this.br.flipSpeed, 'easeOutSine');
624
-
625
- this.br.$('.BRgutter').css({left: `${gutter - this.br.twoPage.bookSpineDivWidth * 0.5}px`});
626
-
627
- this.pageContainers[newIndexR].$container.animate({width: `${newWidthR}px`}, this.br.flipSpeed, 'easeOutSine', () => {
628
- this.pageContainers[newIndexL].$container.css('zIndex', 2);
629
-
630
- $(this.leafEdgeR).css({
631
- // Moves the right leaf edge
632
- width: `${this.br.twoPage.edgeWidth - newLeafEdgeWidthL}px`,
633
- left: `${gutter + newWidthR}px`
634
- });
635
-
636
- $(this.leafEdgeL).css({
637
- // Moves and resizes the left leaf edge
638
- width: `${newLeafEdgeWidthL}px`,
639
- left: `${gutter - newWidthL - newLeafEdgeWidthL}px`
640
- });
641
-
642
- // Resizes the brown border div
643
- $(this.br.twoPage.coverDiv).css({
644
- width: `${this.coverWidth(newWidthL + newWidthR)}px`,
645
- left: `${gutter - newWidthL - newLeafEdgeWidthL - this.br.twoPage.coverInternalPadding}px`
646
- });
647
-
648
- $(this.br.leafEdgeTmp).remove();
649
- this.br.leafEdgeTmp = null;
650
-
651
- // $$$ TODO refactor with opposite direction flip
652
-
653
- this.br.twoPage.currentIndexL = newIndexL;
654
- this.br.twoPage.currentIndexR = newIndexR;
655
- this.br.twoPage.scaledWL = newWidthL;
656
- this.br.twoPage.scaledWR = newWidthR;
657
- this.br.twoPage.gutter = gutter;
658
-
659
- this.br.updateFirstIndex(this.br.twoPage.currentIndexL);
660
- this.br.displayedIndices = [newIndexL, newIndexR];
661
- this.prunePageContainers();
662
- this.br.animating = false;
663
-
664
- this.resizeSpread();
665
-
666
- if (this.br.enableSearch) this.br.updateSearchHilites();
667
-
668
- this.setMouseHandlers();
669
-
670
- if (this.br.animationFinishedCallback) {
671
- this.br.animationFinishedCallback();
672
- this.br.animationFinishedCallback = null;
673
- }
674
-
675
- this.br.refs.$brContainer.removeClass("BRpageFlipping");
676
- this.br.textSelectionPlugin?.stopPageFlip(this.br.refs.$brContainer);
677
- this.centerView();
678
- this.br.trigger('pageChanged');
679
-
680
- // get next previous batch immediately
681
- this.prunePageContainers();
682
- this.createPageContainer(newIndexL - 2);
683
- this.createPageContainer(newIndexR - 2);
684
- this.createPageContainer(newIndexL - 3);
685
- this.createPageContainer(newIndexR - 3);
686
- });
63
+ this.mode2UpLit.style.opacity = '1';
687
64
  });
65
+ this.br.updateBrClasses();
688
66
  }
689
67
 
690
68
  /**
69
+ * BREAKING CHANGE: No longer supports pageX/pageY
691
70
  * @param {PageIndex} index
71
+ * @param {number} [pageX] x position on the page (in pixels) to center on
72
+ * @param {number} [pageY] y position on the page (in pixels) to center on
73
+ * @param {boolean} [noAnimate]
692
74
  */
693
- createPageContainer(index, fetch = false) {
694
- if (!this.pageContainers[index]) {
695
- this.pageContainers[index] = this.br._createPageContainer(index);
696
- }
697
- this.pageContainers[index].update({ reduce: this.br.reduce });
698
- return this.pageContainers[index];
699
- }
700
-
701
- /**
702
- * Whether we flip left or right is dependent on the page progression
703
- * to flip forward one spread, pass index=null
704
- * @param {number} index
705
- */
706
- flipFwdToIndex(index) {
707
- if (this.br.animating) return;
708
-
709
- if (null != this.br.leafEdgeTmp) {
710
- alert('error: leafEdgeTmp should be null!');
711
- return;
712
- }
713
-
714
- if (null == index) {
715
- // Need to use the max here, since it could be a right to left book
716
- const {currentIndexL, currentIndexR} = this.br.twoPage;
717
- const maxDisplayedIndex = Math.max(currentIndexL, currentIndexR);
718
- const nextPage = this.book.getPage(maxDisplayedIndex).findNext({ combineConsecutiveUnviewables: true });
719
- if (!nextPage) return;
720
- index = nextPage.index;
721
- }
722
- if (index > this.br.lastDisplayableIndex()) return;
723
-
724
- this.br.updateNavIndexThrottled(index);
725
-
726
- this.br.animating = true;
727
-
728
- const nextIndices = this.book.getSpreadIndices(index);
729
-
730
- if ('rl' != this.br.pageProgression) {
731
- // We did not specify RTL
732
- this.prepareFlipRightToLeft(nextIndices[0], nextIndices[1]);
733
- this.flipRightToLeft(nextIndices[0], nextIndices[1]);
734
- } else {
735
- // RTL
736
- this.prepareFlipLeftToRight(nextIndices[0], nextIndices[1]);
737
- this.flipLeftToRight(nextIndices[0], nextIndices[1]);
738
- }
739
- }
740
-
741
- /**
742
- * Flip from left to right and show the nextL and nextR indices on those sides
743
- * $$$ better not to have to pass gutter in
744
- * @param {number} newIndexL
745
- * @param {number} newIndexR
746
- */
747
- flipRightToLeft(newIndexL, newIndexR) {
748
- this.br.refs.$brContainer.addClass("BRpageFlipping");
749
-
750
- const oldLeafEdgeWidthL = this.br.leafEdgeWidth(this.br.twoPage.currentIndexL);
751
- const oldLeafEdgeWidthR = this.br.twoPage.edgeWidth - oldLeafEdgeWidthL;
752
- const newLeafEdgeWidthL = this.br.leafEdgeWidth(newIndexL);
753
- const newLeafEdgeWidthR = this.br.twoPage.edgeWidth - newLeafEdgeWidthL;
754
-
755
- const leafEdgeTmpW = oldLeafEdgeWidthR - newLeafEdgeWidthR;
756
-
757
- const top = this.top();
758
- const scaledW = this.getPageWidth(this.br.twoPage.currentIndexR);
759
-
760
- const middle = this.br.twoPage.middle;
761
- const gutter = middle + this.gutterOffsetForIndex(newIndexL);
762
-
763
- const $twoPageViewEl = this.br.refs.$brTwoPageView;
764
-
765
- this.br.leafEdgeTmp = document.createElement('div');
766
- this.br.leafEdgeTmp.className = 'BRleafEdgeTmp';
767
- $(this.br.leafEdgeTmp).css({
768
- width: `${leafEdgeTmpW}px`,
769
- height: `${this.br.twoPage.height}px`,
770
- left: `${gutter + scaledW}px`,
771
- top: `${top}px`,
772
- zIndex:1000
773
- }).appendTo($twoPageViewEl);
774
-
775
- const newWidthL = this.getPageWidth(newIndexL);
776
- const newWidthR = this.getPageWidth(newIndexR);
777
-
778
- $(this.leafEdgeR).css({width: `${newLeafEdgeWidthR}px`, left: `${gutter + newWidthR}px` });
779
- const speed = this.br.flipSpeed;
780
-
781
- if (this.br.enableSearch) this.br.removeSearchHilites();
782
-
783
- $(this.br.leafEdgeTmp).animate({left: gutter}, speed, 'easeInSine');
784
- this.pageContainers[this.br.twoPage.currentIndexR].$container.animate({width: '0px'}, speed, 'easeInSine', () => {
785
- this.br.$('BRgutter').css({left: `${gutter - this.br.twoPage.bookSpineDivWidth * 0.5}px`});
786
- $(this.br.leafEdgeTmp).animate({left: `${gutter - newWidthL - leafEdgeTmpW}px`}, speed, 'easeOutSine');
787
- this.pageContainers[newIndexL].$container.animate({width: `${newWidthL}px`}, speed, 'easeOutSine', () => {
788
- this.pageContainers[newIndexR].$container.css('zIndex', 2);
789
-
790
- $(this.leafEdgeL).css({
791
- width: `${newLeafEdgeWidthL}px`,
792
- left: `${gutter - newWidthL - newLeafEdgeWidthL}px`
793
- });
794
-
795
- // Resizes the book cover
796
- $(this.br.twoPage.coverDiv).css({
797
- width: `${this.coverWidth(newWidthL + newWidthR)}px`,
798
- left: `${gutter - newWidthL - newLeafEdgeWidthL - this.br.twoPage.coverInternalPadding}px`
799
- });
800
-
801
- $(this.br.leafEdgeTmp).remove();
802
- this.br.leafEdgeTmp = null;
803
-
804
- this.br.twoPage.currentIndexL = newIndexL;
805
- this.br.twoPage.currentIndexR = newIndexR;
806
- this.br.twoPage.scaledWL = newWidthL;
807
- this.br.twoPage.scaledWR = newWidthR;
808
- this.br.twoPage.gutter = gutter;
809
-
810
- this.br.updateFirstIndex(this.br.twoPage.currentIndexL);
811
- this.br.displayedIndices = [newIndexL, newIndexR];
812
- this.prunePageContainers();
813
- this.br.animating = false;
814
-
815
- this.resizeSpread();
816
-
817
- if (this.br.enableSearch) this.br.updateSearchHilites();
818
-
819
- this.setMouseHandlers();
820
-
821
- if (this.br.animationFinishedCallback) {
822
- this.br.animationFinishedCallback();
823
- this.br.animationFinishedCallback = null;
824
- }
825
-
826
- this.br.refs.$brContainer.removeClass("BRpageFlipping");
827
- this.br.textSelectionPlugin?.stopPageFlip(this.br.refs.$brContainer);
828
- this.centerView();
829
- this.br.trigger('pageChanged');
830
-
831
- this.prunePageContainers();
832
- this.createPageContainer(newIndexL + 2);
833
- this.createPageContainer(newIndexR + 2);
834
- this.createPageContainer(newIndexL + 3);
835
- this.createPageContainer(newIndexR + 3);
836
- });
837
- });
838
- }
839
-
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
- }
863
-
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
- );
874
- }
875
-
876
- /**
877
- * Prepare to flip the left page towards the right. This corresponds to moving
878
- * backward when the page progression is left to right.
879
- * @param {number} prevL
880
- * @param {number} prevR
881
- */
882
- prepareFlipLeftToRight(prevL, prevR) {
883
- this.createPageContainer(prevL, true);
884
- this.createPageContainer(prevR, true);
885
-
886
- const $twoPageViewEl = this.br.refs.$brTwoPageView;
887
- const height = this.book._getPageHeight(prevL);
888
- const width = this.book._getPageWidth(prevL);
889
- const middle = this.br.twoPage.middle;
890
- const top = this.top();
891
- const scaledW = this.br.twoPage.height * width / height; // $$$ assumes height of page is dominant
892
-
893
- // The gutter is the dividing line between the left and right pages.
894
- // It is offset from the middle to create the illusion of thickness to the pages
895
- const gutter = middle + this.gutterOffsetForIndex(prevL);
896
-
897
- const leftCSS = {
898
- left: `${gutter - scaledW}px`,
899
- right: '', // clear right property
900
- top: `${top}px`,
901
- height: this.br.twoPage.height,
902
- width: `${scaledW}px`,
903
- zIndex: 1
904
- };
905
-
906
- this.pageContainers[prevL].$container
907
- .css(leftCSS)
908
- .appendTo($twoPageViewEl);
909
-
910
- const rightCSS = {
911
- left: `${gutter}px`,
912
- right: '',
913
- top: `${top}px`,
914
- height: this.br.twoPage.height,
915
- width: '0',
916
- zIndex: 2
917
- };
918
-
919
- this.pageContainers[prevR].$container
920
- .css(rightCSS)
921
- .appendTo($twoPageViewEl);
922
- }
923
-
924
- /**
925
- * // $$$ mang we're adding an extra pixel in the middle. See https://bugs.edge.launchpad.net/gnubook/+bug/411667
926
- */
927
- prepareFlipRightToLeft(nextL, nextR) {
928
- this.createPageContainer(nextL, true);
929
- this.createPageContainer(nextR, true);
930
-
931
- const $twoPageViewEl = this.br.refs.$brTwoPageView;
932
- let height = this.book._getPageHeight(nextR);
933
- let width = this.book._getPageWidth(nextR);
934
- const middle = this.br.twoPage.middle;
935
- const top = this.top();
936
- let scaledW = this.br.twoPage.height * width / height;
937
-
938
- const gutter = middle + this.gutterOffsetForIndex(nextL);
939
-
940
- $(this.pageContainers[nextR].$container).css({
941
- left: `${gutter}px`,
942
- top: `${top}px`,
943
- height: this.br.twoPage.height,
944
- width: `${scaledW}px`,
945
- zIndex: 1,
946
- })
947
- .appendTo($twoPageViewEl);
948
-
949
- height = this.book._getPageHeight(nextL);
950
- width = this.book._getPageWidth(nextL);
951
- scaledW = this.br.twoPage.height * width / height;
952
-
953
- $(this.pageContainers[nextL].$container).css({
954
- right: `${$twoPageViewEl.prop('clientWidth') - gutter}px`,
955
- top: `${top}px`,
956
- height: this.br.twoPage.height,
957
- width: '0px', // Start at 0 width, then grow to the left
958
- zIndex: 2,
959
- })
960
- .appendTo($twoPageViewEl);
961
- }
962
-
963
- getPageWidth(index) {
964
- // We return the width based on the dominant height
965
- const height = this.book._getPageHeight(index);
966
- const width = this.book._getPageWidth(index);
967
- // $$$ we assume width is relative to current spread
968
- return Math.floor(this.br.twoPage.height * width / height);
75
+ jumpToIndex(index, pageX, pageY, noAnimate) {
76
+ this.mode2UpLit.jumpToIndex(index);
969
77
  }
970
78
 
971
79
  /**
972
- * Returns the position of the gutter (line between the page images)
80
+ * @param {'in' | 'out'} direction
973
81
  */
974
- gutter() {
975
- return this.br.twoPage.middle + this.gutterOffsetForIndex(this.br.twoPage.currentIndexL);
976
- }
977
-
978
- /**
979
- * Returns the offset for the top of the page images
980
- */
981
- top() {
982
- return this.br.twoPage.coverExternalPadding + this.br.twoPage.coverInternalPadding; // $$$ + border?
983
- }
984
-
985
- /**
986
- * Returns the width of the cover div given the total page width
987
- * @param {number} totalPageWidth
988
- * @return {number}
989
- */
990
- coverWidth(totalPageWidth) {
991
- return totalPageWidth + this.br.twoPage.edgeWidth + 2 * this.br.twoPage.coverInternalPadding;
992
- }
993
-
994
- /**
995
- * Returns the percentage offset into twopageview div at the center of container div
996
- */
997
- getViewCenter() {
998
- const { $brContainer, $brTwoPageView } = this.br.refs;
999
- const center = {};
1000
-
1001
- const containerOffset = $brContainer.offset();
1002
- const viewOffset = $brTwoPageView.offset();
1003
- center.percentageX = (containerOffset.left - viewOffset.left + ($brContainer.prop('clientWidth') >> 1)) / this.br.twoPage.totalWidth;
1004
- center.percentageY = (containerOffset.top - viewOffset.top + ($brContainer.prop('clientHeight') >> 1)) / this.br.twoPage.totalHeight;
1005
-
1006
- return center;
1007
- }
1008
-
1009
- /**
1010
- * Centers the point given by percentage from left,top of twopageview
1011
- * @param {number} [percentageX=0.5]
1012
- * @param {number} [percentageY=0.5]
1013
- */
1014
- centerView(percentageX, percentageY) {
1015
-
1016
- if ('undefined' == typeof(percentageX)) {
1017
- percentageX = 0.5;
1018
- }
1019
- if ('undefined' == typeof(percentageY)) {
1020
- percentageY = 0.5;
1021
- }
1022
-
1023
- const viewWidth = this.br.refs.$brTwoPageView.width();
1024
- const containerClientWidth = this.br.refs.$brContainer.prop('clientWidth');
1025
- const intoViewX = percentageX * viewWidth;
1026
-
1027
- const viewHeight = this.br.refs.$brTwoPageView.height();
1028
- const containerClientHeight = this.br.refs.$brContainer.prop('clientHeight');
1029
- const intoViewY = percentageY * viewHeight;
1030
-
1031
- if (viewWidth < containerClientWidth) {
1032
- // Can fit width without scrollbars - center by adjusting offset
1033
- this.br.refs.$brTwoPageView.css('left', `${(containerClientWidth >> 1) - intoViewX}px`);
1034
- } else {
1035
- // Need to scroll to center
1036
- this.br.refs.$brTwoPageView.css('left', 0);
1037
- this.br.refs.$brContainer.scrollLeft(intoViewX - (containerClientWidth >> 1));
1038
- }
1039
-
1040
- if (viewHeight < containerClientHeight) {
1041
- // Fits with scrollbars - add offset
1042
- this.br.refs.$brTwoPageView.css('top', `${(containerClientHeight >> 1) - intoViewY}px`);
1043
- } else {
1044
- this.br.refs.$brTwoPageView.css('top', 0);
1045
- this.br.refs.$brContainer.scrollTop(intoViewY - (containerClientHeight >> 1));
1046
- }
1047
- }
1048
-
1049
- /**
1050
- * Returns the integer height of the click-to-flip areas at the edges of the book
1051
- * @return {number}
1052
- */
1053
- flipAreaHeight() {
1054
- return Math.floor(this.br.twoPage.height);
1055
- }
1056
-
1057
- /**
1058
- * Returns the the integer width of the flip areas
1059
- * @return {number}
1060
- */
1061
- flipAreaWidth() {
1062
- const max = 100; // $$$ TODO base on view width?
1063
- const min = 10;
1064
-
1065
- const width = this.br.twoPage.width * 0.15;
1066
- return Math.floor(clamp(width, min, max));
1067
- }
1068
-
1069
- /**
1070
- * Returns integer top offset for flip areas
1071
- * @return {number}
1072
- */
1073
- flipAreaTop() {
1074
- return Math.floor(this.br.twoPage.bookCoverDivTop + this.br.twoPage.coverInternalPadding);
1075
- }
1076
-
1077
- /**
1078
- * Left offset for left flip area
1079
- * @return {number}
1080
- */
1081
- leftFlipAreaLeft() {
1082
- return Math.floor(this.br.twoPage.gutter - this.br.twoPage.scaledWL);
1083
- }
1084
-
1085
- /**
1086
- * Left offset for right flip area
1087
- * @return {number}
1088
- */
1089
- rightFlipAreaLeft() {
1090
- return Math.floor(this.br.twoPage.gutter + this.br.twoPage.scaledWR - this.flipAreaWidth());
1091
- }
1092
-
1093
- /**
1094
- * Position calculation shared between search and text-to-speech functions
1095
- */
1096
- setHilightCss(div, index, left, right, top, bottom) {
1097
- // We calculate the reduction factor for the specific page because it can be different
1098
- // for each page in the spread
1099
- const height = this.book._getPageHeight(index);
1100
- const width = this.book._getPageWidth(index);
1101
- const reduce = this.br.twoPage.height / height;
1102
- const scaledW = Math.floor(width * reduce);
1103
-
1104
- const gutter = this.gutter();
1105
- let pageL;
1106
- if ('L' == this.book.getPageSide(index)) {
1107
- pageL = gutter - scaledW;
1108
- } else {
1109
- pageL = gutter;
1110
- }
1111
- const pageT = this.top();
1112
-
1113
- $(div).css({
1114
- width: `${(right - left) * reduce}px`,
1115
- height: `${(bottom - top) * reduce}px`,
1116
- left: `${pageL + left * reduce}px`,
1117
- top: `${pageT + top * reduce}px`
1118
- });
1119
- }
1120
-
1121
- /**
1122
- * Returns the gutter offset for the spread containing the given index.
1123
- * This function supports RTL
1124
- * @param {number} pindex
1125
- * @return {number}
1126
- */
1127
- gutterOffsetForIndex(pindex) {
1128
- // To find the offset of the gutter from the middle we calculate our percentage distance
1129
- // through the book (0..1), remap to (-0.5..0.5) and multiply by the total page edge width
1130
- let offset = Math.floor(((pindex / this.book.getNumLeafs()) - 0.5) * this.br.twoPage.edgeWidth);
1131
-
1132
- // But then again for RTL it's the opposite
1133
- if ('rl' == this.br.pageProgression) {
1134
- offset *= -1;
1135
- }
1136
-
1137
- return offset;
1138
- }
1139
-
1140
- /**
1141
- * Returns the width of the leaf edge div for the page with index given
1142
- * @param {number} pindex
1143
- * @return {number}
1144
- */
1145
- leafEdgeWidth(pindex) {
1146
- // $$$ could there be single pixel rounding errors for L vs R?
1147
- if ((this.book.getPageSide(pindex) == 'L') && (this.br.pageProgression != 'rl')) {
1148
- return Math.floor( (pindex / this.book.getNumLeafs()) * this.br.twoPage.edgeWidth + 0.5);
1149
- } else {
1150
- return Math.floor( (1 - pindex / this.book.getNumLeafs()) * this.br.twoPage.edgeWidth + 0.5);
1151
- }
1152
- }
1153
-
1154
- /**
1155
- * Returns the target jump leaf given a page coordinate (inside the left page edge div)
1156
- * @param {number} pageX
1157
- * @return {PageIndex}
1158
- */
1159
- jumpIndexForLeftEdgePageX(pageX) {
1160
- let jumpIndex;
1161
- if ('rl' != this.br.pageProgression) {
1162
- // LTR - flipping backward
1163
- jumpIndex = this.br.twoPage.currentIndexL - ($(this.leafEdgeL).offset().left + $(this.leafEdgeL).width() - pageX) * 10;
1164
-
1165
- // browser may have resized the div due to font size change -- see https://bugs.launchpad.net/gnubook/+bug/333570
1166
- jumpIndex = clamp(Math.round(jumpIndex), this.br.firstDisplayableIndex(), this.br.twoPage.currentIndexL - 2);
1167
- return jumpIndex;
1168
-
1169
- } else {
1170
- jumpIndex = this.br.twoPage.currentIndexL + ($(this.leafEdgeL).offset().left + $(this.leafEdgeL).width() - pageX) * 10;
1171
- jumpIndex = clamp(Math.round(jumpIndex), this.br.twoPage.currentIndexL + 2, this.br.lastDisplayableIndex());
1172
- return jumpIndex;
1173
- }
1174
- }
1175
-
1176
- /**
1177
- * Returns the target jump leaf given a page coordinate (inside the right page edge div)
1178
- * @param {number} pageX
1179
- * @return {PageIndex}
1180
- */
1181
- jumpIndexForRightEdgePageX(pageX) {
1182
- let jumpIndex;
1183
- if ('rl' != this.br.pageProgression) {
1184
- // LTR
1185
- jumpIndex = this.br.twoPage.currentIndexL + (pageX - $(this.leafEdgeR).offset().left) * 10;
1186
- jumpIndex = clamp(Math.round(jumpIndex), this.br.twoPage.currentIndexL + 2, this.br.lastDisplayableIndex());
1187
- return jumpIndex;
1188
- } else {
1189
- jumpIndex = this.br.twoPage.currentIndexL - (pageX - $(this.leafEdgeR).offset().left) * 10;
1190
- jumpIndex = clamp(Math.round(jumpIndex), this.br.firstDisplayableIndex(), this.br.twoPage.currentIndexL - 2);
1191
- return jumpIndex;
1192
- }
1193
- }
1194
-
1195
- /**
1196
- * Fetches the currently displayed images (if not already fetching)
1197
- * as wells as any nearby pages.
1198
- */
1199
- prefetch() {
1200
- // $$$ We should check here if the current indices have finished
1201
- // loading (with some timeout) before loading more page images
1202
- // See https://bugs.edge.launchpad.net/bookreader/+bug/511391
1203
- const { max, min } = Math;
1204
- const { book } = this;
1205
- const { currentIndexL, currentIndexR } = this.br.twoPage;
1206
- const ADJACENT_PAGES_TO_LOAD = 2;
1207
- // currentIndexL can be -1; getPage returns the last page of the book
1208
- // when given -1, so need to prevent that.
1209
- let lowPage = book.getPage(max(0, min(currentIndexL, currentIndexR)));
1210
- let highPage = book.getPage(max(currentIndexL, currentIndexR));
1211
-
1212
- for (let i = 0; i < ADJACENT_PAGES_TO_LOAD + 2; i++) {
1213
- if (lowPage) {
1214
- this.createPageContainer(lowPage.index);
1215
- lowPage = lowPage.findPrev({ combineConsecutiveUnviewables: true });
1216
- }
1217
-
1218
- if (highPage) {
1219
- this.createPageContainer(highPage.index);
1220
- highPage = highPage.findNext({ combineConsecutiveUnviewables: true });
1221
- }
82
+ zoom(direction) {
83
+ switch (direction) {
84
+ case 'in':
85
+ this.mode2UpLit.zoomIn();
86
+ break;
87
+ case 'out':
88
+ this.mode2UpLit.zoomOut();
89
+ break;
90
+ default:
91
+ console.error(`Unsupported direction: ${direction}`);
1222
92
  }
1223
93
  }
1224
94
 
1225
- /* 2up Container Sizes */
1226
-
1227
- /** main positions for inner containers */
1228
- get baseLeafCss() {
1229
- return {
1230
- position: 'absolute',
1231
- right: '',
1232
- top: `${this.top()}px`,
1233
- zIndex: 2,
1234
- };
1235
- }
1236
-
1237
- /** main height for inner containers */
1238
- get heightCss() {
1239
- return {
1240
- height: `${this.br.twoPage.height}px`, // $$$ height forced the same for both pages
1241
- };
1242
- }
1243
-
1244
- /** Left Page sizing */
1245
- get leftLeafCss() {
1246
- return {
1247
- ...this.baseLeafCss,
1248
- ...this.heightCss,
1249
- left: `${this.br.twoPage.gutter - this.br.twoPage.scaledWL}px`,
1250
- width: `${this.br.twoPage.scaledWL}px`,
95
+ resizePageView() {
96
+ this.mode2UpLit.htmlDimensionsCacher.updateClientSizes();
97
+ if (this.mode2UpLit.scale < this.mode2UpLit.initialScale && this.mode2UpLit.autoFit == 'none') {
98
+ this.mode2UpLit.autoFit = 'auto';
1251
99
  }
1252
- }
1253
-
1254
- /** Left side book thickness */
1255
- get leafEdgeLCss() {
1256
- return {
1257
- ...this.heightCss,
1258
- width: `${this.br.twoPage.leafEdgeWidthL}px`,
1259
- left: `${this.br.twoPage.bookCoverDivLeft + this.br.twoPage.coverInternalPadding}px`,
1260
- top: `${this.br.twoPage.bookCoverDivTop + this.br.twoPage.coverInternalPadding}px`,
1261
- border: this.br.twoPage.leafEdgeWidthL === 0 ? 'none' : null
1262
- };
1263
- }
1264
-
1265
- /** Right Page sizing */
1266
- get rightLeafCss() {
1267
- return {
1268
- ...this.baseLeafCss,
1269
- ...this.heightCss,
1270
- left: `${this.br.twoPage.gutter}px`,
1271
- width: `${this.br.twoPage.scaledWR}px`,
100
+ if (this.mode2UpLit.autoFit != 'none') {
101
+ this.mode2UpLit.resizeViaAutofit();
1272
102
  }
103
+ this.mode2UpLit.recenter();
1273
104
  }
1274
-
1275
- /** Right side book thickness */
1276
- get leafEdgeRCss() {
1277
- return {
1278
- ...this.heightCss,
1279
- width: `${this.br.twoPage.leafEdgeWidthR}px`,
1280
- left: `${this.br.twoPage.scaledWL + this.br.twoPage.scaledWR + this.br.twoPage.leafEdgeWidthL}px`,
1281
- top: `${this.br.twoPage.bookCoverDivTop + this.br.twoPage.coverInternalPadding}px`,
1282
- border: this.br.twoPage.leafEdgeWidthR === 0 ? 'none' : null
1283
- };
1284
- }
1285
-
1286
- /** main container sizing */
1287
- get mainContainerCss() {
1288
- return {
1289
- height: `${this.br.twoPage.totalHeight}px`,
1290
- width: `${this.br.twoPage.totalWidth}px`,
1291
- position: 'absolute'
1292
- };
1293
- }
1294
-
1295
- /** book cover sizing */
1296
- get spreadCoverCss() {
1297
- return {
1298
- width: `${this.br.twoPage.bookCoverDivWidth}px`,
1299
- height: `${this.br.twoPage.bookCoverDivHeight}px`,
1300
- visibility: 'visible'
1301
- };
1302
- }
1303
-
1304
- /** book spine sizing */
1305
- get spineCss() {
1306
- return {
1307
- width: `${this.br.twoPage.bookSpineDivWidth}px`,
1308
- height: `${this.br.twoPage.bookSpineDivHeight}px`,
1309
- left: `${this.br.twoPage.gutter - (this.br.twoPage.bookSpineDivWidth / 2)}px`,
1310
- top: `${this.br.twoPage.bookSpineDivTop}px`
1311
- };
1312
- }
1313
- /** end CSS */
1314
105
  }
1315
-
1316
- /**
1317
- * @implements {BookReaderOptions["twoPage"]}
1318
- * @typedef {object} TwoPageState
1319
- * @property {number} coverInternalPadding
1320
- * @property {number} coverExternalPadding
1321
- *
1322
- * @property {import('./options.js').AutoFitValues} autofit
1323
- * @property {number} width
1324
- * @property {number} height
1325
- * @property {number} currentIndexL
1326
- * @property {number} currentIndexR
1327
- * @property {number} scaledWL
1328
- * @property {number} scaledWR
1329
- * @property {number} gutter
1330
- * @property {Array<{reduce: number, autofit: import('./options.js').AutoFitValues}>} reductionFactors
1331
- * @property {number} totalHeight
1332
- * @property {number} totalWidth
1333
- *
1334
- * @property {HTMLDivElement} coverDiv
1335
- * @property {number} bookCoverDivTop
1336
- * @property {number} bookCoverDivLeft
1337
- * @property {number} bookCoverDivWidth
1338
- * @property {number} bookCoverDivHeight
1339
- *
1340
- * @property {number} leafEdgeWidthL
1341
- * @property {number} leafEdgeWidthR
1342
- *
1343
- * @property {number} bookSpineDivTop
1344
- * @property {number} bookSpineDivLeft
1345
- * @property {number} bookSpineDivWidth
1346
- * @property {number} bookSpineDivHeight
1347
- *
1348
- * @property {number} edgeWidth
1349
- * @property {number} middle
1350
- */