@internetarchive/bookreader 5.0.0-38 → 5.0.0-39

Sign up to get free protection for your applications and to get access to all the features.
Files changed (222) hide show
  1. package/BookReader/BookReader.css +8 -0
  2. package/BookReader/BookReader.js +1 -1
  3. package/BookReader/BookReader.js.map +1 -1
  4. package/BookReader/ia-bookreader-bundle.js +99 -75
  5. package/BookReader/ia-bookreader-bundle.js.map +1 -1
  6. package/BookReader/icons/magnify-minus.svg +1 -1
  7. package/BookReader/icons/magnify-plus.svg +1 -1
  8. package/BookReader/plugins/plugin.autoplay.js +1 -1
  9. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  10. package/BookReader/plugins/plugin.chapters.js +1 -1
  11. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  12. package/BookReader/plugins/plugin.mobile_nav.js +1 -1
  13. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
  14. package/BookReader/plugins/plugin.resume.js +1 -1
  15. package/BookReader/plugins/plugin.resume.js.map +1 -1
  16. package/BookReader/plugins/plugin.search.js +1 -1
  17. package/BookReader/plugins/plugin.search.js.map +1 -1
  18. package/BookReader/plugins/plugin.text_selection.js +1 -1
  19. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  20. package/BookReader/plugins/plugin.tts.js +1 -1
  21. package/BookReader/plugins/plugin.tts.js.map +1 -1
  22. package/BookReader/plugins/plugin.url.js +1 -1
  23. package/BookReader/plugins/plugin.url.js.map +1 -1
  24. package/CHANGELOG.md +5 -0
  25. package/README.md +13 -0
  26. package/package.json +14 -14
  27. package/renovate.json +1 -1
  28. package/src/BookReader/Mode1UpLit.js +7 -1
  29. package/src/BookReader/Mode2Up.js +11 -0
  30. package/src/BookReader/ModeSmoothZoom.js +2 -0
  31. package/src/BookReader/PageContainer.js +10 -4
  32. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  33. package/src/assets/icons/magnify-minus.svg +3 -7
  34. package/src/assets/icons/magnify-plus.svg +3 -7
  35. package/src/css/_TextSelection.scss +13 -0
  36. package/tests/jest/BookReader/PageContainer.test.js +5 -4
  37. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  38. package/.husky/_/husky.sh +0 -30
  39. package/stat/BookNavigator/BookModel.js +0 -14
  40. package/stat/BookNavigator/BookNavigator.js +0 -524
  41. package/stat/BookNavigator/assets/bookmark-colors.js +0 -15
  42. package/stat/BookNavigator/assets/button-base.js +0 -61
  43. package/stat/BookNavigator/assets/ia-logo.js +0 -17
  44. package/stat/BookNavigator/assets/icon_checkmark.js +0 -6
  45. package/stat/BookNavigator/assets/icon_close.js +0 -3
  46. package/stat/BookNavigator/assets/icon_sort_asc.js +0 -5
  47. package/stat/BookNavigator/assets/icon_sort_desc.js +0 -5
  48. package/stat/BookNavigator/assets/icon_sort_neutral.js +0 -5
  49. package/stat/BookNavigator/assets/icon_volumes.js +0 -11
  50. package/stat/BookNavigator/bookmarks/bookmark-button.js +0 -64
  51. package/stat/BookNavigator/bookmarks/bookmark-edit.js +0 -215
  52. package/stat/BookNavigator/bookmarks/bookmarks-list.js +0 -285
  53. package/stat/BookNavigator/bookmarks/bookmarks-loginCTA.js +0 -28
  54. package/stat/BookNavigator/bookmarks/bookmarks-provider.js +0 -56
  55. package/stat/BookNavigator/bookmarks/ia-bookmarks.js +0 -523
  56. package/stat/BookNavigator/br-fullscreen-mgr.js +0 -82
  57. package/stat/BookNavigator/delete-modal-actions.js +0 -49
  58. package/stat/BookNavigator/downloads/downloads-provider.js +0 -72
  59. package/stat/BookNavigator/downloads/downloads.js +0 -139
  60. package/stat/BookNavigator/provider-config.js +0 -0
  61. package/stat/BookNavigator/search/a-search-result.js +0 -55
  62. package/stat/BookNavigator/search/search-provider.js +0 -180
  63. package/stat/BookNavigator/search/search-results.js +0 -360
  64. package/stat/BookNavigator/sharing.js +0 -31
  65. package/stat/BookNavigator/visual-adjustments/visual-adjustments-provider.js +0 -94
  66. package/stat/BookNavigator/visual-adjustments/visual-adjustments.js +0 -280
  67. package/stat/BookNavigator/volumes/volumes-provider.js +0 -83
  68. package/stat/BookNavigator/volumes/volumes.js +0 -178
  69. package/stat/BookReader/BookModel.js +0 -518
  70. package/stat/BookReader/DebugConsole.js +0 -54
  71. package/stat/BookReader/DragScrollable.js +0 -233
  72. package/stat/BookReader/ImageCache.js +0 -116
  73. package/stat/BookReader/Mode1Up.js +0 -102
  74. package/stat/BookReader/Mode1UpLit.js +0 -434
  75. package/stat/BookReader/Mode2Up.js +0 -1372
  76. package/stat/BookReader/ModeSmoothZoom.js +0 -177
  77. package/stat/BookReader/ModeThumb.js +0 -344
  78. package/stat/BookReader/Navbar/Navbar.js +0 -310
  79. package/stat/BookReader/PageContainer.js +0 -120
  80. package/stat/BookReader/ReduceSet.js +0 -26
  81. package/stat/BookReader/Toolbar/Toolbar.js +0 -384
  82. package/stat/BookReader/events.js +0 -20
  83. package/stat/BookReader/options.js +0 -324
  84. package/stat/BookReader/utils/HTMLDimensionsCacher.js +0 -44
  85. package/stat/BookReader/utils/classes.js +0 -36
  86. package/stat/BookReader/utils.js +0 -240
  87. package/stat/BookReader.js +0 -2550
  88. package/stat/BookReaderComponent/BookReaderComponent.js +0 -117
  89. package/stat/assets/icons/1up.svg +0 -12
  90. package/stat/assets/icons/2up.svg +0 -15
  91. package/stat/assets/icons/advance.svg +0 -26
  92. package/stat/assets/icons/chevron-right.svg +0 -1
  93. package/stat/assets/icons/close-circle-dark.svg +0 -1
  94. package/stat/assets/icons/close-circle.svg +0 -1
  95. package/stat/assets/icons/fullscreen.svg +0 -17
  96. package/stat/assets/icons/fullscreen_exit.svg +0 -17
  97. package/stat/assets/icons/hamburger.svg +0 -15
  98. package/stat/assets/icons/left-arrow.svg +0 -12
  99. package/stat/assets/icons/magnify-minus.svg +0 -16
  100. package/stat/assets/icons/magnify-plus.svg +0 -17
  101. package/stat/assets/icons/magnify.svg +0 -15
  102. package/stat/assets/icons/pause.svg +0 -23
  103. package/stat/assets/icons/play.svg +0 -22
  104. package/stat/assets/icons/playback-speed.svg +0 -34
  105. package/stat/assets/icons/read-aloud.svg +0 -22
  106. package/stat/assets/icons/review.svg +0 -22
  107. package/stat/assets/icons/thumbnails.svg +0 -17
  108. package/stat/assets/icons/voice.svg +0 -1
  109. package/stat/assets/icons/volume-full.svg +0 -22
  110. package/stat/assets/images/BRicons.png +0 -0
  111. package/stat/assets/images/BRicons.svg +0 -94
  112. package/stat/assets/images/BRicons_ia.png +0 -0
  113. package/stat/assets/images/back_pages.png +0 -0
  114. package/stat/assets/images/book_bottom_icon.png +0 -0
  115. package/stat/assets/images/book_down_icon.png +0 -0
  116. package/stat/assets/images/book_left_icon.png +0 -0
  117. package/stat/assets/images/book_leftmost_icon.png +0 -0
  118. package/stat/assets/images/book_right_icon.png +0 -0
  119. package/stat/assets/images/book_rightmost_icon.png +0 -0
  120. package/stat/assets/images/book_top_icon.png +0 -0
  121. package/stat/assets/images/book_up_icon.png +0 -0
  122. package/stat/assets/images/books_graphic.svg +0 -177
  123. package/stat/assets/images/booksplit.png +0 -0
  124. package/stat/assets/images/control_pause_icon.png +0 -0
  125. package/stat/assets/images/control_play_icon.png +0 -0
  126. package/stat/assets/images/embed_icon.png +0 -0
  127. package/stat/assets/images/icon-home-ia.png +0 -0
  128. package/stat/assets/images/icon_OL-logo-xs.png +0 -0
  129. package/stat/assets/images/icon_alert-xs.png +0 -0
  130. package/stat/assets/images/icon_book.svg +0 -12
  131. package/stat/assets/images/icon_bookmark.svg +0 -12
  132. package/stat/assets/images/icon_close-pop.png +0 -0
  133. package/stat/assets/images/icon_download.png +0 -0
  134. package/stat/assets/images/icon_gear.svg +0 -14
  135. package/stat/assets/images/icon_hamburger.svg +0 -20
  136. package/stat/assets/images/icon_home.png +0 -0
  137. package/stat/assets/images/icon_home.svg +0 -21
  138. package/stat/assets/images/icon_home_ia.png +0 -0
  139. package/stat/assets/images/icon_indicator.png +0 -0
  140. package/stat/assets/images/icon_info.svg +0 -11
  141. package/stat/assets/images/icon_one_page.svg +0 -8
  142. package/stat/assets/images/icon_pause.svg +0 -1
  143. package/stat/assets/images/icon_play.svg +0 -1
  144. package/stat/assets/images/icon_playback-rate.svg +0 -15
  145. package/stat/assets/images/icon_return.png +0 -0
  146. package/stat/assets/images/icon_search_button.svg +0 -8
  147. package/stat/assets/images/icon_share.svg +0 -9
  148. package/stat/assets/images/icon_skip-ahead.svg +0 -6
  149. package/stat/assets/images/icon_skip-back.svg +0 -13
  150. package/stat/assets/images/icon_speaker.svg +0 -18
  151. package/stat/assets/images/icon_speaker_open.svg +0 -10
  152. package/stat/assets/images/icon_thumbnails.svg +0 -12
  153. package/stat/assets/images/icon_toc.svg +0 -5
  154. package/stat/assets/images/icon_two_pages.svg +0 -9
  155. package/stat/assets/images/icon_zoomer.png +0 -0
  156. package/stat/assets/images/loading.gif +0 -0
  157. package/stat/assets/images/logo_icon.png +0 -0
  158. package/stat/assets/images/marker_chap-off.png +0 -0
  159. package/stat/assets/images/marker_chap-off.svg +0 -11
  160. package/stat/assets/images/marker_chap-off_ia.png +0 -0
  161. package/stat/assets/images/marker_chap-on.png +0 -0
  162. package/stat/assets/images/marker_chap-on.svg +0 -11
  163. package/stat/assets/images/marker_srch-on.svg +0 -11
  164. package/stat/assets/images/marker_srchchap-off.png +0 -0
  165. package/stat/assets/images/marker_srchchap-on.png +0 -0
  166. package/stat/assets/images/nav_control-dn.png +0 -0
  167. package/stat/assets/images/nav_control-dn_ia.png +0 -0
  168. package/stat/assets/images/nav_control-up.png +0 -0
  169. package/stat/assets/images/nav_control-up_ia.png +0 -0
  170. package/stat/assets/images/nav_control.png +0 -0
  171. package/stat/assets/images/one_page_mode_icon.png +0 -0
  172. package/stat/assets/images/paper-badge.png +0 -0
  173. package/stat/assets/images/print_icon.png +0 -0
  174. package/stat/assets/images/progressbar.gif +0 -0
  175. package/stat/assets/images/right_edges.png +0 -0
  176. package/stat/assets/images/slider.png +0 -0
  177. package/stat/assets/images/slider_ia.png +0 -0
  178. package/stat/assets/images/thumbnail_mode_icon.png +0 -0
  179. package/stat/assets/images/transparent.png +0 -0
  180. package/stat/assets/images/two_page_mode_icon.png +0 -0
  181. package/stat/assets/images/zoom_in_icon.png +0 -0
  182. package/stat/assets/images/zoom_out_icon.png +0 -0
  183. package/stat/css/BookReader.scss +0 -89
  184. package/stat/css/_BRBookmarks.scss +0 -29
  185. package/stat/css/_BRComponent.scss +0 -13
  186. package/stat/css/_BRfloat.scss +0 -197
  187. package/stat/css/_BRicon.scss +0 -48
  188. package/stat/css/_BRmain.scss +0 -251
  189. package/stat/css/_BRnav.scss +0 -359
  190. package/stat/css/_BRpages.scss +0 -139
  191. package/stat/css/_BRsearch.scss +0 -226
  192. package/stat/css/_BRtoolbar.scss +0 -84
  193. package/stat/css/_BRvendor.scss +0 -5
  194. package/stat/css/_MobileNav.scss +0 -194
  195. package/stat/css/_TextSelection.scss +0 -32
  196. package/stat/css/_colorbox.scss +0 -52
  197. package/stat/css/_controls.scss +0 -253
  198. package/stat/css/_icons.scss +0 -121
  199. package/stat/jquery-wrapper.js +0 -4
  200. package/stat/plugins/plugin.archive_analytics.js +0 -86
  201. package/stat/plugins/plugin.autoplay.js +0 -129
  202. package/stat/plugins/plugin.chapters.js +0 -248
  203. package/stat/plugins/plugin.iframe.js +0 -48
  204. package/stat/plugins/plugin.mobile_nav.js +0 -288
  205. package/stat/plugins/plugin.resume.js +0 -68
  206. package/stat/plugins/plugin.text_selection.js +0 -291
  207. package/stat/plugins/plugin.url.js +0 -198
  208. package/stat/plugins/plugin.vendor-fullscreen.js +0 -247
  209. package/stat/plugins/search/plugin.search.js +0 -439
  210. package/stat/plugins/search/view.js +0 -439
  211. package/stat/plugins/tts/AbstractTTSEngine.js +0 -249
  212. package/stat/plugins/tts/FestivalTTSEngine.js +0 -169
  213. package/stat/plugins/tts/PageChunk.js +0 -107
  214. package/stat/plugins/tts/PageChunkIterator.js +0 -163
  215. package/stat/plugins/tts/WebTTSEngine.js +0 -357
  216. package/stat/plugins/tts/plugin.tts.js +0 -357
  217. package/stat/plugins/tts/tooltip_dict.js +0 -15
  218. package/stat/plugins/tts/utils.js +0 -91
  219. package/stat/util/browserSniffing.js +0 -30
  220. package/stat/util/debouncer.js +0 -26
  221. package/stat/util/docCookies.js +0 -67
  222. package/stat/util/strings.js +0 -34
@@ -1,177 +0,0 @@
1
- // @ts-check
2
- import Hammer from "hammerjs";
3
- /** @typedef {import('./utils/HTMLDimensionsCacher.js').HTMLDimensionsCacher} HTMLDimensionsCacher */
4
-
5
- /**
6
- * @typedef {object} SmoothZoomable
7
- * @property {HTMLElement} $container
8
- * @property {HTMLElement} $visibleWorld
9
- * @property {number} scale
10
- * @property {{ x: number, y: number }} scaleCenter
11
- * @property {HTMLDimensionsCacher} htmlDimensionsCacher
12
- * @property {function(): void} [attachScrollListeners]
13
- * @property {function(): void} [detachScrollListeners]
14
- */
15
-
16
- /** Manages pinch-zoom, ctrl-wheel, and trackpad pinch smooth zooming. */
17
- export class ModeSmoothZoom {
18
- /** @param {SmoothZoomable} mode */
19
- constructor(mode) {
20
- /** @type {SmoothZoomable} */
21
- this.mode = mode;
22
-
23
- /** Non-null when a scale has been enqueued/is being processed by the buffer function */
24
- this.pinchMoveFrame = null;
25
- /** Promise for the current/enqueued pinch move frame. Resolves when it is complete. */
26
- this.pinchMoveFramePromise = Promise.resolve();
27
- this.oldScale = 1;
28
- /** @type {{ scale: number, center: { x: number, y: number }}} */
29
- this.lastEvent = null;
30
- this.attached = false;
31
-
32
- /** @type {function(function(): void): any} */
33
- this.bufferFn = window.requestAnimationFrame.bind(window);
34
-
35
- // Hammer.js by default set userSelect to None; we don't want that!
36
- // TODO: Is there any way to do this not globally on Hammer?
37
- delete Hammer.defaults.cssProps.userSelect;
38
- this.hammer = new Hammer.Manager(this.mode.$container, {
39
- touchAction: "pan-x pan-y",
40
- });
41
-
42
- this.hammer.add(new Hammer.Pinch());
43
- }
44
-
45
- attach() {
46
- if (this.attached) return;
47
-
48
- this.attachCtrlZoom();
49
-
50
- // GestureEvents work only on Safari; they interfere with Hammer,
51
- // so block them.
52
- this.mode.$container.addEventListener('gesturestart', this._preventEvent);
53
- this.mode.$container.addEventListener('gesturechange', this._preventEvent);
54
- this.mode.$container.addEventListener('gestureend', this._preventEvent);
55
-
56
- // The pinch listeners
57
- this.hammer.on("pinchstart", this._pinchStart);
58
- this.hammer.on("pinchmove", this._pinchMove);
59
- this.hammer.on("pinchend", this._pinchEnd);
60
- this.hammer.on("pinchcancel", this._pinchCancel);
61
-
62
- this.attached = true;
63
- }
64
-
65
- detach() {
66
- this.detachCtrlZoom();
67
-
68
- // GestureEvents work only on Safari; they interfere with Hammer,
69
- // so block them.
70
- this.mode.$container.removeEventListener('gesturestart', this._preventEvent);
71
- this.mode.$container.removeEventListener('gesturechange', this._preventEvent);
72
- this.mode.$container.removeEventListener('gestureend', this._preventEvent);
73
-
74
- // The pinch listeners
75
- this.hammer.off("pinchstart", this._pinchStart);
76
- this.hammer.off("pinchmove", this._pinchMove);
77
- this.hammer.off("pinchend", this._pinchEnd);
78
- this.hammer.off("pinchcancel", this._pinchCancel);
79
-
80
- this.attached = false;
81
- }
82
-
83
- /** @param {Event} ev */
84
- _preventEvent = (ev) => {
85
- ev.preventDefault();
86
- return false;
87
- }
88
-
89
- _pinchStart = () => {
90
- // Do this in case the pinchend hasn't fired yet.
91
- this.oldScale = 1;
92
- this.mode.$visibleWorld.style.willChange = "transform";
93
- this.detachCtrlZoom();
94
- this.mode.detachScrollListeners?.();
95
- }
96
-
97
- /** @param {{ scale: number, center: { x: number, y: number }}} e */
98
- _pinchMove = async (e) => {
99
- this.lastEvent = e;
100
- if (!this.pinchMoveFrame) {
101
- let pinchMoveFramePromiseRes = null;
102
- this.pinchMoveFramePromise = new Promise(
103
- (res) => (pinchMoveFramePromiseRes = res)
104
- );
105
-
106
- // Buffer these events; only update the scale when request animation fires
107
- this.pinchMoveFrame = this.bufferFn(() => {
108
- this.updateScaleCenter({
109
- clientX: this.lastEvent.center.x,
110
- clientY: this.lastEvent.center.y,
111
- });
112
- this.mode.scale *= this.lastEvent.scale / this.oldScale;
113
- this.oldScale = this.lastEvent.scale;
114
- this.pinchMoveFrame = null;
115
- pinchMoveFramePromiseRes();
116
- });
117
- }
118
- }
119
-
120
- _pinchEnd = async () => {
121
- // Want this to happen after the pinchMoveFrame,
122
- // if one is in progress; otherwise setting oldScale
123
- // messes up the transform.
124
- await this.pinchMoveFramePromise;
125
- this.mode.scaleCenter = { x: 0.5, y: 0.5 };
126
- this.oldScale = 1;
127
- this.mode.$visibleWorld.style.willChange = "auto";
128
- this.attachCtrlZoom();
129
- this.mode.attachScrollListeners?.();
130
- }
131
-
132
- _pinchCancel = async () => {
133
- // iOS fires pinchcancel ~randomly; it looks like it sometimes
134
- // thinks the pinch becomes a pan, at which point it cancels?
135
- await this._pinchEnd();
136
- }
137
-
138
- /** @private */
139
- attachCtrlZoom() {
140
- window.addEventListener("wheel", this._handleCtrlWheel, { passive: false });
141
- }
142
-
143
- /** @private */
144
- detachCtrlZoom() {
145
- window.removeEventListener("wheel", this._handleCtrlWheel);
146
- }
147
-
148
- /** @param {WheelEvent} ev **/
149
- _handleCtrlWheel = (ev) => {
150
- if (!ev.ctrlKey) return;
151
- ev.preventDefault();
152
- const zoomMultiplier =
153
- // Zooming on macs was painfully slow; likely due to their better
154
- // trackpads. Give them a higher zoom rate.
155
- /Mac/i.test(navigator.platform)
156
- ? 0.045
157
- : // This worked well for me on Windows
158
- 0.03;
159
-
160
- // Zoom around the cursor
161
- this.updateScaleCenter(ev);
162
- this.mode.scale *= 1 - Math.sign(ev.deltaY) * zoomMultiplier;
163
- }
164
-
165
- /**
166
- * @param {object} param0
167
- * @param {number} param0.clientX
168
- * @param {number} param0.clientY
169
- */
170
- updateScaleCenter({ clientX, clientY }) {
171
- const bc = this.mode.htmlDimensionsCacher.boundingClientRect;
172
- this.mode.scaleCenter = {
173
- x: (clientX - bc.left) / this.mode.htmlDimensionsCacher.clientWidth,
174
- y: (clientY - bc.top) / this.mode.htmlDimensionsCacher.clientHeight,
175
- };
176
- }
177
- }
@@ -1,344 +0,0 @@
1
- // @ts-check
2
- import { notInArray, clamp } from './utils.js';
3
- import { EVENTS } from './events.js';
4
- import { DragScrollable } from './DragScrollable.js';
5
- /** @typedef {import('../BookREader.js').default} BookReader */
6
- /** @typedef {import('./BookModel.js').PageIndex} PageIndex */
7
- /** @typedef {import('./BookModel.js').BookModel} BookModel */
8
-
9
- /** @typedef {JQuery} $lazyLoadImgPlaceholder * jQuery element with data attributes: leaf, reduce */
10
-
11
- export class ModeThumb {
12
- /**
13
- * @param {BookReader} br
14
- * @param {BookModel} bookModel
15
- */
16
- constructor(br, bookModel) {
17
- this.br = br;
18
- this.book = bookModel;
19
- }
20
-
21
- /**
22
- * Draws the thumbnail view
23
- * @param {number} [seekIndex] If seekIndex is defined, the view will be drawn
24
- * with that page visible (without any animated scrolling).
25
- *
26
- * Creates place holder for image to load after gallery has been drawn
27
- */
28
- drawLeafs(seekIndex) {
29
- const { floor } = Math;
30
- const { book } = this;
31
- const viewWidth = this.br.refs.$brContainer.prop('scrollWidth') - 20; // width minus buffer
32
-
33
- let leafHeight;
34
- let rightPos = 0;
35
- let bottomPos = 0;
36
- let maxRight = 0;
37
- let currentRow = 0;
38
- let leafIndex = 0;
39
- /** @type {Array<{ leafs?: Array<{num: PageIndex, left: number}>, height?: number, top?: number }>} */
40
- const leafMap = [];
41
-
42
- // Will be set to top of requested seek index, if set
43
- let seekTop;
44
-
45
- // Calculate the position of every thumbnail. $$$ cache instead of calculating on every draw
46
- // make `leafMap`
47
- for (const page of book.pagesIterator({ combineConsecutiveUnviewables: true })) {
48
- const leafWidth = this.br.thumbWidth;
49
- if (rightPos + (leafWidth + this.br.thumbPadding) > viewWidth) {
50
- currentRow++;
51
- rightPos = 0;
52
- leafIndex = 0;
53
- }
54
-
55
- // Init current row in leafMap
56
- if (!leafMap[currentRow]) {
57
- leafMap[currentRow] = {};
58
- }
59
- if (!leafMap[currentRow].leafs) {
60
- leafMap[currentRow].leafs = [];
61
- leafMap[currentRow].height = 0;
62
- leafMap[currentRow].top = 0;
63
- }
64
- leafMap[currentRow].leafs[leafIndex] = {
65
- num: page.index,
66
- left: rightPos,
67
- };
68
-
69
- leafHeight = floor((page.height * this.br.thumbWidth) / page.width);
70
- if (leafHeight > leafMap[currentRow].height) {
71
- leafMap[currentRow].height = leafHeight;
72
- }
73
- if (leafIndex === 0) { bottomPos += this.br.thumbPadding + leafMap[currentRow].height; }
74
- rightPos += leafWidth + this.br.thumbPadding;
75
- if (rightPos > maxRight) { maxRight = rightPos; }
76
- leafIndex++;
77
-
78
- if (page.index == seekIndex) {
79
- seekTop = bottomPos - this.br.thumbPadding - leafMap[currentRow].height;
80
- }
81
- }
82
-
83
- // reset the bottom position based on thumbnails
84
- this.br.refs.$brPageViewEl.height(bottomPos);
85
-
86
- const pageViewBuffer = floor((this.br.refs.$brContainer.prop('scrollWidth') - maxRight) / 2) - 14;
87
-
88
- // If seekTop is defined, seeking was requested and target found
89
- if (typeof(seekTop) != 'undefined') {
90
- this.br.refs.$brContainer.scrollTop(seekTop);
91
- }
92
-
93
- const scrollTop = this.br.refs.$brContainer.prop('scrollTop');
94
- const scrollBottom = scrollTop + this.br.refs.$brContainer.height();
95
-
96
- let leafTop = 0;
97
- let leafBottom = 0;
98
- const rowsToDisplay = [];
99
- const imagesToDisplay = [];
100
-
101
- // Visible leafs with least/greatest index
102
- let leastVisible = book.getNumLeafs() - 1;
103
- let mostVisible = 0;
104
-
105
- // Determine the thumbnails in view
106
- for (let i = 0; i < leafMap.length; i++) {
107
- if (!leafMap[i]) { continue; }
108
- leafBottom += this.br.thumbPadding + leafMap[i].height;
109
- const topInView = (leafTop >= scrollTop) && (leafTop <= scrollBottom);
110
- const bottomInView = (leafBottom >= scrollTop) && (leafBottom <= scrollBottom);
111
- const middleInView = (leafTop <= scrollTop) && (leafBottom >= scrollBottom);
112
- if (topInView || bottomInView || middleInView) {
113
- rowsToDisplay.push(i);
114
- if (leafMap[i].leafs[0].num < leastVisible) {
115
- leastVisible = leafMap[i].leafs[0].num;
116
- }
117
- if (leafMap[i].leafs[leafMap[i].leafs.length - 1].num > mostVisible) {
118
- mostVisible = leafMap[i].leafs[leafMap[i].leafs.length - 1].num;
119
- }
120
- }
121
- if (leafTop > leafMap[i].top) { leafMap[i].top = leafTop; }
122
- leafTop = leafBottom;
123
- }
124
- // at this point, `rowsToDisplay` now has all the rows in view
125
-
126
- // create a buffer of preloaded rows before and after the visible rows
127
- const firstRow = rowsToDisplay[0];
128
- const lastRow = rowsToDisplay[rowsToDisplay.length - 1];
129
- for (let i = 1; i < this.br.thumbRowBuffer + 1; i++) {
130
- if (lastRow + i < leafMap.length) { rowsToDisplay.push(lastRow + i); }
131
- }
132
- for (let i = 1; i < this.br.thumbRowBuffer; i++) {
133
- if (firstRow - i >= 0) { rowsToDisplay.push(firstRow - i); }
134
- }
135
- rowsToDisplay.sort();
136
-
137
- // Create the thumbnail divs and images (lazy loaded)
138
- for (const row of rowsToDisplay) {
139
- if (notInArray(row, this.br.displayedRows)) {
140
- if (!leafMap[row]) { continue; }
141
- for (const { num: leaf, left: leafLeft } of leafMap[row].leafs) {
142
- const leafWidth = this.br.thumbWidth;
143
- const leafHeight = floor((book.getPageHeight(leaf) * this.br.thumbWidth) / book.getPageWidth(leaf));
144
- const leafTop = leafMap[row].top;
145
- let left = leafLeft + pageViewBuffer;
146
- if ('rl' == this.br.pageProgression) {
147
- left = viewWidth - leafWidth - left;
148
- }
149
-
150
- left += this.br.thumbPadding;
151
- imagesToDisplay.push(leaf);
152
-
153
- /* get thumbnail's reducer */
154
- const idealReduce = floor(book.getPageWidth(leaf) / this.br.thumbWidth);
155
- const nearestFactor2 = 2 * Math.round(idealReduce / 2);
156
- const thumbReduce = nearestFactor2;
157
-
158
- const pageContainer = this.br._createPageContainer(leaf)
159
- .update({
160
- dimensions: {
161
- width: leafWidth,
162
- height: leafHeight,
163
- top: leafTop,
164
- left,
165
- },
166
- reduce: thumbReduce,
167
- });
168
-
169
- pageContainer.$container.data('leaf', leaf).on('mouseup', event => {
170
- // We want to suppress the fragmentChange triggers in `updateFirstIndex` and `switchMode`
171
- // because otherwise it repeatedly triggers listeners and we get in an infinite loop.
172
- // We manually trigger the `fragmentChange` once at the end.
173
- this.br.updateFirstIndex(leaf, { suppressFragmentChange: true });
174
- // as per request in webdev-4042, we want to switch 1-up mode while clicking on thumbnail leafs
175
- this.br.switchMode(this.br.constMode1up, { suppressFragmentChange: true });
176
-
177
- // shift viewModeOrder after clicking on thumbsnail leaf
178
- const nextModeID = this.br.viewModeOrder.shift();
179
- this.br.viewModeOrder.push(nextModeID);
180
- this.br.updateViewModeButton($('.viewmode'), 'twopg', 'Two-page view');
181
-
182
- this.br.trigger(EVENTS.fragmentChange);
183
- event.stopPropagation();
184
- });
185
-
186
- this.br.refs.$brPageViewEl.append(pageContainer.$container);
187
- }
188
- }
189
- }
190
-
191
- // Remove thumbnails that are not to be displayed
192
- for (const row of this.br.displayedRows) {
193
- if (notInArray(row, rowsToDisplay)) {
194
- for (const { num: index } of leafMap[row]?.leafs) {
195
- if (!imagesToDisplay?.includes(index)) {
196
- this.br.$(`.pagediv${index}`)?.remove();
197
- }
198
- }
199
- }
200
- }
201
-
202
- // Update which page is considered current to make sure a visible page is the current one
203
- const currentIndex = this.br.currentIndex();
204
- if (currentIndex < leastVisible) {
205
- this.br.updateFirstIndex(leastVisible);
206
- } else if (currentIndex > mostVisible) {
207
- this.br.updateFirstIndex(mostVisible);
208
- }
209
-
210
- // remember what rows are displayed
211
- this.br.displayedRows = rowsToDisplay.slice();
212
-
213
- // remove previous highlights
214
- this.br.$('.BRpagedivthumb_highlight').removeClass('BRpagedivthumb_highlight');
215
-
216
- // highlight current page
217
- this.br.$('.pagediv' + this.br.currentIndex()).addClass('BRpagedivthumb_highlight');
218
-
219
- this.br.updateToolbarZoom(this.br.reduce);
220
- }
221
-
222
- /**
223
- * Replaces placeholder image with real one
224
- *
225
- * @param {$lazyLoadImgPlaceholder} imgPlaceholder
226
- */
227
- lazyLoadImage(imgPlaceholder) {
228
- const leaf = $(imgPlaceholder).data('leaf');
229
- const reduce = $(imgPlaceholder).data('reduce');
230
- const $img = this.br.imageCache.image(leaf, reduce);
231
- const $parent = $(imgPlaceholder).parent();
232
- /* March 16, 2021 (isa) - manually append & remove, `replaceWith` currently loses closure scope */
233
- $($parent).append($img);
234
- $(imgPlaceholder).remove();
235
- }
236
-
237
- /**
238
- * @param {'in' | 'out'} direction
239
- */
240
- zoom(direction) {
241
- const oldColumns = this.br.thumbColumns;
242
- switch (direction) {
243
- case 'in':
244
- this.br.thumbColumns -= 1;
245
- break;
246
- case 'out':
247
- this.br.thumbColumns += 1;
248
- break;
249
- default:
250
- console.error(`Unsupported direction: ${direction}`);
251
- }
252
-
253
- // Limit zoom in/out columns
254
- this.br.thumbColumns = clamp(
255
- this.br.thumbColumns,
256
- this.br.options.thumbMinZoomColumns,
257
- this.br.options.thumbMaxZoomColumns
258
- );
259
-
260
- if (this.br.thumbColumns != oldColumns) {
261
- this.br.displayedRows = []; /* force a gallery redraw */
262
- this.prepare();
263
- }
264
- }
265
-
266
- /**
267
- * Returns the width per thumbnail to display the requested number of columns
268
- * Note: #BRpageview must already exist since its width is used to calculate the
269
- * thumbnail width
270
- * @param {number} thumbnailColumns
271
- */
272
- getThumbnailWidth(thumbnailColumns) {
273
- const DEFAULT_THUMBNAIL_WIDTH = 100;
274
-
275
- const padding = (thumbnailColumns + 1) * this.br.thumbPadding;
276
- const width = (this.br.refs.$brPageViewEl.width() - padding) / (thumbnailColumns + 0.5); // extra 0.5 is for some space at sides
277
- const idealThumbnailWidth = Math.floor(width);
278
- return idealThumbnailWidth > 0 ? idealThumbnailWidth : DEFAULT_THUMBNAIL_WIDTH;
279
- }
280
-
281
- prepare() {
282
- this.br.refs.$brContainer.empty();
283
- this.br.refs.$brContainer.css({
284
- overflowY: 'scroll',
285
- overflowX: 'auto'
286
- });
287
-
288
- this.br.refs.$brPageViewEl = $("<div class='BRpageview'></div>");
289
- this.br.refs.$brContainer.append(this.br.refs.$brPageViewEl);
290
- this.dragScrollable = this.dragScrollable || new DragScrollable(this.br.refs.$brContainer[0], {preventDefault: true});
291
-
292
- this.br.bindGestures(this.br.refs.$brContainer);
293
-
294
- // $$$ keep select enabled for now since disabling it breaks keyboard
295
- // nav in FF 3.6 (https://bugs.edge.launchpad.net/bookreader/+bug/544666)
296
- // disableSelect(this.br.$('#BRpageview'));
297
- this.br.thumbWidth = this.getThumbnailWidth(this.br.thumbColumns);
298
- this.br.reduce = this.book.getPageWidth(0) / this.br.thumbWidth;
299
- this.br.displayedRows = [];
300
- // Draw leafs with current index directly in view (no animating to the index)
301
- this.drawLeafs(this.br.currentIndex());
302
- this.br.updateBrClasses();
303
- }
304
-
305
- /**
306
- * @param {PageIndex} index
307
- */
308
- jumpToIndex(index) {
309
- const { floor } = Math;
310
- const { book } = this;
311
- const viewWidth = this.br.refs.$brContainer.prop('scrollWidth') - 20; // width minus buffer
312
- const leafWidth = this.br.thumbWidth;
313
- let leafTop = 0;
314
- let rightPos = 0;
315
- let bottomPos = 0;
316
- let rowHeight = 0;
317
- let leafIndex = 0;
318
-
319
- for (let i = 0; i <= index; i++) {
320
- if (rightPos + (leafWidth + this.br.thumbPadding) > viewWidth) {
321
- rightPos = 0;
322
- rowHeight = 0;
323
- leafIndex = 0;
324
- }
325
-
326
- const leafHeight = floor((book.getPageHeight(leafIndex) * this.br.thumbWidth) / book.getPageWidth(leafIndex));
327
- if (leafHeight > rowHeight) { rowHeight = leafHeight; }
328
- if (leafIndex == 0) {
329
- leafTop = bottomPos;
330
- bottomPos += this.br.thumbPadding + rowHeight;
331
- }
332
- rightPos += leafWidth + this.br.thumbPadding;
333
- leafIndex++;
334
- }
335
- this.br.updateFirstIndex(index);
336
- if (this.br.refs.$brContainer.prop('scrollTop') == leafTop) {
337
- this.br.drawLeafs();
338
- } else {
339
- this.br.animating = true;
340
- this.br.refs.$brContainer.stop(true)
341
- .animate({ scrollTop: leafTop }, 'fast', () => { this.br.animating = false; });
342
- }
343
- }
344
- }