@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,320 @@
|
|
1
|
+
/** @typedef {import('./BookModel.js').PageNumString} PageNumString */
|
2
|
+
/** @typedef {import('./BookModel.js').LeafNum} LeafNum */
|
3
|
+
|
4
|
+
export const DEFAULT_OPTIONS = {
|
5
|
+
/**
|
6
|
+
* @type {string} A string, such as "mode/1up". See
|
7
|
+
* http://openlibrary.org/dev/docs/bookurls for valid syntax
|
8
|
+
*/
|
9
|
+
defaults: null,
|
10
|
+
|
11
|
+
/** Padding in 1up */
|
12
|
+
padding: 10,
|
13
|
+
|
14
|
+
/** @type {'full' | 'embed' | 'responsive'} UI mode */
|
15
|
+
ui: 'full',
|
16
|
+
|
17
|
+
/** Controls whether nav/toolbar will autohide */
|
18
|
+
uiAutoHide: false,
|
19
|
+
|
20
|
+
/** thumbnail mode */
|
21
|
+
/** number of rows to pre-cache out a view */
|
22
|
+
thumbRowBuffer: 1,
|
23
|
+
thumbColumns: 6,
|
24
|
+
/** number of thumbnails to load at once */
|
25
|
+
thumbMaxLoading: 4,
|
26
|
+
/** spacing between thumbnails */
|
27
|
+
thumbPadding: 10,
|
28
|
+
|
29
|
+
/** @type {number | 'fast' | 'slow'} speed for flip animation */
|
30
|
+
flipSpeed: 'fast',
|
31
|
+
|
32
|
+
showToolbar: true,
|
33
|
+
showNavbar: true,
|
34
|
+
navBarTitle: '',
|
35
|
+
|
36
|
+
showLogo: true,
|
37
|
+
/** Where the logo links to */
|
38
|
+
logoURL: 'https://archive.org',
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Base URL for UI images - should be overridden (before init) by
|
42
|
+
* custom implementations.
|
43
|
+
* $$$ This is the same directory as the images referenced by relative
|
44
|
+
* path in the CSS. Would be better to automagically find that path.
|
45
|
+
*/
|
46
|
+
imagesBaseURL: '/BookReader/images/',
|
47
|
+
|
48
|
+
/** @type {'pow2' | 'integer'} What reduces are valid for getURI. */
|
49
|
+
reduceSet: 'pow2',
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Zoom levels
|
53
|
+
* @type {ReductionFactor[]}
|
54
|
+
* $$$ provide finer grained zooming, {reduce: 8, autofit: null}, {reduce: 16, autofit: null}
|
55
|
+
* The autofit code ensures that fit to width and fit to height will be available
|
56
|
+
*/
|
57
|
+
reductionFactors: [
|
58
|
+
{reduce: 0.25, autofit: null},
|
59
|
+
{reduce: 0.5, autofit: null},
|
60
|
+
{reduce: 1, autofit: null},
|
61
|
+
{reduce: 2, autofit: null},
|
62
|
+
{reduce: 3, autofit: null},
|
63
|
+
{reduce: 4, autofit: null},
|
64
|
+
{reduce: 6, autofit: null}
|
65
|
+
],
|
66
|
+
|
67
|
+
/** Object to hold parameters related to 1up mode */
|
68
|
+
onePage: {
|
69
|
+
/** @type {AutoFitValues} */
|
70
|
+
autofit: 'auto',
|
71
|
+
},
|
72
|
+
|
73
|
+
/** Object to hold parameters related to 2up mode */
|
74
|
+
twoPage: {
|
75
|
+
/** Width of cover */
|
76
|
+
coverInternalPadding: 0,
|
77
|
+
/** Padding outside of cover */
|
78
|
+
coverExternalPadding: 0,
|
79
|
+
/** Width of book spine $$$ consider sizing based on book length */
|
80
|
+
bookSpineDivWidth: 64,
|
81
|
+
/** @type {AutoFitValues} */
|
82
|
+
autofit: 'auto'
|
83
|
+
},
|
84
|
+
|
85
|
+
onePageMinBreakpoint: 800,
|
86
|
+
|
87
|
+
bookTitle: '',
|
88
|
+
/** @type {string} */
|
89
|
+
bookUrl: null,
|
90
|
+
/** @type {string} */
|
91
|
+
bookUrlText: null,
|
92
|
+
/** @type {string} */
|
93
|
+
bookUrlTitle: null,
|
94
|
+
enableBookTitleLink: true,
|
95
|
+
/**
|
96
|
+
* @type {string} language in ISO 639-1 (PRIVATE: Will also
|
97
|
+
* handle language name in English, native name, 639-2/T, or 639-2/B . (archive.org books
|
98
|
+
* appear to use 639-2/B ? But I don't think that's a guarantee). See
|
99
|
+
* https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes ) */
|
100
|
+
bookLanguage: null,
|
101
|
+
|
102
|
+
/**
|
103
|
+
* @type {Array<{label: string, value: *, extraValueClass: string?}>}
|
104
|
+
* Fields used to populate the info window
|
105
|
+
* @example [
|
106
|
+
* {label: 'Title', value: 'Open Library BookReader Presentation'},
|
107
|
+
* {label: 'Author', value: 'Internet Archive'},
|
108
|
+
* {label: 'Demo Info', value: 'This demo shows how one could use BookReader with their own content.'},
|
109
|
+
* ]
|
110
|
+
**/
|
111
|
+
metadata: [],
|
112
|
+
/** @type {string} */
|
113
|
+
thumbnail: null,
|
114
|
+
/** @type {string} */
|
115
|
+
bookUrlMoreInfo: null,
|
116
|
+
|
117
|
+
/** Experimental Controls (eg b/w) */
|
118
|
+
enableExperimentalControls: false,
|
119
|
+
|
120
|
+
/** CSS selectors */
|
121
|
+
/** Where BookReader mounts to */
|
122
|
+
el: '#BookReader',
|
123
|
+
|
124
|
+
/** @type {'lr' | 'rl'} Page progression */
|
125
|
+
pageProgression: 'lr',
|
126
|
+
|
127
|
+
/** The PPI the book is scanned at **/
|
128
|
+
ppi: 500,
|
129
|
+
|
130
|
+
/** Should image downloads be blocked */
|
131
|
+
protected: false,
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Settings for individual plugins. Note they have to be imported first.
|
135
|
+
* WIP: Most plugins just put their options anywhere in this global options file,
|
136
|
+
* but going forward we'll keep them here.
|
137
|
+
**/
|
138
|
+
plugins: {
|
139
|
+
/** @type {import('../plugins/plugin.text_selection.js').TextSelectionPluginOptions} */
|
140
|
+
textSelection: null,
|
141
|
+
},
|
142
|
+
|
143
|
+
/**
|
144
|
+
* Any variables you want to define. If an option has a StringWithVars type, or
|
145
|
+
* has something like `{{server}}/foo.com` in its value, these variables replace
|
146
|
+
* the `{{foo}}`.
|
147
|
+
* @type { {[var_name: string]: any } }
|
148
|
+
*/
|
149
|
+
vars: {},
|
150
|
+
|
151
|
+
/**
|
152
|
+
* @type {Array<[PageData, PageData]|[PageData]>}
|
153
|
+
* Data is a simple way to populate the bookreader
|
154
|
+
*
|
155
|
+
* Example:
|
156
|
+
* ```
|
157
|
+
* [
|
158
|
+
* // Each child is a spread
|
159
|
+
* [
|
160
|
+
* {
|
161
|
+
* width: 123,
|
162
|
+
* height: 123,
|
163
|
+
* // Optional: If not provided, include a getPageURI
|
164
|
+
* uri: 'https://archive.org/image.jpg',
|
165
|
+
* // Optional: Shown instead of leaf number if present.
|
166
|
+
* pageNum: '1'
|
167
|
+
* },
|
168
|
+
* {width: 123, height: 123, uri: 'https://archive.org/image2.jpg', pageNum: '2'},
|
169
|
+
* ]
|
170
|
+
* ],
|
171
|
+
* ```
|
172
|
+
*
|
173
|
+
* Note if URI is omitted, a custom getPageURI can be provided. This allows the page
|
174
|
+
* URI to the result of a function, which allows for things such as dynamic
|
175
|
+
* page scaling.
|
176
|
+
*/
|
177
|
+
data: [],
|
178
|
+
|
179
|
+
/** Advanced methods for page rendering */
|
180
|
+
/** @type {() => number} */
|
181
|
+
getNumLeafs: null,
|
182
|
+
/** @type {(index: number) => number} */
|
183
|
+
getPageWidth: null,
|
184
|
+
/** @type {(index: number) => number} */
|
185
|
+
getPageHeight: null,
|
186
|
+
/** @type {(index: number, reduce: number, rotate: number) => *} */
|
187
|
+
getPageURI: null,
|
188
|
+
|
189
|
+
/**
|
190
|
+
* @type {(index: number) => 'L' | 'R'}
|
191
|
+
* Return which side, left or right, that a given page should be displayed on
|
192
|
+
*/
|
193
|
+
getPageSide: null,
|
194
|
+
|
195
|
+
/**
|
196
|
+
* @type {(pindex: number) => [number, number]}
|
197
|
+
* This function returns the left and right indices for the user-visible
|
198
|
+
* spread that contains the given index. The return values may be
|
199
|
+
* null if there is no facing page or the index is invalid.
|
200
|
+
*/
|
201
|
+
getSpreadIndices: null,
|
202
|
+
|
203
|
+
/** @type {(index: number) => string} */
|
204
|
+
getPageNum: null,
|
205
|
+
/** @type {(index: number) => *} */
|
206
|
+
getPageProp: null,
|
207
|
+
/** @type {(index: number) => number} */
|
208
|
+
leafNumToIndex: null,
|
209
|
+
|
210
|
+
/**
|
211
|
+
* @type {(frameWidth: number|string, frameHeight: number|string, viewParams) => *}
|
212
|
+
* Optional: if present, and embed code will be shown in the share dialog
|
213
|
+
*/
|
214
|
+
getEmbedCode: null,
|
215
|
+
|
216
|
+
controls: {
|
217
|
+
bookLeft: {
|
218
|
+
visible: true,
|
219
|
+
label: 'Flip left',
|
220
|
+
className: 'book_left',
|
221
|
+
iconClassName: 'left-arrow'
|
222
|
+
},
|
223
|
+
bookRight: {
|
224
|
+
visible: true,
|
225
|
+
label: 'Flip right',
|
226
|
+
className: 'book_right',
|
227
|
+
iconClassName: 'left-arrow hflip'
|
228
|
+
},
|
229
|
+
onePage: {
|
230
|
+
visible: true,
|
231
|
+
label: 'One-page view',
|
232
|
+
className: 'onepg',
|
233
|
+
iconClassName: 'onepg'
|
234
|
+
},
|
235
|
+
twoPage: {
|
236
|
+
visible: true,
|
237
|
+
label: 'Two-page view',
|
238
|
+
className: 'twopg',
|
239
|
+
iconClassName: 'twopg'
|
240
|
+
},
|
241
|
+
thumbnail: {
|
242
|
+
visible: true,
|
243
|
+
label: 'Thumbnail view',
|
244
|
+
className: 'thumb',
|
245
|
+
iconClassName: 'thumb'
|
246
|
+
},
|
247
|
+
viewmode: {
|
248
|
+
visible: true,
|
249
|
+
className: 'viewmode',
|
250
|
+
excludedModes: [],
|
251
|
+
},
|
252
|
+
zoomOut: {
|
253
|
+
visible: true,
|
254
|
+
label: 'Zoom out',
|
255
|
+
className: 'zoom_out',
|
256
|
+
iconClassName: 'magnify'
|
257
|
+
},
|
258
|
+
zoomIn: {
|
259
|
+
visible: true,
|
260
|
+
label: 'Zoom in',
|
261
|
+
className: 'zoom_in',
|
262
|
+
iconClassName: 'magnify plus'
|
263
|
+
},
|
264
|
+
fullScreen: {
|
265
|
+
visible: true,
|
266
|
+
label: 'Toggle fullscreen',
|
267
|
+
className: 'full',
|
268
|
+
iconClassName: 'fullscreen'
|
269
|
+
},
|
270
|
+
},
|
271
|
+
|
272
|
+
/**
|
273
|
+
* @type {Boolean}
|
274
|
+
* Optional: if true, starts in fullscreen mode
|
275
|
+
*/
|
276
|
+
startFullscreen: false,
|
277
|
+
|
278
|
+
/**
|
279
|
+
* @type {Boolean}
|
280
|
+
* On init, by default, we want to handle resizing bookreader
|
281
|
+
* when browser window changes size (inc. `orientationchange` event)
|
282
|
+
* toggle off if you want to handle this outside of bookreader
|
283
|
+
*/
|
284
|
+
autoResize: true,
|
285
|
+
|
286
|
+
/**
|
287
|
+
* @type {Boolean}
|
288
|
+
* On init, by default, we want to use srcSet for images
|
289
|
+
*/
|
290
|
+
useSrcSet: false,
|
291
|
+
};
|
292
|
+
|
293
|
+
/** @typedef {'width' | 'height' | 'auto' | 'none'} AutoFitValues */
|
294
|
+
|
295
|
+
/**
|
296
|
+
* @typedef {object} ReductionFactor
|
297
|
+
* @property {number} reduce
|
298
|
+
* @property {AutoFitValues} [autofit] If set, the corresponding reduction factors
|
299
|
+
* are what will be used when the user tries to autofit by width/height.
|
300
|
+
*/
|
301
|
+
|
302
|
+
/**
|
303
|
+
* @typedef {Object} PageData
|
304
|
+
* @property {number} width
|
305
|
+
* @property {number} height
|
306
|
+
* @property {string} [uri] If not provided, include a getPageURI
|
307
|
+
* @property {PageNumString} [pageNum] Shown instead of leaf number if present
|
308
|
+
* @property {LeafNum} [leafNum] Sometimes specified in Internet Archive books
|
309
|
+
* @property {number} [ppi] The resolution of the page if different from {@see BookReaderOptions.ppi}
|
310
|
+
* @property {'L' | 'R'} [pageSide] PRIVATE; computed automatically
|
311
|
+
* @property {boolean} [viewable=true] Set false if page is not viewable. Displays a dummy preview image.
|
312
|
+
* @property {number} [unviewablesStart] PRIVATE; index where the chunk of unviewable pages started
|
313
|
+
*
|
314
|
+
* Note if URI is omitted, a custom getPageURI can be provided. This allows the page
|
315
|
+
* URI to the result of a function, which allows for things such as dynamic
|
316
|
+
* page scaling.
|
317
|
+
*/
|
318
|
+
|
319
|
+
/** @typedef {typeof DEFAULT_OPTIONS} BookReaderOptions */
|
320
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
// @ts-check
|
2
|
+
import { debounce } from '../utils';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Computing these things repeatedly is expensive (the browser needs to
|
6
|
+
* do a lot of computations/redrawing to make sure these are correct),
|
7
|
+
* so we store them here, and only recompute them when necessary:
|
8
|
+
* - window resize could have cause the container to change size
|
9
|
+
* - zoom could have cause scrollbars to appear/disappear, changing
|
10
|
+
* the client size.
|
11
|
+
*/
|
12
|
+
export class HTMLDimensionsCacher {
|
13
|
+
clientWidth = 100;
|
14
|
+
clientHeight = 100;
|
15
|
+
|
16
|
+
boundingClientRect = { top: 0, left: 0 };
|
17
|
+
|
18
|
+
/**
|
19
|
+
* @param {HTMLElement} element
|
20
|
+
*/
|
21
|
+
constructor(element) {
|
22
|
+
/** @type {HTMLElement} */
|
23
|
+
this.element = element;
|
24
|
+
}
|
25
|
+
|
26
|
+
updateClientSizes = () => {
|
27
|
+
const bc = this.element.getBoundingClientRect();
|
28
|
+
this.clientWidth = this.element.clientWidth;
|
29
|
+
this.clientHeight = this.element.clientHeight;
|
30
|
+
this.boundingClientRect.top = bc.top;
|
31
|
+
this.boundingClientRect.left = bc.left;
|
32
|
+
}
|
33
|
+
debouncedUpdateClientSizes = debounce(this.updateClientSizes, 150, false);
|
34
|
+
|
35
|
+
/** @param {EventTarget} win */
|
36
|
+
attachResizeListener(win = window) {
|
37
|
+
win.addEventListener('resize', this.debouncedUpdateClientSizes);
|
38
|
+
}
|
39
|
+
|
40
|
+
/** @param {EventTarget} win */
|
41
|
+
detachResizeListener(win = window) {
|
42
|
+
win.removeEventListener('resize', this.debouncedUpdateClientSizes);
|
43
|
+
}
|
44
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
/**
|
2
|
+
* Exposes a function from one class (FromClass) to another (ToClass), in such a way
|
3
|
+
* that if the ToClass's method is overridden, the FromClass's method is also overridden.
|
4
|
+
* WARNING: This modifies FromClass' prototype! So FromClasses cannot be shared between
|
5
|
+
* different ToClasses.
|
6
|
+
* @param {new () => TFrom} FromClass the class to get the method from
|
7
|
+
* @param {keyof TFrom} fromMethod the method's name in FromClass
|
8
|
+
* @param {function(TFrom): TTo} fromTransform how to get the TTo `this` to use when setting the method on TFrom
|
9
|
+
* @param {new () => TTo} ToClass the class to add the method to
|
10
|
+
* @param {string} toMethod the name of the method to add to TTo (likely will be equal to fromMethod)
|
11
|
+
* @param {function(TTo): TFrom} toTransform how to get the TFrom this to use when calling the new method
|
12
|
+
* @template TFrom type of FromClass for type-checking/autocomplete
|
13
|
+
* @template TTo type of ToClass for type-checking/autocomplete
|
14
|
+
*/
|
15
|
+
export function exposeOverrideable(FromClass, fromMethod, fromTransform, ToClass, toMethod, toTransform) {
|
16
|
+
// Wrapper function needed to "capture" the current version of fromMethod
|
17
|
+
let wrapper = (fn => {
|
18
|
+
return function () {
|
19
|
+
return fn.apply(toTransform(this), arguments);
|
20
|
+
};
|
21
|
+
})(FromClass.prototype[fromMethod]);
|
22
|
+
|
23
|
+
Object.defineProperty(ToClass.prototype, toMethod, {
|
24
|
+
get() { return wrapper; },
|
25
|
+
set(overrideFn) {
|
26
|
+
// overrideFn expects `this` to be ToClass, so ensure as such
|
27
|
+
// But we can also call this method from FromClass; need to ensure
|
28
|
+
// it's always called with a ToClass
|
29
|
+
FromClass.prototype[fromMethod] = function () {
|
30
|
+
const newThis = this instanceof FromClass ? fromTransform(this) : this;
|
31
|
+
return overrideFn.apply(newThis, arguments);
|
32
|
+
};
|
33
|
+
wrapper = overrideFn;
|
34
|
+
}
|
35
|
+
});
|
36
|
+
}
|
@@ -0,0 +1,240 @@
|
|
1
|
+
/**
|
2
|
+
* Bind mouse handlers
|
3
|
+
* Disable mouse click to avoid selected/highlighted page images
|
4
|
+
* @param {JQuery} jObject
|
5
|
+
*/
|
6
|
+
export function disableSelect(jObject) {
|
7
|
+
// $$$ check here for right-click and don't disable. Also use jQuery style
|
8
|
+
// for stopping propagation. See https://bugs.edge.launchpad.net/gnubook/+bug/362626
|
9
|
+
jObject.bind('mousedown', () => false);
|
10
|
+
// Special hack for IE7
|
11
|
+
jObject[0].onselectstart = () => false;
|
12
|
+
}
|
13
|
+
|
14
|
+
/**
|
15
|
+
* @param {number} value
|
16
|
+
* @param {number} min
|
17
|
+
* @param {number} max
|
18
|
+
* @return {number}
|
19
|
+
*/
|
20
|
+
export function clamp(value, min, max) {
|
21
|
+
return Math.min(Math.max(value, min), max);
|
22
|
+
}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Given value and maximum, calculate a percentage suitable for CSS
|
26
|
+
* @param {number} value
|
27
|
+
* @param {number} max
|
28
|
+
* @return {string}
|
29
|
+
*/
|
30
|
+
export function cssPercentage(value, max) {
|
31
|
+
return ((value / max) * 100) + '%';
|
32
|
+
}
|
33
|
+
|
34
|
+
/**
|
35
|
+
* @param {*} value
|
36
|
+
* @param {Array} array
|
37
|
+
* @return {boolean}
|
38
|
+
*/
|
39
|
+
export function notInArray(value, array) {
|
40
|
+
return !array.includes(value);
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Determines the active element, going into shadow doms.
|
45
|
+
* @return {Element}
|
46
|
+
*/
|
47
|
+
export function getActiveElement(doc = document, recurseShadowDom = true) {
|
48
|
+
const activeElement = doc.activeElement;
|
49
|
+
if (recurseShadowDom && activeElement?.shadowRoot) {
|
50
|
+
return getActiveElement(activeElement.shadowRoot, true);
|
51
|
+
}
|
52
|
+
return activeElement;
|
53
|
+
}
|
54
|
+
|
55
|
+
/** Check if an input field/textarea is active. Also checks shadow DOMs. */
|
56
|
+
export function isInputActive(doc = document) {
|
57
|
+
const activeEl = getActiveElement(doc);
|
58
|
+
return activeEl?.tagName == "INPUT" || activeEl?.tagName == "TEXTAREA";
|
59
|
+
}
|
60
|
+
|
61
|
+
/**
|
62
|
+
* @param {HTMLIFrameElement} iframe
|
63
|
+
* @return {Document}
|
64
|
+
*/
|
65
|
+
export function getIFrameDocument(iframe) {
|
66
|
+
// Adapted from http://xkr.us/articles/dom/iframe-document/
|
67
|
+
const outer = iframe.contentWindow || iframe.contentDocument;
|
68
|
+
return outer.document || outer;
|
69
|
+
}
|
70
|
+
|
71
|
+
/**
|
72
|
+
* @param {string} str
|
73
|
+
* @return {string}
|
74
|
+
*/
|
75
|
+
export function escapeHTML(str) {
|
76
|
+
return str.replace(/&/g,'&')
|
77
|
+
.replace(/>/g,'>')
|
78
|
+
.replace(/</g,'<')
|
79
|
+
.replace(/"/g,'"');
|
80
|
+
}
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Decodes a URI component and converts '+' to ' '
|
84
|
+
* @param {string} value
|
85
|
+
* @return {string}
|
86
|
+
*/
|
87
|
+
export function decodeURIComponentPlus(value) {
|
88
|
+
return decodeURIComponent(value).replace(/\+/g, ' ');
|
89
|
+
}
|
90
|
+
|
91
|
+
/**
|
92
|
+
* Encodes a URI component and converts ' ' to '+'
|
93
|
+
* @param {string|number|boolean} value
|
94
|
+
* @return {string};
|
95
|
+
*/
|
96
|
+
export function encodeURIComponentPlus(value) {
|
97
|
+
return encodeURIComponent(value).replace(/%20/g, '+');
|
98
|
+
}
|
99
|
+
|
100
|
+
/**
|
101
|
+
* @template {Function} T
|
102
|
+
* Returns a function, that, as long as it continues to be invoked, will not
|
103
|
+
* be triggered. The function will be called after it stops being called for
|
104
|
+
* N milliseconds. If `immediate` is passed, trigger the function on the
|
105
|
+
* leading edge, instead of the trailing.
|
106
|
+
* @see https://davidwalsh.name/javascript-debounce-function
|
107
|
+
*
|
108
|
+
* @param {T} func
|
109
|
+
* @param {number} wait
|
110
|
+
* @param {boolean} immediate
|
111
|
+
* @return {T}
|
112
|
+
*/
|
113
|
+
export function debounce(func, wait, immediate) {
|
114
|
+
let timeout;
|
115
|
+
return function() {
|
116
|
+
const context = this;
|
117
|
+
const args = arguments;
|
118
|
+
const later = () => {
|
119
|
+
timeout = null;
|
120
|
+
if (!immediate) func.apply(context, args);
|
121
|
+
};
|
122
|
+
const callNow = immediate && !timeout;
|
123
|
+
clearTimeout(timeout);
|
124
|
+
timeout = setTimeout(later, wait);
|
125
|
+
if (callNow) func.apply(context, args);
|
126
|
+
};
|
127
|
+
}
|
128
|
+
|
129
|
+
/**
|
130
|
+
* @template T
|
131
|
+
* Throttle function
|
132
|
+
* @see https://remysharp.com/2010/07/21/throttling-function-calls
|
133
|
+
* @param {T} fn
|
134
|
+
* @param {number} threshold
|
135
|
+
* @param {boolean} delay
|
136
|
+
* @return {T}
|
137
|
+
*/
|
138
|
+
export function throttle(fn, threshold, delay) {
|
139
|
+
threshold || (threshold = 250);
|
140
|
+
let last;
|
141
|
+
let deferTimer;
|
142
|
+
if (delay) last = +new Date;
|
143
|
+
return function () {
|
144
|
+
const context = this;
|
145
|
+
const now = +new Date;
|
146
|
+
const args = arguments;
|
147
|
+
if (last && now < last + threshold) {
|
148
|
+
// hold on to it
|
149
|
+
clearTimeout(deferTimer);
|
150
|
+
deferTimer = setTimeout(() => {
|
151
|
+
last = now;
|
152
|
+
fn.apply(context, args);
|
153
|
+
}, threshold);
|
154
|
+
} else {
|
155
|
+
last = now;
|
156
|
+
fn.apply(context, args);
|
157
|
+
}
|
158
|
+
};
|
159
|
+
}
|
160
|
+
|
161
|
+
/**
|
162
|
+
* FIXME we need a better way to do this :/ This is not automatically poly-filled by
|
163
|
+
* core-js https://github.com/zloirock/core-js/issues/354
|
164
|
+
* @param {Window} window
|
165
|
+
*/
|
166
|
+
export function polyfillCustomEvent(window) {
|
167
|
+
if (typeof window.CustomEvent === "function") return false;
|
168
|
+
window.CustomEvent = PolyfilledCustomEvent;
|
169
|
+
}
|
170
|
+
|
171
|
+
/**
|
172
|
+
* https://caniuse.com/customevent has issues on older browsers where it can't be
|
173
|
+
* called as a constructor, so we have to use older methods.
|
174
|
+
* @param {String} eventName
|
175
|
+
* @return {CustomEvent}
|
176
|
+
*/
|
177
|
+
export function PolyfilledCustomEvent(eventName, {bubbles = false, cancelable = false, detail = null} = {}) {
|
178
|
+
const event = document.createEvent('CustomEvent');
|
179
|
+
event.initCustomEvent(eventName, bubbles, cancelable, detail);
|
180
|
+
return event;
|
181
|
+
}
|
182
|
+
|
183
|
+
/*
|
184
|
+
* Returns the number pixels something should be rendered at to be ~1n on the users
|
185
|
+
* screen when measured with a ruler.
|
186
|
+
*/
|
187
|
+
export function calcScreenDPI() {
|
188
|
+
const el = document.createElement('div');
|
189
|
+
el.style.width = '1in';
|
190
|
+
document.body.appendChild(el);
|
191
|
+
const dpi = el.offsetWidth;
|
192
|
+
document.body.removeChild(el);
|
193
|
+
|
194
|
+
// Do you believe in magic... numbers? We tested on some devices, and the displayed
|
195
|
+
// size of `width: 1in` was less than desired. On @pezvi's mac, it was ~75% ; on
|
196
|
+
// @cdrini's laptop it was ~85%. Since we want to avoid things appearing too small,
|
197
|
+
// let's just use a multiplier of 1.25
|
198
|
+
const screenDPI = dpi * 1.25;
|
199
|
+
// This will return 0 in testing; never want it to be 0!
|
200
|
+
return screenDPI == 0 ? 100 : screenDPI;
|
201
|
+
}
|
202
|
+
|
203
|
+
/**
|
204
|
+
* @param {number[]} nums
|
205
|
+
* @returns {number}
|
206
|
+
*/
|
207
|
+
export function sum(nums) {
|
208
|
+
return nums.reduce((cur, acc) => cur + acc, 0);
|
209
|
+
}
|
210
|
+
|
211
|
+
/**
|
212
|
+
* @template T
|
213
|
+
* @param {Generator<T>} gen
|
214
|
+
* @returns {T[]}
|
215
|
+
*/
|
216
|
+
export function genToArray(gen) {
|
217
|
+
const result = [];
|
218
|
+
for (const item of gen) {
|
219
|
+
result.push(item);
|
220
|
+
}
|
221
|
+
return result;
|
222
|
+
}
|
223
|
+
|
224
|
+
/**
|
225
|
+
* Check if arrays contain the same elements. Does reference comparison.
|
226
|
+
* @param {Array} arr1
|
227
|
+
* @param {Array} arr2
|
228
|
+
*/
|
229
|
+
export function arrEquals(arr1, arr2) {
|
230
|
+
return arr1.length == arr2.length && arr1.every((x, i) => x == arr2[i]);
|
231
|
+
}
|
232
|
+
|
233
|
+
/**
|
234
|
+
* Check if array has changed; namely to be used with lit's property.hasChanged
|
235
|
+
* @param {Array} [arr1]
|
236
|
+
* @param {Array} [arr2]
|
237
|
+
*/
|
238
|
+
export function arrChanged(arr1, arr2) {
|
239
|
+
return arr1 && arr2 && !arrEquals(arr1, arr2);
|
240
|
+
}
|