@internetarchive/bookreader 5.0.0-8 → 5.0.0-80
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 +73 -10
- package/.github/workflows/npm-publish.yml +6 -20
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +398 -1133
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.LICENSE.txt +20 -20
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +1782 -0
- package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -0
- package/BookReader/ia-bookreader-bundle.js.map +1 -0
- package/BookReader/icons/1up.svg +1 -1
- package/BookReader/icons/2up.svg +1 -1
- package/BookReader/icons/advance.svg +1 -1
- package/BookReader/icons/chevron-right.svg +1 -1
- package/BookReader/icons/close-circle-dark.svg +1 -1
- package/BookReader/icons/close-circle.svg +1 -1
- package/BookReader/icons/fullscreen.svg +1 -1
- package/BookReader/icons/fullscreen_exit.svg +1 -1
- package/BookReader/icons/hamburger.svg +1 -1
- package/BookReader/icons/left-arrow.svg +1 -1
- package/BookReader/icons/magnify-minus.svg +1 -1
- package/BookReader/icons/magnify-plus.svg +1 -1
- package/BookReader/icons/magnify.svg +1 -1
- package/BookReader/icons/pause.svg +1 -1
- package/BookReader/icons/play.svg +1 -1
- package/BookReader/icons/playback-speed.svg +1 -1
- package/BookReader/icons/read-aloud.svg +1 -1
- package/BookReader/icons/review.svg +1 -1
- package/BookReader/icons/thumbnails.svg +1 -1
- package/BookReader/icons/voice.svg +1 -0
- package/BookReader/icons/volume-full.svg +1 -1
- package/BookReader/images/BRicons.svg +3 -3
- package/BookReader/images/books_graphic.svg +1 -1
- package/BookReader/images/icon_book.svg +1 -1
- package/BookReader/images/icon_bookmark.svg +1 -1
- package/BookReader/images/icon_gear.svg +1 -1
- package/BookReader/images/icon_hamburger.svg +1 -1
- package/BookReader/images/icon_home.svg +1 -1
- package/BookReader/images/icon_info.svg +1 -1
- package/BookReader/images/icon_one_page.svg +1 -1
- package/BookReader/images/icon_pause.svg +1 -1
- package/BookReader/images/icon_play.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_skip-ahead.svg +1 -1
- package/BookReader/images/icon_skip-back.svg +1 -1
- package/BookReader/images/icon_speaker.svg +1 -1
- package/BookReader/images/icon_speaker_open.svg +1 -1
- package/BookReader/images/icon_thumbnails.svg +1 -1
- package/BookReader/images/icon_toc.svg +1 -1
- package/BookReader/images/icon_two_pages.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 +25 -1
- package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
- 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.iiif.js +2 -0
- package/BookReader/plugins/plugin.iiif.js.map +1 -0
- package/BookReader/plugins/plugin.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +2 -1
- package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +2 -1
- package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.LICENSE.txt +2 -0
- 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 +18 -19
- package/BookReaderDemo/BookReaderJSAdvanced.js +0 -3
- package/BookReaderDemo/BookReaderJSAutoplay.js +4 -1
- package/BookReaderDemo/BookReaderJSSimple.js +1 -0
- package/BookReaderDemo/IADemoBr.js +147 -0
- package/BookReaderDemo/demo-advanced.html +2 -2
- package/BookReaderDemo/demo-autoplay.html +2 -3
- package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
- package/BookReaderDemo/demo-fullscreen-mobile.html +3 -5
- package/BookReaderDemo/demo-fullscreen.html +2 -4
- package/BookReaderDemo/demo-iiif.html +99 -12
- package/BookReaderDemo/demo-internetarchive.html +214 -18
- 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 -4
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +2 -2
- package/BookReaderDemo/immersion-mode.html +2 -4
- package/BookReaderDemo/toggle_controls.html +3 -2
- package/BookReaderDemo/view_mode.html +2 -1
- package/BookReaderDemo/viewmode-cycle.html +2 -3
- package/CHANGELOG.md +536 -33
- package/README.md +14 -1
- package/babel.config.js +20 -0
- package/codecov.yml +6 -0
- package/index.html +4 -1
- package/jsconfig.json +19 -0
- package/netlify.toml +9 -0
- package/package.json +70 -60
- package/renovate.json +52 -0
- package/scripts/preversion.js +0 -1
- package/src/BookNavigator/assets/bookmark-colors.js +1 -1
- package/src/BookNavigator/assets/button-base.js +4 -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/book-navigator.js +590 -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 +27 -17
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +116 -67
- 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/search-provider.js +49 -27
- package/src/BookNavigator/search/search-results.js +23 -9
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/viewable-files.js +95 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
- package/src/BookReader/BookModel.js +64 -34
- package/src/BookReader/DragScrollable.js +233 -0
- package/src/BookReader/Mode1Up.js +56 -351
- package/src/BookReader/Mode1UpLit.js +388 -0
- package/src/BookReader/Mode2Up.js +73 -1318
- package/src/BookReader/Mode2UpLit.js +776 -0
- package/src/BookReader/ModeCoordinateSpace.js +29 -0
- package/src/BookReader/ModeSmoothZoom.js +312 -0
- package/src/BookReader/ModeThumb.js +18 -12
- package/src/BookReader/Navbar/Navbar.js +14 -40
- package/src/BookReader/PageContainer.js +81 -6
- package/src/BookReader/ReduceSet.js +1 -1
- package/src/BookReader/Toolbar/Toolbar.js +10 -37
- package/src/BookReader/events.js +2 -3
- package/src/BookReader/options.js +27 -2
- package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
- package/src/BookReader/utils/ScrollClassAdder.js +31 -0
- package/src/BookReader/utils/SelectionObserver.js +45 -0
- package/src/BookReader/utils.js +118 -13
- package/src/BookReader.js +427 -1061
- 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 +1 -5
- package/src/css/_BRBookmarks.scss +1 -1
- package/src/css/_BRComponent.scss +1 -1
- package/src/css/_BRmain.scss +16 -3
- package/src/css/_BRnav.scss +12 -39
- package/src/css/_BRpages.scss +149 -40
- package/src/css/_BRsearch.scss +68 -25
- package/src/css/_BRtoolbar.scss +5 -5
- package/src/css/_TextSelection.scss +87 -27
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +20 -7
- package/src/css/_icons.scss +1 -1
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.archive_analytics.js +3 -3
- package/src/plugins/plugin.autoplay.js +5 -11
- package/src/plugins/plugin.chapters.js +237 -191
- package/src/plugins/plugin.iiif.js +151 -0
- package/src/plugins/plugin.resume.js +3 -3
- package/src/plugins/plugin.text_selection.js +464 -134
- package/src/plugins/plugin.vendor-fullscreen.js +4 -4
- package/src/plugins/search/plugin.search.js +142 -125
- package/src/plugins/search/utils.js +43 -0
- package/src/plugins/search/view.js +33 -58
- package/src/plugins/tts/AbstractTTSEngine.js +71 -40
- 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 +87 -71
- package/src/plugins/tts/plugin.tts.js +96 -127
- package/src/plugins/tts/utils.js +15 -25
- package/src/plugins/url/UrlPlugin.js +191 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +45 -16
- package/src/util/browserSniffing.js +22 -0
- package/src/util/docCookies.js +21 -2
- package/tests/e2e/README.md +37 -0
- package/tests/e2e/autoplay.test.js +2 -2
- package/tests/e2e/base.test.js +8 -16
- package/tests/e2e/helpers/base.js +53 -48
- package/tests/e2e/helpers/debug.js +1 -1
- package/tests/e2e/helpers/params.js +17 -0
- package/tests/e2e/helpers/rightToLeft.js +8 -14
- package/tests/e2e/helpers/search.js +73 -0
- package/tests/e2e/models/Navigation.js +20 -37
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +40 -33
- package/tests/jest/BookNavigator/book-navigator.test.js +661 -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 → jest}/BookNavigator/search/search-results.test.js +109 -60
- package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/jest/BookNavigator/viewable-files/viewable-files-provider.test.js +80 -0
- package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +74 -14
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +193 -0
- package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
- package/tests/jest/BookReader/Mode1UpLit.test.js +73 -0
- package/tests/jest/BookReader/Mode2Up.test.js +98 -0
- package/tests/jest/BookReader/Mode2UpLit.test.js +190 -0
- package/tests/jest/BookReader/ModeCoordinateSpace.test.js +16 -0
- package/tests/jest/BookReader/ModeSmoothZoom.test.js +218 -0
- package/tests/jest/BookReader/ModeThumb.test.js +71 -0
- package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +10 -10
- 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/jest/BookReader/utils/SelectionObserver.test.js +57 -0
- package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
- package/tests/jest/BookReader/utils.test.js +229 -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} +26 -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/jest/plugins/plugin.chapters.test.js +195 -0
- package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
- package/tests/jest/plugins/plugin.text_selection.test.js +317 -0
- package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
- package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +25 -47
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +39 -6
- package/tests/jest/plugins/search/utils.js +25 -0
- package/tests/jest/plugins/search/utils.test.js +29 -0
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +29 -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 +47 -1
- package/tests/{plugins → jest/plugins}/tts/utils.test.js +1 -60
- package/tests/jest/plugins/url/UrlPlugin.test.js +198 -0
- package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +53 -14
- package/tests/jest/setup.js +3 -0
- package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
- package/tests/jest/util/docCookies.test.js +24 -0
- package/tests/{util → jest/util}/strings.test.js +1 -1
- package/tests/{utils.js → jest/utils.js} +38 -0
- package/webpack.config.js +12 -6
- 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/BookReader/plugins/plugin.mobile_nav.js +0 -2
- package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
- package/BookReaderDemo/IIIFBookReader.js +0 -207
- package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- package/BookReaderDemo/demo-iiif.js +0 -26
- 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 -446
- package/src/BookNavigator/assets/book-loader.js +0 -27
- package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
- package/src/BookNavigator/search/a-search-result.js +0 -55
- package/src/BookReader/DebugConsole.js +0 -54
- package/src/BookReaderComponent/BookReaderComponent.js +0 -112
- package/src/ItemNavigator/ItemNavigator.js +0 -376
- package/src/ItemNavigator/providers/sharing.js +0 -29
- package/src/css/_MobileNav.scss +0 -194
- package/src/dragscrollable-br.js +0 -261
- package/src/lit-wrapper.js +0 -2
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- package/src/plugins/plugin.mobile_nav.js +0 -287
- package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
- package/tests/BookReader/DebugConsole.test.js +0 -25
- package/tests/BookReader/Mode1Up.test.js +0 -164
- package/tests/BookReader/Mode2Up.test.js +0 -247
- package/tests/BookReader/utils.test.js +0 -109
- package/tests/e2e/helpers/desktopSearch.js +0 -72
- package/tests/e2e/helpers/mobileSearch.js +0 -85
- 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/search/search-provider.test.js +0 -23
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
- package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
- package/tests/plugins/plugin.chapters.test.js +0 -130
- package/tests/plugins/plugin.mobile_nav.test.js +0 -66
- package/tests/plugins/plugin.text_selection.test.js +0 -203
- package/tests/util/docCookies.test.js +0 -15
|
@@ -6,8 +6,9 @@ import FestivalTTSEngine from './FestivalTTSEngine.js';
|
|
|
6
6
|
import WebTTSEngine from './WebTTSEngine.js';
|
|
7
7
|
import { toISO6391, approximateWordCount } from './utils.js';
|
|
8
8
|
import { en as tooltips } from './tooltip_dict.js';
|
|
9
|
-
|
|
10
|
-
/** @typedef {import(
|
|
9
|
+
import { renderBoxesInPageContainerLayer } from '../../BookReader/PageContainer.js';
|
|
10
|
+
/** @typedef {import('./PageChunk.js').default} PageChunk */
|
|
11
|
+
/** @typedef {import("./AbstractTTSEngine.js").default} AbstractTTSEngine */
|
|
11
12
|
|
|
12
13
|
// Default options for TTS
|
|
13
14
|
jQuery.extend(BookReader.defaultOptions, {
|
|
@@ -22,7 +23,9 @@ BookReader.prototype.setup = (function (super_) {
|
|
|
22
23
|
super_.call(this, options);
|
|
23
24
|
|
|
24
25
|
if (this.options.enableTtsPlugin) {
|
|
25
|
-
|
|
26
|
+
/** @type { {[pageIndex: number]: Array<{ l: number, r: number, t: number, b: number }>} } */
|
|
27
|
+
this._ttsBoxesByIndex = {};
|
|
28
|
+
|
|
26
29
|
let TTSEngine = WebTTSEngine.isSupported() ? WebTTSEngine :
|
|
27
30
|
FestivalTTSEngine.isSupported() ? FestivalTTSEngine :
|
|
28
31
|
null;
|
|
@@ -54,17 +57,6 @@ BookReader.prototype.init = (function(super_) {
|
|
|
54
57
|
if (this.options.enableTtsPlugin) {
|
|
55
58
|
// Bind to events
|
|
56
59
|
|
|
57
|
-
// TODO move this to BookReader.js or something
|
|
58
|
-
this.bind(BookReader.eventNames.fragmentChange, () => {
|
|
59
|
-
if (this.mode == this.constMode2up) {
|
|
60
|
-
// clear highlights if they're no longer valid for this page
|
|
61
|
-
const visibleIndices = [this.twoPage.currentIndexL, this.twoPage.currentIndexR];
|
|
62
|
-
const visibleSelector = visibleIndices.map(i => `.BRReadAloudHilite.Leaf-${i}`).join(', ');
|
|
63
|
-
$(this.ttsHilites).filter(visibleSelector).show();
|
|
64
|
-
$(this.ttsHilites).not(visibleSelector).hide();
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
|
|
68
60
|
this.bind(BookReader.eventNames.PostInit, () => {
|
|
69
61
|
this.$('.BRicon.read').click(() => {
|
|
70
62
|
this.ttsToggle();
|
|
@@ -88,6 +80,17 @@ BookReader.prototype.init = (function(super_) {
|
|
|
88
80
|
};
|
|
89
81
|
})(BookReader.prototype.init);
|
|
90
82
|
|
|
83
|
+
/** @override */
|
|
84
|
+
BookReader.prototype._createPageContainer = (function (super_) {
|
|
85
|
+
return function (index) {
|
|
86
|
+
const pageContainer = super_.call(this, index);
|
|
87
|
+
if (this.options.enableTtsPlugin && pageContainer.page && index in this._ttsBoxesByIndex) {
|
|
88
|
+
const pageIndex = pageContainer.page.index;
|
|
89
|
+
renderBoxesInPageContainerLayer('ttsHiliteLayer', this._ttsBoxesByIndex[pageIndex], pageContainer.page, pageContainer.$container[0]);
|
|
90
|
+
}
|
|
91
|
+
return pageContainer;
|
|
92
|
+
};
|
|
93
|
+
})(BookReader.prototype._createPageContainer);
|
|
91
94
|
|
|
92
95
|
// Extend buildMobileDrawerElement
|
|
93
96
|
BookReader.prototype.buildMobileDrawerElement = (function (super_) {
|
|
@@ -146,19 +149,53 @@ BookReader.prototype.initNavbar = (function (super_) {
|
|
|
146
149
|
<div class="icon icon-advance"></div>
|
|
147
150
|
</button>
|
|
148
151
|
</li>
|
|
152
|
+
<li>
|
|
153
|
+
<select class="playback-voices" name="playback-voice" style="display: none" title="Change read aloud voices">
|
|
154
|
+
</select>
|
|
155
|
+
</li>
|
|
149
156
|
</ul>
|
|
150
157
|
`);
|
|
158
|
+
|
|
151
159
|
$el.find('.BRcontrols').prepend(this.refs.$BRReadAloudToolbar);
|
|
160
|
+
|
|
161
|
+
const renderVoiceOption = (voices) => {
|
|
162
|
+
return voices.map(voice =>
|
|
163
|
+
`<option value="${voice.voiceURI}">${voice.lang} - ${voice.name}</option>`).join('');
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const voiceSortOrder = (a,b) => `${a.lang} - ${a.name}`.localeCompare(`${b.lang} - ${b.name}`);
|
|
167
|
+
|
|
168
|
+
const renderVoicesMenu = (voicesMenu) => {
|
|
169
|
+
voicesMenu.empty();
|
|
170
|
+
const bookLanguage = this.ttsEngine.opts.bookLanguage;
|
|
171
|
+
const bookLanguages = this.ttsEngine.getVoices().filter(v => v.lang.startsWith(bookLanguage)).sort(voiceSortOrder);
|
|
172
|
+
const otherLanguages = this.ttsEngine.getVoices().filter(v => !v.lang.startsWith(bookLanguage)).sort(voiceSortOrder);
|
|
173
|
+
|
|
174
|
+
if (this.ttsEngine.getVoices().length > 1) {
|
|
175
|
+
voicesMenu.append($(`<optgroup label="Book Language (${bookLanguage})"> ${renderVoiceOption(bookLanguages)} </optgroup>`));
|
|
176
|
+
voicesMenu.append($(`<optgroup label="Other Languages"> ${renderVoiceOption(otherLanguages)} </optgroup>`));
|
|
177
|
+
|
|
178
|
+
voicesMenu.val(this.ttsEngine.voice.voiceURI);
|
|
179
|
+
voicesMenu.show();
|
|
180
|
+
} else {
|
|
181
|
+
voicesMenu.hide();
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const voicesMenu = this.refs.$BRReadAloudToolbar.find('[name=playback-voice]');
|
|
186
|
+
renderVoicesMenu(voicesMenu);
|
|
187
|
+
voicesMenu.on("change", ev => this.ttsEngine.setVoice(voicesMenu.val()));
|
|
152
188
|
this.ttsEngine.events.on('pause resume start', () => this.ttsUpdateState());
|
|
153
|
-
this.
|
|
154
|
-
this.refs.$BRReadAloudToolbar.find('[name=
|
|
155
|
-
this.refs.$BRReadAloudToolbar.find('[name=
|
|
189
|
+
this.ttsEngine.events.on('voiceschanged', () => renderVoicesMenu(voicesMenu));
|
|
190
|
+
this.refs.$BRReadAloudToolbar.find('[name=play]').on("click", this.ttsPlayPause.bind(this));
|
|
191
|
+
this.refs.$BRReadAloudToolbar.find('[name=advance]').on("click", this.ttsJumpForward.bind(this));
|
|
192
|
+
this.refs.$BRReadAloudToolbar.find('[name=review]').on("click", this.ttsJumpBackward.bind(this));
|
|
156
193
|
const $rateSelector = this.refs.$BRReadAloudToolbar.find('select[name="playback-speed"]');
|
|
157
|
-
$rateSelector.change
|
|
194
|
+
$rateSelector.on("change", ev => this.ttsEngine.setPlaybackRate(parseFloat($rateSelector.val())));
|
|
158
195
|
$(`<li>
|
|
159
196
|
<button class="BRicon read js-tooltip" title="${tooltips.readAloud}">
|
|
160
197
|
<div class="icon icon-read-aloud"></div>
|
|
161
|
-
<span class="
|
|
198
|
+
<span class="BRtooltip">${tooltips.readAloud}</span>
|
|
162
199
|
</button>
|
|
163
200
|
</li>`).insertBefore($el.find('.BRcontrols .BRicon.zoom_out').closest('li'));
|
|
164
201
|
}
|
|
@@ -187,7 +224,7 @@ BookReader.prototype.ttsStart = function (startTTSEngine = true) {
|
|
|
187
224
|
this.$('.BRicon.read').addClass('unread active');
|
|
188
225
|
this.ttsSendAnalyticsEvent('Start');
|
|
189
226
|
if (startTTSEngine)
|
|
190
|
-
this.ttsEngine.start(this.currentIndex(), this.getNumLeafs());
|
|
227
|
+
this.ttsEngine.start(this.currentIndex(), this.book.getNumLeafs());
|
|
191
228
|
};
|
|
192
229
|
|
|
193
230
|
BookReader.prototype.ttsJumpForward = function () {
|
|
@@ -214,7 +251,7 @@ BookReader.prototype.ttsPlayPause = function() {
|
|
|
214
251
|
this.ttsToggle();
|
|
215
252
|
} else {
|
|
216
253
|
this.ttsEngine.togglePlayPause();
|
|
217
|
-
this.ttsUpdateState(
|
|
254
|
+
this.ttsUpdateState();
|
|
218
255
|
}
|
|
219
256
|
};
|
|
220
257
|
|
|
@@ -233,12 +270,10 @@ BookReader.prototype.ttsStop = function () {
|
|
|
233
270
|
* @param {PageChunk} chunk
|
|
234
271
|
* @return {PromiseLike<void>} returns once the flip is done
|
|
235
272
|
*/
|
|
236
|
-
BookReader.prototype.ttsBeforeChunkPlay = function(chunk) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
this.ttsScrollToChunk(chunk);
|
|
241
|
-
});
|
|
273
|
+
BookReader.prototype.ttsBeforeChunkPlay = async function(chunk) {
|
|
274
|
+
await this.ttsMaybeFlipToIndex(chunk.leafIndex);
|
|
275
|
+
this.ttsHighlightChunk(chunk);
|
|
276
|
+
this.ttsScrollToChunk(chunk);
|
|
242
277
|
};
|
|
243
278
|
|
|
244
279
|
/**
|
|
@@ -251,129 +286,63 @@ BookReader.prototype.ttsSendChunkFinishedAnalyticsEvent = function(chunk) {
|
|
|
251
286
|
/**
|
|
252
287
|
* Flip the page if the provided leaf index is not visible
|
|
253
288
|
* @param {Number} leafIndex
|
|
254
|
-
* @return {PromiseLike<void>} resolves once the flip animation has completed
|
|
255
289
|
*/
|
|
256
|
-
BookReader.prototype.ttsMaybeFlipToIndex = function (leafIndex) {
|
|
257
|
-
|
|
258
|
-
let resolve = null;
|
|
259
|
-
const promise = new Promise(res => resolve = res);
|
|
260
|
-
|
|
261
|
-
if (!in2PageMode) {
|
|
290
|
+
BookReader.prototype.ttsMaybeFlipToIndex = async function (leafIndex) {
|
|
291
|
+
if (this.constMode2up != this.mode) {
|
|
262
292
|
this.jumpToIndex(leafIndex);
|
|
263
|
-
resolve();
|
|
264
293
|
} else {
|
|
265
|
-
|
|
266
|
-
if (leafVisible) {
|
|
267
|
-
resolve();
|
|
268
|
-
} else {
|
|
269
|
-
this.animationFinishedCallback = resolve;
|
|
270
|
-
const mustGoNext = leafIndex > Math.max(this.twoPage.currentIndexR, this.twoPage.currentIndexL);
|
|
271
|
-
if (mustGoNext) this.next();
|
|
272
|
-
else this.prev();
|
|
273
|
-
promise.then(this.ttsMaybeFlipToIndex.bind(this, leafIndex));
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return promise;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* @param {PageChunk} chunk
|
|
282
|
-
*/
|
|
283
|
-
BookReader.prototype.ttsHighlightChunk = function(chunk) {
|
|
284
|
-
this.ttsRemoveHilites();
|
|
285
|
-
|
|
286
|
-
if (this.constMode2up == this.mode) {
|
|
287
|
-
this.ttsHilite2UP(chunk);
|
|
288
|
-
} else {
|
|
289
|
-
this.ttsHilite1UP(chunk);
|
|
294
|
+
await this._modes.mode2Up.mode2UpLit.jumpToIndex(leafIndex);
|
|
290
295
|
}
|
|
291
296
|
};
|
|
292
297
|
|
|
293
298
|
/**
|
|
294
299
|
* @param {PageChunk} chunk
|
|
295
300
|
*/
|
|
296
|
-
BookReader.prototype.
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
let leafTop = 0;
|
|
300
|
-
let h;
|
|
301
|
-
let i;
|
|
302
|
-
for (i = 0; i < chunk.leafIndex; i++) {
|
|
303
|
-
h = parseInt(this._getPageHeight(i) / this.reduce);
|
|
304
|
-
leafTop += h + this.padding;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const chunkTop = chunk.lineRects[0][3]; //coords are in l,b,r,t order
|
|
308
|
-
const chunkBot = chunk.lineRects[chunk.lineRects.length - 1][1];
|
|
309
|
-
|
|
310
|
-
const topOfFirstChunk = leafTop + chunkTop / this.reduce;
|
|
311
|
-
const botOfLastChunk = leafTop + chunkBot / this.reduce;
|
|
312
|
-
|
|
313
|
-
if (window?.soundManager?.debugMode) console.log('leafTop = ' + leafTop + ' topOfFirstChunk = ' + topOfFirstChunk + ' botOfLastChunk = ' + botOfLastChunk);
|
|
301
|
+
BookReader.prototype.ttsHighlightChunk = function(chunk) {
|
|
302
|
+
// The poorly-named variable leafIndex
|
|
303
|
+
const pageIndex = chunk.leafIndex;
|
|
314
304
|
|
|
315
|
-
|
|
316
|
-
const containerBot = containerTop + this.refs.$brContainer.height();
|
|
317
|
-
if (window?.soundManager?.debugMode) console.log('containerTop = ' + containerTop + ' containerBot = ' + containerBot);
|
|
305
|
+
this.ttsRemoveHilites();
|
|
318
306
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
};
|
|
307
|
+
// group by index; currently only possible to have chunks on one page :/
|
|
308
|
+
this._ttsBoxesByIndex = {
|
|
309
|
+
[pageIndex]: chunk.lineRects.map(([l, b, r, t]) => ({l, r, b, t}))
|
|
310
|
+
};
|
|
323
311
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const l = chunk.lineRects[i][0];
|
|
331
|
-
const b = chunk.lineRects[i][1];
|
|
332
|
-
const r = chunk.lineRects[i][2];
|
|
333
|
-
const t = chunk.lineRects[i][3];
|
|
334
|
-
|
|
335
|
-
const div = document.createElement('div');
|
|
336
|
-
this.ttsHilites.push(div);
|
|
337
|
-
$(div).prop('className', 'BookReaderSearchHilite').appendTo(
|
|
338
|
-
this.$('.pagediv' + chunk.leafIndex)
|
|
339
|
-
);
|
|
340
|
-
|
|
341
|
-
$(div).css({
|
|
342
|
-
width: (r - l) / this.reduce + 'px',
|
|
343
|
-
height: (b - t) / this.reduce + 'px',
|
|
344
|
-
left: l / this.reduce + 'px',
|
|
345
|
-
top: t / this.reduce + 'px'
|
|
346
|
-
});
|
|
312
|
+
// update any already created pages
|
|
313
|
+
for (const [pageIndexString, boxes] of Object.entries(this._ttsBoxesByIndex)) {
|
|
314
|
+
const pageIndex = parseFloat(pageIndexString);
|
|
315
|
+
const page = this.book.getPage(pageIndex);
|
|
316
|
+
const pageContainers = this.getActivePageContainerElementsForIndex(pageIndex);
|
|
317
|
+
pageContainers.forEach(container => renderBoxesInPageContainerLayer('ttsHiliteLayer', boxes, page, container));
|
|
347
318
|
}
|
|
348
|
-
|
|
349
319
|
};
|
|
350
320
|
|
|
351
321
|
/**
|
|
352
322
|
* @param {PageChunk} chunk
|
|
353
323
|
*/
|
|
354
|
-
BookReader.prototype.
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
324
|
+
BookReader.prototype.ttsScrollToChunk = function(chunk) {
|
|
325
|
+
// It behaves weird if used in thumb mode
|
|
326
|
+
if (this.constModeThumb == this.mode) return;
|
|
327
|
+
|
|
328
|
+
$(`.pagediv${chunk.leafIndex} .ttsHiliteLayer rect`).last()?.[0]?.scrollIntoView({
|
|
329
|
+
// Only vertically center the highlight if we're in 1up or in full screen. In
|
|
330
|
+
// 2up, if we're not fullscreen, the whole body gets scrolled around to try to
|
|
331
|
+
// center the highlight 🙄 See:
|
|
332
|
+
// https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move/11041376
|
|
333
|
+
// Note: nearest doesn't quite work great, because the ReadAloud toolbar is now
|
|
334
|
+
// full-width, and covers up the last line of the highlight.
|
|
335
|
+
block: this.constMode1up == this.mode || this.isFullscreenActive ? 'center' : 'nearest',
|
|
336
|
+
inline: 'center',
|
|
337
|
+
behavior: 'smooth',
|
|
338
|
+
});
|
|
370
339
|
};
|
|
371
340
|
|
|
372
341
|
// ttsRemoveHilites()
|
|
373
342
|
//______________________________________________________________________________
|
|
374
343
|
BookReader.prototype.ttsRemoveHilites = function () {
|
|
375
|
-
$(this.
|
|
376
|
-
this.
|
|
344
|
+
$(this.getActivePageContainerElements()).find('.ttsHiliteLayer').remove();
|
|
345
|
+
this._ttsBoxesByIndex = {};
|
|
377
346
|
};
|
|
378
347
|
|
|
379
348
|
/**
|
package/src/plugins/tts/utils.js
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
1
|
import langs from 'iso-language-codes/js/data.js';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Convert a EventTarget style event into a promise
|
|
5
|
-
* @param {EventTarget} target
|
|
6
|
-
* @param {string} eventType
|
|
7
|
-
* @return {Promise<Event>}
|
|
8
|
-
*/
|
|
9
|
-
export function promisifyEvent(target, eventType) {
|
|
10
|
-
return new Promise(res => {
|
|
11
|
-
const resolver = ev => {
|
|
12
|
-
target.removeEventListener(eventType, resolver);
|
|
13
|
-
res(ev);
|
|
14
|
-
};
|
|
15
|
-
target.addEventListener(eventType, resolver);
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
3
|
/**
|
|
20
4
|
* Use regex to approximate word count in a string
|
|
21
5
|
* @param {string} text
|
|
@@ -26,15 +10,6 @@ export function approximateWordCount(text) {
|
|
|
26
10
|
return m ? m.length : 0;
|
|
27
11
|
}
|
|
28
12
|
|
|
29
|
-
/**
|
|
30
|
-
* Waits the provided number of ms and then resolves with a promise
|
|
31
|
-
* @param {number} ms
|
|
32
|
-
* @return {Promise}
|
|
33
|
-
*/
|
|
34
|
-
export function sleep(ms) {
|
|
35
|
-
return new Promise(res => setTimeout(res, ms));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
13
|
/**
|
|
39
14
|
* Checks whether the current browser is on android
|
|
40
15
|
* @param {string} [userAgent]
|
|
@@ -89,3 +64,18 @@ function searchForISO6391(language, columnsToSearch) {
|
|
|
89
64
|
}
|
|
90
65
|
return null;
|
|
91
66
|
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Checks whether the current browser supports localStorage or
|
|
70
|
+
* if the current context has access to it.
|
|
71
|
+
* @return {boolean}
|
|
72
|
+
*/
|
|
73
|
+
export function hasLocalStorage() {
|
|
74
|
+
try {
|
|
75
|
+
return !!window.localStorage;
|
|
76
|
+
} catch (e) {
|
|
77
|
+
// Will throw in sandboxed iframe
|
|
78
|
+
// DOMException: Window.localStorage getter: Forbidden in a sandboxed document without the 'allow-same-origin' flag.
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
export class UrlPlugin {
|
|
2
|
+
constructor(options = {}) {
|
|
3
|
+
this.bookReaderOptions = options;
|
|
4
|
+
|
|
5
|
+
// the canonical order of elements is important in the path and query string
|
|
6
|
+
this.urlSchema = [
|
|
7
|
+
{ name: 'page', position: 'path', default: 'n0' },
|
|
8
|
+
{ name: 'mode', position: 'path', default: '2up' },
|
|
9
|
+
{ name: 'search', position: 'path', deprecated_for: 'q' },
|
|
10
|
+
{ name: 'q', position: 'query_param' },
|
|
11
|
+
{ name: 'sort', position: 'query_param' },
|
|
12
|
+
{ name: 'view', position: 'query_param' },
|
|
13
|
+
{ name: 'admin', position: 'query_param' },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
this.urlState = {};
|
|
17
|
+
this.urlMode = this.bookReaderOptions.urlMode || 'hash';
|
|
18
|
+
this.urlHistoryBasePath = this.bookReaderOptions.urlHistoryBasePath || '/';
|
|
19
|
+
this.urlLocationPollId = null;
|
|
20
|
+
this.oldLocationHash = null;
|
|
21
|
+
this.oldUserHash = null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Parse JSON object URL state to string format
|
|
26
|
+
* Arrange path names in an order that it is positioned on the urlSchema
|
|
27
|
+
* @param {Object} urlState
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
urlStateToUrlString(urlState) {
|
|
31
|
+
const searchParams = new URLSearchParams();
|
|
32
|
+
const pathParams = {};
|
|
33
|
+
|
|
34
|
+
Object.keys(urlState).forEach(key => {
|
|
35
|
+
let schema = this.urlSchema.find(schema => schema.name === key);
|
|
36
|
+
if (schema?.deprecated_for) {
|
|
37
|
+
schema = this.urlSchema.find(schemaKey => schemaKey.name === schema.deprecated_for);
|
|
38
|
+
}
|
|
39
|
+
if (schema?.position == 'path') {
|
|
40
|
+
pathParams[schema?.name] = urlState[key];
|
|
41
|
+
} else {
|
|
42
|
+
searchParams.append(schema?.name || key, urlState[key]);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const strPathParams = this.urlSchema
|
|
47
|
+
.filter(s => s.position == 'path')
|
|
48
|
+
.map(schema => pathParams[schema.name] ? `${schema.name}/${encodeURIComponent(pathParams[schema.name])}` : '')
|
|
49
|
+
.join('/');
|
|
50
|
+
|
|
51
|
+
// replace consecutive slashes with a single slash + remove trailing slashes
|
|
52
|
+
const strStrippedTrailingSlash = `${strPathParams.replace(/\/+/g, '/').replace(/\/+$/, '')}`;
|
|
53
|
+
const concatenatedPath = `${strStrippedTrailingSlash}?${searchParams.toString()}`;
|
|
54
|
+
return searchParams.toString() ? concatenatedPath : `${strStrippedTrailingSlash}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Parse string URL and add it in the current urlState
|
|
59
|
+
* Example:
|
|
60
|
+
* /page/n7/mode/2up => {page: 'n7', mode: '2up'}
|
|
61
|
+
* /page/n7/mode/2up/search/hello => {page: 'n7', mode: '2up', q: 'hello'}
|
|
62
|
+
* @param {string} urlString
|
|
63
|
+
* @returns {object}
|
|
64
|
+
*/
|
|
65
|
+
urlStringToUrlState(urlString) {
|
|
66
|
+
const urlState = {};
|
|
67
|
+
|
|
68
|
+
// Fetch searchParams from given {str}
|
|
69
|
+
// Note: whole URL path is needed for URL parsing
|
|
70
|
+
const urlPath = new URL(urlString, 'http://example.com');
|
|
71
|
+
const urlSearchParamsObj = Object.fromEntries(urlPath.searchParams.entries());
|
|
72
|
+
const splitUrlMatches = urlPath.pathname.match(/[^\\/]+\/[^\\/]+/g);
|
|
73
|
+
const urlStrSplitSlashObj = splitUrlMatches ? Object.fromEntries(splitUrlMatches.map(x => x.split('/'))) : {};
|
|
74
|
+
|
|
75
|
+
const doesKeyExists = (_object, _key) => {
|
|
76
|
+
return Object.keys(_object).some(value => value == _key);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Add path objects to urlState
|
|
80
|
+
this.urlSchema
|
|
81
|
+
.filter(schema => schema.position == 'path')
|
|
82
|
+
.forEach(schema => {
|
|
83
|
+
const hasPropertyKey = doesKeyExists(urlStrSplitSlashObj, schema.name);
|
|
84
|
+
const hasDeprecatedKey = doesKeyExists(schema, 'deprecated_for') && hasPropertyKey;
|
|
85
|
+
|
|
86
|
+
// Not in the URL
|
|
87
|
+
if (!hasPropertyKey && !hasDeprecatedKey) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const urlStateParam = hasDeprecatedKey ? schema.deprecated_for : schema.name;
|
|
92
|
+
urlState[urlStateParam] = decodeURIComponent(urlStrSplitSlashObj[schema.name]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Add searchParams to urlState
|
|
96
|
+
Object.entries(urlSearchParamsObj).forEach(([key, value]) => {
|
|
97
|
+
urlState[key] = value;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
return urlState;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Add or update key-value to the urlState
|
|
105
|
+
* @param {string} key
|
|
106
|
+
* @param {string} val
|
|
107
|
+
*/
|
|
108
|
+
setUrlParam(key, value) {
|
|
109
|
+
this.urlState[key] = value;
|
|
110
|
+
|
|
111
|
+
this.pushToAddressBar();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Delete key-value to the urlState
|
|
116
|
+
* @param {string} key
|
|
117
|
+
*/
|
|
118
|
+
removeUrlParam(key) {
|
|
119
|
+
delete this.urlState[key];
|
|
120
|
+
|
|
121
|
+
this.pushToAddressBar();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get key-value from the urlState
|
|
126
|
+
* @param {string} key
|
|
127
|
+
* @return {string}
|
|
128
|
+
*/
|
|
129
|
+
getUrlParam(key) {
|
|
130
|
+
return this.urlState[key];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Push URL params to addressbar
|
|
135
|
+
*/
|
|
136
|
+
pushToAddressBar() {
|
|
137
|
+
const urlStrPath = this.urlStateToUrlString(this.urlState);
|
|
138
|
+
const concatenatedPath = urlStrPath !== '/' ? urlStrPath : '';
|
|
139
|
+
if (this.urlMode == 'history') {
|
|
140
|
+
if (!window.history || !window.history.replaceState) {
|
|
141
|
+
this.options.urlMode = 'hash';
|
|
142
|
+
} else {
|
|
143
|
+
const newUrlPath = `${this.urlHistoryBasePath}${concatenatedPath}`.trim().replace(/(\/+)/g, '/');
|
|
144
|
+
try {
|
|
145
|
+
window.history.replaceState({}, null, newUrlPath);
|
|
146
|
+
} catch (e) {
|
|
147
|
+
// DOMException on Chrome when in sandboxed iframe
|
|
148
|
+
this.urlMode = 'hash';
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (this.urlMode == 'hash') {
|
|
154
|
+
window.location.replace('#' + concatenatedPath);
|
|
155
|
+
}
|
|
156
|
+
this.oldLocationHash = urlStrPath;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get the url and check if it has changed
|
|
161
|
+
* If it was changeed, update the urlState
|
|
162
|
+
*/
|
|
163
|
+
listenForHashChanges() {
|
|
164
|
+
this.oldLocationHash = window.location.hash.substr(1);
|
|
165
|
+
if (this.urlLocationPollId) {
|
|
166
|
+
clearInterval(this.urlLocationPollId);
|
|
167
|
+
this.urlLocationPollId = null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// check if the URL changes
|
|
171
|
+
const updateHash = () => {
|
|
172
|
+
const newFragment = window.location.hash.substr(1);
|
|
173
|
+
const hasFragmentChange = newFragment != this.oldLocationHash;
|
|
174
|
+
|
|
175
|
+
if (!hasFragmentChange) { return; }
|
|
176
|
+
|
|
177
|
+
this.urlState = this.urlStringToUrlState(newFragment);
|
|
178
|
+
};
|
|
179
|
+
this.urlLocationPollId = setInterval(updateHash, 500);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Will read either the hash or URL and return the bookreader fragment
|
|
184
|
+
*/
|
|
185
|
+
pullFromAddressBar (location = window.location) {
|
|
186
|
+
const path = this.urlMode === 'history'
|
|
187
|
+
? (location.pathname.substr(this.urlHistoryBasePath.length) + location.search)
|
|
188
|
+
: location.hash.substr(1);
|
|
189
|
+
this.urlState = this.urlStringToUrlState(path);
|
|
190
|
+
}
|
|
191
|
+
}
|