Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions src/BookReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { DEFAULT_OPTIONS, OptionsParseError } from './BookReader/options.js';
/** @typedef {import('./BookReader/options.js').BookReaderOptions} BookReaderOptions */
/** @typedef {import('./BookReader/options.js').ReductionFactor} ReductionFactor */
/** @typedef {import('./BookReader/BookModel.js').PageIndex} PageIndex */
/** @typedef {import('./BookReader/BookModel.js').PageModel} PageModel */
import { EVENTS } from './BookReader/events.js';
import { Toolbar } from './BookReader/Toolbar/Toolbar.js';
import { BookModel } from './BookReader/BookModel.js';
Expand Down Expand Up @@ -1147,22 +1148,23 @@ BookReader.prototype._isIndexDisplayed = function(index) {
* Changes the current page
* @param {PageIndex | 'left' | 'right' | 'next' | 'prev'} indexOrDirection
* @param {object} options
* @param {boolean} [options.allowUnviewable] - whether to allow jumping to unviewable pages; default false
* @param {number} [options.pageX] Position on page ; not implemented
* @param {number} [options.pageY] Position on page ; not implemented
* @param {boolean} [options.noAnimate]
* @param {number | 'fast' | 'slow'} [options.flipSpeed]
* @param {boolean} [options.ariaLive]
* @param {boolean} [options.triggerStop] - whether to trigger the stop event; default true; maybe deprecated?
*/
BookReader.prototype.jumpToIndex = function(indexOrDirection, {pageX = 0, pageY = 0, noAnimate = false, flipSpeed = null, ariaLive = false, triggerStop = true} = {}) {
BookReader.prototype.jumpToIndex = function(indexOrDirection, {pageX = 0, pageY = 0, noAnimate = false, flipSpeed = null, ariaLive = false, triggerStop = true, allowUnviewable = false} = {}) {
const page = this.activeMode.parsePageSpecifier(indexOrDirection);
flipSpeed = utils.parseAnimationSpeed(flipSpeed) || this.flipSpeed;
if (!page || page.index == this.currentIndex()) {
return;
}

// Don't jump into specific unviewable page
if (!page.isViewable && page.unviewablesStart != page.index) {
if (!allowUnviewable && !page.isViewable && page.unviewablesStart != page.index) {
// If already in unviewable range, jump to end of that range
const alreadyInPreview = this._isIndexDisplayed(page.unviewablesStart);
const newIndex = alreadyInPreview ? page.findNext({ combineConsecutiveUnviewables: true })?.index : page.unviewablesStart;
Expand Down Expand Up @@ -1981,6 +1983,29 @@ BookReader.prototype.queryStringFromParams = function(
return result ? `?${result}` : '';
};

/**
* Tries to open the slot for the given page by requesting the server to make it viewable.
* @param {PageModel} page
*/
BookReader.prototype.tryOpenSlotForPage = async function(page) {
if (page.isViewable) return;
const resp = await fetch('/services/bookreader/request_page?' + new URLSearchParams({
id: this.options.bookId,
subprefix: this.options.subPrefix,
leafNum: page.leafNum,
})).then(r => r.json());

for (const leafNum of resp.value) {
this.book.getPage(this.book.leafNumToIndex(leafNum)).makeViewable();
}

// Trigger an update of book
this._modes.mode1Up.mode1UpLit.updatePages();
if (this.activeMode == this._modes.mode1Up) {
await this._modes.mode1Up.mode1UpLit.updateComplete;
}
};

/**
* Helper to select within instance's elements
*/
Expand Down
7 changes: 7 additions & 0 deletions src/plugins/plugin.text_selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ export class TextSelectionPlugin extends BookReaderPlugin {
}
}
});

// Now jump to the page and open a slot if necessary
const page = this.br.book.getPage(this.targetTextFragment.pageIndex);
if (!page.isViewable) {
this.br.tryOpenSlotForPage(page)
.then(() => this.br.jumpToIndex(page.index, { ariaLive: true, allowUnviewable: true }));
}
}
}

Expand Down
40 changes: 4 additions & 36 deletions src/plugins/search/plugin.search.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { applyVariables } from '../../util/strings.js';
import { toISO6391 } from '../tts/utils.js';
/** @typedef {import('../../BookReader/PageContainer').PageContainer} PageContainer */
/** @typedef {import('../../BookReader/BookModel').PageIndex} PageIndex */
/** @typedef {import('../../BookReader/BookModel').PageModel} PageModel */
/** @typedef {import('../../BookReader/BookModel').LeafNum} LeafNum */
/** @typedef {import('../../BookReader/BookModel').PageNumString} PageNumString */

Expand Down Expand Up @@ -341,43 +342,10 @@ export class SearchPlugin extends BookReaderPlugin {
const match = this.searchResults?.matches[matchIndex];
const book = this.br.book;
const pageIndex = book.leafNumToIndex(match.par[0].page);
const page = book.getPage(pageIndex);
const page = /** @type {PageModel} */(book.getPage(pageIndex));
const onNearbyPage = Math.abs(this.br.currentIndex() - pageIndex) < 3;
let makeUnviewableAtEnd = false;
if (!page.isViewable) {
const resp = await fetch('/services/bookreader/request_page?' + new URLSearchParams({
id: this.br.options.bookId,
subprefix: this.br.options.subPrefix,
leafNum: page.leafNum,
})).then(r => r.json());

for (const leafNum of resp.value) {
book.getPage(book.leafNumToIndex(leafNum)).makeViewable();
}

// not able to show page; make the page viewable anyways so that it can
// actually open. On IA, it has a fallback to a special error page.
if (!resp.value.length) {
book.getPage(pageIndex).makeViewable();
makeUnviewableAtEnd = true;
}

// Trigger an update of book
this.br._modes.mode1Up.mode1UpLit.updatePages();
if (this.br.activeMode == this.br._modes.mode1Up) {
await this.br._modes.mode1Up.mode1UpLit.updateComplete;
}
}
/* this updates the URL */
if (!this.br._isIndexDisplayed(pageIndex)) {
this.suppressFragmentChange = false;
this.br.jumpToIndex(pageIndex, { ariaLive: true });
}

// Reset it to unviewable if it wasn't resolved
if (makeUnviewableAtEnd) {
book.getPage(pageIndex).makeViewable(false);
}
await this.br.tryOpenSlotForPage(page);
this.br.jumpToIndex(page.index, { ariaLive: true, allowUnviewable: true });

// Scroll/flash in the ui
const $boxes = await poll(() => $(`rect.match-index-${match.matchIndex}`), { until: result => result.length > 0 });
Expand Down
Loading