@internetarchive/bookreader 5.0.0-58 → 5.0.0-59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BookReader/BookReader.css +110 -39
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.LICENSE.txt +0 -20
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +1 -1
- package/BookReader/ia-bookreader-bundle.js.map +1 -1
- package/BookReader/plugins/plugin.archive_analytics.js +1 -1
- package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
- package/BookReader/plugins/plugin.autoplay.js +1 -1
- package/BookReader/plugins/plugin.autoplay.js.map +1 -1
- package/BookReader/plugins/plugin.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.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/BookReaderDemo/BookReaderJSAutoplay.js +4 -1
- package/BookReaderDemo/BookReaderJSSimple.js +1 -0
- package/BookReaderDemo/IADemoBr.js +1 -2
- package/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/src/BookReader/BookModel.js +59 -1
- package/src/BookReader/Mode1UpLit.js +13 -70
- package/src/BookReader/Mode2Up.js +72 -1332
- package/src/BookReader/Mode2UpLit.js +774 -0
- package/src/BookReader/ModeCoordinateSpace.js +29 -0
- package/src/BookReader/ModeSmoothZoom.js +32 -0
- package/src/BookReader/options.js +8 -2
- package/src/BookReader/utils.js +16 -0
- package/src/BookReader.js +24 -217
- package/src/css/_BRBookmarks.scss +1 -1
- package/src/css/_BRmain.scss +14 -0
- package/src/css/_BRpages.scss +113 -41
- package/src/plugins/plugin.autoplay.js +1 -6
- package/src/plugins/tts/WebTTSEngine.js +2 -2
- package/src/plugins/tts/plugin.tts.js +3 -17
- package/src/plugins/tts/utils.js +0 -16
- package/tests/e2e/helpers/base.js +20 -20
- package/tests/e2e/helpers/rightToLeft.js +4 -10
- package/tests/e2e/viewmode.test.js +10 -8
- package/tests/jest/BookReader/BookModel.test.js +25 -0
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +28 -11
- package/tests/jest/BookReader/Mode1UpLit.test.js +0 -19
- package/tests/jest/BookReader/Mode2Up.test.js +55 -225
- package/tests/jest/BookReader/Mode2UpLit.test.js +190 -0
- package/tests/jest/BookReader/ModeCoordinateSpace.test.js +16 -0
- package/tests/jest/BookReader/ModeSmoothZoom.test.js +26 -0
- package/tests/jest/BookReader/Navbar/Navbar.test.js +3 -3
- package/tests/jest/BookReader/utils.test.js +32 -1
- package/tests/jest/plugins/tts/utils.test.js +0 -34
@@ -0,0 +1,29 @@
|
|
1
|
+
import { calcScreenDPI } from './utils';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* There are a few different "coordinate spaces" at play in BR:
|
5
|
+
* (1) World units: i.e. inches. Unless otherwise stated, all computations
|
6
|
+
* are done in world units.
|
7
|
+
* (2) Rendered Pixels: i.e. img.width = '300'. Note this does _not_ take
|
8
|
+
* into account zoom scaling.
|
9
|
+
* (3) Visible Pixels: Just rendered pixels, but taking into account scaling.
|
10
|
+
*/
|
11
|
+
export class ModeCoordinateSpace {
|
12
|
+
screenDPI = calcScreenDPI();
|
13
|
+
|
14
|
+
/**
|
15
|
+
* @param {{ scale: number }} mode
|
16
|
+
*/
|
17
|
+
constructor(mode) {
|
18
|
+
this.mode = mode;
|
19
|
+
}
|
20
|
+
|
21
|
+
worldUnitsToRenderedPixels = (/** @type {number} */inches) => inches * this.screenDPI;
|
22
|
+
renderedPixelsToWorldUnits = (/** @type {number} */px) => px / this.screenDPI;
|
23
|
+
|
24
|
+
renderedPixelsToVisiblePixels = (/** @type {number} */px) => px * this.mode.scale;
|
25
|
+
visiblePixelsToRenderedPixels = (/** @type {number} */px) => px / this.mode.scale;
|
26
|
+
|
27
|
+
worldUnitsToVisiblePixels = (/** @type {number} */px) => this.renderedPixelsToVisiblePixels(this.worldUnitsToRenderedPixels(px));
|
28
|
+
visiblePixelsToWorldUnits = (/** @type {number} */px) => this.renderedPixelsToWorldUnits(this.visiblePixelsToRenderedPixels(px));
|
29
|
+
}
|
@@ -6,6 +6,7 @@ import Hammer from "hammerjs";
|
|
6
6
|
* @typedef {object} SmoothZoomable
|
7
7
|
* @property {HTMLElement} $container
|
8
8
|
* @property {HTMLElement} $visibleWorld
|
9
|
+
* @property {import("./options.js").AutoFitValues} autoFit
|
9
10
|
* @property {number} scale
|
10
11
|
* @property {{ x: number, y: number }} scaleCenter
|
11
12
|
* @property {HTMLDimensionsCacher} htmlDimensionsCacher
|
@@ -91,6 +92,7 @@ export class ModeSmoothZoom {
|
|
91
92
|
this.oldScale = 1;
|
92
93
|
this.mode.$visibleWorld.classList.add("BRsmooth-zooming");
|
93
94
|
this.mode.$visibleWorld.style.willChange = "transform";
|
95
|
+
this.mode.autoFit = "none";
|
94
96
|
this.detachCtrlZoom();
|
95
97
|
this.mode.detachScrollListeners?.();
|
96
98
|
}
|
@@ -161,6 +163,7 @@ export class ModeSmoothZoom {
|
|
161
163
|
|
162
164
|
// Zoom around the cursor
|
163
165
|
this.updateScaleCenter(ev);
|
166
|
+
this.mode.autoFit = "none";
|
164
167
|
this.mode.scale *= 1 - Math.sign(ev.deltaY) * zoomMultiplier;
|
165
168
|
}
|
166
169
|
|
@@ -176,4 +179,33 @@ export class ModeSmoothZoom {
|
|
176
179
|
y: (clientY - bc.top) / this.mode.htmlDimensionsCacher.clientHeight,
|
177
180
|
};
|
178
181
|
}
|
182
|
+
|
183
|
+
/**
|
184
|
+
* @param {number} newScale
|
185
|
+
* @param {number} oldScale
|
186
|
+
*/
|
187
|
+
updateViewportOnZoom(newScale, oldScale) {
|
188
|
+
const container = this.mode.$container;
|
189
|
+
const { scrollTop: T, scrollLeft: L } = container;
|
190
|
+
const W = this.mode.htmlDimensionsCacher.clientWidth;
|
191
|
+
const H = this.mode.htmlDimensionsCacher.clientHeight;
|
192
|
+
|
193
|
+
// Scale factor change
|
194
|
+
const F = newScale / oldScale;
|
195
|
+
|
196
|
+
// Where in the viewport the zoom is centered on
|
197
|
+
const XPOS = this.mode.scaleCenter.x;
|
198
|
+
const YPOS = this.mode.scaleCenter.y;
|
199
|
+
const oldCenter = {
|
200
|
+
x: L + XPOS * W,
|
201
|
+
y: T + YPOS * H,
|
202
|
+
};
|
203
|
+
const newCenter = {
|
204
|
+
x: F * oldCenter.x,
|
205
|
+
y: F * oldCenter.y,
|
206
|
+
};
|
207
|
+
|
208
|
+
container.scrollTop = newCenter.y - YPOS * H;
|
209
|
+
container.scrollLeft = newCenter.x - XPOS * W;
|
210
|
+
}
|
179
211
|
}
|
@@ -31,7 +31,7 @@ export const DEFAULT_OPTIONS = {
|
|
31
31
|
thumbMaxZoomColumns: 8,
|
32
32
|
|
33
33
|
/** @type {number | 'fast' | 'slow'} speed for flip animation */
|
34
|
-
flipSpeed:
|
34
|
+
flipSpeed: 400,
|
35
35
|
|
36
36
|
showToolbar: true,
|
37
37
|
showNavbar: true,
|
@@ -300,7 +300,13 @@ export const DEFAULT_OPTIONS = {
|
|
300
300
|
useSrcSet: false,
|
301
301
|
};
|
302
302
|
|
303
|
-
/**
|
303
|
+
/**
|
304
|
+
* @typedef {'width' | 'height' | 'auto' | 'none'} AutoFitValues
|
305
|
+
* - width: fill the width of the container
|
306
|
+
* - height: fill the height of the container
|
307
|
+
* - auto: fill the width or height of the container, whichever is smaller
|
308
|
+
* - none: do not autofit
|
309
|
+
**/
|
304
310
|
|
305
311
|
/**
|
306
312
|
* @typedef {object} ReductionFactor
|
package/src/BookReader/utils.js
CHANGED
@@ -262,3 +262,19 @@ export async function poll(fn, { step = 50, timeout = 500, until = val => Boolea
|
|
262
262
|
await _sleep(step);
|
263
263
|
}
|
264
264
|
}
|
265
|
+
|
266
|
+
/**
|
267
|
+
* Convert a EventTarget style event into a promise
|
268
|
+
* @param {EventTarget} target
|
269
|
+
* @param {string} eventType
|
270
|
+
* @return {Promise<Event>}
|
271
|
+
*/
|
272
|
+
export function promisifyEvent(target, eventType) {
|
273
|
+
return new Promise(res => {
|
274
|
+
const resolver = ev => {
|
275
|
+
target.removeEventListener(eventType, resolver);
|
276
|
+
res(ev);
|
277
|
+
};
|
278
|
+
target.addEventListener(eventType, resolver);
|
279
|
+
});
|
280
|
+
}
|
package/src/BookReader.js
CHANGED
@@ -19,9 +19,6 @@ This file is part of BookReader.
|
|
19
19
|
The BookReader source is hosted at http://github.com/internetarchive/bookreader/
|
20
20
|
|
21
21
|
*/
|
22
|
-
// effect.js gives acces to extra easing function (e.g. easeInOutExpo)
|
23
|
-
import 'jquery-ui/ui/effect.js';
|
24
|
-
|
25
22
|
// Needed by touch-punch
|
26
23
|
import 'jquery-ui/ui/widget.js';
|
27
24
|
import 'jquery-ui/ui/widgets/mouse.js';
|
@@ -155,10 +152,11 @@ BookReader.prototype.setup = function(options) {
|
|
155
152
|
this.displayedIndices = [];
|
156
153
|
|
157
154
|
this.animating = false;
|
158
|
-
this.flipSpeed = options.flipSpeed
|
155
|
+
this.flipSpeed = typeof options.flipSpeed === 'number' ? options.flipSpeed : {
|
156
|
+
'fast': 200,
|
157
|
+
'slow': 600,
|
158
|
+
}[options.flipSpeed] || 400;
|
159
159
|
this.flipDelay = options.flipDelay;
|
160
|
-
this.twoPagePopUp = null;
|
161
|
-
this.leafEdgeTmp = null;
|
162
160
|
|
163
161
|
/**
|
164
162
|
* Represents the first displayed index
|
@@ -167,7 +165,6 @@ BookReader.prototype.setup = function(options) {
|
|
167
165
|
* @property {number|null} firstIndex
|
168
166
|
*/
|
169
167
|
this.firstIndex = null;
|
170
|
-
this.lastDisplayableIndex2up = null;
|
171
168
|
this.isFullscreenActive = options.startFullscreen || false;
|
172
169
|
this.lastScroll = null;
|
173
170
|
|
@@ -266,7 +263,7 @@ BookReader.prototype.setup = function(options) {
|
|
266
263
|
* Includes cached elements which might be rendered again.
|
267
264
|
*/
|
268
265
|
BookReader.prototype.getActivePageContainerElements = function() {
|
269
|
-
let containerEls = Object.values(this._modes.mode2Up.
|
266
|
+
let containerEls = Object.values(this._modes.mode2Up.mode2UpLit.pageContainerCache).map(pc => pc.$container[0])
|
270
267
|
.concat(Object.values(this._modes.mode1Up.mode1UpLit.pageContainerCache).map(pc => pc.$container[0]));
|
271
268
|
if (this.mode == this.constModeThumb) {
|
272
269
|
containerEls = containerEls.concat(this.$('.BRpagecontainer').toArray());
|
@@ -281,7 +278,7 @@ BookReader.prototype.getActivePageContainerElements = function() {
|
|
281
278
|
*/
|
282
279
|
BookReader.prototype.getActivePageContainerElementsForIndex = function(pageIndex) {
|
283
280
|
return [
|
284
|
-
this._modes.mode2Up.
|
281
|
+
this._modes.mode2Up.mode2UpLit.pageContainerCache[pageIndex]?.$container?.[0],
|
285
282
|
this._modes.mode1Up.mode1UpLit.pageContainerCache[pageIndex]?.$container?.[0],
|
286
283
|
...(this.mode == this.constModeThumb ? this.$(`.pagediv${pageIndex}`).toArray() : [])
|
287
284
|
].filter(x => x);
|
@@ -648,27 +645,7 @@ BookReader.prototype.resize = function() {
|
|
648
645
|
} else if (this.constModeThumb == this.mode) {
|
649
646
|
this._modes.modeThumb.prepare();
|
650
647
|
} else {
|
651
|
-
|
652
|
-
if (this.twoPage.autofit) {
|
653
|
-
// most common path, esp. for archive.org books
|
654
|
-
this._modes.mode2Up.prepare();
|
655
|
-
} else {
|
656
|
-
// used when zoomed in
|
657
|
-
// Re-center if the scrollbars have disappeared
|
658
|
-
const center = this.twoPageGetViewCenter();
|
659
|
-
let doRecenter = false;
|
660
|
-
if (this.twoPage.totalWidth < this.refs.$brContainer.prop('clientWidth')) {
|
661
|
-
center.percentageX = 0.5;
|
662
|
-
doRecenter = true;
|
663
|
-
}
|
664
|
-
if (this.twoPage.totalHeight < this.refs.$brContainer.prop('clientHeight')) {
|
665
|
-
center.percentageY = 0.5;
|
666
|
-
doRecenter = true;
|
667
|
-
}
|
668
|
-
if (doRecenter) {
|
669
|
-
this._modes.mode2Up.centerView(center.percentageX, center.percentageY);
|
670
|
-
}
|
671
|
-
}
|
648
|
+
this._modes.mode2Up.resizePageView();
|
672
649
|
}
|
673
650
|
this.trigger(BookReader.eventNames.resize);
|
674
651
|
};
|
@@ -1012,13 +989,7 @@ BookReader.prototype.jumpToIndex = function(index, pageX, pageY, noAnimate) {
|
|
1012
989
|
|
1013
990
|
this.trigger(BookReader.eventNames.stop);
|
1014
991
|
|
1015
|
-
|
1016
|
-
this._modes.mode2Up.jumpToIndex(index);
|
1017
|
-
} else if (this.constModeThumb == this.mode) {
|
1018
|
-
this._modes.modeThumb.jumpToIndex(index);
|
1019
|
-
} else { // 1up
|
1020
|
-
this._modes.mode1Up.jumpToIndex(index, pageX, pageY, noAnimate);
|
1021
|
-
}
|
992
|
+
this.activeMode.jumpToIndex(index, pageX, pageY, noAnimate);
|
1022
993
|
};
|
1023
994
|
|
1024
995
|
/**
|
@@ -1084,16 +1055,7 @@ BookReader.prototype.switchMode = function(
|
|
1084
1055
|
this.reduce = this.quantizeReduce(this.reduce, this.reductionFactors);
|
1085
1056
|
this._modes.modeThumb.prepare();
|
1086
1057
|
} else {
|
1087
|
-
// $$$ why don't we save autofit?
|
1088
|
-
// this.twoPage.autofit = null; // Take zoom level from other mode
|
1089
|
-
// spread indices not set, so let's set them
|
1090
|
-
if (init || !pageFound) {
|
1091
|
-
this._modes.mode2Up.setSpreadIndices();
|
1092
|
-
}
|
1093
|
-
|
1094
|
-
this._modes.mode2Up.calculateReductionFactors(); // this sets this.twoPage && this.reduce
|
1095
1058
|
this._modes.mode2Up.prepare();
|
1096
|
-
this._modes.mode2Up.centerView(0.5, 0.5); // $$$ TODO preserve center
|
1097
1059
|
}
|
1098
1060
|
|
1099
1061
|
if (!(this.suppressFragmentChange || suppressFragmentChange)) {
|
@@ -1108,11 +1070,11 @@ BookReader.prototype.switchMode = function(
|
|
1108
1070
|
BookReader.prototype.updateBrClasses = function() {
|
1109
1071
|
const modeToClass = {};
|
1110
1072
|
modeToClass[this.constMode1up] = 'BRmode1up';
|
1111
|
-
modeToClass[this.constMode2up] = '
|
1073
|
+
modeToClass[this.constMode2up] = 'BRmode2up';
|
1112
1074
|
modeToClass[this.constModeThumb] = 'BRmodeThumb';
|
1113
1075
|
|
1114
1076
|
this.refs.$br
|
1115
|
-
.removeClass('BRmode1up
|
1077
|
+
.removeClass('BRmode1up BRmode2up BRmodeThumb')
|
1116
1078
|
.addClass(modeToClass[this.mode]);
|
1117
1079
|
|
1118
1080
|
if (this.isFullscreen()) {
|
@@ -1143,14 +1105,13 @@ BookReader.prototype.toggleFullscreen = async function(bindKeyboardControls = tr
|
|
1143
1105
|
/**
|
1144
1106
|
* Enters fullscreen
|
1145
1107
|
* including:
|
1146
|
-
* - animation
|
1147
1108
|
* - binds keyboard controls
|
1148
1109
|
* - fires custom event
|
1149
1110
|
* @param { boolean } bindKeyboardControls
|
1150
1111
|
*/
|
1151
1112
|
BookReader.prototype.enterFullscreen = async function(bindKeyboardControls = true) {
|
1113
|
+
this.refs.$br.addClass('BRfullscreenAnimation');
|
1152
1114
|
const currentIndex = this.currentIndex();
|
1153
|
-
this.refs.$brContainer.css('opacity', 0);
|
1154
1115
|
|
1155
1116
|
if (bindKeyboardControls) {
|
1156
1117
|
this._fullscreenCloseHandler = (e) => {
|
@@ -1167,8 +1128,6 @@ BookReader.prototype.enterFullscreen = async function(bindKeyboardControls = tru
|
|
1167
1128
|
this.isFullscreenActive = true;
|
1168
1129
|
// prioritize class updates so CSS can propagate
|
1169
1130
|
this.updateBrClasses();
|
1170
|
-
this.animating = true;
|
1171
|
-
await new Promise(res => this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear', res));
|
1172
1131
|
if (this.activeMode instanceof Mode1Up) {
|
1173
1132
|
this.activeMode.mode1UpLit.scale = this.activeMode.mode1UpLit.computeDefaultScale(this.book.getPage(currentIndex));
|
1174
1133
|
// Need the new scale to be applied before calling jumpToIndex
|
@@ -1176,7 +1135,6 @@ BookReader.prototype.enterFullscreen = async function(bindKeyboardControls = tru
|
|
1176
1135
|
await this.activeMode.mode1UpLit.updateComplete;
|
1177
1136
|
}
|
1178
1137
|
this.jumpToIndex(currentIndex);
|
1179
|
-
this.animating = false;
|
1180
1138
|
|
1181
1139
|
this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
|
1182
1140
|
// Add "?view=theater"
|
@@ -1185,10 +1143,11 @@ BookReader.prototype.enterFullscreen = async function(bindKeyboardControls = tru
|
|
1185
1143
|
// class updates happen before book-nav relays to web components
|
1186
1144
|
this.trigger(BookReader.eventNames.fullscreenToggled);
|
1187
1145
|
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1146
|
+
// resize book after all events & css updates
|
1147
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
1148
|
+
|
1149
|
+
this.resize();
|
1150
|
+
this.refs.$br.removeClass('BRfullscreenAnimation');
|
1192
1151
|
};
|
1193
1152
|
|
1194
1153
|
/**
|
@@ -1199,12 +1158,10 @@ BookReader.prototype.enterFullscreen = async function(bindKeyboardControls = tru
|
|
1199
1158
|
* @param { boolean } bindKeyboardControls
|
1200
1159
|
*/
|
1201
1160
|
BookReader.prototype.exitFullScreen = async function () {
|
1202
|
-
this.refs.$
|
1203
|
-
|
1161
|
+
this.refs.$br.addClass('BRfullscreenAnimation');
|
1204
1162
|
$(document).off('keyup', this._fullscreenCloseHandler);
|
1205
1163
|
|
1206
1164
|
const windowWidth = $(window).width();
|
1207
|
-
|
1208
1165
|
const canShow2up = this.options.controls.twoPage.visible;
|
1209
1166
|
if (canShow2up && (windowWidth <= this.onePageMinBreakpoint)) {
|
1210
1167
|
this.switchMode(this.constMode2up);
|
@@ -1216,8 +1173,7 @@ BookReader.prototype.exitFullScreen = async function () {
|
|
1216
1173
|
this.trigger(BookReader.eventNames.fullscreenToggled);
|
1217
1174
|
|
1218
1175
|
this.updateBrClasses();
|
1219
|
-
|
1220
|
-
await new Promise((res => this.refs.$brContainer.animate({opacity: 1}, 'fast', 'linear', res)));
|
1176
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
1221
1177
|
this.resize();
|
1222
1178
|
|
1223
1179
|
if (this.activeMode instanceof Mode1Up) {
|
@@ -1226,11 +1182,10 @@ BookReader.prototype.exitFullScreen = async function () {
|
|
1226
1182
|
await this.activeMode.mode1UpLit.updateComplete;
|
1227
1183
|
}
|
1228
1184
|
|
1229
|
-
this.animating = false;
|
1230
|
-
|
1231
1185
|
this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
|
1232
1186
|
// Remove "?view=theater"
|
1233
1187
|
this.trigger(BookReader.eventNames.fragmentChange);
|
1188
|
+
this.refs.$br.removeClass('BRfullscreenAnimation');
|
1234
1189
|
};
|
1235
1190
|
|
1236
1191
|
/**
|
@@ -1329,9 +1284,9 @@ BookReader.prototype.leftmost = function() {
|
|
1329
1284
|
BookReader.prototype.next = function({triggerStop = true} = {}) {
|
1330
1285
|
if (this.constMode2up == this.mode) {
|
1331
1286
|
if (triggerStop) this.trigger(BookReader.eventNames.stop);
|
1332
|
-
this._modes.mode2Up.
|
1287
|
+
this._modes.mode2Up.mode2UpLit.flipAnimation('next');
|
1333
1288
|
} else {
|
1334
|
-
if (this.firstIndex < this.
|
1289
|
+
if (this.firstIndex < this.book.getNumLeafs() - 1) {
|
1335
1290
|
this.jumpToIndex(this.firstIndex + 1);
|
1336
1291
|
}
|
1337
1292
|
}
|
@@ -1343,7 +1298,7 @@ BookReader.prototype.prev = function({triggerStop = true} = {}) {
|
|
1343
1298
|
|
1344
1299
|
if (this.constMode2up == this.mode) {
|
1345
1300
|
if (triggerStop) this.trigger(BookReader.eventNames.stop);
|
1346
|
-
this._modes.mode2Up.
|
1301
|
+
this._modes.mode2Up.mode2UpLit.flipAnimation('prev');
|
1347
1302
|
} else {
|
1348
1303
|
if (this.firstIndex >= 1) {
|
1349
1304
|
this.jumpToIndex(this.firstIndex - 1);
|
@@ -1352,87 +1307,13 @@ BookReader.prototype.prev = function({triggerStop = true} = {}) {
|
|
1352
1307
|
};
|
1353
1308
|
|
1354
1309
|
BookReader.prototype.first = function() {
|
1355
|
-
this.jumpToIndex(
|
1310
|
+
this.jumpToIndex(0);
|
1356
1311
|
};
|
1357
1312
|
|
1358
1313
|
BookReader.prototype.last = function() {
|
1359
|
-
this.jumpToIndex(this.
|
1360
|
-
};
|
1361
|
-
|
1362
|
-
/**
|
1363
|
-
* Scrolls down one screen view
|
1364
|
-
*/
|
1365
|
-
BookReader.prototype.scrollDown = function() {
|
1366
|
-
if ($.inArray(this.mode, [this.constMode1up, this.constModeThumb]) >= 0) {
|
1367
|
-
if ( this.mode == this.constMode1up && (this.reduce >= this.onePageGetAutofitHeight()) ) {
|
1368
|
-
// Whole pages are visible, scroll whole page only
|
1369
|
-
return this.next();
|
1370
|
-
}
|
1371
|
-
|
1372
|
-
this.refs.$brContainer.stop(true).animate(
|
1373
|
-
{ scrollTop: '+=' + this._scrollAmount() + 'px'},
|
1374
|
-
400, 'easeInOutExpo'
|
1375
|
-
);
|
1376
|
-
return true;
|
1377
|
-
} else {
|
1378
|
-
return false;
|
1379
|
-
}
|
1380
|
-
};
|
1381
|
-
|
1382
|
-
/**
|
1383
|
-
* Scrolls up one screen view
|
1384
|
-
*/
|
1385
|
-
BookReader.prototype.scrollUp = function() {
|
1386
|
-
if ($.inArray(this.mode, [this.constMode1up, this.constModeThumb]) >= 0) {
|
1387
|
-
if ( this.mode == this.constMode1up && (this.reduce >= this.onePageGetAutofitHeight()) ) {
|
1388
|
-
// Whole pages are visible, scroll whole page only
|
1389
|
-
return this.prev();
|
1390
|
-
}
|
1391
|
-
|
1392
|
-
this.refs.$brContainer.stop(true).animate(
|
1393
|
-
{ scrollTop: '-=' + this._scrollAmount() + 'px'},
|
1394
|
-
400, 'easeInOutExpo'
|
1395
|
-
);
|
1396
|
-
return true;
|
1397
|
-
} else {
|
1398
|
-
return false;
|
1399
|
-
}
|
1400
|
-
};
|
1401
|
-
|
1402
|
-
/**
|
1403
|
-
* The amount to scroll vertically in integer pixels
|
1404
|
-
*/
|
1405
|
-
BookReader.prototype._scrollAmount = function() {
|
1406
|
-
if (this.constMode1up == this.mode) {
|
1407
|
-
// Overlap by % of page size
|
1408
|
-
return parseInt(this.refs.$brContainer.prop('clientHeight') - this.book.getPageHeight(this.currentIndex()) / this.reduce * 0.03);
|
1409
|
-
}
|
1410
|
-
|
1411
|
-
return parseInt(0.9 * this.refs.$brContainer.prop('clientHeight'));
|
1314
|
+
this.jumpToIndex(this.book.getNumLeafs() - 1);
|
1412
1315
|
};
|
1413
1316
|
|
1414
|
-
/**
|
1415
|
-
* Immediately stop flip animations. Callbacks are triggered.
|
1416
|
-
*/
|
1417
|
-
BookReader.prototype.stopFlipAnimations = function() {
|
1418
|
-
this.trigger(BookReader.eventNames.stop);
|
1419
|
-
|
1420
|
-
// Stop animation, clear queue, trigger callbacks
|
1421
|
-
if (this.leafEdgeTmp) {
|
1422
|
-
$(this.leafEdgeTmp).stop(false, true);
|
1423
|
-
}
|
1424
|
-
jQuery.each(this._modes.mode2Up.pageContainers, function() {
|
1425
|
-
$(this.$container).stop(false, true);
|
1426
|
-
});
|
1427
|
-
|
1428
|
-
// And again since animations also queued in callbacks
|
1429
|
-
if (this.leafEdgeTmp) {
|
1430
|
-
$(this.leafEdgeTmp).stop(false, true);
|
1431
|
-
}
|
1432
|
-
jQuery.each(this._modes.mode2Up.pageContainers, function() {
|
1433
|
-
$(this.$container).stop(false, true);
|
1434
|
-
});
|
1435
|
-
};
|
1436
1317
|
|
1437
1318
|
/**
|
1438
1319
|
* @template TClass extends { br: BookReader }
|
@@ -1492,20 +1373,6 @@ BookReader.prototype.bindNavigationHandlers = function() {
|
|
1492
1373
|
this.trigger(BookReader.eventNames.stop);
|
1493
1374
|
this.right();
|
1494
1375
|
},
|
1495
|
-
book_up: () => {
|
1496
|
-
if ($.inArray(this.mode, [this.constMode1up, this.constModeThumb]) >= 0) {
|
1497
|
-
this.scrollUp();
|
1498
|
-
} else {
|
1499
|
-
this.prev();
|
1500
|
-
}
|
1501
|
-
},
|
1502
|
-
book_down: () => {
|
1503
|
-
if ($.inArray(this.mode, [this.constMode1up, this.constModeThumb]) >= 0) {
|
1504
|
-
this.scrollDown();
|
1505
|
-
} else {
|
1506
|
-
this.next();
|
1507
|
-
}
|
1508
|
-
},
|
1509
1376
|
book_top: this.first.bind(this),
|
1510
1377
|
book_bottom: this.last.bind(this),
|
1511
1378
|
book_leftmost: this.leftmost.bind(this),
|
@@ -1881,64 +1748,6 @@ BookReader.prototype.showNavigation = function() {
|
|
1881
1748
|
}
|
1882
1749
|
};
|
1883
1750
|
|
1884
|
-
/**
|
1885
|
-
* Returns the index of the first visible page, dependent on the mode.
|
1886
|
-
* $$$ Currently we cannot display the front/back cover in 2-up and will need to update
|
1887
|
-
* this function when we can as part of https://bugs.launchpad.net/gnubook/+bug/296788
|
1888
|
-
* @return {number}
|
1889
|
-
*/
|
1890
|
-
BookReader.prototype.firstDisplayableIndex = function() {
|
1891
|
-
if (this.mode != this.constMode2up) {
|
1892
|
-
return 0;
|
1893
|
-
}
|
1894
|
-
|
1895
|
-
if ('rl' != this.pageProgression) {
|
1896
|
-
// LTR
|
1897
|
-
if (this.book.getPageSide(0) == 'L') {
|
1898
|
-
return 0;
|
1899
|
-
} else {
|
1900
|
-
return -1;
|
1901
|
-
}
|
1902
|
-
} else {
|
1903
|
-
// RTL
|
1904
|
-
if (this.book.getPageSide(0) == 'R') {
|
1905
|
-
return 0;
|
1906
|
-
} else {
|
1907
|
-
return -1;
|
1908
|
-
}
|
1909
|
-
}
|
1910
|
-
};
|
1911
|
-
|
1912
|
-
/**
|
1913
|
-
* Returns the index of the last visible page, dependent on the mode.
|
1914
|
-
* $$$ Currently we cannot display the front/back cover in 2-up and will need to update
|
1915
|
-
* this function when we can as part of https://bugs.launchpad.net/gnubook/+bug/296788
|
1916
|
-
* @return {number}
|
1917
|
-
*/
|
1918
|
-
BookReader.prototype.lastDisplayableIndex = function() {
|
1919
|
-
|
1920
|
-
const lastIndex = this.book.getNumLeafs() - 1;
|
1921
|
-
|
1922
|
-
if (this.mode != this.constMode2up) {
|
1923
|
-
return lastIndex;
|
1924
|
-
}
|
1925
|
-
|
1926
|
-
if ('rl' != this.pageProgression) {
|
1927
|
-
// LTR
|
1928
|
-
if (this.book.getPageSide(lastIndex) == 'R') {
|
1929
|
-
return lastIndex;
|
1930
|
-
} else {
|
1931
|
-
return lastIndex + 1;
|
1932
|
-
}
|
1933
|
-
} else {
|
1934
|
-
// RTL
|
1935
|
-
if (this.book.getPageSide(lastIndex) == 'L') {
|
1936
|
-
return lastIndex;
|
1937
|
-
} else {
|
1938
|
-
return lastIndex + 1;
|
1939
|
-
}
|
1940
|
-
}
|
1941
|
-
};
|
1942
1751
|
|
1943
1752
|
|
1944
1753
|
/**************************/
|
@@ -2112,8 +1921,6 @@ BookReader.prototype.initUIStrings = function() {
|
|
2112
1921
|
'.full': 'Toggle fullscreen',
|
2113
1922
|
'.book_left': 'Flip left',
|
2114
1923
|
'.book_right': 'Flip right',
|
2115
|
-
'.book_up': 'Page up',
|
2116
|
-
'.book_down': 'Page down',
|
2117
1924
|
'.play': 'Play',
|
2118
1925
|
'.pause': 'Pause',
|
2119
1926
|
'.BRdn': 'Show/hide nav bar', // Would have to keep updating on state change to have just "Hide nav bar"
|
package/src/css/_BRmain.scss
CHANGED
@@ -249,3 +249,17 @@ body.BRfullscreenActive {
|
|
249
249
|
.BRpagediv1up { background-color: white; }
|
250
250
|
.BRpagedivthumb { background-color: white; }
|
251
251
|
}
|
252
|
+
|
253
|
+
.BRfullscreenAnimation .br-mode-2up__book {
|
254
|
+
transition: transform .2s ease-in-out;
|
255
|
+
}
|
256
|
+
|
257
|
+
.fullscreenActive.BRmodeThumb .BRcontainer,
|
258
|
+
.fullscreenActive.BRmode1up .BRcontainer {
|
259
|
+
animation: flash 0.3s ease-in-out;
|
260
|
+
}
|
261
|
+
|
262
|
+
@keyframes flash {
|
263
|
+
0% { opacity: 0; }
|
264
|
+
100% { opacity: 1; }
|
265
|
+
}
|