@internetarchive/bookreader 5.0.0-38 → 5.0.0-39
Sign up to get free protection for your applications and to get access to all the features.
- package/BookReader/BookReader.css +8 -0
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +99 -75
- package/BookReader/ia-bookreader-bundle.js.map +1 -1
- package/BookReader/icons/magnify-minus.svg +1 -1
- package/BookReader/icons/magnify-plus.svg +1 -1
- package/BookReader/plugins/plugin.autoplay.js +1 -1
- package/BookReader/plugins/plugin.autoplay.js.map +1 -1
- package/BookReader/plugins/plugin.chapters.js +1 -1
- package/BookReader/plugins/plugin.chapters.js.map +1 -1
- package/BookReader/plugins/plugin.mobile_nav.js +1 -1
- package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
- package/BookReader/plugins/plugin.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +1 -1
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +1 -1
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReader/plugins/plugin.url.js +1 -1
- package/BookReader/plugins/plugin.url.js.map +1 -1
- package/CHANGELOG.md +5 -0
- package/README.md +13 -0
- package/package.json +14 -14
- package/renovate.json +1 -1
- package/src/BookReader/Mode1UpLit.js +7 -1
- package/src/BookReader/Mode2Up.js +11 -0
- package/src/BookReader/ModeSmoothZoom.js +2 -0
- package/src/BookReader/PageContainer.js +10 -4
- package/src/BookReader/utils/ScrollClassAdder.js +31 -0
- package/src/assets/icons/magnify-minus.svg +3 -7
- package/src/assets/icons/magnify-plus.svg +3 -7
- package/src/css/_TextSelection.scss +13 -0
- package/tests/jest/BookReader/PageContainer.test.js +5 -4
- package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
- package/.husky/_/husky.sh +0 -30
- package/stat/BookNavigator/BookModel.js +0 -14
- package/stat/BookNavigator/BookNavigator.js +0 -524
- package/stat/BookNavigator/assets/bookmark-colors.js +0 -15
- package/stat/BookNavigator/assets/button-base.js +0 -61
- package/stat/BookNavigator/assets/ia-logo.js +0 -17
- package/stat/BookNavigator/assets/icon_checkmark.js +0 -6
- package/stat/BookNavigator/assets/icon_close.js +0 -3
- package/stat/BookNavigator/assets/icon_sort_asc.js +0 -5
- package/stat/BookNavigator/assets/icon_sort_desc.js +0 -5
- package/stat/BookNavigator/assets/icon_sort_neutral.js +0 -5
- package/stat/BookNavigator/assets/icon_volumes.js +0 -11
- package/stat/BookNavigator/bookmarks/bookmark-button.js +0 -64
- package/stat/BookNavigator/bookmarks/bookmark-edit.js +0 -215
- package/stat/BookNavigator/bookmarks/bookmarks-list.js +0 -285
- package/stat/BookNavigator/bookmarks/bookmarks-loginCTA.js +0 -28
- package/stat/BookNavigator/bookmarks/bookmarks-provider.js +0 -56
- package/stat/BookNavigator/bookmarks/ia-bookmarks.js +0 -523
- package/stat/BookNavigator/br-fullscreen-mgr.js +0 -82
- package/stat/BookNavigator/delete-modal-actions.js +0 -49
- package/stat/BookNavigator/downloads/downloads-provider.js +0 -72
- package/stat/BookNavigator/downloads/downloads.js +0 -139
- package/stat/BookNavigator/provider-config.js +0 -0
- package/stat/BookNavigator/search/a-search-result.js +0 -55
- package/stat/BookNavigator/search/search-provider.js +0 -180
- package/stat/BookNavigator/search/search-results.js +0 -360
- package/stat/BookNavigator/sharing.js +0 -31
- package/stat/BookNavigator/visual-adjustments/visual-adjustments-provider.js +0 -94
- package/stat/BookNavigator/visual-adjustments/visual-adjustments.js +0 -280
- package/stat/BookNavigator/volumes/volumes-provider.js +0 -83
- package/stat/BookNavigator/volumes/volumes.js +0 -178
- package/stat/BookReader/BookModel.js +0 -518
- package/stat/BookReader/DebugConsole.js +0 -54
- package/stat/BookReader/DragScrollable.js +0 -233
- package/stat/BookReader/ImageCache.js +0 -116
- package/stat/BookReader/Mode1Up.js +0 -102
- package/stat/BookReader/Mode1UpLit.js +0 -434
- package/stat/BookReader/Mode2Up.js +0 -1372
- package/stat/BookReader/ModeSmoothZoom.js +0 -177
- package/stat/BookReader/ModeThumb.js +0 -344
- package/stat/BookReader/Navbar/Navbar.js +0 -310
- package/stat/BookReader/PageContainer.js +0 -120
- package/stat/BookReader/ReduceSet.js +0 -26
- package/stat/BookReader/Toolbar/Toolbar.js +0 -384
- package/stat/BookReader/events.js +0 -20
- package/stat/BookReader/options.js +0 -324
- package/stat/BookReader/utils/HTMLDimensionsCacher.js +0 -44
- package/stat/BookReader/utils/classes.js +0 -36
- package/stat/BookReader/utils.js +0 -240
- package/stat/BookReader.js +0 -2550
- package/stat/BookReaderComponent/BookReaderComponent.js +0 -117
- package/stat/assets/icons/1up.svg +0 -12
- package/stat/assets/icons/2up.svg +0 -15
- package/stat/assets/icons/advance.svg +0 -26
- package/stat/assets/icons/chevron-right.svg +0 -1
- package/stat/assets/icons/close-circle-dark.svg +0 -1
- package/stat/assets/icons/close-circle.svg +0 -1
- package/stat/assets/icons/fullscreen.svg +0 -17
- package/stat/assets/icons/fullscreen_exit.svg +0 -17
- package/stat/assets/icons/hamburger.svg +0 -15
- package/stat/assets/icons/left-arrow.svg +0 -12
- package/stat/assets/icons/magnify-minus.svg +0 -16
- package/stat/assets/icons/magnify-plus.svg +0 -17
- package/stat/assets/icons/magnify.svg +0 -15
- package/stat/assets/icons/pause.svg +0 -23
- package/stat/assets/icons/play.svg +0 -22
- package/stat/assets/icons/playback-speed.svg +0 -34
- package/stat/assets/icons/read-aloud.svg +0 -22
- package/stat/assets/icons/review.svg +0 -22
- package/stat/assets/icons/thumbnails.svg +0 -17
- package/stat/assets/icons/voice.svg +0 -1
- package/stat/assets/icons/volume-full.svg +0 -22
- package/stat/assets/images/BRicons.png +0 -0
- package/stat/assets/images/BRicons.svg +0 -94
- package/stat/assets/images/BRicons_ia.png +0 -0
- package/stat/assets/images/back_pages.png +0 -0
- package/stat/assets/images/book_bottom_icon.png +0 -0
- package/stat/assets/images/book_down_icon.png +0 -0
- package/stat/assets/images/book_left_icon.png +0 -0
- package/stat/assets/images/book_leftmost_icon.png +0 -0
- package/stat/assets/images/book_right_icon.png +0 -0
- package/stat/assets/images/book_rightmost_icon.png +0 -0
- package/stat/assets/images/book_top_icon.png +0 -0
- package/stat/assets/images/book_up_icon.png +0 -0
- package/stat/assets/images/books_graphic.svg +0 -177
- package/stat/assets/images/booksplit.png +0 -0
- package/stat/assets/images/control_pause_icon.png +0 -0
- package/stat/assets/images/control_play_icon.png +0 -0
- package/stat/assets/images/embed_icon.png +0 -0
- package/stat/assets/images/icon-home-ia.png +0 -0
- package/stat/assets/images/icon_OL-logo-xs.png +0 -0
- package/stat/assets/images/icon_alert-xs.png +0 -0
- package/stat/assets/images/icon_book.svg +0 -12
- package/stat/assets/images/icon_bookmark.svg +0 -12
- package/stat/assets/images/icon_close-pop.png +0 -0
- package/stat/assets/images/icon_download.png +0 -0
- package/stat/assets/images/icon_gear.svg +0 -14
- package/stat/assets/images/icon_hamburger.svg +0 -20
- package/stat/assets/images/icon_home.png +0 -0
- package/stat/assets/images/icon_home.svg +0 -21
- package/stat/assets/images/icon_home_ia.png +0 -0
- package/stat/assets/images/icon_indicator.png +0 -0
- package/stat/assets/images/icon_info.svg +0 -11
- package/stat/assets/images/icon_one_page.svg +0 -8
- package/stat/assets/images/icon_pause.svg +0 -1
- package/stat/assets/images/icon_play.svg +0 -1
- package/stat/assets/images/icon_playback-rate.svg +0 -15
- package/stat/assets/images/icon_return.png +0 -0
- package/stat/assets/images/icon_search_button.svg +0 -8
- package/stat/assets/images/icon_share.svg +0 -9
- package/stat/assets/images/icon_skip-ahead.svg +0 -6
- package/stat/assets/images/icon_skip-back.svg +0 -13
- package/stat/assets/images/icon_speaker.svg +0 -18
- package/stat/assets/images/icon_speaker_open.svg +0 -10
- package/stat/assets/images/icon_thumbnails.svg +0 -12
- package/stat/assets/images/icon_toc.svg +0 -5
- package/stat/assets/images/icon_two_pages.svg +0 -9
- package/stat/assets/images/icon_zoomer.png +0 -0
- package/stat/assets/images/loading.gif +0 -0
- package/stat/assets/images/logo_icon.png +0 -0
- package/stat/assets/images/marker_chap-off.png +0 -0
- package/stat/assets/images/marker_chap-off.svg +0 -11
- package/stat/assets/images/marker_chap-off_ia.png +0 -0
- package/stat/assets/images/marker_chap-on.png +0 -0
- package/stat/assets/images/marker_chap-on.svg +0 -11
- package/stat/assets/images/marker_srch-on.svg +0 -11
- package/stat/assets/images/marker_srchchap-off.png +0 -0
- package/stat/assets/images/marker_srchchap-on.png +0 -0
- package/stat/assets/images/nav_control-dn.png +0 -0
- package/stat/assets/images/nav_control-dn_ia.png +0 -0
- package/stat/assets/images/nav_control-up.png +0 -0
- package/stat/assets/images/nav_control-up_ia.png +0 -0
- package/stat/assets/images/nav_control.png +0 -0
- package/stat/assets/images/one_page_mode_icon.png +0 -0
- package/stat/assets/images/paper-badge.png +0 -0
- package/stat/assets/images/print_icon.png +0 -0
- package/stat/assets/images/progressbar.gif +0 -0
- package/stat/assets/images/right_edges.png +0 -0
- package/stat/assets/images/slider.png +0 -0
- package/stat/assets/images/slider_ia.png +0 -0
- package/stat/assets/images/thumbnail_mode_icon.png +0 -0
- package/stat/assets/images/transparent.png +0 -0
- package/stat/assets/images/two_page_mode_icon.png +0 -0
- package/stat/assets/images/zoom_in_icon.png +0 -0
- package/stat/assets/images/zoom_out_icon.png +0 -0
- package/stat/css/BookReader.scss +0 -89
- package/stat/css/_BRBookmarks.scss +0 -29
- package/stat/css/_BRComponent.scss +0 -13
- package/stat/css/_BRfloat.scss +0 -197
- package/stat/css/_BRicon.scss +0 -48
- package/stat/css/_BRmain.scss +0 -251
- package/stat/css/_BRnav.scss +0 -359
- package/stat/css/_BRpages.scss +0 -139
- package/stat/css/_BRsearch.scss +0 -226
- package/stat/css/_BRtoolbar.scss +0 -84
- package/stat/css/_BRvendor.scss +0 -5
- package/stat/css/_MobileNav.scss +0 -194
- package/stat/css/_TextSelection.scss +0 -32
- package/stat/css/_colorbox.scss +0 -52
- package/stat/css/_controls.scss +0 -253
- package/stat/css/_icons.scss +0 -121
- package/stat/jquery-wrapper.js +0 -4
- package/stat/plugins/plugin.archive_analytics.js +0 -86
- package/stat/plugins/plugin.autoplay.js +0 -129
- package/stat/plugins/plugin.chapters.js +0 -248
- package/stat/plugins/plugin.iframe.js +0 -48
- package/stat/plugins/plugin.mobile_nav.js +0 -288
- package/stat/plugins/plugin.resume.js +0 -68
- package/stat/plugins/plugin.text_selection.js +0 -291
- package/stat/plugins/plugin.url.js +0 -198
- package/stat/plugins/plugin.vendor-fullscreen.js +0 -247
- package/stat/plugins/search/plugin.search.js +0 -439
- package/stat/plugins/search/view.js +0 -439
- package/stat/plugins/tts/AbstractTTSEngine.js +0 -249
- package/stat/plugins/tts/FestivalTTSEngine.js +0 -169
- package/stat/plugins/tts/PageChunk.js +0 -107
- package/stat/plugins/tts/PageChunkIterator.js +0 -163
- package/stat/plugins/tts/WebTTSEngine.js +0 -357
- package/stat/plugins/tts/plugin.tts.js +0 -357
- package/stat/plugins/tts/tooltip_dict.js +0 -15
- package/stat/plugins/tts/utils.js +0 -91
- package/stat/util/browserSniffing.js +0 -30
- package/stat/util/debouncer.js +0 -26
- package/stat/util/docCookies.js +0 -67
- package/stat/util/strings.js +0 -34
package/stat/BookReader.js
DELETED
@@ -1,2550 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
Copyright(c)2008-2019 Internet Archive. Software license AGPL version 3.
|
3
|
-
|
4
|
-
This file is part of BookReader.
|
5
|
-
|
6
|
-
BookReader is free software: you can redistribute it and/or modify
|
7
|
-
it under the terms of the GNU Affero General Public License as published by
|
8
|
-
the Free Software Foundation, either version 3 of the License, or
|
9
|
-
(at your option) any later version.
|
10
|
-
|
11
|
-
BookReader is distributed in the hope that it will be useful,
|
12
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
-
GNU Affero General Public License for more details.
|
15
|
-
|
16
|
-
You should have received a copy of the GNU Affero General Public License
|
17
|
-
along with BookReader. If not, see <http://www.gnu.org/licenses/>.
|
18
|
-
|
19
|
-
The BookReader source is hosted at http://github.com/internetarchive/bookreader/
|
20
|
-
|
21
|
-
*/
|
22
|
-
// effect.js gives acces to extra easing function (e.g. easeInOutExpo)
|
23
|
-
import 'jquery-ui/ui/effect.js';
|
24
|
-
|
25
|
-
// Needed by touch-punch
|
26
|
-
import 'jquery-ui/ui/widget.js';
|
27
|
-
import 'jquery-ui/ui/widgets/mouse.js';
|
28
|
-
import 'jquery-ui-touch-punch';
|
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, getNavPageNumHtml } from './BookReader/Navbar/Navbar.js';
|
34
|
-
import { DEFAULT_OPTIONS } 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 { DebugConsole } from './BookReader/DebugConsole.js';
|
40
|
-
import {
|
41
|
-
Toolbar,
|
42
|
-
blankInfoDiv,
|
43
|
-
blankShareDiv,
|
44
|
-
createPopup,
|
45
|
-
} from './BookReader/Toolbar/Toolbar.js';
|
46
|
-
import { BookModel } from './BookReader/BookModel.js';
|
47
|
-
import { Mode1Up } from './BookReader/Mode1Up.js';
|
48
|
-
import { Mode2Up } from './BookReader/Mode2Up.js';
|
49
|
-
import { ModeThumb } from './BookReader/ModeThumb';
|
50
|
-
import { ImageCache } from './BookReader/ImageCache.js';
|
51
|
-
import { PageContainer } from './BookReader/PageContainer.js';
|
52
|
-
import { NAMED_REDUCE_SETS } from './BookReader/ReduceSet';
|
53
|
-
|
54
|
-
if (location.toString().indexOf('_debugShowConsole=true') != -1) {
|
55
|
-
$(() => new DebugConsole().init());
|
56
|
-
}
|
57
|
-
|
58
|
-
/**
|
59
|
-
* BookReader
|
60
|
-
* @param {BookReaderOptions} options
|
61
|
-
* TODO document all options properties
|
62
|
-
* @constructor
|
63
|
-
*/
|
64
|
-
export default function BookReader(overrides = {}) {
|
65
|
-
const options = jQuery.extend(true, {}, BookReader.defaultOptions, overrides, BookReader.optionOverrides);
|
66
|
-
this.setup(options);
|
67
|
-
}
|
68
|
-
|
69
|
-
BookReader.version = PACKAGE_JSON.version;
|
70
|
-
|
71
|
-
// Mode constants
|
72
|
-
/** 1 page view */
|
73
|
-
BookReader.constMode1up = 1;
|
74
|
-
/** 2 pages view */
|
75
|
-
BookReader.constMode2up = 2;
|
76
|
-
/** thumbnails view */
|
77
|
-
BookReader.constModeThumb = 3;
|
78
|
-
/** image cache */
|
79
|
-
BookReader.imageCache = null;
|
80
|
-
|
81
|
-
// Animation constants
|
82
|
-
BookReader.constNavAnimationDuration = 300;
|
83
|
-
BookReader.constResizeAnimationDuration = 100;
|
84
|
-
|
85
|
-
// Names of events that can be triggered via BookReader.prototype.trigger()
|
86
|
-
BookReader.eventNames = EVENTS;
|
87
|
-
|
88
|
-
BookReader.defaultOptions = DEFAULT_OPTIONS;
|
89
|
-
|
90
|
-
/**
|
91
|
-
* @type {BookReaderOptions}
|
92
|
-
* This is here, just in case you need to absolutely override an option.
|
93
|
-
*/
|
94
|
-
BookReader.optionOverrides = {};
|
95
|
-
|
96
|
-
/**
|
97
|
-
* Setup
|
98
|
-
* It is separate from the constructor, so plugins can extend.
|
99
|
-
* @param {BookReaderOptions} options
|
100
|
-
*/
|
101
|
-
BookReader.prototype.setup = function(options) {
|
102
|
-
// Store the options used to setup bookreader
|
103
|
-
this.options = options;
|
104
|
-
|
105
|
-
/** @type {number} @deprecated some past iterations set this */
|
106
|
-
this.numLeafs = undefined;
|
107
|
-
|
108
|
-
/** Overridden by plugin.search.js */
|
109
|
-
this.enableSearch = false;
|
110
|
-
|
111
|
-
/**
|
112
|
-
* Store viewModeOrder states
|
113
|
-
* @var {boolean}
|
114
|
-
*/
|
115
|
-
this.viewModeOrder = [];
|
116
|
-
|
117
|
-
/**
|
118
|
-
* Used to suppress fragment change for init with canonical URLs
|
119
|
-
* @var {boolean}
|
120
|
-
*/
|
121
|
-
this.suppressFragmentChange = false;
|
122
|
-
|
123
|
-
/** @type {function(): void} */
|
124
|
-
this.animationFinishedCallback = null;
|
125
|
-
|
126
|
-
// @deprecated: Instance constants. Use Class constants instead
|
127
|
-
/** 1 page view */
|
128
|
-
this.constMode1up = BookReader.constMode1up;
|
129
|
-
/** 2 pages view */
|
130
|
-
this.constMode2up = BookReader.constMode2up;
|
131
|
-
/** thumbnails view */
|
132
|
-
this.constModeThumb = BookReader.constModeThumb;
|
133
|
-
|
134
|
-
// Private properties below. Configuration should be done with options.
|
135
|
-
/** @type {number} TODO: Make private */
|
136
|
-
this.reduce = 8; /* start very small */
|
137
|
-
this.defaults = options.defaults;
|
138
|
-
this.padding = options.padding;
|
139
|
-
|
140
|
-
this.reduceSet = NAMED_REDUCE_SETS[options.reduceSet];
|
141
|
-
if (!this.reduceSet) {
|
142
|
-
console.warn(`Invalid reduceSet ${options.reduceSet}. Ignoring.`);
|
143
|
-
this.reduceSet = NAMED_REDUCE_SETS[DEFAULT_OPTIONS.reduceSet];
|
144
|
-
}
|
145
|
-
|
146
|
-
/** @type {number}
|
147
|
-
* can be 1 or 2 or 3 based on the display mode const value
|
148
|
-
*/
|
149
|
-
this.mode = null;
|
150
|
-
this.prevReadMode = null;
|
151
|
-
this.ui = options.ui;
|
152
|
-
this.uiAutoHide = options.uiAutoHide;
|
153
|
-
|
154
|
-
this.thumbWidth = 100; // will be overridden during prepareThumbnailView
|
155
|
-
this.thumbRowBuffer = options.thumbRowBuffer;
|
156
|
-
this.thumbColumns = options.thumbColumns;
|
157
|
-
this.thumbMaxLoading = options.thumbMaxLoading;
|
158
|
-
this.thumbPadding = options.thumbPadding;
|
159
|
-
this.displayedRows = [];
|
160
|
-
|
161
|
-
this.displayedIndices = [];
|
162
|
-
/** @deprecated Unused; will be remove in v5 */
|
163
|
-
this.imgs = {};
|
164
|
-
/** @deprecated No longer used; will be remove in v5 */
|
165
|
-
this.prefetchedImgs = {}; //an object with numeric keys corresponding to page index, reduce
|
166
|
-
|
167
|
-
this.animating = false;
|
168
|
-
this.flipSpeed = options.flipSpeed;
|
169
|
-
this.flipDelay = options.flipDelay;
|
170
|
-
this.twoPagePopUp = null;
|
171
|
-
this.leafEdgeTmp = null;
|
172
|
-
|
173
|
-
/**
|
174
|
-
* Represents the first displayed index
|
175
|
-
* In 2up mode it will be the left page
|
176
|
-
* In 1 up mode it is the highest page
|
177
|
-
* @property {number|null} firstIndex
|
178
|
-
*/
|
179
|
-
this.firstIndex = null;
|
180
|
-
this.lastDisplayableIndex2up = null;
|
181
|
-
this.isFullscreenActive = false;
|
182
|
-
this.lastScroll = null;
|
183
|
-
|
184
|
-
this.showLogo = options.showLogo;
|
185
|
-
this.logoURL = options.logoURL;
|
186
|
-
this.imagesBaseURL = options.imagesBaseURL;
|
187
|
-
|
188
|
-
this.reductionFactors = options.reductionFactors;
|
189
|
-
this.onePage = options.onePage;
|
190
|
-
/** @type {import('./BookReader/Mode2Up').TwoPageState} */
|
191
|
-
this.twoPage = options.twoPage;
|
192
|
-
this.onePageMinBreakpoint = options.onePageMinBreakpoint;
|
193
|
-
|
194
|
-
this.bookTitle = options.bookTitle;
|
195
|
-
this.bookUrl = options.bookUrl;
|
196
|
-
this.bookUrlText = options.bookUrlText;
|
197
|
-
this.bookUrlTitle = options.bookUrlTitle;
|
198
|
-
this.titleLeaf = options.titleLeaf;
|
199
|
-
|
200
|
-
this.metadata = options.metadata;
|
201
|
-
this.thumbnail = options.thumbnail;
|
202
|
-
this.bookUrlMoreInfo = options.bookUrlMoreInfo;
|
203
|
-
|
204
|
-
this.enableExperimentalControls = options.enableExperimentalControls;
|
205
|
-
this.el = options.el;
|
206
|
-
|
207
|
-
this.pageProgression = options.pageProgression;
|
208
|
-
this.protected = options.protected;
|
209
|
-
this.getEmbedCode = options.getEmbedCode;
|
210
|
-
this.popup = null;
|
211
|
-
|
212
|
-
// Assign the data methods
|
213
|
-
this.data = options.data;
|
214
|
-
if (options.getNumLeafs) BookReader.prototype.getNumLeafs = options.getNumLeafs;
|
215
|
-
if (options.getPageWidth) BookReader.prototype.getPageWidth = options.getPageWidth;
|
216
|
-
if (options.getPageHeight) BookReader.prototype.getPageHeight = options.getPageHeight;
|
217
|
-
if (options.getPageURI) BookReader.prototype.getPageURI = options.getPageURI;
|
218
|
-
if (options.getPageSide) BookReader.prototype.getPageSide = options.getPageSide;
|
219
|
-
if (options.getPageNum) BookReader.prototype.getPageNum = options.getPageNum;
|
220
|
-
if (options.getPageProp) BookReader.prototype.getPageProp = options.getPageProp;
|
221
|
-
if (options.getSpreadIndices) BookReader.prototype.getSpreadIndices = options.getSpreadIndices;
|
222
|
-
if (options.leafNumToIndex) BookReader.prototype.leafNumToIndex = options.leafNumToIndex;
|
223
|
-
|
224
|
-
/** @type {{[name: string]: JQuery}} */
|
225
|
-
this.refs = {};
|
226
|
-
|
227
|
-
/**
|
228
|
-
* @private (for now) Models are largely state storing classes. This might be too much
|
229
|
-
* granularity, but time will tell!
|
230
|
-
*/
|
231
|
-
this._models = {
|
232
|
-
book: new BookModel(this),
|
233
|
-
};
|
234
|
-
|
235
|
-
/**
|
236
|
-
* @private Components are 'subchunks' of bookreader functionality, usually UI related
|
237
|
-
* They should be relatively decoupled from each other/bookreader.
|
238
|
-
* Note there are no hooks right now; components just provide methods that bookreader
|
239
|
-
* calls at the correct moments.
|
240
|
-
**/
|
241
|
-
this._components = {
|
242
|
-
navbar: new Navbar(this),
|
243
|
-
toolbar: new Toolbar(this),
|
244
|
-
};
|
245
|
-
|
246
|
-
this._modes = {
|
247
|
-
mode1Up: new Mode1Up(this, this._models.book),
|
248
|
-
mode2Up: new Mode2Up(this, this._models.book),
|
249
|
-
modeThumb: new ModeThumb(this, this._models.book),
|
250
|
-
};
|
251
|
-
|
252
|
-
/** Stores classes which we want to expose (selectively) some methods as overridable */
|
253
|
-
this._overrideable = {
|
254
|
-
'_models.book': this._models.book,
|
255
|
-
'_components.navbar': this._components.navbar,
|
256
|
-
'_components.toolbar': this._components.toolbar,
|
257
|
-
'_modes.mode1Up': this._modes.mode1Up,
|
258
|
-
'_modes.mode2Up': this._modes.mode2Up,
|
259
|
-
'_modes.modeThumb': this._modes.modeThumb,
|
260
|
-
};
|
261
|
-
|
262
|
-
/** Image cache for general image fetching */
|
263
|
-
this.imageCache = new ImageCache(this._models.book, {
|
264
|
-
useSrcSet: this.options.useSrcSet,
|
265
|
-
reduceSet: this.reduceSet,
|
266
|
-
});
|
267
|
-
};
|
268
|
-
|
269
|
-
/**
|
270
|
-
* Get all the HTML Elements that are being/can be rendered.
|
271
|
-
* Includes cached elements which might be rendered again.
|
272
|
-
*/
|
273
|
-
BookReader.prototype.getActivePageContainerElements = function() {
|
274
|
-
let containerEls = Object.values(this._modes.mode2Up.pageContainers).map(pc => pc.$container[0])
|
275
|
-
.concat(Object.values(this._modes.mode1Up.mode1UpLit.pageContainerCache).map(pc => pc.$container[0]));
|
276
|
-
if (this.mode == this.constModeThumb) {
|
277
|
-
containerEls = containerEls.concat(this.$('.BRpagecontainer').toArray());
|
278
|
-
}
|
279
|
-
return containerEls;
|
280
|
-
};
|
281
|
-
|
282
|
-
/**
|
283
|
-
* Get the HTML Elements for the rendered page. Note there can be more than one, since
|
284
|
-
* (at least as of writing) different modes can maintain different caches.
|
285
|
-
* @param {PageIndex} pageIndex
|
286
|
-
*/
|
287
|
-
BookReader.prototype.getActivePageContainerElementsForIndex = function(pageIndex) {
|
288
|
-
return [
|
289
|
-
this._modes.mode2Up.pageContainers[pageIndex]?.$container?.[0],
|
290
|
-
this._modes.mode1Up.mode1UpLit.pageContainerCache[pageIndex]?.$container?.[0],
|
291
|
-
...(this.mode == this.constModeThumb ? this.$(`.pagediv${pageIndex}`).toArray() : [])
|
292
|
-
].filter(x => x);
|
293
|
-
};
|
294
|
-
|
295
|
-
Object.defineProperty(BookReader.prototype, 'activeMode', {
|
296
|
-
/** @return {Mode1Up | Mode2Up | ModeThumb} */
|
297
|
-
get() { return {
|
298
|
-
1: this._modes.mode1Up,
|
299
|
-
2: this._modes.mode2Up,
|
300
|
-
3: this._modes.modeThumb,
|
301
|
-
}[this.mode]; },
|
302
|
-
});
|
303
|
-
|
304
|
-
/** @deprecated unused outside Mode2Up */
|
305
|
-
Object.defineProperty(BookReader.prototype, 'leafEdgeL', {
|
306
|
-
get() { return this._modes.mode2Up.leafEdgeL; },
|
307
|
-
set(newVal) { this._modes.mode2Up.leafEdgeL = newVal; }
|
308
|
-
});
|
309
|
-
/** @deprecated unused outside Mode2Up */
|
310
|
-
Object.defineProperty(BookReader.prototype, 'leafEdgeR', {
|
311
|
-
get() { return this._modes.mode2Up.leafEdgeR; },
|
312
|
-
set(newVal) { this._modes.mode2Up.leafEdgeR = newVal; }
|
313
|
-
});
|
314
|
-
|
315
|
-
/**
|
316
|
-
* BookReader.util are static library functions
|
317
|
-
* At top of file so they can be used below
|
318
|
-
*/
|
319
|
-
BookReader.util = utils;
|
320
|
-
|
321
|
-
/**
|
322
|
-
* Helper to merge in params in to a params object.
|
323
|
-
* It normalizes "page" into the "index" field to disambiguate and prevent concflicts
|
324
|
-
* @private
|
325
|
-
*/
|
326
|
-
BookReader.prototype.extendParams = function(params, newParams) {
|
327
|
-
var modifiedNewParams = $.extend({}, newParams);
|
328
|
-
if ('undefined' != typeof(modifiedNewParams.page)) {
|
329
|
-
var pageIndex = this._models.book.parsePageString(modifiedNewParams.page);
|
330
|
-
if (!isNaN(pageIndex))
|
331
|
-
modifiedNewParams.index = pageIndex;
|
332
|
-
delete modifiedNewParams.page;
|
333
|
-
}
|
334
|
-
$.extend(params, modifiedNewParams);
|
335
|
-
};
|
336
|
-
|
337
|
-
/**
|
338
|
-
* Parses params from from various initialization contexts (url, cookie, options)
|
339
|
-
* @private
|
340
|
-
* @return {object} the parsed params
|
341
|
-
*/
|
342
|
-
BookReader.prototype.initParams = function() {
|
343
|
-
var params = {};
|
344
|
-
// Flag initializing for updateFromParams()
|
345
|
-
params.init = true;
|
346
|
-
|
347
|
-
// Flag if page given in defaults or URL (not cookie)
|
348
|
-
// Used for overriding goToFirstResult in plugin.search.js
|
349
|
-
// Note: extendParams() converts params.page to index and gets rid of page
|
350
|
-
// so check and set before extendParams()
|
351
|
-
params.pageFound = false;
|
352
|
-
|
353
|
-
// True if changing the URL
|
354
|
-
params.fragmentChange = false;
|
355
|
-
|
356
|
-
// This is ordered from lowest to highest priority
|
357
|
-
|
358
|
-
// If we have a title leaf, use that as the default instead of index 0,
|
359
|
-
// but only use as default if book has a few pages
|
360
|
-
if ('undefined' != typeof(this.titleLeaf) && this._models.book.getNumLeafs() > 2) {
|
361
|
-
params.index = this._models.book.leafNumToIndex(this.titleLeaf);
|
362
|
-
} else {
|
363
|
-
params.index = 0;
|
364
|
-
}
|
365
|
-
|
366
|
-
// this.defaults is a string passed in the url format. eg "page/1/mode/1up"
|
367
|
-
if (this.defaults) {
|
368
|
-
const defaultParams = this.paramsFromFragment(this.defaults);
|
369
|
-
if ('undefined' != typeof(defaultParams.page)) {
|
370
|
-
params.pageFound = true;
|
371
|
-
}
|
372
|
-
this.extendParams(params, defaultParams);
|
373
|
-
}
|
374
|
-
|
375
|
-
// Check for Resume plugin
|
376
|
-
if (this.options.enablePageResume) {
|
377
|
-
// Check cookies
|
378
|
-
const val = this.getResumeValue();
|
379
|
-
if (val !== null) {
|
380
|
-
// If page index different from default
|
381
|
-
if (params.index !== val) {
|
382
|
-
// Show in URL
|
383
|
-
params.fragmentChange = true;
|
384
|
-
}
|
385
|
-
params.index = val;
|
386
|
-
}
|
387
|
-
}
|
388
|
-
|
389
|
-
// Check for URL plugin
|
390
|
-
if (this.options.enableUrlPlugin) {
|
391
|
-
// Params explicitly set in URL take precedence over all other methods
|
392
|
-
var urlParams = this.paramsFromFragment(this.urlReadFragment());
|
393
|
-
|
394
|
-
// Get params if hash fragment available with 'history' urlMode
|
395
|
-
const hasHashURL = !Object.keys(urlParams).length && this.urlReadHashFragment();
|
396
|
-
if (hasHashURL && (this.options.urlMode === 'history')) {
|
397
|
-
urlParams = this.paramsFromFragment(this.urlReadHashFragment());
|
398
|
-
}
|
399
|
-
|
400
|
-
// If there were any parameters
|
401
|
-
if (Object.keys(urlParams).length) {
|
402
|
-
if ('undefined' != typeof(urlParams.page)) {
|
403
|
-
params.pageFound = true;
|
404
|
-
}
|
405
|
-
this.extendParams(params, urlParams);
|
406
|
-
// Show in URL
|
407
|
-
params.fragmentChange = true;
|
408
|
-
}
|
409
|
-
}
|
410
|
-
|
411
|
-
// Check for Search plugin
|
412
|
-
if (this.options.enableSearch) {
|
413
|
-
// Go to first result only if no default or URL page
|
414
|
-
this.options.goToFirstResult = !params.pageFound;
|
415
|
-
|
416
|
-
// If initialSearchTerm not set
|
417
|
-
if (!this.options.initialSearchTerm) {
|
418
|
-
// Look for any term in URL
|
419
|
-
if (params.search) {
|
420
|
-
// Old style: /search/[term]
|
421
|
-
this.options.initialSearchTerm = params.search;
|
422
|
-
this.searchTerm = params.search;
|
423
|
-
} else {
|
424
|
-
// If we have a query string: q=[term]
|
425
|
-
const searchParams = new URLSearchParams(this.readQueryString());
|
426
|
-
const searchTerm = searchParams.get('q');
|
427
|
-
if (searchTerm) {
|
428
|
-
this.options.initialSearchTerm = utils.decodeURIComponentPlus(searchTerm);
|
429
|
-
}
|
430
|
-
}
|
431
|
-
}
|
432
|
-
}
|
433
|
-
|
434
|
-
// Set for init process, return to false at end of init()
|
435
|
-
this.suppressFragmentChange = !params.fragmentChange;
|
436
|
-
|
437
|
-
return params;
|
438
|
-
};
|
439
|
-
|
440
|
-
/**
|
441
|
-
* Allow mocking of window.location.search
|
442
|
-
*/
|
443
|
-
BookReader.prototype.getLocationSearch = function () {
|
444
|
-
return window.location.search;
|
445
|
-
};
|
446
|
-
|
447
|
-
/**
|
448
|
-
* Allow mocking of window.location.hash
|
449
|
-
*/
|
450
|
-
BookReader.prototype.getLocationHash = function () {
|
451
|
-
return window.location.hash;
|
452
|
-
};
|
453
|
-
|
454
|
-
/**
|
455
|
-
* Return URL or fragment querystring
|
456
|
-
*/
|
457
|
-
BookReader.prototype.readQueryString = function() {
|
458
|
-
const queryString = this.getLocationSearch();
|
459
|
-
if (queryString) {
|
460
|
-
return queryString;
|
461
|
-
}
|
462
|
-
const hash = this.getLocationHash();
|
463
|
-
const found = hash.search(/\?\w+=/);
|
464
|
-
return found > -1 ? hash.slice(found) : '';
|
465
|
-
};
|
466
|
-
|
467
|
-
/**
|
468
|
-
* Determines the initial mode for starting if a mode is not already
|
469
|
-
* present in the params argument
|
470
|
-
* @param {object} params
|
471
|
-
* @return {number} the mode
|
472
|
-
*/
|
473
|
-
BookReader.prototype.getInitialMode = function(params) {
|
474
|
-
// Use params or browser width to set view mode
|
475
|
-
var windowWidth = $(window).width();
|
476
|
-
var nextMode;
|
477
|
-
if ('undefined' != typeof(params.mode)) {
|
478
|
-
nextMode = params.mode;
|
479
|
-
} else if (this.ui == 'full'
|
480
|
-
&& this.enableMobileNav
|
481
|
-
&& this.isFullscreenActive
|
482
|
-
&& windowWidth <= this.onePageMinBreakpoint
|
483
|
-
) {
|
484
|
-
// In full mode, we set the default based on width
|
485
|
-
nextMode = this.constMode1up;
|
486
|
-
} else {
|
487
|
-
nextMode = this.constMode2up;
|
488
|
-
}
|
489
|
-
|
490
|
-
if (!this.canSwitchToMode(nextMode)) {
|
491
|
-
nextMode = this.constMode1up;
|
492
|
-
}
|
493
|
-
return nextMode;
|
494
|
-
};
|
495
|
-
|
496
|
-
/**
|
497
|
-
* This is called by the client to initialize BookReader.
|
498
|
-
* It renders onto the DOM. It should only be called once.
|
499
|
-
*/
|
500
|
-
BookReader.prototype.init = function() {
|
501
|
-
this.init.initComplete = false;
|
502
|
-
this.pageScale = this.reduce; // preserve current reduce
|
503
|
-
|
504
|
-
var params = this.initParams();
|
505
|
-
|
506
|
-
this.firstIndex = params.index ? params.index : 0;
|
507
|
-
|
508
|
-
// Setup Navbars and other UI
|
509
|
-
this.isTouchDevice = !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);
|
510
|
-
|
511
|
-
this.refs.$br = $(this.el)
|
512
|
-
.empty()
|
513
|
-
.removeClass()
|
514
|
-
.addClass("ui-" + this.ui)
|
515
|
-
.addClass("br-ui-" + this.ui)
|
516
|
-
.addClass('BookReader');
|
517
|
-
|
518
|
-
// Add a class if this is a touch enabled device
|
519
|
-
if (this.isTouchDevice) {
|
520
|
-
this.refs.$br.addClass("touch");
|
521
|
-
} else {
|
522
|
-
this.refs.$br.addClass("no-touch");
|
523
|
-
}
|
524
|
-
|
525
|
-
this.refs.$brContainer = $("<div class='BRcontainer' dir='ltr'></div>");
|
526
|
-
this.refs.$br.append(this.refs.$brContainer);
|
527
|
-
|
528
|
-
// Explicitly ensure params.mode exists for updateFromParams() below
|
529
|
-
params.mode = this.getInitialMode(params);
|
530
|
-
|
531
|
-
// Explicitly ensure this.mode exists for initNavbar() below
|
532
|
-
this.mode = params.mode;
|
533
|
-
|
534
|
-
// Display Navigation
|
535
|
-
if (this.options.showToolbar) {
|
536
|
-
this.initToolbar(this.mode, this.ui); // Build inside of toolbar div
|
537
|
-
}
|
538
|
-
if (this.options.showNavbar) { // default navigation
|
539
|
-
this.initNavbar();
|
540
|
-
}
|
541
|
-
|
542
|
-
// Switch navbar controls on mobile/desktop
|
543
|
-
this.switchNavbarControls();
|
544
|
-
|
545
|
-
this.resizeBRcontainer();
|
546
|
-
this.updateFromParams(params);
|
547
|
-
this.initUIStrings();
|
548
|
-
|
549
|
-
// Bind to events
|
550
|
-
|
551
|
-
this.bindNavigationHandlers();
|
552
|
-
this.setupKeyListeners();
|
553
|
-
|
554
|
-
this.lastScroll = (new Date().getTime());
|
555
|
-
this.refs.$brContainer.on('scroll', this, function(e) {
|
556
|
-
// Note, this scroll event fires for both user, and js generated calls
|
557
|
-
// It is functioning in some cases as the primary triggerer for rendering
|
558
|
-
e.data.lastScroll = (new Date().getTime());
|
559
|
-
if (e.data.constModeThumb == e.data.mode) {
|
560
|
-
e.data.drawLeafsThrottled();
|
561
|
-
}
|
562
|
-
});
|
563
|
-
|
564
|
-
if (this.options.autoResize) {
|
565
|
-
$(window).on('resize', this, function(e) {
|
566
|
-
e.data.resize();
|
567
|
-
});
|
568
|
-
$(window).on("orientationchange", this, function(e) {
|
569
|
-
e.data.resize();
|
570
|
-
}.bind(this));
|
571
|
-
}
|
572
|
-
|
573
|
-
if (this.protected) {
|
574
|
-
this.$('.BRicon.share').hide();
|
575
|
-
}
|
576
|
-
|
577
|
-
// If not searching, set to allow on-going fragment changes
|
578
|
-
if (!this.options.initialSearchTerm) {
|
579
|
-
this.suppressFragmentChange = false;
|
580
|
-
}
|
581
|
-
|
582
|
-
this.init.initComplete = true;
|
583
|
-
this.trigger(BookReader.eventNames.PostInit);
|
584
|
-
|
585
|
-
// Must be called after this.init.initComplete set to true to allow
|
586
|
-
// BookReader.prototype.resize to run.
|
587
|
-
if (this.options.startFullscreen) {
|
588
|
-
this.toggleFullscreen();
|
589
|
-
}
|
590
|
-
};
|
591
|
-
|
592
|
-
/**
|
593
|
-
* @param {EVENTS} name
|
594
|
-
* @param {array | object} [props]
|
595
|
-
*/
|
596
|
-
BookReader.prototype.trigger = function(name, props = this) {
|
597
|
-
const eventName = 'BookReader:' + name;
|
598
|
-
$(document).trigger(eventName, props);
|
599
|
-
|
600
|
-
utils.polyfillCustomEvent(window);
|
601
|
-
window.dispatchEvent(new CustomEvent(eventName, {
|
602
|
-
bubbles: true,
|
603
|
-
composed: true,
|
604
|
-
detail: { props },
|
605
|
-
}));
|
606
|
-
};
|
607
|
-
|
608
|
-
BookReader.prototype.bind = function(name, callback) {
|
609
|
-
$(document).on('BookReader:' + name, callback);
|
610
|
-
};
|
611
|
-
|
612
|
-
BookReader.prototype.unbind = function(name, callback) {
|
613
|
-
$(document).off('BookReader:' + name, callback);
|
614
|
-
};
|
615
|
-
|
616
|
-
/**
|
617
|
-
* Resizes based on the container width and height
|
618
|
-
*/
|
619
|
-
BookReader.prototype.resize = function() {
|
620
|
-
if (!this.init.initComplete) return;
|
621
|
-
|
622
|
-
this.resizeBRcontainer();
|
623
|
-
|
624
|
-
// Switch navbar controls on mobile/desktop
|
625
|
-
this.switchNavbarControls();
|
626
|
-
|
627
|
-
if (this.constMode1up == this.mode) {
|
628
|
-
if (this.onePage.autofit != 'none') {
|
629
|
-
this.resizePageView1up();
|
630
|
-
this.centerPageView();
|
631
|
-
} else {
|
632
|
-
this.centerPageView();
|
633
|
-
this.displayedIndices = [];
|
634
|
-
this.drawLeafsThrottled();
|
635
|
-
}
|
636
|
-
} else if (this.constModeThumb == this.mode) {
|
637
|
-
this.prepareThumbnailView();
|
638
|
-
} else {
|
639
|
-
// We only need to prepare again in autofit (size of spread changes)
|
640
|
-
if (this.twoPage.autofit) {
|
641
|
-
// most common path, esp. for archive.org books
|
642
|
-
this.prepareTwoPageView();
|
643
|
-
} else {
|
644
|
-
// used when zoomed in
|
645
|
-
// Re-center if the scrollbars have disappeared
|
646
|
-
var center = this.twoPageGetViewCenter();
|
647
|
-
var doRecenter = false;
|
648
|
-
if (this.twoPage.totalWidth < this.refs.$brContainer.prop('clientWidth')) {
|
649
|
-
center.percentageX = 0.5;
|
650
|
-
doRecenter = true;
|
651
|
-
}
|
652
|
-
if (this.twoPage.totalHeight < this.refs.$brContainer.prop('clientHeight')) {
|
653
|
-
center.percentageY = 0.5;
|
654
|
-
doRecenter = true;
|
655
|
-
}
|
656
|
-
if (doRecenter) {
|
657
|
-
this.twoPageCenterView(center.percentageX, center.percentageY);
|
658
|
-
}
|
659
|
-
}
|
660
|
-
}
|
661
|
-
this.trigger(BookReader.eventNames.resize);
|
662
|
-
};
|
663
|
-
|
664
|
-
/**
|
665
|
-
* Binds keyboard event listeners
|
666
|
-
*/
|
667
|
-
BookReader.prototype.setupKeyListeners = function() {
|
668
|
-
var self = this;
|
669
|
-
|
670
|
-
var KEY_PGUP = 33;
|
671
|
-
var KEY_PGDOWN = 34;
|
672
|
-
var KEY_END = 35;
|
673
|
-
var KEY_HOME = 36;
|
674
|
-
|
675
|
-
var KEY_LEFT = 37;
|
676
|
-
var KEY_UP = 38;
|
677
|
-
var KEY_RIGHT = 39;
|
678
|
-
var KEY_DOWN = 40;
|
679
|
-
// The minus(-) and equal(=) keys have different mappings for different browsers
|
680
|
-
var KEY_MINUS = 189; // Chrome
|
681
|
-
var KEY_MINUS_F = 173; // Firefox
|
682
|
-
var KEY_NUMPAD_SUBTRACT = 109;
|
683
|
-
var KEY_EQUAL = 187; // Chrome
|
684
|
-
var KEY_EQUAL_F = 61; // Firefox
|
685
|
-
var KEY_NUMPAD_ADD = 107;
|
686
|
-
|
687
|
-
// We use document here instead of window to avoid a bug in jQuery on IE7
|
688
|
-
$(document).on("keydown", function(e) {
|
689
|
-
|
690
|
-
// Keyboard navigation
|
691
|
-
switch (e.keyCode) {
|
692
|
-
case KEY_PGUP:
|
693
|
-
case KEY_UP:
|
694
|
-
// In 1up mode page scrolling is handled by browser
|
695
|
-
if (!utils.isInputActive() && self.constMode2up == self.mode) {
|
696
|
-
e.preventDefault();
|
697
|
-
self.prev();
|
698
|
-
}
|
699
|
-
break;
|
700
|
-
case KEY_DOWN:
|
701
|
-
case KEY_PGDOWN:
|
702
|
-
if (!utils.isInputActive() && self.constMode2up == self.mode) {
|
703
|
-
e.preventDefault();
|
704
|
-
self.next();
|
705
|
-
}
|
706
|
-
break;
|
707
|
-
case KEY_END:
|
708
|
-
if (!utils.isInputActive()) {
|
709
|
-
e.preventDefault();
|
710
|
-
self.last();
|
711
|
-
}
|
712
|
-
break;
|
713
|
-
case KEY_HOME:
|
714
|
-
if (!utils.isInputActive()) {
|
715
|
-
e.preventDefault();
|
716
|
-
self.first();
|
717
|
-
}
|
718
|
-
break;
|
719
|
-
case KEY_LEFT:
|
720
|
-
if (!utils.isInputActive() && self.constModeThumb != self.mode) {
|
721
|
-
e.preventDefault();
|
722
|
-
self.left();
|
723
|
-
}
|
724
|
-
break;
|
725
|
-
case KEY_RIGHT:
|
726
|
-
if (!utils.isInputActive() && self.constModeThumb != self.mode) {
|
727
|
-
e.preventDefault();
|
728
|
-
self.right();
|
729
|
-
}
|
730
|
-
break;
|
731
|
-
case KEY_MINUS:
|
732
|
-
case KEY_MINUS_F:
|
733
|
-
case KEY_NUMPAD_SUBTRACT:
|
734
|
-
if (!utils.isInputActive()) {
|
735
|
-
e.preventDefault();
|
736
|
-
self.zoom(-1);
|
737
|
-
}
|
738
|
-
break;
|
739
|
-
case KEY_EQUAL:
|
740
|
-
case KEY_EQUAL_F:
|
741
|
-
case KEY_NUMPAD_ADD:
|
742
|
-
if (!utils.isInputActive()) {
|
743
|
-
e.preventDefault();
|
744
|
-
self.zoom(+1);
|
745
|
-
}
|
746
|
-
break;
|
747
|
-
}
|
748
|
-
});
|
749
|
-
};
|
750
|
-
|
751
|
-
BookReader.prototype.drawLeafs = function() {
|
752
|
-
if (this.constMode1up == this.mode) {
|
753
|
-
// Not needed for Mode1Up anymore
|
754
|
-
} else if (this.constModeThumb == this.mode) {
|
755
|
-
this.drawLeafsThumbnail();
|
756
|
-
} else {
|
757
|
-
this.drawLeafsTwoPage();
|
758
|
-
}
|
759
|
-
};
|
760
|
-
|
761
|
-
/**
|
762
|
-
* @protected
|
763
|
-
* @param {PageIndex} index
|
764
|
-
*/
|
765
|
-
BookReader.prototype._createPageContainer = function(index) {
|
766
|
-
return new PageContainer(this._models.book.getPage(index, false), {
|
767
|
-
isProtected: this.protected,
|
768
|
-
imageCache: this.imageCache,
|
769
|
-
loadingImage: this.imagesBaseURL + 'loading.gif',
|
770
|
-
});
|
771
|
-
};
|
772
|
-
|
773
|
-
BookReader.prototype.bindGestures = function(jElement) {
|
774
|
-
// TODO support gesture change is only iOS. Support android.
|
775
|
-
// HACK(2017-01-20) - Momentum scrolling is causing the scroll position
|
776
|
-
// to jump after zooming in on mobile device. I am able to reproduce
|
777
|
-
// when you move the book with one finger and then add another
|
778
|
-
// finger to pinch. Gestures are aware of scroll state.
|
779
|
-
|
780
|
-
var self = this;
|
781
|
-
var numTouches = 1;
|
782
|
-
|
783
|
-
jElement.unbind('touchmove').bind('touchmove', function(e) {
|
784
|
-
if (e.originalEvent.cancelable) numTouches = e.originalEvent.touches.length;
|
785
|
-
e.stopPropagation();
|
786
|
-
});
|
787
|
-
|
788
|
-
jElement.unbind('gesturechange').bind('gesturechange', function(e) {
|
789
|
-
e.preventDefault();
|
790
|
-
// These are two very important fixes to adjust for the scroll position
|
791
|
-
// issues described below
|
792
|
-
if (!(numTouches !== 2 || (new Date().getTime()) - self.lastScroll < 500)) {
|
793
|
-
if (e.originalEvent.scale > 1.5) {
|
794
|
-
self.zoom(1);
|
795
|
-
} else if (e.originalEvent.scale < 0.6) {
|
796
|
-
self.zoom(-1);
|
797
|
-
}
|
798
|
-
}
|
799
|
-
});
|
800
|
-
};
|
801
|
-
|
802
|
-
/** @deprecated Not used outside ModeThumb */
|
803
|
-
BookReader.prototype.drawLeafsThumbnail = ModeThumb.prototype.drawLeafs;
|
804
|
-
exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'drawLeafs', 'drawLeafsThumbnail');
|
805
|
-
/** @deprecated Not used outside ModeThumb */
|
806
|
-
BookReader.prototype.lazyLoadThumbnails = ModeThumb.prototype.lazyLoadThumbnails;
|
807
|
-
exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'lazyLoadThumbnails', 'lazyLoadThumbnails');
|
808
|
-
BookReader.prototype.lazyLoadImage = ModeThumb.prototype.lazyLoadImage;
|
809
|
-
exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'lazyLoadImage', 'lazyLoadImage');
|
810
|
-
/** @deprecated Internal use only */
|
811
|
-
BookReader.prototype.zoomThumb = ModeThumb.prototype.zoom;
|
812
|
-
exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'zoom', 'zoomThumb');
|
813
|
-
/** @deprecated Not used outside ModeThumb */
|
814
|
-
BookReader.prototype.getThumbnailWidth = ModeThumb.prototype.getThumbnailWidth;
|
815
|
-
exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'getThumbnailWidth', 'getThumbnailWidth');
|
816
|
-
/** @deprecated Not used outside ModeThumb */
|
817
|
-
BookReader.prototype.prepareThumbnailView = ModeThumb.prototype.prepare;
|
818
|
-
exposeOverrideableMethod(ModeThumb, '_modes.modeThumb', 'prepare', 'prepareThumbnailView');
|
819
|
-
|
820
|
-
/**
|
821
|
-
* A throttled version of drawLeafs
|
822
|
-
*/
|
823
|
-
BookReader.prototype.drawLeafsThrottled = utils.throttle(
|
824
|
-
BookReader.prototype.drawLeafs,
|
825
|
-
250 // 250 ms gives quick feedback, but doesn't eat cpu
|
826
|
-
);
|
827
|
-
|
828
|
-
/**
|
829
|
-
* @param {number} direction Pass 1 to zoom in, anything else to zoom out
|
830
|
-
*/
|
831
|
-
BookReader.prototype.zoom = function(direction) {
|
832
|
-
if (direction == 1) {
|
833
|
-
this.activeMode.zoom('in');
|
834
|
-
} else {
|
835
|
-
this.activeMode.zoom('out');
|
836
|
-
}
|
837
|
-
this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
|
838
|
-
return;
|
839
|
-
};
|
840
|
-
|
841
|
-
/**
|
842
|
-
* Resizes the inner container to fit within the visible space to prevent
|
843
|
-
* the top toolbar and bottom navbar from clipping the visible book
|
844
|
-
*
|
845
|
-
* @param { boolean } animate - optional
|
846
|
-
* When used, BookReader will fill the main container with the book's content.
|
847
|
-
* This is primarily for 1up view - a follow up animation to the nav animation
|
848
|
-
* So resize isn't perceived sharp/jerky
|
849
|
-
*/
|
850
|
-
BookReader.prototype.resizeBRcontainer = function(animate) {
|
851
|
-
if (animate) {
|
852
|
-
this.refs.$brContainer.animate({
|
853
|
-
top: this.getToolBarHeight(),
|
854
|
-
bottom: this.getFooterHeight()
|
855
|
-
}, this.constResizeAnimationDuration, 'linear');
|
856
|
-
} else {
|
857
|
-
this.refs.$brContainer.css({
|
858
|
-
top: this.getToolBarHeight(),
|
859
|
-
bottom: this.getFooterHeight()
|
860
|
-
});
|
861
|
-
}
|
862
|
-
};
|
863
|
-
|
864
|
-
BookReader.prototype.centerPageView = function() {
|
865
|
-
var scrollWidth = this.refs.$brContainer.prop('scrollWidth');
|
866
|
-
var clientWidth = this.refs.$brContainer.prop('clientWidth');
|
867
|
-
if (scrollWidth > clientWidth) {
|
868
|
-
this.refs.$brContainer.prop('scrollLeft', (scrollWidth - clientWidth) / 2);
|
869
|
-
}
|
870
|
-
};
|
871
|
-
|
872
|
-
/**
|
873
|
-
* Quantizes the given reduction factor to closest power of two from set from 12.5% to 200%
|
874
|
-
* @param {number} reduce
|
875
|
-
* @param {ReductionFactor[]} reductionFactors
|
876
|
-
* @return {number}
|
877
|
-
*/
|
878
|
-
BookReader.prototype.quantizeReduce = function(reduce, reductionFactors) {
|
879
|
-
let quantized = reductionFactors[0].reduce;
|
880
|
-
let distance = Math.abs(reduce - quantized);
|
881
|
-
|
882
|
-
for (let i = 1; i < reductionFactors.length; i++) {
|
883
|
-
const newDistance = Math.abs(reduce - reductionFactors[i].reduce);
|
884
|
-
if (newDistance < distance) {
|
885
|
-
distance = newDistance;
|
886
|
-
quantized = reductionFactors[i].reduce;
|
887
|
-
}
|
888
|
-
}
|
889
|
-
return quantized;
|
890
|
-
};
|
891
|
-
|
892
|
-
/**
|
893
|
-
* @param {number} currentReduce
|
894
|
-
* @param {'in' | 'out' | 'auto' | 'height' | 'width'} direction
|
895
|
-
* @param {ReductionFactor[]} reductionFactors Must be sorted
|
896
|
-
* @returns {ReductionFactor}
|
897
|
-
*/
|
898
|
-
BookReader.prototype.nextReduce = function(currentReduce, direction, reductionFactors) {
|
899
|
-
// XXX add 'closest', to replace quantize function
|
900
|
-
|
901
|
-
if (direction === 'in') {
|
902
|
-
let newReduceIndex = 0;
|
903
|
-
for (let i = 1; i < reductionFactors.length; i++) {
|
904
|
-
if (reductionFactors[i].reduce < currentReduce) {
|
905
|
-
newReduceIndex = i;
|
906
|
-
}
|
907
|
-
}
|
908
|
-
return reductionFactors[newReduceIndex];
|
909
|
-
} else if (direction === 'out') {
|
910
|
-
const lastIndex = reductionFactors.length - 1;
|
911
|
-
let newReduceIndex = lastIndex;
|
912
|
-
|
913
|
-
for (let i = lastIndex; i >= 0; i--) {
|
914
|
-
if (reductionFactors[i].reduce > currentReduce) {
|
915
|
-
newReduceIndex = i;
|
916
|
-
}
|
917
|
-
}
|
918
|
-
return reductionFactors[newReduceIndex];
|
919
|
-
} else if (direction === 'auto') {
|
920
|
-
// If an 'auto' is specified, use that
|
921
|
-
const autoMatch = reductionFactors.find(rf => rf.autofit == 'auto');
|
922
|
-
if (autoMatch) return autoMatch;
|
923
|
-
|
924
|
-
// Otherwise, choose the least reduction from height/width
|
925
|
-
const candidates = reductionFactors.filter(({autofit}) => autofit == 'height' || autofit == 'width');
|
926
|
-
let choice = null;
|
927
|
-
for (let i = 0; i < candidates.length; i++) {
|
928
|
-
if (choice === null || choice.reduce < candidates[i].reduce) {
|
929
|
-
choice = candidates[i];
|
930
|
-
}
|
931
|
-
}
|
932
|
-
if (choice) return choice;
|
933
|
-
} else if (direction === 'height' || direction === 'width') {
|
934
|
-
// Asked for specific autofit mode
|
935
|
-
const match = reductionFactors.find(rf => rf.autofit == direction);
|
936
|
-
if (match) return match;
|
937
|
-
}
|
938
|
-
|
939
|
-
return reductionFactors[0];
|
940
|
-
};
|
941
|
-
|
942
|
-
/**
|
943
|
-
* @param {ReductionFactor} a
|
944
|
-
* @param {ReductionFactor} b
|
945
|
-
*/
|
946
|
-
BookReader.prototype._reduceSort = (a, b) => a.reduce - b.reduce;
|
947
|
-
|
948
|
-
/**
|
949
|
-
* Attempts to jump to page
|
950
|
-
* @param {string}
|
951
|
-
* @return {boolean} Returns true if page could be found, false otherwise.
|
952
|
-
*/
|
953
|
-
BookReader.prototype.jumpToPage = function(pageNum) {
|
954
|
-
var pageIndex = this._models.book.parsePageString(pageNum);
|
955
|
-
|
956
|
-
if ('undefined' != typeof(pageIndex)) {
|
957
|
-
this.jumpToIndex(pageIndex);
|
958
|
-
return true;
|
959
|
-
}
|
960
|
-
|
961
|
-
// Page not found
|
962
|
-
return false;
|
963
|
-
};
|
964
|
-
|
965
|
-
/**
|
966
|
-
* Check whether the specified index is currently displayed
|
967
|
-
* @param {PageIndex} index
|
968
|
-
*/
|
969
|
-
BookReader.prototype._isIndexDisplayed = function(index) {
|
970
|
-
// One up "caches" pages +- current, so exclude those in the test.
|
971
|
-
return this.constMode1up == this.mode ? this.displayedIndices.slice(1, -1).includes(index) :
|
972
|
-
this.displayedIndices ? this.displayedIndices.includes(index) :
|
973
|
-
this.currentIndex() == index;
|
974
|
-
};
|
975
|
-
|
976
|
-
/**
|
977
|
-
* Changes the current page
|
978
|
-
* @param {PageIndex} index
|
979
|
-
* @param {number} [pageX]
|
980
|
-
* @param {number} [pageY]
|
981
|
-
* @param {boolean} [noAnimate]
|
982
|
-
*/
|
983
|
-
BookReader.prototype.jumpToIndex = function(index, pageX, pageY, noAnimate) {
|
984
|
-
// Don't jump into specific unviewable page
|
985
|
-
const page = this._models.book.getPage(index);
|
986
|
-
if (!page.isViewable && page.unviewablesStart != page.index) {
|
987
|
-
// If already in unviewable range, jump to end of that range
|
988
|
-
const alreadyInPreview = this._isIndexDisplayed(page.unviewablesStart);
|
989
|
-
const newIndex = alreadyInPreview ? page.findNext({ combineConsecutiveUnviewables: true }).index : page.unviewablesStart;
|
990
|
-
return this.jumpToIndex(newIndex, pageX, pageY, noAnimate);
|
991
|
-
}
|
992
|
-
|
993
|
-
this.trigger(BookReader.eventNames.stop);
|
994
|
-
|
995
|
-
if (this.constMode2up == this.mode) {
|
996
|
-
this._modes.mode2Up.jumpToIndex(index);
|
997
|
-
} else if (this.constModeThumb == this.mode) {
|
998
|
-
this._modes.modeThumb.jumpToIndex(index);
|
999
|
-
} else { // 1up
|
1000
|
-
this._modes.mode1Up.jumpToIndex(index, pageX, pageY, noAnimate);
|
1001
|
-
}
|
1002
|
-
};
|
1003
|
-
|
1004
|
-
/**
|
1005
|
-
* Return mode or 1up if initial thumb
|
1006
|
-
* @param {number}
|
1007
|
-
* @see BookReader.prototype.drawLeafsThumbnail
|
1008
|
-
*/
|
1009
|
-
BookReader.prototype.getPrevReadMode = function(mode) {
|
1010
|
-
if (mode === BookReader.constMode1up || mode === BookReader.constMode2up) {
|
1011
|
-
return mode;
|
1012
|
-
} else if (this.prevReadMode === null) {
|
1013
|
-
// Initial thumb, return 1up
|
1014
|
-
return BookReader.constMode1up;
|
1015
|
-
}
|
1016
|
-
};
|
1017
|
-
|
1018
|
-
/**
|
1019
|
-
* Switches the mode (eg 1up 2up thumb)
|
1020
|
-
* @param {number}
|
1021
|
-
* @param {object} [options]
|
1022
|
-
* @param {boolean} [options.suppressFragmentChange = false]
|
1023
|
-
* @param {boolean} [options.onInit = false] - this
|
1024
|
-
*/
|
1025
|
-
BookReader.prototype.switchMode = function(
|
1026
|
-
mode,
|
1027
|
-
{
|
1028
|
-
suppressFragmentChange = false,
|
1029
|
-
init = false,
|
1030
|
-
pageFound = false
|
1031
|
-
} = {}
|
1032
|
-
) {
|
1033
|
-
// Skip checks before init() complete
|
1034
|
-
if (this.init.initComplete) {
|
1035
|
-
if (mode === this.mode) {
|
1036
|
-
return;
|
1037
|
-
}
|
1038
|
-
if (!this.canSwitchToMode(mode)) {
|
1039
|
-
return;
|
1040
|
-
}
|
1041
|
-
}
|
1042
|
-
|
1043
|
-
this.trigger(BookReader.eventNames.stop);
|
1044
|
-
|
1045
|
-
this.prevReadMode = this.getPrevReadMode(this.mode);
|
1046
|
-
|
1047
|
-
if (this.mode != mode) {
|
1048
|
-
this.activeMode.unprepare?.();
|
1049
|
-
}
|
1050
|
-
|
1051
|
-
this.mode = mode;
|
1052
|
-
|
1053
|
-
// reinstate scale if moving from thumbnail view
|
1054
|
-
if (this.pageScale !== this.reduce) {
|
1055
|
-
this.reduce = this.pageScale;
|
1056
|
-
}
|
1057
|
-
|
1058
|
-
// $$$ TODO preserve center of view when switching between mode
|
1059
|
-
// See https://bugs.edge.launchpad.net/gnubook/+bug/416682
|
1060
|
-
|
1061
|
-
// XXX maybe better to preserve zoom in each mode
|
1062
|
-
if (this.constMode1up == mode) {
|
1063
|
-
this.prepareOnePageView();
|
1064
|
-
} else if (this.constModeThumb == mode) {
|
1065
|
-
this.reduce = this.quantizeReduce(this.reduce, this.reductionFactors);
|
1066
|
-
this.prepareThumbnailView();
|
1067
|
-
} else {
|
1068
|
-
// $$$ why don't we save autofit?
|
1069
|
-
// this.twoPage.autofit = null; // Take zoom level from other mode
|
1070
|
-
// spread indices not set, so let's set them
|
1071
|
-
if (init || !pageFound) {
|
1072
|
-
this.setSpreadIndices();
|
1073
|
-
}
|
1074
|
-
|
1075
|
-
this.twoPageCalculateReductionFactors(); // this sets this.twoPage && this.reduce
|
1076
|
-
this.prepareTwoPageView();
|
1077
|
-
this.twoPageCenterView(0.5, 0.5); // $$$ TODO preserve center
|
1078
|
-
}
|
1079
|
-
|
1080
|
-
if (!(this.suppressFragmentChange || suppressFragmentChange)) {
|
1081
|
-
this.trigger(BookReader.eventNames.fragmentChange);
|
1082
|
-
}
|
1083
|
-
var eventName = mode + 'PageViewSelected';
|
1084
|
-
this.trigger(BookReader.eventNames[eventName]);
|
1085
|
-
|
1086
|
-
this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
|
1087
|
-
};
|
1088
|
-
|
1089
|
-
BookReader.prototype.updateBrClasses = function() {
|
1090
|
-
var modeToClass = {};
|
1091
|
-
modeToClass[this.constMode1up] = 'BRmode1up';
|
1092
|
-
modeToClass[this.constMode2up] = 'BRmode2Up';
|
1093
|
-
modeToClass[this.constModeThumb] = 'BRmodeThumb';
|
1094
|
-
|
1095
|
-
this.refs.$br
|
1096
|
-
.removeClass('BRmode1up BRmode2Up BRmodeThumb')
|
1097
|
-
.addClass(modeToClass[this.mode]);
|
1098
|
-
|
1099
|
-
if (this.isFullscreen()) {
|
1100
|
-
this.refs.$br.addClass('fullscreenActive');
|
1101
|
-
$(document.body).addClass('BRfullscreenActive');
|
1102
|
-
} else {
|
1103
|
-
this.refs.$br.removeClass('fullscreenActive');
|
1104
|
-
$(document.body).removeClass('BRfullscreenActive');
|
1105
|
-
}
|
1106
|
-
};
|
1107
|
-
|
1108
|
-
BookReader.prototype.isFullscreen = function() {
|
1109
|
-
return this.isFullscreenActive;
|
1110
|
-
};
|
1111
|
-
|
1112
|
-
/**
|
1113
|
-
* Toggles fullscreen
|
1114
|
-
* @param { boolean } bindKeyboardControls
|
1115
|
-
*/
|
1116
|
-
BookReader.prototype.toggleFullscreen = async function(bindKeyboardControls = true) {
|
1117
|
-
if (this.isFullscreen()) {
|
1118
|
-
await this.exitFullScreen();
|
1119
|
-
} else {
|
1120
|
-
await this.enterFullscreen(bindKeyboardControls);
|
1121
|
-
}
|
1122
|
-
};
|
1123
|
-
|
1124
|
-
/**
|
1125
|
-
* Enters fullscreen
|
1126
|
-
* including:
|
1127
|
-
* - animation
|
1128
|
-
* - binds keyboard controls
|
1129
|
-
* - fires custom event
|
1130
|
-
* @param { boolean } bindKeyboardControls
|
1131
|
-
*/
|
1132
|
-
BookReader.prototype.enterFullscreen = async function(bindKeyboardControls = true) {
|
1133
|
-
const currentIndex = this.currentIndex();
|
1134
|
-
this.refs.$brContainer.css('opacity', 0);
|
1135
|
-
|
1136
|
-
if (bindKeyboardControls) {
|
1137
|
-
this._fullscreenCloseHandler = (e) => {
|
1138
|
-
if (e.keyCode === 27) this.toggleFullscreen();
|
1139
|
-
};
|
1140
|
-
$(document).on("keyup", this._fullscreenCloseHandler);
|
1141
|
-
}
|
1142
|
-
|
1143
|
-
const windowWidth = $(window).width();
|
1144
|
-
if (windowWidth <= this.onePageMinBreakpoint) {
|
1145
|
-
this.switchMode(this.constMode1up);
|
1146
|
-
}
|
1147
|
-
|
1148
|
-
this.isFullscreenActive = true;
|
1149
|
-
this.animating = true;
|
1150
|
-
await new Promise(res => this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear', res));
|
1151
|
-
this.resize();
|
1152
|
-
if (this.activeMode instanceof Mode1Up) {
|
1153
|
-
this.activeMode.mode1UpLit.scale = this.activeMode.mode1UpLit.computeDefaultScale(this._models.book.getPage(currentIndex));
|
1154
|
-
// Need the new scale to be applied before calling jumpToIndex
|
1155
|
-
await this.activeMode.mode1UpLit.requestUpdate();
|
1156
|
-
}
|
1157
|
-
this.jumpToIndex(currentIndex);
|
1158
|
-
this.animating = false;
|
1159
|
-
|
1160
|
-
this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
|
1161
|
-
// Add "?view=theater"
|
1162
|
-
this.trigger(BookReader.eventNames.fragmentChange);
|
1163
|
-
this.trigger(BookReader.eventNames.fullscreenToggled);
|
1164
|
-
};
|
1165
|
-
|
1166
|
-
/**
|
1167
|
-
* Exits fullscreen
|
1168
|
-
* - toggles fullscreen
|
1169
|
-
* - binds keyboard controls
|
1170
|
-
* - fires custom event
|
1171
|
-
* @param { boolean } bindKeyboardControls
|
1172
|
-
*/
|
1173
|
-
BookReader.prototype.exitFullScreen = async function () {
|
1174
|
-
this.refs.$brContainer.css('opacity', 0);
|
1175
|
-
|
1176
|
-
$(document).off('keyup', this._fullscreenCloseHandler);
|
1177
|
-
|
1178
|
-
var windowWidth = $(window).width();
|
1179
|
-
|
1180
|
-
const canShow2up = this.options.controls.twoPage.visible;
|
1181
|
-
if (canShow2up && (windowWidth <= this.onePageMinBreakpoint)) {
|
1182
|
-
this.switchMode(this.constMode2up);
|
1183
|
-
}
|
1184
|
-
|
1185
|
-
this.isFullscreenActive = false;
|
1186
|
-
this.updateBrClasses();
|
1187
|
-
this.animating = true;
|
1188
|
-
await new Promise((res => this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear', res)));
|
1189
|
-
this.resize();
|
1190
|
-
|
1191
|
-
if (this.activeMode instanceof Mode1Up) {
|
1192
|
-
this.activeMode.mode1UpLit.scale = this.activeMode.mode1UpLit.computeDefaultScale(this._models.book.getPage(this.currentIndex()));
|
1193
|
-
await this.activeMode.mode1UpLit.requestUpdate();
|
1194
|
-
}
|
1195
|
-
|
1196
|
-
this.animating = false;
|
1197
|
-
|
1198
|
-
this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
|
1199
|
-
// Remove "?view=theater"
|
1200
|
-
this.trigger(BookReader.eventNames.fragmentChange);
|
1201
|
-
this.trigger(BookReader.eventNames.fullscreenToggled);
|
1202
|
-
};
|
1203
|
-
|
1204
|
-
/**
|
1205
|
-
* Returns the currently active index
|
1206
|
-
* @return {number}
|
1207
|
-
* @throws
|
1208
|
-
*/
|
1209
|
-
BookReader.prototype.currentIndex = function() {
|
1210
|
-
// $$$ we should be cleaner with our idea of which index is active in 1up/2up
|
1211
|
-
if (this.mode == this.constMode1up || this.mode == this.constModeThumb) {
|
1212
|
-
return this.firstIndex; // $$$ TODO page in center of view would be better
|
1213
|
-
} else if (this.mode == this.constMode2up) {
|
1214
|
-
// Only allow indices that are actually present in book
|
1215
|
-
return utils.clamp(this.firstIndex, 0, this._models.book.getNumLeafs() - 1);
|
1216
|
-
} else {
|
1217
|
-
throw 'currentIndex called for unimplemented mode ' + this.mode;
|
1218
|
-
}
|
1219
|
-
};
|
1220
|
-
|
1221
|
-
/**
|
1222
|
-
* Setter for this.firstIndex
|
1223
|
-
* Also triggers an event and updates the navbar slider position
|
1224
|
-
* @param {number} index
|
1225
|
-
* @param {object} [options]
|
1226
|
-
* @param {boolean} [options.suppressFragmentChange = false]
|
1227
|
-
*/
|
1228
|
-
BookReader.prototype.updateFirstIndex = function(
|
1229
|
-
index,
|
1230
|
-
{ suppressFragmentChange = false } = {}
|
1231
|
-
) {
|
1232
|
-
// If there's no change, do nothing
|
1233
|
-
if (this.firstIndex === index) return;
|
1234
|
-
|
1235
|
-
this.firstIndex = index;
|
1236
|
-
if (!(this.suppressFragmentChange || suppressFragmentChange)) {
|
1237
|
-
this.trigger(BookReader.eventNames.fragmentChange);
|
1238
|
-
}
|
1239
|
-
// If there's an initial search we stop suppressing global URL changes
|
1240
|
-
// when local suppression ends
|
1241
|
-
// This seems to correctly handle multiple calls during mode/1up
|
1242
|
-
if (this.options.initialSearchTerm && !suppressFragmentChange) {
|
1243
|
-
this.suppressFragmentChange = false;
|
1244
|
-
}
|
1245
|
-
this.trigger('pageChanged');
|
1246
|
-
this.updateNavIndexThrottled(index);
|
1247
|
-
};
|
1248
|
-
|
1249
|
-
/**
|
1250
|
-
* Flip the right page over onto the left
|
1251
|
-
*/
|
1252
|
-
BookReader.prototype.right = function() {
|
1253
|
-
if ('rl' != this.pageProgression) {
|
1254
|
-
this.next();
|
1255
|
-
} else {
|
1256
|
-
this.prev();
|
1257
|
-
}
|
1258
|
-
};
|
1259
|
-
|
1260
|
-
/**
|
1261
|
-
* Flip to the rightmost page
|
1262
|
-
*/
|
1263
|
-
BookReader.prototype.rightmost = function() {
|
1264
|
-
if ('rl' != this.pageProgression) {
|
1265
|
-
this.last();
|
1266
|
-
} else {
|
1267
|
-
this.first();
|
1268
|
-
}
|
1269
|
-
};
|
1270
|
-
|
1271
|
-
/**
|
1272
|
-
* Flip the left page over onto the right
|
1273
|
-
*/
|
1274
|
-
BookReader.prototype.left = function() {
|
1275
|
-
if ('rl' != this.pageProgression) {
|
1276
|
-
this.prev();
|
1277
|
-
} else {
|
1278
|
-
this.next();
|
1279
|
-
}
|
1280
|
-
};
|
1281
|
-
|
1282
|
-
/**
|
1283
|
-
* Flip to the leftmost page
|
1284
|
-
*/
|
1285
|
-
BookReader.prototype.leftmost = function() {
|
1286
|
-
if ('rl' != this.pageProgression) {
|
1287
|
-
this.first();
|
1288
|
-
} else {
|
1289
|
-
this.last();
|
1290
|
-
}
|
1291
|
-
};
|
1292
|
-
|
1293
|
-
BookReader.prototype.next = function() {
|
1294
|
-
if (this.constMode2up == this.mode) {
|
1295
|
-
this.trigger(BookReader.eventNames.stop);
|
1296
|
-
this.flipFwdToIndex(null);
|
1297
|
-
} else {
|
1298
|
-
if (this.firstIndex < this.lastDisplayableIndex()) {
|
1299
|
-
this.jumpToIndex(this.firstIndex + 1);
|
1300
|
-
}
|
1301
|
-
}
|
1302
|
-
};
|
1303
|
-
|
1304
|
-
BookReader.prototype.prev = function() {
|
1305
|
-
const isOnFrontPage = this.firstIndex < 1;
|
1306
|
-
if (isOnFrontPage) return;
|
1307
|
-
|
1308
|
-
if (this.constMode2up == this.mode) {
|
1309
|
-
this.trigger(BookReader.eventNames.stop);
|
1310
|
-
this.flipBackToIndex(null);
|
1311
|
-
} else {
|
1312
|
-
if (this.firstIndex >= 1) {
|
1313
|
-
this.jumpToIndex(this.firstIndex - 1);
|
1314
|
-
}
|
1315
|
-
}
|
1316
|
-
};
|
1317
|
-
|
1318
|
-
BookReader.prototype.first = function() {
|
1319
|
-
this.jumpToIndex(this.firstDisplayableIndex());
|
1320
|
-
};
|
1321
|
-
|
1322
|
-
BookReader.prototype.last = function() {
|
1323
|
-
this.jumpToIndex(this.lastDisplayableIndex());
|
1324
|
-
};
|
1325
|
-
|
1326
|
-
/**
|
1327
|
-
* Scrolls down one screen view
|
1328
|
-
*/
|
1329
|
-
BookReader.prototype.scrollDown = function() {
|
1330
|
-
if ($.inArray(this.mode, [this.constMode1up, this.constModeThumb]) >= 0) {
|
1331
|
-
if ( this.mode == this.constMode1up && (this.reduce >= this.onePageGetAutofitHeight()) ) {
|
1332
|
-
// Whole pages are visible, scroll whole page only
|
1333
|
-
return this.next();
|
1334
|
-
}
|
1335
|
-
|
1336
|
-
this.refs.$brContainer.stop(true).animate(
|
1337
|
-
{ scrollTop: '+=' + this._scrollAmount() + 'px'},
|
1338
|
-
400, 'easeInOutExpo'
|
1339
|
-
);
|
1340
|
-
return true;
|
1341
|
-
} else {
|
1342
|
-
return false;
|
1343
|
-
}
|
1344
|
-
};
|
1345
|
-
|
1346
|
-
/**
|
1347
|
-
* Scrolls up one screen view
|
1348
|
-
*/
|
1349
|
-
BookReader.prototype.scrollUp = function() {
|
1350
|
-
if ($.inArray(this.mode, [this.constMode1up, this.constModeThumb]) >= 0) {
|
1351
|
-
if ( this.mode == this.constMode1up && (this.reduce >= this.onePageGetAutofitHeight()) ) {
|
1352
|
-
// Whole pages are visible, scroll whole page only
|
1353
|
-
return this.prev();
|
1354
|
-
}
|
1355
|
-
|
1356
|
-
this.refs.$brContainer.stop(true).animate(
|
1357
|
-
{ scrollTop: '-=' + this._scrollAmount() + 'px'},
|
1358
|
-
400, 'easeInOutExpo'
|
1359
|
-
);
|
1360
|
-
return true;
|
1361
|
-
} else {
|
1362
|
-
return false;
|
1363
|
-
}
|
1364
|
-
};
|
1365
|
-
|
1366
|
-
/**
|
1367
|
-
* The amount to scroll vertically in integer pixels
|
1368
|
-
*/
|
1369
|
-
BookReader.prototype._scrollAmount = function() {
|
1370
|
-
if (this.constMode1up == this.mode) {
|
1371
|
-
// Overlap by % of page size
|
1372
|
-
return parseInt(this.refs.$brContainer.prop('clientHeight') - this._models.book.getPageHeight(this.currentIndex()) / this.reduce * 0.03);
|
1373
|
-
}
|
1374
|
-
|
1375
|
-
return parseInt(0.9 * this.refs.$brContainer.prop('clientHeight'));
|
1376
|
-
};
|
1377
|
-
|
1378
|
-
/**
|
1379
|
-
* @deprecated No longer used; will be remove in v5
|
1380
|
-
*/
|
1381
|
-
BookReader.prototype.prefetchImg = async function(index, fetchNow = false) {
|
1382
|
-
console.warn('Call to deprecated function: BookReader.prefetchImg. No-op.');
|
1383
|
-
};
|
1384
|
-
|
1385
|
-
/**
|
1386
|
-
* @deprecated No longer used; will be remove in v5
|
1387
|
-
*/
|
1388
|
-
BookReader.prototype.pruneUnusedImgs = function() {
|
1389
|
-
console.warn('Call to deprecated function: BookReader.pruneUnused. No-op.');
|
1390
|
-
};
|
1391
|
-
|
1392
|
-
/************************/
|
1393
|
-
/** Mode1Up extensions **/
|
1394
|
-
/************************/
|
1395
|
-
/** @deprecated not used outside BookReader */
|
1396
|
-
BookReader.prototype.prepareOnePageView = Mode1Up.prototype.prepare;
|
1397
|
-
exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'prepare', 'prepareOnePageView');
|
1398
|
-
/** @deprecated not used outside BookReader */
|
1399
|
-
BookReader.prototype.zoom1up = Mode1Up.prototype.zoom;
|
1400
|
-
exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'zoom', 'zoom1up');
|
1401
|
-
/** @deprecated not used outside Mode1Up, BookReader */
|
1402
|
-
BookReader.prototype.resizePageView1up = Mode1Up.prototype.resizePageView;
|
1403
|
-
exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'resizePageView', 'resizePageView1up');
|
1404
|
-
/** @deprecated not used outside Mode1Up */
|
1405
|
-
BookReader.prototype.onePageCalculateViewDimensions = Mode1Up.prototype.calculateViewDimensions;
|
1406
|
-
exposeOverrideableMethod(Mode1Up, '_modes.mode1Up', 'calculateViewDimensions', 'onePageCalculateViewDimensions');
|
1407
|
-
|
1408
|
-
/************************/
|
1409
|
-
/** Mode2Up extensions **/
|
1410
|
-
/************************/
|
1411
|
-
/** @deprecated not used outside Mode2Up */
|
1412
|
-
BookReader.prototype.zoom2up = Mode2Up.prototype.zoom;
|
1413
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'zoom', 'zoom2up');
|
1414
|
-
BookReader.prototype.twoPageGetAutofitReduce = Mode2Up.prototype.getAutofitReduce;
|
1415
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'getAutofitReduce', 'twoPageGetAutofitReduce');
|
1416
|
-
BookReader.prototype.flipBackToIndex = Mode2Up.prototype.flipBackToIndex;
|
1417
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipBackToIndex', 'flipBackToIndex');
|
1418
|
-
BookReader.prototype.flipFwdToIndex = Mode2Up.prototype.flipFwdToIndex;
|
1419
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipFwdToIndex', 'flipFwdToIndex');
|
1420
|
-
BookReader.prototype.setHilightCss2UP = Mode2Up.prototype.setHilightCss;
|
1421
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setHilightCss', 'setHilightCss2UP');
|
1422
|
-
/** @deprecated not used outside Mode2Up */
|
1423
|
-
BookReader.prototype.drawLeafsTwoPage = Mode2Up.prototype.drawLeafs;
|
1424
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'drawLeafs', 'drawLeafsTwoPage');
|
1425
|
-
/** @deprecated not used outside BookReader */
|
1426
|
-
BookReader.prototype.prepareTwoPageView = Mode2Up.prototype.prepareTwoPageView;
|
1427
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'prepareTwoPageView', 'prepareTwoPageView');
|
1428
|
-
/** @deprecated not used outside Mode2Up */
|
1429
|
-
BookReader.prototype.prepareTwoPagePopUp = Mode2Up.prototype.preparePopUp;
|
1430
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'preparePopUp', 'prepareTwoPagePopUp');
|
1431
|
-
/** @deprecated not used outside BookReader, Mode2Up */
|
1432
|
-
BookReader.prototype.calculateSpreadSize = Mode2Up.prototype.calculateSpreadSize;
|
1433
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'calculateSpreadSize', 'calculateSpreadSize');
|
1434
|
-
/** @deprecated not used outside BookReader, Mode2Up */
|
1435
|
-
BookReader.prototype.getIdealSpreadSize = Mode2Up.prototype.getIdealSpreadSize;
|
1436
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'getIdealSpreadSize', 'getIdealSpreadSize');
|
1437
|
-
/** @deprecated not used outside BookReader, Mode2Up */
|
1438
|
-
BookReader.prototype.getSpreadSizeFromReduce = Mode2Up.prototype.getSpreadSizeFromReduce;
|
1439
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'getSpreadSizeFromReduce', 'getSpreadSizeFromReduce');
|
1440
|
-
/** @deprecated unused */
|
1441
|
-
BookReader.prototype.twoPageIsZoomedIn = Mode2Up.prototype.isZoomedIn;
|
1442
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'isZoomedIn', 'twoPageIsZoomedIn');
|
1443
|
-
/** @deprecated not used outside BookReader */
|
1444
|
-
BookReader.prototype.twoPageCalculateReductionFactors = Mode2Up.prototype.calculateReductionFactors;
|
1445
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'calculateReductionFactors', 'twoPageCalculateReductionFactors');
|
1446
|
-
/** @deprecated unused */
|
1447
|
-
BookReader.prototype.twoPageSetCursor = Mode2Up.prototype.setCursor;
|
1448
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setCursor', 'twoPageSetCursor');
|
1449
|
-
/** @deprecated unused outside BookReader, Mode2Up */
|
1450
|
-
BookReader.prototype.flipLeftToRight = Mode2Up.prototype.flipLeftToRight;
|
1451
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipLeftToRight', 'flipLeftToRight');
|
1452
|
-
/** @deprecated unused outside BookReader, Mode2Up */
|
1453
|
-
BookReader.prototype.flipRightToLeft = Mode2Up.prototype.flipRightToLeft;
|
1454
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipRightToLeft', 'flipRightToLeft');
|
1455
|
-
/** @deprecated unused outside BookReader, Mode2Up */
|
1456
|
-
BookReader.prototype.prepareFlipLeftToRight = Mode2Up.prototype.prepareFlipLeftToRight;
|
1457
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'prepareFlipLeftToRight', 'prepareFlipLeftToRight');
|
1458
|
-
/** @deprecated unused outside BookReader, Mode2Up */
|
1459
|
-
BookReader.prototype.prepareFlipRightToLeft = Mode2Up.prototype.prepareFlipRightToLeft;
|
1460
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'prepareFlipRightToLeft', 'prepareFlipRightToLeft');
|
1461
|
-
/** @deprecated unused outside Mode2Up */
|
1462
|
-
BookReader.prototype.getPageWidth2UP = Mode2Up.prototype.getPageWidth;
|
1463
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'getPageWidth', 'getPageWidth2UP');
|
1464
|
-
/** @deprecated unused outside Mode2Up */
|
1465
|
-
BookReader.prototype.twoPageGutter = Mode2Up.prototype.gutter;
|
1466
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'gutter', 'twoPageGutter');
|
1467
|
-
/** @deprecated unused outside Mode2Up */
|
1468
|
-
BookReader.prototype.twoPageTop = Mode2Up.prototype.top;
|
1469
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'top', 'twoPageTop');
|
1470
|
-
/** @deprecated unused outside Mode2Up */
|
1471
|
-
BookReader.prototype.twoPageCoverWidth = Mode2Up.prototype.coverWidth;
|
1472
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'coverWidth', 'twoPageCoverWidth');
|
1473
|
-
/** @deprecated unused outside Mode2Up */
|
1474
|
-
BookReader.prototype.twoPageGetViewCenter = Mode2Up.prototype.getViewCenter;
|
1475
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'getViewCenter', 'twoPageGetViewCenter');
|
1476
|
-
/** @deprecated unused outside BookReader, Mode2Up */
|
1477
|
-
BookReader.prototype.twoPageCenterView = Mode2Up.prototype.centerView;
|
1478
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'centerView', 'twoPageCenterView');
|
1479
|
-
/** @deprecated unused outside Mode2Up */
|
1480
|
-
BookReader.prototype.twoPageFlipAreaHeight = Mode2Up.prototype.flipAreaHeight;
|
1481
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipAreaHeight', 'twoPageFlipAreaHeight');
|
1482
|
-
/** @deprecated unused outside Mode2Up */
|
1483
|
-
BookReader.prototype.twoPageFlipAreaWidth = Mode2Up.prototype.flipAreaWidth;
|
1484
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipAreaWidth', 'twoPageFlipAreaWidth');
|
1485
|
-
/** @deprecated unused outside BookReader, Mode2Up */
|
1486
|
-
BookReader.prototype.twoPageFlipAreaTop = Mode2Up.prototype.flipAreaTop;
|
1487
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'flipAreaTop', 'twoPageFlipAreaTop');
|
1488
|
-
/** @deprecated unused outside Mode2Up */
|
1489
|
-
BookReader.prototype.twoPageLeftFlipAreaLeft = Mode2Up.prototype.leftFlipAreaLeft;
|
1490
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'leftFlipAreaLeft', 'twoPageLeftFlipAreaLeft');
|
1491
|
-
/** @deprecated unused outside Mode2Up */
|
1492
|
-
BookReader.prototype.twoPageRightFlipAreaLeft = Mode2Up.prototype.rightFlipAreaLeft;
|
1493
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'rightFlipAreaLeft', 'twoPageRightFlipAreaLeft');
|
1494
|
-
/** @deprecated unused outside BookReader, Mode2Up */
|
1495
|
-
BookReader.prototype.gutterOffsetForIndex = Mode2Up.prototype.gutterOffsetForIndex;
|
1496
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'gutterOffsetForIndex', 'gutterOffsetForIndex');
|
1497
|
-
/** @deprecated unused outside BookReader, Mode2Up */
|
1498
|
-
BookReader.prototype.leafEdgeWidth = Mode2Up.prototype.leafEdgeWidth;
|
1499
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'leafEdgeWidth', 'leafEdgeWidth');
|
1500
|
-
/** @deprecated unused outside BookReader, Mode2Up */
|
1501
|
-
BookReader.prototype.jumpIndexForLeftEdgePageX = Mode2Up.prototype.jumpIndexForLeftEdgePageX;
|
1502
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'jumpIndexForLeftEdgePageX', 'jumpIndexForLeftEdgePageX');
|
1503
|
-
/** @deprecated unused outside BookReader, Mode2Up */
|
1504
|
-
BookReader.prototype.jumpIndexForRightEdgePageX = Mode2Up.prototype.jumpIndexForRightEdgePageX;
|
1505
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'jumpIndexForRightEdgePageX', 'jumpIndexForRightEdgePageX');
|
1506
|
-
/** @deprecated unused outside Mode2Up */
|
1507
|
-
BookReader.prototype.prefetch = Mode2Up.prototype.prefetch;
|
1508
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'prefetch', 'prefetch');
|
1509
|
-
/** @deprecated unused outside Mode2Up */
|
1510
|
-
BookReader.prototype.setSpreadIndices = Mode2Up.prototype.setSpreadIndices;
|
1511
|
-
exposeOverrideableMethod(Mode2Up, '_modes.mode2Up', 'setSpreadIndices', 'setSpreadIndices');
|
1512
|
-
/**
|
1513
|
-
* Immediately stop flip animations. Callbacks are triggered.
|
1514
|
-
*/
|
1515
|
-
BookReader.prototype.stopFlipAnimations = function() {
|
1516
|
-
this.trigger(BookReader.eventNames.stop);
|
1517
|
-
|
1518
|
-
// Stop animation, clear queue, trigger callbacks
|
1519
|
-
if (this.leafEdgeTmp) {
|
1520
|
-
$(this.leafEdgeTmp).stop(false, true);
|
1521
|
-
}
|
1522
|
-
jQuery.each(this._modes.mode2Up.pageContainers, function() {
|
1523
|
-
$(this.$container).stop(false, true);
|
1524
|
-
});
|
1525
|
-
|
1526
|
-
// And again since animations also queued in callbacks
|
1527
|
-
if (this.leafEdgeTmp) {
|
1528
|
-
$(this.leafEdgeTmp).stop(false, true);
|
1529
|
-
}
|
1530
|
-
jQuery.each(this._modes.mode2Up.pageContainers, function() {
|
1531
|
-
$(this.$container).stop(false, true);
|
1532
|
-
});
|
1533
|
-
};
|
1534
|
-
|
1535
|
-
/**
|
1536
|
-
* @template TClass extends { br: BookReader }
|
1537
|
-
* Helper method to expose a method onto BookReader from a composed class.
|
1538
|
-
* Only composed classes in BookReader._overridable can be exposed in this
|
1539
|
-
* way.
|
1540
|
-
* @param {new () => TClass} Class
|
1541
|
-
* @param {keyof BookReader['_overrideable']} classKey
|
1542
|
-
* @param {keyof TClass} method
|
1543
|
-
* @param {string} [brMethod]
|
1544
|
-
*/
|
1545
|
-
function exposeOverrideableMethod(Class, classKey, method, brMethod = method) {
|
1546
|
-
/** @type {function(TClass): BookReader} */
|
1547
|
-
const classToBr = cls => cls.br;
|
1548
|
-
/** @type {function(BookReader): TClass} */
|
1549
|
-
const brToClass = br => br._overrideable[classKey];
|
1550
|
-
exposeOverrideable(Class, method, classToBr, BookReader, brMethod, brToClass);
|
1551
|
-
}
|
1552
|
-
|
1553
|
-
|
1554
|
-
/***********************/
|
1555
|
-
/** Navbar extensions **/
|
1556
|
-
/***********************/
|
1557
|
-
BookReader.prototype.initNavbar = Navbar.prototype.init;
|
1558
|
-
exposeOverrideableMethod(Navbar, '_components.navbar', 'init', 'initNavbar');
|
1559
|
-
BookReader.prototype.switchNavbarControls = Navbar.prototype.switchNavbarControls;
|
1560
|
-
exposeOverrideableMethod(Navbar, '_components.navbar', 'switchNavbarControls');
|
1561
|
-
BookReader.prototype.updateViewModeButton = Navbar.prototype.updateViewModeButton;
|
1562
|
-
exposeOverrideableMethod(Navbar, '_components.navbar', 'updateViewModeButton');
|
1563
|
-
BookReader.prototype.getNavPageNumString = Navbar.prototype.getNavPageNumString;
|
1564
|
-
exposeOverrideableMethod(Navbar, '_components.navbar', 'getNavPageNumString');
|
1565
|
-
/** @deprecated unused */
|
1566
|
-
BookReader.prototype.getNavPageNumHtml = getNavPageNumHtml;
|
1567
|
-
/** @deprecated unused outside this file */
|
1568
|
-
BookReader.prototype.updateNavPageNum = Navbar.prototype.updateNavPageNum;
|
1569
|
-
exposeOverrideableMethod(Navbar, '_components.navbar', 'updateNavPageNum');
|
1570
|
-
/** @deprecated unused outside this file */
|
1571
|
-
BookReader.prototype.updateNavIndex = Navbar.prototype.updateNavIndex;
|
1572
|
-
exposeOverrideableMethod(Navbar, '_components.navbar', 'updateNavIndex');
|
1573
|
-
/** @deprecated unused outside this file */
|
1574
|
-
BookReader.prototype.updateNavIndexThrottled = utils.throttle(BookReader.prototype.updateNavIndex, 250, false);
|
1575
|
-
/** @deprecated unused */
|
1576
|
-
BookReader.prototype.updateNavIndexDebounced = utils.debounce(BookReader.prototype.updateNavIndex, 500, false);
|
1577
|
-
|
1578
|
-
|
1579
|
-
/************************/
|
1580
|
-
/** Toolbar extensions **/
|
1581
|
-
/************************/
|
1582
|
-
BookReader.prototype.buildToolbarElement = Toolbar.prototype.buildToolbarElement;
|
1583
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'buildToolbarElement');
|
1584
|
-
BookReader.prototype.initToolbar = Toolbar.prototype.initToolbar;
|
1585
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'initToolbar');
|
1586
|
-
BookReader.prototype.buildShareDiv = Toolbar.prototype.buildShareDiv;
|
1587
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'buildShareDiv');
|
1588
|
-
BookReader.prototype.buildInfoDiv = Toolbar.prototype.buildInfoDiv;
|
1589
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'buildInfoDiv');
|
1590
|
-
BookReader.prototype.getToolBarHeight = Toolbar.prototype.getToolBarHeight;
|
1591
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'getToolBarHeight');
|
1592
|
-
/** @deprecated zoom no longer in toolbar */
|
1593
|
-
BookReader.prototype.updateToolbarZoom = Toolbar.prototype.updateToolbarZoom;
|
1594
|
-
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'updateToolbarZoom');
|
1595
|
-
/** @deprecated unused */
|
1596
|
-
BookReader.prototype.blankInfoDiv = blankInfoDiv;
|
1597
|
-
/** @deprecated unused */
|
1598
|
-
BookReader.prototype.blankShareDiv = blankShareDiv;
|
1599
|
-
/** @deprecated unused */
|
1600
|
-
BookReader.prototype.createPopup = createPopup;
|
1601
|
-
|
1602
|
-
/**
|
1603
|
-
* Bind navigation handlers
|
1604
|
-
*/
|
1605
|
-
BookReader.prototype.bindNavigationHandlers = function() {
|
1606
|
-
const self = this;
|
1607
|
-
|
1608
|
-
// Note the mobile plugin attaches itself to body, so we need to select outside
|
1609
|
-
const jIcons = this.$('.BRicon').add('.BRmobileMenu .BRicon');
|
1610
|
-
// Map of jIcon class -> click handler
|
1611
|
-
const navigationControls = {
|
1612
|
-
book_left: () => {
|
1613
|
-
this.trigger(BookReader.eventNames.stop);
|
1614
|
-
this.left();
|
1615
|
-
},
|
1616
|
-
book_right: () => {
|
1617
|
-
this.trigger(BookReader.eventNames.stop);
|
1618
|
-
this.right();
|
1619
|
-
},
|
1620
|
-
book_up: () => {
|
1621
|
-
if ($.inArray(this.mode, [this.constMode1up, this.constModeThumb]) >= 0) {
|
1622
|
-
this.scrollUp();
|
1623
|
-
} else {
|
1624
|
-
this.prev();
|
1625
|
-
}
|
1626
|
-
},
|
1627
|
-
book_down: () => {
|
1628
|
-
if ($.inArray(this.mode, [this.constMode1up, this.constModeThumb]) >= 0) {
|
1629
|
-
this.scrollDown();
|
1630
|
-
} else {
|
1631
|
-
this.next();
|
1632
|
-
}
|
1633
|
-
},
|
1634
|
-
book_top: this.first.bind(this),
|
1635
|
-
book_bottom: this.last.bind(this),
|
1636
|
-
book_leftmost: this.leftmost.bind(this),
|
1637
|
-
book_rightmost: this.rightmost.bind(this),
|
1638
|
-
onepg: () => {
|
1639
|
-
this.switchMode(self.constMode1up);
|
1640
|
-
},
|
1641
|
-
thumb: () => {
|
1642
|
-
this.switchMode(self.constModeThumb);
|
1643
|
-
},
|
1644
|
-
twopg: () => {
|
1645
|
-
this.switchMode(self.constMode2up);
|
1646
|
-
},
|
1647
|
-
zoom_in: () => {
|
1648
|
-
this.trigger(BookReader.eventNames.stop);
|
1649
|
-
this.zoom(1);
|
1650
|
-
this.trigger(BookReader.eventNames.zoomIn);
|
1651
|
-
},
|
1652
|
-
zoom_out: () => {
|
1653
|
-
this.trigger(BookReader.eventNames.stop);
|
1654
|
-
this.zoom(-1);
|
1655
|
-
this.trigger(BookReader.eventNames.zoomOut);
|
1656
|
-
},
|
1657
|
-
full: () => {
|
1658
|
-
if (this.ui == 'embed') {
|
1659
|
-
var url = this.$('.BRembedreturn a').attr('href');
|
1660
|
-
window.open(url);
|
1661
|
-
} else {
|
1662
|
-
this.toggleFullscreen();
|
1663
|
-
}
|
1664
|
-
},
|
1665
|
-
};
|
1666
|
-
|
1667
|
-
jIcons.filter('.fit').bind('fit', function() {
|
1668
|
-
// XXXmang implement autofit zoom
|
1669
|
-
});
|
1670
|
-
|
1671
|
-
for (const control in navigationControls) {
|
1672
|
-
jIcons.filter(`.${control}`).on('click.bindNavigationHandlers', () => {
|
1673
|
-
navigationControls[control]();
|
1674
|
-
return false;
|
1675
|
-
});
|
1676
|
-
}
|
1677
|
-
|
1678
|
-
var $brNavCntlBtmEl = this.$('.BRnavCntlBtm');
|
1679
|
-
var $brNavCntlTopEl = this.$('.BRnavCntlTop');
|
1680
|
-
|
1681
|
-
this.$('.BRnavCntl').click(
|
1682
|
-
function() {
|
1683
|
-
var promises = [];
|
1684
|
-
// TODO don't use magic constants
|
1685
|
-
// TODO move this to a function
|
1686
|
-
if ($brNavCntlBtmEl.hasClass('BRdn')) {
|
1687
|
-
if (self.refs.$BRtoolbar)
|
1688
|
-
promises.push(self.refs.$BRtoolbar.animate(
|
1689
|
-
{top: self.getToolBarHeight() * -1}
|
1690
|
-
).promise());
|
1691
|
-
promises.push(self.$('.BRfooter').animate({bottom: self.getFooterHeight() * -1}).promise());
|
1692
|
-
$brNavCntlBtmEl.addClass('BRup').removeClass('BRdn');
|
1693
|
-
$brNavCntlTopEl.addClass('BRdn').removeClass('BRup');
|
1694
|
-
self.$('.BRnavCntlBtm.BRnavCntl').animate({height:'45px'});
|
1695
|
-
self.$('.BRnavCntl').delay(1000).animate({opacity:.75}, 1000);
|
1696
|
-
} else {
|
1697
|
-
if (self.refs.$BRtoolbar)
|
1698
|
-
promises.push(self.refs.$BRtoolbar.animate({top:0}).promise());
|
1699
|
-
promises.push(self.$('.BRfooter').animate({bottom:0}).promise());
|
1700
|
-
$brNavCntlBtmEl.addClass('BRdn').removeClass('BRup');
|
1701
|
-
$brNavCntlTopEl.addClass('BRup').removeClass('BRdn');
|
1702
|
-
self.$('.BRnavCntlBtm.BRnavCntl').animate({height:'30px'});
|
1703
|
-
self.$('.BRvavCntl').animate({opacity:1});
|
1704
|
-
}
|
1705
|
-
$.when.apply($, promises).done(function() {
|
1706
|
-
// Only do full resize in auto mode and need to recalc. size
|
1707
|
-
if (self.mode == self.constMode2up && self.twoPage.autofit != null
|
1708
|
-
&& self.twoPage.autofit != 'none'
|
1709
|
-
) {
|
1710
|
-
self.resize();
|
1711
|
-
} else if (self.mode == self.constMode1up && self.onePage.autofit != null
|
1712
|
-
&& self.onePage.autofit != 'none') {
|
1713
|
-
self.resize();
|
1714
|
-
} else {
|
1715
|
-
// Don't do a full resize to avoid redrawing images
|
1716
|
-
self.resizeBRcontainer();
|
1717
|
-
}
|
1718
|
-
});
|
1719
|
-
}
|
1720
|
-
);
|
1721
|
-
$brNavCntlBtmEl
|
1722
|
-
.on("mouseover", function() {
|
1723
|
-
if ($(this).hasClass('BRup')) {
|
1724
|
-
self.$('.BRnavCntl').animate({opacity:1},250);
|
1725
|
-
}
|
1726
|
-
})
|
1727
|
-
.on("mouseleave", function() {
|
1728
|
-
if ($(this).hasClass('BRup')) {
|
1729
|
-
self.$('.BRnavCntl').animate({opacity:.75},250);
|
1730
|
-
}
|
1731
|
-
});
|
1732
|
-
$brNavCntlTopEl
|
1733
|
-
.on("mouseover", function() {
|
1734
|
-
if ($(this).hasClass('BRdn')) {
|
1735
|
-
self.$('.BRnavCntl').animate({opacity:1},250);
|
1736
|
-
}
|
1737
|
-
})
|
1738
|
-
.on("mouseleave", function() {
|
1739
|
-
if ($(this).hasClass('BRdn')) {
|
1740
|
-
self.$('.BRnavCntl').animate({opacity:.75},250);
|
1741
|
-
}
|
1742
|
-
});
|
1743
|
-
|
1744
|
-
this.initSwipeData();
|
1745
|
-
|
1746
|
-
$(document).off('mousemove.navigation', this.el);
|
1747
|
-
$(document).on(
|
1748
|
-
'mousemove.navigation',
|
1749
|
-
this.el,
|
1750
|
-
{ 'br': this },
|
1751
|
-
this.navigationMousemoveHandler
|
1752
|
-
);
|
1753
|
-
|
1754
|
-
$(document).off('mousedown.swipe', '.BRpageimage');
|
1755
|
-
$(document).on(
|
1756
|
-
'mousedown.swipe',
|
1757
|
-
'.BRpageimage',
|
1758
|
-
{ 'br': this },
|
1759
|
-
this.swipeMousedownHandler
|
1760
|
-
);
|
1761
|
-
|
1762
|
-
this.bindMozTouchHandlers();
|
1763
|
-
};
|
1764
|
-
|
1765
|
-
/**
|
1766
|
-
* Unbind navigation handlers
|
1767
|
-
*/
|
1768
|
-
BookReader.prototype.unbindNavigationHandlers = function() {
|
1769
|
-
$(document).off('mousemove.navigation', this.el);
|
1770
|
-
};
|
1771
|
-
|
1772
|
-
/**
|
1773
|
-
* Handle mousemove related to navigation. Bind at #BookReader level to allow autohide.
|
1774
|
-
*/
|
1775
|
-
BookReader.prototype.navigationMousemoveHandler = function(event) {
|
1776
|
-
// $$$ possibly not great to be calling this for every mousemove
|
1777
|
-
if (event.data['br'].uiAutoHide) {
|
1778
|
-
// 77px is an approximate height of the Internet Archive Top Nav
|
1779
|
-
// 75 & 76 (pixels) provide used in this context is checked against the IA top nav height
|
1780
|
-
var navkey = $(document).height() - 75;
|
1781
|
-
if ((event.pageY < 76) || (event.pageY > navkey)) {
|
1782
|
-
// inside or near navigation elements
|
1783
|
-
event.data['br'].hideNavigation();
|
1784
|
-
} else {
|
1785
|
-
event.data['br'].showNavigation();
|
1786
|
-
}
|
1787
|
-
}
|
1788
|
-
};
|
1789
|
-
|
1790
|
-
BookReader.prototype.initSwipeData = function(clientX, clientY) {
|
1791
|
-
/*
|
1792
|
-
* Based on the really quite awesome "Today's Guardian" at http://guardian.gyford.com/
|
1793
|
-
*/
|
1794
|
-
this._swipe = {
|
1795
|
-
mightBeSwiping: false,
|
1796
|
-
didSwipe: false,
|
1797
|
-
mightBeDraggin: false,
|
1798
|
-
didDrag: false,
|
1799
|
-
startTime: (new Date).getTime(),
|
1800
|
-
startX: clientX,
|
1801
|
-
startY: clientY,
|
1802
|
-
lastX: clientX,
|
1803
|
-
lastY: clientY,
|
1804
|
-
deltaX: 0,
|
1805
|
-
deltaY: 0,
|
1806
|
-
deltaT: 0
|
1807
|
-
};
|
1808
|
-
};
|
1809
|
-
|
1810
|
-
BookReader.prototype.swipeMousedownHandler = function(event) {
|
1811
|
-
var self = event.data['br'];
|
1812
|
-
|
1813
|
-
// We should be the last bubble point for the page images
|
1814
|
-
// Disable image drag and select, but keep right-click
|
1815
|
-
if (event.which == 3) {
|
1816
|
-
return !self.protected;
|
1817
|
-
}
|
1818
|
-
|
1819
|
-
$(event.target).on('mouseout.swipe',
|
1820
|
-
{ 'br': self},
|
1821
|
-
self.swipeMouseupHandler
|
1822
|
-
).on('mouseup.swipe',
|
1823
|
-
{ 'br': self},
|
1824
|
-
self.swipeMouseupHandler
|
1825
|
-
).on('mousemove.swipe',
|
1826
|
-
{ 'br': self },
|
1827
|
-
self.swipeMousemoveHandler
|
1828
|
-
);
|
1829
|
-
|
1830
|
-
self.initSwipeData(event.clientX, event.clientY);
|
1831
|
-
self._swipe.mightBeSwiping = true;
|
1832
|
-
self._swipe.mightBeDragging = true;
|
1833
|
-
|
1834
|
-
event.preventDefault();
|
1835
|
-
event.returnValue = false;
|
1836
|
-
event.cancelBubble = true;
|
1837
|
-
return false;
|
1838
|
-
};
|
1839
|
-
|
1840
|
-
BookReader.prototype.swipeMousemoveHandler = function(event) {
|
1841
|
-
var self = event.data['br'];
|
1842
|
-
var _swipe = self._swipe;
|
1843
|
-
if (! _swipe.mightBeSwiping) {
|
1844
|
-
return;
|
1845
|
-
}
|
1846
|
-
|
1847
|
-
// Update swipe data
|
1848
|
-
_swipe.deltaX = event.clientX - _swipe.startX;
|
1849
|
-
_swipe.deltaY = event.clientY - _swipe.startY;
|
1850
|
-
_swipe.deltaT = (new Date).getTime() - _swipe.startTime;
|
1851
|
-
|
1852
|
-
var absX = Math.abs(_swipe.deltaX);
|
1853
|
-
var absY = Math.abs(_swipe.deltaY);
|
1854
|
-
|
1855
|
-
// Minimum distance in the amount of tim to trigger the swipe
|
1856
|
-
var minSwipeLength = Math.min(self.refs.$br.width() / 5, 80);
|
1857
|
-
var maxSwipeTime = 400;
|
1858
|
-
|
1859
|
-
// Check for horizontal swipe
|
1860
|
-
if (absX > absY && (absX > minSwipeLength) && _swipe.deltaT < maxSwipeTime) {
|
1861
|
-
_swipe.mightBeSwiping = false; // only trigger once
|
1862
|
-
_swipe.didSwipe = true;
|
1863
|
-
if (self.mode == self.constMode2up) {
|
1864
|
-
if (_swipe.deltaX < 0) {
|
1865
|
-
self.right();
|
1866
|
-
} else {
|
1867
|
-
self.left();
|
1868
|
-
}
|
1869
|
-
}
|
1870
|
-
}
|
1871
|
-
|
1872
|
-
if ( _swipe.deltaT > maxSwipeTime && !_swipe.didSwipe) {
|
1873
|
-
if (_swipe.mightBeDragging) {
|
1874
|
-
// Dragging
|
1875
|
-
_swipe.didDrag = true;
|
1876
|
-
self.refs.$brContainer
|
1877
|
-
.scrollTop(self.refs.$brContainer.scrollTop() - event.clientY + _swipe.lastY)
|
1878
|
-
.scrollLeft(self.refs.$brContainer.scrollLeft() - event.clientX + _swipe.lastX);
|
1879
|
-
}
|
1880
|
-
}
|
1881
|
-
_swipe.lastX = event.clientX;
|
1882
|
-
_swipe.lastY = event.clientY;
|
1883
|
-
|
1884
|
-
event.preventDefault();
|
1885
|
-
event.returnValue = false;
|
1886
|
-
event.cancelBubble = true;
|
1887
|
-
return false;
|
1888
|
-
};
|
1889
|
-
|
1890
|
-
BookReader.prototype.swipeMouseupHandler = function(event) {
|
1891
|
-
var _swipe = event.data['br']._swipe;
|
1892
|
-
_swipe.mightBeSwiping = false;
|
1893
|
-
_swipe.mightBeDragging = false;
|
1894
|
-
|
1895
|
-
$(event.target).off('mouseout.swipe').off('mouseup.swipe').off('mousemove.swipe');
|
1896
|
-
|
1897
|
-
if (_swipe.didSwipe || _swipe.didDrag) {
|
1898
|
-
// Swallow event if completed swipe gesture
|
1899
|
-
event.preventDefault();
|
1900
|
-
event.returnValue = false;
|
1901
|
-
event.cancelBubble = true;
|
1902
|
-
return false;
|
1903
|
-
}
|
1904
|
-
return true;
|
1905
|
-
};
|
1906
|
-
|
1907
|
-
BookReader.prototype.bindMozTouchHandlers = function() {
|
1908
|
-
var self = this;
|
1909
|
-
|
1910
|
-
// Currently only want touch handlers in 2up
|
1911
|
-
this.refs.$br
|
1912
|
-
.on('MozTouchDown', function(event) {
|
1913
|
-
if (this.mode == self.constMode2up) {
|
1914
|
-
event.preventDefault();
|
1915
|
-
}
|
1916
|
-
})
|
1917
|
-
.on('MozTouchMove', function(event) {
|
1918
|
-
if (this.mode == self.constMode2up) {
|
1919
|
-
event.preventDefault();
|
1920
|
-
}
|
1921
|
-
})
|
1922
|
-
.on('MozTouchUp', function(event) {
|
1923
|
-
if (this.mode == self.constMode2up) {
|
1924
|
-
event.preventDefault();
|
1925
|
-
}
|
1926
|
-
});
|
1927
|
-
};
|
1928
|
-
|
1929
|
-
/**
|
1930
|
-
* Returns true if the navigation elements are currently visible
|
1931
|
-
* @return {boolean}
|
1932
|
-
*/
|
1933
|
-
BookReader.prototype.navigationIsVisible = function() {
|
1934
|
-
// $$$ doesn't account for transitioning states, nav must be fully visible to return true
|
1935
|
-
var toolpos = this.refs.$BRtoolbar.position();
|
1936
|
-
var tooltop = toolpos.top;
|
1937
|
-
return tooltop == 0;
|
1938
|
-
};
|
1939
|
-
|
1940
|
-
/**
|
1941
|
-
* Main controller that sets navigation into view.
|
1942
|
-
* Defaults to SHOW the navigation chrome
|
1943
|
-
*/
|
1944
|
-
BookReader.prototype.setNavigationView = function brSetNavigationView(hide) {
|
1945
|
-
var animationLength = this.constNavAnimationDuration;
|
1946
|
-
var animationType = 'linear';
|
1947
|
-
var resizePageContainer = function resizePageContainer () {
|
1948
|
-
/* main page container fills whole container */
|
1949
|
-
if (this.constMode2up !== this.mode) {
|
1950
|
-
var animate = true;
|
1951
|
-
this.resizeBRcontainer(animate);
|
1952
|
-
}
|
1953
|
-
this.trigger(BookReader.eventNames.navToggled);
|
1954
|
-
}.bind(this);
|
1955
|
-
|
1956
|
-
var toolbarHeight = 0;
|
1957
|
-
var navbarHeight = 0;
|
1958
|
-
if (hide) {
|
1959
|
-
toolbarHeight = this.getToolBarHeight() * -1;
|
1960
|
-
navbarHeight = this.getFooterHeight() * -1;
|
1961
|
-
|
1962
|
-
this.refs.$BRtoolbar.addClass('js-menu-hide');
|
1963
|
-
this.refs.$BRfooter.addClass('js-menu-hide');
|
1964
|
-
} else {
|
1965
|
-
this.refs.$BRtoolbar.removeClass('js-menu-hide');
|
1966
|
-
this.refs.$BRfooter.removeClass('js-menu-hide');
|
1967
|
-
}
|
1968
|
-
|
1969
|
-
this.refs.$BRtoolbar.animate(
|
1970
|
-
{ top: toolbarHeight },
|
1971
|
-
animationLength,
|
1972
|
-
animationType,
|
1973
|
-
resizePageContainer
|
1974
|
-
);
|
1975
|
-
this.refs.$BRfooter.animate(
|
1976
|
-
{ bottom: navbarHeight },
|
1977
|
-
animationLength,
|
1978
|
-
animationType,
|
1979
|
-
resizePageContainer
|
1980
|
-
);
|
1981
|
-
};
|
1982
|
-
/**
|
1983
|
-
* Hide navigation elements, if visible
|
1984
|
-
*/
|
1985
|
-
BookReader.prototype.hideNavigation = function() {
|
1986
|
-
// Check if navigation is showing
|
1987
|
-
if (this.navigationIsVisible()) {
|
1988
|
-
var hide = true;
|
1989
|
-
this.setNavigationView(hide);
|
1990
|
-
}
|
1991
|
-
};
|
1992
|
-
|
1993
|
-
/**
|
1994
|
-
* Show navigation elements
|
1995
|
-
*/
|
1996
|
-
BookReader.prototype.showNavigation = function() {
|
1997
|
-
// Check if navigation is hidden
|
1998
|
-
if (!this.navigationIsVisible()) {
|
1999
|
-
this.setNavigationView();
|
2000
|
-
}
|
2001
|
-
};
|
2002
|
-
|
2003
|
-
/**
|
2004
|
-
* Returns the index of the first visible page, dependent on the mode.
|
2005
|
-
* $$$ Currently we cannot display the front/back cover in 2-up and will need to update
|
2006
|
-
* this function when we can as part of https://bugs.launchpad.net/gnubook/+bug/296788
|
2007
|
-
* @return {number}
|
2008
|
-
*/
|
2009
|
-
BookReader.prototype.firstDisplayableIndex = function() {
|
2010
|
-
if (this.mode != this.constMode2up) {
|
2011
|
-
return 0;
|
2012
|
-
}
|
2013
|
-
|
2014
|
-
if ('rl' != this.pageProgression) {
|
2015
|
-
// LTR
|
2016
|
-
if (this._models.book.getPageSide(0) == 'L') {
|
2017
|
-
return 0;
|
2018
|
-
} else {
|
2019
|
-
return -1;
|
2020
|
-
}
|
2021
|
-
} else {
|
2022
|
-
// RTL
|
2023
|
-
if (this._models.book.getPageSide(0) == 'R') {
|
2024
|
-
return 0;
|
2025
|
-
} else {
|
2026
|
-
return -1;
|
2027
|
-
}
|
2028
|
-
}
|
2029
|
-
};
|
2030
|
-
|
2031
|
-
/**
|
2032
|
-
* Returns the index of the last visible page, dependent on the mode.
|
2033
|
-
* $$$ Currently we cannot display the front/back cover in 2-up and will need to update
|
2034
|
-
* this function when we can as part of https://bugs.launchpad.net/gnubook/+bug/296788
|
2035
|
-
* @return {number}
|
2036
|
-
*/
|
2037
|
-
BookReader.prototype.lastDisplayableIndex = function() {
|
2038
|
-
|
2039
|
-
var lastIndex = this._models.book.getNumLeafs() - 1;
|
2040
|
-
|
2041
|
-
if (this.mode != this.constMode2up) {
|
2042
|
-
return lastIndex;
|
2043
|
-
}
|
2044
|
-
|
2045
|
-
if ('rl' != this.pageProgression) {
|
2046
|
-
// LTR
|
2047
|
-
if (this._models.book.getPageSide(lastIndex) == 'R') {
|
2048
|
-
return lastIndex;
|
2049
|
-
} else {
|
2050
|
-
return lastIndex + 1;
|
2051
|
-
}
|
2052
|
-
} else {
|
2053
|
-
// RTL
|
2054
|
-
if (this._models.book.getPageSide(lastIndex) == 'L') {
|
2055
|
-
return lastIndex;
|
2056
|
-
} else {
|
2057
|
-
return lastIndex + 1;
|
2058
|
-
}
|
2059
|
-
}
|
2060
|
-
};
|
2061
|
-
|
2062
|
-
|
2063
|
-
/**************************/
|
2064
|
-
/** BookModel extensions **/
|
2065
|
-
/**************************/
|
2066
|
-
/** @deprecated not used outside */
|
2067
|
-
BookReader.prototype.getMedianPageSize = BookModel.prototype.getMedianPageSize;
|
2068
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getMedianPageSize');
|
2069
|
-
BookReader.prototype._getPageWidth = BookModel.prototype._getPageWidth;
|
2070
|
-
exposeOverrideableMethod(BookModel, '_models.book', '_getPageWidth');
|
2071
|
-
BookReader.prototype._getPageHeight = BookModel.prototype._getPageHeight;
|
2072
|
-
exposeOverrideableMethod(BookModel, '_models.book', '_getPageHeight');
|
2073
|
-
BookReader.prototype.getPageIndex = BookModel.prototype.getPageIndex;
|
2074
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getPageIndex');
|
2075
|
-
/** @deprecated not used outside */
|
2076
|
-
BookReader.prototype.getPageIndices = BookModel.prototype.getPageIndices;
|
2077
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getPageIndices');
|
2078
|
-
BookReader.prototype.getPageName = BookModel.prototype.getPageName;
|
2079
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getPageName');
|
2080
|
-
BookReader.prototype.getNumLeafs = BookModel.prototype.getNumLeafs;
|
2081
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getNumLeafs');
|
2082
|
-
BookReader.prototype.getPageWidth = BookModel.prototype.getPageWidth;
|
2083
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getPageWidth');
|
2084
|
-
BookReader.prototype.getPageHeight = BookModel.prototype.getPageHeight;
|
2085
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getPageHeight');
|
2086
|
-
BookReader.prototype.getPageURI = BookModel.prototype.getPageURI;
|
2087
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getPageURI');
|
2088
|
-
BookReader.prototype.getPageSide = BookModel.prototype.getPageSide;
|
2089
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getPageSide');
|
2090
|
-
BookReader.prototype.getPageNum = BookModel.prototype.getPageNum;
|
2091
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getPageNum');
|
2092
|
-
BookReader.prototype.getPageProp = BookModel.prototype.getPageProp;
|
2093
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getPageProp');
|
2094
|
-
BookReader.prototype.getSpreadIndices = BookModel.prototype.getSpreadIndices;
|
2095
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'getSpreadIndices');
|
2096
|
-
BookReader.prototype.leafNumToIndex = BookModel.prototype.leafNumToIndex;
|
2097
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'leafNumToIndex');
|
2098
|
-
BookReader.prototype.parsePageString = BookModel.prototype.parsePageString;
|
2099
|
-
exposeOverrideableMethod(BookModel, '_models.book', 'parsePageString');
|
2100
|
-
/** @deprecated unused */
|
2101
|
-
BookReader.prototype._getDataFlattened = BookModel.prototype._getDataFlattened;
|
2102
|
-
exposeOverrideableMethod(BookModel, '_models.book', '_getDataFlattened');
|
2103
|
-
/** @deprecated unused */
|
2104
|
-
BookReader.prototype._getDataProp = BookModel.prototype._getDataProp;
|
2105
|
-
exposeOverrideableMethod(BookModel, '_models.book', '_getDataProp');
|
2106
|
-
|
2107
|
-
// Parameter related functions
|
2108
|
-
|
2109
|
-
/**
|
2110
|
-
* Update from the params object
|
2111
|
-
* @param {Object}
|
2112
|
-
*/
|
2113
|
-
BookReader.prototype.updateFromParams = function(params) {
|
2114
|
-
// Set init, fragment change options for switchMode()
|
2115
|
-
const {
|
2116
|
-
mode = 0,
|
2117
|
-
init = false,
|
2118
|
-
fragmentChange = false,
|
2119
|
-
} = params;
|
2120
|
-
|
2121
|
-
if (mode) {
|
2122
|
-
this.switchMode(
|
2123
|
-
mode,
|
2124
|
-
{ init: init, suppressFragmentChange: !fragmentChange }
|
2125
|
-
);
|
2126
|
-
}
|
2127
|
-
|
2128
|
-
// $$$ process /zoom
|
2129
|
-
// We only respect page if index is not set
|
2130
|
-
if ('undefined' != typeof(params.index)) {
|
2131
|
-
if (params.index != this.currentIndex()) {
|
2132
|
-
this.jumpToIndex(params.index);
|
2133
|
-
}
|
2134
|
-
} else if ('undefined' != typeof(params.page)) {
|
2135
|
-
// $$$ this assumes page numbers are unique
|
2136
|
-
if (params.page != this._models.book.getPageNum(this.currentIndex())) {
|
2137
|
-
this.jumpToPage(params.page);
|
2138
|
-
}
|
2139
|
-
}
|
2140
|
-
|
2141
|
-
|
2142
|
-
// process /search
|
2143
|
-
// @deprecated for urlMode 'history'
|
2144
|
-
// Continues to work for urlMode 'hash'
|
2145
|
-
if (this.enableSearch && 'undefined' != typeof(params.search)) {
|
2146
|
-
if (this.searchTerm !== params.search) {
|
2147
|
-
this.$('.BRsearchInput').val(params.search);
|
2148
|
-
}
|
2149
|
-
}
|
2150
|
-
|
2151
|
-
// $$$ process /region
|
2152
|
-
// $$$ process /highlight
|
2153
|
-
|
2154
|
-
// $$$ process /theme
|
2155
|
-
if (this.enableThemesPlugin && 'undefined' != typeof(params.theme)) {
|
2156
|
-
this.updateTheme(params.theme);
|
2157
|
-
}
|
2158
|
-
};
|
2159
|
-
|
2160
|
-
/**
|
2161
|
-
* Returns true if we can switch to the requested mode
|
2162
|
-
* @param {number} mode
|
2163
|
-
* @return {boolean}
|
2164
|
-
*/
|
2165
|
-
BookReader.prototype.canSwitchToMode = function(mode) {
|
2166
|
-
if (mode == this.constMode2up || mode == this.constModeThumb) {
|
2167
|
-
// check there are enough pages to display
|
2168
|
-
// $$$ this is a workaround for the mis-feature that we can't display
|
2169
|
-
// short books in 2up mode
|
2170
|
-
if (this._models.book.getNumLeafs() < 2) {
|
2171
|
-
return false;
|
2172
|
-
}
|
2173
|
-
}
|
2174
|
-
|
2175
|
-
return true;
|
2176
|
-
};
|
2177
|
-
|
2178
|
-
|
2179
|
-
/**
|
2180
|
-
* @deprecated. Use PageModel.getURISrcSet. Slated for removal in v5.
|
2181
|
-
* Returns the srcset with correct URIs or void string if out of range
|
2182
|
-
* Also makes the reduce argument optional
|
2183
|
-
* @param {number} index
|
2184
|
-
* @param {number} [reduce]
|
2185
|
-
* @param {number} [rotate]
|
2186
|
-
* @return {string}
|
2187
|
-
*/
|
2188
|
-
BookReader.prototype._getPageURISrcset = function(index, reduce, rotate) {
|
2189
|
-
const page = this._models.book.getPage(index, false);
|
2190
|
-
// Synthesize page
|
2191
|
-
if (!page) return "";
|
2192
|
-
|
2193
|
-
// reduce not passed in
|
2194
|
-
// $$$ this probably won't work for thumbnail mode
|
2195
|
-
if ('undefined' == typeof(reduce)) {
|
2196
|
-
reduce = page.height / this.twoPage.height;
|
2197
|
-
}
|
2198
|
-
|
2199
|
-
return page.getURISrcSet(reduce, rotate);
|
2200
|
-
};
|
2201
|
-
|
2202
|
-
|
2203
|
-
/**
|
2204
|
-
* Returns the page URI or transparent image if out of range
|
2205
|
-
* Also makes the reduce argument optional
|
2206
|
-
* @param {number} index
|
2207
|
-
* @param {number} [reduce]
|
2208
|
-
* @param {number} [rotate]
|
2209
|
-
* @return {string}
|
2210
|
-
*/
|
2211
|
-
BookReader.prototype._getPageURI = function(index, reduce, rotate) {
|
2212
|
-
const page = this._models.book.getPage(index, false);
|
2213
|
-
// Synthesize page
|
2214
|
-
if (!page) return this.imagesBaseURL + "transparent.png";
|
2215
|
-
|
2216
|
-
if ('undefined' == typeof(reduce)) {
|
2217
|
-
// reduce not passed in
|
2218
|
-
// $$$ this probably won't work for thumbnail mode
|
2219
|
-
reduce = page.height / this.twoPage.height;
|
2220
|
-
}
|
2221
|
-
|
2222
|
-
return page.getURI(reduce, rotate);
|
2223
|
-
};
|
2224
|
-
|
2225
|
-
/**
|
2226
|
-
* @param {string} msg
|
2227
|
-
* @param {function|undefined} onCloseCallback
|
2228
|
-
*/
|
2229
|
-
BookReader.prototype.showProgressPopup = function(msg, onCloseCallback) {
|
2230
|
-
if (this.popup) return;
|
2231
|
-
|
2232
|
-
this.popup = document.createElement("div");
|
2233
|
-
$(this.popup).prop('className', 'BRprogresspopup');
|
2234
|
-
|
2235
|
-
if (typeof(onCloseCallback) === 'function') {
|
2236
|
-
const closeButton = document.createElement('button');
|
2237
|
-
closeButton.setAttribute('title', 'close');
|
2238
|
-
closeButton.setAttribute('class', 'close-popup');
|
2239
|
-
const icon = document.createElement('span');
|
2240
|
-
icon.setAttribute('class', 'icon icon-close-dark');
|
2241
|
-
$(closeButton).append(icon);
|
2242
|
-
closeButton.addEventListener('click', () => {
|
2243
|
-
onCloseCallback();
|
2244
|
-
this.removeProgressPopup();
|
2245
|
-
});
|
2246
|
-
$(this.popup).append(closeButton);
|
2247
|
-
}
|
2248
|
-
|
2249
|
-
const bar = document.createElement("div");
|
2250
|
-
$(bar).css({
|
2251
|
-
height: '20px'
|
2252
|
-
}).prop('className', 'BRprogressbar');
|
2253
|
-
$(this.popup).append(bar);
|
2254
|
-
|
2255
|
-
if (msg) {
|
2256
|
-
const msgdiv = document.createElement("div");
|
2257
|
-
msgdiv.innerHTML = msg;
|
2258
|
-
$(this.popup).append(msgdiv);
|
2259
|
-
}
|
2260
|
-
|
2261
|
-
$(this.popup).appendTo(this.refs.$br);
|
2262
|
-
};
|
2263
|
-
|
2264
|
-
BookReader.prototype.removeProgressPopup = function() {
|
2265
|
-
$(this.popup).remove();
|
2266
|
-
this.$('.BRprogresspopup').remove();
|
2267
|
-
this.popup = null;
|
2268
|
-
};
|
2269
|
-
|
2270
|
-
/**
|
2271
|
-
* Can be overridden
|
2272
|
-
*/
|
2273
|
-
BookReader.prototype.initUIStrings = function() {
|
2274
|
-
// Navigation handlers will be bound after all UI is in place -- makes moving icons between
|
2275
|
-
// the toolbar and nav bar easier
|
2276
|
-
|
2277
|
-
// Setup tooltips -- later we could load these from a file for i18n
|
2278
|
-
var titles = {
|
2279
|
-
'.logo': 'Go to Archive.org', // $$$ update after getting OL record
|
2280
|
-
'.zoom_in': 'Zoom in',
|
2281
|
-
'.zoom_out': 'Zoom out',
|
2282
|
-
'.onepg': 'One-page view',
|
2283
|
-
'.twopg': 'Two-page view',
|
2284
|
-
'.thumb': 'Thumbnail view',
|
2285
|
-
'.print': 'Print this page',
|
2286
|
-
'.embed': 'Embed BookReader',
|
2287
|
-
'.link': 'Link to this book (and page)',
|
2288
|
-
'.bookmark': 'Bookmark this page',
|
2289
|
-
'.share': 'Share this book',
|
2290
|
-
'.info': 'About this book',
|
2291
|
-
'.full': 'Toggle fullscreen',
|
2292
|
-
'.book_left': 'Flip left',
|
2293
|
-
'.book_right': 'Flip right',
|
2294
|
-
'.book_up': 'Page up',
|
2295
|
-
'.book_down': 'Page down',
|
2296
|
-
'.play': 'Play',
|
2297
|
-
'.pause': 'Pause',
|
2298
|
-
'.BRdn': 'Show/hide nav bar', // Would have to keep updating on state change to have just "Hide nav bar"
|
2299
|
-
'.BRup': 'Show/hide nav bar',
|
2300
|
-
'.book_top': 'First page',
|
2301
|
-
'.book_bottom': 'Last page',
|
2302
|
-
'.book_leftmost': 'First page',
|
2303
|
-
'.book_rightmost': 'Last page',
|
2304
|
-
};
|
2305
|
-
if ('rl' == this.pageProgression) {
|
2306
|
-
titles['.book_leftmost'] = 'Last page';
|
2307
|
-
titles['.book_rightmost'] = 'First page';
|
2308
|
-
}
|
2309
|
-
|
2310
|
-
for (var icon in titles) {
|
2311
|
-
this.$(icon).prop('title', titles[icon]);
|
2312
|
-
}
|
2313
|
-
};
|
2314
|
-
|
2315
|
-
/**
|
2316
|
-
* Reloads images. Useful when some images might have failed.
|
2317
|
-
*/
|
2318
|
-
BookReader.prototype.reloadImages = function() {
|
2319
|
-
this.refs.$brContainer.find('img').each(function(index, elem) {
|
2320
|
-
if (!elem.complete || elem.naturalHeight === 0) {
|
2321
|
-
var src = elem.src;
|
2322
|
-
elem.src = '';
|
2323
|
-
setTimeout(function() {
|
2324
|
-
elem.src = src;
|
2325
|
-
}, 1000);
|
2326
|
-
}
|
2327
|
-
});
|
2328
|
-
};
|
2329
|
-
|
2330
|
-
/**
|
2331
|
-
* @param {boolean} ignoreDisplay - bypass the display check
|
2332
|
-
* @return {number}
|
2333
|
-
*/
|
2334
|
-
BookReader.prototype.getFooterHeight = function() {
|
2335
|
-
var $heightEl = this.mode == this.constMode2up ? this.refs.$BRfooter : this.refs.$BRnav;
|
2336
|
-
if ($heightEl && this.refs.$BRfooter) {
|
2337
|
-
var outerHeight = $heightEl.outerHeight();
|
2338
|
-
var bottom = parseInt(this.refs.$BRfooter.css('bottom'));
|
2339
|
-
if (!isNaN(outerHeight) && !isNaN(bottom)) {
|
2340
|
-
return outerHeight + bottom;
|
2341
|
-
}
|
2342
|
-
}
|
2343
|
-
return 0;
|
2344
|
-
};
|
2345
|
-
|
2346
|
-
// Basic Usage built-in Methods (can be overridden through options)
|
2347
|
-
// This implementation uses options.data value for populating BookReader
|
2348
|
-
|
2349
|
-
/**
|
2350
|
-
* Create a params object from the current parameters.
|
2351
|
-
* @return {Object}
|
2352
|
-
*/
|
2353
|
-
BookReader.prototype.paramsFromCurrent = function() {
|
2354
|
-
var params = {};
|
2355
|
-
|
2356
|
-
// Path params
|
2357
|
-
var index = this.currentIndex();
|
2358
|
-
var pageNum = this._models.book.getPageNum(index);
|
2359
|
-
if ((pageNum === 0) || pageNum) {
|
2360
|
-
params.page = pageNum;
|
2361
|
-
}
|
2362
|
-
|
2363
|
-
params.index = index;
|
2364
|
-
params.mode = this.mode;
|
2365
|
-
|
2366
|
-
// Unused params
|
2367
|
-
// $$$ highlight
|
2368
|
-
// $$$ region
|
2369
|
-
|
2370
|
-
// Querystring params
|
2371
|
-
// View
|
2372
|
-
const fullscreenView = 'theater';
|
2373
|
-
if (this.isFullscreenActive) {
|
2374
|
-
params.view = fullscreenView;
|
2375
|
-
}
|
2376
|
-
// Search
|
2377
|
-
if (this.enableSearch) {
|
2378
|
-
params.search = this.searchTerm;
|
2379
|
-
}
|
2380
|
-
|
2381
|
-
return params;
|
2382
|
-
};
|
2383
|
-
|
2384
|
-
/**
|
2385
|
-
* Return an object with configuration parameters from a fragment string.
|
2386
|
-
*
|
2387
|
-
* Fragments are formatted as a URL path but may be used outside of URLs as a
|
2388
|
-
* serialization format for BookReader parameters
|
2389
|
-
*
|
2390
|
-
* @see http://openlibrary.org/dev/docs/bookurls for fragment syntax
|
2391
|
-
*
|
2392
|
-
* @param {string} fragment initial # is allowed for backwards compatibility
|
2393
|
-
* but is deprecated
|
2394
|
-
* @return {Object}
|
2395
|
-
*/
|
2396
|
-
BookReader.prototype.paramsFromFragment = function(fragment) {
|
2397
|
-
var params = {};
|
2398
|
-
|
2399
|
-
// For backwards compatibility we allow an initial # character
|
2400
|
-
// (as from window.location.hash) but don't require it
|
2401
|
-
if (fragment.substr(0, 1) == '#') {
|
2402
|
-
fragment = fragment.substr(1);
|
2403
|
-
}
|
2404
|
-
|
2405
|
-
// Simple #nn syntax
|
2406
|
-
var oldStyleLeafNum = parseInt( /^\d+$/.exec(fragment) );
|
2407
|
-
if ( !isNaN(oldStyleLeafNum) ) {
|
2408
|
-
params.index = oldStyleLeafNum;
|
2409
|
-
|
2410
|
-
// Done processing if using old-style syntax
|
2411
|
-
return params;
|
2412
|
-
}
|
2413
|
-
|
2414
|
-
// Split into key-value pairs
|
2415
|
-
var urlArray = fragment.split('/');
|
2416
|
-
var urlHash = {};
|
2417
|
-
for (var i = 0; i < urlArray.length; i += 2) {
|
2418
|
-
urlHash[urlArray[i]] = urlArray[i + 1];
|
2419
|
-
}
|
2420
|
-
|
2421
|
-
// Mode
|
2422
|
-
if ('1up' == urlHash['mode']) {
|
2423
|
-
params.mode = this.constMode1up;
|
2424
|
-
} else if ('2up' == urlHash['mode']) {
|
2425
|
-
params.mode = this.constMode2up;
|
2426
|
-
} else if ('thumb' == urlHash['mode']) {
|
2427
|
-
params.mode = this.constModeThumb;
|
2428
|
-
}
|
2429
|
-
|
2430
|
-
// Index and page
|
2431
|
-
if ('undefined' != typeof(urlHash['page'])) {
|
2432
|
-
// page was set -- may not be int
|
2433
|
-
params.page = urlHash['page'];
|
2434
|
-
}
|
2435
|
-
|
2436
|
-
// $$$ process /region
|
2437
|
-
// $$$ process /search
|
2438
|
-
|
2439
|
-
if (urlHash['search'] != undefined) {
|
2440
|
-
params.search = utils.decodeURIComponentPlus(urlHash['search']);
|
2441
|
-
}
|
2442
|
-
|
2443
|
-
// $$$ process /highlight
|
2444
|
-
|
2445
|
-
// $$$ process /theme
|
2446
|
-
if (urlHash['theme'] != undefined) {
|
2447
|
-
params.theme = urlHash['theme'];
|
2448
|
-
}
|
2449
|
-
return params;
|
2450
|
-
};
|
2451
|
-
|
2452
|
-
/**
|
2453
|
-
* Create a fragment string from the params object.
|
2454
|
-
*
|
2455
|
-
* Fragments are formatted as a URL path but may be used outside of URLs as a
|
2456
|
-
* serialization format for BookReader parameters
|
2457
|
-
*
|
2458
|
-
* @see https://openlibrary.org/dev/docs/bookurls for fragment syntax
|
2459
|
-
*
|
2460
|
-
* @param {Object} params
|
2461
|
-
* @param {string} [urlMode]
|
2462
|
-
* @return {string}
|
2463
|
-
*/
|
2464
|
-
BookReader.prototype.fragmentFromParams = function(params, urlMode = 'hash') {
|
2465
|
-
const separator = '/';
|
2466
|
-
const fragments = [];
|
2467
|
-
|
2468
|
-
if ('undefined' != typeof(params.page)) {
|
2469
|
-
fragments.push('page', params.page);
|
2470
|
-
} else {
|
2471
|
-
if ('undefined' != typeof(params.index)) {
|
2472
|
-
// Don't have page numbering but we do have the index
|
2473
|
-
fragments.push('page', 'n' + params.index);
|
2474
|
-
}
|
2475
|
-
}
|
2476
|
-
|
2477
|
-
// $$$ highlight
|
2478
|
-
// $$$ region
|
2479
|
-
|
2480
|
-
// mode
|
2481
|
-
if ('undefined' != typeof(params.mode)) {
|
2482
|
-
if (params.mode == this.constMode1up) {
|
2483
|
-
fragments.push('mode', '1up');
|
2484
|
-
} else if (params.mode == this.constMode2up) {
|
2485
|
-
fragments.push('mode', '2up');
|
2486
|
-
} else if (params.mode == this.constModeThumb) {
|
2487
|
-
fragments.push('mode', 'thumb');
|
2488
|
-
} else {
|
2489
|
-
throw 'fragmentFromParams called with unknown mode ' + params.mode;
|
2490
|
-
}
|
2491
|
-
}
|
2492
|
-
|
2493
|
-
// search
|
2494
|
-
if (params.search && urlMode === 'hash') {
|
2495
|
-
fragments.push('search', params.search);
|
2496
|
-
}
|
2497
|
-
|
2498
|
-
return utils.encodeURIComponentPlus(fragments.join(separator)).replace(/%2F/g, '/');
|
2499
|
-
};
|
2500
|
-
|
2501
|
-
/**
|
2502
|
-
* Create, update querystring from the params object
|
2503
|
-
*
|
2504
|
-
* Handles:
|
2505
|
-
* view=
|
2506
|
-
* q=
|
2507
|
-
* @param {Object} params
|
2508
|
-
* @param {string} currQueryString
|
2509
|
-
* @param {string} [urlMode]
|
2510
|
-
* @return {string}
|
2511
|
-
*/
|
2512
|
-
BookReader.prototype.queryStringFromParams = function(
|
2513
|
-
params,
|
2514
|
-
currQueryString,
|
2515
|
-
urlMode = 'hash'
|
2516
|
-
) {
|
2517
|
-
const newParams = new URLSearchParams(currQueryString);
|
2518
|
-
|
2519
|
-
if (params.view) {
|
2520
|
-
// Set ?view=theater when fullscreen
|
2521
|
-
newParams.set('view', params.view);
|
2522
|
-
} else {
|
2523
|
-
// Remove
|
2524
|
-
newParams.delete('view');
|
2525
|
-
}
|
2526
|
-
|
2527
|
-
if (params.search && urlMode === 'history') {
|
2528
|
-
newParams.set('q', params.search);
|
2529
|
-
}
|
2530
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/toString
|
2531
|
-
// Note: This method returns the query string without the question mark.
|
2532
|
-
const result = newParams.toString();
|
2533
|
-
return result ? '?' + result : '';
|
2534
|
-
};
|
2535
|
-
|
2536
|
-
/**
|
2537
|
-
* Helper to select within instance's elements
|
2538
|
-
*/
|
2539
|
-
BookReader.prototype.$ = function(selector) {
|
2540
|
-
return this.refs.$br.find(selector);
|
2541
|
-
};
|
2542
|
-
|
2543
|
-
/**
|
2544
|
-
* Polyfill for deprecated method
|
2545
|
-
*/
|
2546
|
-
jQuery.curCSS = function(element, prop, val) {
|
2547
|
-
return jQuery(element).css(prop, val);
|
2548
|
-
};
|
2549
|
-
|
2550
|
-
window.BookReader = BookReader;
|