@internetarchive/bookreader 5.0.0-5 → 5.0.0-50-a1
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/.eslintrc.js +17 -15
- package/.github/workflows/node.js.yml +77 -6
- package/.github/workflows/npm-publish.yml +6 -20
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +131 -339
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.LICENSE.txt +24 -0
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +1493 -0
- package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +17 -0
- package/BookReader/ia-bookreader-bundle.js.map +1 -0
- package/BookReader/icons/close-circle-dark.svg +1 -0
- package/BookReader/icons/magnify-minus.svg +1 -1
- package/BookReader/icons/magnify-plus.svg +1 -1
- package/BookReader/icons/pause.svg +1 -1
- package/BookReader/icons/playback-speed.svg +1 -1
- package/BookReader/icons/read-aloud.svg +1 -1
- package/BookReader/icons/voice.svg +1 -0
- package/BookReader/images/BRicons.svg +2 -2
- package/BookReader/images/books_graphic.svg +1 -1
- package/BookReader/images/icon_book.svg +1 -1
- package/BookReader/images/icon_gear.svg +1 -1
- package/BookReader/images/icon_info.svg +1 -1
- package/BookReader/images/icon_playback-rate.svg +1 -1
- package/BookReader/images/icon_search_button.svg +1 -1
- package/BookReader/images/icon_share.svg +1 -1
- package/BookReader/images/icon_speaker.svg +1 -1
- package/BookReader/images/icon_speaker_open.svg +1 -1
- package/BookReader/images/marker_chap-off.svg +1 -1
- package/BookReader/images/marker_chap-on.svg +1 -1
- package/BookReader/images/marker_srch-on.svg +1 -1
- package/BookReader/jquery-3.js +2 -0
- package/BookReader/jquery-3.js.LICENSE.txt +24 -0
- 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.chapters.js +1 -1
- package/BookReader/plugins/plugin.chapters.js.map +1 -1
- package/BookReader/plugins/plugin.iframe.js +1 -1
- package/BookReader/plugins/plugin.iframe.js.map +1 -1
- package/BookReader/plugins/plugin.mobile_nav.js +1 -1
- package/BookReader/plugins/plugin.mobile_nav.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/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
- package/BookReader/webcomponents-bundle.js +3 -0
- package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
- package/BookReader/webcomponents-bundle.js.map +1 -0
- package/BookReaderDemo/BookReaderDemo.css +14 -1
- package/BookReaderDemo/IADemoBr.js +148 -0
- package/BookReaderDemo/demo-advanced.html +2 -2
- package/BookReaderDemo/demo-autoplay.html +2 -1
- package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
- package/BookReaderDemo/demo-fullscreen-mobile.html +2 -1
- package/BookReaderDemo/demo-fullscreen.html +2 -1
- package/BookReaderDemo/demo-iiif.html +2 -1
- package/BookReaderDemo/demo-internetarchive.html +84 -17
- package/BookReaderDemo/demo-multiple.html +2 -1
- package/BookReaderDemo/demo-preview-pages.html +2 -1
- package/BookReaderDemo/demo-simple.html +2 -1
- package/BookReaderDemo/demo-vendor-fullscreen.html +2 -1
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +2 -1
- package/BookReaderDemo/immersion-mode.html +2 -1
- package/BookReaderDemo/toggle_controls.html +2 -1
- package/BookReaderDemo/view_mode.html +2 -1
- package/BookReaderDemo/viewmode-cycle.html +2 -3
- package/CHANGELOG.md +202 -0
- package/README.md +14 -1
- package/babel.config.js +18 -0
- package/codecov.yml +6 -0
- package/index.html +3 -0
- package/jsconfig.json +19 -0
- package/package.json +66 -56
- package/renovate.json +52 -0
- package/scripts/preversion.js +4 -1
- package/src/BookNavigator/assets/bookmark-colors.js +1 -1
- package/src/BookNavigator/assets/button-base.js +9 -2
- package/src/BookNavigator/assets/ia-logo.js +17 -0
- package/src/BookNavigator/assets/icon_checkmark.js +1 -1
- package/src/BookNavigator/assets/icon_close.js +1 -1
- package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
- package/src/BookNavigator/assets/icon_volumes.js +11 -0
- package/src/BookNavigator/book-navigator.js +583 -0
- package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
- package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
- package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
- package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +21 -8
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +102 -66
- package/src/BookNavigator/delete-modal-actions.js +1 -1
- package/src/BookNavigator/downloads/downloads-provider.js +36 -21
- package/src/BookNavigator/downloads/downloads.js +41 -25
- package/src/BookNavigator/search/a-search-result.js +18 -13
- package/src/BookNavigator/search/search-provider.js +80 -28
- package/src/BookNavigator/search/search-results.js +10 -18
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
- package/src/BookNavigator/volumes/volumes-provider.js +114 -0
- package/src/BookNavigator/volumes/volumes.js +188 -0
- package/src/BookReader/BookModel.js +0 -29
- package/src/BookReader/DebugConsole.js +3 -3
- package/src/BookReader/DragScrollable.js +233 -0
- package/src/BookReader/Mode1Up.js +51 -351
- package/src/BookReader/Mode1UpLit.js +441 -0
- package/src/BookReader/Mode2Up.js +120 -105
- package/src/BookReader/ModeSmoothZoom.js +179 -0
- package/src/BookReader/ModeThumb.js +17 -11
- package/src/BookReader/Navbar/Navbar.js +10 -36
- package/src/BookReader/PageContainer.js +69 -6
- package/src/BookReader/ReduceSet.js +1 -1
- package/src/BookReader/Toolbar/Toolbar.js +10 -37
- package/src/BookReader/options.js +10 -0
- package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
- package/src/BookReader/utils/ScrollClassAdder.js +31 -0
- package/src/BookReader/utils.js +92 -13
- package/src/BookReader.js +431 -620
- package/src/assets/icons/close-circle-dark.svg +1 -0
- package/src/assets/icons/magnify-minus.svg +3 -7
- package/src/assets/icons/magnify-plus.svg +3 -7
- package/src/assets/icons/voice.svg +1 -0
- package/src/css/BookReader.scss +0 -12
- package/src/css/_BRComponent.scss +1 -1
- package/src/css/_BRmain.scss +19 -24
- package/src/css/_BRnav.scss +4 -26
- package/src/css/_BRpages.scss +35 -0
- package/src/css/_BRsearch.scss +25 -216
- package/src/css/_TextSelection.scss +14 -17
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +17 -5
- package/src/css/_icons.scss +6 -0
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.autoplay.js +4 -4
- package/src/plugins/plugin.chapters.js +28 -35
- package/src/plugins/plugin.mobile_nav.js +11 -10
- package/src/plugins/plugin.resume.js +3 -3
- package/src/plugins/plugin.text_selection.js +26 -39
- package/src/plugins/plugin.vendor-fullscreen.js +4 -4
- package/src/plugins/search/plugin.search.js +174 -116
- package/src/plugins/search/view.js +63 -179
- package/src/plugins/tts/AbstractTTSEngine.js +46 -37
- package/src/plugins/tts/FestivalTTSEngine.js +13 -14
- package/src/plugins/tts/PageChunk.js +15 -21
- package/src/plugins/tts/PageChunkIterator.js +8 -12
- package/src/plugins/tts/WebTTSEngine.js +66 -69
- package/src/plugins/tts/plugin.tts.js +92 -109
- package/src/plugins/tts/utils.js +0 -9
- package/src/plugins/url/UrlPlugin.js +184 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
- package/src/util/manifestGenerator.js +0 -0
- package/tests/e2e/README.md +37 -0
- package/tests/e2e/autoplay.test.js +2 -2
- package/tests/e2e/base.test.js +7 -7
- package/tests/e2e/helpers/base.js +9 -3
- package/tests/e2e/helpers/debug.js +1 -1
- package/tests/e2e/helpers/desktopSearch.js +14 -13
- package/tests/e2e/helpers/mobileSearch.js +3 -3
- package/tests/e2e/helpers/params.js +17 -0
- package/tests/e2e/models/Navigation.js +13 -4
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +38 -33
- package/tests/jest/BookNavigator/book-navigator.test.js +634 -0
- package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
- package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
- package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
- package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
- package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
- package/tests/{karma/BookNavigator → jest/BookNavigator/search}/search-results.test.js +102 -58
- package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
- package/tests/jest/BookNavigator/volumes/volumes-provider.test.js +184 -0
- package/tests/jest/BookNavigator/volumes/volumes.test.js +97 -0
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +34 -14
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
- package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
- package/tests/jest/BookReader/Mode1UpLit.test.js +92 -0
- package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +36 -15
- package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
- package/tests/jest/BookReader/ModeThumb.test.js +71 -0
- package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
- package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
- package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
- package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
- package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
- package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
- package/tests/jest/BookReader/utils.test.js +186 -0
- package/tests/jest/BookReader.keyboard.test.js +190 -0
- package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
- package/tests/{BookReader.test.js → jest/BookReader.test.js} +18 -37
- package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
- package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +10 -11
- package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
- package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
- package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
- package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
- package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +63 -47
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +35 -6
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +9 -9
- package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
- package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
- package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
- package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +1 -1
- package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -28
- package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
- package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
- package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
- package/tests/{util → jest/util}/docCookies.test.js +1 -1
- package/tests/{util → jest/util}/strings.test.js +1 -1
- package/tests/{utils.js → jest/utils.js} +38 -0
- package/webpack.config.js +11 -5
- package/.babelrc +0 -12
- package/.dependabot/config.yml +0 -6
- package/.testcaferc.json +0 -5
- package/BookReader/bookreader-component-bundle.js +0 -1450
- package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
- package/BookReader/bookreader-component-bundle.js.map +0 -1
- package/BookReader/jquery-1.10.1.js +0 -2
- package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
- package/BookReader/plugins/plugin.menu_toggle.js +0 -2
- package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
- package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
- package/karma.conf.js +0 -23
- package/src/BookNavigator/BookModel.js +0 -14
- package/src/BookNavigator/BookNavigator.js +0 -438
- package/src/BookNavigator/assets/book-loader.js +0 -27
- package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
- package/src/BookReaderComponent/BookReaderComponent.js +0 -112
- package/src/ItemNavigator/ItemNavigator.js +0 -372
- package/src/ItemNavigator/providers/sharing.js +0 -29
- package/src/Layers/sharing/sharing-provider.js +0 -22
- package/src/dragscrollable-br.js +0 -261
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- package/src/plugins/plugin.bookmarks.js +0 -50
- package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
- package/tests/BookReader/Mode1Up.test.js +0 -164
- package/tests/BookReader/utils.test.js +0 -109
- package/tests/e2e/ia-production/ia-prod-base.js +0 -17
- package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
- package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -4,6 +4,7 @@ import 'jquery-ui/ui/widget.js';
|
|
4
4
|
import 'jquery-ui/ui/widgets/mouse.js';
|
5
5
|
import 'jquery-ui/ui/widgets/slider.js';
|
6
6
|
import { EVENTS } from '../events.js';
|
7
|
+
import { throttle } from '../utils.js';
|
7
8
|
|
8
9
|
export class Navbar {
|
9
10
|
/**
|
@@ -27,6 +28,8 @@ export class Navbar {
|
|
27
28
|
this.maximumControls = [
|
28
29
|
'book_left', 'book_right', 'zoom_in', 'zoom_out', 'onepg', 'twopg', 'thumb'
|
29
30
|
];
|
31
|
+
|
32
|
+
this.updateNavIndexThrottled = throttle(this.updateNavIndex.bind(this), 250, false);
|
30
33
|
}
|
31
34
|
|
32
35
|
controlFor(controlName) {
|
@@ -213,7 +216,7 @@ export class Navbar {
|
|
213
216
|
const $slider = this.$root.find('.BRpager').slider({
|
214
217
|
animate: true,
|
215
218
|
min: 0,
|
216
|
-
max: br.getNumLeafs() - 1,
|
219
|
+
max: br.book.getNumLeafs() - 1,
|
217
220
|
value: br.currentIndex(),
|
218
221
|
range: "min"
|
219
222
|
});
|
@@ -240,35 +243,6 @@ export class Navbar {
|
|
240
243
|
return this.$nav;
|
241
244
|
}
|
242
245
|
|
243
|
-
/**
|
244
|
-
* Initialize the navigation bar when embedded
|
245
|
-
*/
|
246
|
-
initEmbed() {
|
247
|
-
const { br } = this;
|
248
|
-
// IA-specific
|
249
|
-
const thisLink = (window.location + '')
|
250
|
-
.replace('?ui=embed','')
|
251
|
-
.replace('/stream/', '/details/')
|
252
|
-
.replace('#', '/');
|
253
|
-
const logoHtml = br.showLogo ? `<a class="logo" href="${br.logoURL}" target="_blank"></a>` : '';
|
254
|
-
|
255
|
-
br.refs.$BRfooter = this.$root = $('<div class="BRfooter"></div>');
|
256
|
-
br.refs.$BRnav = this.$nav = $(
|
257
|
-
`<div class="BRnav BRnavEmbed">
|
258
|
-
${logoHtml}
|
259
|
-
<span class="BRembedreturn">
|
260
|
-
<a href="${thisLink}" target="_blank">${br.bookTitle}</a>
|
261
|
-
</span>
|
262
|
-
<span class="BRtoolbarbuttons">
|
263
|
-
<button class="BRicon book_left"></button>
|
264
|
-
<button class="BRicon book_right"></button>
|
265
|
-
<button class="BRicon full"></button>
|
266
|
-
</span>
|
267
|
-
</div>`);
|
268
|
-
this.$root.append(this.$nav);
|
269
|
-
br.refs.$br.append(this.$root);
|
270
|
-
}
|
271
|
-
|
272
246
|
/**
|
273
247
|
* Returns the textual representation of the current page for the navbar
|
274
248
|
* @param {number} index
|
@@ -277,16 +251,16 @@ export class Navbar {
|
|
277
251
|
getNavPageNumString(index) {
|
278
252
|
const { br } = this;
|
279
253
|
// Accessible index starts at 0 (alas) so we add 1 to make human
|
280
|
-
const pageNum = br.getPageNum(index);
|
281
|
-
const pageType = br.getPageProp(index, 'pageType');
|
282
|
-
const numLeafs = br.getNumLeafs();
|
254
|
+
const pageNum = br.book.getPageNum(index);
|
255
|
+
const pageType = br.book.getPageProp(index, 'pageType');
|
256
|
+
const numLeafs = br.book.getNumLeafs();
|
283
257
|
|
284
258
|
if (!this.maxPageNum) {
|
285
259
|
// Calculate Max page num (used for pagination display)
|
286
260
|
let maxPageNum = 0;
|
287
261
|
let pageNumVal;
|
288
262
|
for (let i = 0; i < numLeafs; i++) {
|
289
|
-
pageNumVal = br.getPageNum(i);
|
263
|
+
pageNumVal = br.book.getPageNum(i);
|
290
264
|
if (!isNaN(pageNumVal) && pageNumVal > maxPageNum) {
|
291
265
|
maxPageNum = pageNumVal;
|
292
266
|
}
|
@@ -331,9 +305,9 @@ export function getNavPageNumHtml(index, numLeafs, pageNum, pageType, maxPageNum
|
|
331
305
|
|
332
306
|
if (!pageIsAsserted) {
|
333
307
|
const pageIndex = index + 1;
|
334
|
-
return `
|
308
|
+
return `(${pageIndex} of ${numLeafs})`; // Page (8 of 10)
|
335
309
|
}
|
336
310
|
|
337
311
|
const bookLengthLabel = maxPageNum ? ` of ${maxPageNum}` : '';
|
338
|
-
return
|
312
|
+
return `${pageNum}${bookLengthLabel}`;
|
339
313
|
}
|
@@ -46,11 +46,17 @@ export class PageContainer {
|
|
46
46
|
const alreadyLoaded = this.imageCache.imageLoaded(this.page.index, reduce);
|
47
47
|
const nextBestLoadedReduce = !alreadyLoaded && this.imageCache.getBestLoadedReduce(this.page.index, reduce);
|
48
48
|
|
49
|
-
//
|
49
|
+
// Create high res image
|
50
|
+
const $newImg = this.imageCache.image(this.page.index, reduce);
|
51
|
+
|
52
|
+
// Avoid removing/re-adding the image if it's already there
|
53
|
+
// This can be called quite a bit, so we need to be fast
|
54
|
+
if (this.$img?.[0].src == $newImg[0].src) {
|
55
|
+
return this;
|
56
|
+
}
|
57
|
+
|
50
58
|
this.$img?.remove();
|
51
|
-
this.$img = this
|
52
|
-
.image(this.page.index, reduce)
|
53
|
-
.prependTo(this.$container);
|
59
|
+
this.$img = $newImg.prependTo(this.$container);
|
54
60
|
|
55
61
|
const backgroundLayers = [];
|
56
62
|
if (!alreadyLoaded) {
|
@@ -58,14 +64,14 @@ export class PageContainer {
|
|
58
64
|
backgroundLayers.push(`url("${this.loadingImage}") center/20px no-repeat`);
|
59
65
|
}
|
60
66
|
if (nextBestLoadedReduce) {
|
61
|
-
backgroundLayers.push(`url("${this.page.getURI(nextBestLoadedReduce, 0)}") center/100% no-repeat`);
|
67
|
+
backgroundLayers.push(`url("${this.page.getURI(nextBestLoadedReduce, 0)}") center/100% 100% no-repeat`);
|
62
68
|
}
|
63
69
|
|
64
70
|
if (!alreadyLoaded) {
|
65
71
|
this.$img
|
66
72
|
.css('background', backgroundLayers.join(','))
|
67
73
|
.one('loadend', async (ev) => {
|
68
|
-
$(ev.target).css({ 'background': '' })
|
74
|
+
$(ev.target).css({ 'background': '' });
|
69
75
|
$(ev.target).parent().removeClass('BRpageloading');
|
70
76
|
});
|
71
77
|
}
|
@@ -73,3 +79,60 @@ export class PageContainer {
|
|
73
79
|
return this;
|
74
80
|
}
|
75
81
|
}
|
82
|
+
|
83
|
+
|
84
|
+
/**
|
85
|
+
* @param {PageModel} page
|
86
|
+
* @param {string} className
|
87
|
+
*/
|
88
|
+
export function createSVGPageLayer(page, className) {
|
89
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
90
|
+
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
|
91
|
+
svg.setAttribute("viewBox", `0 0 ${page.width} ${page.height}`);
|
92
|
+
svg.setAttribute('class', `BRPageLayer ${className}`);
|
93
|
+
svg.setAttribute('preserveAspectRatio', 'none');
|
94
|
+
return svg;
|
95
|
+
}
|
96
|
+
|
97
|
+
/**
|
98
|
+
* @param {{ l: number, r: number, b: number, t: number }} box
|
99
|
+
*/
|
100
|
+
export function boxToSVGRect({ l: left, r: right, b: bottom, t: top }) {
|
101
|
+
const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
102
|
+
rect.setAttribute("x", left.toString());
|
103
|
+
rect.setAttribute("y", top.toString());
|
104
|
+
rect.setAttribute("width", (right - left).toString());
|
105
|
+
rect.setAttribute("height", (bottom - top).toString());
|
106
|
+
|
107
|
+
// Some style; corner radius 4px. Can't set this in CSS yet
|
108
|
+
rect.setAttribute("rx", "4");
|
109
|
+
rect.setAttribute("ry", "4");
|
110
|
+
return rect;
|
111
|
+
}
|
112
|
+
|
113
|
+
/**
|
114
|
+
* @param {string} layerClass
|
115
|
+
* @param {Array<{ l: number, r: number, b: number, t: number }>} boxes
|
116
|
+
* @param {PageModel} page
|
117
|
+
* @param {HTMLElement} containerEl
|
118
|
+
* @param {string[]} [rectClasses] CSS classes to add to the rects
|
119
|
+
*/
|
120
|
+
export function renderBoxesInPageContainerLayer(layerClass, boxes, page, containerEl, rectClasses = null) {
|
121
|
+
const mountedSvg = containerEl.querySelector(`.${layerClass}`);
|
122
|
+
// Create the layer if it's not there
|
123
|
+
const svg = mountedSvg || createSVGPageLayer(page, layerClass);
|
124
|
+
if (!mountedSvg) {
|
125
|
+
// Insert after the image if the image is already loaded.
|
126
|
+
const imgEl = containerEl.querySelector('.BRpageimage');
|
127
|
+
if (imgEl) $(svg).insertAfter(imgEl);
|
128
|
+
else $(svg).prependTo(containerEl);
|
129
|
+
}
|
130
|
+
|
131
|
+
for (const [i, box] of boxes.entries()) {
|
132
|
+
const rect = boxToSVGRect(box);
|
133
|
+
if (rectClasses) {
|
134
|
+
rect.setAttribute('class', rectClasses[i]);
|
135
|
+
}
|
136
|
+
svg.appendChild(rect);
|
137
|
+
}
|
138
|
+
}
|
@@ -54,7 +54,7 @@ export class Toolbar {
|
|
54
54
|
.attr({href: br.bookUrl, title: br.bookUrlTitle})
|
55
55
|
.addClass('BRreturn')
|
56
56
|
.html(br.bookUrlText || br.bookTitle)
|
57
|
-
)
|
57
|
+
);
|
58
58
|
} else if (br.bookTitle) {
|
59
59
|
$titleSectionEl.append(br.bookUrlText || br.bookTitle);
|
60
60
|
}
|
@@ -75,8 +75,6 @@ export class Toolbar {
|
|
75
75
|
br.$('.BRnavCntl').addClass('BRup');
|
76
76
|
br.$('.pause').hide();
|
77
77
|
|
78
|
-
this.updateToolbarZoom(br.reduce); // Pretty format
|
79
|
-
|
80
78
|
// We build in mode 2
|
81
79
|
br.refs.$BRtoolbar.append();
|
82
80
|
|
@@ -127,31 +125,6 @@ export class Toolbar {
|
|
127
125
|
});
|
128
126
|
}
|
129
127
|
|
130
|
-
/**
|
131
|
-
* @deprecated
|
132
|
-
* @todo .BRzoom doesn't exist anywhere, so this is likely dead code
|
133
|
-
* Update the displayed zoom factor based on reduction factor
|
134
|
-
* @param {number} reduce
|
135
|
-
*/
|
136
|
-
updateToolbarZoom(reduce) {
|
137
|
-
const { br } = this;
|
138
|
-
// $$$ TODO preserve zoom/fit for each mode
|
139
|
-
const autofit = br.mode == br.constMode2up ? br.twoPage.autofit : br.onePage.autofit;
|
140
|
-
/** @type {string} */
|
141
|
-
let value;
|
142
|
-
if (autofit) {
|
143
|
-
value = autofit.slice(0,1).toUpperCase() + autofit.slice(1);
|
144
|
-
} else {
|
145
|
-
value = (100 / reduce)
|
146
|
-
.toFixed(2)
|
147
|
-
// Strip trailing zeroes and decimal if all zeroes
|
148
|
-
.replace(/0+$/,'')
|
149
|
-
.replace(/\.$/,'')
|
150
|
-
+ '%';
|
151
|
-
}
|
152
|
-
br.$('.BRzoom').text(value);
|
153
|
-
}
|
154
|
-
|
155
128
|
/**
|
156
129
|
* @param {JQuery} $shareDiv
|
157
130
|
*/
|
@@ -212,11 +185,11 @@ export class Toolbar {
|
|
212
185
|
$form.appendTo($shareDiv);
|
213
186
|
|
214
187
|
$form.find('.fieldset-embed input').on('change', event => {
|
215
|
-
const form = $(event.target).parents('form
|
188
|
+
const form = $(event.target).parents('form').first();
|
216
189
|
const params = {};
|
217
190
|
params.mode = $(form.find('.fieldset-embed input[name=pages]:checked')).val();
|
218
191
|
if (form.find('.fieldset-embed input[name=thispage]').prop('checked')) {
|
219
|
-
params.page = br.getPageNum(br.currentIndex());
|
192
|
+
params.page = br.book.getPageNum(br.currentIndex());
|
220
193
|
}
|
221
194
|
|
222
195
|
if (br.getEmbedCode) {
|
@@ -232,12 +205,12 @@ export class Toolbar {
|
|
232
205
|
// Bind share buttons
|
233
206
|
|
234
207
|
// Use url without hashes
|
235
|
-
$form.find('.facebook-share-button').click(
|
208
|
+
$form.find('.facebook-share-button').on("click", () => {
|
236
209
|
const params = $.param({ u: this._getSocialShareUrl() });
|
237
210
|
const url = 'https://www.facebook.com/sharer.php?' + params;
|
238
211
|
createPopup(url, 600, 400, 'Share');
|
239
212
|
});
|
240
|
-
$form.find('.twitter-share-button').click(
|
213
|
+
$form.find('.twitter-share-button').on("click", () => {
|
241
214
|
const params = $.param({
|
242
215
|
url: this._getSocialShareUrl(),
|
243
216
|
text: br.bookTitle
|
@@ -245,7 +218,7 @@ export class Toolbar {
|
|
245
218
|
const url = 'https://twitter.com/intent/tweet?' + params;
|
246
219
|
createPopup(url, 600, 400, 'Share');
|
247
220
|
});
|
248
|
-
$form.find('.email-share-button').click(
|
221
|
+
$form.find('.email-share-button').on("click", () => {
|
249
222
|
const body = `${br.bookTitle}\n\n${this._getSocialShareUrl()}`;
|
250
223
|
window.location.href = `mailto:?subject=${encodeURI(br.bookTitle)}&body=${encodeURI(body)}`;
|
251
224
|
});
|
@@ -331,11 +304,11 @@ export class Toolbar {
|
|
331
304
|
}
|
332
305
|
}
|
333
306
|
|
334
|
-
|
307
|
+
function blankInfoDiv() {
|
335
308
|
return $(`
|
336
309
|
<div class="BRfloat BRinfo">
|
337
310
|
<div class="BRfloatHead">About this book
|
338
|
-
<button class="floatShut" href="javascript:;" onclick="$.fn.colorbox.close();"><span class="shift">Close</span></button>
|
311
|
+
<button class="floatShut" href="javascript:;" onclick="$.fn.colorbox.close();"><span class="br-colorbox-shift">Close</span></button>
|
339
312
|
</div>
|
340
313
|
<div class="BRfloatBody">
|
341
314
|
<div class="BRfloatCover"></div>
|
@@ -351,12 +324,12 @@ export function blankInfoDiv() {
|
|
351
324
|
</div>`);
|
352
325
|
}
|
353
326
|
|
354
|
-
|
327
|
+
function blankShareDiv() {
|
355
328
|
return $(`
|
356
329
|
<div class="BRfloat BRshare">
|
357
330
|
<div class="BRfloatHead">
|
358
331
|
Share
|
359
|
-
<button class="floatShut" href="javascript:;" onclick="$.fn.colorbox.close();"><span class="shift">Close</span></button>
|
332
|
+
<button class="floatShut" href="javascript:;" onclick="$.fn.colorbox.close();"><span class="br-colorbox-shift">Close</span></button>
|
360
333
|
</div>
|
361
334
|
</div>`);
|
362
335
|
}
|
@@ -25,6 +25,10 @@ export const DEFAULT_OPTIONS = {
|
|
25
25
|
thumbMaxLoading: 4,
|
26
26
|
/** spacing between thumbnails */
|
27
27
|
thumbPadding: 10,
|
28
|
+
/** min zoom in columns */
|
29
|
+
thumbMinZoomColumns: 2,
|
30
|
+
/** max zoom out columns */
|
31
|
+
thumbMaxZoomColumns: 8,
|
28
32
|
|
29
33
|
/** @type {number | 'fast' | 'slow'} speed for flip animation */
|
30
34
|
flipSpeed: 'fast',
|
@@ -275,6 +279,12 @@ export const DEFAULT_OPTIONS = {
|
|
275
279
|
*/
|
276
280
|
startFullscreen: false,
|
277
281
|
|
282
|
+
/**
|
283
|
+
* @type {Boolean}
|
284
|
+
* will show logo at fullscreen mode
|
285
|
+
*/
|
286
|
+
enableFSLogoShortcut: false,
|
287
|
+
|
278
288
|
/**
|
279
289
|
* @type {Boolean}
|
280
290
|
* On init, by default, we want to handle resizing bookreader
|
@@ -0,0 +1,44 @@
|
|
1
|
+
// @ts-check
|
2
|
+
import { debounce } from '../utils';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Computing these things repeatedly is expensive (the browser needs to
|
6
|
+
* do a lot of computations/redrawing to make sure these are correct),
|
7
|
+
* so we store them here, and only recompute them when necessary:
|
8
|
+
* - window resize could have cause the container to change size
|
9
|
+
* - zoom could have cause scrollbars to appear/disappear, changing
|
10
|
+
* the client size.
|
11
|
+
*/
|
12
|
+
export class HTMLDimensionsCacher {
|
13
|
+
clientWidth = 100;
|
14
|
+
clientHeight = 100;
|
15
|
+
|
16
|
+
boundingClientRect = { top: 0, left: 0 };
|
17
|
+
|
18
|
+
/**
|
19
|
+
* @param {HTMLElement} element
|
20
|
+
*/
|
21
|
+
constructor(element) {
|
22
|
+
/** @type {HTMLElement} */
|
23
|
+
this.element = element;
|
24
|
+
}
|
25
|
+
|
26
|
+
updateClientSizes = () => {
|
27
|
+
const bc = this.element.getBoundingClientRect();
|
28
|
+
this.clientWidth = this.element.clientWidth;
|
29
|
+
this.clientHeight = this.element.clientHeight;
|
30
|
+
this.boundingClientRect.top = bc.top;
|
31
|
+
this.boundingClientRect.left = bc.left;
|
32
|
+
}
|
33
|
+
debouncedUpdateClientSizes = debounce(this.updateClientSizes, 150, false);
|
34
|
+
|
35
|
+
/** @param {EventTarget} win */
|
36
|
+
attachResizeListener(win = window) {
|
37
|
+
win.addEventListener('resize', this.debouncedUpdateClientSizes);
|
38
|
+
}
|
39
|
+
|
40
|
+
/** @param {EventTarget} win */
|
41
|
+
detachResizeListener(win = window) {
|
42
|
+
win.removeEventListener('resize', this.debouncedUpdateClientSizes);
|
43
|
+
}
|
44
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
/** Adds a class while the given element is experiencing scrolling */
|
2
|
+
export class ScrollClassAdder {
|
3
|
+
/**
|
4
|
+
* @param {HTMLElement} element
|
5
|
+
* @param {string} className
|
6
|
+
*/
|
7
|
+
constructor(element, className) {
|
8
|
+
/** @type {HTMLElement} */
|
9
|
+
this.element = element;
|
10
|
+
/** @type {string} */
|
11
|
+
this.className = className;
|
12
|
+
this.timeout = null;
|
13
|
+
}
|
14
|
+
|
15
|
+
attach() {
|
16
|
+
this.element.addEventListener('scroll', this.onScroll);
|
17
|
+
}
|
18
|
+
|
19
|
+
detach() {
|
20
|
+
this.element.removeEventListener('scroll', this.onScroll);
|
21
|
+
}
|
22
|
+
|
23
|
+
onScroll = () => {
|
24
|
+
this.element.classList.add(this.className);
|
25
|
+
clearTimeout(this.timeout);
|
26
|
+
// TODO: Also remove class on mousemove, touch, click, etc.
|
27
|
+
this.timeout = setTimeout(() => {
|
28
|
+
this.element.classList.remove(this.className);
|
29
|
+
}, 600);
|
30
|
+
}
|
31
|
+
}
|
package/src/BookReader/utils.js
CHANGED
@@ -40,6 +40,24 @@ export function notInArray(value, array) {
|
|
40
40
|
return !array.includes(value);
|
41
41
|
}
|
42
42
|
|
43
|
+
/**
|
44
|
+
* Determines the active element, going into shadow doms.
|
45
|
+
* @return {Element}
|
46
|
+
*/
|
47
|
+
export function getActiveElement(doc = document, recurseShadowDom = true) {
|
48
|
+
const activeElement = doc.activeElement;
|
49
|
+
if (recurseShadowDom && activeElement?.shadowRoot) {
|
50
|
+
return getActiveElement(activeElement.shadowRoot, true);
|
51
|
+
}
|
52
|
+
return activeElement;
|
53
|
+
}
|
54
|
+
|
55
|
+
/** Check if an input field/textarea is active. Also checks shadow DOMs. */
|
56
|
+
export function isInputActive(doc = document) {
|
57
|
+
const activeEl = getActiveElement(doc);
|
58
|
+
return activeEl?.tagName == "INPUT" || activeEl?.tagName == "TEXTAREA";
|
59
|
+
}
|
60
|
+
|
43
61
|
/**
|
44
62
|
* @param {HTMLIFrameElement} iframe
|
45
63
|
* @return {Document}
|
@@ -80,16 +98,17 @@ export function encodeURIComponentPlus(value) {
|
|
80
98
|
}
|
81
99
|
|
82
100
|
/**
|
101
|
+
* @template {Function} T
|
83
102
|
* Returns a function, that, as long as it continues to be invoked, will not
|
84
103
|
* be triggered. The function will be called after it stops being called for
|
85
104
|
* N milliseconds. If `immediate` is passed, trigger the function on the
|
86
105
|
* leading edge, instead of the trailing.
|
87
106
|
* @see https://davidwalsh.name/javascript-debounce-function
|
88
107
|
*
|
89
|
-
* @param {
|
108
|
+
* @param {T} func
|
90
109
|
* @param {number} wait
|
91
110
|
* @param {boolean} immediate
|
92
|
-
* @return {
|
111
|
+
* @return {T}
|
93
112
|
*/
|
94
113
|
export function debounce(func, wait, immediate) {
|
95
114
|
let timeout;
|
@@ -108,12 +127,13 @@ export function debounce(func, wait, immediate) {
|
|
108
127
|
}
|
109
128
|
|
110
129
|
/**
|
130
|
+
* @template T
|
111
131
|
* Throttle function
|
112
132
|
* @see https://remysharp.com/2010/07/21/throttling-function-calls
|
113
|
-
* @param {
|
133
|
+
* @param {T} fn
|
114
134
|
* @param {number} threshold
|
115
135
|
* @param {boolean} delay
|
116
|
-
* @return {
|
136
|
+
* @return {T}
|
117
137
|
*/
|
118
138
|
export function throttle(fn, threshold, delay) {
|
119
139
|
threshold || (threshold = 250);
|
@@ -160,14 +180,6 @@ export function PolyfilledCustomEvent(eventName, {bubbles = false, cancelable =
|
|
160
180
|
return event;
|
161
181
|
}
|
162
182
|
|
163
|
-
/**
|
164
|
-
* Promise based sleep - resolves at default 500ms
|
165
|
-
* @param {Number} wait time in milliseconds
|
166
|
-
*/
|
167
|
-
export function sleep(ms = 500) {
|
168
|
-
return new Promise(res => setTimeout(res(true), ms));
|
169
|
-
}
|
170
|
-
|
171
183
|
/*
|
172
184
|
* Returns the number pixels something should be rendered at to be ~1n on the users
|
173
185
|
* screen when measured with a ruler.
|
@@ -179,7 +191,74 @@ export function calcScreenDPI() {
|
|
179
191
|
const dpi = el.offsetWidth;
|
180
192
|
document.body.removeChild(el);
|
181
193
|
|
182
|
-
|
194
|
+
// Do you believe in magic... numbers? We tested on some devices, and the displayed
|
195
|
+
// size of `width: 1in` was less than desired. On @pezvi's mac, it was ~75% ; on
|
196
|
+
// @cdrini's laptop it was ~85%. Since we want to avoid things appearing too small,
|
197
|
+
// let's just use a multiplier of 1.25
|
198
|
+
const screenDPI = dpi * 1.25;
|
183
199
|
// This will return 0 in testing; never want it to be 0!
|
184
200
|
return screenDPI == 0 ? 100 : screenDPI;
|
185
201
|
}
|
202
|
+
|
203
|
+
/**
|
204
|
+
* @param {number[]} nums
|
205
|
+
* @returns {number}
|
206
|
+
*/
|
207
|
+
export function sum(nums) {
|
208
|
+
return nums.reduce((cur, acc) => cur + acc, 0);
|
209
|
+
}
|
210
|
+
|
211
|
+
/**
|
212
|
+
* @template T
|
213
|
+
* @param {Generator<T>} gen
|
214
|
+
* @returns {T[]}
|
215
|
+
*/
|
216
|
+
export function genToArray(gen) {
|
217
|
+
const result = [];
|
218
|
+
for (const item of gen) {
|
219
|
+
result.push(item);
|
220
|
+
}
|
221
|
+
return result;
|
222
|
+
}
|
223
|
+
|
224
|
+
/**
|
225
|
+
* Check if arrays contain the same elements. Does reference comparison.
|
226
|
+
* @param {Array} arr1
|
227
|
+
* @param {Array} arr2
|
228
|
+
*/
|
229
|
+
export function arrEquals(arr1, arr2) {
|
230
|
+
return arr1.length == arr2.length && arr1.every((x, i) => x == arr2[i]);
|
231
|
+
}
|
232
|
+
|
233
|
+
/**
|
234
|
+
* Check if array has changed; namely to be used with lit's property.hasChanged
|
235
|
+
* @param {Array} [arr1]
|
236
|
+
* @param {Array} [arr2]
|
237
|
+
*/
|
238
|
+
export function arrChanged(arr1, arr2) {
|
239
|
+
return arr1 && arr2 && !arrEquals(arr1, arr2);
|
240
|
+
}
|
241
|
+
|
242
|
+
/**
|
243
|
+
* Waits the provided number of ms and then resolves with a promise
|
244
|
+
* @param {number} ms
|
245
|
+
**/
|
246
|
+
export async function sleep(ms) {
|
247
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
248
|
+
}
|
249
|
+
|
250
|
+
/**
|
251
|
+
* @template T
|
252
|
+
* @param {function(): T} fn
|
253
|
+
* @param {Object} options
|
254
|
+
* @param {function(T): boolean} [options.until]
|
255
|
+
* @return {T | undefined}
|
256
|
+
*/
|
257
|
+
export async function poll(fn, { step = 50, timeout = 500, until = val => Boolean(val), _sleep = sleep } = {}) {
|
258
|
+
const startTime = Date.now();
|
259
|
+
while (Date.now() - startTime < timeout) {
|
260
|
+
const result = fn();
|
261
|
+
if (until(result)) return result;
|
262
|
+
await _sleep(step);
|
263
|
+
}
|
264
|
+
}
|