@internetarchive/bookreader 5.0.0-5 → 5.0.0-50-a1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) 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 +1 -1
  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/close-circle-dark.svg +1 -0
  13. package/BookReader/icons/magnify-minus.svg +1 -1
  14. package/BookReader/icons/magnify-plus.svg +1 -1
  15. package/BookReader/icons/pause.svg +1 -1
  16. package/BookReader/icons/playback-speed.svg +1 -1
  17. package/BookReader/icons/read-aloud.svg +1 -1
  18. package/BookReader/icons/voice.svg +1 -0
  19. package/BookReader/images/BRicons.svg +2 -2
  20. package/BookReader/images/books_graphic.svg +1 -1
  21. package/BookReader/images/icon_book.svg +1 -1
  22. package/BookReader/images/icon_gear.svg +1 -1
  23. package/BookReader/images/icon_info.svg +1 -1
  24. package/BookReader/images/icon_playback-rate.svg +1 -1
  25. package/BookReader/images/icon_search_button.svg +1 -1
  26. package/BookReader/images/icon_share.svg +1 -1
  27. package/BookReader/images/icon_speaker.svg +1 -1
  28. package/BookReader/images/icon_speaker_open.svg +1 -1
  29. package/BookReader/images/marker_chap-off.svg +1 -1
  30. package/BookReader/images/marker_chap-on.svg +1 -1
  31. package/BookReader/images/marker_srch-on.svg +1 -1
  32. package/BookReader/jquery-3.js +2 -0
  33. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  34. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  35. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  36. package/BookReader/plugins/plugin.autoplay.js +1 -1
  37. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  38. package/BookReader/plugins/plugin.chapters.js +1 -1
  39. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  40. package/BookReader/plugins/plugin.iframe.js +1 -1
  41. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  42. package/BookReader/plugins/plugin.mobile_nav.js +1 -1
  43. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
  44. package/BookReader/plugins/plugin.resume.js +1 -1
  45. package/BookReader/plugins/plugin.resume.js.map +1 -1
  46. package/BookReader/plugins/plugin.search.js +1 -1
  47. package/BookReader/plugins/plugin.search.js.map +1 -1
  48. package/BookReader/plugins/plugin.text_selection.js +1 -1
  49. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  50. package/BookReader/plugins/plugin.tts.js +1 -1
  51. package/BookReader/plugins/plugin.tts.js.map +1 -1
  52. package/BookReader/plugins/plugin.url.js +1 -1
  53. package/BookReader/plugins/plugin.url.js.map +1 -1
  54. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  55. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  56. package/BookReader/webcomponents-bundle.js +3 -0
  57. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  58. package/BookReader/webcomponents-bundle.js.map +1 -0
  59. package/BookReaderDemo/BookReaderDemo.css +14 -1
  60. package/BookReaderDemo/IADemoBr.js +148 -0
  61. package/BookReaderDemo/demo-advanced.html +2 -2
  62. package/BookReaderDemo/demo-autoplay.html +2 -1
  63. package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
  64. package/BookReaderDemo/demo-fullscreen-mobile.html +2 -1
  65. package/BookReaderDemo/demo-fullscreen.html +2 -1
  66. package/BookReaderDemo/demo-iiif.html +2 -1
  67. package/BookReaderDemo/demo-internetarchive.html +84 -17
  68. package/BookReaderDemo/demo-multiple.html +2 -1
  69. package/BookReaderDemo/demo-preview-pages.html +2 -1
  70. package/BookReaderDemo/demo-simple.html +2 -1
  71. package/BookReaderDemo/demo-vendor-fullscreen.html +2 -1
  72. package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
  73. package/BookReaderDemo/immersion-1up.html +2 -1
  74. package/BookReaderDemo/immersion-mode.html +2 -1
  75. package/BookReaderDemo/toggle_controls.html +2 -1
  76. package/BookReaderDemo/view_mode.html +2 -1
  77. package/BookReaderDemo/viewmode-cycle.html +2 -3
  78. package/CHANGELOG.md +202 -0
  79. package/README.md +14 -1
  80. package/babel.config.js +18 -0
  81. package/codecov.yml +6 -0
  82. package/index.html +3 -0
  83. package/jsconfig.json +19 -0
  84. package/package.json +66 -56
  85. package/renovate.json +52 -0
  86. package/scripts/preversion.js +4 -1
  87. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  88. package/src/BookNavigator/assets/button-base.js +9 -2
  89. package/src/BookNavigator/assets/ia-logo.js +17 -0
  90. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  91. package/src/BookNavigator/assets/icon_close.js +1 -1
  92. package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
  93. package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
  94. package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
  95. package/src/BookNavigator/assets/icon_volumes.js +11 -0
  96. package/src/BookNavigator/book-navigator.js +583 -0
  97. package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
  98. package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
  99. package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
  100. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
  101. package/src/BookNavigator/bookmarks/bookmarks-provider.js +21 -8
  102. package/src/BookNavigator/bookmarks/ia-bookmarks.js +102 -66
  103. package/src/BookNavigator/delete-modal-actions.js +1 -1
  104. package/src/BookNavigator/downloads/downloads-provider.js +36 -21
  105. package/src/BookNavigator/downloads/downloads.js +41 -25
  106. package/src/BookNavigator/search/a-search-result.js +18 -13
  107. package/src/BookNavigator/search/search-provider.js +80 -28
  108. package/src/BookNavigator/search/search-results.js +10 -18
  109. package/src/BookNavigator/sharing.js +27 -0
  110. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
  111. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
  112. package/src/BookNavigator/volumes/volumes-provider.js +114 -0
  113. package/src/BookNavigator/volumes/volumes.js +188 -0
  114. package/src/BookReader/BookModel.js +0 -29
  115. package/src/BookReader/DebugConsole.js +3 -3
  116. package/src/BookReader/DragScrollable.js +233 -0
  117. package/src/BookReader/Mode1Up.js +51 -351
  118. package/src/BookReader/Mode1UpLit.js +441 -0
  119. package/src/BookReader/Mode2Up.js +120 -105
  120. package/src/BookReader/ModeSmoothZoom.js +179 -0
  121. package/src/BookReader/ModeThumb.js +17 -11
  122. package/src/BookReader/Navbar/Navbar.js +10 -36
  123. package/src/BookReader/PageContainer.js +69 -6
  124. package/src/BookReader/ReduceSet.js +1 -1
  125. package/src/BookReader/Toolbar/Toolbar.js +10 -37
  126. package/src/BookReader/options.js +10 -0
  127. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  128. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  129. package/src/BookReader/utils.js +92 -13
  130. package/src/BookReader.js +431 -620
  131. package/src/assets/icons/close-circle-dark.svg +1 -0
  132. package/src/assets/icons/magnify-minus.svg +3 -7
  133. package/src/assets/icons/magnify-plus.svg +3 -7
  134. package/src/assets/icons/voice.svg +1 -0
  135. package/src/css/BookReader.scss +0 -12
  136. package/src/css/_BRComponent.scss +1 -1
  137. package/src/css/_BRmain.scss +19 -24
  138. package/src/css/_BRnav.scss +4 -26
  139. package/src/css/_BRpages.scss +35 -0
  140. package/src/css/_BRsearch.scss +25 -216
  141. package/src/css/_TextSelection.scss +14 -17
  142. package/src/css/_colorbox.scss +2 -2
  143. package/src/css/_controls.scss +17 -5
  144. package/src/css/_icons.scss +6 -0
  145. package/src/ia-bookreader/ia-bookreader.js +224 -0
  146. package/src/plugins/plugin.autoplay.js +4 -4
  147. package/src/plugins/plugin.chapters.js +28 -35
  148. package/src/plugins/plugin.mobile_nav.js +11 -10
  149. package/src/plugins/plugin.resume.js +3 -3
  150. package/src/plugins/plugin.text_selection.js +26 -39
  151. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  152. package/src/plugins/search/plugin.search.js +174 -116
  153. package/src/plugins/search/view.js +63 -179
  154. package/src/plugins/tts/AbstractTTSEngine.js +46 -37
  155. package/src/plugins/tts/FestivalTTSEngine.js +13 -14
  156. package/src/plugins/tts/PageChunk.js +15 -21
  157. package/src/plugins/tts/PageChunkIterator.js +8 -12
  158. package/src/plugins/tts/WebTTSEngine.js +66 -69
  159. package/src/plugins/tts/plugin.tts.js +92 -109
  160. package/src/plugins/tts/utils.js +0 -9
  161. package/src/plugins/url/UrlPlugin.js +184 -0
  162. package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
  163. package/src/util/manifestGenerator.js +0 -0
  164. package/tests/e2e/README.md +37 -0
  165. package/tests/e2e/autoplay.test.js +2 -2
  166. package/tests/e2e/base.test.js +7 -7
  167. package/tests/e2e/helpers/base.js +9 -3
  168. package/tests/e2e/helpers/debug.js +1 -1
  169. package/tests/e2e/helpers/desktopSearch.js +14 -13
  170. package/tests/e2e/helpers/mobileSearch.js +3 -3
  171. package/tests/e2e/helpers/params.js +17 -0
  172. package/tests/e2e/models/Navigation.js +13 -4
  173. package/tests/e2e/rightToLeft.test.js +4 -5
  174. package/tests/e2e/viewmode.test.js +38 -33
  175. package/tests/jest/BookNavigator/book-navigator.test.js +634 -0
  176. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
  177. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  178. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  179. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  180. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
  181. package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
  182. package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
  183. package/tests/{karma/BookNavigator → jest/BookNavigator/search}/search-results.test.js +102 -58
  184. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
  185. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  186. package/tests/jest/BookNavigator/volumes/volumes-provider.test.js +184 -0
  187. package/tests/jest/BookNavigator/volumes/volumes.test.js +97 -0
  188. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +34 -14
  189. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
  190. package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
  191. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  192. package/tests/jest/BookReader/Mode1UpLit.test.js +92 -0
  193. package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +36 -15
  194. package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
  195. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  196. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
  197. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
  198. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  199. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  200. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  201. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  202. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  203. package/tests/jest/BookReader/utils.test.js +186 -0
  204. package/tests/jest/BookReader.keyboard.test.js +190 -0
  205. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  206. package/tests/{BookReader.test.js → jest/BookReader.test.js} +18 -37
  207. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  208. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
  209. package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +10 -11
  210. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  211. package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
  212. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  213. package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
  214. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  215. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +63 -47
  216. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +35 -6
  217. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +9 -9
  218. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  219. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  220. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  221. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +1 -1
  222. package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -28
  223. package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
  224. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
  225. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  226. package/tests/{util → jest/util}/docCookies.test.js +1 -1
  227. package/tests/{util → jest/util}/strings.test.js +1 -1
  228. package/tests/{utils.js → jest/utils.js} +38 -0
  229. package/webpack.config.js +11 -5
  230. package/.babelrc +0 -12
  231. package/.dependabot/config.yml +0 -6
  232. package/.testcaferc.json +0 -5
  233. package/BookReader/bookreader-component-bundle.js +0 -1450
  234. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  235. package/BookReader/bookreader-component-bundle.js.map +0 -1
  236. package/BookReader/jquery-1.10.1.js +0 -2
  237. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  238. package/BookReader/plugins/plugin.menu_toggle.js +0 -2
  239. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  240. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  241. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  242. package/karma.conf.js +0 -23
  243. package/src/BookNavigator/BookModel.js +0 -14
  244. package/src/BookNavigator/BookNavigator.js +0 -438
  245. package/src/BookNavigator/assets/book-loader.js +0 -27
  246. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  247. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  248. package/src/ItemNavigator/ItemNavigator.js +0 -372
  249. package/src/ItemNavigator/providers/sharing.js +0 -29
  250. package/src/Layers/sharing/sharing-provider.js +0 -22
  251. package/src/dragscrollable-br.js +0 -261
  252. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  253. package/src/plugins/plugin.bookmarks.js +0 -50
  254. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  255. package/tests/BookReader/Mode1Up.test.js +0 -164
  256. package/tests/BookReader/utils.test.js +0 -109
  257. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  258. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  259. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  260. 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;