@internetarchive/bookreader 5.0.0-18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +58 -0
- package/.gitattributes +2 -0
- package/.github/ISSUE_TEMPLATE/bug.md +32 -0
- package/.github/ISSUE_TEMPLATE/feature-request.md +30 -0
- package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +15 -0
- package/.github/dependabot.yml +8 -0
- package/.github/workflows/node.js.yml +37 -0
- package/.github/workflows/npm-publish.yml +47 -0
- package/.testcaferc.json +5 -0
- package/BookReader/BookReader.css +2983 -0
- package/BookReader/BookReader.js +3 -0
- package/BookReader/BookReader.js.LICENSE.txt +117 -0
- package/BookReader/BookReader.js.map +1 -0
- package/BookReader/bookreader-component-bundle.js +1436 -0
- package/BookReader/bookreader-component-bundle.js.LICENSE.txt +27 -0
- package/BookReader/bookreader-component-bundle.js.map +1 -0
- package/BookReader/icons/1up.svg +1 -0
- package/BookReader/icons/2up.svg +1 -0
- package/BookReader/icons/advance.svg +3 -0
- package/BookReader/icons/chevron-right.svg +1 -0
- package/BookReader/icons/close-circle-dark.svg +1 -0
- package/BookReader/icons/close-circle.svg +1 -0
- package/BookReader/icons/fullscreen.svg +1 -0
- package/BookReader/icons/fullscreen_exit.svg +1 -0
- package/BookReader/icons/hamburger.svg +1 -0
- package/BookReader/icons/left-arrow.svg +1 -0
- package/BookReader/icons/magnify-minus.svg +1 -0
- package/BookReader/icons/magnify-plus.svg +1 -0
- package/BookReader/icons/magnify.svg +1 -0
- package/BookReader/icons/pause.svg +1 -0
- package/BookReader/icons/play.svg +1 -0
- package/BookReader/icons/playback-speed.svg +1 -0
- package/BookReader/icons/read-aloud.svg +1 -0
- package/BookReader/icons/review.svg +3 -0
- package/BookReader/icons/thumbnails.svg +1 -0
- package/BookReader/icons/volume-full.svg +1 -0
- package/BookReader/images/BRicons.png +0 -0
- package/BookReader/images/BRicons.svg +5 -0
- package/BookReader/images/BRicons_ia.png +0 -0
- package/BookReader/images/back_pages.png +0 -0
- package/BookReader/images/book_bottom_icon.png +0 -0
- package/BookReader/images/book_down_icon.png +0 -0
- package/BookReader/images/book_left_icon.png +0 -0
- package/BookReader/images/book_leftmost_icon.png +0 -0
- package/BookReader/images/book_right_icon.png +0 -0
- package/BookReader/images/book_rightmost_icon.png +0 -0
- package/BookReader/images/book_top_icon.png +0 -0
- package/BookReader/images/book_up_icon.png +0 -0
- package/BookReader/images/books_graphic.svg +1 -0
- package/BookReader/images/booksplit.png +0 -0
- package/BookReader/images/control_pause_icon.png +0 -0
- package/BookReader/images/control_play_icon.png +0 -0
- package/BookReader/images/embed_icon.png +0 -0
- package/BookReader/images/icon-home-ia.png +0 -0
- package/BookReader/images/icon_OL-logo-xs.png +0 -0
- package/BookReader/images/icon_alert-xs.png +0 -0
- package/BookReader/images/icon_book.svg +1 -0
- package/BookReader/images/icon_bookmark.svg +1 -0
- package/BookReader/images/icon_close-pop.png +0 -0
- package/BookReader/images/icon_download.png +0 -0
- package/BookReader/images/icon_gear.svg +1 -0
- package/BookReader/images/icon_hamburger.svg +1 -0
- package/BookReader/images/icon_home.png +0 -0
- package/BookReader/images/icon_home.svg +1 -0
- package/BookReader/images/icon_home_ia.png +0 -0
- package/BookReader/images/icon_indicator.png +0 -0
- package/BookReader/images/icon_info.svg +1 -0
- package/BookReader/images/icon_one_page.svg +1 -0
- package/BookReader/images/icon_pause.svg +1 -0
- package/BookReader/images/icon_play.svg +1 -0
- package/BookReader/images/icon_playback-rate.svg +1 -0
- package/BookReader/images/icon_return.png +0 -0
- package/BookReader/images/icon_search_button.svg +1 -0
- package/BookReader/images/icon_share.svg +1 -0
- package/BookReader/images/icon_skip-ahead.svg +1 -0
- package/BookReader/images/icon_skip-back.svg +2 -0
- package/BookReader/images/icon_speaker.svg +1 -0
- package/BookReader/images/icon_speaker_open.svg +1 -0
- package/BookReader/images/icon_thumbnails.svg +1 -0
- package/BookReader/images/icon_toc.svg +1 -0
- package/BookReader/images/icon_two_pages.svg +1 -0
- package/BookReader/images/icon_zoomer.png +0 -0
- package/BookReader/images/loading.gif +0 -0
- package/BookReader/images/logo_icon.png +0 -0
- package/BookReader/images/marker_chap-off.png +0 -0
- package/BookReader/images/marker_chap-off.svg +1 -0
- package/BookReader/images/marker_chap-off_ia.png +0 -0
- package/BookReader/images/marker_chap-on.png +0 -0
- package/BookReader/images/marker_chap-on.svg +1 -0
- package/BookReader/images/marker_srch-on.svg +1 -0
- package/BookReader/images/marker_srchchap-off.png +0 -0
- package/BookReader/images/marker_srchchap-on.png +0 -0
- package/BookReader/images/nav_control-dn.png +0 -0
- package/BookReader/images/nav_control-dn_ia.png +0 -0
- package/BookReader/images/nav_control-up.png +0 -0
- package/BookReader/images/nav_control-up_ia.png +0 -0
- package/BookReader/images/nav_control.png +0 -0
- package/BookReader/images/one_page_mode_icon.png +0 -0
- package/BookReader/images/paper-badge.png +0 -0
- package/BookReader/images/print_icon.png +0 -0
- package/BookReader/images/progressbar.gif +0 -0
- package/BookReader/images/right_edges.png +0 -0
- package/BookReader/images/slider.png +0 -0
- package/BookReader/images/slider_ia.png +0 -0
- package/BookReader/images/thumbnail_mode_icon.png +0 -0
- package/BookReader/images/transparent.png +0 -0
- package/BookReader/images/two_page_mode_icon.png +0 -0
- package/BookReader/images/zoom_in_icon.png +0 -0
- package/BookReader/images/zoom_out_icon.png +0 -0
- package/BookReader/jquery-1.10.1.js +2 -0
- package/BookReader/jquery-1.10.1.js.LICENSE.txt +24 -0
- package/BookReader/plugins/plugin.archive_analytics.js +2 -0
- package/BookReader/plugins/plugin.archive_analytics.js.map +1 -0
- package/BookReader/plugins/plugin.autoplay.js +2 -0
- package/BookReader/plugins/plugin.autoplay.js.map +1 -0
- package/BookReader/plugins/plugin.chapters.js +2 -0
- package/BookReader/plugins/plugin.chapters.js.map +1 -0
- package/BookReader/plugins/plugin.iframe.js +2 -0
- package/BookReader/plugins/plugin.iframe.js.map +1 -0
- package/BookReader/plugins/plugin.mobile_nav.js +2 -0
- package/BookReader/plugins/plugin.mobile_nav.js.map +1 -0
- package/BookReader/plugins/plugin.resume.js +2 -0
- package/BookReader/plugins/plugin.resume.js.map +1 -0
- package/BookReader/plugins/plugin.search.js +2 -0
- package/BookReader/plugins/plugin.search.js.map +1 -0
- package/BookReader/plugins/plugin.text_selection.js +2 -0
- package/BookReader/plugins/plugin.text_selection.js.map +1 -0
- package/BookReader/plugins/plugin.tts.js +3 -0
- package/BookReader/plugins/plugin.tts.js.LICENSE.txt +27 -0
- package/BookReader/plugins/plugin.tts.js.map +1 -0
- package/BookReader/plugins/plugin.url.js +2 -0
- package/BookReader/plugins/plugin.url.js.map +1 -0
- package/BookReader/plugins/plugin.vendor-fullscreen.js +2 -0
- package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -0
- package/BookReaderDemo/BookReaderDemo.css +41 -0
- package/BookReaderDemo/BookReaderJSAdvanced.js +115 -0
- package/BookReaderDemo/BookReaderJSAutoplay.js +56 -0
- package/BookReaderDemo/BookReaderJSSimple.js +55 -0
- package/BookReaderDemo/IIIFBookReader.js +207 -0
- package/BookReaderDemo/assets/v5/Bookreader-logo-cool-grad.svg +1 -0
- package/BookReaderDemo/assets/v5/Bookreader-logo-flat.svg +1 -0
- package/BookReaderDemo/assets/v5/Bookreader-logo-hex-cool-grad.png +0 -0
- package/BookReaderDemo/assets/v5/Bookreader-logo-hex-flat.png +0 -0
- package/BookReaderDemo/assets/v5/Bookreader-logo-lines.png +0 -0
- package/BookReaderDemo/assets/v5/Bookreader-logo-lines.svg +1 -0
- package/BookReaderDemo/assets/v5/Bookreader-logo-warm.svg +1 -0
- package/BookReaderDemo/assets/v5/bookreader-logo-renders@1x.png +0 -0
- package/BookReaderDemo/assets/v5/bookreader-logo-renders@2x.png +0 -0
- package/BookReaderDemo/assets/v5/bookreader-v5-screenshot.png +0 -0
- package/BookReaderDemo/bookreader-template-bundle.js +7178 -0
- package/BookReaderDemo/demo-advanced.html +32 -0
- package/BookReaderDemo/demo-autoplay.html +38 -0
- package/BookReaderDemo/demo-embed-iframe-src.html +84 -0
- package/BookReaderDemo/demo-embed.html +26 -0
- package/BookReaderDemo/demo-fullscreen-mobile.html +36 -0
- package/BookReaderDemo/demo-fullscreen.html +33 -0
- package/BookReaderDemo/demo-iiif.html +34 -0
- package/BookReaderDemo/demo-iiif.js +26 -0
- package/BookReaderDemo/demo-internetarchive.html +74 -0
- package/BookReaderDemo/demo-multiple.html +43 -0
- package/BookReaderDemo/demo-preview-pages.html +1092 -0
- package/BookReaderDemo/demo-simple.html +34 -0
- package/BookReaderDemo/demo-vendor-fullscreen.html +36 -0
- package/BookReaderDemo/immersion-1up.html +64 -0
- package/BookReaderDemo/immersion-mode.html +35 -0
- package/BookReaderDemo/toggle_controls.html +53 -0
- package/BookReaderDemo/view_mode.html +39 -0
- package/BookReaderDemo/viewmode-cycle.html +41 -0
- package/CHANGELOG.md +540 -0
- package/CONTRIBUTING.md +7 -0
- package/LICENSE +661 -0
- package/README.md +205 -0
- package/babel.config.js +18 -0
- package/codecov.yml +17 -0
- package/index.html +31 -0
- package/jsconfig.json +14 -0
- package/karma.conf.js +23 -0
- package/package.json +129 -0
- package/screenshot.png +0 -0
- package/scripts/postversion.js +10 -0
- package/scripts/preversion.js +14 -0
- package/scripts/version.js +26 -0
- package/src/BookNavigator/BookModel.js +14 -0
- package/src/BookNavigator/BookNavigator.js +468 -0
- package/src/BookNavigator/assets/book-loader.js +27 -0
- package/src/BookNavigator/assets/bookmark-colors.js +15 -0
- package/src/BookNavigator/assets/button-base.js +61 -0
- package/src/BookNavigator/assets/icon_checkmark.js +6 -0
- package/src/BookNavigator/assets/icon_close.js +3 -0
- package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
- package/src/BookNavigator/assets/icon_volumes.js +11 -0
- package/src/BookNavigator/bookmarks/bookmark-button.js +64 -0
- package/src/BookNavigator/bookmarks/bookmark-edit.js +215 -0
- package/src/BookNavigator/bookmarks/bookmarks-list.js +285 -0
- package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +28 -0
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +53 -0
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +500 -0
- package/src/BookNavigator/br-fullscreen-mgr.js +83 -0
- package/src/BookNavigator/delete-modal-actions.js +49 -0
- package/src/BookNavigator/downloads/downloads-provider.js +76 -0
- package/src/BookNavigator/downloads/downloads.js +138 -0
- package/src/BookNavigator/search/a-search-result.js +55 -0
- package/src/BookNavigator/search/search-provider.js +180 -0
- package/src/BookNavigator/search/search-results.js +360 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +93 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +280 -0
- package/src/BookNavigator/volumes/volumes-provider.js +83 -0
- package/src/BookNavigator/volumes/volumes.js +178 -0
- package/src/BookReader/BookModel.js +518 -0
- package/src/BookReader/DebugConsole.js +54 -0
- package/src/BookReader/ImageCache.js +116 -0
- package/src/BookReader/Mode1Up.js +90 -0
- package/src/BookReader/Mode1UpLit.js +434 -0
- package/src/BookReader/Mode2Up.js +1372 -0
- package/src/BookReader/ModeSmoothZoom.js +177 -0
- package/src/BookReader/ModeThumb.js +336 -0
- package/src/BookReader/Navbar/Navbar.js +339 -0
- package/src/BookReader/PageContainer.js +120 -0
- package/src/BookReader/ReduceSet.js +26 -0
- package/src/BookReader/Toolbar/Toolbar.js +384 -0
- package/src/BookReader/events.js +20 -0
- package/src/BookReader/options.js +320 -0
- package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
- package/src/BookReader/utils/classes.js +36 -0
- package/src/BookReader/utils.js +240 -0
- package/src/BookReader.js +2546 -0
- package/src/BookReaderComponent/BookReaderComponent.js +112 -0
- package/src/ItemNavigator/ItemNavigator.js +376 -0
- package/src/ItemNavigator/providers/sharing.js +33 -0
- package/src/assets/icons/1up.svg +12 -0
- package/src/assets/icons/2up.svg +15 -0
- package/src/assets/icons/advance.svg +26 -0
- package/src/assets/icons/chevron-right.svg +1 -0
- package/src/assets/icons/close-circle-dark.svg +1 -0
- package/src/assets/icons/close-circle.svg +1 -0
- package/src/assets/icons/fullscreen.svg +17 -0
- package/src/assets/icons/fullscreen_exit.svg +17 -0
- package/src/assets/icons/hamburger.svg +15 -0
- package/src/assets/icons/left-arrow.svg +12 -0
- package/src/assets/icons/magnify-minus.svg +16 -0
- package/src/assets/icons/magnify-plus.svg +17 -0
- package/src/assets/icons/magnify.svg +15 -0
- package/src/assets/icons/pause.svg +23 -0
- package/src/assets/icons/play.svg +22 -0
- package/src/assets/icons/playback-speed.svg +34 -0
- package/src/assets/icons/read-aloud.svg +22 -0
- package/src/assets/icons/review.svg +22 -0
- package/src/assets/icons/thumbnails.svg +17 -0
- package/src/assets/icons/volume-full.svg +22 -0
- package/src/assets/images/BRicons.png +0 -0
- package/src/assets/images/BRicons.svg +94 -0
- package/src/assets/images/BRicons_ia.png +0 -0
- package/src/assets/images/back_pages.png +0 -0
- package/src/assets/images/book_bottom_icon.png +0 -0
- package/src/assets/images/book_down_icon.png +0 -0
- package/src/assets/images/book_left_icon.png +0 -0
- package/src/assets/images/book_leftmost_icon.png +0 -0
- package/src/assets/images/book_right_icon.png +0 -0
- package/src/assets/images/book_rightmost_icon.png +0 -0
- package/src/assets/images/book_top_icon.png +0 -0
- package/src/assets/images/book_up_icon.png +0 -0
- package/src/assets/images/books_graphic.svg +177 -0
- package/src/assets/images/booksplit.png +0 -0
- package/src/assets/images/control_pause_icon.png +0 -0
- package/src/assets/images/control_play_icon.png +0 -0
- package/src/assets/images/embed_icon.png +0 -0
- package/src/assets/images/icon-home-ia.png +0 -0
- package/src/assets/images/icon_OL-logo-xs.png +0 -0
- package/src/assets/images/icon_alert-xs.png +0 -0
- package/src/assets/images/icon_book.svg +12 -0
- package/src/assets/images/icon_bookmark.svg +12 -0
- package/src/assets/images/icon_close-pop.png +0 -0
- package/src/assets/images/icon_download.png +0 -0
- package/src/assets/images/icon_gear.svg +14 -0
- package/src/assets/images/icon_hamburger.svg +20 -0
- package/src/assets/images/icon_home.png +0 -0
- package/src/assets/images/icon_home.svg +21 -0
- package/src/assets/images/icon_home_ia.png +0 -0
- package/src/assets/images/icon_indicator.png +0 -0
- package/src/assets/images/icon_info.svg +11 -0
- package/src/assets/images/icon_one_page.svg +8 -0
- package/src/assets/images/icon_pause.svg +1 -0
- package/src/assets/images/icon_play.svg +1 -0
- package/src/assets/images/icon_playback-rate.svg +15 -0
- package/src/assets/images/icon_return.png +0 -0
- package/src/assets/images/icon_search_button.svg +8 -0
- package/src/assets/images/icon_share.svg +9 -0
- package/src/assets/images/icon_skip-ahead.svg +6 -0
- package/src/assets/images/icon_skip-back.svg +13 -0
- package/src/assets/images/icon_speaker.svg +18 -0
- package/src/assets/images/icon_speaker_open.svg +10 -0
- package/src/assets/images/icon_thumbnails.svg +12 -0
- package/src/assets/images/icon_toc.svg +5 -0
- package/src/assets/images/icon_two_pages.svg +9 -0
- package/src/assets/images/icon_zoomer.png +0 -0
- package/src/assets/images/loading.gif +0 -0
- package/src/assets/images/logo_icon.png +0 -0
- package/src/assets/images/marker_chap-off.png +0 -0
- package/src/assets/images/marker_chap-off.svg +11 -0
- package/src/assets/images/marker_chap-off_ia.png +0 -0
- package/src/assets/images/marker_chap-on.png +0 -0
- package/src/assets/images/marker_chap-on.svg +11 -0
- package/src/assets/images/marker_srch-on.svg +11 -0
- package/src/assets/images/marker_srchchap-off.png +0 -0
- package/src/assets/images/marker_srchchap-on.png +0 -0
- package/src/assets/images/nav_control-dn.png +0 -0
- package/src/assets/images/nav_control-dn_ia.png +0 -0
- package/src/assets/images/nav_control-up.png +0 -0
- package/src/assets/images/nav_control-up_ia.png +0 -0
- package/src/assets/images/nav_control.png +0 -0
- package/src/assets/images/one_page_mode_icon.png +0 -0
- package/src/assets/images/paper-badge.png +0 -0
- package/src/assets/images/print_icon.png +0 -0
- package/src/assets/images/progressbar.gif +0 -0
- package/src/assets/images/right_edges.png +0 -0
- package/src/assets/images/slider.png +0 -0
- package/src/assets/images/slider_ia.png +0 -0
- package/src/assets/images/thumbnail_mode_icon.png +0 -0
- package/src/assets/images/transparent.png +0 -0
- package/src/assets/images/two_page_mode_icon.png +0 -0
- package/src/assets/images/zoom_in_icon.png +0 -0
- package/src/assets/images/zoom_out_icon.png +0 -0
- package/src/css/BookReader.scss +89 -0
- package/src/css/_BRBookmarks.scss +29 -0
- package/src/css/_BRComponent.scss +13 -0
- package/src/css/_BRfloat.scss +197 -0
- package/src/css/_BRicon.scss +48 -0
- package/src/css/_BRmain.scss +251 -0
- package/src/css/_BRnav.scss +382 -0
- package/src/css/_BRpages.scss +139 -0
- package/src/css/_BRsearch.scss +226 -0
- package/src/css/_BRtoolbar.scss +84 -0
- package/src/css/_BRvendor.scss +5 -0
- package/src/css/_MobileNav.scss +194 -0
- package/src/css/_TextSelection.scss +32 -0
- package/src/css/_colorbox.scss +52 -0
- package/src/css/_controls.scss +244 -0
- package/src/css/_icons.scss +121 -0
- package/src/dragscrollable-br.js +261 -0
- package/src/jquery-wrapper.js +4 -0
- package/src/plugins/plugin.archive_analytics.js +86 -0
- package/src/plugins/plugin.autoplay.js +129 -0
- package/src/plugins/plugin.chapters.js +251 -0
- package/src/plugins/plugin.iframe.js +48 -0
- package/src/plugins/plugin.mobile_nav.js +287 -0
- package/src/plugins/plugin.resume.js +68 -0
- package/src/plugins/plugin.text_selection.js +291 -0
- package/src/plugins/plugin.url.js +198 -0
- package/src/plugins/plugin.vendor-fullscreen.js +247 -0
- package/src/plugins/search/plugin.search.js +439 -0
- package/src/plugins/search/view.js +440 -0
- package/src/plugins/tts/AbstractTTSEngine.js +242 -0
- package/src/plugins/tts/FestivalTTSEngine.js +169 -0
- package/src/plugins/tts/PageChunk.js +107 -0
- package/src/plugins/tts/PageChunkIterator.js +163 -0
- package/src/plugins/tts/WebTTSEngine.js +352 -0
- package/src/plugins/tts/plugin.tts.js +335 -0
- package/src/plugins/tts/tooltip_dict.js +15 -0
- package/src/plugins/tts/utils.js +91 -0
- package/src/util/browserSniffing.js +30 -0
- package/src/util/debouncer.js +26 -0
- package/src/util/docCookies.js +67 -0
- package/src/util/strings.js +34 -0
- package/tests/BookReader/BookModel.test.js +312 -0
- package/tests/BookReader/BookReaderPublicFunctions.test.js +164 -0
- package/tests/BookReader/DebugConsole.test.js +25 -0
- package/tests/BookReader/ImageCache.test.js +150 -0
- package/tests/BookReader/Mode1UpLit.test.js +87 -0
- package/tests/BookReader/Mode2Up.test.js +245 -0
- package/tests/BookReader/ModeSmoothZoom.test.js +149 -0
- package/tests/BookReader/Navbar/Navbar.test.js +169 -0
- package/tests/BookReader/PageContainer.test.js +187 -0
- package/tests/BookReader/ReduceSet.test.js +38 -0
- package/tests/BookReader/Toolbar/Toolbar.test.js +26 -0
- package/tests/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
- package/tests/BookReader/utils/classes.test.js +88 -0
- package/tests/BookReader/utils.test.js +136 -0
- package/tests/BookReader.options.test.js +39 -0
- package/tests/BookReader.test.js +301 -0
- package/tests/e2e/README.md +75 -0
- package/tests/e2e/autoplay.test.js +13 -0
- package/tests/e2e/base.test.js +35 -0
- package/tests/e2e/helpers/base.js +263 -0
- package/tests/e2e/helpers/debug.js +13 -0
- package/tests/e2e/helpers/desktopSearch.js +72 -0
- package/tests/e2e/helpers/mobileSearch.js +85 -0
- package/tests/e2e/helpers/mockSearch.js +93 -0
- package/tests/e2e/helpers/rightToLeft.js +29 -0
- package/tests/e2e/ia-production/ia-prod-base.js +17 -0
- package/tests/e2e/models/BookReader.js +11 -0
- package/tests/e2e/models/Navigation.js +56 -0
- package/tests/e2e/rightToLeft.test.js +20 -0
- package/tests/e2e/viewmode.test.js +37 -0
- package/tests/karma/BookNavigator/book-navigator.test.js +180 -0
- package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +133 -0
- package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +222 -0
- package/tests/karma/BookNavigator/downloads/downloads-provider.test.js +64 -0
- package/tests/karma/BookNavigator/downloads/downloads.test.js +54 -0
- package/tests/karma/BookNavigator/search/search-provider.test.js +23 -0
- package/tests/karma/BookNavigator/search/search-results.test.js +240 -0
- package/tests/karma/BookNavigator/sharing/sharing-provider.test.js +40 -0
- package/tests/karma/BookNavigator/visual-adjustments.test.js +201 -0
- package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +160 -0
- package/tests/karma/BookNavigator/volumes/volumes.test.js +98 -0
- package/tests/plugins/plugin.archive_analytics.test.js +23 -0
- package/tests/plugins/plugin.autoplay.test.js +52 -0
- package/tests/plugins/plugin.chapters.test.js +130 -0
- package/tests/plugins/plugin.iframe.test.js +42 -0
- package/tests/plugins/plugin.mobile_nav.test.js +66 -0
- package/tests/plugins/plugin.resume.test.js +98 -0
- package/tests/plugins/plugin.text_selection.test.js +193 -0
- package/tests/plugins/plugin.url.test.js +129 -0
- package/tests/plugins/plugin.vendor-fullscreen.test.js +65 -0
- package/tests/plugins/search/plugin.search.test.js +173 -0
- package/tests/plugins/search/plugin.search.view.test.js +106 -0
- package/tests/plugins/tts/AbstractTTSEngine.test.js +153 -0
- package/tests/plugins/tts/FestivalTTSEngine.test.js +59 -0
- package/tests/plugins/tts/PageChunk.test.js +57 -0
- package/tests/plugins/tts/PageChunkIterator.test.js +179 -0
- package/tests/plugins/tts/WebTTSEngine.test.js +126 -0
- package/tests/plugins/tts/utils.test.js +133 -0
- package/tests/util/browserSniffing.test.js +56 -0
- package/tests/util/docCookies.test.js +15 -0
- package/tests/util/strings.test.js +63 -0
- package/tests/utils.js +80 -0
- package/webpack.config.js +85 -0
@@ -0,0 +1,1372 @@
|
|
1
|
+
// @ts-check
|
2
|
+
// effect.js gives acces to extra easing function (e.g. easeInSine)
|
3
|
+
import 'jquery-ui/ui/effect.js';
|
4
|
+
import '../dragscrollable-br.js';
|
5
|
+
import { clamp } from './utils.js';
|
6
|
+
import { EVENTS } from './events.js';
|
7
|
+
import { ModeSmoothZoom } from "./ModeSmoothZoom.js";
|
8
|
+
import { HTMLDimensionsCacher } from './utils/HTMLDimensionsCacher.js';
|
9
|
+
|
10
|
+
/** @typedef {import('../BookReader.js').default} BookReader */
|
11
|
+
/** @typedef {import('./BookModel.js').BookModel} BookModel */
|
12
|
+
/** @typedef {import('./BookModel.js').PageIndex} PageIndex */
|
13
|
+
/** @typedef {import('./options.js').BookReaderOptions} BookReaderOptions */
|
14
|
+
/** @typedef {import('./PageContainer.js').PageContainer} PageContainer */
|
15
|
+
/** @typedef {import('./ModeSmoothZoom').SmoothZoomable} SmoothZoomable */
|
16
|
+
|
17
|
+
/** @implements {SmoothZoomable} */
|
18
|
+
export class Mode2Up {
|
19
|
+
/**
|
20
|
+
* @param {BookReader} br
|
21
|
+
* @param {BookModel} bookModel
|
22
|
+
*/
|
23
|
+
constructor(br, bookModel) {
|
24
|
+
this.br = br;
|
25
|
+
this.book = bookModel;
|
26
|
+
|
27
|
+
/** @type {HTMLDivElement} */
|
28
|
+
this.leafEdgeL = null;
|
29
|
+
/** @type {HTMLDivElement} */
|
30
|
+
this.leafEdgeR = null;
|
31
|
+
|
32
|
+
/** @type {{ [index: number]: PageContainer }} */
|
33
|
+
this.pageContainers = {};
|
34
|
+
|
35
|
+
/** @type {ModeSmoothZoom} */
|
36
|
+
this.smoothZoomer = null;
|
37
|
+
this._scale = 1;
|
38
|
+
this.scaleCenter = { x: 0.5, y: 0.5 };
|
39
|
+
}
|
40
|
+
|
41
|
+
get $container() {
|
42
|
+
return this.br.refs.$brContainer[0];
|
43
|
+
}
|
44
|
+
get $visibleWorld() {
|
45
|
+
return this.br.refs.$brTwoPageView?.[0];
|
46
|
+
}
|
47
|
+
|
48
|
+
get scale() { return this._scale; }
|
49
|
+
set scale(newVal) {
|
50
|
+
this.$visibleWorld.style.transform = `scale(${newVal})`;
|
51
|
+
this.updateViewportOnZoom(newVal, this._scale);
|
52
|
+
this._scale = newVal;
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* @param {PageIndex} index
|
57
|
+
*/
|
58
|
+
jumpToIndex(index) {
|
59
|
+
// By checking against min/max we do nothing if requested index
|
60
|
+
// is current
|
61
|
+
if (index < Math.min(this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR)) {
|
62
|
+
this.flipBackToIndex(index);
|
63
|
+
} else if (index > Math.max(this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR)) {
|
64
|
+
this.flipFwdToIndex(index);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* Draws book spread,
|
70
|
+
* sets event handlers,
|
71
|
+
* sets: `this.br.displayedIndices`
|
72
|
+
* updates toolbar zoom
|
73
|
+
* Important: `this.br.refs.$brTwoPageView` parent container must be emptied before calling
|
74
|
+
*/
|
75
|
+
drawLeafs() {
|
76
|
+
const $twoPageViewEl = this.br.refs.$brTwoPageView;
|
77
|
+
const indexL = this.br.twoPage.currentIndexL;
|
78
|
+
const indexR = this.br.twoPage.currentIndexR;
|
79
|
+
|
80
|
+
this.createPageContainer(indexL).$container
|
81
|
+
.css(this.leftLeafCss)
|
82
|
+
.appendTo($twoPageViewEl);
|
83
|
+
this.createPageContainer(indexR).$container
|
84
|
+
.css(this.rightLeafCss)
|
85
|
+
.appendTo($twoPageViewEl);
|
86
|
+
|
87
|
+
this.displayedIndices = [this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR];
|
88
|
+
this.br.displayedIndices = this.displayedIndices;
|
89
|
+
this.br.updateToolbarZoom(this.br.reduce);
|
90
|
+
this.br.trigger('pageChanged');
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* @param {1} direction
|
95
|
+
*/
|
96
|
+
zoom(direction) {
|
97
|
+
this.br.stopFlipAnimations();
|
98
|
+
|
99
|
+
// Recalculate autofit factors
|
100
|
+
this.calculateReductionFactors();
|
101
|
+
|
102
|
+
// Get new zoom state
|
103
|
+
const reductionFactor = this.br.nextReduce(this.br.reduce, direction, this.br.twoPage.reductionFactors);
|
104
|
+
if ((this.br.reduce == reductionFactor.reduce) && (this.br.twoPage.autofit == reductionFactor.autofit)) {
|
105
|
+
// Same zoom
|
106
|
+
return;
|
107
|
+
}
|
108
|
+
this.br.twoPage.autofit = reductionFactor.autofit;
|
109
|
+
this.br.reduce = reductionFactor.reduce;
|
110
|
+
this.br.pageScale = this.br.reduce; // preserve current reduce
|
111
|
+
|
112
|
+
// Preserve view center position
|
113
|
+
const oldCenter = this.getViewCenter();
|
114
|
+
|
115
|
+
// Prepare view with new center to minimize visual glitches
|
116
|
+
const drawNewSpread = true;
|
117
|
+
this.prepareTwoPageView(oldCenter.percentageX, oldCenter.percentageY, drawNewSpread);
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Resize spread containers, does not prefetch
|
122
|
+
* uses `this.br.twoPage` properties
|
123
|
+
*/
|
124
|
+
resizeSpread() {
|
125
|
+
this.br.resizeBRcontainer(false); // no animation
|
126
|
+
this.calculateSpreadSize();
|
127
|
+
|
128
|
+
this.br.refs?.$brTwoPageView.css(this.mainContainerCss);
|
129
|
+
this.centerView(); // let function self adjust
|
130
|
+
|
131
|
+
$(this.br.twoPage.coverDiv).css(this.spreadCoverCss); // click sheath is memoized somehow
|
132
|
+
const $spreadLayers = this.br.refs.$brTwoPageView;
|
133
|
+
|
134
|
+
$spreadLayers.find('.BRleafEdgeR')?.css(this.leafEdgeRCss);
|
135
|
+
$spreadLayers.find('.BRleafEdgeL')?.css(this.leafEdgeLCss);
|
136
|
+
$spreadLayers.find('.BRgutter')?.css(this.spineCss);
|
137
|
+
|
138
|
+
const indexL = this.br.twoPage.currentIndexL;
|
139
|
+
const indexR = this.br.twoPage.currentIndexR;
|
140
|
+
this.pageContainers[indexL].$container.css(this.leftLeafCss);
|
141
|
+
this.pageContainers[indexR].$container.css(this.rightLeafCss);
|
142
|
+
}
|
143
|
+
|
144
|
+
/**
|
145
|
+
* @param {number} centerPercentageX
|
146
|
+
* @param {number} centerPercentageY
|
147
|
+
* @param {Boolean} drawNewSpread
|
148
|
+
*/
|
149
|
+
prepareTwoPageView(centerPercentageX, centerPercentageY, drawNewSpread = false) {
|
150
|
+
// Some decisions about two page view:
|
151
|
+
//
|
152
|
+
// Both pages will be displayed at the same height, even if they were different physical/scanned
|
153
|
+
// sizes. This simplifies the animation (from a design as well as technical standpoint). We
|
154
|
+
// examine the page aspect ratios (in calculateSpreadSize) and use the page with the most "normal"
|
155
|
+
// aspect ratio to determine the height.
|
156
|
+
//
|
157
|
+
// The two page view div is resized to keep the middle of the book in the middle of the div
|
158
|
+
// even as the page sizes change. To e.g. keep the middle of the book in the middle of the BRcontent
|
159
|
+
// div requires adjusting the offset of BRtwpageview and/or scrolling in BRcontent.
|
160
|
+
const startingReduce = this.br.reduce;
|
161
|
+
const startingIndices = this.br.displayedIndices;
|
162
|
+
|
163
|
+
this.br.refs.$brContainer.empty();
|
164
|
+
this.br.refs.$brContainer.css('overflow', 'auto');
|
165
|
+
|
166
|
+
// We want to display two facing pages. We may be missing
|
167
|
+
// one side of the spread because it is the first/last leaf,
|
168
|
+
// foldouts, missing pages, etc
|
169
|
+
|
170
|
+
const targetLeaf = clamp(this.br.firstIndex, this.br.firstDisplayableIndex(), this.br.lastDisplayableIndex());
|
171
|
+
const currentSpreadIndices = this.book.getSpreadIndices(targetLeaf);
|
172
|
+
this.br.twoPage.currentIndexL = currentSpreadIndices[0];
|
173
|
+
this.br.twoPage.currentIndexR = currentSpreadIndices[1];
|
174
|
+
|
175
|
+
this.calculateSpreadSize(); //sets this.br.reduce, twoPage.width, twoPage.height and others
|
176
|
+
|
177
|
+
/* check if calculations have changed that warrant a new book draw */
|
178
|
+
const sameReducer = startingReduce == this.br.reduce;
|
179
|
+
const sameStart = startingIndices == this.br.displayedIndices;
|
180
|
+
const hasNewDisplayPagesOrDimensions = !sameStart || (sameStart && !sameReducer);
|
181
|
+
|
182
|
+
if (drawNewSpread || hasNewDisplayPagesOrDimensions) {
|
183
|
+
this.prunePageContainers();
|
184
|
+
this.prefetch();
|
185
|
+
}
|
186
|
+
|
187
|
+
// Add the two page view
|
188
|
+
// $$$ Can we get everything set up and then append?
|
189
|
+
this.br.refs.$brTwoPageView = this.br.refs.$brTwoPageView || $('<div class="BRtwopageview"></div>');
|
190
|
+
const $twoPageViewEl = this.br.refs.$brTwoPageView;
|
191
|
+
$twoPageViewEl.empty();
|
192
|
+
$twoPageViewEl[0].style.transformOrigin = '0 0';
|
193
|
+
this.br.refs.$brContainer.append($twoPageViewEl);
|
194
|
+
|
195
|
+
// Attaches to first child, so must come after we add the page view
|
196
|
+
this.br.refs.$brContainer.dragscrollable({
|
197
|
+
preventDefault:true,
|
198
|
+
// Only handle mouse events; let browser/HammerJS handle touch
|
199
|
+
dragstart: 'mousedown',
|
200
|
+
dragcontinue: 'mousemove',
|
201
|
+
dragend: 'mouseup',
|
202
|
+
});
|
203
|
+
|
204
|
+
this.attachMouseHandlers();
|
205
|
+
|
206
|
+
// $$$ calculate container size first
|
207
|
+
this.br.refs?.$brTwoPageView.css(this.mainContainerCss);
|
208
|
+
|
209
|
+
// This will trump the incoming coordinates
|
210
|
+
// in order to center book when zooming out
|
211
|
+
if (this.br.twoPage.totalWidth < this.br.refs.$brContainer.prop('clientWidth')) {
|
212
|
+
centerPercentageX = 0.5;
|
213
|
+
}
|
214
|
+
if (this.br.twoPage.totalHeight < this.br.refs.$brContainer.prop('clientHeight')) {
|
215
|
+
centerPercentageY = 0.5;
|
216
|
+
}
|
217
|
+
|
218
|
+
this.centerView(centerPercentageX, centerPercentageY);
|
219
|
+
|
220
|
+
// then set
|
221
|
+
this.br.twoPage.coverDiv = document.createElement('div');
|
222
|
+
$(this.br.twoPage.coverDiv).attr('class', 'BRbookcover').css(this.spreadCoverCss).appendTo(this.br.refs.$brTwoPageView);
|
223
|
+
|
224
|
+
this.leafEdgeR = document.createElement('div');
|
225
|
+
this.leafEdgeR.className = 'BRleafEdgeR';
|
226
|
+
$(this.leafEdgeR).css(this.leafEdgeRCss).appendTo(this.br.refs.$brTwoPageView);
|
227
|
+
|
228
|
+
this.leafEdgeL = document.createElement('div');
|
229
|
+
this.leafEdgeL.className = 'BRleafEdgeL';
|
230
|
+
$(this.leafEdgeL).css(this.leafEdgeLCss).appendTo(this.br.refs.$brTwoPageView);
|
231
|
+
|
232
|
+
const div = document.createElement('div');
|
233
|
+
$(div).attr('class', 'BRgutter').css(this.spineCss).appendTo(this.br.refs.$brTwoPageView);
|
234
|
+
|
235
|
+
this.preparePopUp();
|
236
|
+
|
237
|
+
this.br.displayedIndices = [];
|
238
|
+
|
239
|
+
this.drawLeafs();
|
240
|
+
this.br.updateToolbarZoom(this.br.reduce);
|
241
|
+
this.br.updateBrClasses();
|
242
|
+
|
243
|
+
this.smoothZoomer = this.smoothZoomer || new ModeSmoothZoom(this);
|
244
|
+
this.smoothZoomer.attach();
|
245
|
+
|
246
|
+
this.htmlDimensionsCacher = this.htmlDimensionsCacher || new HTMLDimensionsCacher(this.$container);
|
247
|
+
}
|
248
|
+
|
249
|
+
unprepare() {
|
250
|
+
// Mode2Up attaches these listeners to the main BR container, so we need to
|
251
|
+
// detach these or it will cause issues for the other modes.
|
252
|
+
this.smoothZoomer.detach();
|
253
|
+
}
|
254
|
+
|
255
|
+
/**
|
256
|
+
* @param {number} newScale
|
257
|
+
* @param {number} oldScale
|
258
|
+
*/
|
259
|
+
updateViewportOnZoom(newScale, oldScale) {
|
260
|
+
const container = this.br.refs.$brContainer[0];
|
261
|
+
const { scrollTop: T, scrollLeft: L } = container;
|
262
|
+
const W = this.htmlDimensionsCacher.clientWidth;
|
263
|
+
const H = this.htmlDimensionsCacher.clientHeight;
|
264
|
+
|
265
|
+
// Scale factor change
|
266
|
+
const F = newScale / oldScale;
|
267
|
+
|
268
|
+
// Where in the viewport the zoom is centered on
|
269
|
+
const XPOS = this.scaleCenter.x;
|
270
|
+
const YPOS = this.scaleCenter.y;
|
271
|
+
const oldCenter = {
|
272
|
+
x: L + XPOS * W,
|
273
|
+
y: T + YPOS * H,
|
274
|
+
};
|
275
|
+
const newCenter = {
|
276
|
+
x: F * oldCenter.x,
|
277
|
+
y: F * oldCenter.y,
|
278
|
+
};
|
279
|
+
container.scrollTop = newCenter.y - YPOS * H;
|
280
|
+
container.scrollLeft = newCenter.x - XPOS * W;
|
281
|
+
|
282
|
+
// Also update the visible page containers to load in highres if necessary
|
283
|
+
this.pageContainers[this.br.twoPage.currentIndexL]?.update({ reduce: this.br.reduce / newScale });
|
284
|
+
this.pageContainers[this.br.twoPage.currentIndexR]?.update({ reduce: this.br.reduce / newScale });
|
285
|
+
}
|
286
|
+
|
287
|
+
prunePageContainers() {
|
288
|
+
for (const index in this.pageContainers) {
|
289
|
+
if ((index != this.br.twoPage.currentIndexL) && (index != this.br.twoPage.currentIndexR)) {
|
290
|
+
$(this.pageContainers[index].$container).remove();
|
291
|
+
}
|
292
|
+
if ((index < this.br.twoPage.currentIndexL - 4) || (index > this.br.twoPage.currentIndexR + 4)) {
|
293
|
+
delete this.pageContainers[index];
|
294
|
+
}
|
295
|
+
}
|
296
|
+
}
|
297
|
+
|
298
|
+
/**
|
299
|
+
* This function prepares the "View Page n" popup that shows while the mouse is
|
300
|
+
* over the left/right "stack of sheets" edges. It also binds the mouse
|
301
|
+
* events for these divs.
|
302
|
+
*/
|
303
|
+
preparePopUp() {
|
304
|
+
this.br.twoPagePopUp = document.createElement('div');
|
305
|
+
this.br.twoPagePopUp.className = 'BRtwoPagePopUp';
|
306
|
+
$(this.br.twoPagePopUp).css({
|
307
|
+
zIndex: '1000'
|
308
|
+
}).appendTo(this.br.refs.$brContainer);
|
309
|
+
$(this.br.twoPagePopUp).hide();
|
310
|
+
|
311
|
+
const leafEdges = [
|
312
|
+
{
|
313
|
+
$leafEdge: $(this.leafEdgeL),
|
314
|
+
/** @type {function(number): PageIndex} */
|
315
|
+
jumpIndexForPageX: this.jumpIndexForLeftEdgePageX.bind(this),
|
316
|
+
leftOffset: () => -$(this.br.twoPagePopUp).width() + 120,
|
317
|
+
},
|
318
|
+
{
|
319
|
+
$leafEdge: $(this.leafEdgeR),
|
320
|
+
/** @type {function(number): PageIndex} */
|
321
|
+
jumpIndexForPageX: this.jumpIndexForRightEdgePageX.bind(this),
|
322
|
+
leftOffset: () => -120,
|
323
|
+
},
|
324
|
+
];
|
325
|
+
|
326
|
+
for (const { $leafEdge, jumpIndexForPageX, leftOffset } of leafEdges) {
|
327
|
+
$leafEdge.on('mouseenter', () => $(this.br.twoPagePopUp).show());
|
328
|
+
$leafEdge.on('mouseleave', () => $(this.br.twoPagePopUp).hide());
|
329
|
+
|
330
|
+
$leafEdge.on('click', e => {
|
331
|
+
this.br.trigger(EVENTS.stop);
|
332
|
+
this.br.jumpToIndex(jumpIndexForPageX(e.pageX));
|
333
|
+
});
|
334
|
+
|
335
|
+
$leafEdge.on('mousemove', e => {
|
336
|
+
const jumpIndex = clamp(jumpIndexForPageX(e.pageX), 0, this.book.getNumLeafs() - 1);
|
337
|
+
$(this.br.twoPagePopUp).text(`View ${this.book.getPageName(jumpIndex)}`);
|
338
|
+
|
339
|
+
// $$$ TODO: Make sure popup is positioned so that it is in view
|
340
|
+
// (https://bugs.edge.launchpad.net/gnubook/+bug/327456)
|
341
|
+
$(this.br.twoPagePopUp).css({
|
342
|
+
left: `${e.pageX - this.br.refs.$brContainer.offset().left + this.br.refs.$brContainer.scrollLeft() + leftOffset()}px`,
|
343
|
+
top: `${e.pageY - this.br.refs.$brContainer.offset().top + this.br.refs.$brContainer.scrollTop()}px`
|
344
|
+
});
|
345
|
+
});
|
346
|
+
}
|
347
|
+
}
|
348
|
+
|
349
|
+
setSpreadIndices() {
|
350
|
+
const targetLeaf = clamp(this.br.firstIndex, this.br.firstDisplayableIndex(), this.br.lastDisplayableIndex());
|
351
|
+
const currentSpreadIndices = this.book.getSpreadIndices(targetLeaf);
|
352
|
+
this.br.twoPage.currentIndexL = currentSpreadIndices[0];
|
353
|
+
this.br.twoPage.currentIndexR = currentSpreadIndices[1];
|
354
|
+
}
|
355
|
+
|
356
|
+
/**
|
357
|
+
* Calculates 2-page spread dimensions based on this.br.twoPage.currentIndexL and
|
358
|
+
* this.br.twoPage.currentIndexR
|
359
|
+
* This function sets this.br.twoPage.height, twoPage.width
|
360
|
+
*/
|
361
|
+
calculateSpreadSize() {
|
362
|
+
const firstIndex = this.br.twoPage.currentIndexL;
|
363
|
+
const secondIndex = this.br.twoPage.currentIndexR;
|
364
|
+
|
365
|
+
// Calculate page sizes and total leaf width
|
366
|
+
let spreadSize;
|
367
|
+
if ( this.br.twoPage.autofit) {
|
368
|
+
spreadSize = this.getIdealSpreadSize(firstIndex, secondIndex);
|
369
|
+
} else {
|
370
|
+
// set based on reduction factor
|
371
|
+
spreadSize = this.getSpreadSizeFromReduce(firstIndex, secondIndex, this.br.reduce);
|
372
|
+
}
|
373
|
+
// Both pages together
|
374
|
+
this.br.twoPage.height = spreadSize.height || 0;
|
375
|
+
this.br.twoPage.width = spreadSize.width || 0;
|
376
|
+
|
377
|
+
// Individual pages
|
378
|
+
this.br.twoPage.scaledWL = this.getPageWidth(firstIndex) || 0;
|
379
|
+
this.br.twoPage.scaledWR = this.getPageWidth(secondIndex) || 0;
|
380
|
+
|
381
|
+
// Leaf edges
|
382
|
+
this.br.twoPage.edgeWidth = spreadSize.totalLeafEdgeWidth; // The combined width of both edges
|
383
|
+
this.br.twoPage.leafEdgeWidthL = this.br.leafEdgeWidth(this.br.twoPage.currentIndexL);
|
384
|
+
this.br.twoPage.leafEdgeWidthR = this.br.twoPage.edgeWidth - this.br.twoPage.leafEdgeWidthL;
|
385
|
+
|
386
|
+
|
387
|
+
// Book cover
|
388
|
+
// The width of the book cover div. The combined width of both pages, twice the width
|
389
|
+
// of the book cover internal padding (2*10) and the page edges
|
390
|
+
this.br.twoPage.bookCoverDivWidth = this.coverWidth(this.br.twoPage.scaledWL + this.br.twoPage.scaledWR);
|
391
|
+
// The height of the book cover div
|
392
|
+
this.br.twoPage.bookCoverDivHeight = this.br.twoPage.height + 2 * this.br.twoPage.coverInternalPadding;
|
393
|
+
|
394
|
+
|
395
|
+
// We calculate the total width and height for the div so that we can make the book
|
396
|
+
// spine centered
|
397
|
+
const leftGutterOffset = this.gutterOffsetForIndex(firstIndex);
|
398
|
+
const leftWidthFromCenter = this.br.twoPage.scaledWL - leftGutterOffset + this.br.twoPage.leafEdgeWidthL;
|
399
|
+
const rightWidthFromCenter = this.br.twoPage.scaledWR + leftGutterOffset + this.br.twoPage.leafEdgeWidthR;
|
400
|
+
const largestWidthFromCenter = Math.max( leftWidthFromCenter, rightWidthFromCenter );
|
401
|
+
this.br.twoPage.totalWidth = 2 * (largestWidthFromCenter + this.br.twoPage.coverInternalPadding + this.br.twoPage.coverExternalPadding);
|
402
|
+
this.br.twoPage.totalHeight = this.br.twoPage.height + 2 * (this.br.twoPage.coverInternalPadding + this.br.twoPage.coverExternalPadding);
|
403
|
+
|
404
|
+
// We want to minimize the unused space in two-up mode (maximize the amount of page
|
405
|
+
// shown). We give width to the leaf edges and these widths change (though the sum
|
406
|
+
// of the two remains constant) as we flip through the book. With the book
|
407
|
+
// cover centered and fixed in the BRcontainer div the page images will meet
|
408
|
+
// at the "gutter" which is generally offset from the center.
|
409
|
+
this.br.twoPage.middle = this.br.twoPage.totalWidth >> 1;
|
410
|
+
this.br.twoPage.gutter = this.br.twoPage.middle + this.gutterOffsetForIndex(firstIndex);
|
411
|
+
|
412
|
+
// The left edge of the book cover moves depending on the width of the pages
|
413
|
+
// $$$ change to getter
|
414
|
+
this.br.twoPage.bookCoverDivLeft = this.br.twoPage.gutter - this.br.twoPage.scaledWL - this.br.twoPage.leafEdgeWidthL - this.br.twoPage.coverInternalPadding;
|
415
|
+
// The top edge of the book cover stays a fixed distance from the top
|
416
|
+
this.br.twoPage.bookCoverDivTop = this.br.twoPage.coverExternalPadding;
|
417
|
+
|
418
|
+
// Book spine
|
419
|
+
this.br.twoPage.bookSpineDivHeight = this.br.twoPage.height + 2 * this.br.twoPage.coverInternalPadding;
|
420
|
+
this.br.twoPage.bookSpineDivLeft = this.br.twoPage.middle - (this.br.twoPage.bookSpineDivWidth >> 1);
|
421
|
+
this.br.twoPage.bookSpineDivTop = this.br.twoPage.bookCoverDivTop;
|
422
|
+
|
423
|
+
this.br.reduce = spreadSize.reduce < 0 ? this.br.reduce : spreadSize.reduce; // $$$ really set this here?
|
424
|
+
}
|
425
|
+
|
426
|
+
/**
|
427
|
+
*
|
428
|
+
* @param {number} firstIndex
|
429
|
+
* @param {number} secondIndex
|
430
|
+
* @return {{ width: number, height: number, totalLeafEdgeWidth: number, reduce: number}}
|
431
|
+
*/
|
432
|
+
getIdealSpreadSize(firstIndex, secondIndex) {
|
433
|
+
const ideal = {};
|
434
|
+
|
435
|
+
// We check which page is closest to a "normal" page and use that to set the height
|
436
|
+
// for both pages. This means that foldouts and other odd size pages will be displayed
|
437
|
+
// smaller than the nominal zoom amount.
|
438
|
+
const canon5Dratio = 1.5;
|
439
|
+
|
440
|
+
const first = {
|
441
|
+
height: this.book._getPageHeight(firstIndex),
|
442
|
+
width: this.book._getPageWidth(firstIndex)
|
443
|
+
};
|
444
|
+
|
445
|
+
const second = {
|
446
|
+
height: this.book._getPageHeight(secondIndex),
|
447
|
+
width: this.book._getPageWidth(secondIndex)
|
448
|
+
};
|
449
|
+
|
450
|
+
const firstIndexRatio = first.height / first.width;
|
451
|
+
const secondIndexRatio = second.height / second.width;
|
452
|
+
|
453
|
+
let ratio;
|
454
|
+
if (Math.abs(firstIndexRatio - canon5Dratio) < Math.abs(secondIndexRatio - canon5Dratio)) {
|
455
|
+
ratio = firstIndexRatio;
|
456
|
+
} else {
|
457
|
+
ratio = secondIndexRatio;
|
458
|
+
}
|
459
|
+
|
460
|
+
const totalLeafEdgeWidth = Math.floor(this.book.getNumLeafs() * 0.1);
|
461
|
+
const maxLeafEdgeWidth = Math.floor(this.br.refs.$brContainer.prop('clientWidth') * 0.1);
|
462
|
+
ideal.totalLeafEdgeWidth = Math.min(totalLeafEdgeWidth, maxLeafEdgeWidth);
|
463
|
+
|
464
|
+
const widthOutsidePages = 2 * (this.br.twoPage.coverInternalPadding + this.br.twoPage.coverExternalPadding) + ideal.totalLeafEdgeWidth;
|
465
|
+
const heightOutsidePages = 2 * (this.br.twoPage.coverInternalPadding + this.br.twoPage.coverExternalPadding);
|
466
|
+
|
467
|
+
ideal.width = (this.br.refs.$brContainer.width() - widthOutsidePages) >> 1;
|
468
|
+
ideal.width = ideal.width > 10 ? ideal.width - 10 : 1; // $$$ fudge factor
|
469
|
+
|
470
|
+
ideal.height = this.br.refs.$brContainer.height() - heightOutsidePages;
|
471
|
+
ideal.height = ideal.height > 15 ? ideal.height - 15 : 1; // $$$ fudge factor
|
472
|
+
|
473
|
+
if (ideal.height / ratio <= ideal.width) {
|
474
|
+
//use height
|
475
|
+
ideal.width = Math.floor(ideal.height / ratio) || 1;
|
476
|
+
} else {
|
477
|
+
//use width
|
478
|
+
ideal.height = Math.floor(ideal.width * ratio) || 1;
|
479
|
+
}
|
480
|
+
|
481
|
+
// $$$ check this logic with large spreads
|
482
|
+
ideal.reduce = Math.round(((first.height + second.height) / 2) / ideal.height);
|
483
|
+
|
484
|
+
return ideal;
|
485
|
+
}
|
486
|
+
|
487
|
+
/**
|
488
|
+
* Returns the spread size calculated from the reduction factor for the given pages
|
489
|
+
* @param {number} firstIndex
|
490
|
+
* @param {number} secondIndex
|
491
|
+
* @return {Object}
|
492
|
+
*/
|
493
|
+
getSpreadSizeFromReduce(firstIndex, secondIndex, reduce) {
|
494
|
+
const spreadSize = {};
|
495
|
+
// $$$ Scale this based on reduce?
|
496
|
+
const totalLeafEdgeWidth = Math.floor(this.book.getNumLeafs() * 0.1);
|
497
|
+
// $$$ Assumes leaf edge width constant at all zoom levels
|
498
|
+
const maxLeafEdgeWidth = Math.floor(this.br.refs.$brContainer.prop('clientWidth') * 0.1);
|
499
|
+
spreadSize.totalLeafEdgeWidth = Math.min(totalLeafEdgeWidth, maxLeafEdgeWidth);
|
500
|
+
|
501
|
+
// $$$ Possibly incorrect -- we should make height "dominant"
|
502
|
+
const nativeWidth = this.book._getPageWidth(firstIndex) + this.book._getPageWidth(secondIndex);
|
503
|
+
const nativeHeight = this.book._getPageHeight(firstIndex) + this.book._getPageHeight(secondIndex);
|
504
|
+
spreadSize.height = Math.floor( (nativeHeight / 2) / this.br.reduce );
|
505
|
+
spreadSize.width = Math.floor( (nativeWidth / 2) / this.br.reduce );
|
506
|
+
spreadSize.reduce = reduce;
|
507
|
+
|
508
|
+
return spreadSize;
|
509
|
+
}
|
510
|
+
|
511
|
+
/**
|
512
|
+
* Returns the current ideal reduction factor
|
513
|
+
* @return {number}
|
514
|
+
*/
|
515
|
+
getAutofitReduce() {
|
516
|
+
const spreadSize = this.getIdealSpreadSize(this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR);
|
517
|
+
return spreadSize.reduce;
|
518
|
+
}
|
519
|
+
|
520
|
+
/**
|
521
|
+
* Returns true if the pages extend past the edge of the view
|
522
|
+
* @deprecated slated for deprecation by v5.0.0
|
523
|
+
* @return {boolean}
|
524
|
+
*/
|
525
|
+
isZoomedIn() {
|
526
|
+
let isZoomedIn = false;
|
527
|
+
if (this.br.twoPage.autofit != 'auto') {
|
528
|
+
if (this.br.reduce < this.getAutofitReduce()) {
|
529
|
+
isZoomedIn = true;
|
530
|
+
}
|
531
|
+
}
|
532
|
+
return isZoomedIn;
|
533
|
+
}
|
534
|
+
|
535
|
+
calculateReductionFactors() {
|
536
|
+
this.br.twoPage.reductionFactors = this.br.reductionFactors.concat([
|
537
|
+
{
|
538
|
+
reduce: this.getIdealSpreadSize( this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR ).reduce,
|
539
|
+
autofit: 'auto'
|
540
|
+
}
|
541
|
+
]);
|
542
|
+
this.br.twoPage.reductionFactors.sort(this.br._reduceSort);
|
543
|
+
}
|
544
|
+
|
545
|
+
/**
|
546
|
+
* Set the cursor for two page view
|
547
|
+
* @deprecated Since version 4.3.3. Will be deleted in version 5.0
|
548
|
+
*/
|
549
|
+
setCursor() {
|
550
|
+
console.warn('Call to deprecated method, Mode2Up.setCursor. No-op.');
|
551
|
+
}
|
552
|
+
|
553
|
+
/**
|
554
|
+
* @param {Number|null} index to flip back one spread, pass index=null
|
555
|
+
*/
|
556
|
+
flipBackToIndex(index) {
|
557
|
+
if (this.br.constMode1up == this.br.mode) return;
|
558
|
+
if (this.br.animating) return;
|
559
|
+
|
560
|
+
if (null != this.br.leafEdgeTmp) {
|
561
|
+
alert('error: leafEdgeTmp should be null!');
|
562
|
+
return;
|
563
|
+
}
|
564
|
+
|
565
|
+
if (null == index) {
|
566
|
+
const {currentIndexL, currentIndexR} = this.br.twoPage;
|
567
|
+
const minDisplayedIndex = Math.min(currentIndexL, currentIndexR);
|
568
|
+
const prev = this.book.getPage(minDisplayedIndex).findPrev({ combineConsecutiveUnviewables: true });
|
569
|
+
if (!prev) return;
|
570
|
+
index = prev.index;
|
571
|
+
// Can only flip to a left page
|
572
|
+
// (downstream code handles index = -1, so this is ok I guess)
|
573
|
+
if (prev.pageSide == 'R') index--;
|
574
|
+
}
|
575
|
+
|
576
|
+
this.br.updateNavIndexThrottled(index);
|
577
|
+
|
578
|
+
const previousIndices = this.book.getSpreadIndices(index);
|
579
|
+
|
580
|
+
if (previousIndices[0] < this.br.firstDisplayableIndex() || previousIndices[1] < this.br.firstDisplayableIndex()) {
|
581
|
+
return;
|
582
|
+
}
|
583
|
+
|
584
|
+
this.br.animating = true;
|
585
|
+
|
586
|
+
if ('rl' != this.br.pageProgression) {
|
587
|
+
// Assume LTR and we are going backward
|
588
|
+
this.prepareFlipLeftToRight(previousIndices[0], previousIndices[1]);
|
589
|
+
this.flipLeftToRight(previousIndices[0], previousIndices[1]);
|
590
|
+
} else {
|
591
|
+
// RTL and going backward
|
592
|
+
this.prepareFlipRightToLeft(previousIndices[0], previousIndices[1]);
|
593
|
+
this.flipRightToLeft(previousIndices[0], previousIndices[1]);
|
594
|
+
}
|
595
|
+
}
|
596
|
+
|
597
|
+
/**
|
598
|
+
* Flips the page on the left towards the page on the right
|
599
|
+
* @param {number} newIndexL
|
600
|
+
* @param {number} newIndexR
|
601
|
+
*/
|
602
|
+
flipLeftToRight(newIndexL, newIndexR) {
|
603
|
+
this.br.refs.$brContainer.addClass("BRpageFlipping");
|
604
|
+
const leftLeaf = this.br.twoPage.currentIndexL;
|
605
|
+
|
606
|
+
const oldLeafEdgeWidthL = this.br.leafEdgeWidth(this.br.twoPage.currentIndexL);
|
607
|
+
const newLeafEdgeWidthL = this.br.leafEdgeWidth(newIndexL);
|
608
|
+
const leafEdgeTmpW = oldLeafEdgeWidthL - newLeafEdgeWidthL;
|
609
|
+
|
610
|
+
const currWidthL = this.getPageWidth(leftLeaf);
|
611
|
+
const newWidthL = this.getPageWidth(newIndexL);
|
612
|
+
const newWidthR = this.getPageWidth(newIndexR);
|
613
|
+
|
614
|
+
const top = this.top();
|
615
|
+
const gutter = this.br.twoPage.middle + this.gutterOffsetForIndex(newIndexL);
|
616
|
+
|
617
|
+
//animation strategy:
|
618
|
+
// 0. remove search highlight, if any.
|
619
|
+
// 1. create a new div, called leafEdgeTmp to represent the leaf edge between the leftmost edge
|
620
|
+
// of the left leaf and where the user clicked in the leaf edge.
|
621
|
+
// Note that if this function was triggered by left() and not a
|
622
|
+
// mouse click, the width of leafEdgeTmp is very small (zero px).
|
623
|
+
// 2. animate both leafEdgeTmp to the gutter (without changing its width) and animate
|
624
|
+
// leftLeaf to width=0.
|
625
|
+
// 3. When step 2 is finished, animate leafEdgeTmp to right-hand side of new right leaf
|
626
|
+
// (left=gutter+newWidthR) while also animating the new right leaf from width=0 to
|
627
|
+
// its new full width.
|
628
|
+
// 4. After step 3 is finished, do the following:
|
629
|
+
// - remove leafEdgeTmp from the dom.
|
630
|
+
// - resize and move the right leaf edge (leafEdgeR) to left=gutter+newWidthR
|
631
|
+
// and width=twoPage.edgeWidth-newLeafEdgeWidthL.
|
632
|
+
// - resize and move the left leaf edge (leafEdgeL) to left=gutter-newWidthL-newLeafEdgeWidthL
|
633
|
+
// and width=newLeafEdgeWidthL.
|
634
|
+
// - resize the back cover (twoPage.coverDiv) to left=gutter-newWidthL-newLeafEdgeWidthL-10
|
635
|
+
// and width=newWidthL+newWidthR+twoPage.edgeWidth+20
|
636
|
+
// - move new left leaf (newIndexL) forward to zindex=2 so it can receive clicks.
|
637
|
+
// - remove old left and right leafs from the dom [prunePageContainers()].
|
638
|
+
// - prefetch new adjacent leafs.
|
639
|
+
// - set up click handlers for both new left and right leafs.
|
640
|
+
// - redraw the search highlight.
|
641
|
+
// - update the pagenum box and the url.
|
642
|
+
|
643
|
+
const $twoPageViewEl = this.br.refs.$brTwoPageView;
|
644
|
+
const leftEdgeTmpLeft = gutter - currWidthL - leafEdgeTmpW;
|
645
|
+
|
646
|
+
this.br.leafEdgeTmp = document.createElement('div');
|
647
|
+
this.br.leafEdgeTmp.className = 'BRleafEdgeTmp';
|
648
|
+
$(this.br.leafEdgeTmp).css({
|
649
|
+
width: `${leafEdgeTmpW}px`,
|
650
|
+
height: `${this.br.twoPage.height}px`,
|
651
|
+
left: `${leftEdgeTmpLeft}px`,
|
652
|
+
top: `${top}px`,
|
653
|
+
zIndex: 1000,
|
654
|
+
}).appendTo($twoPageViewEl);
|
655
|
+
|
656
|
+
$(this.leafEdgeL).css({
|
657
|
+
width: `${newLeafEdgeWidthL}px`,
|
658
|
+
left: `${gutter - currWidthL - newLeafEdgeWidthL}px`
|
659
|
+
});
|
660
|
+
|
661
|
+
// Left gets the offset of the current left leaf from the document
|
662
|
+
const left = this.pageContainers[leftLeaf].$container.offset().left;
|
663
|
+
// $$$ This seems very similar to the gutter. May be able to consolidate the logic.
|
664
|
+
const right = `${$twoPageViewEl.prop('clientWidth') - left - this.pageContainers[leftLeaf].$container.width() + $twoPageViewEl.offset().left - 2}px`;
|
665
|
+
|
666
|
+
// We change the left leaf to right positioning
|
667
|
+
// $$$ This causes animation glitches during resize. See https://bugs.edge.launchpad.net/gnubook/+bug/328327
|
668
|
+
this.pageContainers[leftLeaf].$container.css({
|
669
|
+
right,
|
670
|
+
left: ''
|
671
|
+
});
|
672
|
+
|
673
|
+
$(this.br.leafEdgeTmp).animate({left: gutter}, this.br.flipSpeed, 'easeInSine');
|
674
|
+
|
675
|
+
this.pageContainers[leftLeaf].$container.animate({width: '0px'}, this.br.flipSpeed, 'easeInSine', () => {
|
676
|
+
|
677
|
+
$(this.br.leafEdgeTmp).animate({left: `${gutter + newWidthR}px`}, this.br.flipSpeed, 'easeOutSine');
|
678
|
+
|
679
|
+
this.br.$('.BRgutter').css({left: `${gutter - this.br.twoPage.bookSpineDivWidth * 0.5}px`});
|
680
|
+
|
681
|
+
this.pageContainers[newIndexR].$container.animate({width: `${newWidthR}px`}, this.br.flipSpeed, 'easeOutSine', () => {
|
682
|
+
this.pageContainers[newIndexL].$container.css('zIndex', 2);
|
683
|
+
|
684
|
+
$(this.leafEdgeR).css({
|
685
|
+
// Moves the right leaf edge
|
686
|
+
width: `${this.br.twoPage.edgeWidth - newLeafEdgeWidthL}px`,
|
687
|
+
left: `${gutter + newWidthR}px`
|
688
|
+
});
|
689
|
+
|
690
|
+
$(this.leafEdgeL).css({
|
691
|
+
// Moves and resizes the left leaf edge
|
692
|
+
width: `${newLeafEdgeWidthL}px`,
|
693
|
+
left: `${gutter - newWidthL - newLeafEdgeWidthL}px`
|
694
|
+
});
|
695
|
+
|
696
|
+
// Resizes the brown border div
|
697
|
+
$(this.br.twoPage.coverDiv).css({
|
698
|
+
width: `${this.coverWidth(newWidthL + newWidthR)}px`,
|
699
|
+
left: `${gutter - newWidthL - newLeafEdgeWidthL - this.br.twoPage.coverInternalPadding}px`
|
700
|
+
});
|
701
|
+
|
702
|
+
$(this.br.leafEdgeTmp).remove();
|
703
|
+
this.br.leafEdgeTmp = null;
|
704
|
+
|
705
|
+
// $$$ TODO refactor with opposite direction flip
|
706
|
+
|
707
|
+
this.br.twoPage.currentIndexL = newIndexL;
|
708
|
+
this.br.twoPage.currentIndexR = newIndexR;
|
709
|
+
this.br.twoPage.scaledWL = newWidthL;
|
710
|
+
this.br.twoPage.scaledWR = newWidthR;
|
711
|
+
this.br.twoPage.gutter = gutter;
|
712
|
+
|
713
|
+
this.br.updateFirstIndex(this.br.twoPage.currentIndexL);
|
714
|
+
this.br.displayedIndices = [newIndexL, newIndexR];
|
715
|
+
this.prunePageContainers();
|
716
|
+
this.br.animating = false;
|
717
|
+
|
718
|
+
this.resizeSpread();
|
719
|
+
|
720
|
+
if (this.br.animationFinishedCallback) {
|
721
|
+
this.br.animationFinishedCallback();
|
722
|
+
this.br.animationFinishedCallback = null;
|
723
|
+
}
|
724
|
+
|
725
|
+
this.br.refs.$brContainer.removeClass("BRpageFlipping");
|
726
|
+
this.br.textSelectionPlugin?.stopPageFlip(this.br.refs.$brContainer);
|
727
|
+
this.centerView();
|
728
|
+
this.br.trigger('pageChanged');
|
729
|
+
|
730
|
+
// get next previous batch immediately
|
731
|
+
this.prunePageContainers();
|
732
|
+
this.createPageContainer(newIndexL - 2);
|
733
|
+
this.createPageContainer(newIndexR - 2);
|
734
|
+
this.createPageContainer(newIndexL - 3);
|
735
|
+
this.createPageContainer(newIndexR - 3);
|
736
|
+
});
|
737
|
+
});
|
738
|
+
}
|
739
|
+
|
740
|
+
/**
|
741
|
+
* @param {PageIndex} index
|
742
|
+
*/
|
743
|
+
createPageContainer(index) {
|
744
|
+
if (!this.pageContainers[index]) {
|
745
|
+
this.pageContainers[index] = this.br._createPageContainer(index);
|
746
|
+
}
|
747
|
+
this.pageContainers[index].update({ reduce: this.br.reduce / this.scale });
|
748
|
+
return this.pageContainers[index];
|
749
|
+
}
|
750
|
+
|
751
|
+
/**
|
752
|
+
* Whether we flip left or right is dependent on the page progression
|
753
|
+
* to flip forward one spread, pass index=null
|
754
|
+
* @param {number} index
|
755
|
+
*/
|
756
|
+
flipFwdToIndex(index) {
|
757
|
+
if (this.br.animating) return;
|
758
|
+
|
759
|
+
if (null != this.br.leafEdgeTmp) {
|
760
|
+
alert('error: leafEdgeTmp should be null!');
|
761
|
+
return;
|
762
|
+
}
|
763
|
+
|
764
|
+
if (null == index) {
|
765
|
+
// Need to use the max here, since it could be a right to left book
|
766
|
+
const {currentIndexL, currentIndexR} = this.br.twoPage;
|
767
|
+
const maxDisplayedIndex = Math.max(currentIndexL, currentIndexR);
|
768
|
+
const nextPage = this.book.getPage(maxDisplayedIndex).findNext({ combineConsecutiveUnviewables: true });
|
769
|
+
if (!nextPage) return;
|
770
|
+
index = nextPage.index;
|
771
|
+
}
|
772
|
+
if (index > this.br.lastDisplayableIndex()) return;
|
773
|
+
|
774
|
+
this.br.updateNavIndexThrottled(index);
|
775
|
+
|
776
|
+
this.br.animating = true;
|
777
|
+
|
778
|
+
const nextIndices = this.book.getSpreadIndices(index);
|
779
|
+
|
780
|
+
if ('rl' != this.br.pageProgression) {
|
781
|
+
// We did not specify RTL
|
782
|
+
this.prepareFlipRightToLeft(nextIndices[0], nextIndices[1]);
|
783
|
+
this.flipRightToLeft(nextIndices[0], nextIndices[1]);
|
784
|
+
} else {
|
785
|
+
// RTL
|
786
|
+
this.prepareFlipLeftToRight(nextIndices[0], nextIndices[1]);
|
787
|
+
this.flipLeftToRight(nextIndices[0], nextIndices[1]);
|
788
|
+
}
|
789
|
+
}
|
790
|
+
|
791
|
+
/**
|
792
|
+
* Flip from left to right and show the nextL and nextR indices on those sides
|
793
|
+
* $$$ better not to have to pass gutter in
|
794
|
+
* @param {number} newIndexL
|
795
|
+
* @param {number} newIndexR
|
796
|
+
*/
|
797
|
+
flipRightToLeft(newIndexL, newIndexR) {
|
798
|
+
this.br.refs.$brContainer.addClass("BRpageFlipping");
|
799
|
+
|
800
|
+
const oldLeafEdgeWidthL = this.br.leafEdgeWidth(this.br.twoPage.currentIndexL);
|
801
|
+
const oldLeafEdgeWidthR = this.br.twoPage.edgeWidth - oldLeafEdgeWidthL;
|
802
|
+
const newLeafEdgeWidthL = this.br.leafEdgeWidth(newIndexL);
|
803
|
+
const newLeafEdgeWidthR = this.br.twoPage.edgeWidth - newLeafEdgeWidthL;
|
804
|
+
|
805
|
+
const leafEdgeTmpW = oldLeafEdgeWidthR - newLeafEdgeWidthR;
|
806
|
+
|
807
|
+
const top = this.top();
|
808
|
+
const scaledW = this.getPageWidth(this.br.twoPage.currentIndexR);
|
809
|
+
|
810
|
+
const middle = this.br.twoPage.middle;
|
811
|
+
const gutter = middle + this.gutterOffsetForIndex(newIndexL);
|
812
|
+
|
813
|
+
const $twoPageViewEl = this.br.refs.$brTwoPageView;
|
814
|
+
|
815
|
+
this.br.leafEdgeTmp = document.createElement('div');
|
816
|
+
this.br.leafEdgeTmp.className = 'BRleafEdgeTmp';
|
817
|
+
$(this.br.leafEdgeTmp).css({
|
818
|
+
width: `${leafEdgeTmpW}px`,
|
819
|
+
height: `${this.br.twoPage.height}px`,
|
820
|
+
left: `${gutter + scaledW}px`,
|
821
|
+
top: `${top}px`,
|
822
|
+
zIndex:1000
|
823
|
+
}).appendTo($twoPageViewEl);
|
824
|
+
|
825
|
+
const newWidthL = this.getPageWidth(newIndexL);
|
826
|
+
const newWidthR = this.getPageWidth(newIndexR);
|
827
|
+
|
828
|
+
$(this.leafEdgeR).css({width: `${newLeafEdgeWidthR}px`, left: `${gutter + newWidthR}px` });
|
829
|
+
const speed = this.br.flipSpeed;
|
830
|
+
|
831
|
+
$(this.br.leafEdgeTmp).animate({left: gutter}, speed, 'easeInSine');
|
832
|
+
this.pageContainers[this.br.twoPage.currentIndexR].$container.animate({width: '0px'}, speed, 'easeInSine', () => {
|
833
|
+
this.br.$('BRgutter').css({left: `${gutter - this.br.twoPage.bookSpineDivWidth * 0.5}px`});
|
834
|
+
$(this.br.leafEdgeTmp).animate({left: `${gutter - newWidthL - leafEdgeTmpW}px`}, speed, 'easeOutSine');
|
835
|
+
this.pageContainers[newIndexL].$container.animate({width: `${newWidthL}px`}, speed, 'easeOutSine', () => {
|
836
|
+
this.pageContainers[newIndexR].$container.css('zIndex', 2);
|
837
|
+
|
838
|
+
$(this.leafEdgeL).css({
|
839
|
+
width: `${newLeafEdgeWidthL}px`,
|
840
|
+
left: `${gutter - newWidthL - newLeafEdgeWidthL}px`
|
841
|
+
});
|
842
|
+
|
843
|
+
// Resizes the book cover
|
844
|
+
$(this.br.twoPage.coverDiv).css({
|
845
|
+
width: `${this.coverWidth(newWidthL + newWidthR)}px`,
|
846
|
+
left: `${gutter - newWidthL - newLeafEdgeWidthL - this.br.twoPage.coverInternalPadding}px`
|
847
|
+
});
|
848
|
+
|
849
|
+
$(this.br.leafEdgeTmp).remove();
|
850
|
+
this.br.leafEdgeTmp = null;
|
851
|
+
|
852
|
+
this.br.twoPage.currentIndexL = newIndexL;
|
853
|
+
this.br.twoPage.currentIndexR = newIndexR;
|
854
|
+
this.br.twoPage.scaledWL = newWidthL;
|
855
|
+
this.br.twoPage.scaledWR = newWidthR;
|
856
|
+
this.br.twoPage.gutter = gutter;
|
857
|
+
|
858
|
+
this.br.updateFirstIndex(this.br.twoPage.currentIndexL);
|
859
|
+
this.br.displayedIndices = [newIndexL, newIndexR];
|
860
|
+
this.prunePageContainers();
|
861
|
+
this.br.animating = false;
|
862
|
+
|
863
|
+
this.resizeSpread();
|
864
|
+
|
865
|
+
if (this.br.animationFinishedCallback) {
|
866
|
+
this.br.animationFinishedCallback();
|
867
|
+
this.br.animationFinishedCallback = null;
|
868
|
+
}
|
869
|
+
|
870
|
+
this.br.refs.$brContainer.removeClass("BRpageFlipping");
|
871
|
+
this.br.textSelectionPlugin?.stopPageFlip(this.br.refs.$brContainer);
|
872
|
+
this.centerView();
|
873
|
+
this.br.trigger('pageChanged');
|
874
|
+
|
875
|
+
this.prunePageContainers();
|
876
|
+
this.createPageContainer(newIndexL + 2);
|
877
|
+
this.createPageContainer(newIndexR + 2);
|
878
|
+
this.createPageContainer(newIndexL + 3);
|
879
|
+
this.createPageContainer(newIndexR + 3);
|
880
|
+
});
|
881
|
+
});
|
882
|
+
}
|
883
|
+
|
884
|
+
attachMouseHandlers() {
|
885
|
+
this.br.refs.$brTwoPageView
|
886
|
+
.off('mouseup').on('mouseup', ev => {
|
887
|
+
if (ev.which == 3) {
|
888
|
+
// right click
|
889
|
+
return !this.br.protected;
|
890
|
+
}
|
891
|
+
|
892
|
+
const $page = $(ev.target).closest('.BRpagecontainer');
|
893
|
+
if ($page.data('side') == 'L') this.br.left();
|
894
|
+
else if ($page.data('side') == 'R') this.br.right();
|
895
|
+
});
|
896
|
+
}
|
897
|
+
|
898
|
+
/**
|
899
|
+
* Prepare to flip the left page towards the right. This corresponds to moving
|
900
|
+
* backward when the page progression is left to right.
|
901
|
+
* @param {number} prevL
|
902
|
+
* @param {number} prevR
|
903
|
+
*/
|
904
|
+
prepareFlipLeftToRight(prevL, prevR) {
|
905
|
+
this.createPageContainer(prevL, true);
|
906
|
+
this.createPageContainer(prevR, true);
|
907
|
+
|
908
|
+
const $twoPageViewEl = this.br.refs.$brTwoPageView;
|
909
|
+
const height = this.book._getPageHeight(prevL);
|
910
|
+
const width = this.book._getPageWidth(prevL);
|
911
|
+
const middle = this.br.twoPage.middle;
|
912
|
+
const top = this.top();
|
913
|
+
const scaledW = this.br.twoPage.height * width / height; // $$$ assumes height of page is dominant
|
914
|
+
|
915
|
+
// The gutter is the dividing line between the left and right pages.
|
916
|
+
// It is offset from the middle to create the illusion of thickness to the pages
|
917
|
+
const gutter = middle + this.gutterOffsetForIndex(prevL);
|
918
|
+
|
919
|
+
const leftCSS = {
|
920
|
+
left: `${gutter - scaledW}px`,
|
921
|
+
right: '', // clear right property
|
922
|
+
top: `${top}px`,
|
923
|
+
height: this.br.twoPage.height,
|
924
|
+
width: `${scaledW}px`,
|
925
|
+
zIndex: 1
|
926
|
+
};
|
927
|
+
|
928
|
+
this.pageContainers[prevL].$container
|
929
|
+
.css(leftCSS)
|
930
|
+
.appendTo($twoPageViewEl);
|
931
|
+
|
932
|
+
const rightCSS = {
|
933
|
+
left: `${gutter}px`,
|
934
|
+
right: '',
|
935
|
+
top: `${top}px`,
|
936
|
+
height: this.br.twoPage.height,
|
937
|
+
width: '0',
|
938
|
+
zIndex: 2
|
939
|
+
};
|
940
|
+
|
941
|
+
this.pageContainers[prevR].$container
|
942
|
+
.css(rightCSS)
|
943
|
+
.appendTo($twoPageViewEl);
|
944
|
+
}
|
945
|
+
|
946
|
+
/**
|
947
|
+
* // $$$ mang we're adding an extra pixel in the middle. See https://bugs.edge.launchpad.net/gnubook/+bug/411667
|
948
|
+
*/
|
949
|
+
prepareFlipRightToLeft(nextL, nextR) {
|
950
|
+
this.createPageContainer(nextL, true);
|
951
|
+
this.createPageContainer(nextR, true);
|
952
|
+
|
953
|
+
const $twoPageViewEl = this.br.refs.$brTwoPageView;
|
954
|
+
let height = this.book._getPageHeight(nextR);
|
955
|
+
let width = this.book._getPageWidth(nextR);
|
956
|
+
const middle = this.br.twoPage.middle;
|
957
|
+
const top = this.top();
|
958
|
+
let scaledW = this.br.twoPage.height * width / height;
|
959
|
+
|
960
|
+
const gutter = middle + this.gutterOffsetForIndex(nextL);
|
961
|
+
|
962
|
+
$(this.pageContainers[nextR].$container).css({
|
963
|
+
left: `${gutter}px`,
|
964
|
+
top: `${top}px`,
|
965
|
+
height: this.br.twoPage.height,
|
966
|
+
width: `${scaledW}px`,
|
967
|
+
zIndex: 1,
|
968
|
+
})
|
969
|
+
.appendTo($twoPageViewEl);
|
970
|
+
|
971
|
+
height = this.book._getPageHeight(nextL);
|
972
|
+
width = this.book._getPageWidth(nextL);
|
973
|
+
scaledW = this.br.twoPage.height * width / height;
|
974
|
+
|
975
|
+
$(this.pageContainers[nextL].$container).css({
|
976
|
+
right: `${$twoPageViewEl.prop('clientWidth') - gutter}px`,
|
977
|
+
top: `${top}px`,
|
978
|
+
height: this.br.twoPage.height,
|
979
|
+
width: '0px', // Start at 0 width, then grow to the left
|
980
|
+
zIndex: 2,
|
981
|
+
})
|
982
|
+
.appendTo($twoPageViewEl);
|
983
|
+
}
|
984
|
+
|
985
|
+
getPageWidth(index) {
|
986
|
+
// We return the width based on the dominant height
|
987
|
+
const height = this.book._getPageHeight(index);
|
988
|
+
const width = this.book._getPageWidth(index);
|
989
|
+
// $$$ we assume width is relative to current spread
|
990
|
+
return Math.floor(this.br.twoPage.height * width / height);
|
991
|
+
}
|
992
|
+
|
993
|
+
/**
|
994
|
+
* Returns the position of the gutter (line between the page images)
|
995
|
+
*/
|
996
|
+
gutter() {
|
997
|
+
return this.br.twoPage.middle + this.gutterOffsetForIndex(this.br.twoPage.currentIndexL);
|
998
|
+
}
|
999
|
+
|
1000
|
+
/**
|
1001
|
+
* Returns the offset for the top of the page images
|
1002
|
+
*/
|
1003
|
+
top() {
|
1004
|
+
return this.br.twoPage.coverExternalPadding + this.br.twoPage.coverInternalPadding; // $$$ + border?
|
1005
|
+
}
|
1006
|
+
|
1007
|
+
/**
|
1008
|
+
* Returns the width of the cover div given the total page width
|
1009
|
+
* @param {number} totalPageWidth
|
1010
|
+
* @return {number}
|
1011
|
+
*/
|
1012
|
+
coverWidth(totalPageWidth) {
|
1013
|
+
return totalPageWidth + this.br.twoPage.edgeWidth + 2 * this.br.twoPage.coverInternalPadding;
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
/**
|
1017
|
+
* Returns the percentage offset into twopageview div at the center of container div
|
1018
|
+
*/
|
1019
|
+
getViewCenter() {
|
1020
|
+
const { $brContainer, $brTwoPageView } = this.br.refs;
|
1021
|
+
const center = {};
|
1022
|
+
|
1023
|
+
const containerOffset = $brContainer.offset();
|
1024
|
+
const viewOffset = $brTwoPageView.offset();
|
1025
|
+
center.percentageX = (containerOffset.left - viewOffset.left + ($brContainer.prop('clientWidth') >> 1)) / this.br.twoPage.totalWidth;
|
1026
|
+
center.percentageY = (containerOffset.top - viewOffset.top + ($brContainer.prop('clientHeight') >> 1)) / this.br.twoPage.totalHeight;
|
1027
|
+
|
1028
|
+
return center;
|
1029
|
+
}
|
1030
|
+
|
1031
|
+
/**
|
1032
|
+
* Centers the point given by percentage from left,top of twopageview
|
1033
|
+
* @param {number} [percentageX=0.5]
|
1034
|
+
* @param {number} [percentageY=0.5]
|
1035
|
+
*/
|
1036
|
+
centerView(percentageX, percentageY) {
|
1037
|
+
|
1038
|
+
if ('undefined' == typeof(percentageX)) {
|
1039
|
+
percentageX = 0.5;
|
1040
|
+
}
|
1041
|
+
if ('undefined' == typeof(percentageY)) {
|
1042
|
+
percentageY = 0.5;
|
1043
|
+
}
|
1044
|
+
|
1045
|
+
const viewWidth = this.br.refs.$brTwoPageView.width();
|
1046
|
+
const containerClientWidth = this.br.refs.$brContainer.prop('clientWidth');
|
1047
|
+
const intoViewX = percentageX * viewWidth;
|
1048
|
+
|
1049
|
+
const viewHeight = this.br.refs.$brTwoPageView.height();
|
1050
|
+
const containerClientHeight = this.br.refs.$brContainer.prop('clientHeight');
|
1051
|
+
const intoViewY = percentageY * viewHeight;
|
1052
|
+
|
1053
|
+
if (viewWidth < containerClientWidth) {
|
1054
|
+
// Can fit width without scrollbars - center by adjusting offset
|
1055
|
+
this.br.refs.$brTwoPageView.css('left', `${(containerClientWidth >> 1) - intoViewX}px`);
|
1056
|
+
} else {
|
1057
|
+
// Need to scroll to center
|
1058
|
+
this.br.refs.$brTwoPageView.css('left', 0);
|
1059
|
+
this.br.refs.$brContainer.scrollLeft(intoViewX - (containerClientWidth >> 1));
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
if (viewHeight < containerClientHeight) {
|
1063
|
+
// Fits with scrollbars - add offset
|
1064
|
+
this.br.refs.$brTwoPageView.css('top', `${(containerClientHeight >> 1) - intoViewY}px`);
|
1065
|
+
} else {
|
1066
|
+
this.br.refs.$brTwoPageView.css('top', 0);
|
1067
|
+
this.br.refs.$brContainer.scrollTop(intoViewY - (containerClientHeight >> 1));
|
1068
|
+
}
|
1069
|
+
}
|
1070
|
+
|
1071
|
+
/**
|
1072
|
+
* Returns the integer height of the click-to-flip areas at the edges of the book
|
1073
|
+
* @return {number}
|
1074
|
+
*/
|
1075
|
+
flipAreaHeight() {
|
1076
|
+
return Math.floor(this.br.twoPage.height);
|
1077
|
+
}
|
1078
|
+
|
1079
|
+
/**
|
1080
|
+
* Returns the the integer width of the flip areas
|
1081
|
+
* @return {number}
|
1082
|
+
*/
|
1083
|
+
flipAreaWidth() {
|
1084
|
+
const max = 100; // $$$ TODO base on view width?
|
1085
|
+
const min = 10;
|
1086
|
+
|
1087
|
+
const width = this.br.twoPage.width * 0.15;
|
1088
|
+
return Math.floor(clamp(width, min, max));
|
1089
|
+
}
|
1090
|
+
|
1091
|
+
/**
|
1092
|
+
* Returns integer top offset for flip areas
|
1093
|
+
* @return {number}
|
1094
|
+
*/
|
1095
|
+
flipAreaTop() {
|
1096
|
+
return Math.floor(this.br.twoPage.bookCoverDivTop + this.br.twoPage.coverInternalPadding);
|
1097
|
+
}
|
1098
|
+
|
1099
|
+
/**
|
1100
|
+
* Left offset for left flip area
|
1101
|
+
* @return {number}
|
1102
|
+
*/
|
1103
|
+
leftFlipAreaLeft() {
|
1104
|
+
return Math.floor(this.br.twoPage.gutter - this.br.twoPage.scaledWL);
|
1105
|
+
}
|
1106
|
+
|
1107
|
+
/**
|
1108
|
+
* Left offset for right flip area
|
1109
|
+
* @return {number}
|
1110
|
+
*/
|
1111
|
+
rightFlipAreaLeft() {
|
1112
|
+
return Math.floor(this.br.twoPage.gutter + this.br.twoPage.scaledWR - this.flipAreaWidth());
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
/**
|
1116
|
+
* Position calculation shared between search and text-to-speech functions
|
1117
|
+
*/
|
1118
|
+
setHilightCss(div, index, left, right, top, bottom) {
|
1119
|
+
// We calculate the reduction factor for the specific page because it can be different
|
1120
|
+
// for each page in the spread
|
1121
|
+
const height = this.book._getPageHeight(index);
|
1122
|
+
const width = this.book._getPageWidth(index);
|
1123
|
+
const reduce = this.br.twoPage.height / height;
|
1124
|
+
const scaledW = Math.floor(width * reduce);
|
1125
|
+
|
1126
|
+
const gutter = this.gutter();
|
1127
|
+
let pageL;
|
1128
|
+
if ('L' == this.book.getPageSide(index)) {
|
1129
|
+
pageL = gutter - scaledW;
|
1130
|
+
} else {
|
1131
|
+
pageL = gutter;
|
1132
|
+
}
|
1133
|
+
const pageT = this.top();
|
1134
|
+
|
1135
|
+
$(div).css({
|
1136
|
+
width: `${(right - left) * reduce}px`,
|
1137
|
+
height: `${(bottom - top) * reduce}px`,
|
1138
|
+
left: `${pageL + left * reduce}px`,
|
1139
|
+
top: `${pageT + top * reduce}px`
|
1140
|
+
});
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
/**
|
1144
|
+
* Returns the gutter offset for the spread containing the given index.
|
1145
|
+
* This function supports RTL
|
1146
|
+
* @param {number} pindex
|
1147
|
+
* @return {number}
|
1148
|
+
*/
|
1149
|
+
gutterOffsetForIndex(pindex) {
|
1150
|
+
// To find the offset of the gutter from the middle we calculate our percentage distance
|
1151
|
+
// through the book (0..1), remap to (-0.5..0.5) and multiply by the total page edge width
|
1152
|
+
let offset = Math.floor(((pindex / this.book.getNumLeafs()) - 0.5) * this.br.twoPage.edgeWidth);
|
1153
|
+
|
1154
|
+
// But then again for RTL it's the opposite
|
1155
|
+
if ('rl' == this.br.pageProgression) {
|
1156
|
+
offset *= -1;
|
1157
|
+
}
|
1158
|
+
|
1159
|
+
return offset;
|
1160
|
+
}
|
1161
|
+
|
1162
|
+
/**
|
1163
|
+
* Returns the width of the leaf edge div for the page with index given
|
1164
|
+
* @param {number} pindex
|
1165
|
+
* @return {number}
|
1166
|
+
*/
|
1167
|
+
leafEdgeWidth(pindex) {
|
1168
|
+
// $$$ could there be single pixel rounding errors for L vs R?
|
1169
|
+
if ((this.book.getPageSide(pindex) == 'L') && (this.br.pageProgression != 'rl')) {
|
1170
|
+
return Math.floor( (pindex / this.book.getNumLeafs()) * this.br.twoPage.edgeWidth + 0.5);
|
1171
|
+
} else {
|
1172
|
+
return Math.floor( (1 - pindex / this.book.getNumLeafs()) * this.br.twoPage.edgeWidth + 0.5);
|
1173
|
+
}
|
1174
|
+
}
|
1175
|
+
|
1176
|
+
/**
|
1177
|
+
* Returns the target jump leaf given a page coordinate (inside the left page edge div)
|
1178
|
+
* @param {number} pageX
|
1179
|
+
* @return {PageIndex}
|
1180
|
+
*/
|
1181
|
+
jumpIndexForLeftEdgePageX(pageX) {
|
1182
|
+
let jumpIndex;
|
1183
|
+
if ('rl' != this.br.pageProgression) {
|
1184
|
+
// LTR - flipping backward
|
1185
|
+
jumpIndex = this.br.twoPage.currentIndexL - ($(this.leafEdgeL).offset().left + $(this.leafEdgeL).width() - pageX) * 10;
|
1186
|
+
|
1187
|
+
// browser may have resized the div due to font size change -- see https://bugs.launchpad.net/gnubook/+bug/333570
|
1188
|
+
jumpIndex = clamp(Math.round(jumpIndex), this.br.firstDisplayableIndex(), this.br.twoPage.currentIndexL - 2);
|
1189
|
+
return jumpIndex;
|
1190
|
+
|
1191
|
+
} else {
|
1192
|
+
jumpIndex = this.br.twoPage.currentIndexL + ($(this.leafEdgeL).offset().left + $(this.leafEdgeL).width() - pageX) * 10;
|
1193
|
+
jumpIndex = clamp(Math.round(jumpIndex), this.br.twoPage.currentIndexL + 2, this.br.lastDisplayableIndex());
|
1194
|
+
return jumpIndex;
|
1195
|
+
}
|
1196
|
+
}
|
1197
|
+
|
1198
|
+
/**
|
1199
|
+
* Returns the target jump leaf given a page coordinate (inside the right page edge div)
|
1200
|
+
* @param {number} pageX
|
1201
|
+
* @return {PageIndex}
|
1202
|
+
*/
|
1203
|
+
jumpIndexForRightEdgePageX(pageX) {
|
1204
|
+
let jumpIndex;
|
1205
|
+
if ('rl' != this.br.pageProgression) {
|
1206
|
+
// LTR
|
1207
|
+
jumpIndex = this.br.twoPage.currentIndexL + (pageX - $(this.leafEdgeR).offset().left) * 10;
|
1208
|
+
jumpIndex = clamp(Math.round(jumpIndex), this.br.twoPage.currentIndexL + 2, this.br.lastDisplayableIndex());
|
1209
|
+
return jumpIndex;
|
1210
|
+
} else {
|
1211
|
+
jumpIndex = this.br.twoPage.currentIndexL - (pageX - $(this.leafEdgeR).offset().left) * 10;
|
1212
|
+
jumpIndex = clamp(Math.round(jumpIndex), this.br.firstDisplayableIndex(), this.br.twoPage.currentIndexL - 2);
|
1213
|
+
return jumpIndex;
|
1214
|
+
}
|
1215
|
+
}
|
1216
|
+
|
1217
|
+
/**
|
1218
|
+
* Fetches the currently displayed images (if not already fetching)
|
1219
|
+
* as wells as any nearby pages.
|
1220
|
+
*/
|
1221
|
+
prefetch() {
|
1222
|
+
// $$$ We should check here if the current indices have finished
|
1223
|
+
// loading (with some timeout) before loading more page images
|
1224
|
+
// See https://bugs.edge.launchpad.net/bookreader/+bug/511391
|
1225
|
+
const { max, min } = Math;
|
1226
|
+
const { book } = this;
|
1227
|
+
const { currentIndexL, currentIndexR } = this.br.twoPage;
|
1228
|
+
const ADJACENT_PAGES_TO_LOAD = 2;
|
1229
|
+
// currentIndexL can be -1; getPage returns the last page of the book
|
1230
|
+
// when given -1, so need to prevent that.
|
1231
|
+
let lowPage = book.getPage(max(0, min(currentIndexL, currentIndexR)));
|
1232
|
+
let highPage = book.getPage(max(currentIndexL, currentIndexR));
|
1233
|
+
|
1234
|
+
for (let i = 0; i < ADJACENT_PAGES_TO_LOAD + 2; i++) {
|
1235
|
+
if (lowPage) {
|
1236
|
+
this.createPageContainer(lowPage.index);
|
1237
|
+
lowPage = lowPage.findPrev({ combineConsecutiveUnviewables: true });
|
1238
|
+
}
|
1239
|
+
|
1240
|
+
if (highPage) {
|
1241
|
+
this.createPageContainer(highPage.index);
|
1242
|
+
highPage = highPage.findNext({ combineConsecutiveUnviewables: true });
|
1243
|
+
}
|
1244
|
+
}
|
1245
|
+
}
|
1246
|
+
|
1247
|
+
/* 2up Container Sizes */
|
1248
|
+
|
1249
|
+
/** main positions for inner containers */
|
1250
|
+
get baseLeafCss() {
|
1251
|
+
return {
|
1252
|
+
position: 'absolute',
|
1253
|
+
right: '',
|
1254
|
+
top: `${this.top()}px`,
|
1255
|
+
zIndex: 2,
|
1256
|
+
};
|
1257
|
+
}
|
1258
|
+
|
1259
|
+
/** main height for inner containers */
|
1260
|
+
get heightCss() {
|
1261
|
+
return {
|
1262
|
+
height: `${this.br.twoPage.height}px`, // $$$ height forced the same for both pages
|
1263
|
+
};
|
1264
|
+
}
|
1265
|
+
|
1266
|
+
/** Left Page sizing */
|
1267
|
+
get leftLeafCss() {
|
1268
|
+
return {
|
1269
|
+
...this.baseLeafCss,
|
1270
|
+
...this.heightCss,
|
1271
|
+
left: `${this.br.twoPage.gutter - this.br.twoPage.scaledWL}px`,
|
1272
|
+
width: `${this.br.twoPage.scaledWL}px`,
|
1273
|
+
};
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
/** Left side book thickness */
|
1277
|
+
get leafEdgeLCss() {
|
1278
|
+
return {
|
1279
|
+
...this.heightCss,
|
1280
|
+
width: `${this.br.twoPage.leafEdgeWidthL}px`,
|
1281
|
+
left: `${this.br.twoPage.bookCoverDivLeft + this.br.twoPage.coverInternalPadding}px`,
|
1282
|
+
top: `${this.br.twoPage.bookCoverDivTop + this.br.twoPage.coverInternalPadding}px`,
|
1283
|
+
border: this.br.twoPage.leafEdgeWidthL === 0 ? 'none' : null
|
1284
|
+
};
|
1285
|
+
}
|
1286
|
+
|
1287
|
+
/** Right Page sizing */
|
1288
|
+
get rightLeafCss() {
|
1289
|
+
return {
|
1290
|
+
...this.baseLeafCss,
|
1291
|
+
...this.heightCss,
|
1292
|
+
left: `${this.br.twoPage.gutter}px`,
|
1293
|
+
width: `${this.br.twoPage.scaledWR}px`,
|
1294
|
+
};
|
1295
|
+
}
|
1296
|
+
|
1297
|
+
/** Right side book thickness */
|
1298
|
+
get leafEdgeRCss() {
|
1299
|
+
return {
|
1300
|
+
...this.heightCss,
|
1301
|
+
width: `${this.br.twoPage.leafEdgeWidthR}px`,
|
1302
|
+
left: `${this.br.twoPage.scaledWL + this.br.twoPage.scaledWR + this.br.twoPage.leafEdgeWidthL}px`,
|
1303
|
+
top: `${this.br.twoPage.bookCoverDivTop + this.br.twoPage.coverInternalPadding}px`,
|
1304
|
+
border: this.br.twoPage.leafEdgeWidthR === 0 ? 'none' : null
|
1305
|
+
};
|
1306
|
+
}
|
1307
|
+
|
1308
|
+
/** main container sizing */
|
1309
|
+
get mainContainerCss() {
|
1310
|
+
return {
|
1311
|
+
height: `${this.br.twoPage.totalHeight}px`,
|
1312
|
+
width: `${this.br.twoPage.totalWidth}px`,
|
1313
|
+
position: 'absolute'
|
1314
|
+
};
|
1315
|
+
}
|
1316
|
+
|
1317
|
+
/** book cover sizing */
|
1318
|
+
get spreadCoverCss() {
|
1319
|
+
return {
|
1320
|
+
width: `${this.br.twoPage.bookCoverDivWidth}px`,
|
1321
|
+
height: `${this.br.twoPage.bookCoverDivHeight}px`,
|
1322
|
+
visibility: 'visible'
|
1323
|
+
};
|
1324
|
+
}
|
1325
|
+
|
1326
|
+
/** book spine sizing */
|
1327
|
+
get spineCss() {
|
1328
|
+
return {
|
1329
|
+
width: `${this.br.twoPage.bookSpineDivWidth}px`,
|
1330
|
+
height: `${this.br.twoPage.bookSpineDivHeight}px`,
|
1331
|
+
left: `${this.br.twoPage.gutter - (this.br.twoPage.bookSpineDivWidth / 2)}px`,
|
1332
|
+
top: `${this.br.twoPage.bookSpineDivTop}px`
|
1333
|
+
};
|
1334
|
+
}
|
1335
|
+
/** end CSS */
|
1336
|
+
}
|
1337
|
+
|
1338
|
+
/**
|
1339
|
+
* @implements {BookReaderOptions["twoPage"]}
|
1340
|
+
* @typedef {object} TwoPageState
|
1341
|
+
* @property {number} coverInternalPadding
|
1342
|
+
* @property {number} coverExternalPadding
|
1343
|
+
*
|
1344
|
+
* @property {import('./options.js').AutoFitValues} autofit
|
1345
|
+
* @property {number} width
|
1346
|
+
* @property {number} height
|
1347
|
+
* @property {number} currentIndexL
|
1348
|
+
* @property {number} currentIndexR
|
1349
|
+
* @property {number} scaledWL
|
1350
|
+
* @property {number} scaledWR
|
1351
|
+
* @property {number} gutter
|
1352
|
+
* @property {Array<{reduce: number, autofit: import('./options.js').AutoFitValues}>} reductionFactors
|
1353
|
+
* @property {number} totalHeight
|
1354
|
+
* @property {number} totalWidth
|
1355
|
+
*
|
1356
|
+
* @property {HTMLDivElement} coverDiv
|
1357
|
+
* @property {number} bookCoverDivTop
|
1358
|
+
* @property {number} bookCoverDivLeft
|
1359
|
+
* @property {number} bookCoverDivWidth
|
1360
|
+
* @property {number} bookCoverDivHeight
|
1361
|
+
*
|
1362
|
+
* @property {number} leafEdgeWidthL
|
1363
|
+
* @property {number} leafEdgeWidthR
|
1364
|
+
*
|
1365
|
+
* @property {number} bookSpineDivTop
|
1366
|
+
* @property {number} bookSpineDivLeft
|
1367
|
+
* @property {number} bookSpineDivWidth
|
1368
|
+
* @property {number} bookSpineDivHeight
|
1369
|
+
*
|
1370
|
+
* @property {number} edgeWidth
|
1371
|
+
* @property {number} middle
|
1372
|
+
*/
|