@internetarchive/bookreader 5.0.0-4 → 5.0.0-40-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 +75 -4
- package/.github/workflows/npm-publish.yml +2 -16
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +83 -323
- 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 +1623 -0
- package/BookReader/{bookreader-component-bundle.js.LICENSE.txt → ia-bookreader-bundle.js.LICENSE.txt} +14 -10
- 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/voice.svg +1 -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 +120 -0
- package/BookReaderDemo/demo-advanced.html +1 -1
- package/BookReaderDemo/demo-autoplay.html +1 -0
- package/BookReaderDemo/demo-embed-iframe-src.html +1 -0
- package/BookReaderDemo/demo-fullscreen-mobile.html +1 -0
- package/BookReaderDemo/demo-fullscreen.html +1 -0
- package/BookReaderDemo/demo-iiif.html +1 -0
- package/BookReaderDemo/demo-internetarchive.html +74 -17
- package/BookReaderDemo/demo-multiple.html +1 -0
- package/BookReaderDemo/demo-preview-pages.html +1 -0
- package/BookReaderDemo/demo-simple.html +1 -0
- package/BookReaderDemo/demo-vendor-fullscreen.html +1 -0
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +1 -0
- package/BookReaderDemo/immersion-mode.html +1 -0
- package/BookReaderDemo/toggle_controls.html +1 -0
- package/BookReaderDemo/view_mode.html +1 -0
- package/BookReaderDemo/viewmode-cycle.html +1 -2
- package/CHANGELOG.md +166 -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 +62 -47
- package/renovate.json +43 -0
- 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 +556 -0
- package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
- package/src/BookNavigator/bookmarks/bookmark-edit.js +4 -4
- package/src/BookNavigator/bookmarks/bookmarks-list.js +3 -3
- package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +23 -12
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +98 -62
- package/src/BookNavigator/delete-modal-actions.js +1 -1
- package/src/BookNavigator/downloads/downloads-provider.js +23 -17
- package/src/BookNavigator/downloads/downloads.js +17 -25
- package/src/BookNavigator/search/a-search-result.js +3 -3
- package/src/BookNavigator/search/search-provider.js +57 -24
- package/src/BookNavigator/search/search-results.js +8 -20
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -13
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +4 -3
- package/src/BookNavigator/volumes/volumes-provider.js +114 -0
- package/src/BookNavigator/volumes/volumes.js +188 -0
- 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 +104 -71
- package/src/BookReader/ModeSmoothZoom.js +179 -0
- package/src/BookReader/ModeThumb.js +16 -8
- package/src/BookReader/Navbar/Navbar.js +2 -31
- package/src/BookReader/PageContainer.js +57 -6
- package/src/BookReader/ReduceSet.js +1 -1
- package/src/BookReader/Toolbar/Toolbar.js +7 -7
- 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 +68 -13
- package/src/BookReader.js +375 -289
- 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 +11 -215
- package/src/css/_TextSelection.scss +14 -17
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +16 -3
- package/src/css/_icons.scss +6 -0
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.chapters.js +26 -33
- 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 +106 -107
- package/src/plugins/search/view.js +50 -163
- package/src/plugins/tts/AbstractTTSEngine.js +46 -37
- package/src/plugins/tts/FestivalTTSEngine.js +12 -13
- package/src/plugins/tts/PageChunk.js +15 -21
- package/src/plugins/tts/PageChunkIterator.js +8 -12
- package/src/plugins/tts/WebTTSEngine.js +64 -68
- package/src/plugins/tts/plugin.tts.js +79 -108
- package/src/plugins/url/UrlPlugin.js +184 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
- 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 +8 -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 +12 -3
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +38 -33
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +3 -3
- 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 +88 -0
- package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +5 -7
- 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 +79 -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 +136 -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} +20 -4
- package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +8 -8
- 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 +24 -25
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +6 -6
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +6 -6
- 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 -3
- 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/tests/karma/BookNavigator/book-navigator.test.js +501 -0
- package/tests/karma/BookNavigator/bookmarks/bookmark-button.test.js +44 -0
- package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +1 -3
- package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +3 -4
- package/tests/karma/BookNavigator/bookmarks/ia-bookmarks.test.js +57 -0
- package/tests/karma/BookNavigator/downloads/downloads-provider.test.js +67 -0
- package/tests/karma/BookNavigator/downloads/downloads.test.js +54 -0
- package/tests/karma/BookNavigator/search/search-provider.test.js +123 -0
- package/tests/karma/BookNavigator/{search-results.test.js → search/search-results.test.js} +1 -4
- package/tests/karma/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -2
- package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +184 -0
- package/tests/karma/BookNavigator/volumes/volumes.test.js +98 -0
- package/webpack.config.js +10 -4
- 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.map +0 -1
- 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/src/BookNavigator/BookModel.js +0 -14
- package/src/BookNavigator/BookNavigator.js +0 -435
- 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/dragscrollable-br.js +0 -261
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- 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/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -20,8 +20,13 @@
|
|
20
20
|
* the book has not had OCR text indexed yet. Receives `instance`
|
21
21
|
* @event BookReader:SearchCallbackEmpty - When no results found. Receives
|
22
22
|
* `instance`
|
23
|
+
* @event BookReader:SearchCanceled - When no results found. Receives
|
24
|
+
* `instance`
|
23
25
|
*/
|
26
|
+
import { renderBoxesInPageContainerLayer } from '../../BookReader/PageContainer.js';
|
24
27
|
import SearchView from './view.js';
|
28
|
+
/** @typedef {import('../../BookReader/PageContainer').PageContainer} PageContainer */
|
29
|
+
/** @typedef {import('../../BookReader/BookModel').PageIndex} PageIndex */
|
25
30
|
|
26
31
|
jQuery.extend(BookReader.defaultOptions, {
|
27
32
|
server: 'ia600609.us.archive.org',
|
@@ -42,7 +47,6 @@ BookReader.prototype.setup = (function (super_) {
|
|
42
47
|
this.searchResults = null;
|
43
48
|
this.searchInsideUrl = options.searchInsideUrl;
|
44
49
|
this.enableSearch = options.enableSearch;
|
45
|
-
this.goToFirstResult = false;
|
46
50
|
|
47
51
|
// Base server used by some api calls
|
48
52
|
this.bookId = options.bookId;
|
@@ -50,11 +54,14 @@ BookReader.prototype.setup = (function (super_) {
|
|
50
54
|
this.subPrefix = options.subPrefix;
|
51
55
|
this.bookPath = options.bookPath;
|
52
56
|
|
53
|
-
|
54
|
-
this.
|
55
|
-
|
56
|
-
|
57
|
-
}
|
57
|
+
this.searchXHR = null;
|
58
|
+
this._cancelSearch.bind(this);
|
59
|
+
this.cancelSearchRequest.bind(this);
|
60
|
+
|
61
|
+
/** @type { {[pageIndex: number]: SearchInsideMatchBox[]} } */
|
62
|
+
this._searchBoxesByIndex = {};
|
63
|
+
|
64
|
+
this.searchView = undefined;
|
58
65
|
};
|
59
66
|
})(BookReader.prototype.setup);
|
60
67
|
|
@@ -62,28 +69,31 @@ BookReader.prototype.setup = (function (super_) {
|
|
62
69
|
BookReader.prototype.init = (function (super_) {
|
63
70
|
return function () {
|
64
71
|
super_.call(this);
|
65
|
-
|
72
|
+
// give SearchView the most complete bookreader state
|
73
|
+
this.searchView = new SearchView({
|
74
|
+
br: this,
|
75
|
+
searchCancelledCallback: () => {
|
76
|
+
this._cancelSearch();
|
77
|
+
this.trigger('SearchCanceled', { term: this.searchTerm, instance: this });
|
78
|
+
}
|
79
|
+
});
|
66
80
|
if (this.options.enableSearch && this.options.initialSearchTerm) {
|
81
|
+
/**
|
82
|
+
* this.search() take two parameter
|
83
|
+
* 1. this.options.initialSearchTerm - search term
|
84
|
+
* 2. {
|
85
|
+
* goToFirstResult: this.options.goToFirstResult,
|
86
|
+
* suppressFragmentChange: false // always want to change fragment in URL
|
87
|
+
* }
|
88
|
+
*/
|
67
89
|
this.search(
|
68
90
|
this.options.initialSearchTerm,
|
69
|
-
{ goToFirstResult: this.goToFirstResult, suppressFragmentChange:
|
91
|
+
{ goToFirstResult: this.options.goToFirstResult, suppressFragmentChange: false }
|
70
92
|
);
|
71
93
|
}
|
72
94
|
};
|
73
95
|
})(BookReader.prototype.init);
|
74
96
|
|
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
97
|
/** @override */
|
88
98
|
BookReader.prototype.buildToolbarElement = (function (super_) {
|
89
99
|
return function () {
|
@@ -96,6 +106,18 @@ BookReader.prototype.buildToolbarElement = (function (super_) {
|
|
96
106
|
};
|
97
107
|
})(BookReader.prototype.buildToolbarElement);
|
98
108
|
|
109
|
+
/** @override */
|
110
|
+
BookReader.prototype._createPageContainer = (function (super_) {
|
111
|
+
return function (index) {
|
112
|
+
const pageContainer = super_.call(this, index);
|
113
|
+
if (this.enableSearch && pageContainer.page && index in this._searchBoxesByIndex) {
|
114
|
+
const pageIndex = pageContainer.page.index;
|
115
|
+
renderBoxesInPageContainerLayer('searchHiliteLayer', this._searchBoxesByIndex[pageIndex], pageContainer.page, pageContainer.$container[0]);
|
116
|
+
}
|
117
|
+
return pageContainer;
|
118
|
+
};
|
119
|
+
})(BookReader.prototype._createPageContainer);
|
120
|
+
|
99
121
|
/**
|
100
122
|
* @typedef {object} SearchOptions
|
101
123
|
* @property {boolean} goToFirstResult
|
@@ -110,7 +132,7 @@ BookReader.prototype.buildToolbarElement = (function (super_) {
|
|
110
132
|
* @param {string} term
|
111
133
|
* @param {SearchOptions} overrides
|
112
134
|
*/
|
113
|
-
BookReader.prototype.search = function(term = '', overrides = {}) {
|
135
|
+
BookReader.prototype.search = async function(term = '', overrides = {}) {
|
114
136
|
/** @type {SearchOptions} */
|
115
137
|
const defaultOptions = {
|
116
138
|
goToFirstResult: false, /* jump to the first result (default=false) */
|
@@ -122,6 +144,7 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
122
144
|
};
|
123
145
|
const options = jQuery.extend({}, defaultOptions, overrides);
|
124
146
|
this.suppressFragmentChange = options.suppressFragmentChange;
|
147
|
+
this.searchCancelled = false;
|
125
148
|
|
126
149
|
// strip slashes, since this goes in the url
|
127
150
|
this.searchTerm = term.replace(/\//g, ' ');
|
@@ -158,6 +181,9 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
158
181
|
const url = `${baseUrl}${paramStr}`;
|
159
182
|
|
160
183
|
const processSearchResults = (searchInsideResults) => {
|
184
|
+
if (this.searchCancelled) {
|
185
|
+
return;
|
186
|
+
}
|
161
187
|
const responseHasError = searchInsideResults.error || !searchInsideResults.matches.length;
|
162
188
|
const hasCustomError = typeof options.error === 'function';
|
163
189
|
const hasCustomSuccess = typeof options.success === 'function';
|
@@ -173,11 +199,39 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
173
199
|
}
|
174
200
|
};
|
175
201
|
|
176
|
-
this.trigger('SearchStarted', { term: this.searchTerm });
|
177
|
-
return $.ajax({
|
202
|
+
this.trigger('SearchStarted', { term: this.searchTerm, instance: this });
|
203
|
+
return processSearchResults(await $.ajax({
|
178
204
|
url: url,
|
179
|
-
dataType: 'jsonp'
|
180
|
-
|
205
|
+
dataType: 'jsonp',
|
206
|
+
cache: true,
|
207
|
+
beforeSend: xhr => { this.searchXHR = xhr; },
|
208
|
+
}));
|
209
|
+
};
|
210
|
+
|
211
|
+
/**
|
212
|
+
* cancels AJAX Call
|
213
|
+
* emits custom event
|
214
|
+
*/
|
215
|
+
BookReader.prototype._cancelSearch = function () {
|
216
|
+
this.searchXHR?.abort();
|
217
|
+
this.searchView.clearSearchFieldAndResults(false);
|
218
|
+
this.searchTerm = '';
|
219
|
+
this.searchXHR = null;
|
220
|
+
this.searchCancelled = true;
|
221
|
+
this.searchResults = [];
|
222
|
+
};
|
223
|
+
|
224
|
+
/**
|
225
|
+
* External function to cancel search
|
226
|
+
* checks for term & xhr in flight before running
|
227
|
+
*/
|
228
|
+
BookReader.prototype.cancelSearchRequest = function () {
|
229
|
+
this.searchCancelled = true;
|
230
|
+
if (this.searchXHR !== null) {
|
231
|
+
this._cancelSearch();
|
232
|
+
this.searchView.toggleSearchPending();
|
233
|
+
this.trigger('SearchCanceled', { term: this.searchTerm, instance: this });
|
234
|
+
}
|
181
235
|
};
|
182
236
|
|
183
237
|
/**
|
@@ -211,15 +265,16 @@ BookReader.prototype.search = function(term = '', overrides = {}) {
|
|
211
265
|
* @param {boolean} options.goToFirstResult
|
212
266
|
*/
|
213
267
|
BookReader.prototype.BRSearchCallback = function(results, options) {
|
214
|
-
this.searchResults = results;
|
268
|
+
this.searchResults = results || [];
|
215
269
|
|
216
270
|
this.updateSearchHilites();
|
217
271
|
this.removeProgressPopup();
|
218
272
|
if (options.goToFirstResult) {
|
219
|
-
this.
|
273
|
+
const pageIndex = this._models.book.leafNumToIndex(results.matches[0].par[0].page);
|
274
|
+
this._searchPluginGoToResult(pageIndex);
|
220
275
|
}
|
221
276
|
this.trigger('SearchCallback', { results, options, instance: this });
|
222
|
-
}
|
277
|
+
};
|
223
278
|
|
224
279
|
/**
|
225
280
|
* Main search results error handler
|
@@ -259,95 +314,39 @@ BookReader.prototype._BRSearchCallbackError = function(results) {
|
|
259
314
|
* updates search on-page highlights controller
|
260
315
|
*/
|
261
316
|
BookReader.prototype.updateSearchHilites = function() {
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
}
|
266
|
-
this.updateSearchHilites1UP();
|
267
|
-
};
|
317
|
+
/** @type {SearchInsideMatch[]} */
|
318
|
+
const matches = this.searchResults?.matches || [];
|
319
|
+
/** @type { {[pageIndex: number]: SearchInsideMatch[]} } */
|
320
|
+
const boxesByIndex = {};
|
268
321
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
const
|
274
|
-
|
275
|
-
results.matches.forEach(match => {
|
276
|
-
match.par[0].boxes.forEach(box => {
|
322
|
+
// Clear any existing svg layers
|
323
|
+
this.removeSearchHilites();
|
324
|
+
|
325
|
+
// Group by pageIndex
|
326
|
+
for (const match of matches) {
|
327
|
+
for (const box of match.par[0].boxes) {
|
277
328
|
const pageIndex = this.leafNumToIndex(box.page);
|
278
|
-
const
|
279
|
-
|
280
|
-
|
281
|
-
|
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
|
-
};
|
329
|
+
const pageMatches = boxesByIndex[pageIndex] || (boxesByIndex[pageIndex] = []);
|
330
|
+
pageMatches.push(box);
|
331
|
+
}
|
332
|
+
}
|
302
333
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
334
|
+
// update any already created pages
|
335
|
+
for (const [pageIndexString, boxes] of Object.entries(boxesByIndex)) {
|
336
|
+
const pageIndex = parseFloat(pageIndexString);
|
337
|
+
const page = this._models.book.getPage(pageIndex);
|
338
|
+
const pageContainers = this.getActivePageContainerElementsForIndex(pageIndex);
|
339
|
+
pageContainers.forEach(container => renderBoxesInPageContainerLayer('searchHiliteLayer', boxes, page, container));
|
340
|
+
}
|
308
341
|
|
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
|
-
});
|
342
|
+
this._searchBoxesByIndex = boxesByIndex;
|
335
343
|
};
|
336
344
|
|
337
345
|
/**
|
338
346
|
* remove search highlights
|
339
347
|
*/
|
340
348
|
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
|
-
});
|
349
|
+
$(this.getActivePageContainerElements()).find('.searchHiliteLayer').remove();
|
351
350
|
};
|
352
351
|
|
353
352
|
/**
|
@@ -1,75 +1,31 @@
|
|
1
1
|
class SearchView {
|
2
2
|
/**
|
3
3
|
* @param {object} params
|
4
|
-
*
|
5
|
-
*
|
6
|
-
* @param {object} params.br The BookReader instance
|
4
|
+
* @param {object} params.br The BookReader instance
|
5
|
+
* @param {function} params.cancelSearch callback when a user wants to cancel search
|
7
6
|
*
|
8
7
|
* @event BookReader:SearchResultsCleared - when the search results nav gets cleared
|
9
8
|
* @event BookReader:ToggleSearchMenu - when search results menu should toggle
|
10
9
|
*/
|
11
|
-
constructor(
|
12
|
-
|
13
|
-
console.warn('BookReader::Search - SearchView must be passed a valid CSS selector');
|
14
|
-
return;
|
15
|
-
}
|
16
|
-
|
17
|
-
this.br = params.br;
|
10
|
+
constructor({ br, searchCancelledCallback = () => {} }) {
|
11
|
+
this.br = br;
|
18
12
|
|
19
13
|
// Search results are returned as a text blob with the hits wrapped in
|
20
14
|
// triple mustaches. Hits occasionally include text beyond the search
|
21
15
|
// term, so everything within the staches is captured and wrapped.
|
22
16
|
this.matcher = new RegExp('{{{(.+?)}}}', 'g');
|
23
17
|
this.matches = [];
|
24
|
-
this.cacheDOMElements(
|
18
|
+
this.cacheDOMElements();
|
25
19
|
this.bindEvents();
|
20
|
+
this.cancelSearch = searchCancelledCallback;
|
26
21
|
}
|
27
22
|
|
28
|
-
|
29
|
-
* @param {string} selector A selector for the element that the search tray will be rendered in
|
30
|
-
*/
|
31
|
-
cacheDOMElements(selector) {
|
23
|
+
cacheDOMElements() {
|
32
24
|
this.dom = {};
|
33
|
-
|
34
|
-
// The parent search tray in mobile menu
|
35
|
-
this.dom.searchTray = this.renderSearchTray(selector);
|
36
|
-
// Container for rendered search results
|
37
|
-
this.dom.results = this.dom.searchTray.querySelector('[data-id="results"]');
|
38
|
-
// Element used to display number of results
|
39
|
-
this.dom.resultsCount = this.dom.searchTray.querySelector('[data-id="results_count"]');
|
40
|
-
// Search input within the mobile search tray
|
41
|
-
this.dom.searchField = this.dom.searchTray.querySelector('[name="query"]');
|
42
|
-
// Waiting indicator displayed while waiting for a search request
|
43
|
-
this.dom.searchPending = this.dom.searchTray.querySelector('[data-id="searchPending"]');
|
44
|
-
// The element added to the mobile menu that is animated into view when
|
45
|
-
// the "search" nav item is clicked
|
46
|
-
this.dom.mobileSearch = this.buildMobileDrawer();
|
47
25
|
// Search input within the top toolbar. Will be removed once the mobile menu is replaced.
|
48
26
|
this.dom.toolbarSearch = this.buildToolbarSearch();
|
49
27
|
}
|
50
28
|
|
51
|
-
/**
|
52
|
-
* @param {boolean} bool
|
53
|
-
*/
|
54
|
-
toggleSearchTray(bool = this.dom.searchTray.classList.contains('hidden')) {
|
55
|
-
this.dom.searchTray.classList.toggle('hidden', !bool);
|
56
|
-
}
|
57
|
-
|
58
|
-
/**
|
59
|
-
* @param {boolean} bool
|
60
|
-
*/
|
61
|
-
toggleResultsCount(bool) {
|
62
|
-
this.dom.resultsCount.classList.toggle('visible', bool);
|
63
|
-
}
|
64
|
-
|
65
|
-
/**
|
66
|
-
* @param {SearchInsideResults} results
|
67
|
-
*/
|
68
|
-
updateResultsCount(results) {
|
69
|
-
this.dom.resultsCount.innerText = `(${results} result${results != 1 ? 's' : ''})`;
|
70
|
-
this.toggleResultsCount(true);
|
71
|
-
}
|
72
|
-
|
73
29
|
/**
|
74
30
|
* @param {string} query
|
75
31
|
*/
|
@@ -78,7 +34,6 @@ class SearchView {
|
|
78
34
|
}
|
79
35
|
|
80
36
|
emptyMatches() {
|
81
|
-
this.dom.results.innerHTML = '';
|
82
37
|
this.matches = [];
|
83
38
|
}
|
84
39
|
|
@@ -86,48 +41,20 @@ class SearchView {
|
|
86
41
|
this.br.$('.BRnavpos .BRsearch').remove();
|
87
42
|
}
|
88
43
|
|
89
|
-
clearSearchFieldAndResults() {
|
44
|
+
clearSearchFieldAndResults(dispatchEventWhenComplete = true) {
|
90
45
|
this.br.removeSearchResults();
|
91
|
-
this.toggleResultsCount(false);
|
92
46
|
this.removeResultPins();
|
93
47
|
this.emptyMatches();
|
94
48
|
this.setQuery('');
|
95
49
|
this.teardownSearchNavigation();
|
96
|
-
|
50
|
+
if (dispatchEventWhenComplete) {
|
51
|
+
this.br.trigger('SearchResultsCleared');
|
52
|
+
}
|
97
53
|
}
|
98
54
|
|
99
55
|
toggleSidebar() {
|
100
56
|
this.br.trigger('ToggleSearchMenu');
|
101
57
|
}
|
102
|
-
/**
|
103
|
-
* @param {string} selector The ID attribute to be used for the search tray
|
104
|
-
*/
|
105
|
-
renderSearchTray(selector) {
|
106
|
-
const searchTray = document.createElement('div');
|
107
|
-
searchTray.setAttribute('id', selector.replace(/^#/, ''));
|
108
|
-
searchTray.innerHTML = `
|
109
|
-
<header>
|
110
|
-
<div>
|
111
|
-
<h3>Search inside</h3>
|
112
|
-
<p data-id="results_count"></p>
|
113
|
-
</div>
|
114
|
-
<a href="#" class="close"></a>
|
115
|
-
</header>
|
116
|
-
<form action="" method="get">
|
117
|
-
<fieldset>
|
118
|
-
<input name="all_files" id="all_files" type="checkbox" />
|
119
|
-
<label class="checkbox" for="all_files">Search all files</label>
|
120
|
-
<input type="search" name="query" placeholder="Enter a search term" />
|
121
|
-
</fieldset>
|
122
|
-
</form>
|
123
|
-
<div data-id="searchPending" id="search_pending">
|
124
|
-
<p>Your search results will appear below</p>
|
125
|
-
<div class="loader tc mt20"></div>
|
126
|
-
</div>
|
127
|
-
<ul data-id="results"></ul>
|
128
|
-
`;
|
129
|
-
return searchTray;
|
130
|
-
}
|
131
58
|
|
132
59
|
renderSearchNavigation() {
|
133
60
|
const selector = 'BRsearch-navigation';
|
@@ -215,17 +142,19 @@ class SearchView {
|
|
215
142
|
const start = pool.slice(0, pool.length / 2);
|
216
143
|
const end = pool.slice(pool.length / 2);
|
217
144
|
return closestTo((comparisonFn(start, end, comparator) ? start : end), comparator);
|
218
|
-
}
|
145
|
+
};
|
219
146
|
|
220
147
|
const closestPage = closestTo(matchPages, currentPage);
|
221
148
|
return this.matches.indexOf(this.matches.find((m) => m.par[0].page === closestPage));
|
222
149
|
}
|
223
150
|
|
224
151
|
updateResultsPosition() {
|
152
|
+
if (!this.dom.searchNavigation) return;
|
225
153
|
this.dom.searchNavigation.find('[data-id=resultsCount]').text(this.resultsPosition());
|
226
154
|
}
|
227
155
|
|
228
156
|
updateSearchNavigationButtons() {
|
157
|
+
if (!this.dom.searchNavigation) return;
|
229
158
|
this.dom.searchNavigation.find('.prev').attr('disabled', !this.currentMatchIndex);
|
230
159
|
this.dom.searchNavigation.find('.next').attr('disabled', this.currentMatchIndex + 1 === this.matches.length);
|
231
160
|
}
|
@@ -272,19 +201,6 @@ class SearchView {
|
|
272
201
|
this.updateSearchNavigationButtons();
|
273
202
|
}
|
274
203
|
|
275
|
-
/**
|
276
|
-
* @param {array} matches
|
277
|
-
*/
|
278
|
-
renderMatches(matches) {
|
279
|
-
const items = matches.map((match) => `
|
280
|
-
<li data-page="${match.par[0].page}" data-page-index="${this.br.leafNumToIndex(match.par[0].page)}">
|
281
|
-
<h4>Page ${match.par[0].page}</h4>
|
282
|
-
<p>${match.text.replace(this.matcher, '<mark>$1</mark>')}</p>
|
283
|
-
</li>
|
284
|
-
`);
|
285
|
-
this.dom.results.innerHTML = items.join('');
|
286
|
-
}
|
287
|
-
|
288
204
|
/**
|
289
205
|
* @param {boolean} bool
|
290
206
|
*/
|
@@ -293,23 +209,6 @@ class SearchView {
|
|
293
209
|
this.br.refs.$BRfooter.find('.BRsearch').css({ visibility: pinsVisibleState });
|
294
210
|
}
|
295
211
|
|
296
|
-
buildMobileDrawer() {
|
297
|
-
const mobileSearch = document.createElement('li');
|
298
|
-
mobileSearch.innerHTML = `
|
299
|
-
<span>
|
300
|
-
<span class="DrawerIconWrapper">
|
301
|
-
<img class="DrawerIcon" src="${this.br.imagesBaseURL}icon_search_button.svg" />
|
302
|
-
</span>
|
303
|
-
Search
|
304
|
-
</span>
|
305
|
-
<div data-id="search_slot">
|
306
|
-
</div>
|
307
|
-
`;
|
308
|
-
mobileSearch.querySelector('[data-id="search_slot"]').appendChild(this.dom.searchTray);
|
309
|
-
mobileSearch.classList.add('BRmobileMenu__search');
|
310
|
-
return mobileSearch;
|
311
|
-
}
|
312
|
-
|
313
212
|
buildToolbarSearch() {
|
314
213
|
const toolbarSearch = document.createElement('span');
|
315
214
|
toolbarSearch.classList.add('BRtoolbarSection', 'BRtoolbarSectionSearch');
|
@@ -363,28 +262,26 @@ class SearchView {
|
|
363
262
|
`)
|
364
263
|
.data({ pageIndex })
|
365
264
|
.appendTo(this.br.$('.BRnavline'))
|
366
|
-
.
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
.click(function (event) {
|
265
|
+
.on("mouseenter", (event) => {
|
266
|
+
// remove from other markers then turn on just for this
|
267
|
+
// XXX should be done when nav slider moves
|
268
|
+
const marker = event.currentTarget;
|
269
|
+
const tooltip = marker.querySelector('.BRquery');
|
270
|
+
const tooltipOffset = tooltip.getBoundingClientRect();
|
271
|
+
const targetOffset = marker.getBoundingClientRect();
|
272
|
+
const boxSizeAdjust = parseInt(getComputedStyle(tooltip).paddingLeft) * 2;
|
273
|
+
if (tooltipOffset.x - boxSizeAdjust < 0) {
|
274
|
+
tooltip.style.setProperty('transform', `translateX(-${targetOffset.left - boxSizeAdjust}px)`);
|
275
|
+
}
|
276
|
+
$('.BRsearch,.BRchapter').removeClass('front');
|
277
|
+
$(event.target).addClass('front');
|
278
|
+
})
|
279
|
+
.on("mouseleave", (event) => $(event.target).removeClass('front'))
|
280
|
+
.on("click", function (event) {
|
383
281
|
// closures are nested and deep, using an arrow function breaks references.
|
384
282
|
// Todo: update to arrow function & clean up closures
|
385
283
|
// to remove `bind` dependency
|
386
284
|
this.br._searchPluginGoToResult(+$(event.target).data('pageIndex'));
|
387
|
-
this.br.updateSearchHilites();
|
388
285
|
}.bind(this));
|
389
286
|
});
|
390
287
|
}
|
@@ -393,20 +290,28 @@ class SearchView {
|
|
393
290
|
* @param {boolean} bool
|
394
291
|
*/
|
395
292
|
toggleSearchPending(bool) {
|
396
|
-
this.dom.searchPending.classList.toggle('visible', bool);
|
397
293
|
if (bool) {
|
398
|
-
this.br.showProgressPopup("Search results will appear below...");
|
294
|
+
this.br.showProgressPopup("Search results will appear below...", () => this.progressPopupClosed());
|
399
295
|
}
|
400
296
|
else {
|
401
297
|
this.br.removeProgressPopup();
|
402
298
|
}
|
403
299
|
}
|
404
300
|
|
405
|
-
|
301
|
+
/**
|
302
|
+
* Primary callback when user cancels search popup
|
303
|
+
*/
|
304
|
+
progressPopupClosed() {
|
305
|
+
this.toggleSearchPending();
|
306
|
+
this.cancelSearch();
|
307
|
+
}
|
308
|
+
|
309
|
+
renderErrorModal(textIsProcessing = false) {
|
310
|
+
const errorDetails = `${!textIsProcessing ? 'The text may still be processing. ' : ''}Please try again.`;
|
406
311
|
this.renderModalMessage(`
|
407
312
|
Sorry, there was an error with your search.
|
408
313
|
<br />
|
409
|
-
|
314
|
+
${errorDetails}
|
410
315
|
`);
|
411
316
|
this.delayModalRemovalFor(4000);
|
412
317
|
}
|
@@ -445,14 +350,6 @@ class SearchView {
|
|
445
350
|
setTimeout(this.br.removeProgressPopup.bind(this.br), timeoutMS);
|
446
351
|
}
|
447
352
|
|
448
|
-
openMobileMenu() {
|
449
|
-
this.br.refs.$mmenu.data('mmenu').open();
|
450
|
-
}
|
451
|
-
|
452
|
-
closeMobileMenu() {
|
453
|
-
this.br.refs.$mmenu.data('mmenu').close();
|
454
|
-
}
|
455
|
-
|
456
353
|
/**
|
457
354
|
* @param {Event} e
|
458
355
|
*/
|
@@ -461,7 +358,6 @@ class SearchView {
|
|
461
358
|
const query = e.target.querySelector('[name="query"]').value;
|
462
359
|
if (!query.length) { return false; }
|
463
360
|
this.br.search(query);
|
464
|
-
this.dom.searchField.blur();
|
465
361
|
this.emptyMatches();
|
466
362
|
this.toggleSearchPending(true);
|
467
363
|
return false;
|
@@ -479,9 +375,7 @@ class SearchView {
|
|
479
375
|
this.teardownSearchNavigation();
|
480
376
|
this.renderSearchNavigation();
|
481
377
|
this.bindSearchNavigationEvents();
|
482
|
-
this.renderMatches(results.matches);
|
483
378
|
this.renderPins(results.matches);
|
484
|
-
this.updateResultsCount(results.matches.length);
|
485
379
|
this.toggleSearchPending(false);
|
486
380
|
if (options.goToFirstResult) {
|
487
381
|
$(document).one('BookReader:pageChanged', () => {
|
@@ -498,7 +392,6 @@ class SearchView {
|
|
498
392
|
handleNavToggledCallback(e) {
|
499
393
|
const is_visible = this.br.navigationIsVisible();
|
500
394
|
this.togglePinsFor(is_visible);
|
501
|
-
this.toggleSearchTray(is_visible ? !!this.dom.results.querySelector('li') : false);
|
502
395
|
}
|
503
396
|
|
504
397
|
handleSearchStarted() {
|
@@ -510,9 +403,14 @@ class SearchView {
|
|
510
403
|
this.setQuery(this.br.searchTerm);
|
511
404
|
}
|
512
405
|
|
513
|
-
|
406
|
+
/**
|
407
|
+
* Event listener for: `BookReader:SearchCallbackError`
|
408
|
+
* @param {CustomEvent} event
|
409
|
+
*/
|
410
|
+
handleSearchCallbackError(event = {}) {
|
514
411
|
this.toggleSearchPending(false);
|
515
|
-
|
412
|
+
const isIndexed = event?.detail?.props?.results?.indexed;
|
413
|
+
this.renderErrorModal(isIndexed);
|
516
414
|
}
|
517
415
|
|
518
416
|
handleSearchCallbackBookNotIndexed() {
|
@@ -528,26 +426,15 @@ class SearchView {
|
|
528
426
|
bindEvents() {
|
529
427
|
const namespace = 'BookReader:';
|
530
428
|
|
429
|
+
window.addEventListener(`${namespace}SearchCallbackError`, this.handleSearchCallbackError.bind(this));
|
531
430
|
$(document).on(`${namespace}SearchCallback`, this.handleSearchCallback.bind(this))
|
532
431
|
.on(`${namespace}navToggled`, this.handleNavToggledCallback.bind(this))
|
533
432
|
.on(`${namespace}SearchStarted`, this.handleSearchStarted.bind(this))
|
534
|
-
.on(`${namespace}SearchCallbackError`, this.handleSearchCallbackError.bind(this))
|
535
433
|
.on(`${namespace}SearchCallbackBookNotIndexed`, this.handleSearchCallbackBookNotIndexed.bind(this))
|
536
434
|
.on(`${namespace}SearchCallbackEmpty`, this.handleSearchCallbackEmpty.bind(this))
|
537
435
|
.on(`${namespace}pageChanged`, this.updateSearchNavigation.bind(this));
|
538
436
|
|
539
|
-
this.dom.searchTray.addEventListener('submit', this.submitHandler.bind(this));
|
540
437
|
this.dom.toolbarSearch.querySelector('form').addEventListener('submit', this.submitHandler.bind(this));
|
541
|
-
this.dom.searchField.addEventListener('search', () => {
|
542
|
-
if (this.dom.searchField.value) { return; }
|
543
|
-
this.clearSearchFieldAndResults();
|
544
|
-
});
|
545
|
-
|
546
|
-
$(this.dom.results).on('click', 'li', (e) => {
|
547
|
-
this.br._searchPluginGoToResult(+e.currentTarget.dataset.pageIndex);
|
548
|
-
this.br.updateSearchHilites();
|
549
|
-
this.closeMobileMenu();
|
550
|
-
});
|
551
438
|
}
|
552
439
|
}
|
553
440
|
|