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