@internetarchive/bookreader 5.0.0-7 → 5.0.0-70-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.
Files changed (307) hide show
  1. package/.eslintrc.js +17 -15
  2. package/.github/workflows/node.js.yml +73 -10
  3. package/.github/workflows/npm-publish.yml +6 -20
  4. package/.testcaferc.js +10 -0
  5. package/BookReader/BookReader.css +396 -1129
  6. package/BookReader/BookReader.js +1 -1
  7. package/BookReader/BookReader.js.LICENSE.txt +20 -20
  8. package/BookReader/BookReader.js.map +1 -1
  9. package/BookReader/ia-bookreader-bundle.js +1788 -0
  10. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +19 -0
  11. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  12. package/BookReader/icons/1up.svg +1 -1
  13. package/BookReader/icons/2up.svg +1 -1
  14. package/BookReader/icons/advance.svg +1 -1
  15. package/BookReader/icons/chevron-right.svg +1 -1
  16. package/BookReader/icons/close-circle-dark.svg +1 -1
  17. package/BookReader/icons/close-circle.svg +1 -1
  18. package/BookReader/icons/fullscreen.svg +1 -1
  19. package/BookReader/icons/fullscreen_exit.svg +1 -1
  20. package/BookReader/icons/hamburger.svg +1 -1
  21. package/BookReader/icons/left-arrow.svg +1 -1
  22. package/BookReader/icons/magnify-minus.svg +1 -1
  23. package/BookReader/icons/magnify-plus.svg +1 -1
  24. package/BookReader/icons/magnify.svg +1 -1
  25. package/BookReader/icons/pause.svg +1 -1
  26. package/BookReader/icons/play.svg +1 -1
  27. package/BookReader/icons/playback-speed.svg +1 -1
  28. package/BookReader/icons/read-aloud.svg +1 -1
  29. package/BookReader/icons/review.svg +1 -1
  30. package/BookReader/icons/thumbnails.svg +1 -1
  31. package/BookReader/icons/voice.svg +1 -0
  32. package/BookReader/icons/volume-full.svg +1 -1
  33. package/BookReader/images/BRicons.svg +3 -3
  34. package/BookReader/images/books_graphic.svg +1 -1
  35. package/BookReader/images/icon_book.svg +1 -1
  36. package/BookReader/images/icon_bookmark.svg +1 -1
  37. package/BookReader/images/icon_gear.svg +1 -1
  38. package/BookReader/images/icon_hamburger.svg +1 -1
  39. package/BookReader/images/icon_home.svg +1 -1
  40. package/BookReader/images/icon_info.svg +1 -1
  41. package/BookReader/images/icon_one_page.svg +1 -1
  42. package/BookReader/images/icon_pause.svg +1 -1
  43. package/BookReader/images/icon_play.svg +1 -1
  44. package/BookReader/images/icon_playback-rate.svg +1 -1
  45. package/BookReader/images/icon_search_button.svg +1 -1
  46. package/BookReader/images/icon_share.svg +1 -1
  47. package/BookReader/images/icon_skip-ahead.svg +1 -1
  48. package/BookReader/images/icon_skip-back.svg +1 -1
  49. package/BookReader/images/icon_speaker.svg +1 -1
  50. package/BookReader/images/icon_speaker_open.svg +1 -1
  51. package/BookReader/images/icon_thumbnails.svg +1 -1
  52. package/BookReader/images/icon_toc.svg +1 -1
  53. package/BookReader/images/icon_two_pages.svg +1 -1
  54. package/BookReader/images/marker_chap-off.svg +1 -1
  55. package/BookReader/images/marker_chap-on.svg +1 -1
  56. package/BookReader/images/marker_srch-on.svg +1 -1
  57. package/BookReader/jquery-3.js +2 -0
  58. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  59. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  60. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  61. package/BookReader/plugins/plugin.autoplay.js +1 -1
  62. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  63. package/BookReader/plugins/plugin.chapters.js +25 -1
  64. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
  65. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  66. package/BookReader/plugins/plugin.iframe.js +1 -1
  67. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  68. package/BookReader/plugins/plugin.resume.js +1 -1
  69. package/BookReader/plugins/plugin.resume.js.map +1 -1
  70. package/BookReader/plugins/plugin.search.js +2 -1
  71. package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
  72. package/BookReader/plugins/plugin.search.js.map +1 -1
  73. package/BookReader/plugins/plugin.text_selection.js +2 -1
  74. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
  75. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  76. package/BookReader/plugins/plugin.tts.js +1 -1
  77. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +2 -0
  78. package/BookReader/plugins/plugin.tts.js.map +1 -1
  79. package/BookReader/plugins/plugin.url.js +1 -1
  80. package/BookReader/plugins/plugin.url.js.map +1 -1
  81. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  82. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  83. package/BookReader/webcomponents-bundle.js +3 -0
  84. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  85. package/BookReader/webcomponents-bundle.js.map +1 -0
  86. package/BookReaderDemo/BookReaderDemo.css +16 -19
  87. package/BookReaderDemo/BookReaderJSAdvanced.js +0 -3
  88. package/BookReaderDemo/BookReaderJSAutoplay.js +4 -1
  89. package/BookReaderDemo/BookReaderJSSimple.js +1 -0
  90. package/BookReaderDemo/IADemoBr.js +147 -0
  91. package/BookReaderDemo/demo-advanced.html +2 -2
  92. package/BookReaderDemo/demo-autoplay.html +2 -3
  93. package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
  94. package/BookReaderDemo/demo-fullscreen-mobile.html +3 -5
  95. package/BookReaderDemo/demo-fullscreen.html +2 -4
  96. package/BookReaderDemo/demo-iiif.html +2 -1
  97. package/BookReaderDemo/demo-iiif.js +0 -1
  98. package/BookReaderDemo/demo-internetarchive.html +213 -17
  99. package/BookReaderDemo/demo-multiple.html +2 -1
  100. package/BookReaderDemo/demo-preview-pages.html +2 -1
  101. package/BookReaderDemo/demo-simple.html +2 -1
  102. package/BookReaderDemo/demo-vendor-fullscreen.html +2 -4
  103. package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
  104. package/BookReaderDemo/immersion-1up.html +2 -2
  105. package/BookReaderDemo/immersion-mode.html +2 -4
  106. package/BookReaderDemo/toggle_controls.html +3 -2
  107. package/BookReaderDemo/view_mode.html +2 -1
  108. package/BookReaderDemo/viewmode-cycle.html +2 -3
  109. package/CHANGELOG.md +279 -0
  110. package/README.md +14 -1
  111. package/babel.config.js +20 -0
  112. package/codecov.yml +6 -0
  113. package/index.html +4 -1
  114. package/jsconfig.json +19 -0
  115. package/netlify.toml +9 -0
  116. package/package.json +69 -60
  117. package/renovate.json +52 -0
  118. package/scripts/preversion.js +4 -1
  119. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  120. package/src/BookNavigator/assets/button-base.js +4 -2
  121. package/src/BookNavigator/assets/ia-logo.js +17 -0
  122. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  123. package/src/BookNavigator/assets/icon_close.js +1 -1
  124. package/src/BookNavigator/book-navigator.js +586 -0
  125. package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
  126. package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
  127. package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
  128. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
  129. package/src/BookNavigator/bookmarks/bookmarks-provider.js +27 -17
  130. package/src/BookNavigator/bookmarks/ia-bookmarks.js +116 -67
  131. package/src/BookNavigator/delete-modal-actions.js +1 -1
  132. package/src/BookNavigator/downloads/downloads-provider.js +36 -21
  133. package/src/BookNavigator/downloads/downloads.js +41 -25
  134. package/src/BookNavigator/search/search-provider.js +49 -27
  135. package/src/BookNavigator/search/search-results.js +23 -9
  136. package/src/BookNavigator/sharing.js +27 -0
  137. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
  138. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
  139. package/src/BookNavigator/volumes/volumes-provider.js +95 -0
  140. package/src/BookReader/BookModel.js +64 -34
  141. package/src/BookReader/DragScrollable.js +233 -0
  142. package/src/BookReader/Mode1Up.js +56 -351
  143. package/src/BookReader/Mode1UpLit.js +388 -0
  144. package/src/BookReader/Mode2Up.js +73 -1318
  145. package/src/BookReader/Mode2UpLit.js +776 -0
  146. package/src/BookReader/ModeCoordinateSpace.js +29 -0
  147. package/src/BookReader/ModeSmoothZoom.js +312 -0
  148. package/src/BookReader/ModeThumb.js +18 -12
  149. package/src/BookReader/Navbar/Navbar.js +12 -38
  150. package/src/BookReader/PageContainer.js +81 -6
  151. package/src/BookReader/ReduceSet.js +1 -1
  152. package/src/BookReader/Toolbar/Toolbar.js +10 -37
  153. package/src/BookReader/events.js +2 -3
  154. package/src/BookReader/options.js +24 -2
  155. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  156. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  157. package/src/BookReader/utils/SelectionObserver.js +43 -0
  158. package/src/BookReader/utils.js +118 -13
  159. package/src/BookReader.js +423 -1056
  160. package/src/assets/icons/magnify-minus.svg +3 -7
  161. package/src/assets/icons/magnify-plus.svg +3 -7
  162. package/src/assets/icons/voice.svg +1 -0
  163. package/src/css/BookReader.scss +1 -5
  164. package/src/css/_BRBookmarks.scss +1 -1
  165. package/src/css/_BRComponent.scss +1 -1
  166. package/src/css/_BRmain.scss +16 -0
  167. package/src/css/_BRnav.scss +11 -38
  168. package/src/css/_BRpages.scss +149 -40
  169. package/src/css/_BRsearch.scss +67 -21
  170. package/src/css/_TextSelection.scss +87 -27
  171. package/src/css/_colorbox.scss +2 -2
  172. package/src/css/_controls.scss +20 -7
  173. package/src/css/_icons.scss +1 -1
  174. package/src/ia-bookreader/ia-bookreader.js +224 -0
  175. package/src/plugins/plugin.archive_analytics.js +3 -3
  176. package/src/plugins/plugin.autoplay.js +5 -11
  177. package/src/plugins/plugin.chapters.js +211 -186
  178. package/src/plugins/plugin.resume.js +3 -3
  179. package/src/plugins/plugin.text_selection.js +464 -134
  180. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  181. package/src/plugins/search/plugin.search.js +142 -125
  182. package/src/plugins/search/utils.js +43 -0
  183. package/src/plugins/search/view.js +33 -58
  184. package/src/plugins/tts/AbstractTTSEngine.js +46 -37
  185. package/src/plugins/tts/FestivalTTSEngine.js +13 -14
  186. package/src/plugins/tts/PageChunk.js +15 -21
  187. package/src/plugins/tts/PageChunkIterator.js +8 -12
  188. package/src/plugins/tts/WebTTSEngine.js +87 -71
  189. package/src/plugins/tts/plugin.tts.js +95 -126
  190. package/src/plugins/tts/utils.js +0 -25
  191. package/src/plugins/url/UrlPlugin.js +193 -0
  192. package/src/plugins/{plugin.url.js → url/plugin.url.js} +45 -16
  193. package/src/util/browserSniffing.js +22 -0
  194. package/src/util/docCookies.js +21 -2
  195. package/tests/e2e/README.md +37 -0
  196. package/tests/e2e/autoplay.test.js +2 -2
  197. package/tests/e2e/base.test.js +8 -16
  198. package/tests/e2e/helpers/base.js +53 -48
  199. package/tests/e2e/helpers/debug.js +1 -1
  200. package/tests/e2e/helpers/params.js +17 -0
  201. package/tests/e2e/helpers/rightToLeft.js +8 -14
  202. package/tests/e2e/helpers/search.js +73 -0
  203. package/tests/e2e/models/Navigation.js +20 -37
  204. package/tests/e2e/rightToLeft.test.js +4 -5
  205. package/tests/e2e/viewmode.test.js +40 -33
  206. package/tests/jest/BookNavigator/book-navigator.test.js +658 -0
  207. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
  208. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  209. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  210. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  211. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
  212. package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
  213. package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
  214. package/tests/{karma → jest}/BookNavigator/search/search-results.test.js +109 -60
  215. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
  216. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  217. package/tests/jest/BookNavigator/volumes/volumes-provider.test.js +80 -0
  218. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +74 -14
  219. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +193 -0
  220. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  221. package/tests/jest/BookReader/Mode1UpLit.test.js +73 -0
  222. package/tests/jest/BookReader/Mode2Up.test.js +98 -0
  223. package/tests/jest/BookReader/Mode2UpLit.test.js +190 -0
  224. package/tests/jest/BookReader/ModeCoordinateSpace.test.js +16 -0
  225. package/tests/jest/BookReader/ModeSmoothZoom.test.js +218 -0
  226. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  227. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +10 -10
  228. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
  229. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  230. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  231. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  232. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  233. package/tests/jest/BookReader/utils/SelectionObserver.test.js +43 -0
  234. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  235. package/tests/jest/BookReader/utils.test.js +229 -0
  236. package/tests/jest/BookReader.keyboard.test.js +190 -0
  237. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  238. package/tests/{BookReader.test.js → jest/BookReader.test.js} +26 -37
  239. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  240. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
  241. package/tests/jest/plugins/plugin.chapters.test.js +145 -0
  242. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  243. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  244. package/tests/jest/plugins/plugin.text_selection.test.js +317 -0
  245. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  246. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +25 -47
  247. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +39 -6
  248. package/tests/jest/plugins/search/utils.js +25 -0
  249. package/tests/jest/plugins/search/utils.test.js +29 -0
  250. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +9 -9
  251. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  252. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  253. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  254. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +47 -1
  255. package/tests/{plugins → jest/plugins}/tts/utils.test.js +1 -60
  256. package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
  257. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +53 -14
  258. package/tests/jest/setup.js +3 -0
  259. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  260. package/tests/jest/util/docCookies.test.js +24 -0
  261. package/tests/{util → jest/util}/strings.test.js +1 -1
  262. package/tests/{utils.js → jest/utils.js} +38 -0
  263. package/webpack.config.js +11 -6
  264. package/.babelrc +0 -12
  265. package/.dependabot/config.yml +0 -6
  266. package/.testcaferc.json +0 -5
  267. package/BookReader/bookreader-component-bundle.js +0 -1450
  268. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  269. package/BookReader/bookreader-component-bundle.js.map +0 -1
  270. package/BookReader/jquery-1.10.1.js +0 -2
  271. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  272. package/BookReader/plugins/plugin.menu_toggle.js +0 -2
  273. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  274. package/BookReader/plugins/plugin.mobile_nav.js +0 -2
  275. package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
  276. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  277. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  278. package/karma.conf.js +0 -23
  279. package/src/BookNavigator/BookModel.js +0 -14
  280. package/src/BookNavigator/BookNavigator.js +0 -446
  281. package/src/BookNavigator/assets/book-loader.js +0 -27
  282. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  283. package/src/BookNavigator/search/a-search-result.js +0 -55
  284. package/src/BookReader/DebugConsole.js +0 -54
  285. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  286. package/src/ItemNavigator/ItemNavigator.js +0 -376
  287. package/src/ItemNavigator/providers/sharing.js +0 -29
  288. package/src/css/_MobileNav.scss +0 -194
  289. package/src/dragscrollable-br.js +0 -261
  290. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  291. package/src/plugins/plugin.mobile_nav.js +0 -287
  292. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  293. package/tests/BookReader/DebugConsole.test.js +0 -25
  294. package/tests/BookReader/Mode1Up.test.js +0 -164
  295. package/tests/BookReader/Mode2Up.test.js +0 -247
  296. package/tests/BookReader/utils.test.js +0 -109
  297. package/tests/e2e/helpers/desktopSearch.js +0 -72
  298. package/tests/e2e/helpers/mobileSearch.js +0 -85
  299. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  300. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  301. package/tests/karma/BookNavigator/search/search-provider.test.js +0 -23
  302. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  303. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
  304. package/tests/plugins/plugin.chapters.test.js +0 -130
  305. package/tests/plugins/plugin.mobile_nav.test.js +0 -66
  306. package/tests/plugins/plugin.text_selection.test.js +0 -203
  307. package/tests/util/docCookies.test.js +0 -15
@@ -1,7 +1,7 @@
1
- import { html } from 'lit-element';
2
- import { nothing } from 'lit-html';
3
-
1
+ import { html, nothing } from 'lit';
2
+ import '@internetarchive/icon-search/icon-search';
4
3
  import './search-results';
4
+ /** @typedef {import('@/src/plugins/search/plugin.search.js').SearchInsideMatch} SearchInsideMatch */
5
5
 
6
6
  let searchState = {
7
7
  query: '',
@@ -10,8 +10,11 @@ let searchState = {
10
10
  queryInProgress: false,
11
11
  errorMessage: '',
12
12
  };
13
- export default class {
14
- constructor(onSearchChange = () => {}, brInstance) {
13
+ export default class SearchProvider {
14
+ constructor({
15
+ onProviderChange,
16
+ bookreader
17
+ }) {
15
18
  /* search menu events */
16
19
  this.onBookSearchInitiated = this.onBookSearchInitiated.bind(this);
17
20
  /* bookreader search events */
@@ -26,12 +29,12 @@ export default class {
26
29
  this.bindEventListeners = this.bindEventListeners.bind(this);
27
30
  this.getMenuDetails = this.getMenuDetails.bind(this);
28
31
  this.getComponent = this.getComponent.bind(this);
29
- this.advanceToPage = this.advanceToPage.bind(this);
30
32
  this.updateMenu = this.updateMenu.bind(this);
31
33
 
32
- this.onSearchChange = onSearchChange;
33
- this.bookreader = brInstance;
34
- this.icon = html`<ia-icon icon="search" style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon>`;
34
+ this.onProviderChange = onProviderChange;
35
+ /** @type {import('@/src/BookReader.js').default} */
36
+ this.bookreader = bookreader;
37
+ this.icon = html`<ia-icon-search style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon-search>`;
35
38
  this.label = 'Search inside';
36
39
  this.menuDetails = this.getMenuDetails();
37
40
  this.id = 'search';
@@ -41,7 +44,7 @@ export default class {
41
44
 
42
45
  getMenuDetails() {
43
46
  const { resultsCount, query, queryInProgress } = searchState;
44
- if (queryInProgress || !query) { return nothing }
47
+ if (queryInProgress || !query) { return nothing; }
45
48
  const unit = resultsCount === 1 ? 'result' : 'results';
46
49
  return html`(${resultsCount} ${unit})`;
47
50
  }
@@ -49,11 +52,11 @@ export default class {
49
52
  bindEventListeners() {
50
53
  window.addEventListener('BookReader:SearchStarted', this.onSearchStarted);
51
54
  window.addEventListener('BookReader:SearchCallback', this.onSearchResultsChange);
52
- window.addEventListener('BookReader:SearchCallbackEmpty', (event) => { this.onSearchRequestError(event, 'noResults') });
53
- window.addEventListener('BookReader:SearchCallbackNotIndexed', (event) => { this.onSearchRequestError(event, 'notIndexed') });
54
- window.addEventListener('BookReader:SearchCallbackError', (event) => { this.onSearchRequestError(event) });
55
- window.addEventListener('BookReader:SearchResultsCleared', () => { this.onSearchResultsCleared() });
56
- window.addEventListener('BookReader:SearchCanceled', (e) => { this.onSearchCanceled(e) });
55
+ window.addEventListener('BookReader:SearchCallbackEmpty', (event) => { this.onSearchRequestError(event, 'noResults'); });
56
+ window.addEventListener('BookReader:SearchCallbackNotIndexed', (event) => { this.onSearchRequestError(event, 'notIndexed'); });
57
+ window.addEventListener('BookReader:SearchCallbackError', (event) => { this.onSearchRequestError(event); });
58
+ window.addEventListener('BookReader:SearchResultsCleared', () => { this.onSearchResultsCleared(); });
59
+ window.addEventListener('BookReader:SearchCanceled', (e) => { this.onSearchCanceled(e); });
57
60
  }
58
61
 
59
62
  /**
@@ -72,10 +75,17 @@ export default class {
72
75
  searchCanceled: true
73
76
  };
74
77
  this.updateMenu(updateMenuFor);
78
+
79
+ if (this.bookreader.urlPlugin) {
80
+ this.updateSearchInUrl();
81
+ }
75
82
  }
76
83
 
77
84
  onSearchStarted(e) {
78
- const { term = '' } = e.detail.props;
85
+ const { term = '', instance } = e.detail.props;
86
+ if (instance) {
87
+ this.bookreader = instance;
88
+ }
79
89
  searchState.query = term;
80
90
  searchState.results = [];
81
91
  searchState.resultsCount = 0;
@@ -104,6 +114,7 @@ export default class {
104
114
  };
105
115
 
106
116
  const messageToShow = errorMessages[errorType] ?? errorMessages.default;
117
+ searchState.query = instance?.searchResults?.q || '';
107
118
  searchState.results = [];
108
119
  searchState.resultsCount = 0;
109
120
  searchState.queryInProgress = false;
@@ -136,9 +147,24 @@ export default class {
136
147
  resultsCount: 0,
137
148
  queryInProgress: false,
138
149
  errorMessage: '',
150
+ };
151
+ this.updateMenu({ openMenu: false });
152
+ this.bookreader?.searchView?.clearSearchFieldAndResults(false);
153
+ if (this.bookreader.urlPlugin) {
154
+ this.updateSearchInUrl();
155
+ }
156
+ }
157
+
158
+ /** update URL `q=<term>` query param in URL */
159
+ updateSearchInUrl() {
160
+ if (this.bookreader.urlPlugin) {
161
+ this.bookreader.urlPlugin.pullFromAddressBar();
162
+ if (searchState.query) {
163
+ this.bookreader.urlPlugin.setUrlParam('q', searchState.query);
164
+ } else {
165
+ this.bookreader.urlPlugin.removeUrlParam('q');
166
+ }
139
167
  }
140
- this.updateMenu();
141
- this.bookreader?.searchView?.clearSearchFieldAndResults();
142
168
  }
143
169
 
144
170
  /**
@@ -148,7 +174,7 @@ export default class {
148
174
  updateMenu(searchUpdates = {}) {
149
175
  this.menuDetails = this.getMenuDetails();
150
176
  this.component = this.getComponent();
151
- this.onSearchChange(this.bookreader, searchUpdates);
177
+ this.onProviderChange(this.bookreader, searchUpdates);
152
178
  }
153
179
 
154
180
  getComponent() {
@@ -168,14 +194,10 @@ export default class {
168
194
  `;
169
195
  }
170
196
 
197
+ /**
198
+ * @param {{ detail: {match: SearchInsideMatch} }} param0
199
+ */
171
200
  onSearchResultsClicked({ detail }) {
172
- const page = detail.match.par[0].page;
173
- this.advanceToPage(page);
174
- }
175
-
176
- advanceToPage(leaf) {
177
- const page = this.bookreader.leafNumToIndex(leaf);
178
- this.bookreader._searchPluginGoToResult(page);
179
- this.bookreader.updateSearchHilites();
201
+ this.bookreader._searchPluginGoToResult(detail.match.matchIndex);
180
202
  }
181
203
  }
@@ -1,12 +1,11 @@
1
1
  /* eslint-disable class-methods-use-this */
2
- import { nothing } from 'lit-html';
3
- import { css, html, LitElement } from 'lit-element';
2
+ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
3
+ import { css, html, LitElement, nothing } from 'lit';
4
4
  import '@internetarchive/ia-activity-indicator/ia-activity-indicator';
5
- import './a-search-result.js';
6
5
  import checkmarkIcon from '../assets/icon_checkmark.js';
7
6
  import closeIcon from '../assets/icon_close.js';
8
7
  import buttonCSS from '../assets/button-base.js';
9
-
8
+ /** @typedef {import('@/src/plugins/search/plugin.search.js').SearchInsideMatch} SearchInsideMatch */
10
9
 
11
10
  export class IABookSearchResults extends LitElement {
12
11
  static get properties() {
@@ -24,6 +23,7 @@ export class IABookSearchResults extends LitElement {
24
23
  constructor() {
25
24
  super();
26
25
 
26
+ /** @type {SearchInsideMatch[]} */
27
27
  this.results = [];
28
28
  this.query = '';
29
29
  this.queryInProgress = false;
@@ -61,6 +61,9 @@ export class IABookSearchResults extends LitElement {
61
61
 
62
62
  setQuery(e) {
63
63
  this.query = e.currentTarget.value;
64
+ if (!this.query) {
65
+ this.cancelSearch();
66
+ }
64
67
  }
65
68
 
66
69
  performSearch(e) {
@@ -78,7 +81,15 @@ export class IABookSearchResults extends LitElement {
78
81
  }));
79
82
  }
80
83
 
81
- selectResult() {
84
+ /**
85
+ * @param {SearchInsideMatch} match
86
+ */
87
+ selectResult(match) {
88
+ this.dispatchEvent(new CustomEvent('resultSelected', {
89
+ bubbles: true,
90
+ composed: true,
91
+ detail: { match },
92
+ }));
82
93
  this.dispatchEvent(new CustomEvent('closeMenu', {
83
94
  bubbles: true,
84
95
  composed: true,
@@ -130,10 +141,12 @@ export class IABookSearchResults extends LitElement {
130
141
  return html`
131
142
  <ul class="results ${resultsClass}">
132
143
  ${this.results.map(match => html`
133
- <book-search-result
134
- .match=${match}
135
- @resultSelected=${this.selectResult}
136
- ></book-search-result>
144
+ <li @click=${this.selectResult.bind(this, match)}>
145
+ ${match.cover ? html`<img src="${match.cover}" />` : nothing}
146
+ <h4>${match.title || nothing}</h4>
147
+ <p class="page-num">Page ${match.displayPageNumber}</p>
148
+ <p>${unsafeHTML(match.html)}</p>
149
+ </li>
137
150
  `)}
138
151
  </ul>
139
152
  `;
@@ -149,6 +162,7 @@ export class IABookSearchResults extends LitElement {
149
162
  name="query"
150
163
  alt="Search inside this book."
151
164
  @keyup=${this.setQuery}
165
+ @search=${this.setQuery}
152
166
  .value=${this.query}
153
167
  />
154
168
  </fieldset>
@@ -0,0 +1,27 @@
1
+ import { html } from 'lit';
2
+ import { iauxShareIcon } from '@internetarchive/ia-item-navigator';
3
+ import '@internetarchive/ia-item-navigator';
4
+
5
+ export default class SharingProvider {
6
+ constructor({
7
+ item,
8
+ baseHost,
9
+ bookreader
10
+ }) {
11
+ const { identifier, creator, title } = item?.metadata;
12
+ const creatorToUse = Array.isArray(creator) ? creator[0] : creator;
13
+ const subPrefix = bookreader.options.subPrefix || '';
14
+ const label = `Share this book`;
15
+ this.icon = html`${iauxShareIcon}`;
16
+ this.label = label;
17
+ this.id = 'share';
18
+ this.component = html`<iaux-sharing-options
19
+ .identifier=${identifier}
20
+ .type=${`book`}
21
+ .creator=${creatorToUse}
22
+ .description=${title}
23
+ .baseHost=${baseHost}
24
+ .fileSubPrefix=${subPrefix}
25
+ ></iaux-sharing-options>`;
26
+ }
27
+ }
@@ -1,5 +1,6 @@
1
- import { html } from 'lit-element';
2
- import './visual-adjustments.js';
1
+ import { html } from 'lit';
2
+ import '@internetarchive/icon-visual-adjustment/icon-visual-adjustment';
3
+ import './visual-adjustments';
3
4
 
4
5
  const visualAdjustmentOptions = [{
5
6
  id: 'brightness',
@@ -27,11 +28,11 @@ const visualAdjustmentOptions = [{
27
28
  active: false,
28
29
  }];
29
30
 
30
- export default class {
31
+ export default class VisualAdjustmentsProvider {
31
32
  constructor(options) {
32
- const { onOptionChange = () => {}, bookContainerSelector, bookreader } = options;
33
- this.onOptionChange = onOptionChange;
34
- this.bookContainerSelector = bookContainerSelector;
33
+ const { onProviderChange, bookreader } = options;
34
+ this.onProviderChange = onProviderChange;
35
+ this.bookContainer = bookreader.refs.$brContainer;
35
36
  this.bookreader = bookreader;
36
37
 
37
38
  this.onAdjustmentChange = this.onAdjustmentChange.bind(this);
@@ -41,7 +42,7 @@ export default class {
41
42
  this.onZoomOut = this.onZoomOut.bind(this);
42
43
 
43
44
  this.activeCount = 0;
44
- this.icon = html`<ia-icon icon="visualAdjustment" style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon>`;
45
+ this.icon = html`<ia-icon-visual-adjustment style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon-visual-adjustment>`;
45
46
  this.label = 'Visual Adjustments';
46
47
  this.menuDetails = this.updateOptionsCount();
47
48
  this.id = 'adjustment';
@@ -60,7 +61,7 @@ export default class {
60
61
  }
61
62
 
62
63
  onZoomOut() {
63
- this.bookreader.zoom();
64
+ this.bookreader.zoom(-1);
64
65
  }
65
66
 
66
67
  onAdjustmentChange(event) {
@@ -76,7 +77,7 @@ export default class {
76
77
  return newValue ? [...values, newValue] : values;
77
78
  }, []).join(' ');
78
79
 
79
- document.querySelector(this.bookContainerSelector).style.setProperty('filter', filters);
80
+ this.bookContainer.css('filter', filters);
80
81
 
81
82
  this.optionUpdateComplete(event);
82
83
  }
@@ -84,7 +85,7 @@ export default class {
84
85
  optionUpdateComplete(event) {
85
86
  this.activeCount = event.detail.activeCount;
86
87
  this.updateOptionsCount(event);
87
- this.onOptionChange(event);
88
+ this.onProviderChange();
88
89
  }
89
90
 
90
91
  updateOptionsCount() {
@@ -1,6 +1,6 @@
1
- import { css, html, LitElement } from "lit-element";
2
- import { repeat } from "lit-html/directives/repeat.js";
3
- import { nothing } from "lit-html";
1
+ import { css, html, LitElement } from "lit";
2
+ import { repeat } from "lit/directives/repeat.js";
3
+ import { nothing } from "lit";
4
4
  import checkmarkIcon from '../assets/icon_checkmark.js';
5
5
  import "@internetarchive/icon-magnify-minus/icon-magnify-minus";
6
6
  import "@internetarchive/icon-magnify-plus/icon-magnify-plus";
@@ -0,0 +1,95 @@
1
+ import { html } from 'lit';
2
+
3
+ import { viewableFilesIcon } from '@internetarchive/ia-item-navigator';
4
+ import '@internetarchive/ia-item-navigator';
5
+
6
+ /**
7
+ * * @typedef { 'title_asc' | 'title_desc' | 'default'} SortTypesT
8
+ */
9
+ const sortTypes = {
10
+ title_asc: 'title_asc',
11
+ title_desc: 'title_desc',
12
+ default: 'default'
13
+ };
14
+ export default class VolumesProvider {
15
+ /**
16
+ * @param {import('../../BookReader').default} bookreader
17
+ */
18
+ constructor({ baseHost, bookreader, onProviderChange }) {
19
+ /** @type {import('../../BookReader').default} */
20
+ this.bookreader = bookreader;
21
+ this.onProviderChange = onProviderChange;
22
+ this.baseHost = baseHost;
23
+
24
+ const files = bookreader.options.multipleBooksList.by_subprefix;
25
+ this.viewableFiles = Object.keys(files).map(item => files[item]);
26
+ this.volumeCount = Object.keys(files).length;
27
+
28
+ this.id = "volumes";
29
+ this.label = `Viewable files (${this.volumeCount})`;
30
+ this.icon = html`${viewableFilesIcon}`;
31
+ this.sortOrderBy = sortTypes.default;
32
+
33
+ this.component = document.createElement("iaux-viewable-files");
34
+ this.component.addSortToUrl = true;
35
+ this.component.subPrefix = bookreader.options.subPrefix || "";
36
+ this.component.baseHost = baseHost;
37
+ this.component.fileList = [...this.viewableFiles];
38
+
39
+ this.sortFilesComponent = document.createElement("iaux-sort-viewable-files");
40
+ this.sortFilesComponent.fileListRaw = this.viewableFiles;
41
+ this.sortFilesComponent.addEventListener('fileListSorted', (e) => this.handleFileListSorted(e));
42
+ this.actionButton = this.sortFilesComponent;
43
+
44
+ // get sort state from query param
45
+ if (this.bookreader.urlPlugin) {
46
+ this.bookreader.urlPlugin.pullFromAddressBar();
47
+
48
+ const urlSortValue = this.bookreader.urlPlugin.getUrlParam('sort');
49
+ if (urlSortValue === sortTypes.title_asc || urlSortValue === sortTypes.title_desc) {
50
+ this.sortOrderBy = urlSortValue;
51
+ }
52
+ }
53
+
54
+ this.sortFilesComponent.sortVolumes(this.sortOrderBy);
55
+
56
+ this.onProviderChange(this.bookreader);
57
+ }
58
+
59
+ /** @param { SortTypesT } sortType */
60
+ async handleFileListSorted(event) {
61
+ const { sortType, sortedFiles } = event.detail;
62
+
63
+ this.viewableFiles = sortedFiles;
64
+ this.sortOrderBy = sortType;
65
+
66
+ // update the component
67
+ this.component.fileList = [...this.viewableFiles];
68
+ await this.component.updateComplete;
69
+
70
+ if (this.bookreader.urlPlugin) {
71
+ this.bookreader.urlPlugin.pullFromAddressBar();
72
+ if (this.sortOrderBy !== sortTypes.default) {
73
+ this.bookreader.urlPlugin.setUrlParam('sort', this.sortOrderBy);
74
+ } else {
75
+ this.bookreader.urlPlugin.removeUrlParam('sort');
76
+ }
77
+ }
78
+
79
+ this.onProviderChange(this.bookreader);
80
+
81
+ this.multipleFilesClicked(this.sortOrderBy);
82
+ }
83
+
84
+ /**
85
+ * @param { SortTypesT } orderBy
86
+ */
87
+ multipleFilesClicked(orderBy) {
88
+ window.archive_analytics?.send_event(
89
+ 'BookReader',
90
+ `VolumesSort|${orderBy}`,
91
+ window.location.path,
92
+ );
93
+ }
94
+
95
+ }
@@ -23,42 +23,15 @@ export class BookModel {
23
23
  this.br = br;
24
24
  this.reduceSet = br.reduceSet;
25
25
  this.ppi = br.options?.ppi ?? DEFAULT_OPTIONS.ppi;
26
+ /** @type {'lr' | 'rl'} Page progression */
27
+ this.pageProgression = br.options?.pageProgression ?? DEFAULT_OPTIONS.pageProgression;
26
28
 
27
29
  /** @type {{width: number, height: number}} memoize storage */
28
30
  this._medianPageSize = null;
29
- /** @deprecated @type {{width: number, height: number}} memoize storage */
30
- this._medianPageSizePixels = null;
31
31
  /** @type {[PageData[], number]} */
32
32
  this._getDataFlattenedCached = null;
33
33
  }
34
34
 
35
- /**
36
- * @deprecated Use getMedianPageSizeInches
37
- * Memoized
38
- * @return {{width: number, height: number}}
39
- */
40
- getMedianPageSize() {
41
- if (this._medianPageSizePixels) {
42
- return this._medianPageSizePixels;
43
- }
44
-
45
- // A little expensive but we just do it once
46
- const widths = [];
47
- const heights = [];
48
- for (let i = 0; i < this.getNumLeafs(); i++) {
49
- widths.push(this.getPageWidth(i));
50
- heights.push(this.getPageHeight(i));
51
- }
52
-
53
- widths.sort();
54
- heights.sort();
55
- this._medianPageSizePixels = {
56
- width: widths[Math.floor(widths.length / 2)],
57
- height: heights[Math.floor(heights.length / 2)]
58
- };
59
- return this._medianPageSizePixels;
60
- }
61
-
62
35
  /** Get median width/height of page in inches. Memoized for performance. */
63
36
  getMedianPageSizeInches() {
64
37
  if (this._medianPageSize) {
@@ -72,8 +45,8 @@ export class BookModel {
72
45
  heights.push(page.heightInches);
73
46
  }
74
47
 
75
- widths.sort();
76
- heights.sort();
48
+ widths.sort((a, b) => a - b);
49
+ heights.sort((a, b) => a - b);
77
50
 
78
51
  this._medianPageSize = {
79
52
  width: widths[Math.floor(widths.length / 2)],
@@ -226,7 +199,7 @@ export class BookModel {
226
199
  * @return {[PageIndex, PageIndex]} eg [0, 1]
227
200
  */
228
201
  getSpreadIndices(pindex) {
229
- if (this.br.pageProgression == 'rl') {
202
+ if (this.pageProgression == 'rl') {
230
203
  return this.getPageSide(pindex) == 'R' ? [pindex + 1, pindex] : [pindex, pindex - 1];
231
204
  } else {
232
205
  return this.getPageSide(pindex) == 'L' ? [pindex, pindex + 1] : [pindex - 1, pindex];
@@ -379,8 +352,9 @@ export class PageModel {
379
352
  * @param {PageIndex} index
380
353
  */
381
354
  constructor(book, index) {
382
- // TODO: Get default from config
383
- this.ppi = book._getDataProp(index, 'ppi', book.ppi);
355
+ // Values less than 10 cause the UI to not work correctly
356
+ const pagePPI = book._getDataProp(index, 'ppi', book.ppi);
357
+ this.ppi = Math.max(pagePPI < 10 ? book.ppi : pagePPI, 10);
384
358
  this.book = book;
385
359
  this.index = index;
386
360
  this.width = book.getPageWidth(index);
@@ -437,6 +411,42 @@ export class PageModel {
437
411
  return this.findNext();
438
412
  }
439
413
 
414
+ /** @type {PageModel | null} */
415
+ get left() {
416
+ return this.book.pageProgression === 'lr' ? this.prev : this.next;
417
+ }
418
+
419
+ /** @type {PageModel | null} */
420
+ get right() {
421
+ return this.book.pageProgression === 'lr' ? this.next : this.prev;
422
+ }
423
+
424
+ /**
425
+ * @type {{left: PageModel | null, right: PageModel | null}}
426
+ */
427
+ get spread() {
428
+ return {
429
+ left: this.pageSide === 'L' ? this : this.left,
430
+ right: this.pageSide === 'R' ? this : this.right,
431
+ };
432
+ }
433
+
434
+ /**
435
+ * @param {number} pages
436
+ */
437
+ goLeft(pages) {
438
+ const newIndex = this.book.pageProgression === 'lr' ? this.index - pages : this.index + pages;
439
+ return this.book.getPage(newIndex);
440
+ }
441
+
442
+ /**
443
+ * @param {number} pages
444
+ */
445
+ goRight(pages) {
446
+ const newIndex = this.book.pageProgression === 'lr' ? this.index + pages : this.index - pages;
447
+ return this.book.getPage(newIndex);
448
+ }
449
+
440
450
  /**
441
451
  * @param {number} reduce
442
452
  * @param {number} rotate
@@ -498,6 +508,26 @@ export class PageModel {
498
508
  return new PageModel(this.book, this.index - 1);
499
509
  }
500
510
  }
511
+
512
+ /**
513
+ * @param {object} [arg0]
514
+ * @param {boolean} [arg0.combineConsecutiveUnviewables] Whether to only yield the first page
515
+ * of a series of unviewable pages instead of each page
516
+ * @return {PageModel|void}
517
+ */
518
+ findLeft({ combineConsecutiveUnviewables = false } = {}) {
519
+ return this.book.pageProgression === 'lr' ? this.findPrev({ combineConsecutiveUnviewables }) : this.findNext({ combineConsecutiveUnviewables });
520
+ }
521
+
522
+ /**
523
+ * @param {object} [arg0]
524
+ * @param {boolean} [arg0.combineConsecutiveUnviewables] Whether to only yield the first page
525
+ * of a series of unviewable pages instead of each page
526
+ * @return {PageModel|void}
527
+ */
528
+ findRight({ combineConsecutiveUnviewables = false } = {}) {
529
+ return this.book.pageProgression === 'lr' ? this.findNext({ combineConsecutiveUnviewables }) : this.findPrev({ combineConsecutiveUnviewables });
530
+ }
501
531
  }
502
532
 
503
533
  // There are a few main ways we can reference a specific page in a book: