@internetarchive/bookreader 5.0.0-38 → 5.0.0-39

Sign up to get free protection for your applications and to get access to all the features.
Files changed (222) hide show
  1. package/BookReader/BookReader.css +8 -0
  2. package/BookReader/BookReader.js +1 -1
  3. package/BookReader/BookReader.js.map +1 -1
  4. package/BookReader/ia-bookreader-bundle.js +99 -75
  5. package/BookReader/ia-bookreader-bundle.js.map +1 -1
  6. package/BookReader/icons/magnify-minus.svg +1 -1
  7. package/BookReader/icons/magnify-plus.svg +1 -1
  8. package/BookReader/plugins/plugin.autoplay.js +1 -1
  9. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  10. package/BookReader/plugins/plugin.chapters.js +1 -1
  11. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  12. package/BookReader/plugins/plugin.mobile_nav.js +1 -1
  13. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
  14. package/BookReader/plugins/plugin.resume.js +1 -1
  15. package/BookReader/plugins/plugin.resume.js.map +1 -1
  16. package/BookReader/plugins/plugin.search.js +1 -1
  17. package/BookReader/plugins/plugin.search.js.map +1 -1
  18. package/BookReader/plugins/plugin.text_selection.js +1 -1
  19. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  20. package/BookReader/plugins/plugin.tts.js +1 -1
  21. package/BookReader/plugins/plugin.tts.js.map +1 -1
  22. package/BookReader/plugins/plugin.url.js +1 -1
  23. package/BookReader/plugins/plugin.url.js.map +1 -1
  24. package/CHANGELOG.md +5 -0
  25. package/README.md +13 -0
  26. package/package.json +14 -14
  27. package/renovate.json +1 -1
  28. package/src/BookReader/Mode1UpLit.js +7 -1
  29. package/src/BookReader/Mode2Up.js +11 -0
  30. package/src/BookReader/ModeSmoothZoom.js +2 -0
  31. package/src/BookReader/PageContainer.js +10 -4
  32. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  33. package/src/assets/icons/magnify-minus.svg +3 -7
  34. package/src/assets/icons/magnify-plus.svg +3 -7
  35. package/src/css/_TextSelection.scss +13 -0
  36. package/tests/jest/BookReader/PageContainer.test.js +5 -4
  37. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  38. package/.husky/_/husky.sh +0 -30
  39. package/stat/BookNavigator/BookModel.js +0 -14
  40. package/stat/BookNavigator/BookNavigator.js +0 -524
  41. package/stat/BookNavigator/assets/bookmark-colors.js +0 -15
  42. package/stat/BookNavigator/assets/button-base.js +0 -61
  43. package/stat/BookNavigator/assets/ia-logo.js +0 -17
  44. package/stat/BookNavigator/assets/icon_checkmark.js +0 -6
  45. package/stat/BookNavigator/assets/icon_close.js +0 -3
  46. package/stat/BookNavigator/assets/icon_sort_asc.js +0 -5
  47. package/stat/BookNavigator/assets/icon_sort_desc.js +0 -5
  48. package/stat/BookNavigator/assets/icon_sort_neutral.js +0 -5
  49. package/stat/BookNavigator/assets/icon_volumes.js +0 -11
  50. package/stat/BookNavigator/bookmarks/bookmark-button.js +0 -64
  51. package/stat/BookNavigator/bookmarks/bookmark-edit.js +0 -215
  52. package/stat/BookNavigator/bookmarks/bookmarks-list.js +0 -285
  53. package/stat/BookNavigator/bookmarks/bookmarks-loginCTA.js +0 -28
  54. package/stat/BookNavigator/bookmarks/bookmarks-provider.js +0 -56
  55. package/stat/BookNavigator/bookmarks/ia-bookmarks.js +0 -523
  56. package/stat/BookNavigator/br-fullscreen-mgr.js +0 -82
  57. package/stat/BookNavigator/delete-modal-actions.js +0 -49
  58. package/stat/BookNavigator/downloads/downloads-provider.js +0 -72
  59. package/stat/BookNavigator/downloads/downloads.js +0 -139
  60. package/stat/BookNavigator/provider-config.js +0 -0
  61. package/stat/BookNavigator/search/a-search-result.js +0 -55
  62. package/stat/BookNavigator/search/search-provider.js +0 -180
  63. package/stat/BookNavigator/search/search-results.js +0 -360
  64. package/stat/BookNavigator/sharing.js +0 -31
  65. package/stat/BookNavigator/visual-adjustments/visual-adjustments-provider.js +0 -94
  66. package/stat/BookNavigator/visual-adjustments/visual-adjustments.js +0 -280
  67. package/stat/BookNavigator/volumes/volumes-provider.js +0 -83
  68. package/stat/BookNavigator/volumes/volumes.js +0 -178
  69. package/stat/BookReader/BookModel.js +0 -518
  70. package/stat/BookReader/DebugConsole.js +0 -54
  71. package/stat/BookReader/DragScrollable.js +0 -233
  72. package/stat/BookReader/ImageCache.js +0 -116
  73. package/stat/BookReader/Mode1Up.js +0 -102
  74. package/stat/BookReader/Mode1UpLit.js +0 -434
  75. package/stat/BookReader/Mode2Up.js +0 -1372
  76. package/stat/BookReader/ModeSmoothZoom.js +0 -177
  77. package/stat/BookReader/ModeThumb.js +0 -344
  78. package/stat/BookReader/Navbar/Navbar.js +0 -310
  79. package/stat/BookReader/PageContainer.js +0 -120
  80. package/stat/BookReader/ReduceSet.js +0 -26
  81. package/stat/BookReader/Toolbar/Toolbar.js +0 -384
  82. package/stat/BookReader/events.js +0 -20
  83. package/stat/BookReader/options.js +0 -324
  84. package/stat/BookReader/utils/HTMLDimensionsCacher.js +0 -44
  85. package/stat/BookReader/utils/classes.js +0 -36
  86. package/stat/BookReader/utils.js +0 -240
  87. package/stat/BookReader.js +0 -2550
  88. package/stat/BookReaderComponent/BookReaderComponent.js +0 -117
  89. package/stat/assets/icons/1up.svg +0 -12
  90. package/stat/assets/icons/2up.svg +0 -15
  91. package/stat/assets/icons/advance.svg +0 -26
  92. package/stat/assets/icons/chevron-right.svg +0 -1
  93. package/stat/assets/icons/close-circle-dark.svg +0 -1
  94. package/stat/assets/icons/close-circle.svg +0 -1
  95. package/stat/assets/icons/fullscreen.svg +0 -17
  96. package/stat/assets/icons/fullscreen_exit.svg +0 -17
  97. package/stat/assets/icons/hamburger.svg +0 -15
  98. package/stat/assets/icons/left-arrow.svg +0 -12
  99. package/stat/assets/icons/magnify-minus.svg +0 -16
  100. package/stat/assets/icons/magnify-plus.svg +0 -17
  101. package/stat/assets/icons/magnify.svg +0 -15
  102. package/stat/assets/icons/pause.svg +0 -23
  103. package/stat/assets/icons/play.svg +0 -22
  104. package/stat/assets/icons/playback-speed.svg +0 -34
  105. package/stat/assets/icons/read-aloud.svg +0 -22
  106. package/stat/assets/icons/review.svg +0 -22
  107. package/stat/assets/icons/thumbnails.svg +0 -17
  108. package/stat/assets/icons/voice.svg +0 -1
  109. package/stat/assets/icons/volume-full.svg +0 -22
  110. package/stat/assets/images/BRicons.png +0 -0
  111. package/stat/assets/images/BRicons.svg +0 -94
  112. package/stat/assets/images/BRicons_ia.png +0 -0
  113. package/stat/assets/images/back_pages.png +0 -0
  114. package/stat/assets/images/book_bottom_icon.png +0 -0
  115. package/stat/assets/images/book_down_icon.png +0 -0
  116. package/stat/assets/images/book_left_icon.png +0 -0
  117. package/stat/assets/images/book_leftmost_icon.png +0 -0
  118. package/stat/assets/images/book_right_icon.png +0 -0
  119. package/stat/assets/images/book_rightmost_icon.png +0 -0
  120. package/stat/assets/images/book_top_icon.png +0 -0
  121. package/stat/assets/images/book_up_icon.png +0 -0
  122. package/stat/assets/images/books_graphic.svg +0 -177
  123. package/stat/assets/images/booksplit.png +0 -0
  124. package/stat/assets/images/control_pause_icon.png +0 -0
  125. package/stat/assets/images/control_play_icon.png +0 -0
  126. package/stat/assets/images/embed_icon.png +0 -0
  127. package/stat/assets/images/icon-home-ia.png +0 -0
  128. package/stat/assets/images/icon_OL-logo-xs.png +0 -0
  129. package/stat/assets/images/icon_alert-xs.png +0 -0
  130. package/stat/assets/images/icon_book.svg +0 -12
  131. package/stat/assets/images/icon_bookmark.svg +0 -12
  132. package/stat/assets/images/icon_close-pop.png +0 -0
  133. package/stat/assets/images/icon_download.png +0 -0
  134. package/stat/assets/images/icon_gear.svg +0 -14
  135. package/stat/assets/images/icon_hamburger.svg +0 -20
  136. package/stat/assets/images/icon_home.png +0 -0
  137. package/stat/assets/images/icon_home.svg +0 -21
  138. package/stat/assets/images/icon_home_ia.png +0 -0
  139. package/stat/assets/images/icon_indicator.png +0 -0
  140. package/stat/assets/images/icon_info.svg +0 -11
  141. package/stat/assets/images/icon_one_page.svg +0 -8
  142. package/stat/assets/images/icon_pause.svg +0 -1
  143. package/stat/assets/images/icon_play.svg +0 -1
  144. package/stat/assets/images/icon_playback-rate.svg +0 -15
  145. package/stat/assets/images/icon_return.png +0 -0
  146. package/stat/assets/images/icon_search_button.svg +0 -8
  147. package/stat/assets/images/icon_share.svg +0 -9
  148. package/stat/assets/images/icon_skip-ahead.svg +0 -6
  149. package/stat/assets/images/icon_skip-back.svg +0 -13
  150. package/stat/assets/images/icon_speaker.svg +0 -18
  151. package/stat/assets/images/icon_speaker_open.svg +0 -10
  152. package/stat/assets/images/icon_thumbnails.svg +0 -12
  153. package/stat/assets/images/icon_toc.svg +0 -5
  154. package/stat/assets/images/icon_two_pages.svg +0 -9
  155. package/stat/assets/images/icon_zoomer.png +0 -0
  156. package/stat/assets/images/loading.gif +0 -0
  157. package/stat/assets/images/logo_icon.png +0 -0
  158. package/stat/assets/images/marker_chap-off.png +0 -0
  159. package/stat/assets/images/marker_chap-off.svg +0 -11
  160. package/stat/assets/images/marker_chap-off_ia.png +0 -0
  161. package/stat/assets/images/marker_chap-on.png +0 -0
  162. package/stat/assets/images/marker_chap-on.svg +0 -11
  163. package/stat/assets/images/marker_srch-on.svg +0 -11
  164. package/stat/assets/images/marker_srchchap-off.png +0 -0
  165. package/stat/assets/images/marker_srchchap-on.png +0 -0
  166. package/stat/assets/images/nav_control-dn.png +0 -0
  167. package/stat/assets/images/nav_control-dn_ia.png +0 -0
  168. package/stat/assets/images/nav_control-up.png +0 -0
  169. package/stat/assets/images/nav_control-up_ia.png +0 -0
  170. package/stat/assets/images/nav_control.png +0 -0
  171. package/stat/assets/images/one_page_mode_icon.png +0 -0
  172. package/stat/assets/images/paper-badge.png +0 -0
  173. package/stat/assets/images/print_icon.png +0 -0
  174. package/stat/assets/images/progressbar.gif +0 -0
  175. package/stat/assets/images/right_edges.png +0 -0
  176. package/stat/assets/images/slider.png +0 -0
  177. package/stat/assets/images/slider_ia.png +0 -0
  178. package/stat/assets/images/thumbnail_mode_icon.png +0 -0
  179. package/stat/assets/images/transparent.png +0 -0
  180. package/stat/assets/images/two_page_mode_icon.png +0 -0
  181. package/stat/assets/images/zoom_in_icon.png +0 -0
  182. package/stat/assets/images/zoom_out_icon.png +0 -0
  183. package/stat/css/BookReader.scss +0 -89
  184. package/stat/css/_BRBookmarks.scss +0 -29
  185. package/stat/css/_BRComponent.scss +0 -13
  186. package/stat/css/_BRfloat.scss +0 -197
  187. package/stat/css/_BRicon.scss +0 -48
  188. package/stat/css/_BRmain.scss +0 -251
  189. package/stat/css/_BRnav.scss +0 -359
  190. package/stat/css/_BRpages.scss +0 -139
  191. package/stat/css/_BRsearch.scss +0 -226
  192. package/stat/css/_BRtoolbar.scss +0 -84
  193. package/stat/css/_BRvendor.scss +0 -5
  194. package/stat/css/_MobileNav.scss +0 -194
  195. package/stat/css/_TextSelection.scss +0 -32
  196. package/stat/css/_colorbox.scss +0 -52
  197. package/stat/css/_controls.scss +0 -253
  198. package/stat/css/_icons.scss +0 -121
  199. package/stat/jquery-wrapper.js +0 -4
  200. package/stat/plugins/plugin.archive_analytics.js +0 -86
  201. package/stat/plugins/plugin.autoplay.js +0 -129
  202. package/stat/plugins/plugin.chapters.js +0 -248
  203. package/stat/plugins/plugin.iframe.js +0 -48
  204. package/stat/plugins/plugin.mobile_nav.js +0 -288
  205. package/stat/plugins/plugin.resume.js +0 -68
  206. package/stat/plugins/plugin.text_selection.js +0 -291
  207. package/stat/plugins/plugin.url.js +0 -198
  208. package/stat/plugins/plugin.vendor-fullscreen.js +0 -247
  209. package/stat/plugins/search/plugin.search.js +0 -439
  210. package/stat/plugins/search/view.js +0 -439
  211. package/stat/plugins/tts/AbstractTTSEngine.js +0 -249
  212. package/stat/plugins/tts/FestivalTTSEngine.js +0 -169
  213. package/stat/plugins/tts/PageChunk.js +0 -107
  214. package/stat/plugins/tts/PageChunkIterator.js +0 -163
  215. package/stat/plugins/tts/WebTTSEngine.js +0 -357
  216. package/stat/plugins/tts/plugin.tts.js +0 -357
  217. package/stat/plugins/tts/tooltip_dict.js +0 -15
  218. package/stat/plugins/tts/utils.js +0 -91
  219. package/stat/util/browserSniffing.js +0 -30
  220. package/stat/util/debouncer.js +0 -26
  221. package/stat/util/docCookies.js +0 -67
  222. package/stat/util/strings.js +0 -34
@@ -1,518 +0,0 @@
1
- // @ts-check
2
- import { DEFAULT_OPTIONS } from './options.js';
3
- import { clamp } from './utils.js';
4
- /** @typedef {import('./options.js').PageData} PageData */
5
- /** @typedef {import('../BookReader.js').default} BookReader */
6
-
7
- // URI to display when a page is not viewable.
8
- // TODO Render configurable html for the user instead.
9
- // FIXME Don't reference files on archive.org
10
- const UNVIEWABLE_PAGE_URI = '/bookreader/static/preview-default.png';
11
-
12
- /**
13
- * Contains information about the Book/Document independent of the way it is
14
- * being rendering. Nothing here should reference e.g. the mode, zoom, etc.
15
- * It's just information about the book and its pages (usually as specified
16
- * in the BookReader data option.)
17
- */
18
- export class BookModel {
19
- /**
20
- * @param {BookReader} br
21
- */
22
- constructor(br) {
23
- this.br = br;
24
- this.reduceSet = br.reduceSet;
25
- this.ppi = br.options?.ppi ?? DEFAULT_OPTIONS.ppi;
26
-
27
- /** @type {{width: number, height: number}} memoize storage */
28
- this._medianPageSize = null;
29
- /** @deprecated @type {{width: number, height: number}} memoize storage */
30
- this._medianPageSizePixels = null;
31
- /** @type {[PageData[], number]} */
32
- this._getDataFlattenedCached = null;
33
- }
34
-
35
- /**
36
- * @deprecated Use getMedianPageSizeInches
37
- * Memoized
38
- * @return {{width: number, height: number}}
39
- */
40
- getMedianPageSize() {
41
- if (this._medianPageSizePixels) {
42
- return this._medianPageSizePixels;
43
- }
44
-
45
- // A little expensive but we just do it once
46
- const widths = [];
47
- const heights = [];
48
- for (let i = 0; i < this.getNumLeafs(); i++) {
49
- widths.push(this.getPageWidth(i));
50
- heights.push(this.getPageHeight(i));
51
- }
52
-
53
- widths.sort();
54
- heights.sort();
55
- this._medianPageSizePixels = {
56
- width: widths[Math.floor(widths.length / 2)],
57
- height: heights[Math.floor(heights.length / 2)]
58
- };
59
- return this._medianPageSizePixels;
60
- }
61
-
62
- /** Get median width/height of page in inches. Memoized for performance. */
63
- getMedianPageSizeInches() {
64
- if (this._medianPageSize) {
65
- return this._medianPageSize;
66
- }
67
-
68
- const widths = [];
69
- const heights = [];
70
- for (const page of this.pagesIterator()) {
71
- widths.push(page.widthInches);
72
- heights.push(page.heightInches);
73
- }
74
-
75
- widths.sort();
76
- heights.sort();
77
-
78
- this._medianPageSize = {
79
- width: widths[Math.floor(widths.length / 2)],
80
- height: heights[Math.floor(heights.length / 2)]
81
- };
82
- return this._medianPageSize;
83
- }
84
-
85
- /**
86
- * Returns the page width for the given index, or first or last page if out of range
87
- * @deprecated see getPageWidth
88
- * @param {PageIndex} index
89
- */
90
- _getPageWidth(index) {
91
- // Synthesize a page width for pages not actually present in book.
92
- // May or may not be the best approach.
93
- // If index is out of range we return the width of first or last page
94
- index = clamp(index, 0, this.getNumLeafs() - 1);
95
- return this.getPageWidth(index);
96
- }
97
-
98
- /**
99
- * Returns the page height for the given index, or first or last page if out of range
100
- * @deprecated see getPageHeight
101
- * @param {PageIndex} index
102
- */
103
- _getPageHeight(index) {
104
- const clampedIndex = clamp(index, 0, this.getNumLeafs() - 1);
105
- return this.getPageHeight(clampedIndex);
106
- }
107
-
108
- /**
109
- * Returns the *highest* index the given page number, or undefined
110
- * @param {PageNumString} pageNum
111
- * @return {PageIndex|undefined}
112
- */
113
- getPageIndex(pageNum) {
114
- const pageIndices = this.getPageIndices(pageNum);
115
- return pageIndices.length ? pageIndices[pageIndices.length - 1] : undefined;
116
- }
117
-
118
- /**
119
- * Returns an array (possibly empty) of the indices with the given page number
120
- * @param {PageNumString} pageNum
121
- * @return {PageIndex[]}
122
- */
123
- getPageIndices(pageNum) {
124
- const indices = [];
125
-
126
- // Check for special "nXX" page number
127
- if (pageNum.slice(0,1) == 'n') {
128
- try {
129
- const pageIntStr = pageNum.slice(1, pageNum.length);
130
- const pageIndex = parseInt(pageIntStr);
131
- indices.push(pageIndex);
132
- return indices;
133
- } catch (err) {
134
- // Do nothing... will run through page names and see if one matches
135
- }
136
- }
137
-
138
- for (let i = 0; i < this.getNumLeafs(); i++) {
139
- if (this.getPageNum(i) == pageNum) {
140
- indices.push(i);
141
- }
142
- }
143
-
144
- return indices;
145
- }
146
-
147
- /**
148
- * Returns the name of the page as it should be displayed in the user interface
149
- * @param {PageIndex} index
150
- * @return {string}
151
- */
152
- getPageName(index) {
153
- return 'Page ' + this.getPageNum(index);
154
- }
155
-
156
- /**
157
- * @return {number} the total number of leafs (like an array length)
158
- */
159
- getNumLeafs() {
160
- // For deprecated interface support, if numLeafs is set, use that.
161
- if (this.br.numLeafs !== undefined)
162
- return this.br.numLeafs;
163
- return this._getDataFlattened().length;
164
- }
165
-
166
- /**
167
- * @param {PageIndex} index
168
- * @return {Number|undefined}
169
- */
170
- getPageWidth(index) {
171
- return this.getPageProp(index, 'width');
172
- }
173
-
174
- /**
175
- * @param {PageIndex} index
176
- * @return {Number|undefined}
177
- */
178
- getPageHeight(index) {
179
- return this.getPageProp(index, 'height');
180
- }
181
-
182
- /**
183
- * @param {PageIndex} index
184
- * @param {number} reduce - not used in default implementation
185
- * @param {number} rotate - not used in default implementation
186
- * @return {string|undefined}
187
- */
188
- // eslint-disable-next-line no-unused-vars
189
- getPageURI(index, reduce, rotate) {
190
- return !this.getPageProp(index, 'viewable', true) ? UNVIEWABLE_PAGE_URI : this.getPageProp(index, 'uri');
191
- }
192
-
193
- /**
194
- * @param {PageIndex} index
195
- * @return {'L' | 'R'}
196
- */
197
- getPageSide(index) {
198
- return this.getPageProp(index, 'pageSide') || (index % 2 === 0 ? 'R' : 'L');
199
- }
200
-
201
- /**
202
- * @param {PageIndex} index
203
- * @return {PageNumString}
204
- */
205
- getPageNum(index) {
206
- const pageNum = this.getPageProp(index, 'pageNum');
207
- return pageNum === undefined ? `n${index}` : pageNum;
208
- }
209
-
210
- /**
211
- * Generalized property accessor.
212
- * @param {PageIndex} index
213
- * @param {keyof PageData} propName
214
- * @param {*} [fallbackValue] return if undefined
215
- * @return {*|undefined}
216
- */
217
- getPageProp(index, propName, fallbackValue = undefined) {
218
- return this._getDataProp(index, propName, fallbackValue);
219
- }
220
-
221
- /**
222
- * This function returns the left and right indices for the user-visible
223
- * spread that contains the given index.
224
- * @note Can return indices out of range of what's in the book.
225
- * @param {PageIndex} pindex
226
- * @return {[PageIndex, PageIndex]} eg [0, 1]
227
- */
228
- getSpreadIndices(pindex) {
229
- if (this.br.pageProgression == 'rl') {
230
- return this.getPageSide(pindex) == 'R' ? [pindex + 1, pindex] : [pindex, pindex - 1];
231
- } else {
232
- return this.getPageSide(pindex) == 'L' ? [pindex, pindex + 1] : [pindex - 1, pindex];
233
- }
234
- }
235
-
236
- /**
237
- * Single images in the Internet Archive scandata.xml metadata are (somewhat incorrectly)
238
- * given a "leaf" number. Some of these images from the scanning process should not
239
- * be displayed in the BookReader (for example colour calibration cards). Since some
240
- * of the scanned images will not be displayed in the BookReader (those marked with
241
- * addToAccessFormats false in the scandata.xml) leaf numbers and BookReader page
242
- * indexes are generally not the same. This function returns the BookReader page
243
- * index given a scanned leaf number.
244
- *
245
- * This function is used, for example, to map between search results (that use the
246
- * leaf numbers) and the displayed pages in the BookReader.
247
- * @param {LeafNum} leafNum
248
- * @return {PageIndex}
249
- */
250
- leafNumToIndex(leafNum) {
251
- const index = this._getDataFlattened()
252
- .findIndex(d => d.leafNum == leafNum);
253
- // If no match is found, fall back to the leafNum provide (leafNum == index)
254
- return index > -1 ? index : leafNum;
255
- }
256
-
257
- /**
258
- * Parses the pageString format
259
- * @param {PageString} pageString
260
- * @return {PageIndex|undefined}
261
- */
262
- parsePageString(pageString) {
263
- let pageIndex;
264
- // Check for special "leaf"
265
- const leafMatch = /^leaf(\d+)/.exec(pageString);
266
- if (leafMatch) {
267
- pageIndex = this.leafNumToIndex(parseInt(leafMatch[1], 10));
268
- if (pageIndex === null) {
269
- pageIndex = undefined; // to match return type of getPageIndex
270
- }
271
- } else {
272
- pageIndex = this.getPageIndex(pageString);
273
- }
274
- return pageIndex;
275
- }
276
-
277
- /**
278
- * @param {number} index use negatives to get page relative to end
279
- * @param loop whether to loop (i.e. -1 == last page)
280
- */
281
- getPage(index, loop = true) {
282
- const numLeafs = this.getNumLeafs();
283
- if (!loop && (index < 0 || index >= numLeafs)) {
284
- return undefined;
285
- }
286
- if (index < 0 && index >= -numLeafs) {
287
- index += numLeafs;
288
- }
289
- index = index % numLeafs;
290
- return new PageModel(this, index);
291
- }
292
-
293
- /**
294
- * @param {object} [arg0]
295
- * @param {number} [arg0.start] inclusive
296
- * @param {number} [arg0.end] exclusive
297
- * @param {boolean} [arg0.combineConsecutiveUnviewables] Yield only first unviewable
298
- * of a chunk of unviewable pages instead of each page
299
- */
300
- * pagesIterator({ start = 0, end = Infinity, combineConsecutiveUnviewables = false } = {}) {
301
- start = Math.max(0, start);
302
- end = Math.min(end, this.getNumLeafs());
303
-
304
- for (let i = start; i < end; i++) {
305
- const page = this.getPage(i);
306
- if (combineConsecutiveUnviewables && page.isConsecutiveUnviewable) continue;
307
-
308
- yield page;
309
- }
310
- }
311
-
312
- /**
313
- * Flatten the nested structure (make 1d array), and also add pageSide prop
314
- * @return {PageData[]}
315
- */
316
- _getDataFlattened() {
317
- if (this._getDataFlattenedCached && this._getDataFlattenedCached[1] === this.br.data.length)
318
- return this._getDataFlattenedCached[0];
319
-
320
- let prevPageSide = null;
321
- /** @type {number|null} */
322
- let unviewablesChunkStart = null;
323
- let index = 0;
324
- // @ts-ignore TS doesn't know about flatMap for some reason
325
- const flattened = this.br.data.flatMap(spread => {
326
- return spread.map(page => {
327
- if (!page.pageSide) {
328
- if (prevPageSide === null) {
329
- page.pageSide = spread.length === 2 ? 'L' : 'R';
330
- } else {
331
- page.pageSide = prevPageSide === 'L' ? 'R' : 'L';
332
- }
333
- }
334
- prevPageSide = page.pageSide;
335
-
336
- if (page.viewable === false) {
337
- if (unviewablesChunkStart === null) {
338
- page.unviewablesStart = unviewablesChunkStart = index;
339
- } else {
340
- page.unviewablesStart = unviewablesChunkStart;
341
- }
342
- } else {
343
- unviewablesChunkStart = null;
344
- }
345
-
346
- index++;
347
- return page;
348
- });
349
- });
350
-
351
- // length is used as a cache breaker
352
- this._getDataFlattenedCached = [flattened, this.br.data.length];
353
- return flattened;
354
- }
355
-
356
- /**
357
- * Helper. Return a prop for a given index. Returns `fallbackValue` if index is invalid or
358
- * property not on page.
359
- * @param {PageIndex} index
360
- * @param {keyof PageData} prop
361
- * @param {*} fallbackValue return if property not on the record
362
- * @return {*}
363
- */
364
- _getDataProp(index, prop, fallbackValue = undefined) {
365
- const dataf = this._getDataFlattened();
366
- const invalidIndex = isNaN(index) || index < 0 || index >= dataf.length;
367
- if (invalidIndex || 'undefined' == typeof(dataf[index][prop]))
368
- return fallbackValue;
369
- return dataf[index][prop];
370
- }
371
- }
372
-
373
- /**
374
- * A controlled schema for page data.
375
- */
376
- export class PageModel {
377
- /**
378
- * @param {BookModel} book
379
- * @param {PageIndex} index
380
- */
381
- constructor(book, index) {
382
- // TODO: Get default from config
383
- this.ppi = book._getDataProp(index, 'ppi', book.ppi);
384
- this.book = book;
385
- this.index = index;
386
- this.width = book.getPageWidth(index);
387
- this.widthInches = this.width / this.ppi;
388
- this.height = book.getPageHeight(index);
389
- this.heightInches = this.height / this.ppi;
390
- this.pageSide = book.getPageSide(index);
391
- this.leafNum = book._getDataProp(index, 'leafNum', this.index);
392
-
393
- /** @type {boolean} */
394
- this.isViewable = book._getDataProp(index, 'viewable', true);
395
- /** @type {PageIndex} The first in the series of unviewable pages this is in. */
396
- this.unviewablesStart = book._getDataProp(index, 'unviewablesStart') || null;
397
- /**
398
- * Consecutive unviewable pages are pages in an unviewable "chunk" which are not the first
399
- * of that chunk.
400
- */
401
- this.isConsecutiveUnviewable = !this.isViewable && this.unviewablesStart != this.index;
402
-
403
- this._rawData = this.book._getDataFlattened()[this.index];
404
- }
405
-
406
- /**
407
- * Updates the page to no longer be unviewable. Assumes the
408
- * Page's URI is already set/correct.
409
- */
410
- makeViewable(newViewableState = true) {
411
- if (this.isViewable == newViewableState) return;
412
-
413
- if (newViewableState) {
414
- this._rawData.viewable = true;
415
- delete this._rawData.unviewablesStart;
416
- // Update any subsequent page to now point to the right "start"
417
- for (const page of this.book.pagesIterator({ start: this.index + 1 })) {
418
- if (page.isViewable) break;
419
- page._rawData.unviewablesStart = this.index + 1;
420
- }
421
- } else {
422
- this._rawData.viewable = false;
423
- this._rawData.unviewablesStart = (this.prev && !this.prev.isViewable) ? this.prev.unviewablesStart : this.index;
424
- // Update any subsequent page to now point to the right "start"
425
- for (const page of this.book.pagesIterator({ start: this.index + 1 })) {
426
- if (!page.isViewable) break;
427
- page._rawData.unviewablesStart = this._rawData.unviewablesStart;
428
- }
429
- }
430
- }
431
-
432
- get prev() {
433
- return this.findPrev();
434
- }
435
-
436
- get next() {
437
- return this.findNext();
438
- }
439
-
440
- /**
441
- * @param {number} reduce
442
- * @param {number} rotate
443
- */
444
- getURI(reduce, rotate) {
445
- return this.book.getPageURI(this.index, reduce, rotate);
446
- }
447
-
448
- /**
449
- * Returns the srcset with correct URIs or void string if out of range
450
- * @param {number} reduce
451
- * @param {number} [rotate]
452
- */
453
- getURISrcSet(reduce, rotate = 0) {
454
- const { reduceSet } = this.book;
455
- const initialReduce = reduceSet.floor(reduce);
456
- // We don't need to repeat the initial reduce in the srcset
457
- const topReduce = reduceSet.decr(initialReduce);
458
- const reduces = [];
459
- for (let r = topReduce; r >= 1; r = reduceSet.decr(r)) {
460
- reduces.push(r);
461
- }
462
- return reduces
463
- .map(r => `${this.getURI(r, rotate)} ${initialReduce / r}x`)
464
- .join(', ');
465
- }
466
-
467
- /**
468
- * @param {object} [arg0]
469
- * @param {boolean} [arg0.combineConsecutiveUnviewables] Whether to only yield the first page
470
- * of a series of unviewable pages instead of each page
471
- * @return {PageModel|void}
472
- */
473
- findNext({ combineConsecutiveUnviewables = false } = {}) {
474
- return this.book
475
- .pagesIterator({ start: this.index + 1, combineConsecutiveUnviewables })
476
- .next().value;
477
- }
478
-
479
- /**
480
- * @param {object} [arg0]
481
- * @param {boolean} [arg0.combineConsecutiveUnviewables] Whether to only yield the first page
482
- * of a series of unviewable pages instead of each page
483
- * @return {PageModel|void}
484
- */
485
- findPrev({ combineConsecutiveUnviewables = false } = {}) {
486
- if (this.index == 0) return undefined;
487
-
488
- if (combineConsecutiveUnviewables) {
489
- if (this.isConsecutiveUnviewable) {
490
- return this.book.getPage(this.unviewablesStart);
491
- } else {
492
- // Recursively goes backward through the book
493
- // TODO make a reverse iterator to make it look identical to findNext
494
- const prev = new PageModel(this.book, this.index - 1);
495
- return prev.isViewable ? prev : prev.findPrev({ combineConsecutiveUnviewables });
496
- }
497
- } else {
498
- return new PageModel(this.book, this.index - 1);
499
- }
500
- }
501
- }
502
-
503
- // There are a few main ways we can reference a specific page in a book:
504
- /**
505
- * @typedef {string} PageNumString
506
- * Possible values: /^n?\d+$/. Example: 'n7', '18'
507
- * Not necessarily unique
508
- */
509
- /**
510
- * @typedef {number} LeafNum
511
- * No clue if 0 or 1 indexed or consecutive; generally from IA book info.
512
- */
513
- /**
514
- * @typedef {string} PageString
515
- * Possible values: /^(leaf)?\d+$/ Example: 'leaf7', '18'
516
- * If leaf-prefixed, then the number is a LeafNum. Otherwise it's a PageNumString
517
- */
518
- /** @typedef {number} PageIndex 0-based index of all the pages */
@@ -1,54 +0,0 @@
1
- /**
2
- * Displays a console on the document for debugging devices where remote
3
- * debugging is not feasible, and forwards all console.log's to be displayed
4
- * on screen.
5
- */
6
- export class DebugConsole {
7
- constructor() {
8
- /** How many times we've seen the same line in a row */
9
- this.currentRun = 0;
10
- }
11
-
12
- init() {
13
- this.$log = $(`<div id="_debugLog" style="width: 100%; height: 300px; overflow: auto" />`);
14
- $(document.body).prepend(this.$log);
15
-
16
- this.$form = $(`
17
- <form>
18
- <input style="width:100%; font-family: monospace;" id="_debugLogInput">
19
- </form>`);
20
- this.$log.append(this.$form);
21
-
22
- this.$form.on("submit", ev => {
23
- ev.preventDefault();
24
- const result = eval(this.$form.find('input').val());
25
- this.logToScreen([result]);
26
- });
27
-
28
- const _realLog = console.log.bind(console);
29
- console.log = (...args) => {
30
- _realLog(...args);
31
- this.logToScreen(args);
32
- };
33
-
34
- window.onerror = (...args) => this.logToScreen(args);
35
- }
36
-
37
- /**
38
- * Log the provided array onto the on screen console
39
- * @param {Array} args
40
- */
41
- logToScreen(args) {
42
- const html = args.map(JSON.stringify).join(',');
43
- const $lastEntry = this.$log.children('.log-entry:last-child');
44
- if ($lastEntry.find('.entry-code').html() == html) {
45
- $lastEntry.find('.count').text(`(${++this.currentRun})`);
46
- } else {
47
- this.currentRun = 1;
48
- this.$log.append($(`
49
- <div class="log-entry">
50
- <code class="count"></code> <code class="entry-code">${html}</code>
51
- </div>`));
52
- }
53
- }
54
- }