@internetarchive/bookreader 5.0.0-94 → 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/CHANGELOG.md +7 -0
- package/README.md +0 -2
- package/package.json +1 -1
- package/scripts/version.js +0 -3
- package/BookReader/BookReader.css +0 -2251
- 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/hypothesis.ico +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.experiments.js +0 -3
- package/BookReader/plugins/plugin.experiments.js.LICENSE.txt +0 -1
- package/BookReader/plugins/plugin.experiments.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 -564
- package/src/BookReader/DragScrollable.js +0 -233
- package/src/BookReader/ImageCache.js +0 -149
- package/src/BookReader/Mode1Up.js +0 -110
- package/src/BookReader/Mode1UpLit.js +0 -388
- package/src/BookReader/Mode2Up.js +0 -107
- 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 -344
- package/src/BookReader/Navbar/Navbar.js +0 -355
- package/src/BookReader/PageContainer.js +0 -172
- 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 -387
- 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 -313
- 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 -249
- 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
@@ -1,777 +0,0 @@
|
|
1
|
-
// @ts-check
|
2
|
-
import { customElement, property, query } from 'lit/decorators.js';
|
3
|
-
import {LitElement, html} from 'lit';
|
4
|
-
import { styleMap } from 'lit/directives/style-map.js';
|
5
|
-
import { ModeSmoothZoom } from './ModeSmoothZoom.js';
|
6
|
-
import { arrChanged, promisifyEvent } from './utils.js';
|
7
|
-
import { HTMLDimensionsCacher } from "./utils/HTMLDimensionsCacher.js";
|
8
|
-
import { PageModel } from './BookModel.js';
|
9
|
-
import { ModeCoordinateSpace } from './ModeCoordinateSpace.js';
|
10
|
-
/** @typedef {import('./BookModel').BookModel} BookModel */
|
11
|
-
/** @typedef {import('./BookModel').PageIndex} PageIndex */
|
12
|
-
/** @typedef {import('./ModeSmoothZoom').SmoothZoomable} SmoothZoomable */
|
13
|
-
/** @typedef {import('./PageContainer').PageContainer} PageContainer */
|
14
|
-
/** @typedef {import('../BookReader').default} BookReader */
|
15
|
-
|
16
|
-
// I _have_ to make this globally public, otherwise it won't let me call
|
17
|
-
// its constructor :/
|
18
|
-
/** @implements {SmoothZoomable} */
|
19
|
-
@customElement('br-mode-2up')
|
20
|
-
export class Mode2UpLit extends LitElement {
|
21
|
-
/****************************************/
|
22
|
-
/************** PROPERTIES **************/
|
23
|
-
/****************************************/
|
24
|
-
|
25
|
-
/** @type {BookReader} */
|
26
|
-
br;
|
27
|
-
|
28
|
-
/************** BOOK-RELATED PROPERTIES **************/
|
29
|
-
|
30
|
-
/** @type {BookModel} */
|
31
|
-
@property({ type: Object })
|
32
|
-
book;
|
33
|
-
|
34
|
-
/************** SCALE-RELATED PROPERTIES **************/
|
35
|
-
|
36
|
-
/** @type {ModeCoordinateSpace} Manage conversion between coordinates */
|
37
|
-
coordSpace = new ModeCoordinateSpace(this);
|
38
|
-
|
39
|
-
@property({ type: Number })
|
40
|
-
scale = 1;
|
41
|
-
|
42
|
-
initialScale = 1;
|
43
|
-
|
44
|
-
/** @type {import('./options').AutoFitValues} */
|
45
|
-
@property({ type: String })
|
46
|
-
autoFit = 'auto';
|
47
|
-
|
48
|
-
/************** VIRTUAL-FLIPPING PROPERTIES **************/
|
49
|
-
|
50
|
-
/** ms for flip animation */
|
51
|
-
flipSpeed = 400;
|
52
|
-
|
53
|
-
@query('.br-mode-2up__leafs--flipping') $flippingEdges;
|
54
|
-
|
55
|
-
/** @type {PageModel[]} */
|
56
|
-
@property({ type: Array, hasChanged: arrChanged })
|
57
|
-
visiblePages = [];
|
58
|
-
|
59
|
-
/** @type {PageModel | null} */
|
60
|
-
get pageLeft() {
|
61
|
-
return this.visiblePages.find(p => p.pageSide == 'L');
|
62
|
-
}
|
63
|
-
|
64
|
-
/** @type {PageModel | null} */
|
65
|
-
get pageRight() {
|
66
|
-
return this.visiblePages.find(p => p.pageSide == 'R');
|
67
|
-
}
|
68
|
-
|
69
|
-
/** @type {PageModel[]} */
|
70
|
-
@property({ type: Array })
|
71
|
-
renderedPages = [];
|
72
|
-
|
73
|
-
/** @type {Record<PageIndex, PageContainer>} position in inches */
|
74
|
-
pageContainerCache = {};
|
75
|
-
|
76
|
-
/** @type {{ direction: 'left' | 'right', pagesFlipping: [PageIndex, PageIndex], pagesFlippingCount: number }} */
|
77
|
-
activeFlip = null;
|
78
|
-
|
79
|
-
/** @private cache this value */
|
80
|
-
_leftCoverWidth = 0;
|
81
|
-
|
82
|
-
/************** DOM-RELATED PROPERTIES **************/
|
83
|
-
|
84
|
-
/** @type {HTMLElement} */
|
85
|
-
get $container() { return this; }
|
86
|
-
|
87
|
-
/** @type {HTMLElement} */
|
88
|
-
get $visibleWorld() { return this.$book; }
|
89
|
-
|
90
|
-
/** @type {HTMLElement} */
|
91
|
-
@query('.br-mode-2up__book')
|
92
|
-
$book;
|
93
|
-
|
94
|
-
get positions() {
|
95
|
-
return this.computePositions(this.pageLeft, this.pageRight);
|
96
|
-
}
|
97
|
-
|
98
|
-
/** @param {PageModel} page */
|
99
|
-
computePageHeight(page) {
|
100
|
-
return this.book.getMedianPageSizeInches().height;
|
101
|
-
}
|
102
|
-
|
103
|
-
/** @param {PageModel} page */
|
104
|
-
computePageWidth(page) {
|
105
|
-
return page.widthInches * this.computePageHeight(page) / page.heightInches;
|
106
|
-
}
|
107
|
-
|
108
|
-
/**
|
109
|
-
* @param {PageModel | null} pageLeft
|
110
|
-
* @param {PageModel | null} pageRight
|
111
|
-
*/
|
112
|
-
computePositions(pageLeft, pageRight) {
|
113
|
-
const computePageWidth = this.computePageWidth.bind(this);
|
114
|
-
const numLeafs = this.book.getNumLeafs();
|
115
|
-
const movingPagesWidth = this.activeFlip ? Math.ceil(this.activeFlip.pagesFlippingCount / 2) * this.PAGE_THICKNESS_IN : 0;
|
116
|
-
const leftPagesCount = this.book.pageProgression == 'lr' ? (pageLeft?.index ?? 0) : (!pageLeft ? 0 : numLeafs - pageLeft.index);
|
117
|
-
|
118
|
-
// Everything is relative to the gutter
|
119
|
-
const gutter = this._leftCoverWidth + leftPagesCount * this.PAGE_THICKNESS_IN;
|
120
|
-
|
121
|
-
const pageLeftEnd = gutter;
|
122
|
-
const pageLeftWidth = !pageLeft ? computePageWidth(pageRight.right) : computePageWidth(pageLeft);
|
123
|
-
const pageLeftStart = gutter - pageLeftWidth;
|
124
|
-
|
125
|
-
const leafEdgesLeftEnd = pageLeftStart; // leafEdgesLeftStart + leafEdgesLeftMainWidth + leafEdgesLeftMovingWidth;
|
126
|
-
const leafEdgesLeftMovingWidth = this.activeFlip?.direction != 'left' ? 0 : movingPagesWidth;
|
127
|
-
const leafEdgesLeftMainWidth = Math.ceil(leftPagesCount / 2) * this.PAGE_THICKNESS_IN - leafEdgesLeftMovingWidth;
|
128
|
-
const leafEdgesLeftFullWidth = leafEdgesLeftMovingWidth + leafEdgesLeftMainWidth;
|
129
|
-
const leafEdgesLeftMovingStart = leafEdgesLeftEnd - leafEdgesLeftMovingWidth;
|
130
|
-
const leafEdgesLeftStart = leafEdgesLeftMovingStart - leafEdgesLeftMainWidth;
|
131
|
-
|
132
|
-
const pageRightStart = gutter;
|
133
|
-
const pageRightWidth = !pageRight ? 0 : computePageWidth(pageRight);
|
134
|
-
const pageRightEnd = pageRightStart + pageRightWidth;
|
135
|
-
|
136
|
-
const rightPagesCount = this.book.pageProgression == 'lr' ? (!pageRight ? 0 : numLeafs - pageRight.index) : (pageRight?.index ?? 0);
|
137
|
-
const leafEdgesRightStart = pageRightEnd;
|
138
|
-
const leafEdgesRightMovingWidth = this.activeFlip?.direction != 'right' ? 0 : movingPagesWidth;
|
139
|
-
const leafEdgesRightMainStart = leafEdgesRightStart + leafEdgesRightMovingWidth;
|
140
|
-
const leafEdgesRightMainWidth = Math.ceil(rightPagesCount / 2) * this.PAGE_THICKNESS_IN - leafEdgesRightMovingWidth;
|
141
|
-
const leafEdgesRightEnd = leafEdgesRightStart + leafEdgesRightMainWidth + leafEdgesRightMovingWidth;
|
142
|
-
const leafEdgesRightFullWidth = leafEdgesRightMovingWidth + leafEdgesRightMainWidth;
|
143
|
-
|
144
|
-
const spreadWidth = pageRightEnd - pageLeftStart;
|
145
|
-
const bookWidth = leafEdgesRightEnd - leafEdgesLeftStart;
|
146
|
-
return {
|
147
|
-
leafEdgesLeftStart,
|
148
|
-
leafEdgesLeftMainWidth,
|
149
|
-
leafEdgesLeftMovingStart,
|
150
|
-
leafEdgesLeftMovingWidth,
|
151
|
-
leafEdgesLeftEnd,
|
152
|
-
leafEdgesLeftFullWidth,
|
153
|
-
|
154
|
-
pageLeftStart,
|
155
|
-
pageLeftWidth,
|
156
|
-
pageLeftEnd,
|
157
|
-
|
158
|
-
gutter,
|
159
|
-
|
160
|
-
pageRightStart,
|
161
|
-
pageRightWidth,
|
162
|
-
pageRightEnd,
|
163
|
-
|
164
|
-
leafEdgesRightStart,
|
165
|
-
leafEdgesRightMovingWidth,
|
166
|
-
leafEdgesRightMainStart,
|
167
|
-
leafEdgesRightMainWidth,
|
168
|
-
leafEdgesRightEnd,
|
169
|
-
leafEdgesRightFullWidth,
|
170
|
-
|
171
|
-
spreadWidth,
|
172
|
-
bookWidth,
|
173
|
-
};
|
174
|
-
}
|
175
|
-
|
176
|
-
/** @type {HTMLDimensionsCacher} Cache things like clientWidth to reduce repaints */
|
177
|
-
htmlDimensionsCacher = new HTMLDimensionsCacher(this);
|
178
|
-
|
179
|
-
smoothZoomer = new ModeSmoothZoom(this);
|
180
|
-
|
181
|
-
/************** CONSTANT PROPERTIES **************/
|
182
|
-
|
183
|
-
/** How much to zoom when zoom button pressed */
|
184
|
-
ZOOM_FACTOR = 1.1;
|
185
|
-
|
186
|
-
/** How thick a page is in the real world, as an estimate for the leafs */
|
187
|
-
PAGE_THICKNESS_IN = 0.002;
|
188
|
-
|
189
|
-
/****************************************/
|
190
|
-
/************** PUBLIC API **************/
|
191
|
-
/****************************************/
|
192
|
-
|
193
|
-
/************** MAIN PUBLIC METHODS **************/
|
194
|
-
|
195
|
-
/**
|
196
|
-
* @param {PageIndex} index
|
197
|
-
* TODO Remove smooth option from everywhere.
|
198
|
-
*/
|
199
|
-
async jumpToIndex(index, { smooth = true } = {}) {
|
200
|
-
await this.flipAnimation(index, { animate: smooth });
|
201
|
-
}
|
202
|
-
|
203
|
-
zoomIn() {
|
204
|
-
this.scale *= this.ZOOM_FACTOR;
|
205
|
-
}
|
206
|
-
|
207
|
-
zoomOut() {
|
208
|
-
this.scale *= 1 / this.ZOOM_FACTOR;
|
209
|
-
}
|
210
|
-
|
211
|
-
/********************************************/
|
212
|
-
/************** INTERNAL STUFF **************/
|
213
|
-
/********************************************/
|
214
|
-
|
215
|
-
/************** LIFE CYCLE **************/
|
216
|
-
|
217
|
-
/**
|
218
|
-
* @param {BookModel} book
|
219
|
-
* @param {BookReader} br
|
220
|
-
*/
|
221
|
-
constructor(book, br) {
|
222
|
-
super();
|
223
|
-
this.book = book;
|
224
|
-
|
225
|
-
/** @type {BookReader} */
|
226
|
-
this.br = br;
|
227
|
-
}
|
228
|
-
|
229
|
-
/** @override */
|
230
|
-
firstUpdated(changedProps) {
|
231
|
-
super.firstUpdated(changedProps);
|
232
|
-
this.htmlDimensionsCacher.updateClientSizes();
|
233
|
-
this.smoothZoomer.attach();
|
234
|
-
}
|
235
|
-
|
236
|
-
/** @override */
|
237
|
-
connectedCallback() {
|
238
|
-
super.connectedCallback();
|
239
|
-
this.htmlDimensionsCacher.attachResizeListener();
|
240
|
-
this.smoothZoomer.attach();
|
241
|
-
}
|
242
|
-
|
243
|
-
/** @override */
|
244
|
-
disconnectedCallback() {
|
245
|
-
this.htmlDimensionsCacher.detachResizeListener();
|
246
|
-
this.smoothZoomer.detach();
|
247
|
-
super.disconnectedCallback();
|
248
|
-
}
|
249
|
-
|
250
|
-
/** @override */
|
251
|
-
updated(changedProps) {
|
252
|
-
// this.X is the new value
|
253
|
-
// changedProps.get('X') is the old value
|
254
|
-
if (changedProps.has('book')) {
|
255
|
-
this._leftCoverWidth = this.computePageWidth(this.book.getPage(this.book.pageProgression == 'lr' ? 0 : -1));
|
256
|
-
}
|
257
|
-
if (changedProps.has('visiblePages')) {
|
258
|
-
this.renderedPages = this.computeRenderedPages();
|
259
|
-
this.br.displayedIndices = this.visiblePages.map(p => p.index);
|
260
|
-
this.br.updateFirstIndex(this.br.displayedIndices[0]);
|
261
|
-
this.br._components.navbar.updateNavIndexThrottled();
|
262
|
-
}
|
263
|
-
if (changedProps.has('autoFit')) {
|
264
|
-
if (this.autoFit != 'none') {
|
265
|
-
this.resizeViaAutofit();
|
266
|
-
}
|
267
|
-
}
|
268
|
-
if (changedProps.has('scale')) {
|
269
|
-
const oldVal = changedProps.get('scale');
|
270
|
-
this.recenter();
|
271
|
-
this.smoothZoomer.updateViewportOnZoom(this.scale, oldVal);
|
272
|
-
}
|
273
|
-
}
|
274
|
-
|
275
|
-
/************** LIT CONFIGS **************/
|
276
|
-
|
277
|
-
/** @override */
|
278
|
-
createRenderRoot() {
|
279
|
-
// Disable shadow DOM; that would require a huge rejiggering of CSS
|
280
|
-
return this;
|
281
|
-
}
|
282
|
-
|
283
|
-
/************** RENDERING **************/
|
284
|
-
|
285
|
-
/** @override */
|
286
|
-
render() {
|
287
|
-
return html`
|
288
|
-
<div class="br-mode-2up__book" @mouseup=${this.handlePageClick}>
|
289
|
-
${this.renderLeafEdges('left')}
|
290
|
-
${this.renderedPages.map(p => this.renderPage(p))}
|
291
|
-
${this.renderLeafEdges('right')}
|
292
|
-
</div>`;
|
293
|
-
}
|
294
|
-
|
295
|
-
/** @param {PageModel} page */
|
296
|
-
createPageContainer = (page) => {
|
297
|
-
return this.pageContainerCache[page.index] || (
|
298
|
-
this.pageContainerCache[page.index] = (
|
299
|
-
// @ts-ignore I know it's protected, TS! But Mode2Up and BookReader are friends.
|
300
|
-
this.br._createPageContainer(page.index)
|
301
|
-
)
|
302
|
-
);
|
303
|
-
}
|
304
|
-
|
305
|
-
/**
|
306
|
-
* @param {PageIndex} startIndex
|
307
|
-
*/
|
308
|
-
initFirstRender(startIndex) {
|
309
|
-
const page = this.book.getPage(startIndex);
|
310
|
-
const spread = page.spread;
|
311
|
-
this.visiblePages = (
|
312
|
-
this.book.pageProgression == 'lr' ? [spread.left, spread.right] : [spread.right, spread.left]
|
313
|
-
).filter(p => p);
|
314
|
-
this.htmlDimensionsCacher.updateClientSizes();
|
315
|
-
this.resizeViaAutofit(page);
|
316
|
-
this.initialScale = this.scale;
|
317
|
-
}
|
318
|
-
|
319
|
-
/** @param {PageModel} page */
|
320
|
-
renderPage = (page) => {
|
321
|
-
const wToR = this.coordSpace.worldUnitsToRenderedPixels;
|
322
|
-
const wToV = this.coordSpace.worldUnitsToVisiblePixels;
|
323
|
-
|
324
|
-
const width = wToR(this.computePageWidth(page));
|
325
|
-
const height = wToR(this.computePageHeight(page));
|
326
|
-
const isVisible = this.visiblePages.map(p => p.index).includes(page.index);
|
327
|
-
const positions = this.computePositions(page.spread.left, page.spread.right);
|
328
|
-
|
329
|
-
const pageContainerEl = this.createPageContainer(page)
|
330
|
-
.update({
|
331
|
-
dimensions: {
|
332
|
-
width,
|
333
|
-
height,
|
334
|
-
top: 0,
|
335
|
-
left: wToR(page.pageSide == 'L' ? positions.pageLeftStart : positions.pageLeftEnd),
|
336
|
-
},
|
337
|
-
reduce: page.width / wToV(this.computePageWidth(page)),
|
338
|
-
}).$container[0];
|
339
|
-
|
340
|
-
pageContainerEl.classList.toggle('BRpage-visible', isVisible);
|
341
|
-
return pageContainerEl;
|
342
|
-
}
|
343
|
-
|
344
|
-
/**
|
345
|
-
* @param {'left' | 'right'} side
|
346
|
-
* Renders the current leaf edges, as well as any "moving" leaf edges,
|
347
|
-
* i.e. leaf edges that are currently being flipped. Uses a custom element
|
348
|
-
* to render br-leaf-edges.
|
349
|
-
**/
|
350
|
-
renderLeafEdges = (side) => {
|
351
|
-
if (!this.visiblePages.length) return html``;
|
352
|
-
const fullWidthIn = side == 'left' ? this.positions.leafEdgesLeftFullWidth : this.positions.leafEdgesRightFullWidth;
|
353
|
-
if (!fullWidthIn) return html``;
|
354
|
-
|
355
|
-
const wToR = this.coordSpace.worldUnitsToRenderedPixels;
|
356
|
-
const height = wToR(this.computePageHeight(this.visiblePages[0]));
|
357
|
-
const hasMovingPages = this.activeFlip?.direction == side;
|
358
|
-
|
359
|
-
const leftmostPage = this.book.getPage(this.book.pageProgression == 'lr' ? 0 : this.book.getNumLeafs() - 1);
|
360
|
-
const rightmostPage = this.book.getPage(this.book.pageProgression == 'lr' ? this.book.getNumLeafs() - 1 : 0);
|
361
|
-
const numPagesFlipping = hasMovingPages ? this.activeFlip.pagesFlippingCount : 0;
|
362
|
-
const range = side == 'left' ?
|
363
|
-
[leftmostPage.index, this.pageLeft.goLeft(numPagesFlipping).index] :
|
364
|
-
[this.pageRight.goRight(numPagesFlipping).index, rightmostPage.index];
|
365
|
-
|
366
|
-
const mainEdgesStyle = {
|
367
|
-
width: `${wToR(side == 'left' ? this.positions.leafEdgesLeftMainWidth : this.positions.leafEdgesRightMainWidth)}px`,
|
368
|
-
height: `${height}px`,
|
369
|
-
left: `${wToR(side == 'left' ? this.positions.leafEdgesLeftStart : this.positions.leafEdgesRightMainStart)}px`,
|
370
|
-
};
|
371
|
-
const mainEdges = html`
|
372
|
-
<br-leaf-edges
|
373
|
-
leftIndex=${range[0]}
|
374
|
-
rightIndex=${range[1]}
|
375
|
-
.book=${this.book}
|
376
|
-
.pageClickHandler=${(index) => this.br.jumpToIndex(index)}
|
377
|
-
side=${side}
|
378
|
-
class="br-mode-2up__leafs br-mode-2up__leafs--${side}"
|
379
|
-
style=${styleMap(mainEdgesStyle)}
|
380
|
-
></br-leaf-edges>
|
381
|
-
`;
|
382
|
-
|
383
|
-
if (hasMovingPages) {
|
384
|
-
const width = wToR(side == 'left' ? this.positions.leafEdgesLeftMovingWidth : this.positions.leafEdgesRightMovingWidth);
|
385
|
-
const style = {
|
386
|
-
width: `${width}px`,
|
387
|
-
height: `${height}px`,
|
388
|
-
left: `${wToR(side == 'left' ? this.positions.leafEdgesLeftMovingStart : this.positions.leafEdgesRightStart)}px`,
|
389
|
-
pointerEvents: 'none',
|
390
|
-
transformOrigin: `${wToR(side == 'left' ? this.positions.pageLeftWidth : -this.positions.pageRightWidth) + width / 2}px 0`,
|
391
|
-
};
|
392
|
-
|
393
|
-
const movingEdges = html`
|
394
|
-
<br-leaf-edges
|
395
|
-
leftIndex=${this.activeFlip.pagesFlipping[0]}
|
396
|
-
rightIndex=${this.activeFlip.pagesFlipping[1]}
|
397
|
-
.book=${this.book}
|
398
|
-
side=${side}
|
399
|
-
class="br-mode-2up__leafs br-mode-2up__leafs--${side} br-mode-2up__leafs--flipping"
|
400
|
-
style=${styleMap(style)}
|
401
|
-
></br-leaf-edges>
|
402
|
-
`;
|
403
|
-
|
404
|
-
return side == 'left' ? html`${mainEdges}${movingEdges}` : html`${movingEdges}${mainEdges}`;
|
405
|
-
} else {
|
406
|
-
return mainEdges;
|
407
|
-
}
|
408
|
-
}
|
409
|
-
|
410
|
-
resizeViaAutofit(page = this.visiblePages[0]) {
|
411
|
-
this.scale = this.computeScale(page, this.autoFit);
|
412
|
-
}
|
413
|
-
|
414
|
-
recenter(page = this.visiblePages[0]) {
|
415
|
-
const translate = this.computeTranslate(page, this.scale);
|
416
|
-
this.$book.style.transform = `translateX(${translate.x}px) translateY(${translate.y}px) scale(${this.scale})`;
|
417
|
-
}
|
418
|
-
|
419
|
-
/**
|
420
|
-
* @returns {PageModel[]}
|
421
|
-
*/
|
422
|
-
computeRenderedPages() {
|
423
|
-
// Also render 2 pages before/after
|
424
|
-
// @ts-ignore TS doesn't understand the filtering out of null values
|
425
|
-
return [
|
426
|
-
this.visiblePages[0]?.prev?.prev,
|
427
|
-
this.visiblePages[0]?.prev,
|
428
|
-
...this.visiblePages,
|
429
|
-
this.visiblePages[this.visiblePages.length - 1]?.next,
|
430
|
-
this.visiblePages[this.visiblePages.length - 1]?.next?.next,
|
431
|
-
]
|
432
|
-
.filter(p => p)
|
433
|
-
// Never render more than 10 pages! Usually means something is wrong
|
434
|
-
.slice(0, 10);
|
435
|
-
}
|
436
|
-
|
437
|
-
/**
|
438
|
-
* @param {PageModel} page
|
439
|
-
* @param {import('./options').AutoFitValues} autoFit
|
440
|
-
*/
|
441
|
-
computeScale(page, autoFit) {
|
442
|
-
if (!page) return 1;
|
443
|
-
const spread = page.spread;
|
444
|
-
const bookWidth = this.computePositions(spread.left, spread.right).bookWidth;
|
445
|
-
const bookHeight = this.computePageHeight(spread.left || spread.right);
|
446
|
-
const BOOK_PADDING_PX = 10;
|
447
|
-
const curScale = this.scale;
|
448
|
-
this.scale = 1; // Need this temporarily
|
449
|
-
const widthScale = this.coordSpace.renderedPixelsToWorldUnits(this.htmlDimensionsCacher.clientWidth - 2 * BOOK_PADDING_PX) / bookWidth;
|
450
|
-
const heightScale = this.coordSpace.renderedPixelsToWorldUnits(this.htmlDimensionsCacher.clientHeight - 2 * BOOK_PADDING_PX) / bookHeight;
|
451
|
-
this.scale = curScale;
|
452
|
-
const realScale = 1;
|
453
|
-
|
454
|
-
let scale = realScale;
|
455
|
-
if (autoFit == 'width') {
|
456
|
-
scale = widthScale;
|
457
|
-
} else if (autoFit == 'height') {
|
458
|
-
scale = heightScale;
|
459
|
-
} else if (autoFit == 'auto') {
|
460
|
-
scale = Math.min(widthScale, heightScale);
|
461
|
-
} else if (autoFit == 'none') {
|
462
|
-
scale = this.scale;
|
463
|
-
} else {
|
464
|
-
// Should be impossible
|
465
|
-
throw new Error(`Invalid autoFit value: ${autoFit}`);
|
466
|
-
}
|
467
|
-
|
468
|
-
return scale;
|
469
|
-
}
|
470
|
-
|
471
|
-
/**
|
472
|
-
* @param {PageModel} page
|
473
|
-
* @param {number} scale
|
474
|
-
* @returns {{x: number, y: number}}
|
475
|
-
*/
|
476
|
-
computeTranslate(page, scale = this.scale) {
|
477
|
-
if (!page) return { x: 0, y: 0 };
|
478
|
-
const spread = page.spread;
|
479
|
-
// Default to real size if it fits, otherwise default to full height
|
480
|
-
const positions = this.computePositions(spread.left, spread.right);
|
481
|
-
const bookWidth = positions.bookWidth;
|
482
|
-
const bookHeight = this.computePageHeight(spread.left || spread.right);
|
483
|
-
const visibleBookWidth = this.coordSpace.worldUnitsToRenderedPixels(bookWidth) * scale;
|
484
|
-
const visibleBookHeight = this.coordSpace.worldUnitsToRenderedPixels(bookHeight) * scale;
|
485
|
-
const leftOffset = this.coordSpace.worldUnitsToRenderedPixels(-positions.leafEdgesLeftStart) * scale;
|
486
|
-
const translateX = (this.htmlDimensionsCacher.clientWidth - visibleBookWidth) / 2 + leftOffset;
|
487
|
-
const translateY = (this.htmlDimensionsCacher.clientHeight - visibleBookHeight) / 2;
|
488
|
-
return { x: Math.max(leftOffset, translateX), y: Math.max(0, translateY) };
|
489
|
-
}
|
490
|
-
|
491
|
-
/************** VIRTUAL FLIPPING LOGIC **************/
|
492
|
-
|
493
|
-
/**
|
494
|
-
* @param {'left' | 'right' | 'next' | 'prev' | PageIndex | PageModel | {left: PageModel | null, right: PageModel | null}} nextSpread
|
495
|
-
*/
|
496
|
-
async flipAnimation(nextSpread, { animate = true, flipSpeed = this.flipSpeed } = {}) {
|
497
|
-
const curSpread = (this.pageLeft || this.pageRight)?.spread;
|
498
|
-
if (!curSpread) {
|
499
|
-
// Nothings been actually rendered yet! Will be corrected during initFirstRender
|
500
|
-
return;
|
501
|
-
}
|
502
|
-
|
503
|
-
flipSpeed = flipSpeed || this.flipSpeed; // Handle null
|
504
|
-
nextSpread = this.parseNextSpread(nextSpread);
|
505
|
-
if (this.activeFlip || !nextSpread) return;
|
506
|
-
|
507
|
-
const progression = this.book.pageProgression;
|
508
|
-
const curLeftIndex = curSpread.left?.index ?? (progression == 'lr' ? -1 : this.book.getNumLeafs());
|
509
|
-
const nextLeftIndex = nextSpread.left?.index ?? (progression == 'lr' ? -1 : this.book.getNumLeafs());
|
510
|
-
if (curLeftIndex == nextLeftIndex) return;
|
511
|
-
|
512
|
-
const renderedIndices = this.renderedPages.map(p => p.index);
|
513
|
-
/** @type {PageContainer[]} */
|
514
|
-
const nextPageContainers = [];
|
515
|
-
for (const page of [nextSpread.left, nextSpread.right]) {
|
516
|
-
if (!page) continue;
|
517
|
-
nextPageContainers.push(this.createPageContainer(page));
|
518
|
-
if (!renderedIndices.includes(page.index)) {
|
519
|
-
this.renderedPages.push(page);
|
520
|
-
}
|
521
|
-
}
|
522
|
-
|
523
|
-
const curTranslate = this.computeTranslate(curSpread.left || curSpread.right, this.scale);
|
524
|
-
const idealNextTranslate = this.computeTranslate(nextSpread.left || nextSpread.right, this.scale);
|
525
|
-
const translateDiff = Math.sqrt((idealNextTranslate.x - curTranslate.x) ** 2 + (idealNextTranslate.y - curTranslate.y) ** 2);
|
526
|
-
let nextTranslate = `translate(${idealNextTranslate.x}px, ${idealNextTranslate.y}px)`;
|
527
|
-
if (translateDiff < 50) {
|
528
|
-
const activeTranslate = this.$book.style.transform.match(/translate\([^)]+\)/)?.[0];
|
529
|
-
if (activeTranslate) {
|
530
|
-
nextTranslate = activeTranslate;
|
531
|
-
}
|
532
|
-
}
|
533
|
-
const newTransform = `${nextTranslate} scale(${this.scale})`;
|
534
|
-
|
535
|
-
if (animate && 'animate' in Element.prototype) {
|
536
|
-
// This table is used to determine the direction of the flip animation:
|
537
|
-
// | < | >
|
538
|
-
// lr | L | R
|
539
|
-
// rl | R | L
|
540
|
-
const direction = progression == 'lr' ? (nextLeftIndex > curLeftIndex ? 'right' : 'left') : (nextLeftIndex > curLeftIndex ? 'left' : 'right');
|
541
|
-
|
542
|
-
this.activeFlip = {
|
543
|
-
direction,
|
544
|
-
pagesFlipping: [curLeftIndex, nextLeftIndex],
|
545
|
-
pagesFlippingCount: Math.abs(nextLeftIndex - curLeftIndex),
|
546
|
-
};
|
547
|
-
|
548
|
-
this.classList.add(`br-mode-2up--flipping-${direction}`);
|
549
|
-
this.classList.add(`BRpageFlipping`);
|
550
|
-
|
551
|
-
// Wait for lit update cycle to finish so that entering pages are rendered
|
552
|
-
this.requestUpdate();
|
553
|
-
await this.updateComplete;
|
554
|
-
|
555
|
-
this.visiblePages
|
556
|
-
.map(p => this.pageContainerCache[p.index].$container)
|
557
|
-
.forEach($c => $c.addClass('BRpage-exiting'));
|
558
|
-
|
559
|
-
nextPageContainers.forEach(c => c.$container.addClass('BRpage-entering'));
|
560
|
-
|
561
|
-
/** @type {KeyframeAnimationOptions} */
|
562
|
-
const animationStyle = {
|
563
|
-
duration: flipSpeed + this.activeFlip.pagesFlippingCount,
|
564
|
-
easing: 'ease-in',
|
565
|
-
fill: 'none',
|
566
|
-
};
|
567
|
-
|
568
|
-
const bookCenteringAnimation = this.$book.animate([
|
569
|
-
{ transform: newTransform },
|
570
|
-
], animationStyle);
|
571
|
-
|
572
|
-
const edgeTranslationAnimation = this.$flippingEdges.animate([
|
573
|
-
{ transform: `rotateY(0deg)` },
|
574
|
-
{
|
575
|
-
transform: direction == 'left' ? `rotateY(-180deg)` : `rotateY(180deg)`,
|
576
|
-
},
|
577
|
-
], animationStyle);
|
578
|
-
|
579
|
-
const exitingPageAnimation = direction == 'left' ?
|
580
|
-
this.querySelector('.BRpage-exiting[data-side=L]').animate([
|
581
|
-
{ transform: `rotateY(0deg)` },
|
582
|
-
{ transform: `rotateY(180deg)` },
|
583
|
-
], animationStyle) : this.querySelector('.BRpage-exiting[data-side=R]').animate([
|
584
|
-
{ transform: `rotateY(0deg)` },
|
585
|
-
{ transform: `rotateY(-180deg)` },
|
586
|
-
], animationStyle);
|
587
|
-
|
588
|
-
const enteringPageAnimation = direction == 'left' ?
|
589
|
-
this.querySelector('.BRpage-entering[data-side=R]').animate([
|
590
|
-
{ transform: `rotateY(-180deg)` },
|
591
|
-
{ transform: `rotateY(0deg)` },
|
592
|
-
], animationStyle) : this.querySelector('.BRpage-entering[data-side=L]').animate([
|
593
|
-
{ transform: `rotateY(180deg)` },
|
594
|
-
{ transform: `rotateY(0deg)` },
|
595
|
-
], animationStyle);
|
596
|
-
|
597
|
-
bookCenteringAnimation.play();
|
598
|
-
edgeTranslationAnimation.play();
|
599
|
-
exitingPageAnimation.play();
|
600
|
-
enteringPageAnimation.play();
|
601
|
-
|
602
|
-
nextPageContainers.forEach(c => c.$container.addClass('BRpage-visible'));
|
603
|
-
|
604
|
-
await Promise.race([
|
605
|
-
promisifyEvent(bookCenteringAnimation, 'finish'),
|
606
|
-
promisifyEvent(edgeTranslationAnimation, 'finish'),
|
607
|
-
promisifyEvent(exitingPageAnimation, 'finish'),
|
608
|
-
promisifyEvent(enteringPageAnimation, 'finish'),
|
609
|
-
]);
|
610
|
-
|
611
|
-
this.classList.remove(`br-mode-2up--flipping-${direction}`);
|
612
|
-
this.classList.remove(`BRpageFlipping`);
|
613
|
-
|
614
|
-
this.visiblePages
|
615
|
-
.map(p => this.pageContainerCache[p.index].$container)
|
616
|
-
.forEach($c => $c.removeClass('BRpage-exiting BRpage-visible'));
|
617
|
-
nextPageContainers.forEach(c => c.$container.removeClass('BRpage-entering'));
|
618
|
-
this.activeFlip = null;
|
619
|
-
}
|
620
|
-
|
621
|
-
this.$book.style.transform = newTransform;
|
622
|
-
this.visiblePages = (
|
623
|
-
progression == 'lr' ? [nextSpread.left, nextSpread.right] : [nextSpread.right, nextSpread.left]
|
624
|
-
).filter(x => x);
|
625
|
-
}
|
626
|
-
|
627
|
-
/**
|
628
|
-
* @param {'left' | 'right' | 'next' | 'prev' | PageIndex | PageModel | {left: PageModel | null, right: PageModel | null}} nextSpread
|
629
|
-
* @returns {{left: PageModel | null, right: PageModel | null}}
|
630
|
-
*/
|
631
|
-
parseNextSpread(nextSpread) {
|
632
|
-
if (nextSpread == 'next') {
|
633
|
-
nextSpread = this.book.pageProgression == 'lr' ? 'right' : 'left';
|
634
|
-
} else if (nextSpread == 'prev') {
|
635
|
-
nextSpread = this.book.pageProgression == 'lr' ? 'left' : 'right';
|
636
|
-
}
|
637
|
-
|
638
|
-
const curSpread = (this.pageLeft || this.pageRight).spread;
|
639
|
-
|
640
|
-
if (nextSpread == 'left') {
|
641
|
-
nextSpread = curSpread.left?.findLeft({ combineConsecutiveUnviewables: true })?.spread;
|
642
|
-
} else if (nextSpread == 'right') {
|
643
|
-
nextSpread = curSpread.right?.findRight({ combineConsecutiveUnviewables: true })?.spread;
|
644
|
-
}
|
645
|
-
|
646
|
-
if (typeof(nextSpread) == 'number') {
|
647
|
-
nextSpread = this.book.getPage(nextSpread).spread;
|
648
|
-
}
|
649
|
-
|
650
|
-
if (nextSpread instanceof PageModel) {
|
651
|
-
nextSpread = nextSpread.spread;
|
652
|
-
}
|
653
|
-
|
654
|
-
return nextSpread;
|
655
|
-
}
|
656
|
-
|
657
|
-
/************** INPUT HANDLERS **************/
|
658
|
-
|
659
|
-
/**
|
660
|
-
* @param {MouseEvent} ev
|
661
|
-
*/
|
662
|
-
handlePageClick = (ev) => {
|
663
|
-
// right click
|
664
|
-
if (ev.which == 3 && this.br.protected) {
|
665
|
-
return false;
|
666
|
-
}
|
667
|
-
|
668
|
-
if (ev.which != 1) return;
|
669
|
-
|
670
|
-
const $page = $(ev.target).closest('.BRpagecontainer');
|
671
|
-
if (!$page.length) return;
|
672
|
-
if ($page.data('side') == 'L') {
|
673
|
-
this.flipAnimation('left');
|
674
|
-
} else if ($page.data('side') == 'R') {
|
675
|
-
this.flipAnimation('right');
|
676
|
-
}
|
677
|
-
}
|
678
|
-
}
|
679
|
-
|
680
|
-
@customElement('br-leaf-edges')
|
681
|
-
export class LeafEdges extends LitElement {
|
682
|
-
@property({ type: Number }) leftIndex = 0;
|
683
|
-
@property({ type: Number }) rightIndex = 0;
|
684
|
-
/** @type {'left' | 'right'} */
|
685
|
-
@property({ type: String }) side = 'left';
|
686
|
-
|
687
|
-
/** @type {BookModel} */
|
688
|
-
@property({attribute: false})
|
689
|
-
book = null;
|
690
|
-
|
691
|
-
/** @type {(index: PageIndex) => void} */
|
692
|
-
@property({attribute: false, type: Function})
|
693
|
-
pageClickHandler = null;
|
694
|
-
|
695
|
-
@query('.br-leaf-edges__bar') $hoverBar;
|
696
|
-
@query('.br-leaf-edges__label') $hoverLabel;
|
697
|
-
|
698
|
-
get pageWidthPercent() {
|
699
|
-
return 100 * 1 / (this.rightIndex - this.leftIndex + 1);
|
700
|
-
}
|
701
|
-
|
702
|
-
render() {
|
703
|
-
return html`
|
704
|
-
<div
|
705
|
-
class="br-leaf-edges__bar"
|
706
|
-
style="${styleMap({width: `${this.pageWidthPercent}%`})}"
|
707
|
-
></div>
|
708
|
-
<div class="br-leaf-edges__label">Page</div>`;
|
709
|
-
}
|
710
|
-
|
711
|
-
connectedCallback() {
|
712
|
-
super.connectedCallback();
|
713
|
-
this.addEventListener('mouseenter', this.onMouseEnter);
|
714
|
-
this.addEventListener('mouseleave', this.onMouseLeave);
|
715
|
-
this.addEventListener('click', this.onClick);
|
716
|
-
}
|
717
|
-
disconnectedCallback() {
|
718
|
-
super.disconnectedCallback();
|
719
|
-
this.addEventListener('mouseenter', this.onMouseEnter);
|
720
|
-
this.removeEventListener('mousemove', this.onMouseMove);
|
721
|
-
this.removeEventListener('mouseleave', this.onMouseLeave);
|
722
|
-
}
|
723
|
-
|
724
|
-
/** @override */
|
725
|
-
createRenderRoot() {
|
726
|
-
// Disable shadow DOM; that would require a huge rejiggering of CSS
|
727
|
-
return this;
|
728
|
-
}
|
729
|
-
|
730
|
-
/**
|
731
|
-
* @param {MouseEvent} e
|
732
|
-
*/
|
733
|
-
onMouseEnter = (e) => {
|
734
|
-
this.addEventListener('mousemove', this.onMouseMove);
|
735
|
-
this.$hoverBar.style.display = 'block';
|
736
|
-
this.$hoverLabel.style.display = 'block';
|
737
|
-
}
|
738
|
-
|
739
|
-
/**
|
740
|
-
* @param {MouseEvent} e
|
741
|
-
*/
|
742
|
-
onMouseMove = (e) => {
|
743
|
-
this.$hoverBar.style.left = `${e.offsetX}px`;
|
744
|
-
if (this.side == 'right') {
|
745
|
-
this.$hoverLabel.style.left = `${e.offsetX}px`;
|
746
|
-
} else {
|
747
|
-
this.$hoverLabel.style.right = `${this.offsetWidth - e.offsetX}px`;
|
748
|
-
}
|
749
|
-
this.$hoverLabel.style.top = `${e.offsetY}px`;
|
750
|
-
const index = this.mouseEventToPageIndex(e);
|
751
|
-
this.$hoverLabel.textContent = this.book.getPageName(index);
|
752
|
-
}
|
753
|
-
|
754
|
-
/**
|
755
|
-
* @param {MouseEvent} e
|
756
|
-
*/
|
757
|
-
onMouseLeave = (e) => {
|
758
|
-
this.removeEventListener('mousemove', this.onMouseMove);
|
759
|
-
this.$hoverBar.style.display = 'none';
|
760
|
-
this.$hoverLabel.style.display = 'none';
|
761
|
-
}
|
762
|
-
|
763
|
-
/**
|
764
|
-
* @param {MouseEvent} e
|
765
|
-
*/
|
766
|
-
onClick = (e) => {
|
767
|
-
this.pageClickHandler(this.mouseEventToPageIndex(e));
|
768
|
-
}
|
769
|
-
|
770
|
-
/**
|
771
|
-
* @param {MouseEvent} e
|
772
|
-
* @returns {PageIndex}
|
773
|
-
*/
|
774
|
-
mouseEventToPageIndex(e) {
|
775
|
-
return Math.floor(this.leftIndex + (e.offsetX / this.offsetWidth) * (this.rightIndex - this.leftIndex + 1));
|
776
|
-
}
|
777
|
-
}
|