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