@internetarchive/bookreader 5.0.0-5-multiple-files → 5.0.0-50

Sign up to get free protection for your applications and to get access to all the features.
Files changed (289) hide show
  1. package/.eslintrc.js +17 -15
  2. package/.github/workflows/node.js.yml +77 -6
  3. package/.github/workflows/npm-publish.yml +6 -20
  4. package/.testcaferc.js +10 -0
  5. package/BookReader/BookReader.css +131 -339
  6. package/BookReader/BookReader.js +2 -21564
  7. package/BookReader/BookReader.js.LICENSE.txt +24 -0
  8. package/BookReader/BookReader.js.map +1 -1
  9. package/BookReader/ia-bookreader-bundle.js +1493 -0
  10. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +17 -0
  11. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  12. package/BookReader/icons/1up.svg +1 -12
  13. package/BookReader/icons/2up.svg +1 -15
  14. package/BookReader/icons/advance.svg +3 -26
  15. package/BookReader/icons/chevron-right.svg +1 -1
  16. package/BookReader/icons/close-circle-dark.svg +1 -0
  17. package/BookReader/icons/close-circle.svg +1 -1
  18. package/BookReader/icons/fullscreen.svg +1 -17
  19. package/BookReader/icons/fullscreen_exit.svg +1 -17
  20. package/BookReader/icons/hamburger.svg +1 -15
  21. package/BookReader/icons/left-arrow.svg +1 -12
  22. package/BookReader/icons/magnify-minus.svg +1 -16
  23. package/BookReader/icons/magnify-plus.svg +1 -17
  24. package/BookReader/icons/magnify.svg +1 -15
  25. package/BookReader/icons/pause.svg +1 -23
  26. package/BookReader/icons/play.svg +1 -22
  27. package/BookReader/icons/playback-speed.svg +1 -34
  28. package/BookReader/icons/read-aloud.svg +1 -22
  29. package/BookReader/icons/review.svg +3 -22
  30. package/BookReader/icons/thumbnails.svg +1 -17
  31. package/BookReader/icons/voice.svg +1 -0
  32. package/BookReader/icons/volume-full.svg +1 -22
  33. package/BookReader/images/BRicons.svg +5 -94
  34. package/BookReader/images/books_graphic.svg +1 -177
  35. package/BookReader/images/icon_book.svg +1 -12
  36. package/BookReader/images/icon_bookmark.svg +1 -12
  37. package/BookReader/images/icon_gear.svg +1 -14
  38. package/BookReader/images/icon_hamburger.svg +1 -20
  39. package/BookReader/images/icon_home.svg +1 -21
  40. package/BookReader/images/icon_info.svg +1 -11
  41. package/BookReader/images/icon_one_page.svg +1 -8
  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 -15
  45. package/BookReader/images/icon_search_button.svg +1 -8
  46. package/BookReader/images/icon_share.svg +1 -9
  47. package/BookReader/images/icon_skip-ahead.svg +1 -6
  48. package/BookReader/images/icon_skip-back.svg +2 -13
  49. package/BookReader/images/icon_speaker.svg +1 -18
  50. package/BookReader/images/icon_speaker_open.svg +1 -10
  51. package/BookReader/images/icon_thumbnails.svg +1 -12
  52. package/BookReader/images/icon_toc.svg +1 -5
  53. package/BookReader/images/icon_two_pages.svg +1 -9
  54. package/BookReader/images/marker_chap-off.svg +1 -11
  55. package/BookReader/images/marker_chap-on.svg +1 -11
  56. package/BookReader/images/marker_srch-on.svg +1 -11
  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 -172
  60. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  61. package/BookReader/plugins/plugin.autoplay.js +1 -165
  62. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  63. package/BookReader/plugins/plugin.chapters.js +1 -304
  64. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  65. package/BookReader/plugins/plugin.iframe.js +1 -74
  66. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  67. package/BookReader/plugins/plugin.mobile_nav.js +1 -334
  68. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
  69. package/BookReader/plugins/plugin.resume.js +1 -368
  70. package/BookReader/plugins/plugin.resume.js.map +1 -1
  71. package/BookReader/plugins/plugin.search.js +1 -1420
  72. package/BookReader/plugins/plugin.search.js.map +1 -1
  73. package/BookReader/plugins/plugin.text_selection.js +1 -1080
  74. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  75. package/BookReader/plugins/plugin.tts.js +2 -9193
  76. package/BookReader/plugins/plugin.tts.js.map +1 -1
  77. package/BookReader/plugins/plugin.url.js +1 -269
  78. package/BookReader/plugins/plugin.url.js.map +1 -1
  79. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -379
  80. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  81. package/BookReader/webcomponents-bundle.js +3 -0
  82. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  83. package/BookReader/webcomponents-bundle.js.map +1 -0
  84. package/BookReaderDemo/BookReaderDemo.css +14 -1
  85. package/BookReaderDemo/IADemoBr.js +148 -0
  86. package/BookReaderDemo/demo-advanced.html +2 -2
  87. package/BookReaderDemo/demo-autoplay.html +2 -1
  88. package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
  89. package/BookReaderDemo/demo-fullscreen-mobile.html +2 -1
  90. package/BookReaderDemo/demo-fullscreen.html +2 -1
  91. package/BookReaderDemo/demo-iiif.html +2 -1
  92. package/BookReaderDemo/demo-internetarchive.html +84 -17
  93. package/BookReaderDemo/demo-multiple.html +2 -1
  94. package/BookReaderDemo/demo-preview-pages.html +2 -1
  95. package/BookReaderDemo/demo-simple.html +2 -1
  96. package/BookReaderDemo/demo-vendor-fullscreen.html +2 -1
  97. package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
  98. package/BookReaderDemo/immersion-1up.html +2 -1
  99. package/BookReaderDemo/immersion-mode.html +2 -1
  100. package/BookReaderDemo/toggle_controls.html +2 -1
  101. package/BookReaderDemo/view_mode.html +2 -1
  102. package/BookReaderDemo/viewmode-cycle.html +2 -3
  103. package/CHANGELOG.md +205 -0
  104. package/README.md +14 -1
  105. package/babel.config.js +18 -0
  106. package/codecov.yml +6 -0
  107. package/index.html +3 -0
  108. package/jsconfig.json +19 -0
  109. package/package.json +66 -56
  110. package/renovate.json +52 -0
  111. package/scripts/preversion.js +4 -1
  112. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  113. package/src/BookNavigator/assets/button-base.js +9 -2
  114. package/src/BookNavigator/assets/ia-logo.js +17 -0
  115. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  116. package/src/BookNavigator/assets/icon_close.js +1 -1
  117. package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
  118. package/src/BookNavigator/assets/{icon_sort_ascending.js → icon_sort_desc.js} +2 -2
  119. package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
  120. package/src/BookNavigator/assets/icon_volumes.js +11 -0
  121. package/src/BookNavigator/book-navigator.js +583 -0
  122. package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
  123. package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
  124. package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
  125. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
  126. package/src/BookNavigator/bookmarks/bookmarks-provider.js +21 -8
  127. package/src/BookNavigator/bookmarks/ia-bookmarks.js +102 -66
  128. package/src/BookNavigator/delete-modal-actions.js +1 -1
  129. package/src/BookNavigator/downloads/downloads-provider.js +36 -21
  130. package/src/BookNavigator/downloads/downloads.js +41 -25
  131. package/src/BookNavigator/search/a-search-result.js +15 -13
  132. package/src/BookNavigator/search/search-provider.js +80 -28
  133. package/src/BookNavigator/search/search-results.js +10 -18
  134. package/src/BookNavigator/sharing.js +27 -0
  135. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
  136. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
  137. package/src/BookNavigator/volumes/volumes-provider.js +93 -63
  138. package/src/BookNavigator/volumes/volumes.js +40 -46
  139. package/src/BookReader/BookModel.js +0 -29
  140. package/src/BookReader/DebugConsole.js +3 -3
  141. package/src/BookReader/DragScrollable.js +233 -0
  142. package/src/BookReader/Mode1Up.js +51 -351
  143. package/src/BookReader/Mode1UpLit.js +441 -0
  144. package/src/BookReader/Mode2Up.js +120 -105
  145. package/src/BookReader/ModeSmoothZoom.js +179 -0
  146. package/src/BookReader/ModeThumb.js +17 -11
  147. package/src/BookReader/Navbar/Navbar.js +10 -36
  148. package/src/BookReader/PageContainer.js +69 -6
  149. package/src/BookReader/ReduceSet.js +1 -1
  150. package/src/BookReader/Toolbar/Toolbar.js +10 -37
  151. package/src/BookReader/options.js +10 -0
  152. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  153. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  154. package/src/BookReader/utils.js +92 -13
  155. package/src/BookReader.js +431 -620
  156. package/src/assets/icons/close-circle-dark.svg +1 -0
  157. package/src/assets/icons/magnify-minus.svg +3 -7
  158. package/src/assets/icons/magnify-plus.svg +3 -7
  159. package/src/assets/icons/voice.svg +1 -0
  160. package/src/css/BookReader.scss +0 -12
  161. package/src/css/_BRComponent.scss +1 -1
  162. package/src/css/_BRmain.scss +19 -24
  163. package/src/css/_BRnav.scss +4 -26
  164. package/src/css/_BRpages.scss +35 -0
  165. package/src/css/_BRsearch.scss +25 -216
  166. package/src/css/_TextSelection.scss +14 -17
  167. package/src/css/_colorbox.scss +2 -2
  168. package/src/css/_controls.scss +17 -5
  169. package/src/css/_icons.scss +6 -0
  170. package/src/ia-bookreader/ia-bookreader.js +224 -0
  171. package/src/plugins/plugin.autoplay.js +4 -4
  172. package/src/plugins/plugin.chapters.js +28 -35
  173. package/src/plugins/plugin.mobile_nav.js +11 -10
  174. package/src/plugins/plugin.resume.js +3 -3
  175. package/src/plugins/plugin.text_selection.js +26 -39
  176. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  177. package/src/plugins/search/plugin.search.js +174 -116
  178. package/src/plugins/search/view.js +63 -179
  179. package/src/plugins/tts/AbstractTTSEngine.js +46 -37
  180. package/src/plugins/tts/FestivalTTSEngine.js +13 -14
  181. package/src/plugins/tts/PageChunk.js +15 -21
  182. package/src/plugins/tts/PageChunkIterator.js +8 -12
  183. package/src/plugins/tts/WebTTSEngine.js +66 -69
  184. package/src/plugins/tts/plugin.tts.js +92 -109
  185. package/src/plugins/tts/utils.js +0 -9
  186. package/src/plugins/url/UrlPlugin.js +184 -0
  187. package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
  188. package/src/util/manifestGenerator.js +0 -0
  189. package/tests/e2e/README.md +37 -0
  190. package/tests/e2e/autoplay.test.js +2 -2
  191. package/tests/e2e/base.test.js +7 -7
  192. package/tests/e2e/helpers/base.js +8 -3
  193. package/tests/e2e/helpers/debug.js +1 -1
  194. package/tests/e2e/helpers/desktopSearch.js +14 -13
  195. package/tests/e2e/helpers/mobileSearch.js +3 -3
  196. package/tests/e2e/helpers/params.js +17 -0
  197. package/tests/e2e/models/Navigation.js +13 -4
  198. package/tests/e2e/rightToLeft.test.js +4 -5
  199. package/tests/e2e/viewmode.test.js +38 -33
  200. package/tests/jest/BookNavigator/book-navigator.test.js +634 -0
  201. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
  202. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  203. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  204. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  205. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
  206. package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
  207. package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
  208. package/tests/{karma/BookNavigator → jest/BookNavigator/search}/search-results.test.js +102 -58
  209. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
  210. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  211. package/tests/jest/BookNavigator/volumes/volumes-provider.test.js +184 -0
  212. package/tests/jest/BookNavigator/volumes/volumes.test.js +97 -0
  213. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +34 -14
  214. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
  215. package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
  216. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  217. package/tests/jest/BookReader/Mode1UpLit.test.js +92 -0
  218. package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +36 -15
  219. package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
  220. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  221. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
  222. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
  223. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  224. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  225. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  226. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  227. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  228. package/tests/jest/BookReader/utils.test.js +186 -0
  229. package/tests/jest/BookReader.keyboard.test.js +190 -0
  230. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  231. package/tests/{BookReader.test.js → jest/BookReader.test.js} +18 -37
  232. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  233. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
  234. package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +10 -11
  235. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  236. package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
  237. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  238. package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
  239. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  240. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +63 -47
  241. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +35 -6
  242. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +9 -9
  243. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  244. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  245. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  246. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +1 -1
  247. package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -28
  248. package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
  249. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
  250. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  251. package/tests/{util → jest/util}/docCookies.test.js +1 -1
  252. package/tests/{util → jest/util}/strings.test.js +1 -1
  253. package/tests/{utils.js → jest/utils.js} +38 -0
  254. package/webpack.config.js +11 -5
  255. package/.babelrc +0 -12
  256. package/.dependabot/config.yml +0 -6
  257. package/.testcaferc.json +0 -5
  258. package/BookReader/bookreader-component-bundle.js +0 -14275
  259. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  260. package/BookReader/bookreader-component-bundle.js.map +0 -1
  261. package/BookReader/icons/sort-ascending.svg +0 -1
  262. package/BookReader/icons/sort-descending.svg +0 -1
  263. package/BookReader/jquery-1.10.1.js +0 -108
  264. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  265. package/BookReader/plugins/plugin.menu_toggle.js +0 -369
  266. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  267. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  268. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  269. package/karma.conf.js +0 -23
  270. package/src/BookNavigator/BookModel.js +0 -14
  271. package/src/BookNavigator/BookNavigator.js +0 -448
  272. package/src/BookNavigator/assets/book-loader.js +0 -27
  273. package/src/BookNavigator/assets/icon_sort_descending.js +0 -5
  274. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  275. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  276. package/src/ItemNavigator/ItemNavigator.js +0 -373
  277. package/src/ItemNavigator/providers/sharing.js +0 -29
  278. package/src/assets/icons/sort-ascending.svg +0 -1
  279. package/src/assets/icons/sort-descending.svg +0 -1
  280. package/src/dragscrollable-br.js +0 -261
  281. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  282. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  283. package/tests/BookReader/Mode1Up.test.js +0 -164
  284. package/tests/BookReader/utils.test.js +0 -109
  285. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  286. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  287. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  288. package/tests/karma/BookNavigator/volumes.test.js +0 -101
  289. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
package/src/BookReader.js CHANGED
@@ -27,23 +27,17 @@ import 'jquery-ui/ui/widget.js';
27
27
  import 'jquery-ui/ui/widgets/mouse.js';
28
28
  import 'jquery-ui-touch-punch';
29
29
 
30
- import './dragscrollable-br.js';
31
30
  import PACKAGE_JSON from '../package.json';
32
31
  import * as utils from './BookReader/utils.js';
33
32
  import { exposeOverrideable } from './BookReader/utils/classes.js';
34
- import { Navbar, getNavPageNumHtml } from './BookReader/Navbar/Navbar.js';
33
+ import { Navbar } from './BookReader/Navbar/Navbar.js';
35
34
  import { DEFAULT_OPTIONS } from './BookReader/options.js';
36
35
  /** @typedef {import('./BookReader/options.js').BookReaderOptions} BookReaderOptions */
37
36
  /** @typedef {import('./BookReader/options.js').ReductionFactor} ReductionFactor */
38
37
  /** @typedef {import('./BookReader/BookModel.js').PageIndex} PageIndex */
39
38
  import { EVENTS } from './BookReader/events.js';
40
39
  import { DebugConsole } from './BookReader/DebugConsole.js';
41
- import {
42
- Toolbar,
43
- blankInfoDiv,
44
- blankShareDiv,
45
- createPopup,
46
- } from './BookReader/Toolbar/Toolbar.js';
40
+ import { Toolbar } from './BookReader/Toolbar/Toolbar.js';
47
41
  import { BookModel } from './BookReader/BookModel.js';
48
42
  import { Mode1Up } from './BookReader/Mode1Up.js';
49
43
  import { Mode2Up } from './BookReader/Mode2Up.js';
@@ -152,18 +146,13 @@ BookReader.prototype.setup = function(options) {
152
146
  this.ui = options.ui;
153
147
  this.uiAutoHide = options.uiAutoHide;
154
148
 
155
- this.thumbWidth = 100; // will be overridden during prepareThumbnailView
149
+ this.thumbWidth = 100; // will be overridden during this._modes.modeThumb.prepare();
156
150
  this.thumbRowBuffer = options.thumbRowBuffer;
157
151
  this.thumbColumns = options.thumbColumns;
158
152
  this.thumbMaxLoading = options.thumbMaxLoading;
159
153
  this.thumbPadding = options.thumbPadding;
160
154
  this.displayedRows = [];
161
-
162
155
  this.displayedIndices = [];
163
- /** @deprecated Unused; will be remove in v5 */
164
- this.imgs = {};
165
- /** @deprecated No longer used; will be remove in v5 */
166
- this.prefetchedImgs = {}; //an object with numeric keys corresponding to page index, reduce
167
156
 
168
157
  this.animating = false;
169
158
  this.flipSpeed = options.flipSpeed;
@@ -179,7 +168,7 @@ BookReader.prototype.setup = function(options) {
179
168
  */
180
169
  this.firstIndex = null;
181
170
  this.lastDisplayableIndex2up = null;
182
- this.isFullscreenActive = false;
171
+ this.isFullscreenActive = options.startFullscreen || false;
183
172
  this.lastScroll = null;
184
173
 
185
174
  this.showLogo = options.showLogo;
@@ -212,26 +201,22 @@ BookReader.prototype.setup = function(options) {
212
201
 
213
202
  // Assign the data methods
214
203
  this.data = options.data;
215
- if (options.getNumLeafs) BookReader.prototype.getNumLeafs = options.getNumLeafs;
216
- if (options.getPageWidth) BookReader.prototype.getPageWidth = options.getPageWidth;
217
- if (options.getPageHeight) BookReader.prototype.getPageHeight = options.getPageHeight;
218
- if (options.getPageURI) BookReader.prototype.getPageURI = options.getPageURI;
219
- if (options.getPageSide) BookReader.prototype.getPageSide = options.getPageSide;
220
- if (options.getPageNum) BookReader.prototype.getPageNum = options.getPageNum;
221
- if (options.getPageProp) BookReader.prototype.getPageProp = options.getPageProp;
222
- if (options.getSpreadIndices) BookReader.prototype.getSpreadIndices = options.getSpreadIndices;
223
- if (options.leafNumToIndex) BookReader.prototype.leafNumToIndex = options.leafNumToIndex;
224
204
 
225
205
  /** @type {{[name: string]: JQuery}} */
226
206
  this.refs = {};
227
207
 
228
- /**
229
- * @private (for now) Models are largely state storing classes. This might be too much
230
- * granularity, but time will tell!
231
- */
232
- this._models = {
233
- book: new BookModel(this),
234
- };
208
+ /** The book being displayed in BookReader*/
209
+ this.book = new BookModel(this);
210
+
211
+ if (options.getNumLeafs) this.book.getNumLeafs = options.getNumLeafs.bind(this);
212
+ if (options.getPageWidth) this.book.getPageWidth = options.getPageWidth.bind(this);
213
+ if (options.getPageHeight) this.book.getPageHeight = options.getPageHeight.bind(this);
214
+ if (options.getPageURI) this.book.getPageURI = options.getPageURI.bind(this);
215
+ if (options.getPageSide) this.book.getPageSide = options.getPageSide.bind(this);
216
+ if (options.getPageNum) this.book.getPageNum = options.getPageNum.bind(this);
217
+ if (options.getPageProp) this.book.getPageProp = options.getPageProp.bind(this);
218
+ if (options.getSpreadIndices) this.book.getSpreadIndices = options.getSpreadIndices.bind(this);
219
+ if (options.leafNumToIndex) this.book.leafNumToIndex = options.leafNumToIndex.bind(this);
235
220
 
236
221
  /**
237
222
  * @private Components are 'subchunks' of bookreader functionality, usually UI related
@@ -245,14 +230,14 @@ BookReader.prototype.setup = function(options) {
245
230
  };
246
231
 
247
232
  this._modes = {
248
- mode1Up: new Mode1Up(this, this._models.book),
249
- mode2Up: new Mode2Up(this, this._models.book),
250
- modeThumb: new ModeThumb(this, this._models.book),
233
+ mode1Up: new Mode1Up(this, this.book),
234
+ mode2Up: new Mode2Up(this, this.book),
235
+ modeThumb: new ModeThumb(this, this.book),
251
236
  };
252
237
 
253
238
  /** Stores classes which we want to expose (selectively) some methods as overridable */
254
239
  this._overrideable = {
255
- '_models.book': this._models.book,
240
+ 'book': this.book,
256
241
  '_components.navbar': this._components.navbar,
257
242
  '_components.toolbar': this._components.toolbar,
258
243
  '_modes.mode1Up': this._modes.mode1Up,
@@ -261,21 +246,54 @@ BookReader.prototype.setup = function(options) {
261
246
  };
262
247
 
263
248
  /** Image cache for general image fetching */
264
- this.imageCache = new ImageCache(this._models.book, {
249
+ this.imageCache = new ImageCache(this.book, {
265
250
  useSrcSet: this.options.useSrcSet,
266
251
  reduceSet: this.reduceSet,
267
252
  });
253
+
254
+ /**
255
+ * Flag if BookReader has "focus" for keyboard shortcuts
256
+ * Initially true, set to false when:
257
+ * - BookReader scrolled out of view
258
+ * Set to true when:
259
+ * - BookReader scrolled into view
260
+ */
261
+ this.hasKeyFocus = true;
268
262
  };
269
263
 
270
- /** @deprecated unused outside Mode2Up */
271
- Object.defineProperty(BookReader.prototype, 'leafEdgeL', {
272
- get() { return this._modes.mode2Up.leafEdgeL; },
273
- set(newVal) { this._modes.mode2Up.leafEdgeL = newVal; }
274
- });
275
- /** @deprecated unused outside Mode2Up */
276
- Object.defineProperty(BookReader.prototype, 'leafEdgeR', {
277
- get() { return this._modes.mode2Up.leafEdgeR; },
278
- set(newVal) { this._modes.mode2Up.leafEdgeR = newVal; }
264
+ /**
265
+ * Get all the HTML Elements that are being/can be rendered.
266
+ * Includes cached elements which might be rendered again.
267
+ */
268
+ BookReader.prototype.getActivePageContainerElements = function() {
269
+ let containerEls = Object.values(this._modes.mode2Up.pageContainers).map(pc => pc.$container[0])
270
+ .concat(Object.values(this._modes.mode1Up.mode1UpLit.pageContainerCache).map(pc => pc.$container[0]));
271
+ if (this.mode == this.constModeThumb) {
272
+ containerEls = containerEls.concat(this.$('.BRpagecontainer').toArray());
273
+ }
274
+ return containerEls;
275
+ };
276
+
277
+ /**
278
+ * Get the HTML Elements for the rendered page. Note there can be more than one, since
279
+ * (at least as of writing) different modes can maintain different caches.
280
+ * @param {PageIndex} pageIndex
281
+ */
282
+ BookReader.prototype.getActivePageContainerElementsForIndex = function(pageIndex) {
283
+ return [
284
+ this._modes.mode2Up.pageContainers[pageIndex]?.$container?.[0],
285
+ this._modes.mode1Up.mode1UpLit.pageContainerCache[pageIndex]?.$container?.[0],
286
+ ...(this.mode == this.constModeThumb ? this.$(`.pagediv${pageIndex}`).toArray() : [])
287
+ ].filter(x => x);
288
+ };
289
+
290
+ Object.defineProperty(BookReader.prototype, 'activeMode', {
291
+ /** @return {Mode1Up | Mode2Up | ModeThumb} */
292
+ get() { return {
293
+ 1: this._modes.mode1Up,
294
+ 2: this._modes.mode2Up,
295
+ 3: this._modes.modeThumb,
296
+ }[this.mode]; },
279
297
  });
280
298
 
281
299
  /**
@@ -290,15 +308,15 @@ BookReader.util = utils;
290
308
  * @private
291
309
  */
292
310
  BookReader.prototype.extendParams = function(params, newParams) {
293
- var modifiedNewParams = $.extend({}, newParams);
311
+ const modifiedNewParams = $.extend({}, newParams);
294
312
  if ('undefined' != typeof(modifiedNewParams.page)) {
295
- var pageIndex = this._models.book.parsePageString(modifiedNewParams.page);
313
+ const pageIndex = this.book.parsePageString(modifiedNewParams.page);
296
314
  if (!isNaN(pageIndex))
297
315
  modifiedNewParams.index = pageIndex;
298
316
  delete modifiedNewParams.page;
299
317
  }
300
318
  $.extend(params, modifiedNewParams);
301
- }
319
+ };
302
320
 
303
321
  /**
304
322
  * Parses params from from various initialization contexts (url, cookie, options)
@@ -306,7 +324,7 @@ BookReader.prototype.extendParams = function(params, newParams) {
306
324
  * @return {object} the parsed params
307
325
  */
308
326
  BookReader.prototype.initParams = function() {
309
- var params = {};
327
+ const params = {};
310
328
  // Flag initializing for updateFromParams()
311
329
  params.init = true;
312
330
 
@@ -323,8 +341,8 @@ BookReader.prototype.initParams = function() {
323
341
 
324
342
  // If we have a title leaf, use that as the default instead of index 0,
325
343
  // but only use as default if book has a few pages
326
- if ('undefined' != typeof(this.titleLeaf) && this._models.book.getNumLeafs() > 2) {
327
- params.index = this._models.book.leafNumToIndex(this.titleLeaf);
344
+ if ('undefined' != typeof(this.titleLeaf) && this.book.getNumLeafs() > 2) {
345
+ params.index = this.book.leafNumToIndex(this.titleLeaf);
328
346
  } else {
329
347
  params.index = 0;
330
348
  }
@@ -355,7 +373,7 @@ BookReader.prototype.initParams = function() {
355
373
  // Check for URL plugin
356
374
  if (this.options.enableUrlPlugin) {
357
375
  // Params explicitly set in URL take precedence over all other methods
358
- var urlParams = this.paramsFromFragment(this.urlReadFragment());
376
+ let urlParams = this.paramsFromFragment(this.urlReadFragment());
359
377
 
360
378
  // Get params if hash fragment available with 'history' urlMode
361
379
  const hasHashURL = !Object.keys(urlParams).length && this.urlReadHashFragment();
@@ -377,7 +395,7 @@ BookReader.prototype.initParams = function() {
377
395
  // Check for Search plugin
378
396
  if (this.options.enableSearch) {
379
397
  // Go to first result only if no default or URL page
380
- this.goToFirstResult = !params.pageFound
398
+ this.options.goToFirstResult = !params.pageFound;
381
399
 
382
400
  // If initialSearchTerm not set
383
401
  if (!this.options.initialSearchTerm) {
@@ -389,7 +407,7 @@ BookReader.prototype.initParams = function() {
389
407
  } else {
390
408
  // If we have a query string: q=[term]
391
409
  const searchParams = new URLSearchParams(this.readQueryString());
392
- const searchTerm = searchParams.get('q')
410
+ const searchTerm = searchParams.get('q');
393
411
  if (searchTerm) {
394
412
  this.options.initialSearchTerm = utils.decodeURIComponentPlus(searchTerm);
395
413
  }
@@ -401,21 +419,21 @@ BookReader.prototype.initParams = function() {
401
419
  this.suppressFragmentChange = !params.fragmentChange;
402
420
 
403
421
  return params;
404
- }
422
+ };
405
423
 
406
424
  /**
407
425
  * Allow mocking of window.location.search
408
426
  */
409
427
  BookReader.prototype.getLocationSearch = function () {
410
428
  return window.location.search;
411
- }
429
+ };
412
430
 
413
431
  /**
414
432
  * Allow mocking of window.location.hash
415
433
  */
416
434
  BookReader.prototype.getLocationHash = function () {
417
435
  return window.location.hash;
418
- }
436
+ };
419
437
 
420
438
  /**
421
439
  * Return URL or fragment querystring
@@ -428,7 +446,7 @@ BookReader.prototype.readQueryString = function() {
428
446
  const hash = this.getLocationHash();
429
447
  const found = hash.search(/\?\w+=/);
430
448
  return found > -1 ? hash.slice(found) : '';
431
- }
449
+ };
432
450
 
433
451
  /**
434
452
  * Determines the initial mode for starting if a mode is not already
@@ -438,12 +456,11 @@ BookReader.prototype.readQueryString = function() {
438
456
  */
439
457
  BookReader.prototype.getInitialMode = function(params) {
440
458
  // Use params or browser width to set view mode
441
- var windowWidth = $(window).width();
442
- var nextMode;
459
+ const windowWidth = $(window).width();
460
+ let nextMode;
443
461
  if ('undefined' != typeof(params.mode)) {
444
462
  nextMode = params.mode;
445
463
  } else if (this.ui == 'full'
446
- && this.enableMobileNav
447
464
  && this.isFullscreenActive
448
465
  && windowWidth <= this.onePageMinBreakpoint
449
466
  ) {
@@ -467,7 +484,7 @@ BookReader.prototype.init = function() {
467
484
  this.init.initComplete = false;
468
485
  this.pageScale = this.reduce; // preserve current reduce
469
486
 
470
- var params = this.initParams();
487
+ const params = this.initParams();
471
488
 
472
489
  this.firstIndex = params.index ? params.index : 0;
473
490
 
@@ -497,19 +514,16 @@ BookReader.prototype.init = function() {
497
514
  // Explicitly ensure this.mode exists for initNavbar() below
498
515
  this.mode = params.mode;
499
516
 
500
- if (this.ui == "embed" && this.options.showNavbar) {
501
- this.initEmbedNavbar();
502
- } else {
503
- if (this.options.showToolbar) {
504
- this.initToolbar(this.mode, this.ui); // Build inside of toolbar div
505
- }
506
- if (this.options.showNavbar) {
507
- this.initNavbar();
508
- }
517
+ // Display Navigation
518
+ if (this.options.showToolbar) {
519
+ this.initToolbar(this.mode, this.ui); // Build inside of toolbar div
520
+ }
521
+ if (this.options.showNavbar) { // default navigation
522
+ this.initNavbar();
509
523
  }
510
524
 
511
525
  // Switch navbar controls on mobile/desktop
512
- this.switchNavbarControls();
526
+ this._components.navbar.switchNavbarControls();
513
527
 
514
528
  this.resizeBRcontainer();
515
529
  this.updateFromParams(params);
@@ -521,17 +535,17 @@ BookReader.prototype.init = function() {
521
535
  this.setupKeyListeners();
522
536
 
523
537
  this.lastScroll = (new Date().getTime());
524
- this.refs.$brContainer.bind('scroll', this, function(e) {
538
+ this.refs.$brContainer.on('scroll', this, function(e) {
525
539
  // Note, this scroll event fires for both user, and js generated calls
526
540
  // It is functioning in some cases as the primary triggerer for rendering
527
541
  e.data.lastScroll = (new Date().getTime());
528
- if (e.data.constMode2up != e.data.mode) {
542
+ if (e.data.constModeThumb == e.data.mode) {
529
543
  e.data.drawLeafsThrottled();
530
544
  }
531
545
  });
532
546
 
533
547
  if (this.options.autoResize) {
534
- $(window).bind('resize', this, function(e) {
548
+ $(window).on('resize', this, function(e) {
535
549
  e.data.resize();
536
550
  });
537
551
  $(window).on("orientationchange", this, function(e) {
@@ -548,15 +562,17 @@ BookReader.prototype.init = function() {
548
562
  this.suppressFragmentChange = false;
549
563
  }
550
564
 
565
+ if (this.options.startFullscreen) {
566
+ this.enterFullscreen(true);
567
+ }
568
+
551
569
  this.init.initComplete = true;
552
570
  this.trigger(BookReader.eventNames.PostInit);
553
571
 
554
572
  // Must be called after this.init.initComplete set to true to allow
555
573
  // BookReader.prototype.resize to run.
556
- if (this.options.startFullscreen) {
557
- this.toggleFullscreen();
558
- }
559
- }
574
+
575
+ };
560
576
 
561
577
  /**
562
578
  * @param {EVENTS} name
@@ -564,7 +580,6 @@ BookReader.prototype.init = function() {
564
580
  */
565
581
  BookReader.prototype.trigger = function(name, props = this) {
566
582
  const eventName = 'BookReader:' + name;
567
- $(document).trigger(eventName, props);
568
583
 
569
584
  utils.polyfillCustomEvent(window);
570
585
  window.dispatchEvent(new CustomEvent(eventName, {
@@ -572,14 +587,15 @@ BookReader.prototype.trigger = function(name, props = this) {
572
587
  composed: true,
573
588
  detail: { props },
574
589
  }));
590
+ $(document).trigger(eventName, props);
575
591
  };
576
592
 
577
593
  BookReader.prototype.bind = function(name, callback) {
578
- $(document).bind('BookReader:' + name, callback);
594
+ $(document).on('BookReader:' + name, callback);
579
595
  };
580
596
 
581
597
  BookReader.prototype.unbind = function(name, callback) {
582
- $(document).unbind('BookReader:' + name, callback);
598
+ $(document).off('BookReader:' + name, callback);
583
599
  };
584
600
 
585
601
  /**
@@ -591,31 +607,29 @@ BookReader.prototype.resize = function() {
591
607
  this.resizeBRcontainer();
592
608
 
593
609
  // Switch navbar controls on mobile/desktop
594
- this.switchNavbarControls();
610
+ this._components.navbar.switchNavbarControls();
595
611
 
596
612
  if (this.constMode1up == this.mode) {
597
613
  if (this.onePage.autofit != 'none') {
598
- this.resizePageView1up();
614
+ this._modes.mode1Up.resizePageView();
599
615
  this.centerPageView();
600
- if (this.enableSearch) this.updateSearchHilites(); //deletes highlights but does not call remove()
601
616
  } else {
602
617
  this.centerPageView();
603
618
  this.displayedIndices = [];
604
- if (this.enableSearch) this.updateSearchHilites(); //deletes highlights but does not call remove()
605
619
  this.drawLeafsThrottled();
606
620
  }
607
621
  } else if (this.constModeThumb == this.mode) {
608
- this.prepareThumbnailView();
622
+ this._modes.modeThumb.prepare();
609
623
  } else {
610
624
  // We only need to prepare again in autofit (size of spread changes)
611
625
  if (this.twoPage.autofit) {
612
626
  // most common path, esp. for archive.org books
613
- this.prepareTwoPageView();
627
+ this._modes.mode2Up.prepare();
614
628
  } else {
615
629
  // used when zoomed in
616
630
  // Re-center if the scrollbars have disappeared
617
- var center = this.twoPageGetViewCenter();
618
- var doRecenter = false;
631
+ const center = this.twoPageGetViewCenter();
632
+ let doRecenter = false;
619
633
  if (this.twoPage.totalWidth < this.refs.$brContainer.prop('clientWidth')) {
620
634
  center.percentageX = 0.5;
621
635
  doRecenter = true;
@@ -625,7 +639,7 @@ BookReader.prototype.resize = function() {
625
639
  doRecenter = true;
626
640
  }
627
641
  if (doRecenter) {
628
- this.twoPageCenterView(center.percentageX, center.percentageY);
642
+ this._modes.mode2Up.centerView(center.percentageX, center.percentageY);
629
643
  }
630
644
  }
631
645
  }
@@ -633,93 +647,127 @@ BookReader.prototype.resize = function() {
633
647
  };
634
648
 
635
649
  /**
636
- * Binds keyboard event listeners
650
+ * Binds keyboard and keyboard focus event listeners
637
651
  */
638
- BookReader.prototype.setupKeyListeners = function() {
639
- var self = this;
640
-
641
- var KEY_PGUP = 33;
642
- var KEY_PGDOWN = 34;
643
- var KEY_END = 35;
644
- var KEY_HOME = 36;
645
-
646
- var KEY_LEFT = 37;
647
- var KEY_UP = 38;
648
- var KEY_RIGHT = 39;
649
- var KEY_DOWN = 40;
650
- // The minus(-) and equal(=) keys have different mappings for different browsers
651
- var KEY_MINUS = 189; // Chrome
652
- var KEY_MINUS_F = 173; // Firefox
653
- var KEY_NUMPAD_SUBTRACT = 109;
654
- var KEY_EQUAL = 187; // Chrome
655
- var KEY_EQUAL_F = 61; // Firefox
656
- var KEY_NUMPAD_ADD = 107;
657
-
658
- // We use document here instead of window to avoid a bug in jQuery on IE7
659
- $(document).keydown(function(e) {
660
-
661
- // Keyboard navigation
662
- if (!self.keyboardNavigationIsDisabled(e)) {
663
- switch (e.keyCode) {
664
- case KEY_PGUP:
665
- case KEY_UP:
666
- // In 1up mode page scrolling is handled by browser
667
- if (self.constMode2up == self.mode) {
668
- e.preventDefault();
669
- self.prev();
670
- }
671
- break;
672
- case KEY_DOWN:
673
- case KEY_PGDOWN:
674
- if (self.constMode2up == self.mode) {
675
- e.preventDefault();
676
- self.next();
652
+ BookReader.prototype.setupKeyListeners = function () {
653
+
654
+ // Keyboard focus by BookReader in viewport
655
+ //
656
+ // Intersection observer and callback sets BookReader keyboard
657
+ // "focus" flag off when the BookReader is not in the viewport.
658
+ if (window.IntersectionObserver) {
659
+ const observer = new IntersectionObserver((entries) => {
660
+ entries.forEach((entry) => {
661
+ if (entry.intersectionRatio === 0) {
662
+ this.hasKeyFocus = false;
663
+ } else {
664
+ this.hasKeyFocus = true;
677
665
  }
678
- break;
679
- case KEY_END:
666
+ });
667
+ }, {
668
+ root: null,
669
+ rootMargin: '0px',
670
+ threshold: [0, 0.05, 1],
671
+ });
672
+ observer.observe(this.refs.$br[0]);
673
+ }
674
+
675
+ // Keyboard listeners
676
+ document.addEventListener('keydown', (e) => {
677
+
678
+ // Ignore if BookReader "focus" flag not set
679
+ if (!this.hasKeyFocus) {
680
+ return;
681
+ }
682
+
683
+ // Ignore if modifiers are active.
684
+ if (e.getModifierState('Control') ||
685
+ e.getModifierState('Alt') ||
686
+ e.getModifierState('Meta') ||
687
+ e.getModifierState('Win') /* hack for IE */) {
688
+ return;
689
+ }
690
+
691
+ // Ignore in input elements
692
+ if (utils.isInputActive()) {
693
+ return;
694
+ }
695
+
696
+ // KeyboardEvent code values:
697
+ // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
698
+ switch (e.key) {
699
+
700
+ // Page navigation
701
+ case "Home":
702
+ e.preventDefault();
703
+ this.first();
704
+ break;
705
+ case "End":
706
+ e.preventDefault();
707
+ this.last();
708
+ break;
709
+ case "ArrowDown":
710
+ case "PageDown":
711
+ case "Down": // hack for IE and old Gecko
712
+ // In 1up and thumb mode page scrolling handled by browser
713
+ if (this.constMode2up === this.mode) {
680
714
  e.preventDefault();
681
- self.last();
682
- break;
683
- case KEY_HOME:
715
+ this.next();
716
+ }
717
+ break;
718
+ case "ArrowUp":
719
+ case "PageUp":
720
+ case "Up": // hack for IE and old Gecko
721
+ // In 1up and thumb mode page scrolling handled by browser
722
+ if (this.constMode2up === this.mode) {
684
723
  e.preventDefault();
685
- self.first();
686
- break;
687
- case KEY_LEFT:
688
- if (self.constModeThumb != self.mode) {
689
- e.preventDefault();
690
- self.left();
691
- }
692
- break;
693
- case KEY_RIGHT:
694
- if (self.constModeThumb != self.mode) {
695
- e.preventDefault();
696
- self.right();
697
- }
698
- break;
699
- case KEY_MINUS:
700
- case KEY_MINUS_F:
701
- case KEY_NUMPAD_SUBTRACT:
724
+ this.prev();
725
+ }
726
+ break;
727
+ case "ArrowLeft":
728
+ case "Left": // hack for IE and old Gecko
729
+ // No y-scrolling in thumb mode
730
+ if (this.constModeThumb != this.mode) {
702
731
  e.preventDefault();
703
- self.zoom(-1);
704
- break;
705
- case KEY_EQUAL:
706
- case KEY_EQUAL_F:
707
- case KEY_NUMPAD_ADD:
732
+ this.left();
733
+ }
734
+ break;
735
+ case "ArrowRight":
736
+ case "Right": // hack for IE and old Gecko
737
+ // No y-scrolling in thumb mode
738
+ if (this.constModeThumb != this.mode) {
708
739
  e.preventDefault();
709
- self.zoom(+1);
710
- break;
740
+ this.right();
711
741
  }
742
+ break;
743
+ // Zoom
744
+ case '-':
745
+ case 'Subtract':
746
+ e.preventDefault();
747
+ this.zoom(-1);
748
+ break;
749
+ case '+':
750
+ case '=':
751
+ case 'Add':
752
+ e.preventDefault();
753
+ this.zoom(1);
754
+ break;
755
+ // Fullscreen
756
+ case 'F':
757
+ case 'f':
758
+ e.preventDefault();
759
+ this.toggleFullscreen();
760
+ break;
712
761
  }
713
762
  });
714
763
  };
715
764
 
716
765
  BookReader.prototype.drawLeafs = function() {
717
766
  if (this.constMode1up == this.mode) {
718
- this.drawLeafsOnePage();
719
- } else if (this.constModeThumb == this.mode) {
720
- this.drawLeafsThumbnail();
767
+ // Not needed for Mode1Up anymore
768
+ return;
721
769
  } else {
722
- this.drawLeafsTwoPage();
770
+ this.activeMode.drawLeafs();
723
771
  }
724
772
  };
725
773
 
@@ -728,7 +776,7 @@ BookReader.prototype.drawLeafs = function() {
728
776
  * @param {PageIndex} index
729
777
  */
730
778
  BookReader.prototype._createPageContainer = function(index) {
731
- return new PageContainer(this._models.book.getPage(index, false), {
779
+ return new PageContainer(this.book.getPage(index, false), {
732
780
  isProtected: this.protected,
733
781
  imageCache: this.imageCache,
734
782
  loadingImage: this.imagesBaseURL + 'loading.gif',
@@ -742,8 +790,8 @@ BookReader.prototype.bindGestures = function(jElement) {
742
790
  // when you move the book with one finger and then add another
743
791
  // finger to pinch. Gestures are aware of scroll state.
744
792
 
745
- var self = this;
746
- var numTouches = 1;
793
+ const self = this;
794
+ let numTouches = 1;
747
795
 
748
796
  jElement.unbind('touchmove').bind('touchmove', function(e) {
749
797
  if (e.originalEvent.cancelable) numTouches = e.originalEvent.touches.length;
@@ -764,24 +812,6 @@ BookReader.prototype.bindGestures = function(jElement) {
764
812
  });
765
813
  };
766
814
 
767
- /** @deprecated Not used outside ModeThumb */
768
- BookReader.prototype.drawLeafsThumbnail = ModeThumb.prototype.drawLeafs;
769
- exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'drawLeafs', 'drawLeafsThumbnail');
770
- /** @deprecated Not used outside ModeThumb */
771
- BookReader.prototype.lazyLoadThumbnails = ModeThumb.prototype.lazyLoadThumbnails;
772
- exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'lazyLoadThumbnails', 'lazyLoadThumbnails');
773
- BookReader.prototype.lazyLoadImage = ModeThumb.prototype.lazyLoadImage;
774
- exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'lazyLoadImage', 'lazyLoadImage');
775
- /** @deprecated Internal use only */
776
- BookReader.prototype.zoomThumb = ModeThumb.prototype.zoom;
777
- exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'zoom', 'zoomThumb');
778
- /** @deprecated Not used outside ModeThumb */
779
- BookReader.prototype.getThumbnailWidth = ModeThumb.prototype.getThumbnailWidth;
780
- exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'getThumbnailWidth', 'getThumbnailWidth');
781
- /** @deprecated Not used outside ModeThumb */
782
- BookReader.prototype.prepareThumbnailView = ModeThumb.prototype.prepare;
783
- exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'prepare', 'prepareThumbnailView');
784
-
785
815
  /**
786
816
  * A throttled version of drawLeafs
787
817
  */
@@ -794,29 +824,11 @@ BookReader.prototype.drawLeafsThrottled = utils.throttle(
794
824
  * @param {number} direction Pass 1 to zoom in, anything else to zoom out
795
825
  */
796
826
  BookReader.prototype.zoom = function(direction) {
797
- switch (this.mode) {
798
- case this.constMode1up:
799
- if (direction == 1) {
800
- // XXX other cases
801
- this.zoom1up('in');
802
- } else {
803
- this.zoom1up('out');
804
- }
805
- break
806
- case this.constMode2up:
807
- if (direction == 1) {
808
- // XXX other cases
809
- this.zoom2up('in');
810
- } else {
811
- this.zoom2up('out');
812
- }
813
- break
814
- case this.constModeThumb:
815
- // XXX update zoomThumb for named directions
816
- this.zoomThumb(direction);
817
- break
827
+ if (direction == 1) {
828
+ this.activeMode.zoom('in');
829
+ } else {
830
+ this.activeMode.zoom('out');
818
831
  }
819
-
820
832
  this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
821
833
  return;
822
834
  };
@@ -842,11 +854,11 @@ BookReader.prototype.resizeBRcontainer = function(animate) {
842
854
  bottom: this.getFooterHeight()
843
855
  });
844
856
  }
845
- }
857
+ };
846
858
 
847
859
  BookReader.prototype.centerPageView = function() {
848
- var scrollWidth = this.refs.$brContainer.prop('scrollWidth');
849
- var clientWidth = this.refs.$brContainer.prop('clientWidth');
860
+ const scrollWidth = this.refs.$brContainer.prop('scrollWidth');
861
+ const clientWidth = this.refs.$brContainer.prop('clientWidth');
850
862
  if (scrollWidth > clientWidth) {
851
863
  this.refs.$brContainer.prop('scrollLeft', (scrollWidth - clientWidth) / 2);
852
864
  }
@@ -934,7 +946,7 @@ BookReader.prototype._reduceSort = (a, b) => a.reduce - b.reduce;
934
946
  * @return {boolean} Returns true if page could be found, false otherwise.
935
947
  */
936
948
  BookReader.prototype.jumpToPage = function(pageNum) {
937
- var pageIndex = this._models.book.parsePageString(pageNum);
949
+ const pageIndex = this.book.parsePageString(pageNum);
938
950
 
939
951
  if ('undefined' != typeof(pageIndex)) {
940
952
  this.jumpToIndex(pageIndex);
@@ -950,11 +962,9 @@ BookReader.prototype.jumpToPage = function(pageNum) {
950
962
  * @param {PageIndex} index
951
963
  */
952
964
  BookReader.prototype._isIndexDisplayed = function(index) {
953
- // One up "caches" pages +- current, so exclude those in the test.
954
- return this.constMode1up == this.mode ? this.displayedIndices.slice(1, -1).includes(index) :
955
- this.displayedIndices ? this.displayedIndices.includes(index) :
956
- this.currentIndex() == index;
957
- }
965
+ return this.displayedIndices ? this.displayedIndices.includes(index) :
966
+ this.currentIndex() == index;
967
+ };
958
968
 
959
969
  /**
960
970
  * Changes the current page
@@ -965,7 +975,7 @@ BookReader.prototype._isIndexDisplayed = function(index) {
965
975
  */
966
976
  BookReader.prototype.jumpToIndex = function(index, pageX, pageY, noAnimate) {
967
977
  // Don't jump into specific unviewable page
968
- const page = this._models.book.getPage(index);
978
+ const page = this.book.getPage(index);
969
979
  if (!page.isViewable && page.unviewablesStart != page.index) {
970
980
  // If already in unviewable range, jump to end of that range
971
981
  const alreadyInPreview = this._isIndexDisplayed(page.unviewablesStart);
@@ -987,7 +997,6 @@ BookReader.prototype.jumpToIndex = function(index, pageX, pageY, noAnimate) {
987
997
  /**
988
998
  * Return mode or 1up if initial thumb
989
999
  * @param {number}
990
- * @see BookReader.prototype.drawLeafsThumbnail
991
1000
  */
992
1001
  BookReader.prototype.getPrevReadMode = function(mode) {
993
1002
  if (mode === BookReader.constMode1up || mode === BookReader.constMode2up) {
@@ -996,7 +1005,7 @@ BookReader.prototype.getPrevReadMode = function(mode) {
996
1005
  // Initial thumb, return 1up
997
1006
  return BookReader.constMode1up;
998
1007
  }
999
- }
1008
+ };
1000
1009
 
1001
1010
  /**
1002
1011
  * Switches the mode (eg 1up 2up thumb)
@@ -1024,10 +1033,13 @@ BookReader.prototype.switchMode = function(
1024
1033
  }
1025
1034
 
1026
1035
  this.trigger(BookReader.eventNames.stop);
1027
- if (this.enableSearch) this.removeSearchHilites();
1028
1036
 
1029
1037
  this.prevReadMode = this.getPrevReadMode(this.mode);
1030
1038
 
1039
+ if (this.mode != mode) {
1040
+ this.activeMode.unprepare?.();
1041
+ }
1042
+
1031
1043
  this.mode = mode;
1032
1044
 
1033
1045
  // reinstate scale if moving from thumbnail view
@@ -1040,36 +1052,34 @@ BookReader.prototype.switchMode = function(
1040
1052
 
1041
1053
  // XXX maybe better to preserve zoom in each mode
1042
1054
  if (this.constMode1up == mode) {
1043
- this.onePageCalculateReductionFactors();
1044
- this.reduce = this.quantizeReduce(this.reduce, this.onePage.reductionFactors);
1045
- this.prepareOnePageView();
1055
+ this._modes.mode1Up.prepare();
1046
1056
  } else if (this.constModeThumb == mode) {
1047
1057
  this.reduce = this.quantizeReduce(this.reduce, this.reductionFactors);
1048
- this.prepareThumbnailView();
1058
+ this._modes.modeThumb.prepare();
1049
1059
  } else {
1050
1060
  // $$$ why don't we save autofit?
1051
1061
  // this.twoPage.autofit = null; // Take zoom level from other mode
1052
1062
  // spread indices not set, so let's set them
1053
1063
  if (init || !pageFound) {
1054
- this.setSpreadIndices();
1064
+ this._modes.mode2Up.setSpreadIndices();
1055
1065
  }
1056
1066
 
1057
- this.twoPageCalculateReductionFactors(); // this sets this.twoPage && this.reduce
1058
- this.prepareTwoPageView();
1059
- this.twoPageCenterView(0.5, 0.5); // $$$ TODO preserve center
1067
+ this._modes.mode2Up.calculateReductionFactors(); // this sets this.twoPage && this.reduce
1068
+ this._modes.mode2Up.prepare();
1069
+ this._modes.mode2Up.centerView(0.5, 0.5); // $$$ TODO preserve center
1060
1070
  }
1061
1071
 
1062
1072
  if (!(this.suppressFragmentChange || suppressFragmentChange)) {
1063
1073
  this.trigger(BookReader.eventNames.fragmentChange);
1064
1074
  }
1065
- var eventName = mode + 'PageViewSelected';
1075
+ const eventName = mode + 'PageViewSelected';
1066
1076
  this.trigger(BookReader.eventNames[eventName]);
1067
1077
 
1068
1078
  this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
1069
1079
  };
1070
1080
 
1071
1081
  BookReader.prototype.updateBrClasses = function() {
1072
- var modeToClass = {};
1082
+ const modeToClass = {};
1073
1083
  modeToClass[this.constMode1up] = 'BRmode1up';
1074
1084
  modeToClass[this.constMode2up] = 'BRmode2Up';
1075
1085
  modeToClass[this.constModeThumb] = 'BRmodeThumb';
@@ -1095,11 +1105,11 @@ BookReader.prototype.isFullscreen = function() {
1095
1105
  * Toggles fullscreen
1096
1106
  * @param { boolean } bindKeyboardControls
1097
1107
  */
1098
- BookReader.prototype.toggleFullscreen = function(bindKeyboardControls = true) {
1108
+ BookReader.prototype.toggleFullscreen = async function(bindKeyboardControls = true) {
1099
1109
  if (this.isFullscreen()) {
1100
- this.exitFullScreen();
1110
+ await this.exitFullScreen();
1101
1111
  } else {
1102
- this.enterFullscreen(bindKeyboardControls);
1112
+ await this.enterFullscreen(bindKeyboardControls);
1103
1113
  }
1104
1114
  };
1105
1115
 
@@ -1111,7 +1121,7 @@ BookReader.prototype.toggleFullscreen = function(bindKeyboardControls = true) {
1111
1121
  * - fires custom event
1112
1122
  * @param { boolean } bindKeyboardControls
1113
1123
  */
1114
- BookReader.prototype.enterFullscreen = function(bindKeyboardControls = true) {
1124
+ BookReader.prototype.enterFullscreen = async function(bindKeyboardControls = true) {
1115
1125
  const currentIndex = this.currentIndex();
1116
1126
  this.refs.$brContainer.css('opacity', 0);
1117
1127
 
@@ -1119,7 +1129,7 @@ BookReader.prototype.enterFullscreen = function(bindKeyboardControls = true) {
1119
1129
  this._fullscreenCloseHandler = (e) => {
1120
1130
  if (e.keyCode === 27) this.toggleFullscreen();
1121
1131
  };
1122
- $(document).keyup(this._fullscreenCloseHandler);
1132
+ $(document).on("keyup", this._fullscreenCloseHandler);
1123
1133
  }
1124
1134
 
1125
1135
  const windowWidth = $(window).width();
@@ -1128,14 +1138,30 @@ BookReader.prototype.enterFullscreen = function(bindKeyboardControls = true) {
1128
1138
  }
1129
1139
 
1130
1140
  this.isFullscreenActive = true;
1131
-
1132
- this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear',() => {
1133
- this.resize();
1134
- this.jumpToIndex(currentIndex);
1135
- });
1141
+ // prioritize class updates so CSS can propagate
1142
+ this.updateBrClasses();
1143
+ this.animating = true;
1144
+ await new Promise(res => this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear', res));
1145
+ if (this.activeMode instanceof Mode1Up) {
1146
+ this.activeMode.mode1UpLit.scale = this.activeMode.mode1UpLit.computeDefaultScale(this.book.getPage(currentIndex));
1147
+ // Need the new scale to be applied before calling jumpToIndex
1148
+ this.activeMode.mode1UpLit.requestUpdate();
1149
+ await this.activeMode.mode1UpLit.updateComplete;
1150
+ }
1151
+ this.jumpToIndex(currentIndex);
1152
+ this.animating = false;
1136
1153
 
1137
1154
  this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
1155
+ // Add "?view=theater"
1156
+ this.trigger(BookReader.eventNames.fragmentChange);
1157
+ // trigger event here, so that animations,
1158
+ // class updates happen before book-nav relays to web components
1138
1159
  this.trigger(BookReader.eventNames.fullscreenToggled);
1160
+
1161
+ setTimeout(() => {
1162
+ // resize book after all events & css updates
1163
+ this.resize();
1164
+ }, 0);
1139
1165
  };
1140
1166
 
1141
1167
  /**
@@ -1145,12 +1171,12 @@ BookReader.prototype.enterFullscreen = function(bindKeyboardControls = true) {
1145
1171
  * - fires custom event
1146
1172
  * @param { boolean } bindKeyboardControls
1147
1173
  */
1148
- BookReader.prototype.exitFullScreen = function() {
1174
+ BookReader.prototype.exitFullScreen = async function () {
1149
1175
  this.refs.$brContainer.css('opacity', 0);
1150
1176
 
1151
- $(document).unbind('keyup', this._fullscreenCloseHandler);
1177
+ $(document).off('keyup', this._fullscreenCloseHandler);
1152
1178
 
1153
- var windowWidth = $(window).width();
1179
+ const windowWidth = $(window).width();
1154
1180
 
1155
1181
  const canShow2up = this.options.controls.twoPage.visible;
1156
1182
  if (canShow2up && (windowWidth <= this.onePageMinBreakpoint)) {
@@ -1158,13 +1184,26 @@ BookReader.prototype.exitFullScreen = function() {
1158
1184
  }
1159
1185
 
1160
1186
  this.isFullscreenActive = false;
1187
+ // Trigger fullscreen event immediately
1188
+ // so that book-nav can relay to web components
1189
+ this.trigger(BookReader.eventNames.fullscreenToggled);
1190
+
1161
1191
  this.updateBrClasses();
1192
+ this.animating = true;
1193
+ await new Promise((res => this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear', res)));
1194
+ this.resize();
1195
+
1196
+ if (this.activeMode instanceof Mode1Up) {
1197
+ this.activeMode.mode1UpLit.scale = this.activeMode.mode1UpLit.computeDefaultScale(this.book.getPage(this.currentIndex()));
1198
+ this.activeMode.mode1UpLit.requestUpdate();
1199
+ await this.activeMode.mode1UpLit.updateComplete;
1200
+ }
1201
+
1202
+ this.animating = false;
1162
1203
 
1163
- this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear', () => {
1164
- this.resize();
1165
- });
1166
1204
  this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
1167
- this.trigger(BookReader.eventNames.fullscreenToggled);
1205
+ // Remove "?view=theater"
1206
+ this.trigger(BookReader.eventNames.fragmentChange);
1168
1207
  };
1169
1208
 
1170
1209
  /**
@@ -1178,7 +1217,7 @@ BookReader.prototype.currentIndex = function() {
1178
1217
  return this.firstIndex; // $$$ TODO page in center of view would be better
1179
1218
  } else if (this.mode == this.constMode2up) {
1180
1219
  // Only allow indices that are actually present in book
1181
- return utils.clamp(this.firstIndex, 0, this._models.book.getNumLeafs() - 1);
1220
+ return utils.clamp(this.firstIndex, 0, this.book.getNumLeafs() - 1);
1182
1221
  } else {
1183
1222
  throw 'currentIndex called for unimplemented mode ' + this.mode;
1184
1223
  }
@@ -1195,11 +1234,9 @@ BookReader.prototype.updateFirstIndex = function(
1195
1234
  index,
1196
1235
  { suppressFragmentChange = false } = {}
1197
1236
  ) {
1198
- // Called multiple times when defaults contains "mode/1up",
1199
- // including after init(). Skip fragment change if no index change
1200
- if (this.firstIndex === index) {
1201
- suppressFragmentChange = true;
1202
- }
1237
+ // If there's no change, do nothing
1238
+ if (this.firstIndex === index) return;
1239
+
1203
1240
  this.firstIndex = index;
1204
1241
  if (!(this.suppressFragmentChange || suppressFragmentChange)) {
1205
1242
  this.trigger(BookReader.eventNames.fragmentChange);
@@ -1211,7 +1248,7 @@ BookReader.prototype.updateFirstIndex = function(
1211
1248
  this.suppressFragmentChange = false;
1212
1249
  }
1213
1250
  this.trigger('pageChanged');
1214
- this.updateNavIndexThrottled(index);
1251
+ this._components.navbar.updateNavIndexThrottled(index);
1215
1252
  };
1216
1253
 
1217
1254
  /**
@@ -1258,10 +1295,10 @@ BookReader.prototype.leftmost = function() {
1258
1295
  }
1259
1296
  };
1260
1297
 
1261
- BookReader.prototype.next = function() {
1298
+ BookReader.prototype.next = function({triggerStop = true} = {}) {
1262
1299
  if (this.constMode2up == this.mode) {
1263
- this.trigger(BookReader.eventNames.stop);
1264
- this.flipFwdToIndex(null);
1300
+ if (triggerStop) this.trigger(BookReader.eventNames.stop);
1301
+ this._modes.mode2Up.flipFwdToIndex(null);
1265
1302
  } else {
1266
1303
  if (this.firstIndex < this.lastDisplayableIndex()) {
1267
1304
  this.jumpToIndex(this.firstIndex + 1);
@@ -1269,13 +1306,13 @@ BookReader.prototype.next = function() {
1269
1306
  }
1270
1307
  };
1271
1308
 
1272
- BookReader.prototype.prev = function() {
1309
+ BookReader.prototype.prev = function({triggerStop = true} = {}) {
1273
1310
  const isOnFrontPage = this.firstIndex < 1;
1274
1311
  if (isOnFrontPage) return;
1275
1312
 
1276
1313
  if (this.constMode2up == this.mode) {
1277
- this.trigger(BookReader.eventNames.stop);
1278
- this.flipBackToIndex(null);
1314
+ if (triggerStop) this.trigger(BookReader.eventNames.stop);
1315
+ this._modes.mode2Up.flipBackToIndex(null);
1279
1316
  } else {
1280
1317
  if (this.firstIndex >= 1) {
1281
1318
  this.jumpToIndex(this.firstIndex - 1);
@@ -1337,173 +1374,12 @@ BookReader.prototype.scrollUp = function() {
1337
1374
  BookReader.prototype._scrollAmount = function() {
1338
1375
  if (this.constMode1up == this.mode) {
1339
1376
  // Overlap by % of page size
1340
- return parseInt(this.refs.$brContainer.prop('clientHeight') - this._models.book.getPageHeight(this.currentIndex()) / this.reduce * 0.03);
1377
+ return parseInt(this.refs.$brContainer.prop('clientHeight') - this.book.getPageHeight(this.currentIndex()) / this.reduce * 0.03);
1341
1378
  }
1342
1379
 
1343
1380
  return parseInt(0.9 * this.refs.$brContainer.prop('clientHeight'));
1344
1381
  };
1345
1382
 
1346
- /**
1347
- * @deprecated No longer used; will be remove in v5
1348
- */
1349
- BookReader.prototype.prefetchImg = async function(index, fetchNow = false) {
1350
- console.warn('Call to deprecated function: BookReader.prefetchImg. No-op.');
1351
- };
1352
-
1353
- /**
1354
- * @deprecated No longer used; will be remove in v5
1355
- */
1356
- BookReader.prototype.pruneUnusedImgs = function() {
1357
- console.warn('Call to deprecated function: BookReader.pruneUnused. No-op.');
1358
- };
1359
-
1360
- /************************/
1361
- /** Mode1Up extensions **/
1362
- /************************/
1363
- /** @deprecated not used outside BookReader */
1364
- BookReader.prototype.prepareOnePageView = Mode1Up.prototype.prepare;
1365
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'prepare', 'prepareOnePageView');
1366
- /** @deprecated not used outside BookReader */
1367
- BookReader.prototype.drawLeafsOnePage = Mode1Up.prototype.drawLeafs;
1368
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'drawLeafs', 'drawLeafsOnePage');
1369
- /** @deprecated not used outside BookReader */
1370
- BookReader.prototype.zoom1up = Mode1Up.prototype.zoom;
1371
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'zoom', 'zoom1up');
1372
- /** @deprecated not used outside Mode1Up */
1373
- BookReader.prototype.onePageGetAutofitWidth = Mode1Up.prototype.getAutofitWidth;
1374
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'getAutofitWidth', 'onePageGetAutofitWidth');
1375
- /** @deprecated not used outside Mode1Up, BookReader */
1376
- BookReader.prototype.onePageGetAutofitHeight = Mode1Up.prototype.getAutofitHeight;
1377
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'getAutofitHeight', 'onePageGetAutofitHeight');
1378
- /** @deprecated not used outside Mode1Up, BookReader */
1379
- BookReader.prototype.onePageGetPageTop = Mode1Up.prototype.getPageTop;
1380
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'getPageTop', 'onePageGetPageTop');
1381
- /** @deprecated not used outside Mode1Up, BookReader */
1382
- BookReader.prototype.onePageCalculateReductionFactors = Mode1Up.prototype.calculateReductionFactors;
1383
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'calculateReductionFactors', 'onePageCalculateReductionFactors');
1384
- /** @deprecated not used outside Mode1Up, BookReader */
1385
- BookReader.prototype.resizePageView1up = Mode1Up.prototype.resizePageView;
1386
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'resizePageView', 'resizePageView1up');
1387
- /** @deprecated not used outside Mode1Up */
1388
- BookReader.prototype.onePageCalculateViewDimensions = Mode1Up.prototype.calculateViewDimensions;
1389
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'calculateViewDimensions', 'onePageCalculateViewDimensions');
1390
- /** @deprecated not used outside Mode1Up */
1391
- BookReader.prototype.centerX1up = Mode1Up.prototype.centerX;
1392
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'centerX', 'centerX1up');
1393
- /** @deprecated not used outside Mode1Up */
1394
- BookReader.prototype.centerY1up = Mode1Up.prototype.centerY;
1395
- exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'centerY', 'centerY1up');
1396
-
1397
- /************************/
1398
- /** Mode2Up extensions **/
1399
- /************************/
1400
- /** @deprecated not used outside Mode2Up */
1401
- BookReader.prototype.zoom2up = Mode2Up.prototype.zoom;
1402
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'zoom', 'zoom2up');
1403
- BookReader.prototype.twoPageGetAutofitReduce = Mode2Up.prototype.getAutofitReduce;
1404
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'getAutofitReduce', 'twoPageGetAutofitReduce');
1405
- BookReader.prototype.flipBackToIndex = Mode2Up.prototype.flipBackToIndex;
1406
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipBackToIndex', 'flipBackToIndex');
1407
- BookReader.prototype.flipFwdToIndex = Mode2Up.prototype.flipFwdToIndex;
1408
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipFwdToIndex', 'flipFwdToIndex');
1409
- BookReader.prototype.setHilightCss2UP = Mode2Up.prototype.setHilightCss;
1410
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setHilightCss', 'setHilightCss2UP');
1411
- /** @deprecated not used outside Mode2Up */
1412
- BookReader.prototype.setClickHandler2UP = Mode2Up.prototype.setClickHandler;
1413
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setClickHandler', 'setClickHandler2UP');
1414
- /** @deprecated not used outside Mode2Up */
1415
- BookReader.prototype.drawLeafsTwoPage = Mode2Up.prototype.drawLeafs;
1416
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'drawLeafs', 'drawLeafsTwoPage');
1417
- /** @deprecated not used outside BookReader */
1418
- BookReader.prototype.prepareTwoPageView = Mode2Up.prototype.prepareTwoPageView;
1419
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'prepareTwoPageView', 'prepareTwoPageView');
1420
- /** @deprecated not used outside Mode2Up */
1421
- BookReader.prototype.prepareTwoPagePopUp = Mode2Up.prototype.preparePopUp;
1422
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'preparePopUp', 'prepareTwoPagePopUp');
1423
- /** @deprecated not used outside BookReader, Mode2Up */
1424
- BookReader.prototype.calculateSpreadSize = Mode2Up.prototype.calculateSpreadSize;
1425
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'calculateSpreadSize', 'calculateSpreadSize');
1426
- /** @deprecated not used outside BookReader, Mode2Up */
1427
- BookReader.prototype.getIdealSpreadSize = Mode2Up.prototype.getIdealSpreadSize;
1428
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'getIdealSpreadSize', 'getIdealSpreadSize');
1429
- /** @deprecated not used outside BookReader, Mode2Up */
1430
- BookReader.prototype.getSpreadSizeFromReduce = Mode2Up.prototype.getSpreadSizeFromReduce;
1431
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'getSpreadSizeFromReduce', 'getSpreadSizeFromReduce');
1432
- /** @deprecated unused */
1433
- BookReader.prototype.twoPageIsZoomedIn = Mode2Up.prototype.isZoomedIn;
1434
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'isZoomedIn', 'twoPageIsZoomedIn');
1435
- /** @deprecated not used outside BookReader */
1436
- BookReader.prototype.twoPageCalculateReductionFactors = Mode2Up.prototype.calculateReductionFactors;
1437
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'calculateReductionFactors', 'twoPageCalculateReductionFactors');
1438
- /** @deprecated unused */
1439
- BookReader.prototype.twoPageSetCursor = Mode2Up.prototype.setCursor;
1440
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setCursor', 'twoPageSetCursor');
1441
- /** @deprecated unused outside BookReader, Mode2Up */
1442
- BookReader.prototype.flipLeftToRight = Mode2Up.prototype.flipLeftToRight;
1443
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipLeftToRight', 'flipLeftToRight');
1444
- /** @deprecated unused outside BookReader, Mode2Up */
1445
- BookReader.prototype.flipRightToLeft = Mode2Up.prototype.flipRightToLeft;
1446
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipRightToLeft', 'flipRightToLeft');
1447
- /** @deprecated unused outside Mode2Up */
1448
- BookReader.prototype.setMouseHandlers2UP = Mode2Up.prototype.setMouseHandlers;
1449
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setMouseHandlers', 'setMouseHandlers2UP');
1450
- /** @deprecated unused outside BookReader, Mode2Up */
1451
- BookReader.prototype.prepareFlipLeftToRight = Mode2Up.prototype.prepareFlipLeftToRight;
1452
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'prepareFlipLeftToRight', 'prepareFlipLeftToRight');
1453
- /** @deprecated unused outside BookReader, Mode2Up */
1454
- BookReader.prototype.prepareFlipRightToLeft = Mode2Up.prototype.prepareFlipRightToLeft;
1455
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'prepareFlipRightToLeft', 'prepareFlipRightToLeft');
1456
- /** @deprecated unused outside Mode2Up */
1457
- BookReader.prototype.getPageWidth2UP = Mode2Up.prototype.getPageWidth;
1458
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'getPageWidth', 'getPageWidth2UP');
1459
- /** @deprecated unused outside Mode2Up */
1460
- BookReader.prototype.twoPageGutter = Mode2Up.prototype.gutter;
1461
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'gutter', 'twoPageGutter');
1462
- /** @deprecated unused outside Mode2Up */
1463
- BookReader.prototype.twoPageTop = Mode2Up.prototype.top;
1464
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'top', 'twoPageTop');
1465
- /** @deprecated unused outside Mode2Up */
1466
- BookReader.prototype.twoPageCoverWidth = Mode2Up.prototype.coverWidth;
1467
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'coverWidth', 'twoPageCoverWidth');
1468
- /** @deprecated unused outside Mode2Up */
1469
- BookReader.prototype.twoPageGetViewCenter = Mode2Up.prototype.getViewCenter;
1470
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'getViewCenter', 'twoPageGetViewCenter');
1471
- /** @deprecated unused outside BookReader, Mode2Up */
1472
- BookReader.prototype.twoPageCenterView = Mode2Up.prototype.centerView;
1473
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'centerView', 'twoPageCenterView');
1474
- /** @deprecated unused outside Mode2Up */
1475
- BookReader.prototype.twoPageFlipAreaHeight = Mode2Up.prototype.flipAreaHeight;
1476
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipAreaHeight', 'twoPageFlipAreaHeight');
1477
- /** @deprecated unused outside Mode2Up */
1478
- BookReader.prototype.twoPageFlipAreaWidth = Mode2Up.prototype.flipAreaWidth;
1479
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipAreaWidth', 'twoPageFlipAreaWidth');
1480
- /** @deprecated unused outside BookReader, Mode2Up */
1481
- BookReader.prototype.twoPageFlipAreaTop = Mode2Up.prototype.flipAreaTop;
1482
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipAreaTop', 'twoPageFlipAreaTop');
1483
- /** @deprecated unused outside Mode2Up */
1484
- BookReader.prototype.twoPageLeftFlipAreaLeft = Mode2Up.prototype.leftFlipAreaLeft;
1485
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'leftFlipAreaLeft', 'twoPageLeftFlipAreaLeft');
1486
- /** @deprecated unused outside Mode2Up */
1487
- BookReader.prototype.twoPageRightFlipAreaLeft = Mode2Up.prototype.rightFlipAreaLeft;
1488
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'rightFlipAreaLeft', 'twoPageRightFlipAreaLeft');
1489
- /** @deprecated unused outside BookReader, Mode2Up */
1490
- BookReader.prototype.gutterOffsetForIndex = Mode2Up.prototype.gutterOffsetForIndex;
1491
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'gutterOffsetForIndex', 'gutterOffsetForIndex');
1492
- /** @deprecated unused outside BookReader, Mode2Up */
1493
- BookReader.prototype.leafEdgeWidth = Mode2Up.prototype.leafEdgeWidth;
1494
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'leafEdgeWidth', 'leafEdgeWidth');
1495
- /** @deprecated unused outside BookReader, Mode2Up */
1496
- BookReader.prototype.jumpIndexForLeftEdgePageX = Mode2Up.prototype.jumpIndexForLeftEdgePageX;
1497
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'jumpIndexForLeftEdgePageX', 'jumpIndexForLeftEdgePageX');
1498
- /** @deprecated unused outside BookReader, Mode2Up */
1499
- BookReader.prototype.jumpIndexForRightEdgePageX = Mode2Up.prototype.jumpIndexForRightEdgePageX;
1500
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'jumpIndexForRightEdgePageX', 'jumpIndexForRightEdgePageX');
1501
- /** @deprecated unused outside Mode2Up */
1502
- BookReader.prototype.prefetch = Mode2Up.prototype.prefetch;
1503
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'prefetch', 'prefetch');
1504
- /** @deprecated unused outside Mode2Up */
1505
- BookReader.prototype.setSpreadIndices = Mode2Up.prototype.setSpreadIndices;
1506
- exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setSpreadIndices', 'setSpreadIndices');
1507
1383
  /**
1508
1384
  * Immediately stop flip animations. Callbacks are triggered.
1509
1385
  */
@@ -1527,15 +1403,6 @@ BookReader.prototype.stopFlipAnimations = function() {
1527
1403
  });
1528
1404
  };
1529
1405
 
1530
- /**
1531
- * Returns true if keyboard navigation should be disabled for the event
1532
- * @param {Event}
1533
- * @return {boolean}
1534
- */
1535
- BookReader.prototype.keyboardNavigationIsDisabled = function(event) {
1536
- return event.target.tagName == "INPUT";
1537
- };
1538
-
1539
1406
  /**
1540
1407
  * @template TClass extends { br: BookReader }
1541
1408
  * Helper method to expose a method onto BookReader from a composed class.
@@ -1558,30 +1425,9 @@ function exposeOverrideableMethod(Class, classKey, method, brMethod = method) {
1558
1425
  /***********************/
1559
1426
  /** Navbar extensions **/
1560
1427
  /***********************/
1428
+ /** This cannot be removed yet because plugin.tts.js overrides it */
1561
1429
  BookReader.prototype.initNavbar = Navbar.prototype.init;
1562
1430
  exposeOverrideableMethod(Navbar, '_components.navbar', 'init', 'initNavbar');
1563
- BookReader.prototype.switchNavbarControls = Navbar.prototype.switchNavbarControls;
1564
- exposeOverrideableMethod(Navbar, '_components.navbar', 'switchNavbarControls');
1565
- BookReader.prototype.updateViewModeButton = Navbar.prototype.updateViewModeButton;
1566
- exposeOverrideableMethod(Navbar, '_components.navbar', 'updateViewModeButton');
1567
- BookReader.prototype.getNavPageNumString = Navbar.prototype.getNavPageNumString;
1568
- exposeOverrideableMethod(Navbar, '_components.navbar', 'getNavPageNumString');
1569
- /** @deprecated */
1570
- BookReader.prototype.initEmbedNavbar = Navbar.prototype.initEmbed;
1571
- exposeOverrideableMethod(Navbar, '_components.navbar', 'initEmbed', 'initEmbedNavbar');
1572
- /** @deprecated unused */
1573
- BookReader.prototype.getNavPageNumHtml = getNavPageNumHtml;
1574
- /** @deprecated unused outside this file */
1575
- BookReader.prototype.updateNavPageNum = Navbar.prototype.updateNavPageNum;
1576
- exposeOverrideableMethod(Navbar, '_components.navbar', 'updateNavPageNum');
1577
- /** @deprecated unused outside this file */
1578
- BookReader.prototype.updateNavIndex = Navbar.prototype.updateNavIndex;
1579
- exposeOverrideableMethod(Navbar, '_components.navbar', 'updateNavIndex');
1580
- /** @deprecated unused outside this file */
1581
- BookReader.prototype.updateNavIndexThrottled = utils.throttle(BookReader.prototype.updateNavIndex, 250, false);
1582
- /** @deprecated unused */
1583
- BookReader.prototype.updateNavIndexDebounced = utils.debounce(BookReader.prototype.updateNavIndex, 500, false);
1584
-
1585
1431
 
1586
1432
  /************************/
1587
1433
  /** Toolbar extensions **/
@@ -1596,15 +1442,6 @@ BookReader.prototype.buildInfoDiv = Toolbar.prototype.buildInfoDiv;
1596
1442
  exposeOverrideableMethod(Toolbar, '_components.toolbar', 'buildInfoDiv');
1597
1443
  BookReader.prototype.getToolBarHeight = Toolbar.prototype.getToolBarHeight;
1598
1444
  exposeOverrideableMethod(Toolbar, '_components.toolbar', 'getToolBarHeight');
1599
- /** @deprecated zoom no longer in toolbar */
1600
- BookReader.prototype.updateToolbarZoom = Toolbar.prototype.updateToolbarZoom;
1601
- exposeOverrideableMethod(Toolbar, '_components.toolbar', 'updateToolbarZoom');
1602
- /** @deprecated unused */
1603
- BookReader.prototype.blankInfoDiv = blankInfoDiv;
1604
- /** @deprecated unused */
1605
- BookReader.prototype.blankShareDiv = blankShareDiv;
1606
- /** @deprecated unused */
1607
- BookReader.prototype.createPopup = createPopup;
1608
1445
 
1609
1446
  /**
1610
1447
  * Bind navigation handlers
@@ -1663,7 +1500,7 @@ BookReader.prototype.bindNavigationHandlers = function() {
1663
1500
  },
1664
1501
  full: () => {
1665
1502
  if (this.ui == 'embed') {
1666
- var url = this.$('.BRembedreturn a').attr('href');
1503
+ const url = this.$('.BRembedreturn a').attr('href');
1667
1504
  window.open(url);
1668
1505
  } else {
1669
1506
  this.toggleFullscreen();
@@ -1677,17 +1514,17 @@ BookReader.prototype.bindNavigationHandlers = function() {
1677
1514
 
1678
1515
  for (const control in navigationControls) {
1679
1516
  jIcons.filter(`.${control}`).on('click.bindNavigationHandlers', () => {
1680
- navigationControls[control]()
1517
+ navigationControls[control]();
1681
1518
  return false;
1682
1519
  });
1683
1520
  }
1684
1521
 
1685
- var $brNavCntlBtmEl = this.$('.BRnavCntlBtm');
1686
- var $brNavCntlTopEl = this.$('.BRnavCntlTop');
1522
+ const $brNavCntlBtmEl = this.$('.BRnavCntlBtm');
1523
+ const $brNavCntlTopEl = this.$('.BRnavCntlTop');
1687
1524
 
1688
1525
  this.$('.BRnavCntl').click(
1689
1526
  function() {
1690
- var promises = [];
1527
+ const promises = [];
1691
1528
  // TODO don't use magic constants
1692
1529
  // TODO move this to a function
1693
1530
  if ($brNavCntlBtmEl.hasClass('BRdn')) {
@@ -1707,7 +1544,7 @@ BookReader.prototype.bindNavigationHandlers = function() {
1707
1544
  $brNavCntlBtmEl.addClass('BRdn').removeClass('BRup');
1708
1545
  $brNavCntlTopEl.addClass('BRup').removeClass('BRdn');
1709
1546
  self.$('.BRnavCntlBtm.BRnavCntl').animate({height:'30px'});
1710
- self.$('.BRvavCntl').animate({opacity:1})
1547
+ self.$('.BRvavCntl').animate({opacity:1});
1711
1548
  }
1712
1549
  $.when.apply($, promises).done(function() {
1713
1550
  // Only do full resize in auto mode and need to recalc. size
@@ -1725,24 +1562,28 @@ BookReader.prototype.bindNavigationHandlers = function() {
1725
1562
  });
1726
1563
  }
1727
1564
  );
1728
- $brNavCntlBtmEl.mouseover(function() {
1729
- if ($(this).hasClass('BRup')) {
1730
- self.$('.BRnavCntl').animate({opacity:1},250);
1731
- }
1732
- }).mouseleave(function() {
1733
- if ($(this).hasClass('BRup')) {
1734
- self.$('.BRnavCntl').animate({opacity:.75},250);
1735
- }
1736
- });
1737
- $brNavCntlTopEl.mouseover(function() {
1738
- if ($(this).hasClass('BRdn')) {
1739
- self.$('.BRnavCntl').animate({opacity:1},250);
1740
- }
1741
- }).mouseleave(function() {
1742
- if ($(this).hasClass('BRdn')) {
1743
- self.$('.BRnavCntl').animate({opacity:.75},250);
1744
- }
1745
- });
1565
+ $brNavCntlBtmEl
1566
+ .on("mouseover", function() {
1567
+ if ($(this).hasClass('BRup')) {
1568
+ self.$('.BRnavCntl').animate({opacity:1},250);
1569
+ }
1570
+ })
1571
+ .on("mouseleave", function() {
1572
+ if ($(this).hasClass('BRup')) {
1573
+ self.$('.BRnavCntl').animate({opacity:.75},250);
1574
+ }
1575
+ });
1576
+ $brNavCntlTopEl
1577
+ .on("mouseover", function() {
1578
+ if ($(this).hasClass('BRdn')) {
1579
+ self.$('.BRnavCntl').animate({opacity:1},250);
1580
+ }
1581
+ })
1582
+ .on("mouseleave", function() {
1583
+ if ($(this).hasClass('BRdn')) {
1584
+ self.$('.BRnavCntl').animate({opacity:.75},250);
1585
+ }
1586
+ });
1746
1587
 
1747
1588
  this.initSwipeData();
1748
1589
 
@@ -1780,7 +1621,7 @@ BookReader.prototype.navigationMousemoveHandler = function(event) {
1780
1621
  if (event.data['br'].uiAutoHide) {
1781
1622
  // 77px is an approximate height of the Internet Archive Top Nav
1782
1623
  // 75 & 76 (pixels) provide used in this context is checked against the IA top nav height
1783
- var navkey = $(document).height() - 75;
1624
+ const navkey = $(document).height() - 75;
1784
1625
  if ((event.pageY < 76) || (event.pageY > navkey)) {
1785
1626
  // inside or near navigation elements
1786
1627
  event.data['br'].hideNavigation();
@@ -1807,11 +1648,11 @@ BookReader.prototype.initSwipeData = function(clientX, clientY) {
1807
1648
  deltaX: 0,
1808
1649
  deltaY: 0,
1809
1650
  deltaT: 0
1810
- }
1651
+ };
1811
1652
  };
1812
1653
 
1813
1654
  BookReader.prototype.swipeMousedownHandler = function(event) {
1814
- var self = event.data['br'];
1655
+ const self = event.data['br'];
1815
1656
 
1816
1657
  // We should be the last bubble point for the page images
1817
1658
  // Disable image drag and select, but keep right-click
@@ -1819,13 +1660,13 @@ BookReader.prototype.swipeMousedownHandler = function(event) {
1819
1660
  return !self.protected;
1820
1661
  }
1821
1662
 
1822
- $(event.target).bind('mouseout.swipe',
1663
+ $(event.target).on('mouseout.swipe',
1823
1664
  { 'br': self},
1824
1665
  self.swipeMouseupHandler
1825
- ).bind('mouseup.swipe',
1666
+ ).on('mouseup.swipe',
1826
1667
  { 'br': self},
1827
1668
  self.swipeMouseupHandler
1828
- ).bind('mousemove.swipe',
1669
+ ).on('mousemove.swipe',
1829
1670
  { 'br': self },
1830
1671
  self.swipeMousemoveHandler
1831
1672
  );
@@ -1841,8 +1682,8 @@ BookReader.prototype.swipeMousedownHandler = function(event) {
1841
1682
  };
1842
1683
 
1843
1684
  BookReader.prototype.swipeMousemoveHandler = function(event) {
1844
- var self = event.data['br'];
1845
- var _swipe = self._swipe;
1685
+ const self = event.data['br'];
1686
+ const _swipe = self._swipe;
1846
1687
  if (! _swipe.mightBeSwiping) {
1847
1688
  return;
1848
1689
  }
@@ -1852,12 +1693,12 @@ BookReader.prototype.swipeMousemoveHandler = function(event) {
1852
1693
  _swipe.deltaY = event.clientY - _swipe.startY;
1853
1694
  _swipe.deltaT = (new Date).getTime() - _swipe.startTime;
1854
1695
 
1855
- var absX = Math.abs(_swipe.deltaX);
1856
- var absY = Math.abs(_swipe.deltaY);
1696
+ const absX = Math.abs(_swipe.deltaX);
1697
+ const absY = Math.abs(_swipe.deltaY);
1857
1698
 
1858
1699
  // Minimum distance in the amount of tim to trigger the swipe
1859
- var minSwipeLength = Math.min(self.refs.$br.width() / 5, 80);
1860
- var maxSwipeTime = 400;
1700
+ const minSwipeLength = Math.min(self.refs.$br.width() / 5, 80);
1701
+ const maxSwipeTime = 400;
1861
1702
 
1862
1703
  // Check for horizontal swipe
1863
1704
  if (absX > absY && (absX > minSwipeLength) && _swipe.deltaT < maxSwipeTime) {
@@ -1891,11 +1732,11 @@ BookReader.prototype.swipeMousemoveHandler = function(event) {
1891
1732
  };
1892
1733
 
1893
1734
  BookReader.prototype.swipeMouseupHandler = function(event) {
1894
- var _swipe = event.data['br']._swipe;
1735
+ const _swipe = event.data['br']._swipe;
1895
1736
  _swipe.mightBeSwiping = false;
1896
1737
  _swipe.mightBeDragging = false;
1897
1738
 
1898
- $(event.target).unbind('mouseout.swipe').unbind('mouseup.swipe').unbind('mousemove.swipe');
1739
+ $(event.target).off('mouseout.swipe').off('mouseup.swipe').off('mousemove.swipe');
1899
1740
 
1900
1741
  if (_swipe.didSwipe || _swipe.didDrag) {
1901
1742
  // Swallow event if completed swipe gesture
@@ -1908,20 +1749,21 @@ BookReader.prototype.swipeMouseupHandler = function(event) {
1908
1749
  };
1909
1750
 
1910
1751
  BookReader.prototype.bindMozTouchHandlers = function() {
1911
- var self = this;
1752
+ const self = this;
1912
1753
 
1913
1754
  // Currently only want touch handlers in 2up
1914
- this.refs.$br.bind('MozTouchDown', function(event) {
1915
- if (this.mode == self.constMode2up) {
1916
- event.preventDefault();
1917
- }
1918
- })
1919
- .bind('MozTouchMove', function(event) {
1755
+ this.refs.$br
1756
+ .on('MozTouchDown', function(event) {
1757
+ if (this.mode == self.constMode2up) {
1758
+ event.preventDefault();
1759
+ }
1760
+ })
1761
+ .on('MozTouchMove', function(event) {
1920
1762
  if (this.mode == self.constMode2up) {
1921
1763
  event.preventDefault();
1922
1764
  }
1923
1765
  })
1924
- .bind('MozTouchUp', function(event) {
1766
+ .on('MozTouchUp', function(event) {
1925
1767
  if (this.mode == self.constMode2up) {
1926
1768
  event.preventDefault();
1927
1769
  }
@@ -1934,8 +1776,8 @@ BookReader.prototype.bindMozTouchHandlers = function() {
1934
1776
  */
1935
1777
  BookReader.prototype.navigationIsVisible = function() {
1936
1778
  // $$$ doesn't account for transitioning states, nav must be fully visible to return true
1937
- var toolpos = this.refs.$BRtoolbar.position();
1938
- var tooltop = toolpos.top;
1779
+ const toolpos = this.refs.$BRtoolbar.position();
1780
+ const tooltop = toolpos.top;
1939
1781
  return tooltop == 0;
1940
1782
  };
1941
1783
 
@@ -1944,19 +1786,19 @@ BookReader.prototype.navigationIsVisible = function() {
1944
1786
  * Defaults to SHOW the navigation chrome
1945
1787
  */
1946
1788
  BookReader.prototype.setNavigationView = function brSetNavigationView(hide) {
1947
- var animationLength = this.constNavAnimationDuration;
1948
- var animationType = 'linear';
1949
- var resizePageContainer = function resizePageContainer () {
1789
+ const animationLength = this.constNavAnimationDuration;
1790
+ const animationType = 'linear';
1791
+ const resizePageContainer = function resizePageContainer () {
1950
1792
  /* main page container fills whole container */
1951
1793
  if (this.constMode2up !== this.mode) {
1952
- var animate = true;
1794
+ const animate = true;
1953
1795
  this.resizeBRcontainer(animate);
1954
1796
  }
1955
1797
  this.trigger(BookReader.eventNames.navToggled);
1956
1798
  }.bind(this);
1957
1799
 
1958
- var toolbarHeight = 0;
1959
- var navbarHeight = 0;
1800
+ let toolbarHeight = 0;
1801
+ let navbarHeight = 0;
1960
1802
  if (hide) {
1961
1803
  toolbarHeight = this.getToolBarHeight() * -1;
1962
1804
  navbarHeight = this.getFooterHeight() * -1;
@@ -1987,7 +1829,7 @@ BookReader.prototype.setNavigationView = function brSetNavigationView(hide) {
1987
1829
  BookReader.prototype.hideNavigation = function() {
1988
1830
  // Check if navigation is showing
1989
1831
  if (this.navigationIsVisible()) {
1990
- var hide = true;
1832
+ const hide = true;
1991
1833
  this.setNavigationView(hide);
1992
1834
  }
1993
1835
  };
@@ -2015,14 +1857,14 @@ BookReader.prototype.firstDisplayableIndex = function() {
2015
1857
 
2016
1858
  if ('rl' != this.pageProgression) {
2017
1859
  // LTR
2018
- if (this._models.book.getPageSide(0) == 'L') {
1860
+ if (this.book.getPageSide(0) == 'L') {
2019
1861
  return 0;
2020
1862
  } else {
2021
1863
  return -1;
2022
1864
  }
2023
1865
  } else {
2024
1866
  // RTL
2025
- if (this._models.book.getPageSide(0) == 'R') {
1867
+ if (this.book.getPageSide(0) == 'R') {
2026
1868
  return 0;
2027
1869
  } else {
2028
1870
  return -1;
@@ -2038,7 +1880,7 @@ BookReader.prototype.firstDisplayableIndex = function() {
2038
1880
  */
2039
1881
  BookReader.prototype.lastDisplayableIndex = function() {
2040
1882
 
2041
- var lastIndex = this._models.book.getNumLeafs() - 1;
1883
+ const lastIndex = this.book.getNumLeafs() - 1;
2042
1884
 
2043
1885
  if (this.mode != this.constMode2up) {
2044
1886
  return lastIndex;
@@ -2046,14 +1888,14 @@ BookReader.prototype.lastDisplayableIndex = function() {
2046
1888
 
2047
1889
  if ('rl' != this.pageProgression) {
2048
1890
  // LTR
2049
- if (this._models.book.getPageSide(lastIndex) == 'R') {
1891
+ if (this.book.getPageSide(lastIndex) == 'R') {
2050
1892
  return lastIndex;
2051
1893
  } else {
2052
1894
  return lastIndex + 1;
2053
1895
  }
2054
1896
  } else {
2055
1897
  // RTL
2056
- if (this._models.book.getPageSide(lastIndex) == 'L') {
1898
+ if (this.book.getPageSide(lastIndex) == 'L') {
2057
1899
  return lastIndex;
2058
1900
  } else {
2059
1901
  return lastIndex + 1;
@@ -2065,46 +1907,11 @@ BookReader.prototype.lastDisplayableIndex = function() {
2065
1907
  /**************************/
2066
1908
  /** BookModel extensions **/
2067
1909
  /**************************/
2068
- /** @deprecated not used outside */
2069
- BookReader.prototype.getMedianPageSize = BookModel.prototype.getMedianPageSize;
2070
- exposeOverrideableMethod(BookModel, '_models.book', 'getMedianPageSize');
2071
- BookReader.prototype._getPageWidth = BookModel.prototype._getPageWidth;
2072
- exposeOverrideableMethod(BookModel, '_models.book', '_getPageWidth');
2073
- BookReader.prototype._getPageHeight = BookModel.prototype._getPageHeight;
2074
- exposeOverrideableMethod(BookModel, '_models.book', '_getPageHeight');
2075
- BookReader.prototype.getPageIndex = BookModel.prototype.getPageIndex;
2076
- exposeOverrideableMethod(BookModel, '_models.book', 'getPageIndex');
2077
- /** @deprecated not used outside */
2078
- BookReader.prototype.getPageIndices = BookModel.prototype.getPageIndices;
2079
- exposeOverrideableMethod(BookModel, '_models.book', 'getPageIndices');
2080
- BookReader.prototype.getPageName = BookModel.prototype.getPageName;
2081
- exposeOverrideableMethod(BookModel, '_models.book', 'getPageName');
2082
- BookReader.prototype.getNumLeafs = BookModel.prototype.getNumLeafs;
2083
- exposeOverrideableMethod(BookModel, '_models.book', 'getNumLeafs');
2084
- BookReader.prototype.getPageWidth = BookModel.prototype.getPageWidth;
2085
- exposeOverrideableMethod(BookModel, '_models.book', 'getPageWidth');
2086
- BookReader.prototype.getPageHeight = BookModel.prototype.getPageHeight;
2087
- exposeOverrideableMethod(BookModel, '_models.book', 'getPageHeight');
1910
+ // Must modify petabox extension, which expects this on the prototype
1911
+ // before removing.
2088
1912
  BookReader.prototype.getPageURI = BookModel.prototype.getPageURI;
2089
- exposeOverrideableMethod(BookModel, '_models.book', 'getPageURI');
2090
- BookReader.prototype.getPageSide = BookModel.prototype.getPageSide;
2091
- exposeOverrideableMethod(BookModel, '_models.book', 'getPageSide');
2092
- BookReader.prototype.getPageNum = BookModel.prototype.getPageNum;
2093
- exposeOverrideableMethod(BookModel, '_models.book', 'getPageNum');
2094
- BookReader.prototype.getPageProp = BookModel.prototype.getPageProp;
2095
- exposeOverrideableMethod(BookModel, '_models.book', 'getPageProp');
2096
- BookReader.prototype.getSpreadIndices = BookModel.prototype.getSpreadIndices;
2097
- exposeOverrideableMethod(BookModel, '_models.book', 'getSpreadIndices');
2098
- BookReader.prototype.leafNumToIndex = BookModel.prototype.leafNumToIndex;
2099
- exposeOverrideableMethod(BookModel, '_models.book', 'leafNumToIndex');
2100
- BookReader.prototype.parsePageString = BookModel.prototype.parsePageString;
2101
- exposeOverrideableMethod(BookModel, '_models.book', 'parsePageString');
2102
- /** @deprecated unused */
2103
- BookReader.prototype._getDataFlattened = BookModel.prototype._getDataFlattened;
2104
- exposeOverrideableMethod(BookModel, '_models.book', '_getDataFlattened');
2105
- /** @deprecated unused */
2106
- BookReader.prototype._getDataProp = BookModel.prototype._getDataProp;
2107
- exposeOverrideableMethod(BookModel, '_models.book', '_getDataProp');
1913
+ exposeOverrideableMethod(BookModel, 'book', 'getPageURI');
1914
+
2108
1915
 
2109
1916
  // Parameter related functions
2110
1917
 
@@ -2135,7 +1942,7 @@ BookReader.prototype.updateFromParams = function(params) {
2135
1942
  }
2136
1943
  } else if ('undefined' != typeof(params.page)) {
2137
1944
  // $$$ this assumes page numbers are unique
2138
- if (params.page != this._models.book.getPageNum(this.currentIndex())) {
1945
+ if (params.page != this.book.getPageNum(this.currentIndex())) {
2139
1946
  this.jumpToPage(params.page);
2140
1947
  }
2141
1948
  }
@@ -2169,7 +1976,7 @@ BookReader.prototype.canSwitchToMode = function(mode) {
2169
1976
  // check there are enough pages to display
2170
1977
  // $$$ this is a workaround for the mis-feature that we can't display
2171
1978
  // short books in 2up mode
2172
- if (this._models.book.getNumLeafs() < 2) {
1979
+ if (this.book.getNumLeafs() < 2) {
2173
1980
  return false;
2174
1981
  }
2175
1982
  }
@@ -2177,31 +1984,6 @@ BookReader.prototype.canSwitchToMode = function(mode) {
2177
1984
  return true;
2178
1985
  };
2179
1986
 
2180
-
2181
- /**
2182
- * @deprecated. Use PageModel.getURISrcSet. Slated for removal in v5.
2183
- * Returns the srcset with correct URIs or void string if out of range
2184
- * Also makes the reduce argument optional
2185
- * @param {number} index
2186
- * @param {number} [reduce]
2187
- * @param {number} [rotate]
2188
- * @return {string}
2189
- */
2190
- BookReader.prototype._getPageURISrcset = function(index, reduce, rotate) {
2191
- const page = this._models.book.getPage(index, false);
2192
- // Synthesize page
2193
- if (!page) return "";
2194
-
2195
- // reduce not passed in
2196
- // $$$ this probably won't work for thumbnail mode
2197
- if ('undefined' == typeof(reduce)) {
2198
- reduce = page.height / this.twoPage.height;
2199
- }
2200
-
2201
- return page.getURISrcSet(reduce, rotate);
2202
- }
2203
-
2204
-
2205
1987
  /**
2206
1988
  * Returns the page URI or transparent image if out of range
2207
1989
  * Also makes the reduce argument optional
@@ -2211,7 +1993,7 @@ BookReader.prototype._getPageURISrcset = function(index, reduce, rotate) {
2211
1993
  * @return {string}
2212
1994
  */
2213
1995
  BookReader.prototype._getPageURI = function(index, reduce, rotate) {
2214
- const page = this._models.book.getPage(index, false);
1996
+ const page = this.book.getPage(index, false);
2215
1997
  // Synthesize page
2216
1998
  if (!page) return this.imagesBaseURL + "transparent.png";
2217
1999
 
@@ -2225,21 +2007,37 @@ BookReader.prototype._getPageURI = function(index, reduce, rotate) {
2225
2007
  };
2226
2008
 
2227
2009
  /**
2228
- * @param {string}
2010
+ * @param {string} msg
2011
+ * @param {function|undefined} onCloseCallback
2229
2012
  */
2230
- BookReader.prototype.showProgressPopup = function(msg) {
2013
+ BookReader.prototype.showProgressPopup = function(msg, onCloseCallback) {
2231
2014
  if (this.popup) return;
2232
2015
 
2233
2016
  this.popup = document.createElement("div");
2234
2017
  $(this.popup).prop('className', 'BRprogresspopup');
2235
- var bar = document.createElement("div");
2018
+
2019
+ if (typeof(onCloseCallback) === 'function') {
2020
+ const closeButton = document.createElement('button');
2021
+ closeButton.setAttribute('title', 'close');
2022
+ closeButton.setAttribute('class', 'close-popup');
2023
+ const icon = document.createElement('span');
2024
+ icon.setAttribute('class', 'icon icon-close-dark');
2025
+ $(closeButton).append(icon);
2026
+ closeButton.addEventListener('click', () => {
2027
+ onCloseCallback();
2028
+ this.removeProgressPopup();
2029
+ });
2030
+ $(this.popup).append(closeButton);
2031
+ }
2032
+
2033
+ const bar = document.createElement("div");
2236
2034
  $(bar).css({
2237
2035
  height: '20px'
2238
2036
  }).prop('className', 'BRprogressbar');
2239
2037
  $(this.popup).append(bar);
2240
2038
 
2241
2039
  if (msg) {
2242
- var msgdiv = document.createElement("div");
2040
+ const msgdiv = document.createElement("div");
2243
2041
  msgdiv.innerHTML = msg;
2244
2042
  $(this.popup).append(msgdiv);
2245
2043
  }
@@ -2261,7 +2059,7 @@ BookReader.prototype.initUIStrings = function() {
2261
2059
  // the toolbar and nav bar easier
2262
2060
 
2263
2061
  // Setup tooltips -- later we could load these from a file for i18n
2264
- var titles = {
2062
+ const titles = {
2265
2063
  '.logo': 'Go to Archive.org', // $$$ update after getting OL record
2266
2064
  '.zoom_in': 'Zoom in',
2267
2065
  '.zoom_out': 'Zoom out',
@@ -2293,10 +2091,10 @@ BookReader.prototype.initUIStrings = function() {
2293
2091
  titles['.book_rightmost'] = 'First page';
2294
2092
  }
2295
2093
 
2296
- for (var icon in titles) {
2094
+ for (const icon in titles) {
2297
2095
  this.$(icon).prop('title', titles[icon]);
2298
2096
  }
2299
- }
2097
+ };
2300
2098
 
2301
2099
  /**
2302
2100
  * Reloads images. Useful when some images might have failed.
@@ -2304,7 +2102,7 @@ BookReader.prototype.initUIStrings = function() {
2304
2102
  BookReader.prototype.reloadImages = function() {
2305
2103
  this.refs.$brContainer.find('img').each(function(index, elem) {
2306
2104
  if (!elem.complete || elem.naturalHeight === 0) {
2307
- var src = elem.src;
2105
+ const src = elem.src;
2308
2106
  elem.src = '';
2309
2107
  setTimeout(function() {
2310
2108
  elem.src = src;
@@ -2318,16 +2116,16 @@ BookReader.prototype.reloadImages = function() {
2318
2116
  * @return {number}
2319
2117
  */
2320
2118
  BookReader.prototype.getFooterHeight = function() {
2321
- var $heightEl = this.mode == this.constMode2up ? this.refs.$BRfooter : this.refs.$BRnav;
2119
+ const $heightEl = this.mode == this.constMode2up ? this.refs.$BRfooter : this.refs.$BRnav;
2322
2120
  if ($heightEl && this.refs.$BRfooter) {
2323
- var outerHeight = $heightEl.outerHeight();
2324
- var bottom = parseInt(this.refs.$BRfooter.css('bottom'));
2121
+ const outerHeight = $heightEl.outerHeight();
2122
+ const bottom = parseInt(this.refs.$BRfooter.css('bottom'));
2325
2123
  if (!isNaN(outerHeight) && !isNaN(bottom)) {
2326
2124
  return outerHeight + bottom;
2327
2125
  }
2328
2126
  }
2329
2127
  return 0;
2330
- }
2128
+ };
2331
2129
 
2332
2130
  // Basic Usage built-in Methods (can be overridden through options)
2333
2131
  // This implementation uses options.data value for populating BookReader
@@ -2337,10 +2135,11 @@ BookReader.prototype.getFooterHeight = function() {
2337
2135
  * @return {Object}
2338
2136
  */
2339
2137
  BookReader.prototype.paramsFromCurrent = function() {
2340
- var params = {};
2138
+ const params = {};
2341
2139
 
2342
- var index = this.currentIndex();
2343
- var pageNum = this._models.book.getPageNum(index);
2140
+ // Path params
2141
+ const index = this.currentIndex();
2142
+ const pageNum = this.book.getPageNum(index);
2344
2143
  if ((pageNum === 0) || pageNum) {
2345
2144
  params.page = pageNum;
2346
2145
  }
@@ -2348,10 +2147,17 @@ BookReader.prototype.paramsFromCurrent = function() {
2348
2147
  params.index = index;
2349
2148
  params.mode = this.mode;
2350
2149
 
2150
+ // Unused params
2351
2151
  // $$$ highlight
2352
2152
  // $$$ region
2353
2153
 
2354
- // search
2154
+ // Querystring params
2155
+ // View
2156
+ const fullscreenView = 'theater';
2157
+ if (this.isFullscreenActive) {
2158
+ params.view = fullscreenView;
2159
+ }
2160
+ // Search
2355
2161
  if (this.enableSearch) {
2356
2162
  params.search = this.searchTerm;
2357
2163
  }
@@ -2372,7 +2178,7 @@ BookReader.prototype.paramsFromCurrent = function() {
2372
2178
  * @return {Object}
2373
2179
  */
2374
2180
  BookReader.prototype.paramsFromFragment = function(fragment) {
2375
- var params = {};
2181
+ const params = {};
2376
2182
 
2377
2183
  // For backwards compatibility we allow an initial # character
2378
2184
  // (as from window.location.hash) but don't require it
@@ -2381,7 +2187,7 @@ BookReader.prototype.paramsFromFragment = function(fragment) {
2381
2187
  }
2382
2188
 
2383
2189
  // Simple #nn syntax
2384
- var oldStyleLeafNum = parseInt( /^\d+$/.exec(fragment) );
2190
+ const oldStyleLeafNum = parseInt( /^\d+$/.exec(fragment) );
2385
2191
  if ( !isNaN(oldStyleLeafNum) ) {
2386
2192
  params.index = oldStyleLeafNum;
2387
2193
 
@@ -2390,9 +2196,9 @@ BookReader.prototype.paramsFromFragment = function(fragment) {
2390
2196
  }
2391
2197
 
2392
2198
  // Split into key-value pairs
2393
- var urlArray = fragment.split('/');
2394
- var urlHash = {};
2395
- for (var i = 0; i < urlArray.length; i += 2) {
2199
+ const urlArray = fragment.split('/');
2200
+ const urlHash = {};
2201
+ for (let i = 0; i < urlArray.length; i += 2) {
2396
2202
  urlHash[urlArray[i]] = urlArray[i + 1];
2397
2203
  }
2398
2204
 
@@ -2422,7 +2228,7 @@ BookReader.prototype.paramsFromFragment = function(fragment) {
2422
2228
 
2423
2229
  // $$$ process /theme
2424
2230
  if (urlHash['theme'] != undefined) {
2425
- params.theme = urlHash['theme']
2231
+ params.theme = urlHash['theme'];
2426
2232
  }
2427
2233
  return params;
2428
2234
  };
@@ -2479,6 +2285,9 @@ BookReader.prototype.fragmentFromParams = function(params, urlMode = 'hash') {
2479
2285
  /**
2480
2286
  * Create, update querystring from the params object
2481
2287
  *
2288
+ * Handles:
2289
+ * view=
2290
+ * q=
2482
2291
  * @param {Object} params
2483
2292
  * @param {string} currQueryString
2484
2293
  * @param {string} [urlMode]
@@ -2490,27 +2299,29 @@ BookReader.prototype.queryStringFromParams = function(
2490
2299
  urlMode = 'hash'
2491
2300
  ) {
2492
2301
  const newParams = new URLSearchParams(currQueryString);
2302
+
2303
+ if (params.view) {
2304
+ // Set ?view=theater when fullscreen
2305
+ newParams.set('view', params.view);
2306
+ } else {
2307
+ // Remove
2308
+ newParams.delete('view');
2309
+ }
2310
+
2493
2311
  if (params.search && urlMode === 'history') {
2494
- newParams.set('q', params.search)
2312
+ newParams.set('q', params.search);
2495
2313
  }
2496
2314
  // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/toString
2497
2315
  // Note: This method returns the query string without the question mark.
2498
2316
  const result = newParams.toString();
2499
2317
  return result ? '?' + result : '';
2500
- }
2318
+ };
2501
2319
 
2502
2320
  /**
2503
2321
  * Helper to select within instance's elements
2504
2322
  */
2505
2323
  BookReader.prototype.$ = function(selector) {
2506
2324
  return this.refs.$br.find(selector);
2507
- }
2508
-
2509
- /**
2510
- * Polyfill for deprecated method
2511
- */
2512
- jQuery.curCSS = function(element, prop, val) {
2513
- return jQuery(element).css(prop, val);
2514
2325
  };
2515
2326
 
2516
2327
  window.BookReader = BookReader;