@internetarchive/bookreader 5.0.0-88-alpha.8 → 5.0.0-88-alpha.10

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 (182) hide show
  1. package/dist/esm/BookNavigator/assets/bookmark-colors.js +4 -0
  2. package/dist/esm/BookNavigator/assets/button-base.js +4 -0
  3. package/dist/esm/BookNavigator/assets/ia-logo.js +4 -0
  4. package/dist/esm/BookNavigator/assets/icon_checkmark.js +8 -0
  5. package/dist/esm/BookNavigator/assets/icon_close.js +4 -0
  6. package/dist/esm/BookNavigator/book-navigator.js +612 -0
  7. package/dist/esm/BookNavigator/bookmarks/bookmark-button.js +35 -0
  8. package/dist/esm/BookNavigator/bookmarks/bookmark-edit.js +78 -0
  9. package/dist/esm/BookNavigator/bookmarks/bookmarks-list.js +160 -0
  10. package/dist/esm/BookNavigator/bookmarks/bookmarks-loginCTA.js +24 -0
  11. package/dist/esm/BookNavigator/bookmarks/bookmarks-provider.js +55 -0
  12. package/dist/esm/BookNavigator/bookmarks/ia-bookmarks.js +521 -0
  13. package/dist/esm/BookNavigator/delete-modal-actions.js +29 -0
  14. package/dist/esm/BookNavigator/downloads/downloads-provider.js +84 -0
  15. package/dist/esm/BookNavigator/downloads/downloads.js +69 -0
  16. package/dist/esm/BookNavigator/search/search-provider.js +238 -0
  17. package/dist/esm/BookNavigator/search/search-results.js +161 -0
  18. package/dist/esm/BookNavigator/sharing.js +26 -0
  19. package/dist/esm/BookNavigator/viewable-files.js +94 -0
  20. package/dist/esm/BookNavigator/visual-adjustments/visual-adjustments-provider.js +83 -0
  21. package/dist/esm/BookNavigator/visual-adjustments/visual-adjustments.js +131 -0
  22. package/dist/esm/BookReader/BookModel.js +575 -0
  23. package/dist/esm/BookReader/DragScrollable.js +224 -0
  24. package/dist/esm/BookReader/ImageCache.js +122 -0
  25. package/dist/esm/BookReader/Mode1Up.js +114 -0
  26. package/dist/esm/BookReader/Mode1UpLit.js +579 -0
  27. package/dist/esm/BookReader/Mode2Up.js +106 -0
  28. package/dist/esm/BookReader/Mode2UpLit.js +1020 -0
  29. package/dist/esm/BookReader/ModeCoordinateSpace.js +28 -0
  30. package/dist/esm/BookReader/ModeSmoothZoom.js +318 -0
  31. package/dist/esm/BookReader/ModeThumb.js +366 -0
  32. package/dist/esm/BookReader/Navbar/Navbar.js +253 -0
  33. package/dist/esm/BookReader/PageContainer.js +165 -0
  34. package/dist/esm/BookReader/ReduceSet.js +27 -0
  35. package/dist/esm/BookReader/Toolbar/Toolbar.js +242 -0
  36. package/dist/esm/BookReader/events.js +20 -0
  37. package/dist/esm/BookReader/options.js +331 -0
  38. package/dist/esm/BookReader/utils/HTMLDimensionsCacher.js +48 -0
  39. package/dist/esm/BookReader/utils/ScrollClassAdder.js +31 -0
  40. package/dist/esm/BookReader/utils/SelectionObserver.js +42 -0
  41. package/dist/esm/BookReader/utils/classes.js +37 -0
  42. package/dist/esm/BookReader/utils.js +315 -0
  43. package/dist/esm/BookReader.js +1827 -0
  44. package/dist/esm/assets/icons/1up.svg +12 -0
  45. package/dist/esm/assets/icons/2up.svg +15 -0
  46. package/dist/esm/assets/icons/advance.svg +26 -0
  47. package/dist/esm/assets/icons/chevron-right.svg +1 -0
  48. package/dist/esm/assets/icons/close-circle-dark.svg +1 -0
  49. package/dist/esm/assets/icons/close-circle.svg +1 -0
  50. package/dist/esm/assets/icons/fullscreen.svg +17 -0
  51. package/dist/esm/assets/icons/fullscreen_exit.svg +17 -0
  52. package/dist/esm/assets/icons/hamburger.svg +15 -0
  53. package/dist/esm/assets/icons/left-arrow.svg +12 -0
  54. package/dist/esm/assets/icons/magnify-minus.svg +12 -0
  55. package/dist/esm/assets/icons/magnify-plus.svg +13 -0
  56. package/dist/esm/assets/icons/magnify.svg +15 -0
  57. package/dist/esm/assets/icons/pause.svg +23 -0
  58. package/dist/esm/assets/icons/play.svg +22 -0
  59. package/dist/esm/assets/icons/playback-speed.svg +34 -0
  60. package/dist/esm/assets/icons/read-aloud.svg +22 -0
  61. package/dist/esm/assets/icons/review.svg +22 -0
  62. package/dist/esm/assets/icons/thumbnails.svg +17 -0
  63. package/dist/esm/assets/icons/voice.svg +1 -0
  64. package/dist/esm/assets/icons/volume-full.svg +22 -0
  65. package/dist/esm/assets/images/BRicons.png +0 -0
  66. package/dist/esm/assets/images/BRicons.svg +94 -0
  67. package/dist/esm/assets/images/BRicons_ia.png +0 -0
  68. package/dist/esm/assets/images/back_pages.png +0 -0
  69. package/dist/esm/assets/images/book_bottom_icon.png +0 -0
  70. package/dist/esm/assets/images/book_down_icon.png +0 -0
  71. package/dist/esm/assets/images/book_left_icon.png +0 -0
  72. package/dist/esm/assets/images/book_leftmost_icon.png +0 -0
  73. package/dist/esm/assets/images/book_right_icon.png +0 -0
  74. package/dist/esm/assets/images/book_rightmost_icon.png +0 -0
  75. package/dist/esm/assets/images/book_top_icon.png +0 -0
  76. package/dist/esm/assets/images/book_up_icon.png +0 -0
  77. package/dist/esm/assets/images/books_graphic.svg +177 -0
  78. package/dist/esm/assets/images/booksplit.png +0 -0
  79. package/dist/esm/assets/images/control_pause_icon.png +0 -0
  80. package/dist/esm/assets/images/control_play_icon.png +0 -0
  81. package/dist/esm/assets/images/embed_icon.png +0 -0
  82. package/dist/esm/assets/images/icon-home-ia.png +0 -0
  83. package/dist/esm/assets/images/icon_OL-logo-xs.png +0 -0
  84. package/dist/esm/assets/images/icon_alert-xs.png +0 -0
  85. package/dist/esm/assets/images/icon_book.svg +12 -0
  86. package/dist/esm/assets/images/icon_bookmark.svg +12 -0
  87. package/dist/esm/assets/images/icon_close-pop.png +0 -0
  88. package/dist/esm/assets/images/icon_download.png +0 -0
  89. package/dist/esm/assets/images/icon_gear.svg +14 -0
  90. package/dist/esm/assets/images/icon_hamburger.svg +20 -0
  91. package/dist/esm/assets/images/icon_home.png +0 -0
  92. package/dist/esm/assets/images/icon_home.svg +21 -0
  93. package/dist/esm/assets/images/icon_home_ia.png +0 -0
  94. package/dist/esm/assets/images/icon_indicator.png +0 -0
  95. package/dist/esm/assets/images/icon_info.svg +11 -0
  96. package/dist/esm/assets/images/icon_one_page.svg +8 -0
  97. package/dist/esm/assets/images/icon_pause.svg +1 -0
  98. package/dist/esm/assets/images/icon_play.svg +1 -0
  99. package/dist/esm/assets/images/icon_playback-rate.svg +15 -0
  100. package/dist/esm/assets/images/icon_return.png +0 -0
  101. package/dist/esm/assets/images/icon_search_button.svg +8 -0
  102. package/dist/esm/assets/images/icon_share.svg +9 -0
  103. package/dist/esm/assets/images/icon_skip-ahead.svg +6 -0
  104. package/dist/esm/assets/images/icon_skip-back.svg +13 -0
  105. package/dist/esm/assets/images/icon_speaker.svg +18 -0
  106. package/dist/esm/assets/images/icon_speaker_open.svg +10 -0
  107. package/dist/esm/assets/images/icon_thumbnails.svg +12 -0
  108. package/dist/esm/assets/images/icon_toc.svg +5 -0
  109. package/dist/esm/assets/images/icon_two_pages.svg +9 -0
  110. package/dist/esm/assets/images/icon_zoomer.png +0 -0
  111. package/dist/esm/assets/images/loading.gif +0 -0
  112. package/dist/esm/assets/images/logo_icon.png +0 -0
  113. package/dist/esm/assets/images/marker_chap-off.png +0 -0
  114. package/dist/esm/assets/images/marker_chap-off.svg +11 -0
  115. package/dist/esm/assets/images/marker_chap-off_ia.png +0 -0
  116. package/dist/esm/assets/images/marker_chap-on.png +0 -0
  117. package/dist/esm/assets/images/marker_chap-on.svg +11 -0
  118. package/dist/esm/assets/images/marker_srch-on.svg +11 -0
  119. package/dist/esm/assets/images/marker_srchchap-off.png +0 -0
  120. package/dist/esm/assets/images/marker_srchchap-on.png +0 -0
  121. package/dist/esm/assets/images/nav_control-dn.png +0 -0
  122. package/dist/esm/assets/images/nav_control-dn_ia.png +0 -0
  123. package/dist/esm/assets/images/nav_control-up.png +0 -0
  124. package/dist/esm/assets/images/nav_control-up_ia.png +0 -0
  125. package/dist/esm/assets/images/nav_control.png +0 -0
  126. package/dist/esm/assets/images/one_page_mode_icon.png +0 -0
  127. package/dist/esm/assets/images/paper-badge.png +0 -0
  128. package/dist/esm/assets/images/print_icon.png +0 -0
  129. package/dist/esm/assets/images/progressbar.gif +0 -0
  130. package/dist/esm/assets/images/right_edges.png +0 -0
  131. package/dist/esm/assets/images/slider.png +0 -0
  132. package/dist/esm/assets/images/slider_ia.png +0 -0
  133. package/dist/esm/assets/images/thumbnail_mode_icon.png +0 -0
  134. package/dist/esm/assets/images/transparent.png +0 -0
  135. package/dist/esm/assets/images/two_page_mode_icon.png +0 -0
  136. package/dist/esm/assets/images/unviewable_page.png +0 -0
  137. package/dist/esm/assets/images/zoom_in_icon.png +0 -0
  138. package/dist/esm/assets/images/zoom_out_icon.png +0 -0
  139. package/dist/esm/css/BookReader.scss +85 -0
  140. package/dist/esm/css/_BRBookmarks.scss +29 -0
  141. package/dist/esm/css/_BRComponent.scss +13 -0
  142. package/dist/esm/css/_BRfloat.scss +197 -0
  143. package/dist/esm/css/_BRicon.scss +54 -0
  144. package/dist/esm/css/_BRmain.scss +262 -0
  145. package/dist/esm/css/_BRnav.scss +354 -0
  146. package/dist/esm/css/_BRpages.scss +213 -0
  147. package/dist/esm/css/_BRsearch.scss +268 -0
  148. package/dist/esm/css/_BRtoolbar.scss +84 -0
  149. package/dist/esm/css/_BRvendor.scss +5 -0
  150. package/dist/esm/css/_TextSelection.scss +108 -0
  151. package/dist/esm/css/_colorbox.scss +52 -0
  152. package/dist/esm/css/_controls.scss +257 -0
  153. package/dist/esm/css/_icons.scss +121 -0
  154. package/dist/esm/ia-bookreader/ia-bookreader.js +141 -0
  155. package/dist/esm/jquery-wrapper.js +3 -0
  156. package/dist/esm/plugins/plugin.archive_analytics.js +72 -0
  157. package/dist/esm/plugins/plugin.autoplay.js +119 -0
  158. package/dist/esm/plugins/plugin.chapters.js +288 -0
  159. package/dist/esm/plugins/plugin.iframe.js +44 -0
  160. package/dist/esm/plugins/plugin.iiif.js +146 -0
  161. package/dist/esm/plugins/plugin.resume.js +66 -0
  162. package/dist/esm/plugins/plugin.text_selection.js +621 -0
  163. package/dist/esm/plugins/plugin.vendor-fullscreen.js +227 -0
  164. package/dist/esm/plugins/search/plugin.search.js +499 -0
  165. package/dist/esm/plugins/search/utils.js +42 -0
  166. package/dist/esm/plugins/search/view.js +360 -0
  167. package/dist/esm/plugins/tts/AbstractTTSEngine.js +282 -0
  168. package/dist/esm/plugins/tts/FestivalTTSEngine.js +192 -0
  169. package/dist/esm/plugins/tts/PageChunk.js +105 -0
  170. package/dist/esm/plugins/tts/PageChunkIterator.js +155 -0
  171. package/dist/esm/plugins/tts/WebTTSEngine.js +364 -0
  172. package/dist/esm/plugins/tts/plugin.tts.js +315 -0
  173. package/dist/esm/plugins/tts/tooltip_dict.js +14 -0
  174. package/dist/esm/plugins/tts/utils.js +79 -0
  175. package/dist/esm/plugins/url/UrlPlugin.js +197 -0
  176. package/dist/esm/plugins/url/plugin.url.js +212 -0
  177. package/dist/esm/util/browserSniffing.js +56 -0
  178. package/dist/esm/util/debouncer.js +25 -0
  179. package/dist/esm/util/docCookies.js +75 -0
  180. package/dist/esm/util/strings.js +34 -0
  181. package/jsconfig.json +1 -0
  182. package/package.json +1 -7
@@ -0,0 +1,315 @@
1
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
2
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
3
+ /* global BookReader */
4
+ /**
5
+ * Plugin for Text to Speech in BookReader
6
+ */
7
+ import FestivalTTSEngine from './FestivalTTSEngine.js';
8
+ import WebTTSEngine from './WebTTSEngine.js';
9
+ import { toISO6391, approximateWordCount } from './utils.js';
10
+ import { en as tooltips } from './tooltip_dict.js';
11
+ import { renderBoxesInPageContainerLayer } from '../../BookReader/PageContainer.js';
12
+ /** @typedef {import('./PageChunk.js').default} PageChunk */
13
+ /** @typedef {import("./AbstractTTSEngine.js").default} AbstractTTSEngine */
14
+
15
+ // Default options for TTS
16
+ jQuery.extend(BookReader.defaultOptions, {
17
+ server: 'ia600609.us.archive.org',
18
+ bookPath: '',
19
+ enableTtsPlugin: true
20
+ });
21
+
22
+ // Extend the constructor to add TTS properties
23
+ BookReader.prototype.setup = function (super_) {
24
+ return function (options) {
25
+ super_.call(this, options);
26
+ if (this.options.enableTtsPlugin) {
27
+ /** @type { {[pageIndex: number]: Array<{ l: number, r: number, t: number, b: number }>} } */
28
+ this._ttsBoxesByIndex = {};
29
+ var TTSEngine = WebTTSEngine.isSupported() ? WebTTSEngine : FestivalTTSEngine.isSupported() ? FestivalTTSEngine : null;
30
+ if (/_forceTTSEngine=(festival|web)/.test(location.toString())) {
31
+ var engineName = location.toString().match(/_forceTTSEngine=(festival|web)/)[1];
32
+ TTSEngine = {
33
+ festival: FestivalTTSEngine,
34
+ web: WebTTSEngine
35
+ }[engineName];
36
+ }
37
+ if (TTSEngine) {
38
+ /** @type {AbstractTTSEngine} */
39
+ this.ttsEngine = new TTSEngine({
40
+ server: options.server,
41
+ bookPath: options.bookPath,
42
+ bookLanguage: toISO6391(options.bookLanguage),
43
+ onLoadingStart: this.showProgressPopup.bind(this, 'Loading audio...'),
44
+ onLoadingComplete: this.removeProgressPopup.bind(this),
45
+ onDone: this.ttsStop.bind(this),
46
+ beforeChunkPlay: this.ttsBeforeChunkPlay.bind(this),
47
+ afterChunkPlay: this.ttsSendChunkFinishedAnalyticsEvent.bind(this)
48
+ });
49
+ }
50
+ }
51
+ };
52
+ }(BookReader.prototype.setup);
53
+ BookReader.prototype.init = function (super_) {
54
+ return function () {
55
+ if (this.options.enableTtsPlugin) {
56
+ // Bind to events
57
+
58
+ this.bind(BookReader.eventNames.PostInit, () => {
59
+ this.$('.BRicon.read').click(() => {
60
+ this.ttsToggle();
61
+ return false;
62
+ });
63
+ if (this.ttsEngine) {
64
+ this.ttsEngine.init();
65
+ if (/[?&]_autoReadAloud=show/.test(location.toString())) {
66
+ this.ttsStart(false); // false flag is to initiate read aloud controls
67
+ }
68
+ }
69
+ });
70
+
71
+ // This is fired when the hash changes by one of the other plugins!
72
+ // i.e. it will fire every time the page changes -_-
73
+ // this.bind(BookReader.eventNames.stop, function(e, br) {
74
+ // this.ttsStop();
75
+ // }.bind(this));
76
+ }
77
+ super_.call(this);
78
+ };
79
+ }(BookReader.prototype.init);
80
+
81
+ /** @override */
82
+ BookReader.prototype._createPageContainer = function (super_) {
83
+ return function (index) {
84
+ var pageContainer = super_.call(this, index);
85
+ if (this.options.enableTtsPlugin && pageContainer.page && index in this._ttsBoxesByIndex) {
86
+ var pageIndex = pageContainer.page.index;
87
+ renderBoxesInPageContainerLayer('ttsHiliteLayer', this._ttsBoxesByIndex[pageIndex], pageContainer.page, pageContainer.$container[0]);
88
+ }
89
+ return pageContainer;
90
+ };
91
+ }(BookReader.prototype._createPageContainer);
92
+
93
+ // Extend buildMobileDrawerElement
94
+ BookReader.prototype.buildMobileDrawerElement = function (super_) {
95
+ return function () {
96
+ var $el = super_.call(this);
97
+ if (this.options.enableTtsPlugin && this.ttsEngine) {
98
+ $el.find('.BRmobileMenu__moreInfoRow').after($("\n <li>\n <span>\n <span class=\"DrawerIconWrapper\"><img class=\"DrawerIcon\" src=\"".concat(this.imagesBaseURL, "icon_speaker_open.svg\" alt=\"info-speaker\"/></span>\n Read Aloud\n </span>\n <div>\n <span class=\"larger\">Press to toggle read aloud</span>\n <br/>\n <button class=\"BRicon read\"></button>\n </div>\n </li>")));
99
+ }
100
+ return $el;
101
+ };
102
+ }(BookReader.prototype.buildMobileDrawerElement);
103
+
104
+ // Extend initNavbar
105
+ BookReader.prototype.initNavbar = function (super_) {
106
+ return function () {
107
+ var $el = super_.call(this);
108
+ if (this.options.enableTtsPlugin && this.ttsEngine) {
109
+ this.refs.$BRReadAloudToolbar = $("\n <ul class=\"read-aloud\">\n <li>\n <select class=\"playback-speed\" name=\"playback-speed\" title=\"".concat(tooltips.playbackSpeed, "\">\n <option value=\"0.25\">0.25x</option>\n <option value=\"0.5\">0.5x</option>\n <option value=\"0.75\">0.75x</option>\n <option value=\"1.0\" selected>1.0x</option>\n <option value=\"1.25\">1.25x</option>\n <option value=\"1.5\">1.5x</option>\n <option value=\"1.75\">1.75x</option>\n <option value=\"2\">2x</option>\n </select>\n </li>\n <li>\n <button type=\"button\" name=\"review\" title=\"").concat(tooltips.review, "\">\n <div class=\"icon icon-review\"></div>\n </button>\n </li>\n <li>\n <button type=\"button\" name=\"play\" title=\"").concat(tooltips.play, "\">\n <div class=\"icon icon-play\"></div>\n <div class=\"icon icon-pause\"></div>\n </button>\n </li>\n <li>\n <button type=\"button\" name=\"advance\" title=\"").concat(tooltips.advance, "\">\n <div class=\"icon icon-advance\"></div>\n </button>\n </li>\n <li>\n <select class=\"playback-voices\" name=\"playback-voice\" style=\"display: none\" title=\"Change read aloud voices\">\n </select>\n </li>\n </ul>\n "));
110
+ $el.find('.BRcontrols').prepend(this.refs.$BRReadAloudToolbar);
111
+ var renderVoiceOption = voices => {
112
+ return voices.map(voice => "<option value=\"".concat(voice.voiceURI, "\">").concat(voice.lang, " - ").concat(voice.name, "</option>")).join('');
113
+ };
114
+ var voiceSortOrder = (a, b) => "".concat(a.lang, " - ").concat(a.name).localeCompare("".concat(b.lang, " - ").concat(b.name));
115
+ var renderVoicesMenu = voicesMenu => {
116
+ voicesMenu.empty();
117
+ var bookLanguage = this.ttsEngine.opts.bookLanguage;
118
+ var bookLanguages = this.ttsEngine.getVoices().filter(v => v.lang.startsWith(bookLanguage)).sort(voiceSortOrder);
119
+ var otherLanguages = this.ttsEngine.getVoices().filter(v => !v.lang.startsWith(bookLanguage)).sort(voiceSortOrder);
120
+ if (this.ttsEngine.getVoices().length > 1) {
121
+ voicesMenu.append($("<optgroup label=\"Book Language (".concat(bookLanguage, ")\"> ").concat(renderVoiceOption(bookLanguages), " </optgroup>")));
122
+ voicesMenu.append($("<optgroup label=\"Other Languages\"> ".concat(renderVoiceOption(otherLanguages), " </optgroup>")));
123
+ voicesMenu.val(this.ttsEngine.voice.voiceURI);
124
+ voicesMenu.show();
125
+ } else {
126
+ voicesMenu.hide();
127
+ }
128
+ };
129
+ var voicesMenu = this.refs.$BRReadAloudToolbar.find('[name=playback-voice]');
130
+ renderVoicesMenu(voicesMenu);
131
+ voicesMenu.on("change", ev => this.ttsEngine.setVoice(voicesMenu.val()));
132
+ this.ttsEngine.events.on('pause resume start', () => this.ttsUpdateState());
133
+ this.ttsEngine.events.on('voiceschanged', () => renderVoicesMenu(voicesMenu));
134
+ this.refs.$BRReadAloudToolbar.find('[name=play]').on("click", this.ttsPlayPause.bind(this));
135
+ this.refs.$BRReadAloudToolbar.find('[name=advance]').on("click", this.ttsJumpForward.bind(this));
136
+ this.refs.$BRReadAloudToolbar.find('[name=review]').on("click", this.ttsJumpBackward.bind(this));
137
+ var $rateSelector = this.refs.$BRReadAloudToolbar.find('select[name="playback-speed"]');
138
+ $rateSelector.on("change", ev => this.ttsEngine.setPlaybackRate(parseFloat($rateSelector.val())));
139
+ $("<li>\n <button class=\"BRicon read js-tooltip\" title=\"".concat(tooltips.readAloud, "\">\n <div class=\"icon icon-read-aloud\"></div>\n <span class=\"BRtooltip\">").concat(tooltips.readAloud, "</span>\n </button>\n </li>")).insertBefore($el.find('.BRcontrols .BRicon.zoom_out').closest('li'));
140
+ }
141
+ return $el;
142
+ };
143
+ }(BookReader.prototype.initNavbar);
144
+
145
+ // ttsToggle()
146
+ //______________________________________________________________________________
147
+ BookReader.prototype.ttsToggle = function () {
148
+ if (this.autoStop) this.autoStop();
149
+ if (this.ttsEngine.playing) {
150
+ this.ttsStop();
151
+ } else {
152
+ this.ttsStart();
153
+ }
154
+ };
155
+
156
+ // ttsStart(
157
+ //______________________________________________________________________________
158
+ BookReader.prototype.ttsStart = function () {
159
+ var startTTSEngine = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
160
+ if (this.constModeThumb == this.mode) this.switchMode(this.constMode1up);
161
+ this.refs.$BRReadAloudToolbar.addClass('visible');
162
+ this.$('.BRicon.read').addClass('unread active');
163
+ this.ttsSendAnalyticsEvent('Start');
164
+ if (startTTSEngine) this.ttsEngine.start(this.currentIndex(), this.book.getNumLeafs());
165
+ };
166
+ BookReader.prototype.ttsJumpForward = function () {
167
+ if (this.ttsEngine.paused) {
168
+ this.ttsEngine.resume();
169
+ }
170
+ this.ttsEngine.jumpForward();
171
+ };
172
+ BookReader.prototype.ttsJumpBackward = function () {
173
+ if (this.ttsEngine.paused) {
174
+ this.ttsEngine.resume();
175
+ }
176
+ this.ttsEngine.jumpBackward();
177
+ };
178
+ BookReader.prototype.ttsUpdateState = function () {
179
+ var isPlaying = !(this.ttsEngine.paused || !this.ttsEngine.playing);
180
+ this.$('.read-aloud [name=play]').toggleClass('playing', isPlaying);
181
+ };
182
+ BookReader.prototype.ttsPlayPause = function () {
183
+ if (!this.ttsEngine.playing) {
184
+ this.ttsToggle();
185
+ } else {
186
+ this.ttsEngine.togglePlayPause();
187
+ this.ttsUpdateState();
188
+ }
189
+ };
190
+
191
+ // ttsStop()
192
+ //______________________________________________________________________________
193
+ BookReader.prototype.ttsStop = function () {
194
+ this.refs.$BRReadAloudToolbar.removeClass('visible');
195
+ this.$('.BRicon.read').removeClass('unread active');
196
+ this.ttsSendAnalyticsEvent('Stop');
197
+ this.ttsEngine.stop();
198
+ this.ttsRemoveHilites();
199
+ this.removeProgressPopup();
200
+ };
201
+
202
+ /**
203
+ * @param {PageChunk} chunk
204
+ * @return {PromiseLike<void>} returns once the flip is done
205
+ */
206
+ BookReader.prototype.ttsBeforeChunkPlay = /*#__PURE__*/function () {
207
+ var _ref = _asyncToGenerator(function* (chunk) {
208
+ yield this.ttsMaybeFlipToIndex(chunk.leafIndex);
209
+ this.ttsHighlightChunk(chunk);
210
+ this.ttsScrollToChunk(chunk);
211
+ });
212
+ return function (_x) {
213
+ return _ref.apply(this, arguments);
214
+ };
215
+ }();
216
+
217
+ /**
218
+ * @param {PageChunk} chunk
219
+ */
220
+ BookReader.prototype.ttsSendChunkFinishedAnalyticsEvent = function (chunk) {
221
+ this.ttsSendAnalyticsEvent('ChunkFinished-Words', approximateWordCount(chunk.text));
222
+ };
223
+
224
+ /**
225
+ * Flip the page if the provided leaf index is not visible
226
+ * @param {Number} leafIndex
227
+ */
228
+ BookReader.prototype.ttsMaybeFlipToIndex = /*#__PURE__*/function () {
229
+ var _ref2 = _asyncToGenerator(function* (leafIndex) {
230
+ if (this.constMode2up != this.mode) {
231
+ this.jumpToIndex(leafIndex);
232
+ } else {
233
+ yield this._modes.mode2Up.mode2UpLit.jumpToIndex(leafIndex);
234
+ }
235
+ });
236
+ return function (_x2) {
237
+ return _ref2.apply(this, arguments);
238
+ };
239
+ }();
240
+
241
+ /**
242
+ * @param {PageChunk} chunk
243
+ */
244
+ BookReader.prototype.ttsHighlightChunk = function (chunk) {
245
+ var _this = this;
246
+ // The poorly-named variable leafIndex
247
+ var pageIndex = chunk.leafIndex;
248
+ this.ttsRemoveHilites();
249
+
250
+ // group by index; currently only possible to have chunks on one page :/
251
+ this._ttsBoxesByIndex = {
252
+ [pageIndex]: chunk.lineRects.map(_ref3 => {
253
+ var [l, b, r, t] = _ref3;
254
+ return {
255
+ l,
256
+ r,
257
+ b,
258
+ t
259
+ };
260
+ })
261
+ };
262
+
263
+ // update any already created pages
264
+ var _loop = function _loop(boxes) {
265
+ var pageIndex = parseFloat(pageIndexString);
266
+ var page = _this.book.getPage(pageIndex);
267
+ var pageContainers = _this.getActivePageContainerElementsForIndex(pageIndex);
268
+ pageContainers.forEach(container => renderBoxesInPageContainerLayer('ttsHiliteLayer', boxes, page, container));
269
+ };
270
+ for (var [pageIndexString, boxes] of Object.entries(this._ttsBoxesByIndex)) {
271
+ _loop(boxes);
272
+ }
273
+ };
274
+
275
+ /**
276
+ * @param {PageChunk} chunk
277
+ */
278
+ BookReader.prototype.ttsScrollToChunk = function (chunk) {
279
+ var _$$last;
280
+ // It behaves weird if used in thumb mode
281
+ if (this.constModeThumb == this.mode) return;
282
+ (_$$last = $(".pagediv".concat(chunk.leafIndex, " .ttsHiliteLayer rect")).last()) === null || _$$last === void 0 || (_$$last = _$$last[0]) === null || _$$last === void 0 || _$$last.scrollIntoView({
283
+ // Only vertically center the highlight if we're in 1up or in full screen. In
284
+ // 2up, if we're not fullscreen, the whole body gets scrolled around to try to
285
+ // center the highlight 🙄 See:
286
+ // https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move/11041376
287
+ // Note: nearest doesn't quite work great, because the ReadAloud toolbar is now
288
+ // full-width, and covers up the last line of the highlight.
289
+ block: this.constMode1up == this.mode || this.isFullscreenActive ? 'center' : 'nearest',
290
+ inline: 'center',
291
+ behavior: 'smooth'
292
+ });
293
+ };
294
+
295
+ // ttsRemoveHilites()
296
+ //______________________________________________________________________________
297
+ BookReader.prototype.ttsRemoveHilites = function () {
298
+ $(this.getActivePageContainerElements()).find('.ttsHiliteLayer').remove();
299
+ this._ttsBoxesByIndex = {};
300
+ };
301
+
302
+ /**
303
+ * @private
304
+ * Send an analytics event with an optional value. Also attaches the book's language.
305
+ * @param {string} action
306
+ * @param {number} [value]
307
+ */
308
+ BookReader.prototype.ttsSendAnalyticsEvent = function (action, value) {
309
+ if (this.archiveAnalyticsSendEvent) {
310
+ var extraValues = {};
311
+ var mediaLanguage = this.ttsEngine.opts.bookLanguage;
312
+ if (mediaLanguage) extraValues.mediaLanguage = mediaLanguage;
313
+ this.archiveAnalyticsSendEvent('BRReadAloud', action, value, extraValues);
314
+ }
315
+ };
@@ -0,0 +1,14 @@
1
+ export var en = {
2
+ advance: 'Advance 10 seconds',
3
+ play: 'Play',
4
+ playbackSpeed: 'Playback speed',
5
+ readAloud: 'Read this book aloud',
6
+ review: 'Review 10 seconds'
7
+ };
8
+ export var es = {
9
+ advance: 'Avance 10 segundos',
10
+ play: 'Jugar',
11
+ playbackSpeed: 'Velocidad de reproducción',
12
+ readAloud: 'Lee este libro en voz alta',
13
+ review: 'Revisar 10 segundos'
14
+ };
@@ -0,0 +1,79 @@
1
+ import langs from 'iso-language-codes/js/data.js';
2
+
3
+ /**
4
+ * Use regex to approximate word count in a string
5
+ * @param {string} text
6
+ * @return {number}
7
+ */
8
+ export function approximateWordCount(text) {
9
+ var m = text.match(/\S+/g);
10
+ return m ? m.length : 0;
11
+ }
12
+
13
+ /**
14
+ * Checks whether the current browser is on android
15
+ * @param {string} [userAgent]
16
+ * @return {boolean}
17
+ */
18
+ export function isAndroid() {
19
+ var userAgent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : navigator.userAgent;
20
+ return /android/i.test(userAgent);
21
+ }
22
+
23
+ /**
24
+ * @typedef {string} ISO6391
25
+ * Language code in ISO 639-1 format. e.g. en, fr, zh
26
+ **/
27
+
28
+ /** Each lang is an array, with each index mapping to a different property */
29
+ var COLUMN_TO_LANG_INDEX = {
30
+ 'Name': 0,
31
+ 'Endonym': 1,
32
+ 'ISO 639-1': 2,
33
+ 'ISO 639-2/T': 3,
34
+ 'ISO 639-2/B': 4
35
+ };
36
+
37
+ /**
38
+ * @param {string} language in some format
39
+ * @return {ISO6391?}
40
+ */
41
+ export function toISO6391(language) {
42
+ if (!language) return null;
43
+ language = language.toLowerCase();
44
+ return searchForISO6391(language, ['ISO 639-1']) || searchForISO6391(language, ['ISO 639-2/B']) || searchForISO6391(language, ['ISO 639-2/T', 'Endonym', 'Name']);
45
+ }
46
+
47
+ /**
48
+ * Searches for the given long in the given columns.
49
+ * @param {string} language
50
+ * @param {Array<keyof COLUMN_TO_LANG_INDEX>} columnsToSearch
51
+ * @return {ISO6391?}
52
+ */
53
+ function searchForISO6391(language, columnsToSearch) {
54
+ for (var i = 0; i < langs.length; i++) {
55
+ for (var colI = 0; colI < columnsToSearch.length; colI++) {
56
+ var column = columnsToSearch[colI];
57
+ var columnValue = langs[i][COLUMN_TO_LANG_INDEX[column]];
58
+ if (columnValue.split(', ').map(x => x.toLowerCase()).indexOf(language) != -1) {
59
+ return langs[i][COLUMN_TO_LANG_INDEX['ISO 639-1']];
60
+ }
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+
66
+ /**
67
+ * Checks whether the current browser supports localStorage or
68
+ * if the current context has access to it.
69
+ * @return {boolean}
70
+ */
71
+ export function hasLocalStorage() {
72
+ try {
73
+ return !!window.localStorage;
74
+ } catch (e) {
75
+ // Will throw in sandboxed iframe
76
+ // DOMException: Window.localStorage getter: Forbidden in a sandboxed document without the 'allow-same-origin' flag.
77
+ return false;
78
+ }
79
+ }
@@ -0,0 +1,197 @@
1
+ export class UrlPlugin {
2
+ constructor() {
3
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4
+ this.bookReaderOptions = options;
5
+
6
+ // the canonical order of elements is important in the path and query string
7
+ this.urlSchema = [{
8
+ name: 'page',
9
+ position: 'path',
10
+ default: 'n0'
11
+ }, {
12
+ name: 'mode',
13
+ position: 'path',
14
+ default: '2up'
15
+ }, {
16
+ name: 'search',
17
+ position: 'path',
18
+ deprecated_for: 'q'
19
+ }, {
20
+ name: 'q',
21
+ position: 'query_param'
22
+ }, {
23
+ name: 'sort',
24
+ position: 'query_param'
25
+ }, {
26
+ name: 'view',
27
+ position: 'query_param'
28
+ }, {
29
+ name: 'admin',
30
+ position: 'query_param'
31
+ }];
32
+ this.urlState = {};
33
+ this.urlMode = this.bookReaderOptions.urlMode || 'hash';
34
+ this.urlHistoryBasePath = this.bookReaderOptions.urlHistoryBasePath || '/';
35
+ this.urlLocationPollId = null;
36
+ this.oldLocationHash = null;
37
+ this.oldUserHash = null;
38
+ }
39
+
40
+ /**
41
+ * Parse JSON object URL state to string format
42
+ * Arrange path names in an order that it is positioned on the urlSchema
43
+ * @param {Object} urlState
44
+ * @returns {string}
45
+ */
46
+ urlStateToUrlString(urlState) {
47
+ var searchParams = new URLSearchParams();
48
+ var pathParams = {};
49
+ Object.keys(urlState).forEach(key => {
50
+ var _schema, _schema2;
51
+ var schema = this.urlSchema.find(schema => schema.name === key);
52
+ if ((_schema = schema) !== null && _schema !== void 0 && _schema.deprecated_for) {
53
+ schema = this.urlSchema.find(schemaKey => schemaKey.name === schema.deprecated_for);
54
+ }
55
+ if (((_schema2 = schema) === null || _schema2 === void 0 ? void 0 : _schema2.position) == 'path') {
56
+ var _schema3;
57
+ pathParams[(_schema3 = schema) === null || _schema3 === void 0 ? void 0 : _schema3.name] = urlState[key];
58
+ } else {
59
+ var _schema4;
60
+ searchParams.append(((_schema4 = schema) === null || _schema4 === void 0 ? void 0 : _schema4.name) || key, urlState[key]);
61
+ }
62
+ });
63
+ var strPathParams = this.urlSchema.filter(s => s.position == 'path').map(schema => pathParams[schema.name] ? "".concat(schema.name, "/").concat(encodeURIComponent(pathParams[schema.name])) : '').join('/');
64
+
65
+ // replace consecutive slashes with a single slash + remove trailing slashes
66
+ var strStrippedTrailingSlash = "".concat(strPathParams.replace(/\/+/g, '/').replace(/\/+$/, ''));
67
+ var concatenatedPath = "".concat(strStrippedTrailingSlash, "?").concat(searchParams.toString());
68
+ return searchParams.toString() ? concatenatedPath : "".concat(strStrippedTrailingSlash);
69
+ }
70
+
71
+ /**
72
+ * Parse string URL and add it in the current urlState
73
+ * Example:
74
+ * /page/n7/mode/2up => {page: 'n7', mode: '2up'}
75
+ * /page/n7/mode/2up/search/hello => {page: 'n7', mode: '2up', q: 'hello'}
76
+ * @param {string} urlString
77
+ * @returns {object}
78
+ */
79
+ urlStringToUrlState(urlString) {
80
+ var urlState = {};
81
+
82
+ // Fetch searchParams from given {str}
83
+ // Note: whole URL path is needed for URL parsing
84
+ var urlPath = new URL(urlString, 'http://example.com');
85
+ var urlSearchParamsObj = Object.fromEntries(urlPath.searchParams.entries());
86
+ var splitUrlMatches = urlPath.pathname.match(/[^\\/]+\/[^\\/]+/g);
87
+ var urlStrSplitSlashObj = splitUrlMatches ? Object.fromEntries(splitUrlMatches.map(x => x.split('/'))) : {};
88
+ var doesKeyExists = (_object, _key) => {
89
+ return Object.keys(_object).some(value => value == _key);
90
+ };
91
+
92
+ // Add path objects to urlState
93
+ this.urlSchema.filter(schema => schema.position == 'path').forEach(schema => {
94
+ var hasPropertyKey = doesKeyExists(urlStrSplitSlashObj, schema.name);
95
+ var hasDeprecatedKey = doesKeyExists(schema, 'deprecated_for') && hasPropertyKey;
96
+
97
+ // Not in the URL
98
+ if (!hasPropertyKey && !hasDeprecatedKey) {
99
+ return;
100
+ }
101
+ var urlStateParam = hasDeprecatedKey ? schema.deprecated_for : schema.name;
102
+ urlState[urlStateParam] = decodeURIComponent(urlStrSplitSlashObj[schema.name]);
103
+ });
104
+
105
+ // Add searchParams to urlState
106
+ Object.entries(urlSearchParamsObj).forEach(_ref => {
107
+ var [key, value] = _ref;
108
+ urlState[key] = value;
109
+ });
110
+ return urlState;
111
+ }
112
+
113
+ /**
114
+ * Add or update key-value to the urlState
115
+ * @param {string} key
116
+ * @param {string} val
117
+ */
118
+ setUrlParam(key, value) {
119
+ this.urlState[key] = value;
120
+ this.pushToAddressBar();
121
+ }
122
+
123
+ /**
124
+ * Delete key-value to the urlState
125
+ * @param {string} key
126
+ */
127
+ removeUrlParam(key) {
128
+ delete this.urlState[key];
129
+ this.pushToAddressBar();
130
+ }
131
+
132
+ /**
133
+ * Get key-value from the urlState
134
+ * @param {string} key
135
+ * @return {string}
136
+ */
137
+ getUrlParam(key) {
138
+ return this.urlState[key];
139
+ }
140
+
141
+ /**
142
+ * Push URL params to addressbar
143
+ */
144
+ pushToAddressBar() {
145
+ var urlStrPath = this.urlStateToUrlString(this.urlState);
146
+ var concatenatedPath = urlStrPath !== '/' ? urlStrPath : '';
147
+ if (this.urlMode == 'history') {
148
+ if (!window.history || !window.history.replaceState) {
149
+ this.options.urlMode = 'hash';
150
+ } else {
151
+ var newUrlPath = "".concat(this.urlHistoryBasePath).concat(concatenatedPath).trim().replace(/(\/+)/g, '/');
152
+ try {
153
+ window.history.replaceState({}, null, newUrlPath);
154
+ } catch (e) {
155
+ // DOMException on Chrome when in sandboxed iframe
156
+ this.urlMode = 'hash';
157
+ }
158
+ }
159
+ }
160
+ if (this.urlMode == 'hash') {
161
+ window.location.replace('#' + concatenatedPath);
162
+ }
163
+ this.oldLocationHash = urlStrPath;
164
+ }
165
+
166
+ /**
167
+ * Get the url and check if it has changed
168
+ * If it was changeed, update the urlState
169
+ */
170
+ listenForHashChanges() {
171
+ this.oldLocationHash = window.location.hash.substr(1);
172
+ if (this.urlLocationPollId) {
173
+ clearInterval(this.urlLocationPollId);
174
+ this.urlLocationPollId = null;
175
+ }
176
+
177
+ // check if the URL changes
178
+ var updateHash = () => {
179
+ var newFragment = window.location.hash.substr(1);
180
+ var hasFragmentChange = newFragment != this.oldLocationHash;
181
+ if (!hasFragmentChange) {
182
+ return;
183
+ }
184
+ this.urlState = this.urlStringToUrlState(newFragment);
185
+ };
186
+ this.urlLocationPollId = setInterval(updateHash, 500);
187
+ }
188
+
189
+ /**
190
+ * Will read either the hash or URL and return the bookreader fragment
191
+ */
192
+ pullFromAddressBar() {
193
+ var location = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.location;
194
+ var path = this.urlMode === 'history' ? location.pathname.substr(this.urlHistoryBasePath.length) + location.search : location.hash.substr(1);
195
+ this.urlState = this.urlStringToUrlState(path);
196
+ }
197
+ }