@internetarchive/bookreader 5.0.0-94 → 5.0.0-95

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