@internetarchive/bookreader 5.0.0-100 → 5.0.0-102

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.
Files changed (107) hide show
  1. package/BookReader/474.js +1 -1
  2. package/BookReader/474.js.map +1 -1
  3. package/BookReader/BookReader.css +79 -8
  4. package/BookReader/BookReader.js +1 -1
  5. package/BookReader/BookReader.js.LICENSE.txt +1 -1
  6. package/BookReader/BookReader.js.map +1 -1
  7. package/BookReader/ia-bookreader-bundle.js +52 -52
  8. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -1
  9. package/BookReader/ia-bookreader-bundle.js.map +1 -1
  10. package/BookReader/icons/1up.svg +1 -1
  11. package/BookReader/icons/2up.svg +1 -1
  12. package/BookReader/icons/advance.svg +1 -1
  13. package/BookReader/icons/chevron-right.svg +1 -1
  14. package/BookReader/icons/close-circle-dark.svg +1 -1
  15. package/BookReader/icons/close-circle.svg +1 -1
  16. package/BookReader/icons/fullscreen.svg +1 -1
  17. package/BookReader/icons/fullscreen_exit.svg +1 -1
  18. package/BookReader/icons/hamburger.svg +1 -1
  19. package/BookReader/icons/left-arrow.svg +1 -1
  20. package/BookReader/icons/magnify-minus.svg +1 -1
  21. package/BookReader/icons/magnify-plus.svg +1 -1
  22. package/BookReader/icons/magnify.svg +1 -1
  23. package/BookReader/icons/pause.svg +1 -1
  24. package/BookReader/icons/play.svg +1 -1
  25. package/BookReader/icons/playback-speed.svg +1 -1
  26. package/BookReader/icons/read-aloud.svg +1 -1
  27. package/BookReader/icons/review.svg +1 -1
  28. package/BookReader/icons/slider-toggle.svg +1 -0
  29. package/BookReader/icons/thumbnails.svg +1 -1
  30. package/BookReader/icons/voice.svg +1 -1
  31. package/BookReader/icons/volume-full.svg +1 -1
  32. package/BookReader/images/BRicons.svg +2 -2
  33. package/BookReader/images/books_graphic.svg +1 -1
  34. package/BookReader/images/icon_book.svg +1 -1
  35. package/BookReader/images/icon_bookmark.svg +1 -1
  36. package/BookReader/images/icon_gear.svg +1 -1
  37. package/BookReader/images/icon_hamburger.svg +1 -1
  38. package/BookReader/images/icon_home.svg +1 -1
  39. package/BookReader/images/icon_info.svg +1 -1
  40. package/BookReader/images/icon_one_page.svg +1 -1
  41. package/BookReader/images/icon_pause.svg +1 -1
  42. package/BookReader/images/icon_play.svg +1 -1
  43. package/BookReader/images/icon_playback-rate.svg +1 -1
  44. package/BookReader/images/icon_search_button.svg +1 -1
  45. package/BookReader/images/icon_share.svg +1 -1
  46. package/BookReader/images/icon_skip-back.svg +1 -1
  47. package/BookReader/images/icon_speaker.svg +1 -1
  48. package/BookReader/images/icon_speaker_open.svg +1 -1
  49. package/BookReader/images/icon_thumbnails.svg +1 -1
  50. package/BookReader/images/icon_toc.svg +1 -1
  51. package/BookReader/images/icon_two_pages.svg +1 -1
  52. package/BookReader/images/marker_chap-off.svg +1 -1
  53. package/BookReader/images/marker_chap-on.svg +1 -1
  54. package/BookReader/images/marker_srch-on.svg +1 -1
  55. package/BookReader/images/translate.svg +1 -1
  56. package/BookReader/jquery-3.js +1 -1
  57. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  58. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  59. package/BookReader/plugins/plugin.autoplay.js +1 -1
  60. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  61. package/BookReader/plugins/plugin.chapters.js +2 -2
  62. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -1
  63. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  64. package/BookReader/plugins/plugin.experiments.js +1 -1
  65. package/BookReader/plugins/plugin.experiments.js.LICENSE.txt +1 -1
  66. package/BookReader/plugins/plugin.experiments.js.map +1 -1
  67. package/BookReader/plugins/plugin.iframe.js +1 -1
  68. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  69. package/BookReader/plugins/plugin.iiif.js +1 -1
  70. package/BookReader/plugins/plugin.iiif.js.map +1 -1
  71. package/BookReader/plugins/plugin.resume.js +1 -1
  72. package/BookReader/plugins/plugin.resume.js.map +1 -1
  73. package/BookReader/plugins/plugin.search.js +1 -1
  74. package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -1
  75. package/BookReader/plugins/plugin.search.js.map +1 -1
  76. package/BookReader/plugins/plugin.text_selection.js +1 -1
  77. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -1
  78. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  79. package/BookReader/plugins/plugin.translate.js +4 -4
  80. package/BookReader/plugins/plugin.translate.js.LICENSE.txt +1 -1
  81. package/BookReader/plugins/plugin.translate.js.map +1 -1
  82. package/BookReader/plugins/plugin.tts.js +1 -1
  83. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +1 -1
  84. package/BookReader/plugins/plugin.tts.js.map +1 -1
  85. package/BookReader/plugins/plugin.url.js +1 -1
  86. package/BookReader/plugins/plugin.url.js.map +1 -1
  87. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  88. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  89. package/BookReader/plugins/translator-worker.js +1 -1
  90. package/BookReader/plugins/translator-worker.js.map +1 -1
  91. package/BookReader/webcomponents-bundle.js +1 -1
  92. package/BookReader/webcomponents-bundle.js.map +1 -1
  93. package/package.json +20 -20
  94. package/src/BookNavigator/search/search-results.js +84 -63
  95. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +4 -4
  96. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +77 -59
  97. package/src/BookReader/Navbar/Navbar.js +54 -71
  98. package/src/BookReader/options.js +6 -0
  99. package/src/BookReader.js +12 -0
  100. package/src/assets/icons/slider-toggle.svg +1 -0
  101. package/src/css/_BRnav.scss +57 -4
  102. package/src/css/_BRpages.scss +9 -0
  103. package/src/css/_icons.scss +7 -0
  104. package/src/plugins/plugin.text_selection.js +9 -0
  105. package/src/plugins/search/plugin.search.js +4 -0
  106. package/src/plugins/search/utils.js +8 -1
  107. package/src/plugins/search/view.js +1 -1
@@ -23,11 +23,11 @@ export class Navbar {
23
23
 
24
24
  /** @type {Object} controls will be switch over "this.maximumControls" */
25
25
  this.minimumControls = [
26
- 'viewmode',
26
+ 'toggle_slider', 'viewmode',
27
27
  ];
28
28
  /** @type {Object} controls will be switch over "this.minimumControls" */
29
29
  this.maximumControls = [
30
- 'book_left', 'book_right', 'zoom_in', 'zoom_out', 'onepg', 'twopg', 'thumb',
30
+ 'BRnavpos', 'book_left', 'book_right', 'zoom_in', 'zoom_out', 'onepg', 'twopg', 'thumb',
31
31
  ];
32
32
 
33
33
  this.updateNavIndexThrottled = throttle(this.updateNavIndex.bind(this), 250, false);
@@ -50,6 +50,7 @@ export class Navbar {
50
50
  /** @private */
51
51
  _renderControls() {
52
52
  return [
53
+ 'toggleSlider',
53
54
  'bookLeft',
54
55
  'bookRight',
55
56
  'onePage',
@@ -126,6 +127,9 @@ export class Navbar {
126
127
 
127
128
  // Map of jIcon class -> click handler
128
129
  const navigationControls = {
130
+ toggle_slider: () => {
131
+ this.br.toggleSlider();
132
+ },
129
133
  book_left: () => {
130
134
  this.br.trigger(EVENTS.stop);
131
135
  this.br.left();
@@ -199,71 +203,48 @@ export class Navbar {
199
203
  * Switch navbar controls on mobile and desktop
200
204
  */
201
205
  switchNavbarControls() {
202
- if (this.br.refs.$brContainer.prop('clientWidth') < 640) {
203
- this.showMinimumNavPageNum();
204
- // we don't want navbar controls switching with liner-notes
205
- if (this.br.options.bookType !== 'linerNotes') {
206
- this.showMinimumNavbarControls();
207
- }
208
- } else {
209
- this.showMaximumNavPageNum();
210
- // we don't want navbar controls switching with liner-notes
211
- if (this.br.options.bookType !== 'linerNotes') {
212
- this.showMaximumNavbarControls();
206
+ // we don't want navbar controls switching with liner-notes
207
+ if (this.br.options.bookType !== 'linerNotes') {
208
+ if (this.br.refs.$brContainer.prop('clientWidth') < 640) {
209
+ this.showMobileControls();
210
+ } else {
211
+ this.showDesktopControls();
213
212
  }
214
213
  }
215
214
  }
216
215
 
217
216
  /**
218
- * Switch Book Nav page number display to minimum/mobile
219
- */
220
- showMinimumNavPageNum() {
221
- const minElement = document.querySelector('.BRcurrentpage.BRmin');
222
- const maxElement = document.querySelector('.BRcurrentpage.BRmax');
223
-
224
- if (minElement) minElement.classList.remove('hide');
225
- if (maxElement) maxElement.classList.add('hide');
226
- }
227
-
228
- /**
229
- * Switch Book Nav page number display to maximum/desktop
230
- */
231
- showMaximumNavPageNum() {
232
- const minElement = document.querySelector('.BRcurrentpage.BRmin');
233
- const maxElement = document.querySelector('.BRcurrentpage.BRmax');
234
-
235
- if (minElement) minElement.classList.add('hide');
236
- if (maxElement) maxElement.classList.remove('hide');
237
- }
238
-
239
- /**
240
- * Switch Book Navbar controls to minimised
241
- * NOTE: only `this.minimumControls` and `this.maximumControls` switch on resize
217
+ * Switch Book controls to mobile mode
218
+ * NOTE: `this.minimumControls`, `this.maximumControls`, and .BRnavMobile switch on resize
242
219
  */
243
- showMinimumNavbarControls() {
220
+ showMobileControls() {
244
221
  this.minimumControls.forEach((control) => {
245
- const element = document.querySelector(`.controls .${control}`);
222
+ const element = document.querySelector(`.BRnavMain .controls .${control}`);
246
223
  if (element) element.classList.remove('hide');
247
224
  });
248
225
  this.maximumControls.forEach((control) => {
249
- const element = document.querySelector(`.controls .${control}`);
226
+ const element = document.querySelector(`.BRnavMain .controls .${control}`);
250
227
  if (element) element.classList.add('hide');
251
228
  });
229
+ const mobileNav = document.querySelector(`.BRnavMobile`);
230
+ if (mobileNav) mobileNav.classList.remove('hide');
252
231
  }
253
232
 
254
233
  /**
255
- * Switch Book Navbar controls to maximized
256
- * NOTE: only `this.minimumControls` and `this.maximumControls` switch on resize
234
+ * Switch Book controls to desktop mode
235
+ * NOTE: `this.minimumControls`, `this.maximumControls`, and .BRnavMobile switch on resize
257
236
  */
258
- showMaximumNavbarControls() {
237
+ showDesktopControls() {
259
238
  this.maximumControls.forEach((control) => {
260
- const element = document.querySelector(`.controls .${control}`);
239
+ const element = document.querySelector(`.BRnavMain .controls .${control}`);
261
240
  if (element) element.classList.remove('hide');
262
241
  });
263
242
  this.minimumControls.forEach((control) => {
264
- const element = document.querySelector(`.controls .${control}`);
243
+ const element = document.querySelector(`.BRnavMain .controls .${control}`);
265
244
  if (element) element.classList.add('hide');
266
245
  });
246
+ const mobileNav = document.querySelector(`.BRnavMobile`);
247
+ if (mobileNav) mobileNav.classList.add('hide');
267
248
  }
268
249
 
269
250
  /**
@@ -282,7 +263,7 @@ export class Navbar {
282
263
 
283
264
  br.refs.$BRfooter = this.$root = $(`<div class="BRfooter"></div>`);
284
265
  br.refs.$BRnav = this.$nav = $(
285
- `<div class="BRnav BRnavDesktop">
266
+ `<div class="BRnav BRnavMobile docked">
286
267
  ${title ? `<div class="BRnavTitle">${title}</div>` : ''}
287
268
  <nav class="BRcontrols">
288
269
  <ul class="controls">
@@ -291,10 +272,24 @@ export class Navbar {
291
272
  <div class="BRpager"></div>
292
273
  <div class="BRnavline"></div>
293
274
  </div>
275
+ </li>
276
+ ${this.controlFor('bookLeft')}
277
+ ${this.controlFor('bookRight')}
278
+ </ul>
279
+ </nav>
280
+ </div>
281
+ <div class="BRnav BRnavMain">
282
+ ${title ? `<div class="BRnavTitle">${title}</div>` : ''}
283
+ <nav class="BRcontrols">
284
+ <ul class="controls">
285
+ <li class="scrubber">
294
286
  <p>
295
- <span class="BRcurrentpage BRmax"></span>
296
- <span class="BRcurrentpage BRmin"></span>
287
+ <span class="BRcurrentpage"></span>
297
288
  </p>
289
+ <div class="BRnavpos">
290
+ <div class="BRpager"></div>
291
+ <div class="BRnavline"></div>
292
+ </div>
298
293
  </li>
299
294
  ${this._renderControls()}
300
295
  </ul>
@@ -304,7 +299,8 @@ export class Navbar {
304
299
  this.$root.append(this.$nav);
305
300
  br.refs.$br.append(this.$root);
306
301
 
307
- const $slider = this.$root.find('.BRpager').slider({
302
+ /** @type {JQuery} sliders */
303
+ const $sliders = this.$root.find('.BRpager').slider({
308
304
  animate: true,
309
305
  min: 0,
310
306
  max: br.book.getNumLeafs() - 1,
@@ -312,16 +308,16 @@ export class Navbar {
312
308
  range: "min",
313
309
  });
314
310
 
315
- $slider.on('slide', (event, ui) => {
311
+ $sliders.on('slide', (event, ui) => {
316
312
  this.updateNavPageNum(ui.value);
317
313
  return true;
318
314
  });
319
315
 
320
- $slider.on('slidechange', (event, ui) => {
316
+ $sliders.on('slidechange', (event, ui) => {
321
317
  this.updateNavPageNum(ui.value);
322
318
  // recursion prevention for jumpToIndex
323
- if ($slider.data('swallowchange')) {
324
- $slider.data('swallowchange', false);
319
+ if ($(event.currentTarget).data('swallowchange')) {
320
+ $(event.currentTarget).data('swallowchange', false);
325
321
  } else {
326
322
  br.jumpToIndex(ui.value);
327
323
  }
@@ -337,10 +333,9 @@ export class Navbar {
337
333
  /**
338
334
  * Returns the textual representation of the current page for the navbar
339
335
  * @param {number} index
340
- * @param {boolean} [useMaxFormat = false]
341
336
  * @return {string}
342
337
  */
343
- getNavPageNumString(index, useMaxFormat = false) {
338
+ getNavPageNumString(index) {
344
339
  const { br } = this;
345
340
  // Accessible index starts at 0 (alas) so we add 1 to make human
346
341
  const pageNum = br.book.getPageNum(index);
@@ -360,7 +355,7 @@ export class Navbar {
360
355
  this.maxPageNum = maxPageNum;
361
356
  }
362
357
 
363
- return getNavPageNumHtml(index, numLeafs, pageNum, pageType, this.maxPageNum, useMaxFormat);
358
+ return getNavPageNumHtml(index, numLeafs, pageNum, pageType, this.maxPageNum);
364
359
 
365
360
  }
366
361
 
@@ -369,8 +364,7 @@ export class Navbar {
369
364
  * @param {number} index
370
365
  */
371
366
  updateNavPageNum(index) {
372
- this.$root.find('.BRcurrentpage.BRmax').html(this.getNavPageNumString(index, true));
373
- this.$root.find('.BRcurrentpage.BRmin').html(this.getNavPageNumString(index));
367
+ this.$root.find('.BRcurrentpage').html(this.getNavPageNumString(index, true));
374
368
  }
375
369
 
376
370
  /**
@@ -392,25 +386,14 @@ export class Navbar {
392
386
  * @param {number|string} pageNum
393
387
  * @param {*} pageType - Deprecated
394
388
  * @param {number} maxPageNum
395
- * @param {boolean} [useMaxFormat = false]
396
389
  * @return {string}
397
390
  */
398
- export function getNavPageNumHtml(index, numLeafs, pageNum, pageType, maxPageNum, useMaxFormat = false) {
391
+ export function getNavPageNumHtml(index, numLeafs, pageNum, pageType, maxPageNum) {
399
392
  const pageIsAsserted = pageNum[0] != 'n';
400
393
  const pageIndex = index + 1;
401
394
 
402
395
  if (!pageIsAsserted) {
403
396
  pageNum = '—';
404
397
  }
405
-
406
- if (useMaxFormat === true) {
407
- return `Page ${pageNum} (${pageIndex}/${numLeafs})`;
408
- }
409
-
410
- if (!pageIsAsserted) {
411
- return `(${pageIndex} of ${numLeafs})`;
412
- }
413
-
414
- const bookLengthLabel = (maxPageNum && parseFloat(pageNum)) ? ` of ${maxPageNum}` : '';
415
- return `${pageNum}${bookLengthLabel}`;
398
+ return `Page ${pageNum} (${pageIndex}/${numLeafs})`;
416
399
  }
@@ -258,6 +258,12 @@ export const DEFAULT_OPTIONS = {
258
258
  getEmbedCode: null,
259
259
 
260
260
  controls: {
261
+ toggleSlider: {
262
+ visible: true,
263
+ label: 'Toggle page controls',
264
+ className: 'toggle_slider',
265
+ iconClassName: 'toggle-slider',
266
+ },
261
267
  bookLeft: {
262
268
  visible: true,
263
269
  label: 'Flip left',
package/src/BookReader.js CHANGED
@@ -1380,6 +1380,17 @@ BookReader.prototype.exitFullScreen = async function () {
1380
1380
  this.refs.$br.removeClass('BRfullscreenAnimation');
1381
1381
  };
1382
1382
 
1383
+ /**
1384
+ * Toggles the mobile slider and page controls
1385
+ */
1386
+ BookReader.prototype.toggleSlider = function () {
1387
+ const toggleButton = this.refs.$BRnav.find('.toggle_slider');
1388
+ const mobileControls = this.refs.$br.find('.BRnavMobile');
1389
+
1390
+ toggleButton.toggleClass('active');
1391
+ mobileControls.toggleClass('docked');
1392
+ };
1393
+
1383
1394
  /**
1384
1395
  * Returns the currently active index
1385
1396
  * @return {number}
@@ -1734,6 +1745,7 @@ BookReader.prototype.initUIStrings = function() {
1734
1745
  '.share': 'Share this book',
1735
1746
  '.info': 'About this book',
1736
1747
  '.full': 'Toggle fullscreen',
1748
+ '.toggle_slider': 'Toggle page controls',
1737
1749
  '.book_left': 'Flip left',
1738
1750
  '.book_right': 'Flip right',
1739
1751
  '.play': 'Play',
@@ -0,0 +1 @@
1
+ <svg height="100" viewBox="0 0 100 100" width="100" xmlns="http://www.w3.org/2000/svg"><g fill="#fff" fill-rule="evenodd" transform="translate(0 23)"><path d="m35 0v54l-35-27.8266318zm30 0 35 26.1733682-35 27.8266318z"/><circle cx="50" cy="27.236059" r="10"/></g></svg>
@@ -118,7 +118,6 @@
118
118
  height: 100%;
119
119
  }
120
120
 
121
-
122
121
  .BRToolbarButton {
123
122
  .icon {
124
123
  width: $toolbarHeight;
@@ -226,6 +225,12 @@
226
225
  border: none;
227
226
  }
228
227
 
228
+ &.ui-slider-docked {
229
+ height: 1px;
230
+ width: 100%;
231
+ margin: 0px;
232
+ }
233
+
229
234
  .ui-slider-horizontal .ui-slider-handle,
230
235
  .ui-slider-handle {
231
236
  position: absolute;
@@ -262,10 +267,10 @@
262
267
  }
263
268
  .BRcurrentpage {
264
269
  display: inline-block;
265
- text-align: center;
270
+ text-align: left;
266
271
  padding: 0 0 0 0;
267
272
  font-size: $brFontSizeSmaller;
268
- margin-left: 5px;
273
+ margin-left: 15px;
269
274
  margin-right: 10px;
270
275
  line-height: 1;
271
276
  }
@@ -310,7 +315,6 @@
310
315
  .BRnavline .BRchapter { display: none; }
311
316
 
312
317
  .BRpager.ui-slider {
313
- height: 10px;
314
318
  top: math.div($brNavHeightMobile, 2) - 5px;
315
319
  }
316
320
  }
@@ -325,3 +329,52 @@
325
329
  .DrawerSettingsWrapper .zoom_in {
326
330
  background-position: -1384px center;
327
331
  }
332
+
333
+ .BRnavMobile {
334
+ box-sizing: content-box;
335
+ }
336
+
337
+ .BRnavMobile.docked {
338
+ height: 0px;
339
+ border: none;
340
+ .BRcontrols .scrubber .BRpager.ui-slider {
341
+ top: -1px;
342
+ }
343
+
344
+ .ui-slider,
345
+ .ui-slider-range {
346
+ height: 2px;
347
+ border-radius: 0px;
348
+ }
349
+
350
+ .BRnavpos {
351
+ margin: 0px;
352
+ }
353
+
354
+ .scrubber {
355
+ margin: 0px;
356
+ padding: 0px;
357
+ height: 0px;
358
+ }
359
+
360
+ .controls {
361
+ padding: 0px;
362
+ background-color: transparent;
363
+ }
364
+
365
+ .BRnavline {
366
+ display: none;
367
+ }
368
+
369
+ .ui-slider-handle {
370
+ display: none;
371
+ }
372
+
373
+ button {
374
+ display: none;
375
+ }
376
+ }
377
+
378
+ .BRnavMobile.hide {
379
+ display: none;
380
+ }
@@ -91,6 +91,15 @@
91
91
  }
92
92
  }
93
93
 
94
+ // Used for search result rectangles
95
+ svg.BRPageLayer {
96
+ position: absolute;
97
+ top: 0;
98
+ left: 0;
99
+ right: 0;
100
+ bottom: 0;
101
+ }
102
+
94
103
  // Hides page layers during page flip animation
95
104
  .BRpageFlipping .BRtextLayer {
96
105
  display: none;
@@ -119,3 +119,10 @@
119
119
  height: 12px;
120
120
  background-image: url("icons/close-circle-dark.svg");
121
121
  }
122
+
123
+ .icon-toggle-slider {
124
+ background-size: 25px;
125
+ width: 25px;
126
+ height: 25px;
127
+ background-image: url("icons/slider-toggle.svg");
128
+ }
@@ -137,6 +137,15 @@ export class TextSelectionPlugin extends BookReaderPlugin {
137
137
  if ($textLayers.length) return;
138
138
  const XMLpage = await this.getPageText(pageIndex);
139
139
  if (!XMLpage) return;
140
+ // Seeing some 0 left and 0 top coordinates in OCR, remove it entirely to prevent odd rendering
141
+ // eg https://archive.org/details/illustratedbooko00robe/page/n11/mode/2up
142
+ $(XMLpage).find("WORD").filter((_, ele) => {
143
+ const [left, , , top] = ele.getAttribute('coords').split(",").map(parseFloat);
144
+ if (left == 0 && top == 0) {
145
+ console.error("Found invalid ocr word coordinates");
146
+ return true;
147
+ }
148
+ }).remove();
140
149
  recursivelyAddCoords(XMLpage);
141
150
 
142
151
  const totalWords = $(XMLpage).find("WORD").length;
@@ -26,6 +26,7 @@ import SearchView from './view.js';
26
26
  import { marshallSearchResults } from './utils.js';
27
27
  import { BookReaderPlugin } from '../../BookReaderPlugin.js';
28
28
  import { applyVariables } from '../../util/strings.js';
29
+ import { toISO6391 } from '../tts/utils.js';
29
30
  /** @typedef {import('../../BookReader/PageContainer').PageContainer} PageContainer */
30
31
  /** @typedef {import('../../BookReader/BookModel').PageIndex} PageIndex */
31
32
  /** @typedef {import('../../BookReader/BookModel').LeafNum} LeafNum */
@@ -239,11 +240,13 @@ export class SearchPlugin extends BookReaderPlugin {
239
240
  * @param {boolean} options.goToFirstResult
240
241
  */
241
242
  BRSearchCallback(results, options) {
243
+ const bookLangCode = toISO6391(this.br.options.bookLanguage);
242
244
  marshallSearchResults(
243
245
  results,
244
246
  pageNum => this.br.book.getPageNum(this.br.book.leafNumToIndex(pageNum)),
245
247
  this.options.preTag,
246
248
  this.options.postTag,
249
+ bookLangCode,
247
250
  );
248
251
  this.searchResults = results || null;
249
252
 
@@ -435,6 +438,7 @@ BookReader?.registerPlugin('search', SearchPlugin);
435
438
  * @property {string} displayPageNumber (fake field) The page number as it should be displayed in the UI.
436
439
  * @property {string} html (computed field) The html-escaped raw html to display in the UI.
437
440
  * @property {string} text
441
+ * @property {string} lang (fake field) The ISO 639-1 language code of the book
438
442
  * @property {Array<{ page: number, boxes: SearchInsideMatchBox[] }>} par
439
443
  */
440
444
 
@@ -1,4 +1,8 @@
1
+ // @ts-check
1
2
  import { escapeHTML, escapeRegExp } from '../../BookReader/utils.js';
3
+ /** @typedef {import('@/src/plugins/search/plugin.search.js').SearchInsideResults} SearchInsideResults */
4
+ /** @typedef {import('@/src/plugins/search/plugin.search.js').LeafNum} LeafNum */
5
+ /** @typedef {import('@/src/plugins/search/plugin.search.js').PageNumString} PageNumString */
2
6
 
3
7
  /**
4
8
  * @param {string} match
@@ -26,14 +30,17 @@ export function renderMatch(match, preTag, postTag) {
26
30
  * @param {(pageNum: LeafNum) => PageNumString} displayPageNumberFn
27
31
  * @param {string} preTag
28
32
  * @param {string} postTag
33
+ * @param {string | null} bookLanguage The ISO 639-1 language code of the book
29
34
  */
30
- export function marshallSearchResults(results, displayPageNumberFn, preTag, postTag) {
35
+ export function marshallSearchResults(results, displayPageNumberFn, preTag, postTag, bookLanguage) {
31
36
  // Attach matchIndex to a few things to make it easier to identify
32
37
  // an active/selected match
38
+
33
39
  for (const [index, match] of results.matches.entries()) {
34
40
  match.matchIndex = index;
35
41
  match.displayPageNumber = displayPageNumberFn(match.par[0].page);
36
42
  match.html = renderMatch(match.text, preTag, postTag);
43
+ match.lang = bookLanguage;
37
44
  for (const par of match.par) {
38
45
  for (const box of par.boxes) {
39
46
  box.matchIndex = index;
@@ -60,7 +60,7 @@ class SearchView {
60
60
 
61
61
  renderSearchNavigation() {
62
62
  const selector = 'BRsearch-navigation';
63
- $('.BRnav').before(`
63
+ $('.BRnav.BRnavMain').before(`
64
64
  <div class="${selector}">
65
65
  <button class="toggle-sidebar">
66
66
  <h4>