@internetarchive/bookreader 5.0.0-57 → 5.0.0-59
Sign up to get free protection for your applications and to get access to all the features.
- 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 +8 -0
- package/babel.config.js +5 -2
- package/package.json +10 -9
- package/src/BookReader/BookModel.js +59 -1
- package/src/BookReader/Mode1Up.js +5 -0
- package/src/BookReader/Mode1UpLit.js +19 -73
- 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
- package/tests/jest/setup.js +3 -0
@@ -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
|
+
}
|