@internetarchive/bookreader 5.0.0-8-multiple-files → 5.0.0-80
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 +78 -6
- package/.github/workflows/npm-publish.yml +6 -20
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +442 -1393
- package/BookReader/BookReader.js +2 -21564
- package/BookReader/BookReader.js.LICENSE.txt +20 -20
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +1782 -0
- package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -0
- package/BookReader/ia-bookreader-bundle.js.map +1 -0
- package/BookReader/icons/1up.svg +1 -12
- package/BookReader/icons/2up.svg +1 -15
- package/BookReader/icons/advance.svg +3 -26
- package/BookReader/icons/chevron-right.svg +1 -1
- package/BookReader/icons/close-circle-dark.svg +1 -0
- package/BookReader/icons/close-circle.svg +1 -1
- package/BookReader/icons/fullscreen.svg +1 -17
- package/BookReader/icons/fullscreen_exit.svg +1 -17
- package/BookReader/icons/hamburger.svg +1 -15
- package/BookReader/icons/left-arrow.svg +1 -12
- package/BookReader/icons/magnify-minus.svg +1 -16
- package/BookReader/icons/magnify-plus.svg +1 -17
- package/BookReader/icons/magnify.svg +1 -15
- package/BookReader/icons/pause.svg +1 -23
- package/BookReader/icons/play.svg +1 -22
- package/BookReader/icons/playback-speed.svg +1 -34
- package/BookReader/icons/read-aloud.svg +1 -22
- package/BookReader/icons/review.svg +3 -22
- package/BookReader/icons/thumbnails.svg +1 -17
- package/BookReader/icons/voice.svg +1 -0
- package/BookReader/icons/volume-full.svg +1 -22
- package/BookReader/images/BRicons.svg +5 -94
- package/BookReader/images/books_graphic.svg +1 -177
- package/BookReader/images/icon_book.svg +1 -12
- package/BookReader/images/icon_bookmark.svg +1 -12
- package/BookReader/images/icon_gear.svg +1 -14
- package/BookReader/images/icon_hamburger.svg +1 -20
- package/BookReader/images/icon_home.svg +1 -21
- package/BookReader/images/icon_info.svg +1 -11
- package/BookReader/images/icon_one_page.svg +1 -8
- package/BookReader/images/icon_pause.svg +1 -1
- package/BookReader/images/icon_play.svg +1 -1
- package/BookReader/images/icon_playback-rate.svg +1 -15
- package/BookReader/images/icon_search_button.svg +1 -8
- package/BookReader/images/icon_share.svg +1 -9
- package/BookReader/images/icon_skip-ahead.svg +1 -6
- package/BookReader/images/icon_skip-back.svg +2 -13
- package/BookReader/images/icon_speaker.svg +1 -18
- package/BookReader/images/icon_speaker_open.svg +1 -10
- package/BookReader/images/icon_thumbnails.svg +1 -12
- package/BookReader/images/icon_toc.svg +1 -5
- package/BookReader/images/icon_two_pages.svg +1 -9
- package/BookReader/images/marker_chap-off.svg +1 -11
- package/BookReader/images/marker_chap-on.svg +1 -11
- package/BookReader/images/marker_srch-on.svg +1 -11
- package/BookReader/jquery-3.js +2 -0
- package/BookReader/jquery-3.js.LICENSE.txt +24 -0
- package/BookReader/plugins/plugin.archive_analytics.js +1 -172
- package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
- package/BookReader/plugins/plugin.autoplay.js +1 -165
- package/BookReader/plugins/plugin.autoplay.js.map +1 -1
- package/BookReader/plugins/plugin.chapters.js +22 -301
- package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.chapters.js.map +1 -1
- package/BookReader/plugins/plugin.iframe.js +1 -74
- package/BookReader/plugins/plugin.iframe.js.map +1 -1
- package/BookReader/plugins/plugin.iiif.js +2 -0
- package/BookReader/plugins/plugin.iiif.js.map +1 -0
- package/BookReader/plugins/plugin.resume.js +1 -368
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +2 -1420
- package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +2 -1080
- package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +2 -9193
- package/BookReader/plugins/plugin.tts.js.LICENSE.txt +2 -0
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReader/plugins/plugin.url.js +1 -269
- package/BookReader/plugins/plugin.url.js.map +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -379
- 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 +18 -19
- package/BookReaderDemo/BookReaderJSAdvanced.js +0 -3
- package/BookReaderDemo/BookReaderJSAutoplay.js +4 -1
- package/BookReaderDemo/BookReaderJSSimple.js +1 -0
- package/BookReaderDemo/IADemoBr.js +147 -0
- package/BookReaderDemo/demo-advanced.html +2 -2
- package/BookReaderDemo/demo-autoplay.html +2 -3
- package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
- package/BookReaderDemo/demo-fullscreen-mobile.html +3 -5
- package/BookReaderDemo/demo-fullscreen.html +2 -4
- package/BookReaderDemo/demo-iiif.html +99 -12
- package/BookReaderDemo/demo-internetarchive.html +214 -18
- 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 -4
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +2 -2
- package/BookReaderDemo/immersion-mode.html +2 -4
- package/BookReaderDemo/toggle_controls.html +3 -2
- package/BookReaderDemo/view_mode.html +2 -1
- package/BookReaderDemo/viewmode-cycle.html +2 -3
- package/CHANGELOG.md +545 -33
- package/README.md +14 -1
- package/babel.config.js +20 -0
- package/codecov.yml +6 -0
- package/index.html +4 -1
- package/jsconfig.json +19 -0
- package/netlify.toml +9 -0
- package/package.json +70 -60
- package/renovate.json +52 -0
- package/scripts/preversion.js +0 -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/book-navigator.js +590 -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 +27 -17
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +116 -67
- 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/search-provider.js +80 -28
- package/src/BookNavigator/search/search-results.js +28 -25
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/viewable-files.js +95 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
- package/src/BookReader/BookModel.js +64 -34
- package/src/BookReader/DragScrollable.js +233 -0
- package/src/BookReader/Mode1Up.js +56 -351
- package/src/BookReader/Mode1UpLit.js +388 -0
- package/src/BookReader/Mode2Up.js +73 -1318
- package/src/BookReader/Mode2UpLit.js +776 -0
- package/src/BookReader/ModeCoordinateSpace.js +29 -0
- package/src/BookReader/ModeSmoothZoom.js +312 -0
- package/src/BookReader/ModeThumb.js +18 -12
- package/src/BookReader/Navbar/Navbar.js +14 -40
- package/src/BookReader/PageContainer.js +81 -6
- package/src/BookReader/ReduceSet.js +1 -1
- package/src/BookReader/Toolbar/Toolbar.js +10 -37
- package/src/BookReader/events.js +2 -3
- package/src/BookReader/options.js +27 -2
- package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
- package/src/BookReader/utils/ScrollClassAdder.js +31 -0
- package/src/BookReader/utils/SelectionObserver.js +45 -0
- package/src/BookReader/utils.js +118 -13
- package/src/BookReader.js +446 -1062
- 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 +1 -17
- package/src/css/_BRBookmarks.scss +1 -1
- package/src/css/_BRComponent.scss +1 -1
- package/src/css/_BRmain.scss +33 -27
- package/src/css/_BRnav.scss +12 -39
- package/src/css/_BRpages.scss +149 -40
- package/src/css/_BRsearch.scss +68 -230
- package/src/css/_BRtoolbar.scss +5 -5
- package/src/css/_TextSelection.scss +87 -27
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +20 -7
- package/src/css/_icons.scss +7 -1
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.archive_analytics.js +3 -3
- package/src/plugins/plugin.autoplay.js +5 -11
- package/src/plugins/plugin.chapters.js +237 -191
- package/src/plugins/plugin.iiif.js +151 -0
- package/src/plugins/plugin.resume.js +3 -3
- package/src/plugins/plugin.text_selection.js +464 -134
- package/src/plugins/plugin.vendor-fullscreen.js +4 -4
- package/src/plugins/search/plugin.search.js +175 -120
- package/src/plugins/search/utils.js +43 -0
- package/src/plugins/search/view.js +64 -202
- package/src/plugins/tts/AbstractTTSEngine.js +71 -40
- 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 +87 -71
- package/src/plugins/tts/plugin.tts.js +96 -127
- package/src/plugins/tts/utils.js +15 -25
- package/src/plugins/url/UrlPlugin.js +191 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +45 -16
- package/src/util/browserSniffing.js +22 -0
- package/src/util/docCookies.js +21 -2
- package/tests/e2e/README.md +37 -0
- package/tests/e2e/autoplay.test.js +2 -2
- package/tests/e2e/base.test.js +8 -16
- package/tests/e2e/helpers/base.js +53 -48
- package/tests/e2e/helpers/debug.js +1 -1
- package/tests/e2e/helpers/params.js +17 -0
- package/tests/e2e/helpers/rightToLeft.js +8 -14
- package/tests/e2e/helpers/search.js +73 -0
- package/tests/e2e/models/Navigation.js +20 -37
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +40 -33
- package/tests/jest/BookNavigator/book-navigator.test.js +661 -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 +109 -60
- package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/jest/BookNavigator/viewable-files/viewable-files-provider.test.js +80 -0
- package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +74 -14
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +193 -0
- package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
- package/tests/jest/BookReader/Mode1UpLit.test.js +73 -0
- package/tests/jest/BookReader/Mode2Up.test.js +98 -0
- 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 +218 -0
- package/tests/jest/BookReader/ModeThumb.test.js +71 -0
- package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +10 -10
- 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/jest/BookReader/utils/SelectionObserver.test.js +57 -0
- package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
- package/tests/jest/BookReader/utils.test.js +229 -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} +26 -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/jest/plugins/plugin.chapters.test.js +195 -0
- package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
- package/tests/jest/plugins/plugin.text_selection.test.js +317 -0
- package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
- package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +26 -47
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +39 -6
- package/tests/jest/plugins/search/utils.js +25 -0
- package/tests/jest/plugins/search/utils.test.js +29 -0
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +29 -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 +47 -1
- package/tests/{plugins → jest/plugins}/tts/utils.test.js +1 -60
- package/tests/jest/plugins/url/UrlPlugin.test.js +198 -0
- package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +53 -14
- package/tests/jest/setup.js +3 -0
- package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
- package/tests/jest/util/docCookies.test.js +24 -0
- package/tests/{util → jest/util}/strings.test.js +1 -1
- package/tests/{utils.js → jest/utils.js} +38 -0
- package/webpack.config.js +12 -6
- package/.babelrc +0 -12
- package/.dependabot/config.yml +0 -6
- package/.testcaferc.json +0 -5
- package/BookReader/bookreader-component-bundle.js +0 -14312
- package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
- package/BookReader/bookreader-component-bundle.js.map +0 -1
- package/BookReader/icons/sort-ascending.svg +0 -1
- package/BookReader/icons/sort-descending.svg +0 -1
- package/BookReader/jquery-1.10.1.js +0 -108
- package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
- package/BookReader/plugins/plugin.menu_toggle.js +0 -369
- package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
- package/BookReader/plugins/plugin.mobile_nav.js +0 -335
- package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
- package/BookReaderDemo/IIIFBookReader.js +0 -207
- package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- package/BookReaderDemo/demo-iiif.js +0 -26
- 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 -452
- package/src/BookNavigator/assets/book-loader.js +0 -27
- package/src/BookNavigator/assets/icon_sort_ascending.js +0 -5
- package/src/BookNavigator/assets/icon_sort_descending.js +0 -5
- package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
- package/src/BookNavigator/search/a-search-result.js +0 -55
- package/src/BookNavigator/volumes/volumes-provider.js +0 -76
- package/src/BookNavigator/volumes/volumes.js +0 -161
- package/src/BookReader/DebugConsole.js +0 -54
- package/src/BookReaderComponent/BookReaderComponent.js +0 -112
- package/src/ItemNavigator/ItemNavigator.js +0 -372
- package/src/ItemNavigator/providers/sharing.js +0 -29
- package/src/assets/icons/sort-ascending.svg +0 -1
- package/src/assets/icons/sort-descending.svg +0 -1
- package/src/css/_MobileNav.scss +0 -194
- package/src/dragscrollable-br.js +0 -261
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- package/src/plugins/plugin.mobile_nav.js +0 -287
- package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
- package/tests/BookReader/DebugConsole.test.js +0 -25
- package/tests/BookReader/Mode1Up.test.js +0 -164
- package/tests/BookReader/Mode2Up.test.js +0 -247
- package/tests/BookReader/utils.test.js +0 -109
- package/tests/e2e/helpers/desktopSearch.js +0 -72
- package/tests/e2e/helpers/mobileSearch.js +0 -85
- 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/karma/BookNavigator/volumes.test.js +0 -101
- package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
- package/tests/plugins/plugin.chapters.test.js +0 -130
- package/tests/plugins/plugin.mobile_nav.test.js +0 -66
- package/tests/plugins/plugin.text_selection.test.js +0 -203
- package/tests/util/docCookies.test.js +0 -15
|
@@ -56,7 +56,7 @@ if (!isMobile()) {
|
|
|
56
56
|
$(document.body).append(cboxOverlay).append(cbox);
|
|
57
57
|
}
|
|
58
58
|
});
|
|
59
|
-
}
|
|
59
|
+
};
|
|
60
60
|
})(BookReader.prototype.init);
|
|
61
61
|
|
|
62
62
|
/**
|
|
@@ -92,7 +92,7 @@ if (!isMobile()) {
|
|
|
92
92
|
$(document).off('keyup' + EVENT_NAMESPACE);
|
|
93
93
|
|
|
94
94
|
this.isFullscreenActive = false;
|
|
95
|
-
this.updateBrClasses()
|
|
95
|
+
this.updateBrClasses();
|
|
96
96
|
|
|
97
97
|
this.resize();
|
|
98
98
|
this.refs.$brContainer.animate({ opacity: 1 }, 400, 'linear');
|
|
@@ -233,8 +233,8 @@ export function bindFullscreenChangeListener(
|
|
|
233
233
|
'moz',
|
|
234
234
|
'ms'
|
|
235
235
|
];
|
|
236
|
-
const all_events =
|
|
237
|
-
$(document).
|
|
236
|
+
const all_events = (event + vendor_prefixes.join(event) + event).trim();
|
|
237
|
+
$(document).on(all_events, data, fullscreenchangeListener);
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
/**
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/* global BookReader */
|
|
2
3
|
/**
|
|
3
4
|
* Plugin for Archive.org book search
|
|
4
|
-
* NOTE: This script must be loaded AFTER `plugin.mobile_nav.js`
|
|
5
|
-
* as it mutates mobile nav drawer
|
|
6
|
-
*
|
|
7
5
|
* Events fired at various points throughout search processing are published
|
|
8
6
|
* on the document DOM element. These can be subscribed to using jQuery's event
|
|
9
7
|
* binding method `$.fn.on`. All of the events are prefixed with a BookReader
|
|
@@ -20,8 +18,17 @@
|
|
|
20
18
|
* the book has not had OCR text indexed yet. Receives `instance`
|
|
21
19
|
* @event BookReader:SearchCallbackEmpty - When no results found. Receives
|
|
22
20
|
* `instance`
|
|
21
|
+
* @event BookReader:SearchCanceled - When no results found. Receives
|
|
22
|
+
* `instance`
|
|
23
23
|
*/
|
|
24
|
+
import { poll } from '../../BookReader/utils.js';
|
|
25
|
+
import { renderBoxesInPageContainerLayer } from '../../BookReader/PageContainer.js';
|
|
24
26
|
import SearchView from './view.js';
|
|
27
|
+
import { marshallSearchResults } from './utils.js';
|
|
28
|
+
/** @typedef {import('../../BookReader/PageContainer').PageContainer} PageContainer */
|
|
29
|
+
/** @typedef {import('../../BookReader/BookModel').PageIndex} PageIndex */
|
|
30
|
+
/** @typedef {import('../../BookReader/BookModel').LeafNum} LeafNum */
|
|
31
|
+
/** @typedef {import('../../BookReader/BookModel').PageNumString} PageNumString */
|
|
25
32
|
|
|
26
33
|
jQuery.extend(BookReader.defaultOptions, {
|
|
27
34
|
server: 'ia600609.us.archive.org',
|
|
@@ -29,7 +36,10 @@ jQuery.extend(BookReader.defaultOptions, {
|
|
|
29
36
|
subPrefix: '',
|
|
30
37
|
bookPath: '',
|
|
31
38
|
enableSearch: true,
|
|
39
|
+
searchInsideProtocol: 'https',
|
|
32
40
|
searchInsideUrl: '/fulltext/inside.php',
|
|
41
|
+
searchInsidePreTag: '{{{',
|
|
42
|
+
searchInsidePostTag: '}}}',
|
|
33
43
|
initialSearchTerm: null,
|
|
34
44
|
});
|
|
35
45
|
|
|
@@ -42,7 +52,6 @@ BookReader.prototype.setup = (function (super_) {
|
|
|
42
52
|
this.searchResults = null;
|
|
43
53
|
this.searchInsideUrl = options.searchInsideUrl;
|
|
44
54
|
this.enableSearch = options.enableSearch;
|
|
45
|
-
this.goToFirstResult = false;
|
|
46
55
|
|
|
47
56
|
// Base server used by some api calls
|
|
48
57
|
this.bookId = options.bookId;
|
|
@@ -50,11 +59,14 @@ BookReader.prototype.setup = (function (super_) {
|
|
|
50
59
|
this.subPrefix = options.subPrefix;
|
|
51
60
|
this.bookPath = options.bookPath;
|
|
52
61
|
|
|
53
|
-
|
|
54
|
-
this.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
62
|
+
this.searchXHR = null;
|
|
63
|
+
this._cancelSearch.bind(this);
|
|
64
|
+
this.cancelSearchRequest.bind(this);
|
|
65
|
+
|
|
66
|
+
/** @type { {[pageIndex: number]: SearchInsideMatchBox[]} } */
|
|
67
|
+
this._searchBoxesByIndex = {};
|
|
68
|
+
|
|
69
|
+
this.searchView = undefined;
|
|
58
70
|
};
|
|
59
71
|
})(BookReader.prototype.setup);
|
|
60
72
|
|
|
@@ -62,28 +74,31 @@ BookReader.prototype.setup = (function (super_) {
|
|
|
62
74
|
BookReader.prototype.init = (function (super_) {
|
|
63
75
|
return function () {
|
|
64
76
|
super_.call(this);
|
|
65
|
-
|
|
77
|
+
// give SearchView the most complete bookreader state
|
|
78
|
+
this.searchView = new SearchView({
|
|
79
|
+
br: this,
|
|
80
|
+
searchCancelledCallback: () => {
|
|
81
|
+
this._cancelSearch();
|
|
82
|
+
this.trigger('SearchCanceled', { term: this.searchTerm, instance: this });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
66
85
|
if (this.options.enableSearch && this.options.initialSearchTerm) {
|
|
86
|
+
/**
|
|
87
|
+
* this.search() take two parameter
|
|
88
|
+
* 1. this.options.initialSearchTerm - search term
|
|
89
|
+
* 2. {
|
|
90
|
+
* goToFirstResult: this.options.goToFirstResult,
|
|
91
|
+
* suppressFragmentChange: false // always want to change fragment in URL
|
|
92
|
+
* }
|
|
93
|
+
*/
|
|
67
94
|
this.search(
|
|
68
95
|
this.options.initialSearchTerm,
|
|
69
|
-
{ goToFirstResult: this.goToFirstResult, suppressFragmentChange:
|
|
96
|
+
{ goToFirstResult: this.options.goToFirstResult, suppressFragmentChange: false }
|
|
70
97
|
);
|
|
71
98
|
}
|
|
72
99
|
};
|
|
73
100
|
})(BookReader.prototype.init);
|
|
74
101
|
|
|
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
102
|
/** @override */
|
|
88
103
|
BookReader.prototype.buildToolbarElement = (function (super_) {
|
|
89
104
|
return function () {
|
|
@@ -96,6 +111,25 @@ BookReader.prototype.buildToolbarElement = (function (super_) {
|
|
|
96
111
|
};
|
|
97
112
|
})(BookReader.prototype.buildToolbarElement);
|
|
98
113
|
|
|
114
|
+
/** @override */
|
|
115
|
+
BookReader.prototype._createPageContainer = (function (super_) {
|
|
116
|
+
return function (index) {
|
|
117
|
+
const pageContainer = super_.call(this, index);
|
|
118
|
+
if (this.enableSearch && pageContainer.page && index in this._searchBoxesByIndex) {
|
|
119
|
+
const pageIndex = pageContainer.page.index;
|
|
120
|
+
const boxes = this._searchBoxesByIndex[pageIndex];
|
|
121
|
+
renderBoxesInPageContainerLayer(
|
|
122
|
+
'searchHiliteLayer',
|
|
123
|
+
boxes,
|
|
124
|
+
pageContainer.page,
|
|
125
|
+
pageContainer.$container[0],
|
|
126
|
+
boxes.map(b => `match-index-${b.matchIndex}`),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
return pageContainer;
|
|
130
|
+
};
|
|
131
|
+
})(BookReader.prototype._createPageContainer);
|
|
132
|
+
|
|
99
133
|
/**
|
|
100
134
|
* @typedef {object} SearchOptions
|
|
101
135
|
* @property {boolean} goToFirstResult
|
|
@@ -110,7 +144,7 @@ BookReader.prototype.buildToolbarElement = (function (super_) {
|
|
|
110
144
|
* @param {string} term
|
|
111
145
|
* @param {SearchOptions} overrides
|
|
112
146
|
*/
|
|
113
|
-
BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
147
|
+
BookReader.prototype.search = async function(term = '', overrides = {}) {
|
|
114
148
|
/** @type {SearchOptions} */
|
|
115
149
|
const defaultOptions = {
|
|
116
150
|
goToFirstResult: false, /* jump to the first result (default=false) */
|
|
@@ -122,6 +156,7 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
|
122
156
|
};
|
|
123
157
|
const options = jQuery.extend({}, defaultOptions, overrides);
|
|
124
158
|
this.suppressFragmentChange = options.suppressFragmentChange;
|
|
159
|
+
this.searchCancelled = false;
|
|
125
160
|
|
|
126
161
|
// strip slashes, since this goes in the url
|
|
127
162
|
this.searchTerm = term.replace(/\//g, ' ');
|
|
@@ -136,7 +171,7 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
|
136
171
|
|
|
137
172
|
// Remove the port and userdir
|
|
138
173
|
const serverPath = this.server.replace(/:.+/, '');
|
|
139
|
-
const baseUrl =
|
|
174
|
+
const baseUrl = `${this.options.searchInsideProtocol}://${serverPath}${this.searchInsideUrl}?`;
|
|
140
175
|
|
|
141
176
|
// Remove subPrefix from end of path
|
|
142
177
|
let path = this.bookPath;
|
|
@@ -150,6 +185,8 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
|
150
185
|
doc: this.subPrefix,
|
|
151
186
|
path,
|
|
152
187
|
q: term,
|
|
188
|
+
pre_tag: this.options.searchInsidePreTag,
|
|
189
|
+
post_tag: this.options.searchInsidePostTag,
|
|
153
190
|
};
|
|
154
191
|
|
|
155
192
|
// NOTE that the API does not expect / (slashes) to be encoded. (%2F) won't work
|
|
@@ -157,12 +194,16 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
|
157
194
|
|
|
158
195
|
const url = `${baseUrl}${paramStr}`;
|
|
159
196
|
|
|
160
|
-
const
|
|
197
|
+
const callSearchResultsCallback = (searchInsideResults) => {
|
|
198
|
+
if (this.searchCancelled) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
161
201
|
const responseHasError = searchInsideResults.error || !searchInsideResults.matches.length;
|
|
162
202
|
const hasCustomError = typeof options.error === 'function';
|
|
163
203
|
const hasCustomSuccess = typeof options.success === 'function';
|
|
164
204
|
|
|
165
205
|
if (responseHasError) {
|
|
206
|
+
console.error('Search Inside Response Error', searchInsideResults.error || 'matches.length == 0');
|
|
166
207
|
hasCustomError
|
|
167
208
|
? options.error.call(this, searchInsideResults, options)
|
|
168
209
|
: this.BRSearchCallbackError(searchInsideResults, options);
|
|
@@ -173,11 +214,39 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
|
173
214
|
}
|
|
174
215
|
};
|
|
175
216
|
|
|
176
|
-
this.trigger('SearchStarted', { term: this.searchTerm });
|
|
177
|
-
|
|
217
|
+
this.trigger('SearchStarted', { term: this.searchTerm, instance: this });
|
|
218
|
+
callSearchResultsCallback(await $.ajax({
|
|
178
219
|
url: url,
|
|
179
|
-
dataType: 'jsonp'
|
|
180
|
-
|
|
220
|
+
dataType: 'jsonp',
|
|
221
|
+
cache: true,
|
|
222
|
+
beforeSend: xhr => { this.searchXHR = xhr; },
|
|
223
|
+
}));
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* cancels AJAX Call
|
|
228
|
+
* emits custom event
|
|
229
|
+
*/
|
|
230
|
+
BookReader.prototype._cancelSearch = function () {
|
|
231
|
+
this.searchXHR?.abort();
|
|
232
|
+
this.searchView.clearSearchFieldAndResults(false);
|
|
233
|
+
this.searchTerm = '';
|
|
234
|
+
this.searchXHR = null;
|
|
235
|
+
this.searchCancelled = true;
|
|
236
|
+
this.searchResults = [];
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* External function to cancel search
|
|
241
|
+
* checks for term & xhr in flight before running
|
|
242
|
+
*/
|
|
243
|
+
BookReader.prototype.cancelSearchRequest = function () {
|
|
244
|
+
this.searchCancelled = true;
|
|
245
|
+
if (this.searchXHR !== null) {
|
|
246
|
+
this._cancelSearch();
|
|
247
|
+
this.searchView.toggleSearchPending();
|
|
248
|
+
this.trigger('SearchCanceled', { term: this.searchTerm, instance: this });
|
|
249
|
+
}
|
|
181
250
|
};
|
|
182
251
|
|
|
183
252
|
/**
|
|
@@ -188,10 +257,14 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
|
188
257
|
* @property {number} b
|
|
189
258
|
* @property {number} t
|
|
190
259
|
* @property {HTMLDivElement} [div]
|
|
260
|
+
* @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
261
|
*/
|
|
192
262
|
|
|
193
263
|
/**
|
|
194
264
|
* @typedef {object} SearchInsideMatch
|
|
265
|
+
* @property {number} matchIndex This is a fake field! Not part of the API response. It is added by the JS.
|
|
266
|
+
* @property {string} displayPageNumber (fake field) The page number as it should be displayed in the UI.
|
|
267
|
+
* @property {string} html (computed field) The html-escaped raw html to display in the UI.
|
|
195
268
|
* @property {string} text
|
|
196
269
|
* @property {Array<{ page: number, boxes: SearchInsideMatchBox[] }>} par
|
|
197
270
|
*/
|
|
@@ -205,21 +278,26 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
|
205
278
|
|
|
206
279
|
/**
|
|
207
280
|
* Search Results return handler
|
|
208
|
-
* @callback
|
|
209
281
|
* @param {SearchInsideResults} results
|
|
210
282
|
* @param {object} options
|
|
211
283
|
* @param {boolean} options.goToFirstResult
|
|
212
284
|
*/
|
|
213
285
|
BookReader.prototype.BRSearchCallback = function(results, options) {
|
|
214
|
-
|
|
286
|
+
marshallSearchResults(
|
|
287
|
+
results,
|
|
288
|
+
pageNum => this.book.getPageNum(this.book.leafNumToIndex(pageNum)),
|
|
289
|
+
this.options.searchInsidePreTag,
|
|
290
|
+
this.options.searchInsidePostTag,
|
|
291
|
+
);
|
|
292
|
+
this.searchResults = results || [];
|
|
215
293
|
|
|
216
294
|
this.updateSearchHilites();
|
|
217
295
|
this.removeProgressPopup();
|
|
218
296
|
if (options.goToFirstResult) {
|
|
219
|
-
this._searchPluginGoToResult(
|
|
297
|
+
this._searchPluginGoToResult(0);
|
|
220
298
|
}
|
|
221
299
|
this.trigger('SearchCallback', { results, options, instance: this });
|
|
222
|
-
}
|
|
300
|
+
};
|
|
223
301
|
|
|
224
302
|
/**
|
|
225
303
|
* Main search results error handler
|
|
@@ -259,95 +337,41 @@ BookReader.prototype._BRSearchCallbackError = function(results) {
|
|
|
259
337
|
* updates search on-page highlights controller
|
|
260
338
|
*/
|
|
261
339
|
BookReader.prototype.updateSearchHilites = function() {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
340
|
+
/** @type {SearchInsideMatch[]} */
|
|
341
|
+
const matches = this.searchResults?.matches || [];
|
|
342
|
+
/** @type { {[pageIndex: number]: SearchInsideMatchBox[]} } */
|
|
343
|
+
const boxesByIndex = {};
|
|
344
|
+
|
|
345
|
+
// Clear any existing svg layers
|
|
346
|
+
this.removeSearchHilites();
|
|
347
|
+
|
|
348
|
+
// Group by pageIndex
|
|
349
|
+
for (const match of matches) {
|
|
350
|
+
for (const box of match.par[0].boxes) {
|
|
351
|
+
const pageIndex = this.book.leafNumToIndex(box.page);
|
|
352
|
+
const pageBoxes = boxesByIndex[pageIndex] || (boxesByIndex[pageIndex] = []);
|
|
353
|
+
pageBoxes.push(box);
|
|
354
|
+
}
|
|
265
355
|
}
|
|
266
|
-
this.updateSearchHilites1UP();
|
|
267
|
-
};
|
|
268
356
|
|
|
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;
|
|
357
|
+
// update any already created pages
|
|
358
|
+
for (const [pageIndexString, boxes] of Object.entries(boxesByIndex)) {
|
|
359
|
+
const pageIndex = parseFloat(pageIndexString);
|
|
360
|
+
const page = this.book.getPage(pageIndex);
|
|
361
|
+
const pageContainers = this.getActivePageContainerElementsForIndex(pageIndex);
|
|
362
|
+
for (const container of pageContainers) {
|
|
363
|
+
renderBoxesInPageContainerLayer('searchHiliteLayer', boxes, page, container, boxes.map(b => `match-index-${b.matchIndex}`));
|
|
364
|
+
}
|
|
365
|
+
}
|
|
308
366
|
|
|
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
|
-
});
|
|
367
|
+
this._searchBoxesByIndex = boxesByIndex;
|
|
335
368
|
};
|
|
336
369
|
|
|
337
370
|
/**
|
|
338
371
|
* remove search highlights
|
|
339
372
|
*/
|
|
340
373
|
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
|
-
});
|
|
374
|
+
$(this.getActivePageContainerElements()).find('.searchHiliteLayer').remove();
|
|
351
375
|
};
|
|
352
376
|
|
|
353
377
|
/**
|
|
@@ -355,11 +379,14 @@ BookReader.prototype.removeSearchHilites = function() {
|
|
|
355
379
|
* Goes to the page specified. If the page is not viewable, tries to load the page
|
|
356
380
|
* FIXME Most of this logic is IA specific, and should be less integrated into here
|
|
357
381
|
* or at least more configurable.
|
|
358
|
-
* @param {
|
|
382
|
+
* @param {number} matchIndex
|
|
359
383
|
*/
|
|
360
|
-
BookReader.prototype._searchPluginGoToResult = async function (
|
|
361
|
-
const
|
|
384
|
+
BookReader.prototype._searchPluginGoToResult = async function (matchIndex) {
|
|
385
|
+
const match = this.searchResults?.matches[matchIndex];
|
|
386
|
+
const book = this.book;
|
|
387
|
+
const pageIndex = book.leafNumToIndex(match.par[0].page);
|
|
362
388
|
const page = book.getPage(pageIndex);
|
|
389
|
+
const onNearbyPage = Math.abs(this.currentIndex() - pageIndex) < 3;
|
|
363
390
|
let makeUnviewableAtEnd = false;
|
|
364
391
|
if (!page.isViewable) {
|
|
365
392
|
const resp = await fetch('/services/bookreader/request_page?' + new URLSearchParams({
|
|
@@ -378,15 +405,43 @@ BookReader.prototype._searchPluginGoToResult = async function (pageIndex) {
|
|
|
378
405
|
book.getPage(pageIndex).makeViewable();
|
|
379
406
|
makeUnviewableAtEnd = true;
|
|
380
407
|
}
|
|
408
|
+
|
|
409
|
+
// Trigger an update of book
|
|
410
|
+
this._modes.mode1Up.mode1UpLit.updatePages();
|
|
411
|
+
if (this.activeMode == this._modes.mode1Up) {
|
|
412
|
+
await this._modes.mode1Up.mode1UpLit.updateComplete;
|
|
413
|
+
}
|
|
381
414
|
}
|
|
382
415
|
/* this updates the URL */
|
|
383
|
-
this.
|
|
384
|
-
|
|
416
|
+
if (!this._isIndexDisplayed(pageIndex)) {
|
|
417
|
+
this.suppressFragmentChange = false;
|
|
418
|
+
this.jumpToIndex(pageIndex);
|
|
419
|
+
}
|
|
385
420
|
|
|
386
421
|
// Reset it to unviewable if it wasn't resolved
|
|
387
422
|
if (makeUnviewableAtEnd) {
|
|
388
423
|
book.getPage(pageIndex).makeViewable(false);
|
|
389
424
|
}
|
|
425
|
+
|
|
426
|
+
// Scroll/flash in the ui
|
|
427
|
+
const $boxes = await poll(() => $(`rect.match-index-${match.matchIndex}`), { until: result => result.length > 0 });
|
|
428
|
+
if ($boxes.length) {
|
|
429
|
+
$boxes.css('animation', 'none');
|
|
430
|
+
$boxes[0].scrollIntoView({
|
|
431
|
+
// Only vertically center the highlight if we're in 1up or in full screen. In
|
|
432
|
+
// 2up, if we're not fullscreen, the whole body gets scrolled around to try to
|
|
433
|
+
// center the highlight 🙄 See:
|
|
434
|
+
// https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move/11041376
|
|
435
|
+
// Note: nearest doesn't quite work great, because the ReadAloud toolbar is now
|
|
436
|
+
// full-width, and covers up the last line of the highlight.
|
|
437
|
+
block: this.constMode1up == this.mode || this.isFullscreenActive ? 'center' : 'nearest',
|
|
438
|
+
inline: 'center',
|
|
439
|
+
behavior: onNearbyPage ? 'smooth' : 'auto',
|
|
440
|
+
});
|
|
441
|
+
// wait for animation to start
|
|
442
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
443
|
+
$boxes.removeAttr("style");
|
|
444
|
+
}
|
|
390
445
|
};
|
|
391
446
|
|
|
392
447
|
/**
|
|
@@ -420,7 +475,7 @@ BookReader.prototype.searchHighlightVisible = function() {
|
|
|
420
475
|
|
|
421
476
|
results.matches.some(match => {
|
|
422
477
|
return match.par[0].boxes.some(box => {
|
|
423
|
-
const pageIndex = this.leafNumToIndex(box.page);
|
|
478
|
+
const pageIndex = this.book.leafNumToIndex(box.page);
|
|
424
479
|
if (jQuery.inArray(pageIndex, visiblePages) >= 0) {
|
|
425
480
|
return true;
|
|
426
481
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { escapeHTML, escapeRegExp } from '../../BookReader/utils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} match
|
|
5
|
+
* @param {string} preTag
|
|
6
|
+
* @param {string} postTag
|
|
7
|
+
* @returns {string}
|
|
8
|
+
*/
|
|
9
|
+
export function renderMatch(match, preTag, postTag) {
|
|
10
|
+
// Search results are returned as a text blob with the hits wrapped in
|
|
11
|
+
// triple mustaches. Hits occasionally include text beyond the search
|
|
12
|
+
// term, so everything within the staches is captured and wrapped.
|
|
13
|
+
const preTagRe = escapeRegExp(escapeHTML(preTag));
|
|
14
|
+
const postTagRe = escapeRegExp(escapeHTML(postTag));
|
|
15
|
+
// [^] matches any character, including line breaks
|
|
16
|
+
const regex = new RegExp(`${preTagRe}([^]+?)${postTagRe}`, 'g');
|
|
17
|
+
return escapeHTML(match)
|
|
18
|
+
.replace(regex, '<mark>$1</mark>')
|
|
19
|
+
// Fix trailing hyphens. This over-corrects but is net useful.
|
|
20
|
+
.replace(/(\b)- /g, '$1');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Attach some fields to search inside results
|
|
25
|
+
* @param {SearchInsideResults} results
|
|
26
|
+
* @param {(pageNum: LeafNum) => PageNumString} displayPageNumberFn
|
|
27
|
+
* @param {string} preTag
|
|
28
|
+
* @param {string} postTag
|
|
29
|
+
*/
|
|
30
|
+
export function marshallSearchResults(results, displayPageNumberFn, preTag, postTag) {
|
|
31
|
+
// Attach matchIndex to a few things to make it easier to identify
|
|
32
|
+
// an active/selected match
|
|
33
|
+
for (const [index, match] of results.matches.entries()) {
|
|
34
|
+
match.matchIndex = index;
|
|
35
|
+
match.displayPageNumber = displayPageNumberFn(match.par[0].page);
|
|
36
|
+
match.html = renderMatch(match.text, preTag, postTag);
|
|
37
|
+
for (const par of match.par) {
|
|
38
|
+
for (const box of par.boxes) {
|
|
39
|
+
box.matchIndex = index;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|