@internetarchive/bookreader 5.0.0-5 → 5.0.0-50-a1
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/.eslintrc.js +17 -15
- package/.github/workflows/node.js.yml +77 -6
- package/.github/workflows/npm-publish.yml +6 -20
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +131 -339
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.LICENSE.txt +24 -0
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +1493 -0
- package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +17 -0
- package/BookReader/ia-bookreader-bundle.js.map +1 -0
- package/BookReader/icons/close-circle-dark.svg +1 -0
- package/BookReader/icons/magnify-minus.svg +1 -1
- package/BookReader/icons/magnify-plus.svg +1 -1
- package/BookReader/icons/pause.svg +1 -1
- package/BookReader/icons/playback-speed.svg +1 -1
- package/BookReader/icons/read-aloud.svg +1 -1
- package/BookReader/icons/voice.svg +1 -0
- package/BookReader/images/BRicons.svg +2 -2
- package/BookReader/images/books_graphic.svg +1 -1
- package/BookReader/images/icon_book.svg +1 -1
- package/BookReader/images/icon_gear.svg +1 -1
- package/BookReader/images/icon_info.svg +1 -1
- package/BookReader/images/icon_playback-rate.svg +1 -1
- package/BookReader/images/icon_search_button.svg +1 -1
- package/BookReader/images/icon_share.svg +1 -1
- package/BookReader/images/icon_speaker.svg +1 -1
- package/BookReader/images/icon_speaker_open.svg +1 -1
- package/BookReader/images/marker_chap-off.svg +1 -1
- package/BookReader/images/marker_chap-on.svg +1 -1
- package/BookReader/images/marker_srch-on.svg +1 -1
- package/BookReader/jquery-3.js +2 -0
- package/BookReader/jquery-3.js.LICENSE.txt +24 -0
- 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.chapters.js +1 -1
- package/BookReader/plugins/plugin.chapters.js.map +1 -1
- package/BookReader/plugins/plugin.iframe.js +1 -1
- package/BookReader/plugins/plugin.iframe.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/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
- package/BookReader/webcomponents-bundle.js +3 -0
- package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
- package/BookReader/webcomponents-bundle.js.map +1 -0
- package/BookReaderDemo/BookReaderDemo.css +14 -1
- package/BookReaderDemo/IADemoBr.js +148 -0
- package/BookReaderDemo/demo-advanced.html +2 -2
- package/BookReaderDemo/demo-autoplay.html +2 -1
- package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
- package/BookReaderDemo/demo-fullscreen-mobile.html +2 -1
- package/BookReaderDemo/demo-fullscreen.html +2 -1
- package/BookReaderDemo/demo-iiif.html +2 -1
- package/BookReaderDemo/demo-internetarchive.html +84 -17
- package/BookReaderDemo/demo-multiple.html +2 -1
- package/BookReaderDemo/demo-preview-pages.html +2 -1
- package/BookReaderDemo/demo-simple.html +2 -1
- package/BookReaderDemo/demo-vendor-fullscreen.html +2 -1
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +2 -1
- package/BookReaderDemo/immersion-mode.html +2 -1
- package/BookReaderDemo/toggle_controls.html +2 -1
- package/BookReaderDemo/view_mode.html +2 -1
- package/BookReaderDemo/viewmode-cycle.html +2 -3
- package/CHANGELOG.md +202 -0
- package/README.md +14 -1
- package/babel.config.js +18 -0
- package/codecov.yml +6 -0
- package/index.html +3 -0
- package/jsconfig.json +19 -0
- package/package.json +66 -56
- package/renovate.json +52 -0
- package/scripts/preversion.js +4 -1
- package/src/BookNavigator/assets/bookmark-colors.js +1 -1
- package/src/BookNavigator/assets/button-base.js +9 -2
- package/src/BookNavigator/assets/ia-logo.js +17 -0
- package/src/BookNavigator/assets/icon_checkmark.js +1 -1
- package/src/BookNavigator/assets/icon_close.js +1 -1
- package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
- package/src/BookNavigator/assets/icon_volumes.js +11 -0
- package/src/BookNavigator/book-navigator.js +583 -0
- package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
- package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
- package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
- package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +21 -8
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +102 -66
- package/src/BookNavigator/delete-modal-actions.js +1 -1
- package/src/BookNavigator/downloads/downloads-provider.js +36 -21
- package/src/BookNavigator/downloads/downloads.js +41 -25
- package/src/BookNavigator/search/a-search-result.js +18 -13
- package/src/BookNavigator/search/search-provider.js +80 -28
- package/src/BookNavigator/search/search-results.js +10 -18
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
- package/src/BookNavigator/volumes/volumes-provider.js +114 -0
- package/src/BookNavigator/volumes/volumes.js +188 -0
- package/src/BookReader/BookModel.js +0 -29
- package/src/BookReader/DebugConsole.js +3 -3
- package/src/BookReader/DragScrollable.js +233 -0
- package/src/BookReader/Mode1Up.js +51 -351
- package/src/BookReader/Mode1UpLit.js +441 -0
- package/src/BookReader/Mode2Up.js +120 -105
- package/src/BookReader/ModeSmoothZoom.js +179 -0
- package/src/BookReader/ModeThumb.js +17 -11
- package/src/BookReader/Navbar/Navbar.js +10 -36
- package/src/BookReader/PageContainer.js +69 -6
- package/src/BookReader/ReduceSet.js +1 -1
- package/src/BookReader/Toolbar/Toolbar.js +10 -37
- package/src/BookReader/options.js +10 -0
- package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
- package/src/BookReader/utils/ScrollClassAdder.js +31 -0
- package/src/BookReader/utils.js +92 -13
- package/src/BookReader.js +431 -620
- package/src/assets/icons/close-circle-dark.svg +1 -0
- package/src/assets/icons/magnify-minus.svg +3 -7
- package/src/assets/icons/magnify-plus.svg +3 -7
- package/src/assets/icons/voice.svg +1 -0
- package/src/css/BookReader.scss +0 -12
- package/src/css/_BRComponent.scss +1 -1
- package/src/css/_BRmain.scss +19 -24
- package/src/css/_BRnav.scss +4 -26
- package/src/css/_BRpages.scss +35 -0
- package/src/css/_BRsearch.scss +25 -216
- package/src/css/_TextSelection.scss +14 -17
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +17 -5
- package/src/css/_icons.scss +6 -0
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.autoplay.js +4 -4
- package/src/plugins/plugin.chapters.js +28 -35
- package/src/plugins/plugin.mobile_nav.js +11 -10
- package/src/plugins/plugin.resume.js +3 -3
- package/src/plugins/plugin.text_selection.js +26 -39
- package/src/plugins/plugin.vendor-fullscreen.js +4 -4
- package/src/plugins/search/plugin.search.js +174 -116
- package/src/plugins/search/view.js +63 -179
- package/src/plugins/tts/AbstractTTSEngine.js +46 -37
- package/src/plugins/tts/FestivalTTSEngine.js +13 -14
- package/src/plugins/tts/PageChunk.js +15 -21
- package/src/plugins/tts/PageChunkIterator.js +8 -12
- package/src/plugins/tts/WebTTSEngine.js +66 -69
- package/src/plugins/tts/plugin.tts.js +92 -109
- package/src/plugins/tts/utils.js +0 -9
- package/src/plugins/url/UrlPlugin.js +184 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
- package/src/util/manifestGenerator.js +0 -0
- package/tests/e2e/README.md +37 -0
- package/tests/e2e/autoplay.test.js +2 -2
- package/tests/e2e/base.test.js +7 -7
- package/tests/e2e/helpers/base.js +9 -3
- package/tests/e2e/helpers/debug.js +1 -1
- package/tests/e2e/helpers/desktopSearch.js +14 -13
- package/tests/e2e/helpers/mobileSearch.js +3 -3
- package/tests/e2e/helpers/params.js +17 -0
- package/tests/e2e/models/Navigation.js +13 -4
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +38 -33
- package/tests/jest/BookNavigator/book-navigator.test.js +634 -0
- package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
- package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
- package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
- package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
- package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
- package/tests/{karma/BookNavigator → jest/BookNavigator/search}/search-results.test.js +102 -58
- package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
- package/tests/jest/BookNavigator/volumes/volumes-provider.test.js +184 -0
- package/tests/jest/BookNavigator/volumes/volumes.test.js +97 -0
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +34 -14
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
- package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
- package/tests/jest/BookReader/Mode1UpLit.test.js +92 -0
- package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +36 -15
- package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
- package/tests/jest/BookReader/ModeThumb.test.js +71 -0
- package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
- package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
- package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
- package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
- package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
- package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
- package/tests/jest/BookReader/utils.test.js +186 -0
- package/tests/jest/BookReader.keyboard.test.js +190 -0
- package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
- package/tests/{BookReader.test.js → jest/BookReader.test.js} +18 -37
- package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
- package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +10 -11
- package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
- package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
- package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
- package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
- package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +63 -47
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +35 -6
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +9 -9
- package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
- package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
- package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
- package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +1 -1
- package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -28
- package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
- package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
- package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
- package/tests/{util → jest/util}/docCookies.test.js +1 -1
- package/tests/{util → jest/util}/strings.test.js +1 -1
- package/tests/{utils.js → jest/utils.js} +38 -0
- package/webpack.config.js +11 -5
- package/.babelrc +0 -12
- package/.dependabot/config.yml +0 -6
- package/.testcaferc.json +0 -5
- package/BookReader/bookreader-component-bundle.js +0 -1450
- package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
- package/BookReader/bookreader-component-bundle.js.map +0 -1
- package/BookReader/jquery-1.10.1.js +0 -2
- package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
- package/BookReader/plugins/plugin.menu_toggle.js +0 -2
- package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
- package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
- package/karma.conf.js +0 -23
- package/src/BookNavigator/BookModel.js +0 -14
- package/src/BookNavigator/BookNavigator.js +0 -438
- package/src/BookNavigator/assets/book-loader.js +0 -27
- package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
- package/src/BookReaderComponent/BookReaderComponent.js +0 -112
- package/src/ItemNavigator/ItemNavigator.js +0 -372
- package/src/ItemNavigator/providers/sharing.js +0 -29
- package/src/Layers/sharing/sharing-provider.js +0 -22
- package/src/dragscrollable-br.js +0 -261
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- package/src/plugins/plugin.bookmarks.js +0 -50
- package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
- package/tests/BookReader/Mode1Up.test.js +0 -164
- package/tests/BookReader/utils.test.js +0 -109
- package/tests/e2e/ia-production/ia-prod-base.js +0 -17
- package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
- package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -1,3 +1,4 @@
|
|
1
|
+
// @ts-check
|
1
2
|
/* global BookReader */
|
2
3
|
/**
|
3
4
|
* Plugin for Archive.org book search
|
@@ -20,8 +21,16 @@
|
|
20
21
|
* the book has not had OCR text indexed yet. Receives `instance`
|
21
22
|
* @event BookReader:SearchCallbackEmpty - When no results found. Receives
|
22
23
|
* `instance`
|
24
|
+
* @event BookReader:SearchCanceled - When no results found. Receives
|
25
|
+
* `instance`
|
23
26
|
*/
|
27
|
+
import { poll } from '../../BookReader/utils.js';
|
28
|
+
import { renderBoxesInPageContainerLayer } from '../../BookReader/PageContainer.js';
|
24
29
|
import SearchView from './view.js';
|
30
|
+
/** @typedef {import('../../BookReader/PageContainer').PageContainer} PageContainer */
|
31
|
+
/** @typedef {import('../../BookReader/BookModel').PageIndex} PageIndex */
|
32
|
+
/** @typedef {import('../../BookReader/BookModel').LeafNum} LeafNum */
|
33
|
+
/** @typedef {import('../../BookReader/BookModel').PageNumString} PageNumString */
|
25
34
|
|
26
35
|
jQuery.extend(BookReader.defaultOptions, {
|
27
36
|
server: 'ia600609.us.archive.org',
|
@@ -42,7 +51,6 @@ BookReader.prototype.setup = (function (super_) {
|
|
42
51
|
this.searchResults = null;
|
43
52
|
this.searchInsideUrl = options.searchInsideUrl;
|
44
53
|
this.enableSearch = options.enableSearch;
|
45
|
-
this.goToFirstResult = false;
|
46
54
|
|
47
55
|
// Base server used by some api calls
|
48
56
|
this.bookId = options.bookId;
|
@@ -50,11 +58,14 @@ BookReader.prototype.setup = (function (super_) {
|
|
50
58
|
this.subPrefix = options.subPrefix;
|
51
59
|
this.bookPath = options.bookPath;
|
52
60
|
|
53
|
-
|
54
|
-
this.
|
55
|
-
|
56
|
-
|
57
|
-
}
|
61
|
+
this.searchXHR = null;
|
62
|
+
this._cancelSearch.bind(this);
|
63
|
+
this.cancelSearchRequest.bind(this);
|
64
|
+
|
65
|
+
/** @type { {[pageIndex: number]: SearchInsideMatchBox[]} } */
|
66
|
+
this._searchBoxesByIndex = {};
|
67
|
+
|
68
|
+
this.searchView = undefined;
|
58
69
|
};
|
59
70
|
})(BookReader.prototype.setup);
|
60
71
|
|
@@ -62,28 +73,31 @@ BookReader.prototype.setup = (function (super_) {
|
|
62
73
|
BookReader.prototype.init = (function (super_) {
|
63
74
|
return function () {
|
64
75
|
super_.call(this);
|
65
|
-
|
76
|
+
// give SearchView the most complete bookreader state
|
77
|
+
this.searchView = new SearchView({
|
78
|
+
br: this,
|
79
|
+
searchCancelledCallback: () => {
|
80
|
+
this._cancelSearch();
|
81
|
+
this.trigger('SearchCanceled', { term: this.searchTerm, instance: this });
|
82
|
+
}
|
83
|
+
});
|
66
84
|
if (this.options.enableSearch && this.options.initialSearchTerm) {
|
85
|
+
/**
|
86
|
+
* this.search() take two parameter
|
87
|
+
* 1. this.options.initialSearchTerm - search term
|
88
|
+
* 2. {
|
89
|
+
* goToFirstResult: this.options.goToFirstResult,
|
90
|
+
* suppressFragmentChange: false // always want to change fragment in URL
|
91
|
+
* }
|
92
|
+
*/
|
67
93
|
this.search(
|
68
94
|
this.options.initialSearchTerm,
|
69
|
-
{ goToFirstResult: this.goToFirstResult, suppressFragmentChange:
|
95
|
+
{ goToFirstResult: this.options.goToFirstResult, suppressFragmentChange: false }
|
70
96
|
);
|
71
97
|
}
|
72
98
|
};
|
73
99
|
})(BookReader.prototype.init);
|
74
100
|
|
75
|
-
/** @override */
|
76
|
-
BookReader.prototype.buildMobileDrawerElement = (function (super_) {
|
77
|
-
return function () {
|
78
|
-
const $el = super_.call(this);
|
79
|
-
if (!this.enableSearch) { return; }
|
80
|
-
if (this.searchView.dom.mobileSearch) {
|
81
|
-
$el.find('.BRmobileMenu__moreInfoRow').after(this.searchView.dom.mobileSearch);
|
82
|
-
}
|
83
|
-
return $el;
|
84
|
-
};
|
85
|
-
})(BookReader.prototype.buildMobileDrawerElement);
|
86
|
-
|
87
101
|
/** @override */
|
88
102
|
BookReader.prototype.buildToolbarElement = (function (super_) {
|
89
103
|
return function () {
|
@@ -96,6 +110,25 @@ BookReader.prototype.buildToolbarElement = (function (super_) {
|
|
96
110
|
};
|
97
111
|
})(BookReader.prototype.buildToolbarElement);
|
98
112
|
|
113
|
+
/** @override */
|
114
|
+
BookReader.prototype._createPageContainer = (function (super_) {
|
115
|
+
return function (index) {
|
116
|
+
const pageContainer = super_.call(this, index);
|
117
|
+
if (this.enableSearch && pageContainer.page && index in this._searchBoxesByIndex) {
|
118
|
+
const pageIndex = pageContainer.page.index;
|
119
|
+
const boxes = this._searchBoxesByIndex[pageIndex];
|
120
|
+
renderBoxesInPageContainerLayer(
|
121
|
+
'searchHiliteLayer',
|
122
|
+
boxes,
|
123
|
+
pageContainer.page,
|
124
|
+
pageContainer.$container[0],
|
125
|
+
boxes.map(b => `match-index-${b.matchIndex}`),
|
126
|
+
);
|
127
|
+
}
|
128
|
+
return pageContainer;
|
129
|
+
};
|
130
|
+
})(BookReader.prototype._createPageContainer);
|
131
|
+
|
99
132
|
/**
|
100
133
|
* @typedef {object} SearchOptions
|
101
134
|
* @property {boolean} goToFirstResult
|
@@ -110,7 +143,7 @@ BookReader.prototype.buildToolbarElement = (function (super_) {
|
|
110
143
|
* @param {string} term
|
111
144
|
* @param {SearchOptions} overrides
|
112
145
|
*/
|
113
|
-
BookReader.prototype.search = function(term = '', overrides = {}) {
|
146
|
+
BookReader.prototype.search = async function(term = '', overrides = {}) {
|
114
147
|
/** @type {SearchOptions} */
|
115
148
|
const defaultOptions = {
|
116
149
|
goToFirstResult: false, /* jump to the first result (default=false) */
|
@@ -122,6 +155,7 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
122
155
|
};
|
123
156
|
const options = jQuery.extend({}, defaultOptions, overrides);
|
124
157
|
this.suppressFragmentChange = options.suppressFragmentChange;
|
158
|
+
this.searchCancelled = false;
|
125
159
|
|
126
160
|
// strip slashes, since this goes in the url
|
127
161
|
this.searchTerm = term.replace(/\//g, ' ');
|
@@ -157,7 +191,10 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
157
191
|
|
158
192
|
const url = `${baseUrl}${paramStr}`;
|
159
193
|
|
160
|
-
const
|
194
|
+
const callSearchResultsCallback = (searchInsideResults) => {
|
195
|
+
if (this.searchCancelled) {
|
196
|
+
return;
|
197
|
+
}
|
161
198
|
const responseHasError = searchInsideResults.error || !searchInsideResults.matches.length;
|
162
199
|
const hasCustomError = typeof options.error === 'function';
|
163
200
|
const hasCustomSuccess = typeof options.success === 'function';
|
@@ -173,11 +210,39 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
173
210
|
}
|
174
211
|
};
|
175
212
|
|
176
|
-
this.trigger('SearchStarted', { term: this.searchTerm });
|
177
|
-
|
213
|
+
this.trigger('SearchStarted', { term: this.searchTerm, instance: this });
|
214
|
+
callSearchResultsCallback(await $.ajax({
|
178
215
|
url: url,
|
179
|
-
dataType: 'jsonp'
|
180
|
-
|
216
|
+
dataType: 'jsonp',
|
217
|
+
cache: true,
|
218
|
+
beforeSend: xhr => { this.searchXHR = xhr; },
|
219
|
+
}));
|
220
|
+
};
|
221
|
+
|
222
|
+
/**
|
223
|
+
* cancels AJAX Call
|
224
|
+
* emits custom event
|
225
|
+
*/
|
226
|
+
BookReader.prototype._cancelSearch = function () {
|
227
|
+
this.searchXHR?.abort();
|
228
|
+
this.searchView.clearSearchFieldAndResults(false);
|
229
|
+
this.searchTerm = '';
|
230
|
+
this.searchXHR = null;
|
231
|
+
this.searchCancelled = true;
|
232
|
+
this.searchResults = [];
|
233
|
+
};
|
234
|
+
|
235
|
+
/**
|
236
|
+
* External function to cancel search
|
237
|
+
* checks for term & xhr in flight before running
|
238
|
+
*/
|
239
|
+
BookReader.prototype.cancelSearchRequest = function () {
|
240
|
+
this.searchCancelled = true;
|
241
|
+
if (this.searchXHR !== null) {
|
242
|
+
this._cancelSearch();
|
243
|
+
this.searchView.toggleSearchPending();
|
244
|
+
this.trigger('SearchCanceled', { term: this.searchTerm, instance: this });
|
245
|
+
}
|
181
246
|
};
|
182
247
|
|
183
248
|
/**
|
@@ -188,10 +253,13 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
188
253
|
* @property {number} b
|
189
254
|
* @property {number} t
|
190
255
|
* @property {HTMLDivElement} [div]
|
256
|
+
* @property {number} matchIndex This is a fake field! not part of the API response. The index of the match that contains this box in total search results matches.
|
191
257
|
*/
|
192
258
|
|
193
259
|
/**
|
194
260
|
* @typedef {object} SearchInsideMatch
|
261
|
+
* @property {number} matchIndex This is a fake field! Not part of the API response. It is added by the JS.
|
262
|
+
* @property {string} displayPageNumber (fake field) The page number as it should be displayed in the UI.
|
195
263
|
* @property {string} text
|
196
264
|
* @property {Array<{ page: number, boxes: SearchInsideMatchBox[] }>} par
|
197
265
|
*/
|
@@ -203,23 +271,42 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
203
271
|
* @property {boolean} indexed
|
204
272
|
*/
|
205
273
|
|
274
|
+
/**
|
275
|
+
* Attach some fields to search inside results
|
276
|
+
* @param {SearchInsideResults} results
|
277
|
+
* @param {(pageNum: LeafNum) => PageNumString} displayPageNumberFn
|
278
|
+
*/
|
279
|
+
export function marshallSearchResults(results, displayPageNumberFn) {
|
280
|
+
// Attach matchIndex to a few things to make it easier to identify
|
281
|
+
// an active/selected match
|
282
|
+
for (const [index, match] of results.matches.entries()) {
|
283
|
+
match.matchIndex = index;
|
284
|
+
match.displayPageNumber = displayPageNumberFn(match.par[0].page);
|
285
|
+
for (const par of match.par) {
|
286
|
+
for (const box of par.boxes) {
|
287
|
+
box.matchIndex = index;
|
288
|
+
}
|
289
|
+
}
|
290
|
+
}
|
291
|
+
}
|
292
|
+
|
206
293
|
/**
|
207
294
|
* Search Results return handler
|
208
|
-
* @callback
|
209
295
|
* @param {SearchInsideResults} results
|
210
296
|
* @param {object} options
|
211
297
|
* @param {boolean} options.goToFirstResult
|
212
298
|
*/
|
213
299
|
BookReader.prototype.BRSearchCallback = function(results, options) {
|
214
|
-
this.
|
300
|
+
marshallSearchResults(results, pageNum => this.book.getPageNum(this.book.leafNumToIndex(pageNum)));
|
301
|
+
this.searchResults = results || [];
|
215
302
|
|
216
303
|
this.updateSearchHilites();
|
217
304
|
this.removeProgressPopup();
|
218
305
|
if (options.goToFirstResult) {
|
219
|
-
this._searchPluginGoToResult(
|
306
|
+
this._searchPluginGoToResult(0);
|
220
307
|
}
|
221
308
|
this.trigger('SearchCallback', { results, options, instance: this });
|
222
|
-
}
|
309
|
+
};
|
223
310
|
|
224
311
|
/**
|
225
312
|
* Main search results error handler
|
@@ -259,95 +346,41 @@ BookReader.prototype._BRSearchCallbackError = function(results) {
|
|
259
346
|
* updates search on-page highlights controller
|
260
347
|
*/
|
261
348
|
BookReader.prototype.updateSearchHilites = function() {
|
262
|
-
|
263
|
-
|
264
|
-
|
349
|
+
/** @type {SearchInsideMatch[]} */
|
350
|
+
const matches = this.searchResults?.matches || [];
|
351
|
+
/** @type { {[pageIndex: number]: SearchInsideMatchBox[]} } */
|
352
|
+
const boxesByIndex = {};
|
353
|
+
|
354
|
+
// Clear any existing svg layers
|
355
|
+
this.removeSearchHilites();
|
356
|
+
|
357
|
+
// Group by pageIndex
|
358
|
+
for (const match of matches) {
|
359
|
+
for (const box of match.par[0].boxes) {
|
360
|
+
const pageIndex = this.book.leafNumToIndex(box.page);
|
361
|
+
const pageBoxes = boxesByIndex[pageIndex] || (boxesByIndex[pageIndex] = []);
|
362
|
+
pageBoxes.push(box);
|
363
|
+
}
|
265
364
|
}
|
266
|
-
this.updateSearchHilites1UP();
|
267
|
-
};
|
268
365
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
const pageIsInView = jQuery.inArray(pageIndex, this.displayedIndices) >= 0;
|
279
|
-
if (pageIsInView) {
|
280
|
-
if (!box.div) {
|
281
|
-
//create a div for the search highlight, and stash it in the box object
|
282
|
-
box.div = document.createElement('div');
|
283
|
-
$(box.div).prop('className', 'BookReaderSearchHilite').appendTo(this.$(`.pagediv${pageIndex}`));
|
284
|
-
}
|
285
|
-
const page = this._models.book.getPage(pageIndex);
|
286
|
-
const highlight = {
|
287
|
-
width: this._modes.mode1Up.physicalInchesToDisplayPixels((box.r - box.l) / page.ppi),
|
288
|
-
height: this._modes.mode1Up.physicalInchesToDisplayPixels((box.b - box.t) / page.ppi),
|
289
|
-
left: this._modes.mode1Up.physicalInchesToDisplayPixels(box.l / page.ppi),
|
290
|
-
top: this._modes.mode1Up.physicalInchesToDisplayPixels(box.t / page.ppi),
|
291
|
-
};
|
292
|
-
$(box.div).css(highlight);
|
293
|
-
} else {
|
294
|
-
if (box.div) {
|
295
|
-
$(box.div).remove();
|
296
|
-
box.div = null;
|
297
|
-
}
|
298
|
-
}
|
299
|
-
});
|
300
|
-
});
|
301
|
-
};
|
302
|
-
|
303
|
-
/**
|
304
|
-
* update search on-page highlights in 2up mode
|
305
|
-
*/
|
306
|
-
BookReader.prototype.updateSearchHilites2UP = function() {
|
307
|
-
const results = this.searchResults;
|
366
|
+
// update any already created pages
|
367
|
+
for (const [pageIndexString, boxes] of Object.entries(boxesByIndex)) {
|
368
|
+
const pageIndex = parseFloat(pageIndexString);
|
369
|
+
const page = this.book.getPage(pageIndex);
|
370
|
+
const pageContainers = this.getActivePageContainerElementsForIndex(pageIndex);
|
371
|
+
for (const container of pageContainers) {
|
372
|
+
renderBoxesInPageContainerLayer('searchHiliteLayer', boxes, page, container, boxes.map(b => `match-index-${b.matchIndex}`));
|
373
|
+
}
|
374
|
+
}
|
308
375
|
|
309
|
-
|
310
|
-
|
311
|
-
const { matches } = results;
|
312
|
-
matches.forEach((match) => {
|
313
|
-
match.par[0].boxes.forEach(box => {
|
314
|
-
const pageIndex = this.leafNumToIndex(match.par[0].page);
|
315
|
-
const pageIsInView = jQuery.inArray(pageIndex, this.displayedIndices) >= 0;
|
316
|
-
const { isViewable } = this._models.book.getPage(pageIndex);
|
317
|
-
|
318
|
-
if (pageIsInView && isViewable) {
|
319
|
-
if (!box.div) {
|
320
|
-
//create a div for the search highlight, and stash it in the box object
|
321
|
-
box.div = document.createElement('div');
|
322
|
-
$(box.div).addClass('BookReaderSearchHilite')
|
323
|
-
.appendTo(this.refs.$brTwoPageView);
|
324
|
-
}
|
325
|
-
this.setHilightCss2UP(box.div, pageIndex, box.l, box.r, box.t, box.b);
|
326
|
-
} else {
|
327
|
-
// clear stale reference
|
328
|
-
if (box.div) {
|
329
|
-
$(box.div).remove();
|
330
|
-
box.div = null;
|
331
|
-
}
|
332
|
-
}
|
333
|
-
});
|
334
|
-
});
|
376
|
+
this._searchBoxesByIndex = boxesByIndex;
|
335
377
|
};
|
336
378
|
|
337
379
|
/**
|
338
380
|
* remove search highlights
|
339
381
|
*/
|
340
382
|
BookReader.prototype.removeSearchHilites = function() {
|
341
|
-
|
342
|
-
if (null == results || !results.matches) { return; }
|
343
|
-
results.matches.forEach(match => {
|
344
|
-
match.par[0].boxes.forEach(box => {
|
345
|
-
if (null != box.div) {
|
346
|
-
$(box.div).remove();
|
347
|
-
box.div = null;
|
348
|
-
}
|
349
|
-
});
|
350
|
-
});
|
383
|
+
$(this.getActivePageContainerElements()).find('.searchHiliteLayer').remove();
|
351
384
|
};
|
352
385
|
|
353
386
|
/**
|
@@ -355,11 +388,14 @@ BookReader.prototype.removeSearchHilites = function() {
|
|
355
388
|
* Goes to the page specified. If the page is not viewable, tries to load the page
|
356
389
|
* FIXME Most of this logic is IA specific, and should be less integrated into here
|
357
390
|
* or at least more configurable.
|
358
|
-
* @param {
|
391
|
+
* @param {number} matchIndex
|
359
392
|
*/
|
360
|
-
BookReader.prototype._searchPluginGoToResult = async function (
|
361
|
-
const
|
393
|
+
BookReader.prototype._searchPluginGoToResult = async function (matchIndex) {
|
394
|
+
const match = this.searchResults?.matches[matchIndex];
|
395
|
+
const book = this.book;
|
396
|
+
const pageIndex = book.leafNumToIndex(match.par[0].page);
|
362
397
|
const page = book.getPage(pageIndex);
|
398
|
+
const onNearbyPage = Math.abs(this.currentIndex() - pageIndex) < 3;
|
363
399
|
let makeUnviewableAtEnd = false;
|
364
400
|
if (!page.isViewable) {
|
365
401
|
const resp = await fetch('/services/bookreader/request_page?' + new URLSearchParams({
|
@@ -380,13 +416,35 @@ BookReader.prototype._searchPluginGoToResult = async function (pageIndex) {
|
|
380
416
|
}
|
381
417
|
}
|
382
418
|
/* this updates the URL */
|
383
|
-
this.
|
384
|
-
|
419
|
+
if (!this._isIndexDisplayed(pageIndex)) {
|
420
|
+
this.suppressFragmentChange = false;
|
421
|
+
this.jumpToIndex(pageIndex);
|
422
|
+
}
|
385
423
|
|
386
424
|
// Reset it to unviewable if it wasn't resolved
|
387
425
|
if (makeUnviewableAtEnd) {
|
388
426
|
book.getPage(pageIndex).makeViewable(false);
|
389
427
|
}
|
428
|
+
|
429
|
+
// Scroll/flash in the ui
|
430
|
+
const $boxes = await poll(() => $(`rect.match-index-${match.matchIndex}`), { until: result => result.length > 0 });
|
431
|
+
if ($boxes.length) {
|
432
|
+
$boxes.css('animation', 'none');
|
433
|
+
$boxes[0].scrollIntoView({
|
434
|
+
// Only vertically center the highlight if we're in 1up or in full screen. In
|
435
|
+
// 2up, if we're not fullscreen, the whole body gets scrolled around to try to
|
436
|
+
// center the highlight 🙄 See:
|
437
|
+
// https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move/11041376
|
438
|
+
// Note: nearest doesn't quite work great, because the ReadAloud toolbar is now
|
439
|
+
// full-width, and covers up the last line of the highlight.
|
440
|
+
block: this.constMode1up == this.mode || this.isFullscreenActive ? 'center' : 'nearest',
|
441
|
+
inline: 'center',
|
442
|
+
behavior: onNearbyPage ? 'smooth' : 'auto',
|
443
|
+
});
|
444
|
+
// wait for animation to start
|
445
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
446
|
+
$boxes.removeAttr("style");
|
447
|
+
}
|
390
448
|
};
|
391
449
|
|
392
450
|
/**
|
@@ -420,7 +478,7 @@ BookReader.prototype.searchHighlightVisible = function() {
|
|
420
478
|
|
421
479
|
results.matches.some(match => {
|
422
480
|
return match.par[0].boxes.some(box => {
|
423
|
-
const pageIndex = this.leafNumToIndex(box.page);
|
481
|
+
const pageIndex = this.book.leafNumToIndex(box.page);
|
424
482
|
if (jQuery.inArray(pageIndex, visiblePages) >= 0) {
|
425
483
|
return true;
|
426
484
|
}
|