@internetarchive/bookreader 5.0.0-88-alpha.11 → 5.0.0-89
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/BookReader/BookReader.css +17 -3
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +87 -108
- package/BookReader/ia-bookreader-bundle.js.map +1 -1
- package/BookReader/plugins/plugin.archive_analytics.js +1 -1
- package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
- package/BookReader/plugins/plugin.autoplay.js +1 -1
- package/BookReader/plugins/plugin.autoplay.js.map +1 -1
- package/BookReader/plugins/plugin.iiif.js +1 -1
- package/BookReader/plugins/plugin.iiif.js.map +1 -1
- package/BookReader/plugins/plugin.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +1 -1
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +1 -1
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReader/plugins/plugin.url.js +1 -1
- package/BookReader/plugins/plugin.url.js.map +1 -1
- package/CHANGELOG.md +14 -0
- package/babel.config.js +12 -30
- package/codecov.yml +1 -1
- package/jsconfig.json +1 -3
- package/package.json +14 -16
- package/src/BookNavigator/search/search-results.js +1 -1
- package/src/BookReader/ImageCache.js +48 -15
- package/src/BookReader/Mode1UpLit.js +56 -86
- package/src/BookReader/Mode2UpLit.js +5 -5
- package/src/BookReader/Navbar/Navbar.js +53 -11
- package/src/BookReader/PageContainer.js +41 -22
- package/src/BookReader/options.js +27 -3
- package/src/BookReader/utils.js +10 -0
- package/src/BookReader.js +120 -21
- package/src/BookReaderPlugin.js +44 -0
- package/src/css/_BRnav.scss +0 -3
- package/src/css/_BRpages.scss +21 -2
- package/src/css/_controls.scss +4 -0
- package/src/plugins/plugin.archive_analytics.js +84 -78
- package/src/plugins/plugin.autoplay.js +98 -102
- package/src/plugins/plugin.chapters.js +17 -22
- package/src/plugins/plugin.iiif.js +16 -30
- package/src/plugins/plugin.resume.js +54 -51
- package/src/plugins/plugin.text_selection.js +68 -76
- package/src/plugins/tts/AbstractTTSEngine.js +2 -4
- package/src/plugins/tts/PageChunk.js +5 -9
- package/src/plugins/tts/PageChunkIterator.js +3 -5
- package/src/plugins/tts/plugin.tts.js +309 -329
- package/src/plugins/url/plugin.url.js +1 -1
- package/src/util/strings.js +1 -0
- package/tests/e2e/autoplay.test.js +8 -5
- package/tests/e2e/helpers/base.js +2 -2
- package/tests/e2e/helpers/mockSearch.js +6 -9
- package/tests/jest/BookReader/Navbar/Navbar.test.js +16 -3
- package/tests/jest/BookReader/PageContainer.test.js +96 -55
- package/tests/jest/BookReader/utils.test.js +21 -0
- package/tests/jest/BookReader.test.js +13 -12
- package/tests/jest/plugins/plugin.archive_analytics.test.js +8 -11
- package/tests/jest/plugins/plugin.autoplay.test.js +9 -22
- package/tests/jest/plugins/plugin.resume.test.js +19 -32
- package/tests/jest/plugins/plugin.text_selection.test.js +23 -24
- package/dist/esm/BookNavigator/assets/bookmark-colors.js +0 -4
- package/dist/esm/BookNavigator/assets/button-base.js +0 -4
- package/dist/esm/BookNavigator/assets/ia-logo.js +0 -4
- package/dist/esm/BookNavigator/assets/icon_checkmark.js +0 -8
- package/dist/esm/BookNavigator/assets/icon_close.js +0 -4
- package/dist/esm/BookNavigator/book-navigator.js +0 -612
- package/dist/esm/BookNavigator/bookmarks/bookmark-button.js +0 -35
- package/dist/esm/BookNavigator/bookmarks/bookmark-edit.js +0 -78
- package/dist/esm/BookNavigator/bookmarks/bookmarks-list.js +0 -160
- package/dist/esm/BookNavigator/bookmarks/bookmarks-loginCTA.js +0 -24
- package/dist/esm/BookNavigator/bookmarks/bookmarks-provider.js +0 -55
- package/dist/esm/BookNavigator/bookmarks/ia-bookmarks.js +0 -521
- package/dist/esm/BookNavigator/delete-modal-actions.js +0 -29
- package/dist/esm/BookNavigator/downloads/downloads-provider.js +0 -84
- package/dist/esm/BookNavigator/downloads/downloads.js +0 -69
- package/dist/esm/BookNavigator/search/search-provider.js +0 -238
- package/dist/esm/BookNavigator/search/search-results.js +0 -161
- package/dist/esm/BookNavigator/sharing.js +0 -26
- package/dist/esm/BookNavigator/viewable-files.js +0 -94
- package/dist/esm/BookNavigator/visual-adjustments/visual-adjustments-provider.js +0 -83
- package/dist/esm/BookNavigator/visual-adjustments/visual-adjustments.js +0 -131
- package/dist/esm/BookReader/BookModel.js +0 -575
- package/dist/esm/BookReader/DragScrollable.js +0 -224
- package/dist/esm/BookReader/ImageCache.js +0 -122
- package/dist/esm/BookReader/Mode1Up.js +0 -114
- package/dist/esm/BookReader/Mode1UpLit.js +0 -579
- package/dist/esm/BookReader/Mode2Up.js +0 -106
- package/dist/esm/BookReader/Mode2UpLit.js +0 -1020
- package/dist/esm/BookReader/ModeCoordinateSpace.js +0 -28
- package/dist/esm/BookReader/ModeSmoothZoom.js +0 -318
- package/dist/esm/BookReader/ModeThumb.js +0 -366
- package/dist/esm/BookReader/Navbar/Navbar.js +0 -253
- package/dist/esm/BookReader/PageContainer.js +0 -165
- package/dist/esm/BookReader/ReduceSet.js +0 -27
- package/dist/esm/BookReader/Toolbar/Toolbar.js +0 -242
- package/dist/esm/BookReader/events.js +0 -20
- package/dist/esm/BookReader/options.js +0 -331
- package/dist/esm/BookReader/utils/HTMLDimensionsCacher.js +0 -48
- package/dist/esm/BookReader/utils/ScrollClassAdder.js +0 -31
- package/dist/esm/BookReader/utils/SelectionObserver.js +0 -42
- package/dist/esm/BookReader/utils/classes.js +0 -37
- package/dist/esm/BookReader/utils.js +0 -315
- package/dist/esm/BookReader.js +0 -1828
- package/dist/esm/assets/icons/1up.svg +0 -12
- package/dist/esm/assets/icons/2up.svg +0 -15
- package/dist/esm/assets/icons/advance.svg +0 -26
- package/dist/esm/assets/icons/chevron-right.svg +0 -1
- package/dist/esm/assets/icons/close-circle-dark.svg +0 -1
- package/dist/esm/assets/icons/close-circle.svg +0 -1
- package/dist/esm/assets/icons/fullscreen.svg +0 -17
- package/dist/esm/assets/icons/fullscreen_exit.svg +0 -17
- package/dist/esm/assets/icons/hamburger.svg +0 -15
- package/dist/esm/assets/icons/left-arrow.svg +0 -12
- package/dist/esm/assets/icons/magnify-minus.svg +0 -12
- package/dist/esm/assets/icons/magnify-plus.svg +0 -13
- package/dist/esm/assets/icons/magnify.svg +0 -15
- package/dist/esm/assets/icons/pause.svg +0 -23
- package/dist/esm/assets/icons/play.svg +0 -22
- package/dist/esm/assets/icons/playback-speed.svg +0 -34
- package/dist/esm/assets/icons/read-aloud.svg +0 -22
- package/dist/esm/assets/icons/review.svg +0 -22
- package/dist/esm/assets/icons/thumbnails.svg +0 -17
- package/dist/esm/assets/icons/voice.svg +0 -1
- package/dist/esm/assets/icons/volume-full.svg +0 -22
- package/dist/esm/assets/images/BRicons.png +0 -0
- package/dist/esm/assets/images/BRicons.svg +0 -94
- 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 +0 -177
- 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 +0 -12
- package/dist/esm/assets/images/icon_bookmark.svg +0 -12
- 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 +0 -14
- package/dist/esm/assets/images/icon_hamburger.svg +0 -20
- package/dist/esm/assets/images/icon_home.png +0 -0
- package/dist/esm/assets/images/icon_home.svg +0 -21
- 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 +0 -11
- package/dist/esm/assets/images/icon_one_page.svg +0 -8
- package/dist/esm/assets/images/icon_pause.svg +0 -1
- package/dist/esm/assets/images/icon_play.svg +0 -1
- package/dist/esm/assets/images/icon_playback-rate.svg +0 -15
- package/dist/esm/assets/images/icon_return.png +0 -0
- package/dist/esm/assets/images/icon_search_button.svg +0 -8
- package/dist/esm/assets/images/icon_share.svg +0 -9
- package/dist/esm/assets/images/icon_skip-ahead.svg +0 -6
- package/dist/esm/assets/images/icon_skip-back.svg +0 -13
- package/dist/esm/assets/images/icon_speaker.svg +0 -18
- package/dist/esm/assets/images/icon_speaker_open.svg +0 -10
- package/dist/esm/assets/images/icon_thumbnails.svg +0 -12
- package/dist/esm/assets/images/icon_toc.svg +0 -5
- package/dist/esm/assets/images/icon_two_pages.svg +0 -9
- 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 +0 -11
- 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 +0 -11
- package/dist/esm/assets/images/marker_srch-on.svg +0 -11
- 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 +0 -85
- package/dist/esm/css/_BRBookmarks.scss +0 -29
- package/dist/esm/css/_BRComponent.scss +0 -13
- package/dist/esm/css/_BRfloat.scss +0 -197
- package/dist/esm/css/_BRicon.scss +0 -54
- package/dist/esm/css/_BRmain.scss +0 -262
- package/dist/esm/css/_BRnav.scss +0 -354
- package/dist/esm/css/_BRpages.scss +0 -213
- package/dist/esm/css/_BRsearch.scss +0 -268
- package/dist/esm/css/_BRtoolbar.scss +0 -84
- package/dist/esm/css/_BRvendor.scss +0 -5
- package/dist/esm/css/_TextSelection.scss +0 -108
- package/dist/esm/css/_colorbox.scss +0 -52
- package/dist/esm/css/_controls.scss +0 -257
- package/dist/esm/css/_icons.scss +0 -121
- package/dist/esm/ia-bookreader/ia-bookreader.js +0 -141
- package/dist/esm/jquery-wrapper.js +0 -3
- package/dist/esm/plugins/plugin.archive_analytics.js +0 -72
- package/dist/esm/plugins/plugin.autoplay.js +0 -119
- package/dist/esm/plugins/plugin.chapters.js +0 -288
- package/dist/esm/plugins/plugin.iframe.js +0 -44
- package/dist/esm/plugins/plugin.iiif.js +0 -146
- package/dist/esm/plugins/plugin.resume.js +0 -66
- package/dist/esm/plugins/plugin.text_selection.js +0 -621
- package/dist/esm/plugins/plugin.vendor-fullscreen.js +0 -227
- package/dist/esm/plugins/search/plugin.search.js +0 -499
- package/dist/esm/plugins/search/utils.js +0 -42
- package/dist/esm/plugins/search/view.js +0 -360
- package/dist/esm/plugins/tts/AbstractTTSEngine.js +0 -282
- package/dist/esm/plugins/tts/FestivalTTSEngine.js +0 -192
- package/dist/esm/plugins/tts/PageChunk.js +0 -105
- package/dist/esm/plugins/tts/PageChunkIterator.js +0 -155
- package/dist/esm/plugins/tts/WebTTSEngine.js +0 -364
- package/dist/esm/plugins/tts/plugin.tts.js +0 -315
- package/dist/esm/plugins/tts/tooltip_dict.js +0 -14
- package/dist/esm/plugins/tts/utils.js +0 -79
- package/dist/esm/plugins/url/UrlPlugin.js +0 -197
- package/dist/esm/plugins/url/plugin.url.js +0 -212
- package/dist/esm/util/browserSniffing.js +0 -56
- package/dist/esm/util/debouncer.js +0 -25
- package/dist/esm/util/docCookies.js +0 -75
- package/dist/esm/util/strings.js +0 -34
- package/index.js +0 -2
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@internetarchive/bookreader",
|
3
|
-
"version": "5.0.0-
|
3
|
+
"version": "5.0.0-89",
|
4
4
|
"description": "The Internet Archive BookReader.",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -9,7 +9,7 @@
|
|
9
9
|
"publishConfig": {
|
10
10
|
"access": "public"
|
11
11
|
},
|
12
|
-
"module": "
|
12
|
+
"module": "src/ia-bookreader/ia-bookreader.js",
|
13
13
|
"keywords": [
|
14
14
|
"online",
|
15
15
|
"bookreader",
|
@@ -25,8 +25,8 @@
|
|
25
25
|
"homepage": "https://github.com/internetarchive/bookreader#readme",
|
26
26
|
"private": false,
|
27
27
|
"dependencies": {
|
28
|
-
"@internetarchive/ia-activity-indicator": "^0.0.
|
29
|
-
"@internetarchive/ia-item-navigator": "^2.1.
|
28
|
+
"@internetarchive/ia-activity-indicator": "^0.0.4",
|
29
|
+
"@internetarchive/ia-item-navigator": "^2.1.2",
|
30
30
|
"@internetarchive/icon-bookmark": "^1.3.4",
|
31
31
|
"@internetarchive/icon-dl": "^1.3.4",
|
32
32
|
"@internetarchive/icon-edit-pencil": "^1.3.4",
|
@@ -35,20 +35,11 @@
|
|
35
35
|
"@internetarchive/icon-search": "^1.3.4",
|
36
36
|
"@internetarchive/icon-toc": "^1.3.4",
|
37
37
|
"@internetarchive/icon-visual-adjustment": "^1.3.4",
|
38
|
-
"@internetarchive/modal-manager": "^2.
|
38
|
+
"@internetarchive/modal-manager": "^0.2.12",
|
39
39
|
"@internetarchive/shared-resize-observer": "^0.2.0",
|
40
|
-
"
|
41
|
-
"iso-language-codes": "1.1.0",
|
42
|
-
"jquery": "3.6.1",
|
43
|
-
"jquery-colorbox": "1.6.4",
|
44
|
-
"jquery-ui": "^1.12.1",
|
45
|
-
"jquery-ui-touch-punch": "0.2.3",
|
46
|
-
"jquery.browser": "0.1.0",
|
47
|
-
"lit": "^2.8.0",
|
48
|
-
"soundmanager2": "2.97.20170602"
|
40
|
+
"lit": "^2.5.0"
|
49
41
|
},
|
50
42
|
"devDependencies": {
|
51
|
-
"@babel/cli": "^7.26.4",
|
52
43
|
"@babel/core": "7.25.8",
|
53
44
|
"@babel/eslint-parser": "7.25.7",
|
54
45
|
"@babel/plugin-proposal-class-properties": "7.18.6",
|
@@ -67,12 +58,20 @@
|
|
67
58
|
"eslint-plugin-no-jquery": "^2.7.0",
|
68
59
|
"eslint-plugin-testcafe": "^0.2.1",
|
69
60
|
"http-server": "14.1.1",
|
61
|
+
"interactjs": "^1.10.18",
|
62
|
+
"iso-language-codes": "1.1.0",
|
70
63
|
"jest": "29.7.0",
|
71
64
|
"jest-environment-jsdom": "^29.7.0",
|
65
|
+
"jquery": "3.6.1",
|
66
|
+
"jquery-colorbox": "1.6.4",
|
67
|
+
"jquery-ui": "1.12.1",
|
68
|
+
"jquery-ui-touch-punch": "0.2.3",
|
69
|
+
"jquery.browser": "0.1.0",
|
72
70
|
"live-server": "1.2.2",
|
73
71
|
"regenerator-runtime": "0.14.1",
|
74
72
|
"sass": "1.79.5",
|
75
73
|
"sinon": "19.0.2",
|
74
|
+
"soundmanager2": "2.97.20170602",
|
76
75
|
"svgo": "3.3.2",
|
77
76
|
"testcafe": "3.6.2",
|
78
77
|
"testcafe-browser-provider-browserstack": "^1.13.2-alpha.1",
|
@@ -104,7 +103,6 @@
|
|
104
103
|
"build-assets": "npx cpx \"src/assets/**/*\" BookReader && npx svgo -f BookReader/icons && npx svgo -f BookReader/images",
|
105
104
|
"build-assets:watch": "npx cpx --watch --verbose \"src/assets/**/*\" BookReader",
|
106
105
|
"build-js": "npx webpack",
|
107
|
-
"build-esm": "env BABEL_ENV=esm npx babel src --out-dir dist/esm --copy-files --extensions \".js\"",
|
108
106
|
"build-js:watch": "npx webpack --mode=development --watch",
|
109
107
|
"build-css": "npx sass --no-source-map ./src/css/BookReader.scss ./BookReader/BookReader.css",
|
110
108
|
"build-css:watch": "npx sass --watch --no-source-map ./src/css/BookReader.scss ./BookReader/BookReader.css",
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/* eslint-disable class-methods-use-this */
|
2
2
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
3
3
|
import { css, html, LitElement, nothing } from 'lit';
|
4
|
-
import '@internetarchive/ia-activity-indicator';
|
4
|
+
import '@internetarchive/ia-activity-indicator/ia-activity-indicator';
|
5
5
|
import checkmarkIcon from '../assets/icon_checkmark.js';
|
6
6
|
import closeIcon from '../assets/icon_close.js';
|
7
7
|
import buttonCSS from '../assets/button-base.js';
|
@@ -7,8 +7,10 @@
|
|
7
7
|
/** @typedef {import("./BookModel").BookModel} BookModel */
|
8
8
|
/** @typedef {import("./BookModel").PageIndex} PageIndex */
|
9
9
|
/** @typedef {import("./ReduceSet").ReduceSet} ReduceSet */
|
10
|
+
/** @typedef {import("./options").BookReaderOptions} BookReaderOptions */
|
10
11
|
|
11
12
|
import { Pow2ReduceSet } from "./ReduceSet";
|
13
|
+
import { DEFAULT_OPTIONS } from "./options";
|
12
14
|
|
13
15
|
export class ImageCache {
|
14
16
|
/**
|
@@ -16,11 +18,25 @@ export class ImageCache {
|
|
16
18
|
* @param {object} opts
|
17
19
|
* @param {boolean} [opts.useSrcSet]
|
18
20
|
* @param {ReduceSet} [opts.reduceSet]
|
21
|
+
* @param {BookReaderOptions['renderPageURI']} [opts.renderPageURI]
|
19
22
|
*/
|
20
|
-
constructor(
|
23
|
+
constructor(
|
24
|
+
book,
|
25
|
+
{
|
26
|
+
useSrcSet = false,
|
27
|
+
reduceSet = Pow2ReduceSet,
|
28
|
+
renderPageURI = DEFAULT_OPTIONS.renderPageURI,
|
29
|
+
} = {},
|
30
|
+
) {
|
31
|
+
/** @type {BookModel} */
|
21
32
|
this.book = book;
|
33
|
+
/** @type {boolean} */
|
22
34
|
this.useSrcSet = useSrcSet;
|
35
|
+
/** @type {ReduceSet} */
|
23
36
|
this.reduceSet = reduceSet;
|
37
|
+
/** @type {BookReaderOptions['renderPageURI']} */
|
38
|
+
this.renderPageURI = renderPageURI;
|
39
|
+
|
24
40
|
/** @type {{ [index: number]: { reduce: number, loaded: boolean }[] }} */
|
25
41
|
this.cache = {};
|
26
42
|
this.defaultScale = 8;
|
@@ -33,19 +49,35 @@ export class ImageCache {
|
|
33
49
|
*
|
34
50
|
* @param {PageIndex} index
|
35
51
|
* @param {Number} reduce
|
52
|
+
* @param {HTMLImageElement?} [img]
|
36
53
|
*/
|
37
|
-
image(index, reduce) {
|
54
|
+
image(index, reduce, img = null) {
|
55
|
+
const finalReduce = this.getFinalReduce(index, reduce);
|
56
|
+
return this._serveImageElement(index, finalReduce, img);
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Get the final reduce factor to use for the given index
|
61
|
+
*
|
62
|
+
* @param {PageIndex} index
|
63
|
+
* @param {Number} reduce
|
64
|
+
*/
|
65
|
+
getFinalReduce(index, reduce) {
|
38
66
|
const cachedImages = this.cache[index] || [];
|
39
67
|
const sufficientImages = cachedImages
|
40
68
|
.filter(x => x.loaded && x.reduce <= reduce);
|
69
|
+
|
41
70
|
if (sufficientImages.length) {
|
42
71
|
// Choose the largest reduction factor that meets our needs
|
43
72
|
const bestReduce = Math.max(...sufficientImages.map(e => e.reduce));
|
44
|
-
|
73
|
+
// Don't need to floor here, since we know the image is in the cache
|
74
|
+
// and hence was already floor'd by the below `else` clause before
|
75
|
+
// it was added
|
76
|
+
return bestReduce;
|
45
77
|
} else {
|
46
78
|
// Don't use a cache entry; i.e. a fresh fetch will be made
|
47
79
|
// for this reduce
|
48
|
-
return this.
|
80
|
+
return this.reduceSet.floor(reduce);
|
49
81
|
}
|
50
82
|
}
|
51
83
|
|
@@ -87,26 +119,27 @@ export class ImageCache {
|
|
87
119
|
*
|
88
120
|
* @param {PageIndex} index
|
89
121
|
* @param {number} reduce
|
122
|
+
* @param {HTMLImageElement?} [img]
|
90
123
|
* @returns {JQuery<HTMLImageElement>} with base image classes
|
91
124
|
*/
|
92
|
-
_serveImageElement(index, reduce) {
|
93
|
-
|
94
|
-
let cacheEntry = this.cache[index]?.find(e => e.reduce == validReduce);
|
125
|
+
_serveImageElement(index, reduce, img = null) {
|
126
|
+
let cacheEntry = this.cache[index]?.find(e => e.reduce == reduce);
|
95
127
|
if (!cacheEntry) {
|
96
|
-
cacheEntry = { reduce
|
128
|
+
cacheEntry = { reduce, loaded: false };
|
97
129
|
const entries = this.cache[index] || (this.cache[index] = []);
|
98
130
|
entries.push(cacheEntry);
|
99
131
|
}
|
100
132
|
const page = this.book.getPage(index);
|
101
133
|
|
102
|
-
const
|
103
|
-
|
104
|
-
'
|
105
|
-
|
106
|
-
|
107
|
-
.data('
|
134
|
+
const uri = page.getURI(reduce, 0);
|
135
|
+
const $img = $(img || document.createElement('img'))
|
136
|
+
.addClass('BRpageimage')
|
137
|
+
.attr('alt', 'Book page image')
|
138
|
+
.data('reduce', reduce)
|
139
|
+
.data('src', uri);
|
140
|
+
this.renderPageURI($img[0], uri);
|
108
141
|
if (this.useSrcSet) {
|
109
|
-
$img.attr('srcset', page.getURISrcSet(
|
142
|
+
$img.attr('srcset', page.getURISrcSet(reduce));
|
110
143
|
}
|
111
144
|
if (!cacheEntry.loaded) {
|
112
145
|
$img.one('load', () => cacheEntry.loaded = true);
|
@@ -1,10 +1,10 @@
|
|
1
1
|
// @ts-check
|
2
|
-
import { property, query } from 'lit/decorators.js';
|
3
|
-
import {
|
2
|
+
import { customElement, property, query } from 'lit/decorators.js';
|
3
|
+
import {LitElement, html} from 'lit';
|
4
4
|
import { styleMap } from 'lit/directives/style-map.js';
|
5
5
|
import { ModeSmoothZoom } from './ModeSmoothZoom';
|
6
6
|
import { arrChanged, genToArray, sum, throttle } from './utils';
|
7
|
-
import { HTMLDimensionsCacher } from
|
7
|
+
import { HTMLDimensionsCacher } from "./utils/HTMLDimensionsCacher";
|
8
8
|
import { ScrollClassAdder } from './utils/ScrollClassAdder';
|
9
9
|
import { ModeCoordinateSpace } from './ModeCoordinateSpace';
|
10
10
|
/** @typedef {import('./BookModel').BookModel} BookModel */
|
@@ -17,6 +17,7 @@ import { ModeCoordinateSpace } from './ModeCoordinateSpace';
|
|
17
17
|
// I _have_ to make this globally public, otherwise it won't let me call
|
18
18
|
// it's constructor :/
|
19
19
|
/** @implements {SmoothZoomable} */
|
20
|
+
@customElement('br-mode-1up')
|
20
21
|
export class Mode1UpLit extends LitElement {
|
21
22
|
/****************************************/
|
22
23
|
/************** PROPERTIES **************/
|
@@ -85,15 +86,13 @@ export class Mode1UpLit extends LitElement {
|
|
85
86
|
get worldStyle() {
|
86
87
|
const wToR = this.coordSpace.worldUnitsToRenderedPixels;
|
87
88
|
return {
|
88
|
-
width: wToR(this.worldDimensions.width) +
|
89
|
-
height: wToR(this.worldDimensions.height) +
|
89
|
+
width: wToR(this.worldDimensions.width) + "px",
|
90
|
+
height: wToR(this.worldDimensions.height) + "px",
|
90
91
|
};
|
91
92
|
}
|
92
93
|
|
93
94
|
/** @type {HTMLElement} */
|
94
|
-
get $container() {
|
95
|
-
return this;
|
96
|
-
}
|
95
|
+
get $container() { return this; }
|
97
96
|
|
98
97
|
/** @type {HTMLElement} */
|
99
98
|
@query('.br-mode-1up__visible-world')
|
@@ -129,12 +128,10 @@ export class Mode1UpLit extends LitElement {
|
|
129
128
|
if (smooth) {
|
130
129
|
this.style.scrollBehavior = 'smooth';
|
131
130
|
}
|
132
|
-
this.scrollTop = this.coordSpace.worldUnitsToVisiblePixels(
|
133
|
-
this.pageTops[index] - this.SPACING_IN / 2,
|
134
|
-
);
|
131
|
+
this.scrollTop = this.coordSpace.worldUnitsToVisiblePixels(this.pageTops[index] - this.SPACING_IN / 2);
|
135
132
|
// TODO: Also h center?
|
136
133
|
if (smooth) {
|
137
|
-
setTimeout(() =>
|
134
|
+
setTimeout(() => this.style.scrollBehavior = '', 100);
|
138
135
|
}
|
139
136
|
}
|
140
137
|
|
@@ -197,7 +194,7 @@ export class Mode1UpLit extends LitElement {
|
|
197
194
|
this.throttledUpdateRenderedPages();
|
198
195
|
if (this.visiblePages.length) {
|
199
196
|
// unclear why this is ever really happening
|
200
|
-
this.br.displayedIndices = this.visiblePages.map(
|
197
|
+
this.br.displayedIndices = this.visiblePages.map(p => p.index);
|
201
198
|
this.br.updateFirstIndex(this.br.displayedIndices[0]);
|
202
199
|
this.br._components.navbar.updateNavIndexThrottled();
|
203
200
|
}
|
@@ -214,9 +211,7 @@ export class Mode1UpLit extends LitElement {
|
|
214
211
|
}
|
215
212
|
|
216
213
|
updatePages() {
|
217
|
-
this.pages = genToArray(
|
218
|
-
this.book.pagesIterator({ combineConsecutiveUnviewables: true }),
|
219
|
-
);
|
214
|
+
this.pages = genToArray(this.book.pagesIterator({ combineConsecutiveUnviewables: true }));
|
220
215
|
}
|
221
216
|
|
222
217
|
/** @override */
|
@@ -247,59 +242,50 @@ export class Mode1UpLit extends LitElement {
|
|
247
242
|
|
248
243
|
/** @override */
|
249
244
|
render() {
|
250
|
-
return html`
|
251
|
-
|
252
|
-
style=${styleMap(this.worldStyle)}
|
253
|
-
></div>
|
245
|
+
return html`
|
246
|
+
<div class="br-mode-1up__world" style=${styleMap(this.worldStyle)}></div>
|
254
247
|
<div class="br-mode-1up__visible-world">
|
255
|
-
${this.renderedPages.map(
|
248
|
+
${this.renderedPages.map(p => this.renderPage(p))}
|
256
249
|
</div>`;
|
257
250
|
}
|
258
251
|
|
259
252
|
/** @param {PageModel} page */
|
260
253
|
createPageContainer = (page) => {
|
261
|
-
return (
|
262
|
-
this.pageContainerCache[page.index]
|
263
|
-
(this.pageContainerCache[page.index] =
|
254
|
+
return this.pageContainerCache[page.index] || (
|
255
|
+
this.pageContainerCache[page.index] = (
|
264
256
|
// @ts-ignore I know it's protected, TS! But Mode1Up and BookReader are friends.
|
265
|
-
this.br._createPageContainer(page.index)
|
257
|
+
this.br._createPageContainer(page.index)
|
258
|
+
)
|
266
259
|
);
|
267
|
-
}
|
260
|
+
}
|
268
261
|
|
269
262
|
/** @param {PageModel} page */
|
270
263
|
renderPage = (page) => {
|
271
264
|
const wToR = this.coordSpace.worldUnitsToRenderedPixels;
|
272
265
|
const wToV = this.coordSpace.worldUnitsToVisiblePixels;
|
273
|
-
const containerWidth = this.coordSpace.visiblePixelsToWorldUnits(
|
274
|
-
this.htmlDimensionsCacher.clientWidth,
|
275
|
-
);
|
266
|
+
const containerWidth = this.coordSpace.visiblePixelsToWorldUnits(this.htmlDimensionsCacher.clientWidth);
|
276
267
|
|
277
268
|
const width = wToR(page.widthInches);
|
278
269
|
const height = wToR(page.heightInches);
|
279
|
-
const left = Math.max(
|
280
|
-
this.SPACING_IN,
|
281
|
-
(containerWidth - page.widthInches) / 2,
|
282
|
-
);
|
270
|
+
const left = Math.max(this.SPACING_IN, (containerWidth - page.widthInches) / 2);
|
283
271
|
const top = this.pageTops[page.index];
|
284
272
|
|
285
273
|
const transform = `translate(${wToR(left)}px, ${wToR(top)}px)`;
|
286
|
-
const pageContainerEl = this.createPageContainer(page)
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
274
|
+
const pageContainerEl = this.createPageContainer(page)
|
275
|
+
.update({
|
276
|
+
dimensions: {
|
277
|
+
width,
|
278
|
+
height,
|
279
|
+
top: 0,
|
280
|
+
left: 0,
|
281
|
+
},
|
282
|
+
reduce: page.width / wToV(page.widthInches),
|
283
|
+
}).$container[0];
|
295
284
|
|
296
285
|
pageContainerEl.style.transform = transform;
|
297
|
-
pageContainerEl.classList.toggle(
|
298
|
-
'BRpage-visible',
|
299
|
-
this.visiblePages.includes(page),
|
300
|
-
);
|
286
|
+
pageContainerEl.classList.toggle('BRpage-visible', this.visiblePages.includes(page));
|
301
287
|
return pageContainerEl;
|
302
|
-
}
|
288
|
+
}
|
303
289
|
|
304
290
|
/************** VIRTUAL SCROLLING LOGIC **************/
|
305
291
|
|
@@ -320,7 +306,7 @@ export class Mode1UpLit extends LitElement {
|
|
320
306
|
left: vToW(scrollLeft),
|
321
307
|
width: vToW(clientWidth),
|
322
308
|
};
|
323
|
-
}
|
309
|
+
}
|
324
310
|
|
325
311
|
/**
|
326
312
|
* @returns {PageModel[]}
|
@@ -328,26 +314,20 @@ export class Mode1UpLit extends LitElement {
|
|
328
314
|
computeRenderedPages() {
|
329
315
|
// Also render 1 page before/after
|
330
316
|
// @ts-ignore TS doesn't understand the filtering out of null values
|
331
|
-
return
|
332
|
-
[
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
.slice(0, 10)
|
340
|
-
);
|
317
|
+
return [
|
318
|
+
this.visiblePages[0]?.prev,
|
319
|
+
...this.visiblePages,
|
320
|
+
this.visiblePages[this.visiblePages.length - 1]?.next,
|
321
|
+
]
|
322
|
+
.filter(p => p)
|
323
|
+
// Never render more than 10 pages! Usually means something is wrong
|
324
|
+
.slice(0, 10);
|
341
325
|
}
|
342
326
|
|
343
|
-
throttledUpdateRenderedPages = throttle(
|
344
|
-
()
|
345
|
-
|
346
|
-
|
347
|
-
},
|
348
|
-
100,
|
349
|
-
null,
|
350
|
-
);
|
327
|
+
throttledUpdateRenderedPages = throttle(() => {
|
328
|
+
this.renderedPages = this.computeRenderedPages();
|
329
|
+
this.requestUpdate();
|
330
|
+
}, 100, null)
|
351
331
|
|
352
332
|
/**
|
353
333
|
* @param {PageModel[]} pages
|
@@ -370,29 +350,21 @@ export class Mode1UpLit extends LitElement {
|
|
370
350
|
*/
|
371
351
|
computeDefaultScale(page) {
|
372
352
|
// Default to real size if it fits, otherwise default to full width
|
373
|
-
const containerWidthIn = this.coordSpace.renderedPixelsToWorldUnits(
|
374
|
-
|
375
|
-
);
|
376
|
-
return (
|
377
|
-
Math.min(
|
378
|
-
1,
|
379
|
-
containerWidthIn / (page.widthInches + 2 * this.SPACING_IN),
|
380
|
-
) || 1
|
381
|
-
);
|
353
|
+
const containerWidthIn = this.coordSpace.renderedPixelsToWorldUnits(this.clientWidth);
|
354
|
+
return Math.min(1, containerWidthIn / (page.widthInches + 2 * this.SPACING_IN)) || 1;
|
382
355
|
}
|
383
356
|
|
384
357
|
computeWorldDimensions() {
|
385
358
|
return {
|
386
|
-
width:
|
387
|
-
Math.max(...this.pages.map((p) => p.widthInches)) + 2 * this.SPACING_IN,
|
359
|
+
width: Math.max(...this.pages.map(p => p.widthInches)) + 2 * this.SPACING_IN,
|
388
360
|
height:
|
389
|
-
|
390
|
-
|
361
|
+
sum(this.pages.map(p => p.heightInches)) +
|
362
|
+
(this.pages.length + 1) * this.SPACING_IN,
|
391
363
|
};
|
392
364
|
}
|
393
365
|
|
394
366
|
computeVisiblePages() {
|
395
|
-
return this.pages.filter(
|
367
|
+
return this.pages.filter(page => {
|
396
368
|
const PT = this.pageTops[page.index];
|
397
369
|
const PB = PT + page.heightInches;
|
398
370
|
|
@@ -405,14 +377,12 @@ export class Mode1UpLit extends LitElement {
|
|
405
377
|
/************** INPUT HANDLERS **************/
|
406
378
|
|
407
379
|
attachScrollListeners = () => {
|
408
|
-
this.addEventListener(
|
380
|
+
this.addEventListener("scroll", this.updateVisibleRegion);
|
409
381
|
this.scrollClassAdder.attach();
|
410
|
-
}
|
382
|
+
}
|
411
383
|
|
412
384
|
detachScrollListeners = () => {
|
413
|
-
this.removeEventListener(
|
385
|
+
this.removeEventListener("scroll", this.updateVisibleRegion);
|
414
386
|
this.scrollClassAdder.detach();
|
415
|
-
}
|
387
|
+
}
|
416
388
|
}
|
417
|
-
|
418
|
-
customElements.define('br-mode-1up', Mode1UpLit);
|
@@ -16,6 +16,7 @@ import { ModeCoordinateSpace } from './ModeCoordinateSpace';
|
|
16
16
|
// I _have_ to make this globally public, otherwise it won't let me call
|
17
17
|
// its constructor :/
|
18
18
|
/** @implements {SmoothZoomable} */
|
19
|
+
@customElement('br-mode-2up')
|
19
20
|
export class Mode2UpLit extends LitElement {
|
20
21
|
/****************************************/
|
21
22
|
/************** PROPERTIES **************/
|
@@ -492,13 +493,14 @@ export class Mode2UpLit extends LitElement {
|
|
492
493
|
/**
|
493
494
|
* @param {'left' | 'right' | 'next' | 'prev' | PageIndex | PageModel | {left: PageModel | null, right: PageModel | null}} nextSpread
|
494
495
|
*/
|
495
|
-
async flipAnimation(nextSpread, { animate = true } = {}) {
|
496
|
+
async flipAnimation(nextSpread, { animate = true, flipSpeed = this.flipSpeed } = {}) {
|
496
497
|
const curSpread = (this.pageLeft || this.pageRight)?.spread;
|
497
498
|
if (!curSpread) {
|
498
499
|
// Nothings been actually rendered yet! Will be corrected during initFirstRender
|
499
500
|
return;
|
500
501
|
}
|
501
502
|
|
503
|
+
flipSpeed = flipSpeed || this.flipSpeed; // Handle null
|
502
504
|
nextSpread = this.parseNextSpread(nextSpread);
|
503
505
|
if (this.activeFlip || !nextSpread) return;
|
504
506
|
|
@@ -558,7 +560,7 @@ export class Mode2UpLit extends LitElement {
|
|
558
560
|
|
559
561
|
/** @type {KeyframeAnimationOptions} */
|
560
562
|
const animationStyle = {
|
561
|
-
duration:
|
563
|
+
duration: flipSpeed + this.activeFlip.pagesFlippingCount,
|
562
564
|
easing: 'ease-in',
|
563
565
|
fill: 'none',
|
564
566
|
};
|
@@ -675,6 +677,7 @@ export class Mode2UpLit extends LitElement {
|
|
675
677
|
}
|
676
678
|
}
|
677
679
|
|
680
|
+
@customElement('br-leaf-edges')
|
678
681
|
export class LeafEdges extends LitElement {
|
679
682
|
@property({ type: Number }) leftIndex = 0;
|
680
683
|
@property({ type: Number }) rightIndex = 0;
|
@@ -772,6 +775,3 @@ export class LeafEdges extends LitElement {
|
|
772
775
|
return Math.floor(this.leftIndex + (e.offsetX / this.offsetWidth) * (this.rightIndex - this.leftIndex + 1));
|
773
776
|
}
|
774
777
|
}
|
775
|
-
|
776
|
-
customElements.define('br-mode-2up', Mode2UpLit);
|
777
|
-
customElements.define('br-leaf-edges', LeafEdges);
|
@@ -138,16 +138,43 @@ export class Navbar {
|
|
138
138
|
* Switch navbar controls on mobile and desktop
|
139
139
|
*/
|
140
140
|
switchNavbarControls() {
|
141
|
-
|
142
|
-
|
143
|
-
|
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') {
|
144
145
|
this.showMinimumNavbarControls();
|
145
|
-
}
|
146
|
+
}
|
147
|
+
} else {
|
148
|
+
this.showMaximumNavPageNum();
|
149
|
+
// we don't want navbar controls switching with liner-notes
|
150
|
+
if (this.br.options.bookType !== 'linerNotes') {
|
146
151
|
this.showMaximumNavbarControls();
|
147
152
|
}
|
148
153
|
}
|
149
154
|
}
|
150
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
|
+
|
151
178
|
/**
|
152
179
|
* Switch Book Navbar controls to minimised
|
153
180
|
* NOTE: only `this.minimumControls` and `this.maximumControls` switch on resize
|
@@ -203,7 +230,10 @@ export class Navbar {
|
|
203
230
|
<div class="BRpager"></div>
|
204
231
|
<div class="BRnavline"></div>
|
205
232
|
</div>
|
206
|
-
<p
|
233
|
+
<p>
|
234
|
+
<span class="BRcurrentpage BRmax"></span>
|
235
|
+
<span class="BRcurrentpage BRmin"></span>
|
236
|
+
</p>
|
207
237
|
</li>
|
208
238
|
${this._renderControls()}
|
209
239
|
</ul>
|
@@ -246,9 +276,10 @@ export class Navbar {
|
|
246
276
|
/**
|
247
277
|
* Returns the textual representation of the current page for the navbar
|
248
278
|
* @param {number} index
|
279
|
+
* @param {boolean} [useMaxFormat = false]
|
249
280
|
* @return {string}
|
250
281
|
*/
|
251
|
-
getNavPageNumString(index) {
|
282
|
+
getNavPageNumString(index, useMaxFormat = false) {
|
252
283
|
const { br } = this;
|
253
284
|
// Accessible index starts at 0 (alas) so we add 1 to make human
|
254
285
|
const pageNum = br.book.getPageNum(index);
|
@@ -268,7 +299,8 @@ export class Navbar {
|
|
268
299
|
this.maxPageNum = maxPageNum;
|
269
300
|
}
|
270
301
|
|
271
|
-
return getNavPageNumHtml(index, numLeafs, pageNum, pageType, this.maxPageNum);
|
302
|
+
return getNavPageNumHtml(index, numLeafs, pageNum, pageType, this.maxPageNum, useMaxFormat);
|
303
|
+
|
272
304
|
}
|
273
305
|
|
274
306
|
/**
|
@@ -276,7 +308,8 @@ export class Navbar {
|
|
276
308
|
* @param {number} index
|
277
309
|
*/
|
278
310
|
updateNavPageNum(index) {
|
279
|
-
this.$root.find('.BRcurrentpage').html(this.getNavPageNumString(index));
|
311
|
+
this.$root.find('.BRcurrentpage.BRmax').html(this.getNavPageNumString(index, true));
|
312
|
+
this.$root.find('.BRcurrentpage.BRmin').html(this.getNavPageNumString(index));
|
280
313
|
}
|
281
314
|
|
282
315
|
/**
|
@@ -298,14 +331,23 @@ export class Navbar {
|
|
298
331
|
* @param {number|string} pageNum
|
299
332
|
* @param {*} pageType - Deprecated
|
300
333
|
* @param {number} maxPageNum
|
334
|
+
* @param {boolean} [useMaxFormat = false]
|
301
335
|
* @return {string}
|
302
336
|
*/
|
303
|
-
export function getNavPageNumHtml(index, numLeafs, pageNum, pageType, maxPageNum) {
|
337
|
+
export function getNavPageNumHtml(index, numLeafs, pageNum, pageType, maxPageNum, useMaxFormat = false) {
|
304
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
|
+
}
|
305
348
|
|
306
349
|
if (!pageIsAsserted) {
|
307
|
-
|
308
|
-
return `(${pageIndex} of ${numLeafs})`; // Page (8 of 10)
|
350
|
+
return `(${pageIndex} of ${numLeafs})`;
|
309
351
|
}
|
310
352
|
|
311
353
|
const bookLengthLabel = (maxPageNum && parseFloat(pageNum)) ? ` of ${maxPageNum}` : '';
|