@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,287 @@
|
|
1
|
+
/* global BookReader */
|
2
|
+
/**
|
3
|
+
* Adds mobile navigation at responsive breakpoint
|
4
|
+
*/
|
5
|
+
|
6
|
+
import * as utils from '../BookReader/utils.js';
|
7
|
+
import 'jquery.mmenu/dist/js/jquery.mmenu.min.js';
|
8
|
+
import 'jquery.mmenu/dist/addons/navbars/jquery.mmenu.navbars.min.js';
|
9
|
+
|
10
|
+
//contains all filters and labels for checkboxs
|
11
|
+
const FILTERLIST = [
|
12
|
+
{
|
13
|
+
filter: "grayscale(100%)",
|
14
|
+
label: "Grayscale"
|
15
|
+
},
|
16
|
+
{
|
17
|
+
filter: "brightness(120%)",
|
18
|
+
label: "High brightness"
|
19
|
+
},
|
20
|
+
{
|
21
|
+
filter: "invert(100%)",
|
22
|
+
label: "Inverted (dark mode)"
|
23
|
+
},
|
24
|
+
{
|
25
|
+
filter: "contrast(120%)",
|
26
|
+
label: "High contrast"
|
27
|
+
},
|
28
|
+
];
|
29
|
+
|
30
|
+
jQuery.extend(BookReader.defaultOptions, {
|
31
|
+
enableMobileNav: true,
|
32
|
+
mobileNavTitle: 'Internet Archive',
|
33
|
+
mobileNavFullscreenOnly: false,
|
34
|
+
});
|
35
|
+
|
36
|
+
BookReader.prototype.setup = (function(super_) {
|
37
|
+
return function (options) {
|
38
|
+
super_.call(this, options);
|
39
|
+
|
40
|
+
this.enableMobileNav = options.enableMobileNav;
|
41
|
+
this.mobileNavTitle = options.mobileNavTitle;
|
42
|
+
this.mobileNavFullscreenOnly = options.mobileNavFullscreenOnly;
|
43
|
+
|
44
|
+
this.refs.$mmenu = null;
|
45
|
+
};
|
46
|
+
})(BookReader.prototype.setup);
|
47
|
+
|
48
|
+
|
49
|
+
// Extend initToolbar
|
50
|
+
BookReader.prototype.initToolbar = (function (super_) {
|
51
|
+
return function (mode, ui) {
|
52
|
+
let $mmenuEl;
|
53
|
+
if (this.enableMobileNav) {
|
54
|
+
const $drawerEl = this.buildMobileDrawerElement();
|
55
|
+
this.refs.$br.append($drawerEl);
|
56
|
+
|
57
|
+
// Render info into mobile info before mmenu
|
58
|
+
this.buildInfoDiv(this.$('.BRmobileInfo'));
|
59
|
+
this.buildShareDiv(this.$('.BRmobileShare'));
|
60
|
+
|
61
|
+
$mmenuEl = $drawerEl;
|
62
|
+
$mmenuEl.mmenu({
|
63
|
+
navbars: [
|
64
|
+
{ "position": "top" },
|
65
|
+
],
|
66
|
+
navbar: {
|
67
|
+
add: true,
|
68
|
+
title: this.mobileNavTitle,
|
69
|
+
titleLink: 'panel'
|
70
|
+
},
|
71
|
+
extensions: [ "panelshadow" ],
|
72
|
+
}, {
|
73
|
+
offCanvas: {
|
74
|
+
wrapPageIfNeeded: false,
|
75
|
+
zposition: 'next',
|
76
|
+
pageSelector: this.el,
|
77
|
+
}
|
78
|
+
});
|
79
|
+
|
80
|
+
const $BRpageviewField = $mmenuEl.find('.BRpageviewValue');
|
81
|
+
$mmenuEl.data('mmenu').bind('opened', () => {
|
82
|
+
// Update "Link to this page view" link
|
83
|
+
if ($BRpageviewField.length) {
|
84
|
+
$BRpageviewField.val(window.location.href);
|
85
|
+
}
|
86
|
+
});
|
87
|
+
|
88
|
+
//apply filters when checkboxs clicked
|
89
|
+
$drawerEl.find('.BRcheckbox-filters').click(() => applyFilters($drawerEl, this));
|
90
|
+
|
91
|
+
// Bind mobile switch buttons
|
92
|
+
$drawerEl.find('.DrawerLayoutButton.one_page_mode').click(
|
93
|
+
() => this.switchMode(this.constMode1up));
|
94
|
+
$drawerEl.find('.DrawerLayoutButton.two_page_mode').click(
|
95
|
+
() => this.switchMode(this.constMode2up));
|
96
|
+
$drawerEl.find('.DrawerLayoutButton.thumbnail_mode').click(
|
97
|
+
() => this.switchMode(this.constModeThumb));
|
98
|
+
|
99
|
+
if (this.mobileNavFullscreenOnly) {
|
100
|
+
$(document.body).addClass('BRbodyMobileNavEnabledFullscreen');
|
101
|
+
} else {
|
102
|
+
$(document.body).addClass('BRbodyMobileNavEnabled');
|
103
|
+
}
|
104
|
+
|
105
|
+
this.refs.$mmenu = $mmenuEl;
|
106
|
+
|
107
|
+
}
|
108
|
+
|
109
|
+
// Call the parent method at the end, because it binds events to DOM
|
110
|
+
super_.apply(this, arguments);
|
111
|
+
|
112
|
+
|
113
|
+
if (this.enableMobileNav) {
|
114
|
+
// Need to bind more, console after toolbar is initialized
|
115
|
+
this.$('.BRmobileHamburger').click(() => {
|
116
|
+
if ($mmenuEl.data('mmenu').getInstance().vars.opened) {
|
117
|
+
$mmenuEl.data('mmenu').close();
|
118
|
+
} else {
|
119
|
+
$mmenuEl.data('mmenu').open();
|
120
|
+
this.trigger("mobileNavOpen");
|
121
|
+
}
|
122
|
+
});
|
123
|
+
|
124
|
+
|
125
|
+
const closeMobileMenu = (e) => {
|
126
|
+
// Need to close the mobile menu to reset DOM & Style
|
127
|
+
// driven by menu plugin
|
128
|
+
const width = $( window ).width();
|
129
|
+
const mobileMenuIsOpen = $mmenuEl.data('mmenu').getInstance().vars.opened;
|
130
|
+
// $brBreakPointMobile: 800px;
|
131
|
+
if (mobileMenuIsOpen && (width >= 800)) {
|
132
|
+
$mmenuEl.data('mmenu').close ();
|
133
|
+
}
|
134
|
+
};
|
135
|
+
|
136
|
+
window.addEventListener('resize', utils.debounce(closeMobileMenu, 900));
|
137
|
+
}
|
138
|
+
};
|
139
|
+
})(BookReader.prototype.initToolbar);
|
140
|
+
|
141
|
+
|
142
|
+
BookReader.prototype.buildToolbarElement = (function (super_) {
|
143
|
+
return function () {
|
144
|
+
const $el = super_.call(this);
|
145
|
+
if (this.enableMobileNav) {
|
146
|
+
const escapedTitle = BookReader.util.escapeHTML(this.bookTitle);
|
147
|
+
const toolbar = `
|
148
|
+
<span class="BRmobileHamburgerWrapper">
|
149
|
+
<button class="BRmobileHamburger"></button>
|
150
|
+
<span class="BRtoolbarMobileTitle" title="${escapedTitle}">${escapedTitle}</span>
|
151
|
+
</span>
|
152
|
+
`;
|
153
|
+
$el
|
154
|
+
.addClass('responsive')
|
155
|
+
.prepend($(toolbar));
|
156
|
+
}
|
157
|
+
return $el;
|
158
|
+
};
|
159
|
+
})(BookReader.prototype.buildToolbarElement);
|
160
|
+
|
161
|
+
/**
|
162
|
+
* This method builds the html for the mobile drawer. It can be decorated to
|
163
|
+
* extend the default drawer.
|
164
|
+
* @return {jqueryElement}
|
165
|
+
*/
|
166
|
+
BookReader.prototype.buildMobileDrawerElement = function() {
|
167
|
+
let experimentalHtml = '';
|
168
|
+
//builds filters checkbox html
|
169
|
+
if (this.enableExperimentalControls) {
|
170
|
+
experimentalHtml = `
|
171
|
+
<p class="DrawerSettingsTitle">Visual Adjustment</p>
|
172
|
+
<div class="BRcheckbox-group-filters">
|
173
|
+
`;
|
174
|
+
FILTERLIST.forEach( (el, i) => {
|
175
|
+
const checkboxHtml = `
|
176
|
+
<input type="checkbox" class="BRcheckbox-filters" id="filter${i}">
|
177
|
+
<label for="filter${i}" class="BRcheckbox-label-filters">${el.label}</label><br>
|
178
|
+
|
179
|
+
`;
|
180
|
+
experimentalHtml = experimentalHtml.concat(checkboxHtml);
|
181
|
+
});
|
182
|
+
experimentalHtml = experimentalHtml.concat("</div>");
|
183
|
+
}
|
184
|
+
|
185
|
+
|
186
|
+
const settingsSection = `
|
187
|
+
<span>
|
188
|
+
<span class="DrawerIconWrapper">
|
189
|
+
<img class="DrawerIcon" src="${`${this.imagesBaseURL}icon_gear.svg`}" alt="settings-icon"/>
|
190
|
+
</span>
|
191
|
+
Settings
|
192
|
+
</span>
|
193
|
+
<div class=DrawerSettingsWrapper>
|
194
|
+
<div class="DrawerSettingsLayoutWrapper">
|
195
|
+
<button class="DrawerLayoutButton one_page_mode">
|
196
|
+
<img src="${this.imagesBaseURL}icon_one_page.svg" alt="Single Page"/>
|
197
|
+
<br>
|
198
|
+
One Page
|
199
|
+
</button>
|
200
|
+
<button class="DrawerLayoutButton two_page_mode TwoPagesButton">
|
201
|
+
<img src="${this.imagesBaseURL}icon_two_pages.svg" alt="Two Pages"/>
|
202
|
+
<br>
|
203
|
+
Two Pages
|
204
|
+
</button>
|
205
|
+
<button class="DrawerLayoutButton thumbnail_mode">
|
206
|
+
<img src="${this.imagesBaseURL}icon_thumbnails.svg" alt="Thumbnails"/>
|
207
|
+
<br>
|
208
|
+
Thumbnails
|
209
|
+
</button>
|
210
|
+
</div>
|
211
|
+
<br>
|
212
|
+
<div class="DrawerSettingsTitle">Zoom</div>
|
213
|
+
<button class='BRicon zoom_out'></button>
|
214
|
+
<button class='BRicon zoom_in'></button>
|
215
|
+
<br style="clear:both"><br><br>
|
216
|
+
${experimentalHtml}
|
217
|
+
</div>
|
218
|
+
`;
|
219
|
+
const moreInfo = `
|
220
|
+
<span>
|
221
|
+
<span class="DrawerIconWrapper ">
|
222
|
+
<img class="DrawerIcon" src="${this.imagesBaseURL}icon_info.svg" alt="info-icon"/>
|
223
|
+
</span>
|
224
|
+
About This Book
|
225
|
+
</span>
|
226
|
+
<div class="BRmobileInfo"></div>
|
227
|
+
`;
|
228
|
+
const share = `
|
229
|
+
<span>
|
230
|
+
<span class="DrawerIconWrapper">
|
231
|
+
<img class="DrawerIcon" src="${this.imagesBaseURL}icon_share.svg" alt="info-share"/>
|
232
|
+
</span>
|
233
|
+
Share This Book
|
234
|
+
</span>
|
235
|
+
<div class="BRmobileShare"></div>
|
236
|
+
`;
|
237
|
+
const navMenu = `
|
238
|
+
<nav id="BRmobileMenu" class="BRmobileMenu">
|
239
|
+
<ul>
|
240
|
+
<li class="BRmobileMenu__settings">${settingsSection}</li>
|
241
|
+
<li class="BRmobileMenu__moreInfoRow">${moreInfo}</li>
|
242
|
+
<li class="BRmobileMenu__share">${share}</li>
|
243
|
+
</ul>
|
244
|
+
</nav>
|
245
|
+
`;
|
246
|
+
|
247
|
+
const $el = $(navMenu);
|
248
|
+
return $el;
|
249
|
+
};
|
250
|
+
|
251
|
+
/**
|
252
|
+
* Mmenu moves itself out side of the root BookReader element, so we need to
|
253
|
+
* include it in the scoped $ function.
|
254
|
+
*/
|
255
|
+
BookReader.prototype.$ = (function (super_) {
|
256
|
+
return function (arg) {
|
257
|
+
let $results = super_.call(this, arg);
|
258
|
+
if (this.refs.$mmenu) {
|
259
|
+
$results = $results.add(this.refs.$mmenu.find(arg));
|
260
|
+
}
|
261
|
+
return $results;
|
262
|
+
};
|
263
|
+
})(BookReader.prototype.$);
|
264
|
+
|
265
|
+
/**
|
266
|
+
* Dynamically creates styles combining different filters for BookReaders imgs
|
267
|
+
* based on filters checkbox
|
268
|
+
*/
|
269
|
+
const applyFilters = (drawerEl, br) => {
|
270
|
+
let filterStr = "";
|
271
|
+
|
272
|
+
$('.BRcheckbox-filters').each(
|
273
|
+
(i, el) => {
|
274
|
+
br.refs.$br.removeClass("filter-applied");
|
275
|
+
if ($(el).is(':checked')) {
|
276
|
+
br.refs.$br.addClass($(el).attr("filter-applied"));
|
277
|
+
filterStr = filterStr + FILTERLIST[i].filter;
|
278
|
+
}
|
279
|
+
}
|
280
|
+
);
|
281
|
+
const filtersSheet = $("#filtersStyle")[0] || document.createElement('style');
|
282
|
+
filtersSheet.id = "filtersStyle";
|
283
|
+
filtersSheet.innerHTML = `.BRpagecontainer img {
|
284
|
+
filter: ${filterStr};
|
285
|
+
-webkit-filter: ${filterStr};}`;
|
286
|
+
document.body.appendChild(filtersSheet);
|
287
|
+
};
|
@@ -0,0 +1,68 @@
|
|
1
|
+
import * as docCookies from '../util/docCookies.js';
|
2
|
+
|
3
|
+
/* global BookReader */
|
4
|
+
|
5
|
+
/** @deprecated Exposed for backward compatibility */
|
6
|
+
BookReader.docCookies = docCookies;
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Plugin to remember the current page number in a cookie
|
10
|
+
*/
|
11
|
+
jQuery.extend(BookReader.defaultOptions, {
|
12
|
+
enablePageResume: true,
|
13
|
+
/** @type {string|null} eg '/', '/details/id' */
|
14
|
+
resumeCookiePath: null,
|
15
|
+
});
|
16
|
+
|
17
|
+
/** @override */
|
18
|
+
BookReader.prototype.init = (function(super_) {
|
19
|
+
return function() {
|
20
|
+
super_.call(this);
|
21
|
+
if (this.options.enablePageResume) {
|
22
|
+
this.bind(BookReader.eventNames.fragmentChange, () => {
|
23
|
+
const params = this.paramsFromCurrent();
|
24
|
+
this.updateResumeValue(params.index);
|
25
|
+
});
|
26
|
+
}
|
27
|
+
};
|
28
|
+
})(BookReader.prototype.init);
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Gets page resume value, for remembering reader's page
|
32
|
+
* Can be overridden for different implementation
|
33
|
+
*
|
34
|
+
* @return {number|null}
|
35
|
+
*/
|
36
|
+
BookReader.prototype.getResumeValue = function() {
|
37
|
+
const val = BookReader.docCookies.getItem('br-resume');
|
38
|
+
if (val !== null) return parseInt(val);
|
39
|
+
else return null;
|
40
|
+
};
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Return cookie path using pathname up to /page/... or /mode/...
|
44
|
+
* using window.location.pathname for urlPathPart:
|
45
|
+
* - matches encoding
|
46
|
+
* - ignores querystring part
|
47
|
+
* - ignores fragment part (after #)
|
48
|
+
* @param {string} urlPathPart - window.location.pathname
|
49
|
+
*/
|
50
|
+
BookReader.prototype.getCookiePath = function(urlPathPart) {
|
51
|
+
return urlPathPart.match('.+?(?=/page/|/mode/|$)')[0];
|
52
|
+
};
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Sets page resume value, for remembering reader's page
|
56
|
+
* Can be overridden for different implementation
|
57
|
+
*
|
58
|
+
* @param {Number} index leaf index
|
59
|
+
* @param {string} [cookieName]
|
60
|
+
*/
|
61
|
+
BookReader.prototype.updateResumeValue = function(index, cookieName) {
|
62
|
+
const ttl = new Date(+new Date + 12096e5); // 2 weeks
|
63
|
+
// For multiple files in item, leave resumeCookiePath blank
|
64
|
+
// It's likely we can remove resumeCookiePath using getCookiePath()
|
65
|
+
const path = this.options.resumeCookiePath
|
66
|
+
|| this.getCookiePath(window.location.pathname);
|
67
|
+
BookReader.docCookies.setItem(cookieName || 'br-resume', index, ttl, path, null, false);
|
68
|
+
};
|
@@ -0,0 +1,291 @@
|
|
1
|
+
//@ts-check
|
2
|
+
import { createSVGPageLayer } from '../BookReader/PageContainer.js';
|
3
|
+
import { isFirefox, isSafari } from '../util/browserSniffing.js';
|
4
|
+
import { applyVariables } from '../util/strings.js';
|
5
|
+
/** @typedef {import('../util/strings.js').StringWithVars} StringWithVars */
|
6
|
+
/** @typedef {import('../BookReader/PageContainer.js').PageContainer} PageContainer */
|
7
|
+
|
8
|
+
const BookReader = /** @type {typeof import('../BookReader').default} */(window.BookReader);
|
9
|
+
|
10
|
+
export const DEFAULT_OPTIONS = {
|
11
|
+
enabled: true,
|
12
|
+
/** @type {StringWithVars} The URL to fetch the entire DJVU xml. Supports options.vars */
|
13
|
+
fullDjvuXmlUrl: null,
|
14
|
+
/** @type {StringWithVars} The URL to fetch a single page of the DJVU xml. Supports options.vars. Also has {{pageIndex}} */
|
15
|
+
singlePageDjvuXmlUrl: null,
|
16
|
+
};
|
17
|
+
/** @typedef {typeof DEFAULT_OPTIONS} TextSelectionPluginOptions */
|
18
|
+
|
19
|
+
/**
|
20
|
+
* @template T
|
21
|
+
*/
|
22
|
+
export class Cache {
|
23
|
+
constructor(maxSize = 10) {
|
24
|
+
this.maxSize = maxSize;
|
25
|
+
/** @type {T[]} */
|
26
|
+
this.entries = [];
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* @param {T} entry
|
31
|
+
*/
|
32
|
+
add(entry) {
|
33
|
+
if (this.entries.length >= this.maxSize) {
|
34
|
+
this.entries.shift();
|
35
|
+
}
|
36
|
+
this.entries.push(entry);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
export class TextSelectionPlugin {
|
41
|
+
|
42
|
+
constructor(options = DEFAULT_OPTIONS, optionVariables, avoidTspans = isFirefox(), pointerEventsOnParagraph = isSafari()) {
|
43
|
+
this.options = options;
|
44
|
+
this.optionVariables = optionVariables;
|
45
|
+
/**@type {PromiseLike<JQuery<HTMLElement>|undefined>} */
|
46
|
+
this.djvuPagesPromise = null;
|
47
|
+
// Using text elements instead of tspans for words because Firefox does not allow svg tspan stretch.
|
48
|
+
// Tspans are necessary on Chrome because they prevent newline character after every word when copying
|
49
|
+
this.svgParagraphElement = "text";
|
50
|
+
this.svgWordElement = "tspan";
|
51
|
+
this.insertNewlines = avoidTspans;
|
52
|
+
// Safari has a bug where `pointer-events` doesn't work on `<tspans>`. So
|
53
|
+
// there we will set `pointer-events: all` on the paragraph element. We don't
|
54
|
+
// do this everywhere, because it's a worse experience. Thanks Safari :/
|
55
|
+
this.pointerEventsOnParagraph = pointerEventsOnParagraph;
|
56
|
+
if (avoidTspans) {
|
57
|
+
this.svgParagraphElement = "g";
|
58
|
+
this.svgWordElement = "text";
|
59
|
+
}
|
60
|
+
|
61
|
+
/** @type {Cache<{index: number, response: any}>} */
|
62
|
+
this.pageTextCache = new Cache();
|
63
|
+
|
64
|
+
/**
|
65
|
+
* Sometimes there are too many words on a page, and the browser becomes near
|
66
|
+
* unusable. For now don't render text layer for pages with too many words.
|
67
|
+
*/
|
68
|
+
this.maxWordRendered = 2500;
|
69
|
+
}
|
70
|
+
|
71
|
+
init() {
|
72
|
+
// Only fetch the full djvu xml if the single page url isn't there
|
73
|
+
if (this.options.singlePageDjvuXmlUrl) return;
|
74
|
+
this.djvuPagesPromise = $.ajax({
|
75
|
+
type: "GET",
|
76
|
+
url: applyVariables(this.options.fullDjvuXmlUrl, this.optionVariables),
|
77
|
+
dataType: "html",
|
78
|
+
error: (e) => undefined
|
79
|
+
}).then((res) => {
|
80
|
+
try {
|
81
|
+
const xmlMap = $.parseXML(res);
|
82
|
+
return xmlMap && $(xmlMap).find("OBJECT");
|
83
|
+
} catch (e) {
|
84
|
+
return undefined;
|
85
|
+
}
|
86
|
+
});
|
87
|
+
}
|
88
|
+
|
89
|
+
/**
|
90
|
+
* @param {number} index
|
91
|
+
* @returns {Promise<HTMLElement|undefined>}
|
92
|
+
*/
|
93
|
+
async getPageText(index) {
|
94
|
+
if (this.options.singlePageDjvuXmlUrl) {
|
95
|
+
const cachedEntry = this.pageTextCache.entries.find(x => x.index == index);
|
96
|
+
if (cachedEntry) {
|
97
|
+
return cachedEntry.response;
|
98
|
+
}
|
99
|
+
return $.ajax({
|
100
|
+
type: "GET",
|
101
|
+
url: applyVariables(this.options.singlePageDjvuXmlUrl, this.optionVariables, { pageIndex: index }),
|
102
|
+
dataType: "html",
|
103
|
+
error: (e) => undefined,
|
104
|
+
}).then((res) => {
|
105
|
+
try {
|
106
|
+
const xmlDoc = $.parseXML(res);
|
107
|
+
const result = xmlDoc && $(xmlDoc).find("OBJECT")[0];
|
108
|
+
this.pageTextCache.add({ index, response: result });
|
109
|
+
return result;
|
110
|
+
} catch (e) {
|
111
|
+
return undefined;
|
112
|
+
}
|
113
|
+
});
|
114
|
+
} else {
|
115
|
+
const XMLpagesArr = await this.djvuPagesPromise;
|
116
|
+
if (XMLpagesArr) return XMLpagesArr[index];
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Intercept copied text to remove any styling applied to it
|
122
|
+
* @param {JQuery} $container
|
123
|
+
*/
|
124
|
+
interceptCopy($container) {
|
125
|
+
$container[0].addEventListener('copy', (event) => {
|
126
|
+
const selection = document.getSelection();
|
127
|
+
event.clipboardData.setData('text/plain', selection.toString());
|
128
|
+
event.preventDefault();
|
129
|
+
});
|
130
|
+
}
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Applies mouse events when in default mode
|
134
|
+
* @param {SVGElement} svg
|
135
|
+
*/
|
136
|
+
defaultMode(svg) {
|
137
|
+
svg.classList.remove("selectingSVG");
|
138
|
+
$(svg).on("mousedown.textSelectPluginHandler", (event) => {
|
139
|
+
if (!$(event.target).is(".BRwordElement")) return;
|
140
|
+
event.stopPropagation();
|
141
|
+
svg.classList.add("selectingSVG");
|
142
|
+
$(svg).one("mouseup.textSelectPluginHandler", (event) => {
|
143
|
+
if (window.getSelection().toString() != "") {
|
144
|
+
event.stopPropagation();
|
145
|
+
$(svg).off(".textSelectPluginHandler");
|
146
|
+
this.textSelectingMode(svg);
|
147
|
+
}
|
148
|
+
else svg.classList.remove("selectingSVG");
|
149
|
+
});
|
150
|
+
});
|
151
|
+
}
|
152
|
+
|
153
|
+
/**
|
154
|
+
* Applies mouse events when in textSelecting mode
|
155
|
+
* @param {SVGElement} svg
|
156
|
+
*/
|
157
|
+
textSelectingMode(svg) {
|
158
|
+
$(svg).on('mousedown.textSelectPluginHandler', (event) => {
|
159
|
+
if (!$(event.target).is(".BRwordElement")) {
|
160
|
+
if (window.getSelection().toString() != "") window.getSelection().removeAllRanges();
|
161
|
+
}
|
162
|
+
event.stopPropagation();
|
163
|
+
});
|
164
|
+
$(svg).on('mouseup.textSelectPluginHandler', (event) => {
|
165
|
+
event.stopPropagation();
|
166
|
+
if (window.getSelection().toString() == "") {
|
167
|
+
$(svg).off(".textSelectPluginHandler");
|
168
|
+
this.defaultMode(svg); }
|
169
|
+
});
|
170
|
+
}
|
171
|
+
|
172
|
+
/**
|
173
|
+
* Initializes text selection modes if there is an svg on the page
|
174
|
+
* @param {JQuery} $container
|
175
|
+
*/
|
176
|
+
stopPageFlip($container) {
|
177
|
+
/** @type {JQuery<SVGElement>} */
|
178
|
+
const $svg = $container.find('svg.textSelectionSVG');
|
179
|
+
if (!$svg.length) return;
|
180
|
+
$svg.each((i, s) => this.defaultMode(s));
|
181
|
+
this.interceptCopy($container);
|
182
|
+
}
|
183
|
+
|
184
|
+
/**
|
185
|
+
* @param {PageContainer} pageContainer
|
186
|
+
*/
|
187
|
+
async createTextLayer(pageContainer) {
|
188
|
+
const pageIndex = pageContainer.page.index;
|
189
|
+
const $container = pageContainer.$container;
|
190
|
+
const $svgLayers = $container.find('.textSelectionSVG');
|
191
|
+
if ($svgLayers.length) return;
|
192
|
+
const XMLpage = await this.getPageText(pageIndex);
|
193
|
+
if (!XMLpage) return;
|
194
|
+
|
195
|
+
const totalWords = $(XMLpage).find("WORD").length;
|
196
|
+
if (totalWords > this.maxWordRendered) {
|
197
|
+
console.log(`Page ${pageIndex} has too many words (${totalWords} > ${this.maxWordRendered}). Not rendering text layer.`);
|
198
|
+
return;
|
199
|
+
}
|
200
|
+
|
201
|
+
const svg = createSVGPageLayer(pageContainer.page, 'textSelectionSVG');
|
202
|
+
$container.append(svg);
|
203
|
+
|
204
|
+
$(XMLpage).find("PARAGRAPH").each((i, paragraph) => {
|
205
|
+
// Adding text element for each paragraph in the page
|
206
|
+
const words = $(paragraph).find("WORD");
|
207
|
+
if (!words.length) return;
|
208
|
+
const paragSvg = document.createElementNS("http://www.w3.org/2000/svg", this.svgParagraphElement);
|
209
|
+
paragSvg.setAttribute("class", "BRparagElement");
|
210
|
+
if (this.pointerEventsOnParagraph) {
|
211
|
+
paragSvg.style.pointerEvents = "all";
|
212
|
+
}
|
213
|
+
|
214
|
+
const wordHeightArr = [];
|
215
|
+
|
216
|
+
for (let i = 0; i < words.length; i++) {
|
217
|
+
// Adding tspan for each word in paragraph
|
218
|
+
const currWord = words[i];
|
219
|
+
// eslint-disable-next-line no-unused-vars
|
220
|
+
const [left, bottom, right, top] = $(currWord).attr("coords").split(',').map(parseFloat);
|
221
|
+
const wordHeight = bottom - top;
|
222
|
+
wordHeightArr.push(wordHeight);
|
223
|
+
|
224
|
+
const wordTspan = document.createElementNS("http://www.w3.org/2000/svg", this.svgWordElement);
|
225
|
+
wordTspan.setAttribute("class", "BRwordElement");
|
226
|
+
wordTspan.setAttribute("x", left.toString());
|
227
|
+
wordTspan.setAttribute("y", bottom.toString());
|
228
|
+
wordTspan.setAttribute("textLength", (right - left).toString());
|
229
|
+
wordTspan.setAttribute("lengthAdjust", "spacingAndGlyphs");
|
230
|
+
wordTspan.textContent = currWord.textContent;
|
231
|
+
paragSvg.appendChild(wordTspan);
|
232
|
+
|
233
|
+
// Adding spaces after words except at the end of the paragraph
|
234
|
+
// TODO: assumes left-to-right text
|
235
|
+
if (i < words.length - 1) {
|
236
|
+
const nextWord = words[i + 1];
|
237
|
+
// eslint-disable-next-line no-unused-vars
|
238
|
+
const [leftNext, bottomNext, rightNext, topNext] = $(nextWord).attr("coords").split(',').map(parseFloat);
|
239
|
+
const spaceTspan = document.createElementNS("http://www.w3.org/2000/svg", this.svgWordElement);
|
240
|
+
spaceTspan.setAttribute("class", "BRwordElement");
|
241
|
+
spaceTspan.setAttribute("x", right.toString());
|
242
|
+
spaceTspan.setAttribute("y", bottom.toString());
|
243
|
+
if ((leftNext - right) > 0) spaceTspan.setAttribute("textLength", (leftNext - right).toString());
|
244
|
+
spaceTspan.setAttribute("lengthAdjust", "spacingAndGlyphs");
|
245
|
+
spaceTspan.textContent = " ";
|
246
|
+
paragSvg.appendChild(spaceTspan);
|
247
|
+
}
|
248
|
+
|
249
|
+
// Adds newline at the end of paragraph on Firefox
|
250
|
+
if ((i == words.length - 1 && (this.insertNewlines))) {
|
251
|
+
paragSvg.appendChild(document.createTextNode("\n"));
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
wordHeightArr.sort();
|
256
|
+
const paragWordHeight = wordHeightArr[Math.floor(wordHeightArr.length * 0.85)];
|
257
|
+
paragSvg.setAttribute("font-size", paragWordHeight.toString());
|
258
|
+
svg.appendChild(paragSvg);
|
259
|
+
});
|
260
|
+
this.stopPageFlip($container);
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
export class BookreaderWithTextSelection extends BookReader {
|
265
|
+
init() {
|
266
|
+
const options = Object.assign({}, DEFAULT_OPTIONS, this.options.plugins.textSelection);
|
267
|
+
if (options.enabled) {
|
268
|
+
this.textSelectionPlugin = new TextSelectionPlugin(options, this.options.vars);
|
269
|
+
// Write this back; this way the plugin is the source of truth, and BR just
|
270
|
+
// contains a reference to it.
|
271
|
+
this.options.plugins.textSelection = options;
|
272
|
+
this.textSelectionPlugin.init();
|
273
|
+
}
|
274
|
+
super.init();
|
275
|
+
}
|
276
|
+
|
277
|
+
/**
|
278
|
+
* @param {number} index
|
279
|
+
*/
|
280
|
+
_createPageContainer(index) {
|
281
|
+
const pageContainer = super._createPageContainer(index);
|
282
|
+
// Disable if thumb mode; it's too janky
|
283
|
+
// .page can be null for "pre-cover" region
|
284
|
+
if (this.mode !== this.constModeThumb && pageContainer.page) {
|
285
|
+
this.textSelectionPlugin?.createTextLayer(pageContainer);
|
286
|
+
}
|
287
|
+
return pageContainer;
|
288
|
+
}
|
289
|
+
}
|
290
|
+
window.BookReader = BookreaderWithTextSelection;
|
291
|
+
export default BookreaderWithTextSelection;
|