@internetarchive/bookreader 5.0.0-93 → 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 (224) hide show
  1. package/.github/workflows/npm-publish.yml +2 -12
  2. package/BookReaderDemo/IADemoBr.js +1 -24
  3. package/BookReaderDemo/demo-internetarchive.html +1 -0
  4. package/CHANGELOG.md +19 -1
  5. package/README.md +0 -2
  6. package/package.json +8 -4
  7. package/scripts/postversion.js +3 -2
  8. package/scripts/preversion.js +3 -1
  9. package/scripts/version.js +4 -6
  10. package/src/BookNavigator/book-navigator.js +38 -12
  11. package/src/BookNavigator/downloads/downloads-provider.js +2 -2
  12. package/src/BookNavigator/search/search-provider.js +5 -5
  13. package/src/BookNavigator/search/search-results.js +1 -1
  14. package/src/BookNavigator/sharing.js +2 -2
  15. package/src/BookNavigator/viewable-files.js +2 -2
  16. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +3 -3
  17. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +2 -2
  18. package/src/BookReader.js +57 -31
  19. package/src/assets/images/hypothesis.ico +0 -0
  20. package/src/css/_TextSelection.scss +3 -1
  21. package/src/plugins/plugin.autoplay.js +3 -3
  22. package/src/plugins/plugin.chapters.js +2 -2
  23. package/src/plugins/plugin.experiments.js +294 -0
  24. package/src/plugins/plugin.iiif.js +1 -1
  25. package/src/plugins/plugin.text_selection.js +112 -1
  26. package/src/plugins/search/view.js +5 -5
  27. package/src/plugins/tts/plugin.tts.js +3 -3
  28. package/src/plugins/url/plugin.url.js +2 -2
  29. package/tests/e2e/autoplay.test.js +1 -1
  30. package/tests/e2e/base.test.js +4 -4
  31. package/tests/e2e/helpers/base.js +2 -2
  32. package/tests/e2e/models/BookReader.js +1 -1
  33. package/tests/e2e/rightToLeft.test.js +4 -4
  34. package/tests/e2e/viewmode.test.js +2 -2
  35. package/tests/jest/BookNavigator/book-navigator.test.js +0 -13
  36. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +1 -1
  37. package/tests/jest/BookNavigator/downloads/downloads.test.js +1 -1
  38. package/tests/jest/BookNavigator/search/search-provider.test.js +5 -5
  39. package/tests/jest/BookReader.test.js +10 -10
  40. package/tests/jest/plugins/plugin.autoplay.test.js +6 -6
  41. package/tests/jest/plugins/plugin.chapters.test.js +2 -2
  42. package/tests/jest/plugins/plugin.resume.test.js +13 -13
  43. package/tests/jest/plugins/plugin.text_selection.test.js +155 -24
  44. package/tests/jest/plugins/search/plugin.search.test.js +7 -7
  45. package/tests/jest/plugins/search/plugin.search.view.test.js +8 -8
  46. package/tests/jest/plugins/search/utils.js +1 -1
  47. package/tests/jest/plugins/tts/PageChunkIterator.test.js +2 -2
  48. package/tests/jest/plugins/url/UrlPlugin.test.js +1 -1
  49. package/webpack.config.js +8 -3
  50. package/BookReader/BookReader.css +0 -2250
  51. package/BookReader/BookReader.js +0 -3
  52. package/BookReader/BookReader.js.LICENSE.txt +0 -72
  53. package/BookReader/BookReader.js.map +0 -1
  54. package/BookReader/ia-bookreader-bundle.js +0 -1782
  55. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +0 -7
  56. package/BookReader/ia-bookreader-bundle.js.map +0 -1
  57. package/BookReader/icons/1up.svg +0 -1
  58. package/BookReader/icons/2up.svg +0 -1
  59. package/BookReader/icons/advance.svg +0 -3
  60. package/BookReader/icons/chevron-right.svg +0 -1
  61. package/BookReader/icons/close-circle-dark.svg +0 -1
  62. package/BookReader/icons/close-circle.svg +0 -1
  63. package/BookReader/icons/fullscreen.svg +0 -1
  64. package/BookReader/icons/fullscreen_exit.svg +0 -1
  65. package/BookReader/icons/hamburger.svg +0 -1
  66. package/BookReader/icons/left-arrow.svg +0 -1
  67. package/BookReader/icons/magnify-minus.svg +0 -1
  68. package/BookReader/icons/magnify-plus.svg +0 -1
  69. package/BookReader/icons/magnify.svg +0 -1
  70. package/BookReader/icons/pause.svg +0 -1
  71. package/BookReader/icons/play.svg +0 -1
  72. package/BookReader/icons/playback-speed.svg +0 -1
  73. package/BookReader/icons/read-aloud.svg +0 -1
  74. package/BookReader/icons/review.svg +0 -3
  75. package/BookReader/icons/thumbnails.svg +0 -1
  76. package/BookReader/icons/voice.svg +0 -1
  77. package/BookReader/icons/volume-full.svg +0 -1
  78. package/BookReader/images/BRicons.png +0 -0
  79. package/BookReader/images/BRicons.svg +0 -5
  80. package/BookReader/images/BRicons_ia.png +0 -0
  81. package/BookReader/images/back_pages.png +0 -0
  82. package/BookReader/images/book_bottom_icon.png +0 -0
  83. package/BookReader/images/book_down_icon.png +0 -0
  84. package/BookReader/images/book_left_icon.png +0 -0
  85. package/BookReader/images/book_leftmost_icon.png +0 -0
  86. package/BookReader/images/book_right_icon.png +0 -0
  87. package/BookReader/images/book_rightmost_icon.png +0 -0
  88. package/BookReader/images/book_top_icon.png +0 -0
  89. package/BookReader/images/book_up_icon.png +0 -0
  90. package/BookReader/images/books_graphic.svg +0 -1
  91. package/BookReader/images/booksplit.png +0 -0
  92. package/BookReader/images/control_pause_icon.png +0 -0
  93. package/BookReader/images/control_play_icon.png +0 -0
  94. package/BookReader/images/embed_icon.png +0 -0
  95. package/BookReader/images/icon-home-ia.png +0 -0
  96. package/BookReader/images/icon_OL-logo-xs.png +0 -0
  97. package/BookReader/images/icon_alert-xs.png +0 -0
  98. package/BookReader/images/icon_book.svg +0 -1
  99. package/BookReader/images/icon_bookmark.svg +0 -1
  100. package/BookReader/images/icon_close-pop.png +0 -0
  101. package/BookReader/images/icon_download.png +0 -0
  102. package/BookReader/images/icon_gear.svg +0 -1
  103. package/BookReader/images/icon_hamburger.svg +0 -1
  104. package/BookReader/images/icon_home.png +0 -0
  105. package/BookReader/images/icon_home.svg +0 -1
  106. package/BookReader/images/icon_home_ia.png +0 -0
  107. package/BookReader/images/icon_indicator.png +0 -0
  108. package/BookReader/images/icon_info.svg +0 -1
  109. package/BookReader/images/icon_one_page.svg +0 -1
  110. package/BookReader/images/icon_pause.svg +0 -1
  111. package/BookReader/images/icon_play.svg +0 -1
  112. package/BookReader/images/icon_playback-rate.svg +0 -1
  113. package/BookReader/images/icon_return.png +0 -0
  114. package/BookReader/images/icon_search_button.svg +0 -1
  115. package/BookReader/images/icon_share.svg +0 -1
  116. package/BookReader/images/icon_skip-ahead.svg +0 -1
  117. package/BookReader/images/icon_skip-back.svg +0 -2
  118. package/BookReader/images/icon_speaker.svg +0 -1
  119. package/BookReader/images/icon_speaker_open.svg +0 -1
  120. package/BookReader/images/icon_thumbnails.svg +0 -1
  121. package/BookReader/images/icon_toc.svg +0 -1
  122. package/BookReader/images/icon_two_pages.svg +0 -1
  123. package/BookReader/images/icon_zoomer.png +0 -0
  124. package/BookReader/images/loading.gif +0 -0
  125. package/BookReader/images/logo_icon.png +0 -0
  126. package/BookReader/images/marker_chap-off.png +0 -0
  127. package/BookReader/images/marker_chap-off.svg +0 -1
  128. package/BookReader/images/marker_chap-off_ia.png +0 -0
  129. package/BookReader/images/marker_chap-on.png +0 -0
  130. package/BookReader/images/marker_chap-on.svg +0 -1
  131. package/BookReader/images/marker_srch-on.svg +0 -1
  132. package/BookReader/images/marker_srchchap-off.png +0 -0
  133. package/BookReader/images/marker_srchchap-on.png +0 -0
  134. package/BookReader/images/nav_control-dn.png +0 -0
  135. package/BookReader/images/nav_control-dn_ia.png +0 -0
  136. package/BookReader/images/nav_control-up.png +0 -0
  137. package/BookReader/images/nav_control-up_ia.png +0 -0
  138. package/BookReader/images/nav_control.png +0 -0
  139. package/BookReader/images/one_page_mode_icon.png +0 -0
  140. package/BookReader/images/paper-badge.png +0 -0
  141. package/BookReader/images/print_icon.png +0 -0
  142. package/BookReader/images/progressbar.gif +0 -0
  143. package/BookReader/images/right_edges.png +0 -0
  144. package/BookReader/images/slider.png +0 -0
  145. package/BookReader/images/slider_ia.png +0 -0
  146. package/BookReader/images/thumbnail_mode_icon.png +0 -0
  147. package/BookReader/images/transparent.png +0 -0
  148. package/BookReader/images/two_page_mode_icon.png +0 -0
  149. package/BookReader/images/unviewable_page.png +0 -0
  150. package/BookReader/images/zoom_in_icon.png +0 -0
  151. package/BookReader/images/zoom_out_icon.png +0 -0
  152. package/BookReader/jquery-3.js +0 -2
  153. package/BookReader/jquery-3.js.LICENSE.txt +0 -24
  154. package/BookReader/plugins/plugin.archive_analytics.js +0 -2
  155. package/BookReader/plugins/plugin.archive_analytics.js.map +0 -1
  156. package/BookReader/plugins/plugin.autoplay.js +0 -2
  157. package/BookReader/plugins/plugin.autoplay.js.map +0 -1
  158. package/BookReader/plugins/plugin.chapters.js +0 -26
  159. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +0 -1
  160. package/BookReader/plugins/plugin.chapters.js.map +0 -1
  161. package/BookReader/plugins/plugin.iframe.js +0 -2
  162. package/BookReader/plugins/plugin.iframe.js.map +0 -1
  163. package/BookReader/plugins/plugin.iiif.js +0 -2
  164. package/BookReader/plugins/plugin.iiif.js.map +0 -1
  165. package/BookReader/plugins/plugin.resume.js +0 -2
  166. package/BookReader/plugins/plugin.resume.js.map +0 -1
  167. package/BookReader/plugins/plugin.search.js +0 -3
  168. package/BookReader/plugins/plugin.search.js.LICENSE.txt +0 -1
  169. package/BookReader/plugins/plugin.search.js.map +0 -1
  170. package/BookReader/plugins/plugin.text_selection.js +0 -3
  171. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +0 -1
  172. package/BookReader/plugins/plugin.text_selection.js.map +0 -1
  173. package/BookReader/plugins/plugin.tts.js +0 -3
  174. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +0 -29
  175. package/BookReader/plugins/plugin.tts.js.map +0 -1
  176. package/BookReader/plugins/plugin.url.js +0 -2
  177. package/BookReader/plugins/plugin.url.js.map +0 -1
  178. package/BookReader/plugins/plugin.vendor-fullscreen.js +0 -2
  179. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +0 -1
  180. package/BookReader/webcomponents-bundle.js +0 -3
  181. package/BookReader/webcomponents-bundle.js.LICENSE.txt +0 -9
  182. package/BookReader/webcomponents-bundle.js.map +0 -1
  183. package/src/BookReader/BookModel.js +0 -554
  184. package/src/BookReader/DragScrollable.js +0 -233
  185. package/src/BookReader/ImageCache.js +0 -149
  186. package/src/BookReader/Mode1Up.js +0 -108
  187. package/src/BookReader/Mode1UpLit.js +0 -388
  188. package/src/BookReader/Mode2Up.js +0 -105
  189. package/src/BookReader/Mode2UpLit.js +0 -777
  190. package/src/BookReader/ModeCoordinateSpace.js +0 -29
  191. package/src/BookReader/ModeSmoothZoom.js +0 -312
  192. package/src/BookReader/ModeThumb.js +0 -342
  193. package/src/BookReader/Navbar/Navbar.js +0 -355
  194. package/src/BookReader/PageContainer.js +0 -169
  195. package/src/BookReader/ReduceSet.js +0 -26
  196. package/src/BookReader/Toolbar/Toolbar.js +0 -362
  197. package/src/BookReader/events.js +0 -19
  198. package/src/BookReader/options.js +0 -382
  199. package/src/BookReader/utils/HTMLDimensionsCacher.js +0 -44
  200. package/src/BookReader/utils/ScrollClassAdder.js +0 -31
  201. package/src/BookReader/utils/SelectionObserver.js +0 -45
  202. package/src/BookReader/utils/classes.js +0 -36
  203. package/src/BookReader/utils.js +0 -300
  204. package/tests/jest/BookReader/BookModel.test.js +0 -372
  205. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +0 -263
  206. package/tests/jest/BookReader/ImageCache.test.js +0 -150
  207. package/tests/jest/BookReader/Mode1UpLit.test.js +0 -73
  208. package/tests/jest/BookReader/Mode2Up.test.js +0 -98
  209. package/tests/jest/BookReader/Mode2UpLit.test.js +0 -190
  210. package/tests/jest/BookReader/ModeCoordinateSpace.test.js +0 -16
  211. package/tests/jest/BookReader/ModeSmoothZoom.test.js +0 -218
  212. package/tests/jest/BookReader/ModeThumb.test.js +0 -71
  213. package/tests/jest/BookReader/Navbar/Navbar.test.js +0 -182
  214. package/tests/jest/BookReader/PageContainer.test.js +0 -238
  215. package/tests/jest/BookReader/ReduceSet.test.js +0 -38
  216. package/tests/jest/BookReader/Toolbar/Toolbar.test.js +0 -26
  217. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +0 -59
  218. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +0 -49
  219. package/tests/jest/BookReader/utils/SelectionObserver.test.js +0 -57
  220. package/tests/jest/BookReader/utils/classes.test.js +0 -88
  221. package/tests/jest/BookReader/utils.test.js +0 -250
  222. /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
  223. /package/{.testcaferc.js → .testcaferc.cjs} +0 -0
  224. /package/{babel.config.js → babel.config.cjs} +0 -0
@@ -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,169 +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
- }).attr('data-side', page?.pageSide);
22
-
23
- if (isProtected) {
24
- this.$container.append($('<div class="BRscreen" />'));
25
- this.$container.addClass('protected');
26
- }
27
-
28
- /** @type {JQuery<HTMLImageElement>} The main book page image */
29
- this.$img = null;
30
- }
31
-
32
- /**
33
- * @param {object} param0
34
- * @param {{ width: number, height: number, top: number, left: number }} [param0.dimensions]
35
- * @param {number} param0.reduce
36
- */
37
- update({dimensions = null, reduce = null}) {
38
- if (dimensions) {
39
- this.$container.css(dimensions);
40
- }
41
-
42
- if (reduce == null || !this.page) {
43
- return;
44
- }
45
-
46
- const finalReduce = this.imageCache.getFinalReduce(this.page.index, reduce);
47
- const newImageURI = this.page.getURI(finalReduce, 0);
48
-
49
- // Note: These must be computed _before_ we call .image()
50
- const alreadyLoaded = this.imageCache.imageLoaded(this.page.index, finalReduce);
51
- const nextBestLoadedReduce = this.imageCache.getBestLoadedReduce(this.page.index, reduce);
52
-
53
- // Avoid removing/re-adding the image if it's already there
54
- // This can be called quite a bit, so we need to be fast
55
- if (this.$img?.data('src') == newImageURI) {
56
- return this;
57
- }
58
-
59
- let $oldImg = this.$img;
60
- this.$img = this.imageCache.image(this.page.index, finalReduce);
61
- if ($oldImg) {
62
- this.$img.insertAfter($oldImg);
63
- } else {
64
- this.$img.prependTo(this.$container);
65
- }
66
-
67
- if (!alreadyLoaded) {
68
- this.$container.addClass('BRpageloading');
69
- }
70
-
71
- if (!alreadyLoaded && nextBestLoadedReduce) {
72
- // If we have a slightly lower quality image loaded, use that as the background
73
- // while the higher res one loads
74
- const nextBestUri = this.page.getURI(nextBestLoadedReduce, 0);
75
- if ($oldImg) {
76
- if ($oldImg.data('src') == nextBestUri) {
77
- // Do nothing! It's already showing the right thing
78
- } else {
79
- // We have a different src, need to update the src
80
- this.imageCache.image(this.page.index, nextBestLoadedReduce, $oldImg[0]);
81
- }
82
- } else {
83
- // We don't have an old <img>, so we need to create a new one
84
- $oldImg = this.imageCache.image(this.page.index, nextBestLoadedReduce);
85
- $oldImg.prependTo(this.$container);
86
- }
87
- }
88
-
89
- this.$img
90
- .one('load', async (ev) => {
91
- this.$container.removeClass('BRpageloading');
92
- // `load` can fire a little early, so wait a spell before removing the old image
93
- // to avoid flicker
94
- await sleep(100);
95
- $oldImg?.remove();
96
- });
97
-
98
- return this;
99
- }
100
- }
101
-
102
-
103
- /**
104
- * @param {PageModel} page
105
- * @param {string} className
106
- */
107
- export function createSVGPageLayer(page, className) {
108
- const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
109
- svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
110
- svg.setAttribute("viewBox", `0 0 ${page.width} ${page.height}`);
111
- svg.setAttribute('class', `BRPageLayer ${className}`);
112
- svg.setAttribute('preserveAspectRatio', 'none');
113
- return svg;
114
- }
115
-
116
- /**
117
- * @param {PageModel} page
118
- * @param {string} className
119
- */
120
- export function createDIVPageLayer(page, className) {
121
- const div = document.createElement("div");
122
- div.style.width = `${page.width}px`;
123
- div.style.height = `${page.height}px`;
124
- div.setAttribute('class', `BRPageLayer ${className}`);
125
- return div;
126
- }
127
-
128
- /**
129
- * @param {{ l: number, r: number, b: number, t: number }} box
130
- */
131
- export function boxToSVGRect({ l: left, r: right, b: bottom, t: top }) {
132
- const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
133
- rect.setAttribute("x", left.toString());
134
- rect.setAttribute("y", top.toString());
135
- rect.setAttribute("width", (right - left).toString());
136
- rect.setAttribute("height", (bottom - top).toString());
137
-
138
- // Some style; corner radius 4px. Can't set this in CSS yet
139
- rect.setAttribute("rx", "4");
140
- rect.setAttribute("ry", "4");
141
- return rect;
142
- }
143
-
144
- /**
145
- * @param {string} layerClass
146
- * @param {Array<{ l: number, r: number, b: number, t: number }>} boxes
147
- * @param {PageModel} page
148
- * @param {HTMLElement} containerEl
149
- * @param {string[]} [rectClasses] CSS classes to add to the rects
150
- */
151
- export function renderBoxesInPageContainerLayer(layerClass, boxes, page, containerEl, rectClasses = null) {
152
- const mountedSvg = containerEl.querySelector(`.${layerClass}`);
153
- // Create the layer if it's not there
154
- const svg = mountedSvg || createSVGPageLayer(page, layerClass);
155
- if (!mountedSvg) {
156
- // Insert after the image if the image is already loaded.
157
- const imgEl = containerEl.querySelector('.BRpageimage');
158
- if (imgEl) $(svg).insertAfter(imgEl);
159
- else $(svg).prependTo(containerEl);
160
- }
161
-
162
- for (const [i, box] of boxes.entries()) {
163
- const rect = boxToSVGRect(box);
164
- if (rectClasses) {
165
- rect.setAttribute('class', rectClasses[i]);
166
- }
167
- svg.appendChild(rect);
168
- }
169
- }
@@ -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
- };