@internetarchive/bookreader 5.0.0-88-alpha.11 → 5.0.0-89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BookReader/BookReader.css +17 -3
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +87 -108
- package/BookReader/ia-bookreader-bundle.js.map +1 -1
- package/BookReader/plugins/plugin.archive_analytics.js +1 -1
- package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
- package/BookReader/plugins/plugin.autoplay.js +1 -1
- package/BookReader/plugins/plugin.autoplay.js.map +1 -1
- package/BookReader/plugins/plugin.iiif.js +1 -1
- package/BookReader/plugins/plugin.iiif.js.map +1 -1
- package/BookReader/plugins/plugin.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +1 -1
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +1 -1
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReader/plugins/plugin.url.js +1 -1
- package/BookReader/plugins/plugin.url.js.map +1 -1
- package/CHANGELOG.md +14 -0
- package/babel.config.js +12 -30
- package/codecov.yml +1 -1
- package/jsconfig.json +1 -3
- package/package.json +14 -16
- package/src/BookNavigator/search/search-results.js +1 -1
- package/src/BookReader/ImageCache.js +48 -15
- package/src/BookReader/Mode1UpLit.js +56 -86
- package/src/BookReader/Mode2UpLit.js +5 -5
- package/src/BookReader/Navbar/Navbar.js +53 -11
- package/src/BookReader/PageContainer.js +41 -22
- package/src/BookReader/options.js +27 -3
- package/src/BookReader/utils.js +10 -0
- package/src/BookReader.js +120 -21
- package/src/BookReaderPlugin.js +44 -0
- package/src/css/_BRnav.scss +0 -3
- package/src/css/_BRpages.scss +21 -2
- package/src/css/_controls.scss +4 -0
- package/src/plugins/plugin.archive_analytics.js +84 -78
- package/src/plugins/plugin.autoplay.js +98 -102
- package/src/plugins/plugin.chapters.js +17 -22
- package/src/plugins/plugin.iiif.js +16 -30
- package/src/plugins/plugin.resume.js +54 -51
- package/src/plugins/plugin.text_selection.js +68 -76
- package/src/plugins/tts/AbstractTTSEngine.js +2 -4
- package/src/plugins/tts/PageChunk.js +5 -9
- package/src/plugins/tts/PageChunkIterator.js +3 -5
- package/src/plugins/tts/plugin.tts.js +309 -329
- package/src/plugins/url/plugin.url.js +1 -1
- package/src/util/strings.js +1 -0
- package/tests/e2e/autoplay.test.js +8 -5
- package/tests/e2e/helpers/base.js +2 -2
- package/tests/e2e/helpers/mockSearch.js +6 -9
- package/tests/jest/BookReader/Navbar/Navbar.test.js +16 -3
- package/tests/jest/BookReader/PageContainer.test.js +96 -55
- package/tests/jest/BookReader/utils.test.js +21 -0
- package/tests/jest/BookReader.test.js +13 -12
- package/tests/jest/plugins/plugin.archive_analytics.test.js +8 -11
- package/tests/jest/plugins/plugin.autoplay.test.js +9 -22
- package/tests/jest/plugins/plugin.resume.test.js +19 -32
- package/tests/jest/plugins/plugin.text_selection.test.js +23 -24
- package/dist/esm/BookNavigator/assets/bookmark-colors.js +0 -4
- package/dist/esm/BookNavigator/assets/button-base.js +0 -4
- package/dist/esm/BookNavigator/assets/ia-logo.js +0 -4
- package/dist/esm/BookNavigator/assets/icon_checkmark.js +0 -8
- package/dist/esm/BookNavigator/assets/icon_close.js +0 -4
- package/dist/esm/BookNavigator/book-navigator.js +0 -612
- package/dist/esm/BookNavigator/bookmarks/bookmark-button.js +0 -35
- package/dist/esm/BookNavigator/bookmarks/bookmark-edit.js +0 -78
- package/dist/esm/BookNavigator/bookmarks/bookmarks-list.js +0 -160
- package/dist/esm/BookNavigator/bookmarks/bookmarks-loginCTA.js +0 -24
- package/dist/esm/BookNavigator/bookmarks/bookmarks-provider.js +0 -55
- package/dist/esm/BookNavigator/bookmarks/ia-bookmarks.js +0 -521
- package/dist/esm/BookNavigator/delete-modal-actions.js +0 -29
- package/dist/esm/BookNavigator/downloads/downloads-provider.js +0 -84
- package/dist/esm/BookNavigator/downloads/downloads.js +0 -69
- package/dist/esm/BookNavigator/search/search-provider.js +0 -238
- package/dist/esm/BookNavigator/search/search-results.js +0 -161
- package/dist/esm/BookNavigator/sharing.js +0 -26
- package/dist/esm/BookNavigator/viewable-files.js +0 -94
- package/dist/esm/BookNavigator/visual-adjustments/visual-adjustments-provider.js +0 -83
- package/dist/esm/BookNavigator/visual-adjustments/visual-adjustments.js +0 -131
- package/dist/esm/BookReader/BookModel.js +0 -575
- package/dist/esm/BookReader/DragScrollable.js +0 -224
- package/dist/esm/BookReader/ImageCache.js +0 -122
- package/dist/esm/BookReader/Mode1Up.js +0 -114
- package/dist/esm/BookReader/Mode1UpLit.js +0 -579
- package/dist/esm/BookReader/Mode2Up.js +0 -106
- package/dist/esm/BookReader/Mode2UpLit.js +0 -1020
- package/dist/esm/BookReader/ModeCoordinateSpace.js +0 -28
- package/dist/esm/BookReader/ModeSmoothZoom.js +0 -318
- package/dist/esm/BookReader/ModeThumb.js +0 -366
- package/dist/esm/BookReader/Navbar/Navbar.js +0 -253
- package/dist/esm/BookReader/PageContainer.js +0 -165
- package/dist/esm/BookReader/ReduceSet.js +0 -27
- package/dist/esm/BookReader/Toolbar/Toolbar.js +0 -242
- package/dist/esm/BookReader/events.js +0 -20
- package/dist/esm/BookReader/options.js +0 -331
- package/dist/esm/BookReader/utils/HTMLDimensionsCacher.js +0 -48
- package/dist/esm/BookReader/utils/ScrollClassAdder.js +0 -31
- package/dist/esm/BookReader/utils/SelectionObserver.js +0 -42
- package/dist/esm/BookReader/utils/classes.js +0 -37
- package/dist/esm/BookReader/utils.js +0 -315
- package/dist/esm/BookReader.js +0 -1828
- package/dist/esm/assets/icons/1up.svg +0 -12
- package/dist/esm/assets/icons/2up.svg +0 -15
- package/dist/esm/assets/icons/advance.svg +0 -26
- package/dist/esm/assets/icons/chevron-right.svg +0 -1
- package/dist/esm/assets/icons/close-circle-dark.svg +0 -1
- package/dist/esm/assets/icons/close-circle.svg +0 -1
- package/dist/esm/assets/icons/fullscreen.svg +0 -17
- package/dist/esm/assets/icons/fullscreen_exit.svg +0 -17
- package/dist/esm/assets/icons/hamburger.svg +0 -15
- package/dist/esm/assets/icons/left-arrow.svg +0 -12
- package/dist/esm/assets/icons/magnify-minus.svg +0 -12
- package/dist/esm/assets/icons/magnify-plus.svg +0 -13
- package/dist/esm/assets/icons/magnify.svg +0 -15
- package/dist/esm/assets/icons/pause.svg +0 -23
- package/dist/esm/assets/icons/play.svg +0 -22
- package/dist/esm/assets/icons/playback-speed.svg +0 -34
- package/dist/esm/assets/icons/read-aloud.svg +0 -22
- package/dist/esm/assets/icons/review.svg +0 -22
- package/dist/esm/assets/icons/thumbnails.svg +0 -17
- package/dist/esm/assets/icons/voice.svg +0 -1
- package/dist/esm/assets/icons/volume-full.svg +0 -22
- package/dist/esm/assets/images/BRicons.png +0 -0
- package/dist/esm/assets/images/BRicons.svg +0 -94
- package/dist/esm/assets/images/BRicons_ia.png +0 -0
- package/dist/esm/assets/images/back_pages.png +0 -0
- package/dist/esm/assets/images/book_bottom_icon.png +0 -0
- package/dist/esm/assets/images/book_down_icon.png +0 -0
- package/dist/esm/assets/images/book_left_icon.png +0 -0
- package/dist/esm/assets/images/book_leftmost_icon.png +0 -0
- package/dist/esm/assets/images/book_right_icon.png +0 -0
- package/dist/esm/assets/images/book_rightmost_icon.png +0 -0
- package/dist/esm/assets/images/book_top_icon.png +0 -0
- package/dist/esm/assets/images/book_up_icon.png +0 -0
- package/dist/esm/assets/images/books_graphic.svg +0 -177
- package/dist/esm/assets/images/booksplit.png +0 -0
- package/dist/esm/assets/images/control_pause_icon.png +0 -0
- package/dist/esm/assets/images/control_play_icon.png +0 -0
- package/dist/esm/assets/images/embed_icon.png +0 -0
- package/dist/esm/assets/images/icon-home-ia.png +0 -0
- package/dist/esm/assets/images/icon_OL-logo-xs.png +0 -0
- package/dist/esm/assets/images/icon_alert-xs.png +0 -0
- package/dist/esm/assets/images/icon_book.svg +0 -12
- package/dist/esm/assets/images/icon_bookmark.svg +0 -12
- package/dist/esm/assets/images/icon_close-pop.png +0 -0
- package/dist/esm/assets/images/icon_download.png +0 -0
- package/dist/esm/assets/images/icon_gear.svg +0 -14
- package/dist/esm/assets/images/icon_hamburger.svg +0 -20
- package/dist/esm/assets/images/icon_home.png +0 -0
- package/dist/esm/assets/images/icon_home.svg +0 -21
- package/dist/esm/assets/images/icon_home_ia.png +0 -0
- package/dist/esm/assets/images/icon_indicator.png +0 -0
- package/dist/esm/assets/images/icon_info.svg +0 -11
- package/dist/esm/assets/images/icon_one_page.svg +0 -8
- package/dist/esm/assets/images/icon_pause.svg +0 -1
- package/dist/esm/assets/images/icon_play.svg +0 -1
- package/dist/esm/assets/images/icon_playback-rate.svg +0 -15
- package/dist/esm/assets/images/icon_return.png +0 -0
- package/dist/esm/assets/images/icon_search_button.svg +0 -8
- package/dist/esm/assets/images/icon_share.svg +0 -9
- package/dist/esm/assets/images/icon_skip-ahead.svg +0 -6
- package/dist/esm/assets/images/icon_skip-back.svg +0 -13
- package/dist/esm/assets/images/icon_speaker.svg +0 -18
- package/dist/esm/assets/images/icon_speaker_open.svg +0 -10
- package/dist/esm/assets/images/icon_thumbnails.svg +0 -12
- package/dist/esm/assets/images/icon_toc.svg +0 -5
- package/dist/esm/assets/images/icon_two_pages.svg +0 -9
- package/dist/esm/assets/images/icon_zoomer.png +0 -0
- package/dist/esm/assets/images/loading.gif +0 -0
- package/dist/esm/assets/images/logo_icon.png +0 -0
- package/dist/esm/assets/images/marker_chap-off.png +0 -0
- package/dist/esm/assets/images/marker_chap-off.svg +0 -11
- package/dist/esm/assets/images/marker_chap-off_ia.png +0 -0
- package/dist/esm/assets/images/marker_chap-on.png +0 -0
- package/dist/esm/assets/images/marker_chap-on.svg +0 -11
- package/dist/esm/assets/images/marker_srch-on.svg +0 -11
- package/dist/esm/assets/images/marker_srchchap-off.png +0 -0
- package/dist/esm/assets/images/marker_srchchap-on.png +0 -0
- package/dist/esm/assets/images/nav_control-dn.png +0 -0
- package/dist/esm/assets/images/nav_control-dn_ia.png +0 -0
- package/dist/esm/assets/images/nav_control-up.png +0 -0
- package/dist/esm/assets/images/nav_control-up_ia.png +0 -0
- package/dist/esm/assets/images/nav_control.png +0 -0
- package/dist/esm/assets/images/one_page_mode_icon.png +0 -0
- package/dist/esm/assets/images/paper-badge.png +0 -0
- package/dist/esm/assets/images/print_icon.png +0 -0
- package/dist/esm/assets/images/progressbar.gif +0 -0
- package/dist/esm/assets/images/right_edges.png +0 -0
- package/dist/esm/assets/images/slider.png +0 -0
- package/dist/esm/assets/images/slider_ia.png +0 -0
- package/dist/esm/assets/images/thumbnail_mode_icon.png +0 -0
- package/dist/esm/assets/images/transparent.png +0 -0
- package/dist/esm/assets/images/two_page_mode_icon.png +0 -0
- package/dist/esm/assets/images/unviewable_page.png +0 -0
- package/dist/esm/assets/images/zoom_in_icon.png +0 -0
- package/dist/esm/assets/images/zoom_out_icon.png +0 -0
- package/dist/esm/css/BookReader.scss +0 -85
- package/dist/esm/css/_BRBookmarks.scss +0 -29
- package/dist/esm/css/_BRComponent.scss +0 -13
- package/dist/esm/css/_BRfloat.scss +0 -197
- package/dist/esm/css/_BRicon.scss +0 -54
- package/dist/esm/css/_BRmain.scss +0 -262
- package/dist/esm/css/_BRnav.scss +0 -354
- package/dist/esm/css/_BRpages.scss +0 -213
- package/dist/esm/css/_BRsearch.scss +0 -268
- package/dist/esm/css/_BRtoolbar.scss +0 -84
- package/dist/esm/css/_BRvendor.scss +0 -5
- package/dist/esm/css/_TextSelection.scss +0 -108
- package/dist/esm/css/_colorbox.scss +0 -52
- package/dist/esm/css/_controls.scss +0 -257
- package/dist/esm/css/_icons.scss +0 -121
- package/dist/esm/ia-bookreader/ia-bookreader.js +0 -141
- package/dist/esm/jquery-wrapper.js +0 -3
- package/dist/esm/plugins/plugin.archive_analytics.js +0 -72
- package/dist/esm/plugins/plugin.autoplay.js +0 -119
- package/dist/esm/plugins/plugin.chapters.js +0 -288
- package/dist/esm/plugins/plugin.iframe.js +0 -44
- package/dist/esm/plugins/plugin.iiif.js +0 -146
- package/dist/esm/plugins/plugin.resume.js +0 -66
- package/dist/esm/plugins/plugin.text_selection.js +0 -621
- package/dist/esm/plugins/plugin.vendor-fullscreen.js +0 -227
- package/dist/esm/plugins/search/plugin.search.js +0 -499
- package/dist/esm/plugins/search/utils.js +0 -42
- package/dist/esm/plugins/search/view.js +0 -360
- package/dist/esm/plugins/tts/AbstractTTSEngine.js +0 -282
- package/dist/esm/plugins/tts/FestivalTTSEngine.js +0 -192
- package/dist/esm/plugins/tts/PageChunk.js +0 -105
- package/dist/esm/plugins/tts/PageChunkIterator.js +0 -155
- package/dist/esm/plugins/tts/WebTTSEngine.js +0 -364
- package/dist/esm/plugins/tts/plugin.tts.js +0 -315
- package/dist/esm/plugins/tts/tooltip_dict.js +0 -14
- package/dist/esm/plugins/tts/utils.js +0 -79
- package/dist/esm/plugins/url/UrlPlugin.js +0 -197
- package/dist/esm/plugins/url/plugin.url.js +0 -212
- package/dist/esm/util/browserSniffing.js +0 -56
- package/dist/esm/util/debouncer.js +0 -25
- package/dist/esm/util/docCookies.js +0 -75
- package/dist/esm/util/strings.js +0 -34
- package/index.js +0 -2
package/dist/esm/BookReader.js
DELETED
@@ -1,1828 +0,0 @@
|
|
1
|
-
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
2
|
-
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
3
|
-
/*
|
4
|
-
Copyright(c)2008-2019 Internet Archive. Software license AGPL version 3.
|
5
|
-
|
6
|
-
This file is part of BookReader.
|
7
|
-
|
8
|
-
BookReader is free software: you can redistribute it and/or modify
|
9
|
-
it under the terms of the GNU Affero General Public License as published by
|
10
|
-
the Free Software Foundation, either version 3 of the License, or
|
11
|
-
(at your option) any later version.
|
12
|
-
|
13
|
-
BookReader is distributed in the hope that it will be useful,
|
14
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
-
GNU Affero General Public License for more details.
|
17
|
-
|
18
|
-
You should have received a copy of the GNU Affero General Public License
|
19
|
-
along with BookReader. If not, see <http://www.gnu.org/licenses/>.
|
20
|
-
|
21
|
-
The BookReader source is hosted at http://github.com/internetarchive/bookreader/
|
22
|
-
|
23
|
-
*/
|
24
|
-
// Needed by touch-punch
|
25
|
-
import 'jquery-ui/ui/widget.js';
|
26
|
-
import 'jquery-ui/ui/widgets/mouse.js';
|
27
|
-
import 'jquery-ui-touch-punch';
|
28
|
-
import jQuery from 'jquery';
|
29
|
-
|
30
|
-
// import PACKAGE_JSON from '../package.json';
|
31
|
-
import * as utils from './BookReader/utils.js';
|
32
|
-
import { exposeOverrideable } from './BookReader/utils/classes.js';
|
33
|
-
import { Navbar } from './BookReader/Navbar/Navbar.js';
|
34
|
-
import { DEFAULT_OPTIONS, OptionsParseError } from './BookReader/options.js';
|
35
|
-
/** @typedef {import('./BookReader/options.js').BookReaderOptions} BookReaderOptions */
|
36
|
-
/** @typedef {import('./BookReader/options.js').ReductionFactor} ReductionFactor */
|
37
|
-
/** @typedef {import('./BookReader/BookModel.js').PageIndex} PageIndex */
|
38
|
-
import { EVENTS } from './BookReader/events.js';
|
39
|
-
import { Toolbar } from './BookReader/Toolbar/Toolbar.js';
|
40
|
-
import { BookModel } from './BookReader/BookModel.js';
|
41
|
-
import { Mode1Up } from './BookReader/Mode1Up.js';
|
42
|
-
import { Mode2Up } from './BookReader/Mode2Up.js';
|
43
|
-
import { ModeThumb } from './BookReader/ModeThumb';
|
44
|
-
import { ImageCache } from './BookReader/ImageCache.js';
|
45
|
-
import { PageContainer } from './BookReader/PageContainer.js';
|
46
|
-
import { NAMED_REDUCE_SETS } from './BookReader/ReduceSet';
|
47
|
-
|
48
|
-
/**
|
49
|
-
* BookReader
|
50
|
-
* @param {BookReaderOptions} options
|
51
|
-
* TODO document all options properties
|
52
|
-
* @constructor
|
53
|
-
*/
|
54
|
-
export default function BookReader() {
|
55
|
-
var overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
56
|
-
var options = jQuery.extend(true, {}, BookReader.defaultOptions, overrides, BookReader.optionOverrides);
|
57
|
-
this.setup(options);
|
58
|
-
}
|
59
|
-
BookReader.version = '123';
|
60
|
-
|
61
|
-
// Mode constants
|
62
|
-
/** 1 page view */
|
63
|
-
BookReader.constMode1up = 1;
|
64
|
-
/** 2 pages view */
|
65
|
-
BookReader.constMode2up = 2;
|
66
|
-
/** thumbnails view */
|
67
|
-
BookReader.constModeThumb = 3;
|
68
|
-
/** image cache */
|
69
|
-
BookReader.imageCache = null;
|
70
|
-
|
71
|
-
// Animation constants
|
72
|
-
BookReader.constNavAnimationDuration = 300;
|
73
|
-
BookReader.constResizeAnimationDuration = 100;
|
74
|
-
|
75
|
-
// Names of events that can be triggered via BookReader.prototype.trigger()
|
76
|
-
BookReader.eventNames = EVENTS;
|
77
|
-
BookReader.defaultOptions = DEFAULT_OPTIONS;
|
78
|
-
|
79
|
-
/**
|
80
|
-
* @type {BookReaderOptions}
|
81
|
-
* This is here, just in case you need to absolutely override an option.
|
82
|
-
*/
|
83
|
-
BookReader.optionOverrides = {};
|
84
|
-
|
85
|
-
/**
|
86
|
-
* Setup
|
87
|
-
* It is separate from the constructor, so plugins can extend.
|
88
|
-
* @param {BookReaderOptions} options
|
89
|
-
*/
|
90
|
-
BookReader.prototype.setup = function (options) {
|
91
|
-
// Store the options used to setup bookreader
|
92
|
-
this.options = options;
|
93
|
-
|
94
|
-
/** @type {number} @deprecated some past iterations set this */
|
95
|
-
this.numLeafs = undefined;
|
96
|
-
|
97
|
-
/** Overridden by plugin.search.js */
|
98
|
-
this.enableSearch = false;
|
99
|
-
|
100
|
-
/**
|
101
|
-
* Store viewModeOrder states
|
102
|
-
* @var {boolean}
|
103
|
-
*/
|
104
|
-
this.viewModeOrder = [];
|
105
|
-
|
106
|
-
/**
|
107
|
-
* Used to suppress fragment change for init with canonical URLs
|
108
|
-
* @var {boolean}
|
109
|
-
*/
|
110
|
-
this.suppressFragmentChange = false;
|
111
|
-
|
112
|
-
/** @type {function(): void} */
|
113
|
-
this.animationFinishedCallback = null;
|
114
|
-
|
115
|
-
// @deprecated: Instance constants. Use Class constants instead
|
116
|
-
/** 1 page view */
|
117
|
-
this.constMode1up = BookReader.constMode1up;
|
118
|
-
/** 2 pages view */
|
119
|
-
this.constMode2up = BookReader.constMode2up;
|
120
|
-
/** thumbnails view */
|
121
|
-
this.constModeThumb = BookReader.constModeThumb;
|
122
|
-
|
123
|
-
// Private properties below. Configuration should be done with options.
|
124
|
-
/** @type {number} TODO: Make private */
|
125
|
-
this.reduce = 8; /* start very small */
|
126
|
-
this.defaults = options.defaults;
|
127
|
-
this.padding = options.padding;
|
128
|
-
this.reduceSet = NAMED_REDUCE_SETS[options.reduceSet];
|
129
|
-
if (!this.reduceSet) {
|
130
|
-
console.warn("Invalid reduceSet ".concat(options.reduceSet, ". Ignoring."));
|
131
|
-
this.reduceSet = NAMED_REDUCE_SETS[DEFAULT_OPTIONS.reduceSet];
|
132
|
-
}
|
133
|
-
|
134
|
-
/** @type {number}
|
135
|
-
* can be 1 or 2 or 3 based on the display mode const value
|
136
|
-
*/
|
137
|
-
this.mode = null;
|
138
|
-
this.prevReadMode = null;
|
139
|
-
this.ui = options.ui;
|
140
|
-
this.uiAutoHide = options.uiAutoHide;
|
141
|
-
this.thumbWidth = 100; // will be overridden during this._modes.modeThumb.prepare();
|
142
|
-
this.thumbRowBuffer = options.thumbRowBuffer;
|
143
|
-
this.thumbColumns = options.thumbColumns;
|
144
|
-
this.thumbMaxLoading = options.thumbMaxLoading;
|
145
|
-
this.thumbPadding = options.thumbPadding;
|
146
|
-
this.displayedRows = [];
|
147
|
-
this.displayedIndices = [];
|
148
|
-
this.animating = false;
|
149
|
-
this.flipSpeed = typeof options.flipSpeed === 'number' ? options.flipSpeed : {
|
150
|
-
'fast': 200,
|
151
|
-
'slow': 600
|
152
|
-
}[options.flipSpeed] || 400;
|
153
|
-
this.flipDelay = options.flipDelay;
|
154
|
-
|
155
|
-
/**
|
156
|
-
* Represents the first displayed index
|
157
|
-
* In 2up mode it will be the left page
|
158
|
-
* In 1 up mode it is the highest page
|
159
|
-
* @property {number|null} firstIndex
|
160
|
-
*/
|
161
|
-
this.firstIndex = null;
|
162
|
-
this.isFullscreenActive = options.startFullscreen || false;
|
163
|
-
this.lastScroll = null;
|
164
|
-
this.showLogo = options.showLogo;
|
165
|
-
this.logoURL = options.logoURL;
|
166
|
-
this.imagesBaseURL = options.imagesBaseURL;
|
167
|
-
this.reductionFactors = options.reductionFactors;
|
168
|
-
this.onePage = options.onePage;
|
169
|
-
/** @type {import('./BookReader/Mode2Up').TwoPageState} */
|
170
|
-
this.twoPage = options.twoPage;
|
171
|
-
this.onePageMinBreakpoint = options.onePageMinBreakpoint;
|
172
|
-
this.bookTitle = options.bookTitle;
|
173
|
-
this.bookUrl = options.bookUrl;
|
174
|
-
this.bookUrlText = options.bookUrlText;
|
175
|
-
this.bookUrlTitle = options.bookUrlTitle;
|
176
|
-
this.titleLeaf = options.titleLeaf;
|
177
|
-
this.metadata = options.metadata;
|
178
|
-
this.thumbnail = options.thumbnail;
|
179
|
-
this.bookUrlMoreInfo = options.bookUrlMoreInfo;
|
180
|
-
this.enableExperimentalControls = options.enableExperimentalControls;
|
181
|
-
this.el = options.el;
|
182
|
-
this.pageProgression = options.pageProgression;
|
183
|
-
this.protected = options.protected;
|
184
|
-
this.getEmbedCode = options.getEmbedCode;
|
185
|
-
this.popup = null;
|
186
|
-
|
187
|
-
// Assign the data methods
|
188
|
-
this.data = options.data;
|
189
|
-
|
190
|
-
/** @type {{[name: string]: JQuery}} */
|
191
|
-
this.refs = {};
|
192
|
-
|
193
|
-
/** The book being displayed in BookReader*/
|
194
|
-
this.book = new BookModel(this);
|
195
|
-
if (options.getNumLeafs) this.book.getNumLeafs = options.getNumLeafs.bind(this);
|
196
|
-
if (options.getPageWidth) this.book.getPageWidth = options.getPageWidth.bind(this);
|
197
|
-
if (options.getPageHeight) this.book.getPageHeight = options.getPageHeight.bind(this);
|
198
|
-
if (options.getPageURI) this.book.getPageURI = options.getPageURI.bind(this);
|
199
|
-
if (options.getPageSide) this.book.getPageSide = options.getPageSide.bind(this);
|
200
|
-
if (options.getPageNum) this.book.getPageNum = options.getPageNum.bind(this);
|
201
|
-
if (options.getPageProp) this.book.getPageProp = options.getPageProp.bind(this);
|
202
|
-
if (options.getSpreadIndices) this.book.getSpreadIndices = options.getSpreadIndices.bind(this);
|
203
|
-
if (options.leafNumToIndex) this.book.leafNumToIndex = options.leafNumToIndex.bind(this);
|
204
|
-
|
205
|
-
/**
|
206
|
-
* @private Components are 'subchunks' of bookreader functionality, usually UI related
|
207
|
-
* They should be relatively decoupled from each other/bookreader.
|
208
|
-
* Note there are no hooks right now; components just provide methods that bookreader
|
209
|
-
* calls at the correct moments.
|
210
|
-
**/
|
211
|
-
this._components = {
|
212
|
-
navbar: new Navbar(this),
|
213
|
-
toolbar: new Toolbar(this)
|
214
|
-
};
|
215
|
-
this._modes = {
|
216
|
-
mode1Up: new Mode1Up(this, this.book),
|
217
|
-
mode2Up: new Mode2Up(this, this.book),
|
218
|
-
modeThumb: new ModeThumb(this, this.book)
|
219
|
-
};
|
220
|
-
|
221
|
-
/** Stores classes which we want to expose (selectively) some methods as overridable */
|
222
|
-
this._overrideable = {
|
223
|
-
'book': this.book,
|
224
|
-
'_components.navbar': this._components.navbar,
|
225
|
-
'_components.toolbar': this._components.toolbar,
|
226
|
-
'_modes.mode1Up': this._modes.mode1Up,
|
227
|
-
'_modes.mode2Up': this._modes.mode2Up,
|
228
|
-
'_modes.modeThumb': this._modes.modeThumb
|
229
|
-
};
|
230
|
-
|
231
|
-
/** Image cache for general image fetching */
|
232
|
-
this.imageCache = new ImageCache(this.book, {
|
233
|
-
useSrcSet: this.options.useSrcSet,
|
234
|
-
reduceSet: this.reduceSet
|
235
|
-
});
|
236
|
-
|
237
|
-
/**
|
238
|
-
* Flag if BookReader has "focus" for keyboard shortcuts
|
239
|
-
* Initially true, set to false when:
|
240
|
-
* - BookReader scrolled out of view
|
241
|
-
* Set to true when:
|
242
|
-
* - BookReader scrolled into view
|
243
|
-
*/
|
244
|
-
this.hasKeyFocus = true;
|
245
|
-
};
|
246
|
-
|
247
|
-
/**
|
248
|
-
* Get all the HTML Elements that are being/can be rendered.
|
249
|
-
* Includes cached elements which might be rendered again.
|
250
|
-
*/
|
251
|
-
BookReader.prototype.getActivePageContainerElements = function () {
|
252
|
-
var containerEls = Object.values(this._modes.mode2Up.mode2UpLit.pageContainerCache).map(pc => pc.$container[0]).concat(Object.values(this._modes.mode1Up.mode1UpLit.pageContainerCache).map(pc => pc.$container[0]));
|
253
|
-
if (this.mode == this.constModeThumb) {
|
254
|
-
containerEls = containerEls.concat(this.$('.BRpagecontainer').toArray());
|
255
|
-
}
|
256
|
-
return containerEls;
|
257
|
-
};
|
258
|
-
|
259
|
-
/**
|
260
|
-
* Get the HTML Elements for the rendered page. Note there can be more than one, since
|
261
|
-
* (at least as of writing) different modes can maintain different caches.
|
262
|
-
* @param {PageIndex} pageIndex
|
263
|
-
*/
|
264
|
-
BookReader.prototype.getActivePageContainerElementsForIndex = function (pageIndex) {
|
265
|
-
var _this$_modes$mode2Up$, _this$_modes$mode1Up$;
|
266
|
-
return [(_this$_modes$mode2Up$ = this._modes.mode2Up.mode2UpLit.pageContainerCache[pageIndex]) === null || _this$_modes$mode2Up$ === void 0 || (_this$_modes$mode2Up$ = _this$_modes$mode2Up$.$container) === null || _this$_modes$mode2Up$ === void 0 ? void 0 : _this$_modes$mode2Up$[0], (_this$_modes$mode1Up$ = this._modes.mode1Up.mode1UpLit.pageContainerCache[pageIndex]) === null || _this$_modes$mode1Up$ === void 0 || (_this$_modes$mode1Up$ = _this$_modes$mode1Up$.$container) === null || _this$_modes$mode1Up$ === void 0 ? void 0 : _this$_modes$mode1Up$[0], ...(this.mode == this.constModeThumb ? this.$(".pagediv".concat(pageIndex)).toArray() : [])].filter(x => x);
|
267
|
-
};
|
268
|
-
Object.defineProperty(BookReader.prototype, 'activeMode', {
|
269
|
-
/** @return {Mode1Up | Mode2Up | ModeThumb} */
|
270
|
-
get() {
|
271
|
-
return {
|
272
|
-
1: this._modes.mode1Up,
|
273
|
-
2: this._modes.mode2Up,
|
274
|
-
3: this._modes.modeThumb
|
275
|
-
}[this.mode];
|
276
|
-
}
|
277
|
-
});
|
278
|
-
|
279
|
-
/**
|
280
|
-
* BookReader.util are static library functions
|
281
|
-
* At top of file so they can be used below
|
282
|
-
*/
|
283
|
-
BookReader.util = utils;
|
284
|
-
|
285
|
-
/**
|
286
|
-
* Helper to merge in params in to a params object.
|
287
|
-
* It normalizes "page" into the "index" field to disambiguate and prevent concflicts
|
288
|
-
* @private
|
289
|
-
*/
|
290
|
-
BookReader.prototype.extendParams = function (params, newParams) {
|
291
|
-
var modifiedNewParams = $.extend({}, newParams);
|
292
|
-
if ('undefined' != typeof modifiedNewParams.page) {
|
293
|
-
var pageIndex = this.book.parsePageString(modifiedNewParams.page);
|
294
|
-
if (!isNaN(pageIndex)) modifiedNewParams.index = pageIndex;
|
295
|
-
delete modifiedNewParams.page;
|
296
|
-
}
|
297
|
-
$.extend(params, modifiedNewParams);
|
298
|
-
};
|
299
|
-
|
300
|
-
/**
|
301
|
-
* Parses params from from various initialization contexts (url, cookie, options)
|
302
|
-
* @private
|
303
|
-
* @return {object} the parsed params
|
304
|
-
*/
|
305
|
-
BookReader.prototype.initParams = function () {
|
306
|
-
var params = {};
|
307
|
-
// Flag initializing for updateFromParams()
|
308
|
-
params.init = true;
|
309
|
-
|
310
|
-
// Flag if page given in defaults or URL (not cookie)
|
311
|
-
// Used for overriding goToFirstResult in plugin.search.js
|
312
|
-
// Note: extendParams() converts params.page to index and gets rid of page
|
313
|
-
// so check and set before extendParams()
|
314
|
-
params.pageFound = false;
|
315
|
-
|
316
|
-
// True if changing the URL
|
317
|
-
params.fragmentChange = false;
|
318
|
-
|
319
|
-
// This is ordered from lowest to highest priority
|
320
|
-
|
321
|
-
// If we have a title leaf, use that as the default instead of index 0,
|
322
|
-
// but only use as default if book has a few pages
|
323
|
-
if ('undefined' != typeof this.titleLeaf && this.book.getNumLeafs() > 2) {
|
324
|
-
params.index = this.book.leafNumToIndex(this.titleLeaf);
|
325
|
-
} else {
|
326
|
-
params.index = 0;
|
327
|
-
}
|
328
|
-
|
329
|
-
// this.defaults is a string passed in the url format. eg "page/1/mode/1up"
|
330
|
-
if (this.defaults) {
|
331
|
-
var defaultParams = this.paramsFromFragment(this.defaults);
|
332
|
-
if ('undefined' != typeof defaultParams.page) {
|
333
|
-
params.pageFound = true;
|
334
|
-
}
|
335
|
-
this.extendParams(params, defaultParams);
|
336
|
-
}
|
337
|
-
|
338
|
-
// Check for Resume plugin
|
339
|
-
if (this.options.enablePageResume) {
|
340
|
-
// Check cookies
|
341
|
-
var val = this.getResumeValue();
|
342
|
-
if (val !== null) {
|
343
|
-
// If page index different from default
|
344
|
-
if (params.index !== val) {
|
345
|
-
// Show in URL
|
346
|
-
params.fragmentChange = true;
|
347
|
-
}
|
348
|
-
params.index = val;
|
349
|
-
}
|
350
|
-
}
|
351
|
-
|
352
|
-
// Check for URL plugin
|
353
|
-
if (this.options.enableUrlPlugin) {
|
354
|
-
// Params explicitly set in URL take precedence over all other methods
|
355
|
-
var urlParams = this.paramsFromFragment(this.urlReadFragment());
|
356
|
-
|
357
|
-
// Get params if hash fragment available with 'history' urlMode
|
358
|
-
var hasHashURL = !Object.keys(urlParams).length && this.urlReadHashFragment();
|
359
|
-
if (hasHashURL && this.options.urlMode === 'history') {
|
360
|
-
urlParams = this.paramsFromFragment(this.urlReadHashFragment());
|
361
|
-
}
|
362
|
-
|
363
|
-
// If there were any parameters
|
364
|
-
if (Object.keys(urlParams).length) {
|
365
|
-
if ('undefined' != typeof urlParams.page) {
|
366
|
-
params.pageFound = true;
|
367
|
-
}
|
368
|
-
this.extendParams(params, urlParams);
|
369
|
-
// Show in URL
|
370
|
-
params.fragmentChange = true;
|
371
|
-
}
|
372
|
-
}
|
373
|
-
|
374
|
-
// Check for Search plugin
|
375
|
-
if (this.options.enableSearch) {
|
376
|
-
// Go to first result only if no default or URL page
|
377
|
-
this.options.goToFirstResult = !params.pageFound;
|
378
|
-
|
379
|
-
// If initialSearchTerm not set
|
380
|
-
if (!this.options.initialSearchTerm) {
|
381
|
-
// Look for any term in URL
|
382
|
-
if (params.search) {
|
383
|
-
// Old style: /search/[term]
|
384
|
-
this.options.initialSearchTerm = params.search;
|
385
|
-
this.searchTerm = params.search;
|
386
|
-
} else {
|
387
|
-
// If we have a query string: q=[term]
|
388
|
-
var searchParams = new URLSearchParams(this.readQueryString());
|
389
|
-
var searchTerm = searchParams.get('q');
|
390
|
-
if (searchTerm) {
|
391
|
-
this.options.initialSearchTerm = utils.decodeURIComponentPlus(searchTerm);
|
392
|
-
}
|
393
|
-
}
|
394
|
-
}
|
395
|
-
}
|
396
|
-
|
397
|
-
// Set for init process, return to false at end of init()
|
398
|
-
this.suppressFragmentChange = !params.fragmentChange;
|
399
|
-
return params;
|
400
|
-
};
|
401
|
-
|
402
|
-
/**
|
403
|
-
* Allow mocking of window.location.search
|
404
|
-
*/
|
405
|
-
BookReader.prototype.getLocationSearch = function () {
|
406
|
-
return window.location.search;
|
407
|
-
};
|
408
|
-
|
409
|
-
/**
|
410
|
-
* Allow mocking of window.location.hash
|
411
|
-
*/
|
412
|
-
BookReader.prototype.getLocationHash = function () {
|
413
|
-
return window.location.hash;
|
414
|
-
};
|
415
|
-
|
416
|
-
/**
|
417
|
-
* Return URL or fragment querystring
|
418
|
-
*/
|
419
|
-
BookReader.prototype.readQueryString = function () {
|
420
|
-
var queryString = this.getLocationSearch();
|
421
|
-
if (queryString) {
|
422
|
-
return queryString;
|
423
|
-
}
|
424
|
-
var hash = this.getLocationHash();
|
425
|
-
var found = hash.search(/\?\w+=/);
|
426
|
-
return found > -1 ? hash.slice(found) : '';
|
427
|
-
};
|
428
|
-
|
429
|
-
/**
|
430
|
-
* Determines the initial mode for starting if a mode is not already
|
431
|
-
* present in the params argument
|
432
|
-
* @param {object} params
|
433
|
-
* @return {1 | 2 | 3} the initial mode
|
434
|
-
*/
|
435
|
-
BookReader.prototype.getInitialMode = function (params) {
|
436
|
-
// if mobile breakpoint, we always show this.constMode1up mode
|
437
|
-
var windowWidth = $(window).width();
|
438
|
-
var isMobile = windowWidth && windowWidth <= this.onePageMinBreakpoint;
|
439
|
-
var initialMode;
|
440
|
-
if (params.mode) {
|
441
|
-
initialMode = params.mode;
|
442
|
-
} else if (isMobile) {
|
443
|
-
initialMode = this.constMode1up;
|
444
|
-
} else {
|
445
|
-
initialMode = this.constMode2up;
|
446
|
-
}
|
447
|
-
if (!this.canSwitchToMode(initialMode)) {
|
448
|
-
initialMode = this.constMode1up;
|
449
|
-
}
|
450
|
-
|
451
|
-
// override defaults mode via `options.defaults` metadata
|
452
|
-
if (this.options.defaults) {
|
453
|
-
try {
|
454
|
-
initialMode = _modeStringToNumber(this.options.defaults);
|
455
|
-
} catch (e) {
|
456
|
-
// Can ignore this error
|
457
|
-
}
|
458
|
-
}
|
459
|
-
return initialMode;
|
460
|
-
};
|
461
|
-
|
462
|
-
/**
|
463
|
-
* Converts a mode string to a the mode numeric constant
|
464
|
-
* @param {'mode/1up'|'mode/2up'|'mode/thumb'} modeString
|
465
|
-
* @return {1 | 2 | 3}
|
466
|
-
*/
|
467
|
-
export function _modeStringToNumber(modeString) {
|
468
|
-
var MAPPING = {
|
469
|
-
'mode/1up': 1,
|
470
|
-
'mode/2up': 2,
|
471
|
-
'mode/thumb': 3
|
472
|
-
};
|
473
|
-
if (!(modeString in MAPPING)) {
|
474
|
-
throw new OptionsParseError("Invalid mode string: ".concat(modeString));
|
475
|
-
}
|
476
|
-
return MAPPING[modeString];
|
477
|
-
}
|
478
|
-
|
479
|
-
/**
|
480
|
-
* This is called by the client to initialize BookReader.
|
481
|
-
* It renders onto the DOM. It should only be called once.
|
482
|
-
*/
|
483
|
-
BookReader.prototype.init = function () {
|
484
|
-
this.init.initComplete = false;
|
485
|
-
this.pageScale = this.reduce; // preserve current reduce
|
486
|
-
|
487
|
-
var params = this.initParams();
|
488
|
-
this.firstIndex = params.index ? params.index : 0;
|
489
|
-
|
490
|
-
// Setup Navbars and other UI
|
491
|
-
this.isTouchDevice = !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);
|
492
|
-
this.refs.$br = $(this.el).empty().removeClass().addClass("ui-" + this.ui).addClass("br-ui-" + this.ui).addClass('BookReader');
|
493
|
-
|
494
|
-
// Add a class if this is a touch enabled device
|
495
|
-
if (this.isTouchDevice) {
|
496
|
-
this.refs.$br.addClass("touch");
|
497
|
-
} else {
|
498
|
-
this.refs.$br.addClass("no-touch");
|
499
|
-
}
|
500
|
-
this.refs.$brContainer = $("<div class='BRcontainer' dir='ltr'></div>");
|
501
|
-
this.refs.$br.append(this.refs.$brContainer);
|
502
|
-
|
503
|
-
// Explicitly ensure params.mode exists for updateFromParams() below
|
504
|
-
params.mode = this.getInitialMode(params);
|
505
|
-
|
506
|
-
// Explicitly ensure this.mode exists for initNavbar() below
|
507
|
-
this.mode = params.mode;
|
508
|
-
|
509
|
-
// Display Navigation
|
510
|
-
if (this.options.showToolbar) {
|
511
|
-
this.initToolbar(this.mode, this.ui); // Build inside of toolbar div
|
512
|
-
}
|
513
|
-
if (this.options.showNavbar) {
|
514
|
-
// default navigation
|
515
|
-
this.initNavbar();
|
516
|
-
}
|
517
|
-
|
518
|
-
// Switch navbar controls on mobile/desktop
|
519
|
-
this._components.navbar.switchNavbarControls();
|
520
|
-
this.resizeBRcontainer();
|
521
|
-
this.updateFromParams(params);
|
522
|
-
this.initUIStrings();
|
523
|
-
|
524
|
-
// Bind to events
|
525
|
-
|
526
|
-
this.bindNavigationHandlers();
|
527
|
-
this.setupKeyListeners();
|
528
|
-
this.lastScroll = new Date().getTime();
|
529
|
-
this.refs.$brContainer.on('scroll', this, function (e) {
|
530
|
-
// Note, this scroll event fires for both user, and js generated calls
|
531
|
-
// It is functioning in some cases as the primary triggerer for rendering
|
532
|
-
e.data.lastScroll = new Date().getTime();
|
533
|
-
if (e.data.constModeThumb == e.data.mode) {
|
534
|
-
e.data.drawLeafsThrottled();
|
535
|
-
}
|
536
|
-
});
|
537
|
-
if (this.options.autoResize) {
|
538
|
-
$(window).on('resize', this, function (e) {
|
539
|
-
e.data.resize();
|
540
|
-
});
|
541
|
-
$(window).on("orientationchange", this, function (e) {
|
542
|
-
e.data.resize();
|
543
|
-
}.bind(this));
|
544
|
-
}
|
545
|
-
if (this.protected) {
|
546
|
-
this.$('.BRicon.share').hide();
|
547
|
-
}
|
548
|
-
|
549
|
-
// If not searching, set to allow on-going fragment changes
|
550
|
-
if (!this.options.initialSearchTerm) {
|
551
|
-
this.suppressFragmentChange = false;
|
552
|
-
}
|
553
|
-
if (this.options.startFullscreen) {
|
554
|
-
this.enterFullscreen(true);
|
555
|
-
}
|
556
|
-
this.init.initComplete = true;
|
557
|
-
this.trigger(BookReader.eventNames.PostInit);
|
558
|
-
|
559
|
-
// Must be called after this.init.initComplete set to true to allow
|
560
|
-
// BookReader.prototype.resize to run.
|
561
|
-
};
|
562
|
-
|
563
|
-
/**
|
564
|
-
* @param {EVENTS} name
|
565
|
-
* @param {array | object} [props]
|
566
|
-
*/
|
567
|
-
BookReader.prototype.trigger = function (name) {
|
568
|
-
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this;
|
569
|
-
var eventName = 'BookReader:' + name;
|
570
|
-
utils.polyfillCustomEvent(window);
|
571
|
-
window.dispatchEvent(new CustomEvent(eventName, {
|
572
|
-
bubbles: true,
|
573
|
-
composed: true,
|
574
|
-
detail: {
|
575
|
-
props
|
576
|
-
}
|
577
|
-
}));
|
578
|
-
$(document).trigger(eventName, props);
|
579
|
-
};
|
580
|
-
BookReader.prototype.bind = function (name, callback) {
|
581
|
-
$(document).on('BookReader:' + name, callback);
|
582
|
-
};
|
583
|
-
BookReader.prototype.unbind = function (name, callback) {
|
584
|
-
$(document).off('BookReader:' + name, callback);
|
585
|
-
};
|
586
|
-
|
587
|
-
/**
|
588
|
-
* Resizes based on the container width and height
|
589
|
-
*/
|
590
|
-
BookReader.prototype.resize = function () {
|
591
|
-
if (!this.init.initComplete) return;
|
592
|
-
this.resizeBRcontainer();
|
593
|
-
|
594
|
-
// Switch navbar controls on mobile/desktop
|
595
|
-
this._components.navbar.switchNavbarControls();
|
596
|
-
if (this.constMode1up == this.mode) {
|
597
|
-
if (this.onePage.autofit != 'none') {
|
598
|
-
this._modes.mode1Up.resizePageView();
|
599
|
-
this.centerPageView();
|
600
|
-
} else {
|
601
|
-
this.centerPageView();
|
602
|
-
this.displayedIndices = [];
|
603
|
-
this.drawLeafsThrottled();
|
604
|
-
}
|
605
|
-
} else if (this.constModeThumb == this.mode) {
|
606
|
-
this._modes.modeThumb.prepare();
|
607
|
-
} else {
|
608
|
-
this._modes.mode2Up.resizePageView();
|
609
|
-
}
|
610
|
-
this.trigger(BookReader.eventNames.resize);
|
611
|
-
};
|
612
|
-
|
613
|
-
/**
|
614
|
-
* Binds keyboard and keyboard focus event listeners
|
615
|
-
*/
|
616
|
-
BookReader.prototype.setupKeyListeners = function () {
|
617
|
-
// Keyboard focus by BookReader in viewport
|
618
|
-
//
|
619
|
-
// Intersection observer and callback sets BookReader keyboard
|
620
|
-
// "focus" flag off when the BookReader is not in the viewport.
|
621
|
-
if (window.IntersectionObserver) {
|
622
|
-
var observer = new IntersectionObserver(entries => {
|
623
|
-
entries.forEach(entry => {
|
624
|
-
if (entry.intersectionRatio === 0) {
|
625
|
-
this.hasKeyFocus = false;
|
626
|
-
} else {
|
627
|
-
this.hasKeyFocus = true;
|
628
|
-
}
|
629
|
-
});
|
630
|
-
}, {
|
631
|
-
root: null,
|
632
|
-
rootMargin: '0px',
|
633
|
-
threshold: [0, 0.05, 1]
|
634
|
-
});
|
635
|
-
observer.observe(this.refs.$br[0]);
|
636
|
-
}
|
637
|
-
|
638
|
-
// Keyboard listeners
|
639
|
-
document.addEventListener('keydown', e => {
|
640
|
-
// Ignore if BookReader "focus" flag not set
|
641
|
-
if (!this.hasKeyFocus) {
|
642
|
-
return;
|
643
|
-
}
|
644
|
-
|
645
|
-
// Ignore if modifiers are active.
|
646
|
-
if (e.getModifierState('Control') || e.getModifierState('Alt') || e.getModifierState('Meta') || e.getModifierState('Win') /* hack for IE */) {
|
647
|
-
return;
|
648
|
-
}
|
649
|
-
|
650
|
-
// Ignore in input elements
|
651
|
-
if (utils.isInputActive()) {
|
652
|
-
return;
|
653
|
-
}
|
654
|
-
|
655
|
-
// KeyboardEvent code values:
|
656
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
|
657
|
-
switch (e.key) {
|
658
|
-
// Page navigation
|
659
|
-
case "Home":
|
660
|
-
e.preventDefault();
|
661
|
-
this.first();
|
662
|
-
break;
|
663
|
-
case "End":
|
664
|
-
e.preventDefault();
|
665
|
-
this.last();
|
666
|
-
break;
|
667
|
-
case "ArrowDown":
|
668
|
-
case "PageDown":
|
669
|
-
case "Down":
|
670
|
-
// hack for IE and old Gecko
|
671
|
-
// In 1up and thumb mode page scrolling handled by browser
|
672
|
-
if (this.constMode2up === this.mode) {
|
673
|
-
e.preventDefault();
|
674
|
-
this.next();
|
675
|
-
}
|
676
|
-
break;
|
677
|
-
case "ArrowUp":
|
678
|
-
case "PageUp":
|
679
|
-
case "Up":
|
680
|
-
// hack for IE and old Gecko
|
681
|
-
// In 1up and thumb mode page scrolling handled by browser
|
682
|
-
if (this.constMode2up === this.mode) {
|
683
|
-
e.preventDefault();
|
684
|
-
this.prev();
|
685
|
-
}
|
686
|
-
break;
|
687
|
-
case "ArrowLeft":
|
688
|
-
case "Left":
|
689
|
-
// hack for IE and old Gecko
|
690
|
-
// No y-scrolling in thumb mode
|
691
|
-
if (this.constModeThumb != this.mode) {
|
692
|
-
e.preventDefault();
|
693
|
-
this.left();
|
694
|
-
}
|
695
|
-
break;
|
696
|
-
case "ArrowRight":
|
697
|
-
case "Right":
|
698
|
-
// hack for IE and old Gecko
|
699
|
-
// No y-scrolling in thumb mode
|
700
|
-
if (this.constModeThumb != this.mode) {
|
701
|
-
e.preventDefault();
|
702
|
-
this.right();
|
703
|
-
}
|
704
|
-
break;
|
705
|
-
// Zoom
|
706
|
-
case '-':
|
707
|
-
case 'Subtract':
|
708
|
-
e.preventDefault();
|
709
|
-
this.zoom(-1);
|
710
|
-
break;
|
711
|
-
case '+':
|
712
|
-
case '=':
|
713
|
-
case 'Add':
|
714
|
-
e.preventDefault();
|
715
|
-
this.zoom(1);
|
716
|
-
break;
|
717
|
-
// Fullscreen
|
718
|
-
case 'F':
|
719
|
-
case 'f':
|
720
|
-
e.preventDefault();
|
721
|
-
this.toggleFullscreen();
|
722
|
-
break;
|
723
|
-
}
|
724
|
-
});
|
725
|
-
};
|
726
|
-
BookReader.prototype.drawLeafs = function () {
|
727
|
-
if (this.constMode1up == this.mode) {
|
728
|
-
// Not needed for Mode1Up anymore
|
729
|
-
return;
|
730
|
-
} else {
|
731
|
-
this.activeMode.drawLeafs();
|
732
|
-
}
|
733
|
-
};
|
734
|
-
|
735
|
-
/**
|
736
|
-
* @protected
|
737
|
-
* @param {PageIndex} index
|
738
|
-
*/
|
739
|
-
BookReader.prototype._createPageContainer = function (index) {
|
740
|
-
return new PageContainer(this.book.getPage(index, false), {
|
741
|
-
isProtected: this.protected,
|
742
|
-
imageCache: this.imageCache,
|
743
|
-
loadingImage: this.imagesBaseURL + 'loading.gif'
|
744
|
-
});
|
745
|
-
};
|
746
|
-
BookReader.prototype.bindGestures = function (jElement) {
|
747
|
-
// TODO support gesture change is only iOS. Support android.
|
748
|
-
// HACK(2017-01-20) - Momentum scrolling is causing the scroll position
|
749
|
-
// to jump after zooming in on mobile device. I am able to reproduce
|
750
|
-
// when you move the book with one finger and then add another
|
751
|
-
// finger to pinch. Gestures are aware of scroll state.
|
752
|
-
|
753
|
-
var self = this;
|
754
|
-
var numTouches = 1;
|
755
|
-
jElement.unbind('touchmove').bind('touchmove', function (e) {
|
756
|
-
if (e.originalEvent.cancelable) numTouches = e.originalEvent.touches.length;
|
757
|
-
e.stopPropagation();
|
758
|
-
});
|
759
|
-
jElement.unbind('gesturechange').bind('gesturechange', function (e) {
|
760
|
-
e.preventDefault();
|
761
|
-
// These are two very important fixes to adjust for the scroll position
|
762
|
-
// issues described below
|
763
|
-
if (!(numTouches !== 2 || new Date().getTime() - self.lastScroll < 500)) {
|
764
|
-
if (e.originalEvent.scale > 1.5) {
|
765
|
-
self.zoom(1);
|
766
|
-
} else if (e.originalEvent.scale < 0.6) {
|
767
|
-
self.zoom(-1);
|
768
|
-
}
|
769
|
-
}
|
770
|
-
});
|
771
|
-
};
|
772
|
-
|
773
|
-
/**
|
774
|
-
* A throttled version of drawLeafs
|
775
|
-
*/
|
776
|
-
BookReader.prototype.drawLeafsThrottled = utils.throttle(BookReader.prototype.drawLeafs, 250 // 250 ms gives quick feedback, but doesn't eat cpu
|
777
|
-
);
|
778
|
-
|
779
|
-
/**
|
780
|
-
* @param {number} direction Pass 1 to zoom in, anything else to zoom out
|
781
|
-
*/
|
782
|
-
BookReader.prototype.zoom = function (direction) {
|
783
|
-
var _this$textSelectionPl;
|
784
|
-
if (direction == 1) {
|
785
|
-
this.activeMode.zoom('in');
|
786
|
-
} else {
|
787
|
-
this.activeMode.zoom('out');
|
788
|
-
}
|
789
|
-
(_this$textSelectionPl = this.textSelectionPlugin) === null || _this$textSelectionPl === void 0 || _this$textSelectionPl.stopPageFlip(this.refs.$brContainer);
|
790
|
-
return;
|
791
|
-
};
|
792
|
-
|
793
|
-
/**
|
794
|
-
* Resizes the inner container to fit within the visible space to prevent
|
795
|
-
* the top toolbar and bottom navbar from clipping the visible book
|
796
|
-
*
|
797
|
-
* @param { boolean } animate - optional
|
798
|
-
* When used, BookReader will fill the main container with the book's content.
|
799
|
-
* This is primarily for 1up view - a follow up animation to the nav animation
|
800
|
-
* So resize isn't perceived sharp/jerky
|
801
|
-
*/
|
802
|
-
BookReader.prototype.resizeBRcontainer = function (animate) {
|
803
|
-
if (animate) {
|
804
|
-
this.refs.$brContainer.animate({
|
805
|
-
top: this.getToolBarHeight(),
|
806
|
-
bottom: this.getFooterHeight()
|
807
|
-
}, this.constResizeAnimationDuration, 'linear');
|
808
|
-
} else {
|
809
|
-
this.refs.$brContainer.css({
|
810
|
-
top: this.getToolBarHeight(),
|
811
|
-
bottom: this.getFooterHeight()
|
812
|
-
});
|
813
|
-
}
|
814
|
-
};
|
815
|
-
BookReader.prototype.centerPageView = function () {
|
816
|
-
var scrollWidth = this.refs.$brContainer.prop('scrollWidth');
|
817
|
-
var clientWidth = this.refs.$brContainer.prop('clientWidth');
|
818
|
-
if (scrollWidth > clientWidth) {
|
819
|
-
this.refs.$brContainer.prop('scrollLeft', (scrollWidth - clientWidth) / 2);
|
820
|
-
}
|
821
|
-
};
|
822
|
-
|
823
|
-
/**
|
824
|
-
* Quantizes the given reduction factor to closest power of two from set from 12.5% to 200%
|
825
|
-
* @param {number} reduce
|
826
|
-
* @param {ReductionFactor[]} reductionFactors
|
827
|
-
* @return {number}
|
828
|
-
*/
|
829
|
-
BookReader.prototype.quantizeReduce = function (reduce, reductionFactors) {
|
830
|
-
var quantized = reductionFactors[0].reduce;
|
831
|
-
var distance = Math.abs(reduce - quantized);
|
832
|
-
for (var i = 1; i < reductionFactors.length; i++) {
|
833
|
-
var newDistance = Math.abs(reduce - reductionFactors[i].reduce);
|
834
|
-
if (newDistance < distance) {
|
835
|
-
distance = newDistance;
|
836
|
-
quantized = reductionFactors[i].reduce;
|
837
|
-
}
|
838
|
-
}
|
839
|
-
return quantized;
|
840
|
-
};
|
841
|
-
|
842
|
-
/**
|
843
|
-
* @param {number} currentReduce
|
844
|
-
* @param {'in' | 'out' | 'auto' | 'height' | 'width'} direction
|
845
|
-
* @param {ReductionFactor[]} reductionFactors Must be sorted
|
846
|
-
* @returns {ReductionFactor}
|
847
|
-
*/
|
848
|
-
BookReader.prototype.nextReduce = function (currentReduce, direction, reductionFactors) {
|
849
|
-
// XXX add 'closest', to replace quantize function
|
850
|
-
|
851
|
-
if (direction === 'in') {
|
852
|
-
var newReduceIndex = 0;
|
853
|
-
for (var i = 1; i < reductionFactors.length; i++) {
|
854
|
-
if (reductionFactors[i].reduce < currentReduce) {
|
855
|
-
newReduceIndex = i;
|
856
|
-
}
|
857
|
-
}
|
858
|
-
return reductionFactors[newReduceIndex];
|
859
|
-
} else if (direction === 'out') {
|
860
|
-
var lastIndex = reductionFactors.length - 1;
|
861
|
-
var _newReduceIndex = lastIndex;
|
862
|
-
for (var _i = lastIndex; _i >= 0; _i--) {
|
863
|
-
if (reductionFactors[_i].reduce > currentReduce) {
|
864
|
-
_newReduceIndex = _i;
|
865
|
-
}
|
866
|
-
}
|
867
|
-
return reductionFactors[_newReduceIndex];
|
868
|
-
} else if (direction === 'auto') {
|
869
|
-
// If an 'auto' is specified, use that
|
870
|
-
var autoMatch = reductionFactors.find(rf => rf.autofit == 'auto');
|
871
|
-
if (autoMatch) return autoMatch;
|
872
|
-
|
873
|
-
// Otherwise, choose the least reduction from height/width
|
874
|
-
var candidates = reductionFactors.filter(_ref => {
|
875
|
-
var {
|
876
|
-
autofit
|
877
|
-
} = _ref;
|
878
|
-
return autofit == 'height' || autofit == 'width';
|
879
|
-
});
|
880
|
-
var choice = null;
|
881
|
-
for (var _i2 = 0; _i2 < candidates.length; _i2++) {
|
882
|
-
if (choice === null || choice.reduce < candidates[_i2].reduce) {
|
883
|
-
choice = candidates[_i2];
|
884
|
-
}
|
885
|
-
}
|
886
|
-
if (choice) return choice;
|
887
|
-
} else if (direction === 'height' || direction === 'width') {
|
888
|
-
// Asked for specific autofit mode
|
889
|
-
var match = reductionFactors.find(rf => rf.autofit == direction);
|
890
|
-
if (match) return match;
|
891
|
-
}
|
892
|
-
return reductionFactors[0];
|
893
|
-
};
|
894
|
-
|
895
|
-
/**
|
896
|
-
* @param {ReductionFactor} a
|
897
|
-
* @param {ReductionFactor} b
|
898
|
-
*/
|
899
|
-
BookReader.prototype._reduceSort = (a, b) => a.reduce - b.reduce;
|
900
|
-
|
901
|
-
/**
|
902
|
-
* Attempts to jump to page
|
903
|
-
* @param {string}
|
904
|
-
* @return {boolean} Returns true if page could be found, false otherwise.
|
905
|
-
*/
|
906
|
-
BookReader.prototype.jumpToPage = function (pageNum) {
|
907
|
-
var pageIndex = this.book.parsePageString(pageNum);
|
908
|
-
if ('undefined' != typeof pageIndex) {
|
909
|
-
this.jumpToIndex(pageIndex);
|
910
|
-
return true;
|
911
|
-
}
|
912
|
-
|
913
|
-
// Page not found
|
914
|
-
return false;
|
915
|
-
};
|
916
|
-
|
917
|
-
/**
|
918
|
-
* Check whether the specified index is currently displayed
|
919
|
-
* @param {PageIndex} index
|
920
|
-
*/
|
921
|
-
BookReader.prototype._isIndexDisplayed = function (index) {
|
922
|
-
return this.displayedIndices ? this.displayedIndices.includes(index) : this.currentIndex() == index;
|
923
|
-
};
|
924
|
-
|
925
|
-
/**
|
926
|
-
* Changes the current page
|
927
|
-
* @param {PageIndex} index
|
928
|
-
* @param {number} [pageX]
|
929
|
-
* @param {number} [pageY]
|
930
|
-
* @param {boolean} [noAnimate]
|
931
|
-
*/
|
932
|
-
BookReader.prototype.jumpToIndex = function (index, pageX, pageY, noAnimate) {
|
933
|
-
// Don't jump into specific unviewable page
|
934
|
-
var page = this.book.getPage(index);
|
935
|
-
if (!page.isViewable && page.unviewablesStart != page.index) {
|
936
|
-
// If already in unviewable range, jump to end of that range
|
937
|
-
var alreadyInPreview = this._isIndexDisplayed(page.unviewablesStart);
|
938
|
-
var newIndex = alreadyInPreview ? page.findNext({
|
939
|
-
combineConsecutiveUnviewables: true
|
940
|
-
}).index : page.unviewablesStart;
|
941
|
-
return this.jumpToIndex(newIndex, pageX, pageY, noAnimate);
|
942
|
-
}
|
943
|
-
this.trigger(BookReader.eventNames.stop);
|
944
|
-
this.activeMode.jumpToIndex(index, pageX, pageY, noAnimate);
|
945
|
-
};
|
946
|
-
|
947
|
-
/**
|
948
|
-
* Return mode or 1up if initial thumb
|
949
|
-
* @param {number}
|
950
|
-
*/
|
951
|
-
BookReader.prototype.getPrevReadMode = function (mode) {
|
952
|
-
if (mode === BookReader.constMode1up || mode === BookReader.constMode2up) {
|
953
|
-
return mode;
|
954
|
-
} else if (this.prevReadMode === null) {
|
955
|
-
// Initial thumb, return 1up
|
956
|
-
return BookReader.constMode1up;
|
957
|
-
}
|
958
|
-
};
|
959
|
-
|
960
|
-
/**
|
961
|
-
* Switches the mode (eg 1up 2up thumb)
|
962
|
-
* @param {number}
|
963
|
-
* @param {object} [options]
|
964
|
-
* @param {boolean} [options.suppressFragmentChange = false]
|
965
|
-
* @param {boolean} [options.onInit = false] - this
|
966
|
-
*/
|
967
|
-
BookReader.prototype.switchMode = function (mode) {
|
968
|
-
var _this$textSelectionPl2;
|
969
|
-
var {
|
970
|
-
suppressFragmentChange = false,
|
971
|
-
init = false,
|
972
|
-
pageFound = false
|
973
|
-
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
974
|
-
// Skip checks before init() complete
|
975
|
-
if (this.init.initComplete) {
|
976
|
-
if (mode === this.mode) {
|
977
|
-
return;
|
978
|
-
}
|
979
|
-
if (!this.canSwitchToMode(mode)) {
|
980
|
-
return;
|
981
|
-
}
|
982
|
-
}
|
983
|
-
this.trigger(BookReader.eventNames.stop);
|
984
|
-
this.prevReadMode = this.getPrevReadMode(this.mode);
|
985
|
-
if (this.mode != mode) {
|
986
|
-
var _this$activeMode$unpr, _this$activeMode;
|
987
|
-
(_this$activeMode$unpr = (_this$activeMode = this.activeMode).unprepare) === null || _this$activeMode$unpr === void 0 || _this$activeMode$unpr.call(_this$activeMode);
|
988
|
-
}
|
989
|
-
this.mode = mode;
|
990
|
-
|
991
|
-
// reinstate scale if moving from thumbnail view
|
992
|
-
if (this.pageScale !== this.reduce) {
|
993
|
-
this.reduce = this.pageScale;
|
994
|
-
}
|
995
|
-
|
996
|
-
// $$$ TODO preserve center of view when switching between mode
|
997
|
-
// See https://bugs.edge.launchpad.net/gnubook/+bug/416682
|
998
|
-
|
999
|
-
// XXX maybe better to preserve zoom in each mode
|
1000
|
-
if (this.constMode1up == mode) {
|
1001
|
-
this._modes.mode1Up.prepare();
|
1002
|
-
} else if (this.constModeThumb == mode) {
|
1003
|
-
this.reduce = this.quantizeReduce(this.reduce, this.reductionFactors);
|
1004
|
-
this._modes.modeThumb.prepare();
|
1005
|
-
} else {
|
1006
|
-
this._modes.mode2Up.prepare();
|
1007
|
-
}
|
1008
|
-
if (!(this.suppressFragmentChange || suppressFragmentChange)) {
|
1009
|
-
this.trigger(BookReader.eventNames.fragmentChange);
|
1010
|
-
}
|
1011
|
-
var eventName = mode + 'PageViewSelected';
|
1012
|
-
this.trigger(BookReader.eventNames[eventName]);
|
1013
|
-
(_this$textSelectionPl2 = this.textSelectionPlugin) === null || _this$textSelectionPl2 === void 0 || _this$textSelectionPl2.stopPageFlip(this.refs.$brContainer);
|
1014
|
-
};
|
1015
|
-
BookReader.prototype.updateBrClasses = function () {
|
1016
|
-
var modeToClass = {};
|
1017
|
-
modeToClass[this.constMode1up] = 'BRmode1up';
|
1018
|
-
modeToClass[this.constMode2up] = 'BRmode2up';
|
1019
|
-
modeToClass[this.constModeThumb] = 'BRmodeThumb';
|
1020
|
-
this.refs.$br.removeClass('BRmode1up BRmode2up BRmodeThumb').addClass(modeToClass[this.mode]);
|
1021
|
-
if (this.isFullscreen()) {
|
1022
|
-
this.refs.$br.addClass('fullscreenActive');
|
1023
|
-
$(document.body).addClass('BRfullscreenActive');
|
1024
|
-
} else {
|
1025
|
-
this.refs.$br.removeClass('fullscreenActive');
|
1026
|
-
$(document.body).removeClass('BRfullscreenActive');
|
1027
|
-
}
|
1028
|
-
};
|
1029
|
-
BookReader.prototype.isFullscreen = function () {
|
1030
|
-
return this.isFullscreenActive;
|
1031
|
-
};
|
1032
|
-
|
1033
|
-
/**
|
1034
|
-
* Toggles fullscreen
|
1035
|
-
* @param { boolean } bindKeyboardControls
|
1036
|
-
*/
|
1037
|
-
BookReader.prototype.toggleFullscreen = /*#__PURE__*/_asyncToGenerator(function* () {
|
1038
|
-
var bindKeyboardControls = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
1039
|
-
if (this.isFullscreen()) {
|
1040
|
-
yield this.exitFullScreen();
|
1041
|
-
} else {
|
1042
|
-
yield this.enterFullscreen(bindKeyboardControls);
|
1043
|
-
}
|
1044
|
-
});
|
1045
|
-
|
1046
|
-
/**
|
1047
|
-
* Enters fullscreen
|
1048
|
-
* including:
|
1049
|
-
* - binds keyboard controls
|
1050
|
-
* - fires custom event
|
1051
|
-
* @param { boolean } bindKeyboardControls
|
1052
|
-
*/
|
1053
|
-
BookReader.prototype.enterFullscreen = /*#__PURE__*/_asyncToGenerator(function* () {
|
1054
|
-
var _this$textSelectionPl3;
|
1055
|
-
var bindKeyboardControls = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
1056
|
-
this.refs.$br.addClass('BRfullscreenAnimation');
|
1057
|
-
var currentIndex = this.currentIndex();
|
1058
|
-
if (bindKeyboardControls) {
|
1059
|
-
this._fullscreenCloseHandler = e => {
|
1060
|
-
if (e.keyCode === 27) this.toggleFullscreen();
|
1061
|
-
};
|
1062
|
-
$(document).on("keyup", this._fullscreenCloseHandler);
|
1063
|
-
}
|
1064
|
-
var windowWidth = $(window).width();
|
1065
|
-
if (windowWidth <= this.onePageMinBreakpoint) {
|
1066
|
-
this.switchMode(this.constMode1up);
|
1067
|
-
}
|
1068
|
-
this.isFullscreenActive = true;
|
1069
|
-
// prioritize class updates so CSS can propagate
|
1070
|
-
this.updateBrClasses();
|
1071
|
-
if (this.activeMode instanceof Mode1Up) {
|
1072
|
-
this.activeMode.mode1UpLit.scale = this.activeMode.mode1UpLit.computeDefaultScale(this.book.getPage(currentIndex));
|
1073
|
-
// Need the new scale to be applied before calling jumpToIndex
|
1074
|
-
this.activeMode.mode1UpLit.requestUpdate();
|
1075
|
-
yield this.activeMode.mode1UpLit.updateComplete;
|
1076
|
-
}
|
1077
|
-
this.jumpToIndex(currentIndex);
|
1078
|
-
(_this$textSelectionPl3 = this.textSelectionPlugin) === null || _this$textSelectionPl3 === void 0 || _this$textSelectionPl3.stopPageFlip(this.refs.$brContainer);
|
1079
|
-
// Add "?view=theater"
|
1080
|
-
this.trigger(BookReader.eventNames.fragmentChange);
|
1081
|
-
// trigger event here, so that animations,
|
1082
|
-
// class updates happen before book-nav relays to web components
|
1083
|
-
this.trigger(BookReader.eventNames.fullscreenToggled);
|
1084
|
-
|
1085
|
-
// resize book after all events & css updates
|
1086
|
-
yield new Promise(resolve => setTimeout(resolve, 0));
|
1087
|
-
this.resize();
|
1088
|
-
this.refs.$br.removeClass('BRfullscreenAnimation');
|
1089
|
-
});
|
1090
|
-
|
1091
|
-
/**
|
1092
|
-
* Exits fullscreen
|
1093
|
-
* - toggles fullscreen
|
1094
|
-
* - binds keyboard controls
|
1095
|
-
* - fires custom event
|
1096
|
-
* @param { boolean } bindKeyboardControls
|
1097
|
-
*/
|
1098
|
-
BookReader.prototype.exitFullScreen = /*#__PURE__*/_asyncToGenerator(function* () {
|
1099
|
-
var _this$textSelectionPl4;
|
1100
|
-
this.refs.$br.addClass('BRfullscreenAnimation');
|
1101
|
-
$(document).off('keyup', this._fullscreenCloseHandler);
|
1102
|
-
var windowWidth = $(window).width();
|
1103
|
-
var canShow2up = this.options.controls.twoPage.visible;
|
1104
|
-
if (canShow2up && windowWidth <= this.onePageMinBreakpoint) {
|
1105
|
-
this.switchMode(this.constMode2up);
|
1106
|
-
}
|
1107
|
-
this.isFullscreenActive = false;
|
1108
|
-
// Trigger fullscreen event immediately
|
1109
|
-
// so that book-nav can relay to web components
|
1110
|
-
this.trigger(BookReader.eventNames.fullscreenToggled);
|
1111
|
-
this.updateBrClasses();
|
1112
|
-
yield new Promise(resolve => setTimeout(resolve, 0));
|
1113
|
-
this.resize();
|
1114
|
-
if (this.activeMode instanceof Mode1Up) {
|
1115
|
-
this.activeMode.mode1UpLit.scale = this.activeMode.mode1UpLit.computeDefaultScale(this.book.getPage(this.currentIndex()));
|
1116
|
-
this.activeMode.mode1UpLit.requestUpdate();
|
1117
|
-
yield this.activeMode.mode1UpLit.updateComplete;
|
1118
|
-
}
|
1119
|
-
(_this$textSelectionPl4 = this.textSelectionPlugin) === null || _this$textSelectionPl4 === void 0 || _this$textSelectionPl4.stopPageFlip(this.refs.$brContainer);
|
1120
|
-
// Remove "?view=theater"
|
1121
|
-
this.trigger(BookReader.eventNames.fragmentChange);
|
1122
|
-
this.refs.$br.removeClass('BRfullscreenAnimation');
|
1123
|
-
});
|
1124
|
-
|
1125
|
-
/**
|
1126
|
-
* Returns the currently active index
|
1127
|
-
* @return {number}
|
1128
|
-
* @throws
|
1129
|
-
*/
|
1130
|
-
BookReader.prototype.currentIndex = function () {
|
1131
|
-
// $$$ we should be cleaner with our idea of which index is active in 1up/2up
|
1132
|
-
if (this.mode == this.constMode1up || this.mode == this.constModeThumb) {
|
1133
|
-
return this.firstIndex; // $$$ TODO page in center of view would be better
|
1134
|
-
} else if (this.mode == this.constMode2up) {
|
1135
|
-
// Only allow indices that are actually present in book
|
1136
|
-
return utils.clamp(this.firstIndex, 0, this.book.getNumLeafs() - 1);
|
1137
|
-
} else {
|
1138
|
-
throw 'currentIndex called for unimplemented mode ' + this.mode;
|
1139
|
-
}
|
1140
|
-
};
|
1141
|
-
|
1142
|
-
/**
|
1143
|
-
* Setter for this.firstIndex
|
1144
|
-
* Also triggers an event and updates the navbar slider position
|
1145
|
-
* @param {number} index
|
1146
|
-
* @param {object} [options]
|
1147
|
-
* @param {boolean} [options.suppressFragmentChange = false]
|
1148
|
-
*/
|
1149
|
-
BookReader.prototype.updateFirstIndex = function (index) {
|
1150
|
-
var {
|
1151
|
-
suppressFragmentChange = false
|
1152
|
-
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
1153
|
-
// If there's no change, do nothing
|
1154
|
-
if (this.firstIndex === index) return;
|
1155
|
-
this.firstIndex = index;
|
1156
|
-
if (!(this.suppressFragmentChange || suppressFragmentChange)) {
|
1157
|
-
this.trigger(BookReader.eventNames.fragmentChange);
|
1158
|
-
}
|
1159
|
-
// If there's an initial search we stop suppressing global URL changes
|
1160
|
-
// when local suppression ends
|
1161
|
-
// This seems to correctly handle multiple calls during mode/1up
|
1162
|
-
if (this.options.initialSearchTerm && !suppressFragmentChange) {
|
1163
|
-
this.suppressFragmentChange = false;
|
1164
|
-
}
|
1165
|
-
this.trigger(BookReader.eventNames.pageChanged);
|
1166
|
-
|
1167
|
-
// event to know if user is actively reading
|
1168
|
-
this.trigger(BookReader.eventNames.userAction);
|
1169
|
-
this._components.navbar.updateNavIndexThrottled(index);
|
1170
|
-
};
|
1171
|
-
|
1172
|
-
/**
|
1173
|
-
* Flip the right page over onto the left
|
1174
|
-
*/
|
1175
|
-
BookReader.prototype.right = function () {
|
1176
|
-
if ('rl' != this.pageProgression) {
|
1177
|
-
this.next();
|
1178
|
-
} else {
|
1179
|
-
this.prev();
|
1180
|
-
}
|
1181
|
-
};
|
1182
|
-
|
1183
|
-
/**
|
1184
|
-
* Flip to the rightmost page
|
1185
|
-
*/
|
1186
|
-
BookReader.prototype.rightmost = function () {
|
1187
|
-
if ('rl' != this.pageProgression) {
|
1188
|
-
this.last();
|
1189
|
-
} else {
|
1190
|
-
this.first();
|
1191
|
-
}
|
1192
|
-
};
|
1193
|
-
|
1194
|
-
/**
|
1195
|
-
* Flip the left page over onto the right
|
1196
|
-
*/
|
1197
|
-
BookReader.prototype.left = function () {
|
1198
|
-
if ('rl' != this.pageProgression) {
|
1199
|
-
this.prev();
|
1200
|
-
} else {
|
1201
|
-
this.next();
|
1202
|
-
}
|
1203
|
-
};
|
1204
|
-
|
1205
|
-
/**
|
1206
|
-
* Flip to the leftmost page
|
1207
|
-
*/
|
1208
|
-
BookReader.prototype.leftmost = function () {
|
1209
|
-
if ('rl' != this.pageProgression) {
|
1210
|
-
this.first();
|
1211
|
-
} else {
|
1212
|
-
this.last();
|
1213
|
-
}
|
1214
|
-
};
|
1215
|
-
BookReader.prototype.next = function () {
|
1216
|
-
var {
|
1217
|
-
triggerStop = true
|
1218
|
-
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
1219
|
-
if (this.constMode2up == this.mode) {
|
1220
|
-
if (triggerStop) this.trigger(BookReader.eventNames.stop);
|
1221
|
-
this._modes.mode2Up.mode2UpLit.flipAnimation('next');
|
1222
|
-
} else {
|
1223
|
-
if (this.firstIndex < this.book.getNumLeafs() - 1) {
|
1224
|
-
this.jumpToIndex(this.firstIndex + 1);
|
1225
|
-
}
|
1226
|
-
}
|
1227
|
-
};
|
1228
|
-
BookReader.prototype.prev = function () {
|
1229
|
-
var {
|
1230
|
-
triggerStop = true
|
1231
|
-
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
1232
|
-
var isOnFrontPage = this.firstIndex < 1;
|
1233
|
-
if (isOnFrontPage) return;
|
1234
|
-
if (this.constMode2up == this.mode) {
|
1235
|
-
if (triggerStop) this.trigger(BookReader.eventNames.stop);
|
1236
|
-
this._modes.mode2Up.mode2UpLit.flipAnimation('prev');
|
1237
|
-
} else {
|
1238
|
-
if (this.firstIndex >= 1) {
|
1239
|
-
this.jumpToIndex(this.firstIndex - 1);
|
1240
|
-
}
|
1241
|
-
}
|
1242
|
-
};
|
1243
|
-
BookReader.prototype.first = function () {
|
1244
|
-
this.jumpToIndex(0);
|
1245
|
-
};
|
1246
|
-
BookReader.prototype.last = function () {
|
1247
|
-
this.jumpToIndex(this.book.getNumLeafs() - 1);
|
1248
|
-
};
|
1249
|
-
|
1250
|
-
/**
|
1251
|
-
* @template TClass extends { br: BookReader }
|
1252
|
-
* Helper method to expose a method onto BookReader from a composed class.
|
1253
|
-
* Only composed classes in BookReader._overridable can be exposed in this
|
1254
|
-
* way.
|
1255
|
-
* @param {new () => TClass} Class
|
1256
|
-
* @param {keyof BookReader['_overrideable']} classKey
|
1257
|
-
* @param {keyof TClass} method
|
1258
|
-
* @param {string} [brMethod]
|
1259
|
-
*/
|
1260
|
-
function exposeOverrideableMethod(Class, classKey, method) {
|
1261
|
-
var brMethod = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : method;
|
1262
|
-
/** @type {function(TClass): BookReader} */
|
1263
|
-
var classToBr = cls => cls.br;
|
1264
|
-
/** @type {function(BookReader): TClass} */
|
1265
|
-
var brToClass = br => br._overrideable[classKey];
|
1266
|
-
exposeOverrideable(Class, method, classToBr, BookReader, brMethod, brToClass);
|
1267
|
-
}
|
1268
|
-
|
1269
|
-
/***********************/
|
1270
|
-
/** Navbar extensions **/
|
1271
|
-
/***********************/
|
1272
|
-
/** This cannot be removed yet because plugin.tts.js overrides it */
|
1273
|
-
BookReader.prototype.initNavbar = Navbar.prototype.init;
|
1274
|
-
exposeOverrideableMethod(Navbar, '_components.navbar', 'init', 'initNavbar');
|
1275
|
-
|
1276
|
-
/************************/
|
1277
|
-
/** Toolbar extensions **/
|
1278
|
-
/************************/
|
1279
|
-
BookReader.prototype.buildToolbarElement = Toolbar.prototype.buildToolbarElement;
|
1280
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'buildToolbarElement');
|
1281
|
-
BookReader.prototype.initToolbar = Toolbar.prototype.initToolbar;
|
1282
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'initToolbar');
|
1283
|
-
BookReader.prototype.buildShareDiv = Toolbar.prototype.buildShareDiv;
|
1284
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'buildShareDiv');
|
1285
|
-
BookReader.prototype.buildInfoDiv = Toolbar.prototype.buildInfoDiv;
|
1286
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'buildInfoDiv');
|
1287
|
-
BookReader.prototype.getToolBarHeight = Toolbar.prototype.getToolBarHeight;
|
1288
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'getToolBarHeight');
|
1289
|
-
|
1290
|
-
/**
|
1291
|
-
* Bind navigation handlers
|
1292
|
-
*/
|
1293
|
-
BookReader.prototype.bindNavigationHandlers = function () {
|
1294
|
-
var self = this;
|
1295
|
-
var jIcons = this.$('.BRicon');
|
1296
|
-
|
1297
|
-
// Map of jIcon class -> click handler
|
1298
|
-
var navigationControls = {
|
1299
|
-
book_left: () => {
|
1300
|
-
this.trigger(BookReader.eventNames.stop);
|
1301
|
-
this.left();
|
1302
|
-
},
|
1303
|
-
book_right: () => {
|
1304
|
-
this.trigger(BookReader.eventNames.stop);
|
1305
|
-
this.right();
|
1306
|
-
},
|
1307
|
-
book_top: this.first.bind(this),
|
1308
|
-
book_bottom: this.last.bind(this),
|
1309
|
-
book_leftmost: this.leftmost.bind(this),
|
1310
|
-
book_rightmost: this.rightmost.bind(this),
|
1311
|
-
onepg: () => {
|
1312
|
-
this.switchMode(self.constMode1up);
|
1313
|
-
},
|
1314
|
-
thumb: () => {
|
1315
|
-
this.switchMode(self.constModeThumb);
|
1316
|
-
},
|
1317
|
-
twopg: () => {
|
1318
|
-
this.switchMode(self.constMode2up);
|
1319
|
-
},
|
1320
|
-
zoom_in: () => {
|
1321
|
-
this.trigger(BookReader.eventNames.stop);
|
1322
|
-
this.zoom(1);
|
1323
|
-
this.trigger(BookReader.eventNames.zoomIn);
|
1324
|
-
},
|
1325
|
-
zoom_out: () => {
|
1326
|
-
this.trigger(BookReader.eventNames.stop);
|
1327
|
-
this.zoom(-1);
|
1328
|
-
this.trigger(BookReader.eventNames.zoomOut);
|
1329
|
-
},
|
1330
|
-
full: () => {
|
1331
|
-
if (this.ui == 'embed') {
|
1332
|
-
var url = this.$('.BRembedreturn a').attr('href');
|
1333
|
-
window.open(url);
|
1334
|
-
} else {
|
1335
|
-
this.toggleFullscreen();
|
1336
|
-
}
|
1337
|
-
}
|
1338
|
-
};
|
1339
|
-
|
1340
|
-
// custom event for auto-loan-renew in ia-book-actions
|
1341
|
-
// - to know if user is actively reading
|
1342
|
-
this.$('nav.BRcontrols li button').on('click', () => {
|
1343
|
-
this.trigger(BookReader.eventNames.userAction);
|
1344
|
-
});
|
1345
|
-
var _loop = function _loop(control) {
|
1346
|
-
jIcons.filter(".".concat(control)).on('click.bindNavigationHandlers', () => {
|
1347
|
-
navigationControls[control]();
|
1348
|
-
return false;
|
1349
|
-
});
|
1350
|
-
};
|
1351
|
-
for (var control in navigationControls) {
|
1352
|
-
_loop(control);
|
1353
|
-
}
|
1354
|
-
var $brNavCntlBtmEl = this.$('.BRnavCntlBtm');
|
1355
|
-
var $brNavCntlTopEl = this.$('.BRnavCntlTop');
|
1356
|
-
this.$('.BRnavCntl').click(function () {
|
1357
|
-
var promises = [];
|
1358
|
-
// TODO don't use magic constants
|
1359
|
-
// TODO move this to a function
|
1360
|
-
if ($brNavCntlBtmEl.hasClass('BRdn')) {
|
1361
|
-
if (self.refs.$BRtoolbar) promises.push(self.refs.$BRtoolbar.animate({
|
1362
|
-
top: self.getToolBarHeight() * -1
|
1363
|
-
}).promise());
|
1364
|
-
promises.push(self.$('.BRfooter').animate({
|
1365
|
-
bottom: self.getFooterHeight() * -1
|
1366
|
-
}).promise());
|
1367
|
-
$brNavCntlBtmEl.addClass('BRup').removeClass('BRdn');
|
1368
|
-
$brNavCntlTopEl.addClass('BRdn').removeClass('BRup');
|
1369
|
-
self.$('.BRnavCntlBtm.BRnavCntl').animate({
|
1370
|
-
height: '45px'
|
1371
|
-
});
|
1372
|
-
self.$('.BRnavCntl').delay(1000).animate({
|
1373
|
-
opacity: .75
|
1374
|
-
}, 1000);
|
1375
|
-
} else {
|
1376
|
-
if (self.refs.$BRtoolbar) promises.push(self.refs.$BRtoolbar.animate({
|
1377
|
-
top: 0
|
1378
|
-
}).promise());
|
1379
|
-
promises.push(self.$('.BRfooter').animate({
|
1380
|
-
bottom: 0
|
1381
|
-
}).promise());
|
1382
|
-
$brNavCntlBtmEl.addClass('BRdn').removeClass('BRup');
|
1383
|
-
$brNavCntlTopEl.addClass('BRup').removeClass('BRdn');
|
1384
|
-
self.$('.BRnavCntlBtm.BRnavCntl').animate({
|
1385
|
-
height: '30px'
|
1386
|
-
});
|
1387
|
-
self.$('.BRvavCntl').animate({
|
1388
|
-
opacity: 1
|
1389
|
-
});
|
1390
|
-
}
|
1391
|
-
$.when.apply($, promises).done(function () {
|
1392
|
-
// Only do full resize in auto mode and need to recalc. size
|
1393
|
-
if (self.mode == self.constMode2up && self.twoPage.autofit != null && self.twoPage.autofit != 'none') {
|
1394
|
-
self.resize();
|
1395
|
-
} else if (self.mode == self.constMode1up && self.onePage.autofit != null && self.onePage.autofit != 'none') {
|
1396
|
-
self.resize();
|
1397
|
-
} else {
|
1398
|
-
// Don't do a full resize to avoid redrawing images
|
1399
|
-
self.resizeBRcontainer();
|
1400
|
-
}
|
1401
|
-
});
|
1402
|
-
});
|
1403
|
-
$brNavCntlBtmEl.on("mouseover", function () {
|
1404
|
-
if ($(this).hasClass('BRup')) {
|
1405
|
-
self.$('.BRnavCntl').animate({
|
1406
|
-
opacity: 1
|
1407
|
-
}, 250);
|
1408
|
-
}
|
1409
|
-
}).on("mouseleave", function () {
|
1410
|
-
if ($(this).hasClass('BRup')) {
|
1411
|
-
self.$('.BRnavCntl').animate({
|
1412
|
-
opacity: .75
|
1413
|
-
}, 250);
|
1414
|
-
}
|
1415
|
-
});
|
1416
|
-
$brNavCntlTopEl.on("mouseover", function () {
|
1417
|
-
if ($(this).hasClass('BRdn')) {
|
1418
|
-
self.$('.BRnavCntl').animate({
|
1419
|
-
opacity: 1
|
1420
|
-
}, 250);
|
1421
|
-
}
|
1422
|
-
}).on("mouseleave", function () {
|
1423
|
-
if ($(this).hasClass('BRdn')) {
|
1424
|
-
self.$('.BRnavCntl').animate({
|
1425
|
-
opacity: .75
|
1426
|
-
}, 250);
|
1427
|
-
}
|
1428
|
-
});
|
1429
|
-
};
|
1430
|
-
|
1431
|
-
/**************************/
|
1432
|
-
/** BookModel extensions **/
|
1433
|
-
/**************************/
|
1434
|
-
// Must modify petabox extension, which expects this on the prototype
|
1435
|
-
// before removing.
|
1436
|
-
BookReader.prototype.getPageURI = BookModel.prototype.getPageURI;
|
1437
|
-
exposeOverrideableMethod(BookModel, 'book', 'getPageURI');
|
1438
|
-
|
1439
|
-
// Parameter related functions
|
1440
|
-
|
1441
|
-
/**
|
1442
|
-
* Update from the params object
|
1443
|
-
* @param {Object}
|
1444
|
-
*/
|
1445
|
-
BookReader.prototype.updateFromParams = function (params) {
|
1446
|
-
// Set init, fragment change options for switchMode()
|
1447
|
-
var {
|
1448
|
-
mode = 0,
|
1449
|
-
init = false,
|
1450
|
-
fragmentChange = false
|
1451
|
-
} = params;
|
1452
|
-
if (mode) {
|
1453
|
-
this.switchMode(mode, {
|
1454
|
-
init: init,
|
1455
|
-
suppressFragmentChange: !fragmentChange
|
1456
|
-
});
|
1457
|
-
}
|
1458
|
-
|
1459
|
-
// $$$ process /zoom
|
1460
|
-
// We only respect page if index is not set
|
1461
|
-
if ('undefined' != typeof params.index) {
|
1462
|
-
if (params.index != this.currentIndex()) {
|
1463
|
-
this.jumpToIndex(params.index);
|
1464
|
-
}
|
1465
|
-
} else if ('undefined' != typeof params.page) {
|
1466
|
-
// $$$ this assumes page numbers are unique
|
1467
|
-
if (params.page != this.book.getPageNum(this.currentIndex())) {
|
1468
|
-
this.jumpToPage(params.page);
|
1469
|
-
}
|
1470
|
-
}
|
1471
|
-
|
1472
|
-
// process /search
|
1473
|
-
// @deprecated for urlMode 'history'
|
1474
|
-
// Continues to work for urlMode 'hash'
|
1475
|
-
if (this.enableSearch && 'undefined' != typeof params.search) {
|
1476
|
-
if (this.searchTerm !== params.search) {
|
1477
|
-
this.$('.BRsearchInput').val(params.search);
|
1478
|
-
}
|
1479
|
-
}
|
1480
|
-
|
1481
|
-
// $$$ process /region
|
1482
|
-
// $$$ process /highlight
|
1483
|
-
|
1484
|
-
// $$$ process /theme
|
1485
|
-
if (this.enableThemesPlugin && 'undefined' != typeof params.theme) {
|
1486
|
-
this.updateTheme(params.theme);
|
1487
|
-
}
|
1488
|
-
};
|
1489
|
-
|
1490
|
-
/**
|
1491
|
-
* Returns true if we can switch to the requested mode
|
1492
|
-
* @param {number} mode
|
1493
|
-
* @return {boolean}
|
1494
|
-
*/
|
1495
|
-
BookReader.prototype.canSwitchToMode = function (mode) {
|
1496
|
-
if (mode == this.constMode2up || mode == this.constModeThumb) {
|
1497
|
-
// check there are enough pages to display
|
1498
|
-
// $$$ this is a workaround for the mis-feature that we can't display
|
1499
|
-
// short books in 2up mode
|
1500
|
-
if (this.book.getNumLeafs() < 2) {
|
1501
|
-
return false;
|
1502
|
-
}
|
1503
|
-
}
|
1504
|
-
return true;
|
1505
|
-
};
|
1506
|
-
|
1507
|
-
/**
|
1508
|
-
* Returns the page URI or transparent image if out of range
|
1509
|
-
* Also makes the reduce argument optional
|
1510
|
-
* @param {number} index
|
1511
|
-
* @param {number} [reduce]
|
1512
|
-
* @param {number} [rotate]
|
1513
|
-
* @return {string}
|
1514
|
-
*/
|
1515
|
-
BookReader.prototype._getPageURI = function (index, reduce, rotate) {
|
1516
|
-
var page = this.book.getPage(index, false);
|
1517
|
-
// Synthesize page
|
1518
|
-
if (!page) return this.imagesBaseURL + "transparent.png";
|
1519
|
-
if ('undefined' == typeof reduce) {
|
1520
|
-
// reduce not passed in
|
1521
|
-
// $$$ this probably won't work for thumbnail mode
|
1522
|
-
reduce = page.height / this.twoPage.height;
|
1523
|
-
}
|
1524
|
-
return page.getURI(reduce, rotate);
|
1525
|
-
};
|
1526
|
-
|
1527
|
-
/**
|
1528
|
-
* @param {string} msg
|
1529
|
-
* @param {function|undefined} onCloseCallback
|
1530
|
-
*/
|
1531
|
-
BookReader.prototype.showProgressPopup = function (msg, onCloseCallback) {
|
1532
|
-
if (this.popup) return;
|
1533
|
-
this.popup = document.createElement("div");
|
1534
|
-
$(this.popup).prop('className', 'BRprogresspopup');
|
1535
|
-
if (typeof onCloseCallback === 'function') {
|
1536
|
-
var closeButton = document.createElement('button');
|
1537
|
-
closeButton.setAttribute('title', 'close');
|
1538
|
-
closeButton.setAttribute('class', 'close-popup');
|
1539
|
-
var icon = document.createElement('span');
|
1540
|
-
icon.setAttribute('class', 'icon icon-close-dark');
|
1541
|
-
$(closeButton).append(icon);
|
1542
|
-
closeButton.addEventListener('click', () => {
|
1543
|
-
onCloseCallback();
|
1544
|
-
this.removeProgressPopup();
|
1545
|
-
});
|
1546
|
-
$(this.popup).append(closeButton);
|
1547
|
-
}
|
1548
|
-
var bar = document.createElement("div");
|
1549
|
-
$(bar).css({
|
1550
|
-
height: '20px'
|
1551
|
-
}).prop('className', 'BRprogressbar');
|
1552
|
-
$(this.popup).append(bar);
|
1553
|
-
if (msg) {
|
1554
|
-
var msgdiv = document.createElement("div");
|
1555
|
-
msgdiv.innerHTML = msg;
|
1556
|
-
$(this.popup).append(msgdiv);
|
1557
|
-
}
|
1558
|
-
$(this.popup).appendTo(this.refs.$br);
|
1559
|
-
};
|
1560
|
-
BookReader.prototype.removeProgressPopup = function () {
|
1561
|
-
$(this.popup).remove();
|
1562
|
-
this.$('.BRprogresspopup').remove();
|
1563
|
-
this.popup = null;
|
1564
|
-
};
|
1565
|
-
|
1566
|
-
/**
|
1567
|
-
* Can be overridden
|
1568
|
-
*/
|
1569
|
-
BookReader.prototype.initUIStrings = function () {
|
1570
|
-
// Navigation handlers will be bound after all UI is in place -- makes moving icons between
|
1571
|
-
// the toolbar and nav bar easier
|
1572
|
-
|
1573
|
-
// Setup tooltips -- later we could load these from a file for i18n
|
1574
|
-
var titles = {
|
1575
|
-
'.logo': 'Go to Archive.org',
|
1576
|
-
// $$$ update after getting OL record
|
1577
|
-
'.zoom_in': 'Zoom in',
|
1578
|
-
'.zoom_out': 'Zoom out',
|
1579
|
-
'.onepg': 'One-page view',
|
1580
|
-
'.twopg': 'Two-page view',
|
1581
|
-
'.thumb': 'Thumbnail view',
|
1582
|
-
'.print': 'Print this page',
|
1583
|
-
'.embed': 'Embed BookReader',
|
1584
|
-
'.link': 'Link to this book (and page)',
|
1585
|
-
'.bookmark': 'Bookmark this page',
|
1586
|
-
'.share': 'Share this book',
|
1587
|
-
'.info': 'About this book',
|
1588
|
-
'.full': 'Toggle fullscreen',
|
1589
|
-
'.book_left': 'Flip left',
|
1590
|
-
'.book_right': 'Flip right',
|
1591
|
-
'.play': 'Play',
|
1592
|
-
'.pause': 'Pause',
|
1593
|
-
'.BRdn': 'Show/hide nav bar',
|
1594
|
-
// Would have to keep updating on state change to have just "Hide nav bar"
|
1595
|
-
'.BRup': 'Show/hide nav bar',
|
1596
|
-
'.book_top': 'First page',
|
1597
|
-
'.book_bottom': 'Last page',
|
1598
|
-
'.book_leftmost': 'First page',
|
1599
|
-
'.book_rightmost': 'Last page'
|
1600
|
-
};
|
1601
|
-
if ('rl' == this.pageProgression) {
|
1602
|
-
titles['.book_leftmost'] = 'Last page';
|
1603
|
-
titles['.book_rightmost'] = 'First page';
|
1604
|
-
}
|
1605
|
-
for (var icon in titles) {
|
1606
|
-
this.$(icon).prop('title', titles[icon]);
|
1607
|
-
}
|
1608
|
-
};
|
1609
|
-
|
1610
|
-
/**
|
1611
|
-
* Reloads images. Useful when some images might have failed.
|
1612
|
-
*/
|
1613
|
-
BookReader.prototype.reloadImages = function () {
|
1614
|
-
this.refs.$brContainer.find('img').each(function (index, elem) {
|
1615
|
-
if (!elem.complete || elem.naturalHeight === 0) {
|
1616
|
-
var src = elem.src;
|
1617
|
-
elem.src = '';
|
1618
|
-
setTimeout(function () {
|
1619
|
-
elem.src = src;
|
1620
|
-
}, 1000);
|
1621
|
-
}
|
1622
|
-
});
|
1623
|
-
};
|
1624
|
-
|
1625
|
-
/**
|
1626
|
-
* @param {boolean} ignoreDisplay - bypass the display check
|
1627
|
-
* @return {number}
|
1628
|
-
*/
|
1629
|
-
BookReader.prototype.getFooterHeight = function () {
|
1630
|
-
var $heightEl = this.mode == this.constMode2up ? this.refs.$BRfooter : this.refs.$BRnav;
|
1631
|
-
if ($heightEl && this.refs.$BRfooter) {
|
1632
|
-
var outerHeight = $heightEl.outerHeight();
|
1633
|
-
var bottom = parseInt(this.refs.$BRfooter.css('bottom'));
|
1634
|
-
if (!isNaN(outerHeight) && !isNaN(bottom)) {
|
1635
|
-
return outerHeight + bottom;
|
1636
|
-
}
|
1637
|
-
}
|
1638
|
-
return 0;
|
1639
|
-
};
|
1640
|
-
|
1641
|
-
// Basic Usage built-in Methods (can be overridden through options)
|
1642
|
-
// This implementation uses options.data value for populating BookReader
|
1643
|
-
|
1644
|
-
/**
|
1645
|
-
* Create a params object from the current parameters.
|
1646
|
-
* @return {Object}
|
1647
|
-
*/
|
1648
|
-
BookReader.prototype.paramsFromCurrent = function () {
|
1649
|
-
var params = {};
|
1650
|
-
|
1651
|
-
// Path params
|
1652
|
-
var index = this.currentIndex();
|
1653
|
-
var pageNum = this.book.getPageNum(index);
|
1654
|
-
if (pageNum === 0 || pageNum) {
|
1655
|
-
params.page = pageNum;
|
1656
|
-
}
|
1657
|
-
params.index = index;
|
1658
|
-
params.mode = this.mode;
|
1659
|
-
|
1660
|
-
// Unused params
|
1661
|
-
// $$$ highlight
|
1662
|
-
// $$$ region
|
1663
|
-
|
1664
|
-
// Querystring params
|
1665
|
-
// View
|
1666
|
-
var fullscreenView = 'theater';
|
1667
|
-
if (this.isFullscreenActive) {
|
1668
|
-
params.view = fullscreenView;
|
1669
|
-
}
|
1670
|
-
// Search
|
1671
|
-
if (this.enableSearch) {
|
1672
|
-
params.search = this.searchTerm;
|
1673
|
-
}
|
1674
|
-
return params;
|
1675
|
-
};
|
1676
|
-
|
1677
|
-
/**
|
1678
|
-
* Return an object with configuration parameters from a fragment string.
|
1679
|
-
*
|
1680
|
-
* Fragments are formatted as a URL path but may be used outside of URLs as a
|
1681
|
-
* serialization format for BookReader parameters
|
1682
|
-
*
|
1683
|
-
* @see http://openlibrary.org/dev/docs/bookurls for fragment syntax
|
1684
|
-
*
|
1685
|
-
* @param {string} fragment initial # is allowed for backwards compatibility
|
1686
|
-
* but is deprecated
|
1687
|
-
* @return {Object}
|
1688
|
-
*/
|
1689
|
-
BookReader.prototype.paramsFromFragment = function (fragment) {
|
1690
|
-
var params = {};
|
1691
|
-
|
1692
|
-
// For backwards compatibility we allow an initial # character
|
1693
|
-
// (as from window.location.hash) but don't require it
|
1694
|
-
if (fragment.substr(0, 1) == '#') {
|
1695
|
-
fragment = fragment.substr(1);
|
1696
|
-
}
|
1697
|
-
|
1698
|
-
// Simple #nn syntax
|
1699
|
-
var oldStyleLeafNum = parseInt(/^\d+$/.exec(fragment));
|
1700
|
-
if (!isNaN(oldStyleLeafNum)) {
|
1701
|
-
params.index = oldStyleLeafNum;
|
1702
|
-
|
1703
|
-
// Done processing if using old-style syntax
|
1704
|
-
return params;
|
1705
|
-
}
|
1706
|
-
|
1707
|
-
// Split into key-value pairs
|
1708
|
-
var urlArray = fragment.split('/');
|
1709
|
-
var urlHash = {};
|
1710
|
-
for (var i = 0; i < urlArray.length; i += 2) {
|
1711
|
-
urlHash[urlArray[i]] = urlArray[i + 1];
|
1712
|
-
}
|
1713
|
-
|
1714
|
-
// Mode
|
1715
|
-
if ('1up' == urlHash['mode']) {
|
1716
|
-
params.mode = this.constMode1up;
|
1717
|
-
} else if ('2up' == urlHash['mode']) {
|
1718
|
-
params.mode = this.constMode2up;
|
1719
|
-
} else if ('thumb' == urlHash['mode']) {
|
1720
|
-
params.mode = this.constModeThumb;
|
1721
|
-
}
|
1722
|
-
|
1723
|
-
// Index and page
|
1724
|
-
if ('undefined' != typeof urlHash['page']) {
|
1725
|
-
// page was set -- may not be int
|
1726
|
-
params.page = decodeURIComponent(urlHash['page']);
|
1727
|
-
}
|
1728
|
-
|
1729
|
-
// $$$ process /region
|
1730
|
-
// $$$ process /search
|
1731
|
-
|
1732
|
-
if (urlHash['search'] != undefined) {
|
1733
|
-
params.search = utils.decodeURIComponentPlus(urlHash['search']);
|
1734
|
-
}
|
1735
|
-
|
1736
|
-
// $$$ process /highlight
|
1737
|
-
|
1738
|
-
// $$$ process /theme
|
1739
|
-
if (urlHash['theme'] != undefined) {
|
1740
|
-
params.theme = urlHash['theme'];
|
1741
|
-
}
|
1742
|
-
return params;
|
1743
|
-
};
|
1744
|
-
|
1745
|
-
/**
|
1746
|
-
* Create a fragment string from the params object.
|
1747
|
-
*
|
1748
|
-
* Fragments are formatted as a URL path but may be used outside of URLs as a
|
1749
|
-
* serialization format for BookReader parameters
|
1750
|
-
*
|
1751
|
-
* @see https://openlibrary.org/dev/docs/bookurls for fragment syntax
|
1752
|
-
*
|
1753
|
-
* @param {Object} params
|
1754
|
-
* @param {string} [urlMode]
|
1755
|
-
* @return {string}
|
1756
|
-
*/
|
1757
|
-
BookReader.prototype.fragmentFromParams = function (params) {
|
1758
|
-
var urlMode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'hash';
|
1759
|
-
var fragments = [];
|
1760
|
-
if ('undefined' != typeof params.page) {
|
1761
|
-
fragments.push('page', encodeURIComponent(params.page));
|
1762
|
-
} else {
|
1763
|
-
if ('undefined' != typeof params.index) {
|
1764
|
-
// Don't have page numbering but we do have the index
|
1765
|
-
fragments.push('page', 'n' + params.index);
|
1766
|
-
}
|
1767
|
-
}
|
1768
|
-
|
1769
|
-
// $$$ highlight
|
1770
|
-
// $$$ region
|
1771
|
-
|
1772
|
-
// mode
|
1773
|
-
if ('undefined' != typeof params.mode) {
|
1774
|
-
if (params.mode == this.constMode1up) {
|
1775
|
-
fragments.push('mode', '1up');
|
1776
|
-
} else if (params.mode == this.constMode2up) {
|
1777
|
-
fragments.push('mode', '2up');
|
1778
|
-
} else if (params.mode == this.constModeThumb) {
|
1779
|
-
fragments.push('mode', 'thumb');
|
1780
|
-
} else {
|
1781
|
-
throw 'fragmentFromParams called with unknown mode ' + params.mode;
|
1782
|
-
}
|
1783
|
-
}
|
1784
|
-
|
1785
|
-
// search
|
1786
|
-
if (params.search && urlMode === 'hash') {
|
1787
|
-
fragments.push('search', utils.encodeURIComponentPlus(params.search));
|
1788
|
-
}
|
1789
|
-
return fragments.join('/');
|
1790
|
-
};
|
1791
|
-
|
1792
|
-
/**
|
1793
|
-
* Create, update querystring from the params object
|
1794
|
-
*
|
1795
|
-
* Handles:
|
1796
|
-
* view=
|
1797
|
-
* q=
|
1798
|
-
* @param {Object} params
|
1799
|
-
* @param {string} currQueryString
|
1800
|
-
* @param {string} [urlMode]
|
1801
|
-
* @return {string}
|
1802
|
-
*/
|
1803
|
-
BookReader.prototype.queryStringFromParams = function (params, currQueryString) {
|
1804
|
-
var urlMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'hash';
|
1805
|
-
var newParams = new URLSearchParams(currQueryString);
|
1806
|
-
if (params.view) {
|
1807
|
-
// Set ?view=theater when fullscreen
|
1808
|
-
newParams.set('view', params.view);
|
1809
|
-
} else {
|
1810
|
-
// Remove
|
1811
|
-
newParams.delete('view');
|
1812
|
-
}
|
1813
|
-
if (params.search && urlMode === 'history') {
|
1814
|
-
newParams.set('q', params.search);
|
1815
|
-
}
|
1816
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/toString
|
1817
|
-
// Note: This method returns the query string without the question mark.
|
1818
|
-
var result = newParams.toString();
|
1819
|
-
return result ? '?' + result : '';
|
1820
|
-
};
|
1821
|
-
|
1822
|
-
/**
|
1823
|
-
* Helper to select within instance's elements
|
1824
|
-
*/
|
1825
|
-
BookReader.prototype.$ = function (selector) {
|
1826
|
-
return this.refs.$br.find(selector);
|
1827
|
-
};
|
1828
|
-
window.BookReader = BookReader;
|