@internetarchive/bookreader 5.0.0-112 → 5.0.0-113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/BookReader/BookReader.css +13 -7
  2. package/BookReader/BookReader.js +43 -1
  3. package/BookReader/BookReader.js.map +1 -1
  4. package/BookReader/ia-bookreader-bundle.js +3 -45
  5. package/BookReader/ia-bookreader-bundle.js.map +1 -1
  6. package/BookReader/plugins/plugin.chapters.js +2 -2
  7. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  8. package/BookReader/plugins/plugin.experiments.js +1 -1
  9. package/BookReader/plugins/plugin.experiments.js.map +1 -1
  10. package/BookReader/plugins/plugin.search.js +1 -1
  11. package/BookReader/plugins/plugin.search.js.map +1 -1
  12. package/BookReader/plugins/plugin.text_selection.js +1 -23
  13. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  14. package/BookReader/plugins/plugin.translate.js +3 -25
  15. package/BookReader/plugins/plugin.translate.js.map +1 -1
  16. package/BookReader/plugins/plugin.tts.js +1 -1
  17. package/BookReader/plugins/plugin.tts.js.map +1 -1
  18. package/BookReader/plugins/plugin.url.js +1 -2
  19. package/BookReader/plugins/plugin.url.js.map +1 -1
  20. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  21. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  22. package/package.json +1 -1
  23. package/src/BookReader/utils/SelectionObserver.js +2 -2
  24. package/src/BookReader.js +5 -4
  25. package/src/css/_BRpages.scss +5 -2
  26. package/src/css/_TextSelection.scss +15 -9
  27. package/src/plugins/plugin.experiments.js +31 -5
  28. package/src/plugins/plugin.text_selection.js +19 -56
  29. package/src/plugins/url/UrlPlugin.js +2 -15
  30. package/src/plugins/url/plugin.url.js +7 -59
  31. package/src/util/TextSelectionManager.js +834 -137
  32. package/BookReader/plugins/plugin.url.js.LICENSE.txt +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"plugins/plugin.vendor-fullscreen.js","mappings":"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","sources":["webpack://@internetarchive/bookreader/./node_modules/core-js/internals/string-trim-forced.js","webpack://@internetarchive/bookreader/./node_modules/core-js/modules/es.string.trim.js","webpack://@internetarchive/bookreader/./src/plugins/plugin.vendor-fullscreen.js"],"sourcesContent":["'use strict';\nvar PROPER_FUNCTION_NAME = require('../internals/function-name').PROPER;\nvar fails = require('../internals/fails');\nvar whitespaces = require('../internals/whitespaces');\n\nvar non = '\\u200B\\u0085\\u180E';\n\n// check that a method works with the correct list\n// of whitespaces and has a correct name\nmodule.exports = function (METHOD_NAME) {\n return fails(function () {\n return !!whitespaces[METHOD_NAME]()\n || non[METHOD_NAME]() !== non\n || (PROPER_FUNCTION_NAME && whitespaces[METHOD_NAME].name !== METHOD_NAME);\n });\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar $trim = require('../internals/string-trim').trim;\nvar forcedStringTrimMethod = require('../internals/string-trim-forced');\n\n// `String.prototype.trim` method\n// https://tc39.es/ecma262/#sec-string.prototype.trim\n$({ target: 'String', proto: true, forced: forcedStringTrimMethod('trim') }, {\n trim: function trim() {\n return $trim(this);\n }\n});\n","/* global BookReader */\n\n/**\n * Toggles browser's native fullscreen mode if available device is not mobile\n */\nif (!isMobile()) {\n const EVENT_NAMESPACE = '.bookreader_vendor-fullscreen';\n\n jQuery.extend(BookReader.defaultOptions, {\n /** @type {boolean} */\n enableVendorFullscreenPlugin: true,\n });\n\n /** @override */\n BookReader.prototype.setup = (function(super_) {\n return function(options) {\n super_.call(this, options);\n\n this.isVendorFullscreenActive = false;\n };\n })(BookReader.prototype.setup);\n\n /** @override */\n BookReader.prototype.getInitialMode = (function(super_) {\n return function(params) {\n let nextMode = super_.call(this, params);\n if (this.isVendorFullscreenActive) {\n nextMode = this.constMode1up;\n }\n return nextMode;\n };\n })(BookReader.prototype.getInitialMode);\n\n /** @override */\n BookReader.prototype.init = (function(super_) {\n return function() {\n super_.call(this);\n\n if (!fullscreenAllowed()) {\n return;\n }\n // In fullscreen mode the colorbox and overlay need to be inside the fullscreen element to display properly.\n bindFullscreenChangeListener(this, (e) => {\n e.data.resize();\n e.data.updateBrClasses();\n const cboxOverlay = $('#cboxOverlay');\n const cbox = $('#colorbox');\n if (isFullscreenActive()) {\n // In full screen mode, the colorbox and overlay need\n // to be children of the fullscreen element to display properly.\n const $fullscreen = $(getFullscreenElement());\n $fullscreen.append(cboxOverlay).append(cbox);\n } else {\n // In non-fullscreen mode, the colorbox and overlay need\n // to be children of the main document body.\n $(document.body).append(cboxOverlay).append(cbox);\n }\n });\n };\n })(BookReader.prototype.init);\n\n /**\n * Start fullscreen mode\n */\n BookReader.prototype.enterFullWindow = function() {\n this.refs.$brContainer.css('opacity', 0);\n\n const windowWidth = $(window).width();\n if (windowWidth <= this.onePageMinBreakpoint) {\n this.switchMode(this.constMode1up);\n }\n\n this.isVendorFullscreenActive = true;\n this.updateBrClasses();\n\n this.resize();\n this.jumpToIndex(this.currentIndex());\n\n this.refs.$brContainer.animate({ opacity: 1 }, 400, 'linear');\n\n $(document).on(`keyup.${EVENT_NAMESPACE}`, e => {\n if (e.keyCode === 27) this.exitFullScreen();\n });\n };\n\n /**\n * Exit from fullscreen mode\n */\n BookReader.prototype.exitFullWindow = function() {\n this.refs.$brContainer.css('opacity', 0);\n\n $(document).off('keyup' + EVENT_NAMESPACE);\n\n this.isFullscreenActive = false;\n this.updateBrClasses();\n\n this.resize();\n this.refs.$brContainer.animate({ opacity: 1 }, 400, 'linear');\n };\n\n /**\n * Returns true if fullscreen mode is enabled\n *\n * @returns {boolean}\n */\n BookReader.prototype.isFullscreen = function() {\n return isFullscreenActive() || this.isVendorFullscreenActive;\n };\n\n /**\n * Toggle screen\n */\n BookReader.prototype.toggleFullscreen = function() {\n if (this.isFullscreen()) {\n if (fullscreenAllowed()) {\n exitFullscreen();\n } else {\n this.exitFullWindow();\n }\n } else {\n if (fullscreenAllowed()) {\n requestFullscreen(this.refs.$br[0]);\n } else {\n this.enterFullWindow();\n }\n }\n };\n\n /** @deprecated */\n BookReader.util.isMobile = isMobile;\n\n /** @deprecated */\n BookReader.util.getFullscreenElement = getFullscreenElement;\n\n /** @deprecated */\n BookReader.util.bindFullscreenChangeListener = bindFullscreenChangeListener;\n\n /** @deprecated */\n BookReader.util.fullscreenAllowed = fullscreenAllowed;\n\n /** @deprecated */\n BookReader.util.requestFullscreen = requestFullscreen;\n\n /** @deprecated */\n BookReader.util.exitFullscreen = exitFullscreen;\n\n /** @deprecated */\n BookReader.util.isFullscreenActive = isFullscreenActive;\n}\n\n\n/**\n * Returns the DOM element being used for fullscreen.\n *\n * @returns {HTMLElement}\n * @see https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/fullscreenElement\n */\nexport function getFullscreenElement() {\n return document.fullscreenElement ||\n document.webkitFullscreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement;\n}\n\n/**\n * Returns true if the document is in fullscreen mode.\n *\n * @returns {boolean}\n */\nexport function isFullscreenActive() {\n const fullscreenElement = getFullscreenElement();\n return fullscreenElement !== null && fullscreenElement !== undefined;\n}\n\n/**\n * Exits fullscreen mode.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/exitFullscreen\n */\nexport function exitFullscreen() {\n if (document.exitFullscreen) {\n document.exitFullscreen();\n } else if (document.webkitExitFullscreen) {\n document.webkitExitFullscreen();\n } else if (document.mozCancelFullScreen) {\n document.mozCancelFullScreen();\n } else if (document.msExitFullscreen) {\n document.msExitFullscreen();\n }\n}\n\n/**\n * Requests fullscreen mode for the given element\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullscreen\n */\nexport function requestFullscreen(element) {\n if (element.requestFullscreen) {\n element.requestFullscreen();\n } else if (element.webkitRequestFullscreen) {\n element.webkitRequestFullscreen();\n } else if (element.mozRequestFullScreen) {\n element.mozRequestFullScreen();\n } else if (element.msRequestFullscreen) {\n element.msRequestFullscreen();\n }\n}\n\n/**\n * Returns true if fullscreen mode is allowed on this device and document.\n *\n * @returns {boolean}\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/fullscreenEnabled\n */\nexport function fullscreenAllowed() {\n return (document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullScreenEnabled);\n}\n\n/**\n * jQuery-style binding to a fullscreenchange event.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/fullscreenchange_event\n */\nexport function bindFullscreenChangeListener(\n data, fullscreenchangeListener,\n) {\n const event = 'fullscreenchange ';\n const vendor_prefixes = [\n 'webkit',\n 'moz',\n 'ms',\n ];\n const all_events = (event + vendor_prefixes.join(event) + event).trim();\n $(document).on(all_events, data, fullscreenchangeListener);\n}\n\n/**\n * Returns true if current device is mobile\n *\n * @returns {boolean}\n */\nexport function isMobile() {\n return (typeof window.orientation !== 'undefined') || (navigator.userAgent.indexOf('IEMobile') !== -1);\n}\n"],"names":["PROPER_FUNCTION_NAME","fails","whitespaces","module","exports","METHOD_NAME","name","$","$trim","target","proto","forced","forcedStringTrimMethod","trim","this","super_","isMobile","EVENT_NAMESPACE","jQuery","extend","BookReader","defaultOptions","enableVendorFullscreenPlugin","prototype","setup","options","call","isVendorFullscreenActive","getInitialMode","params","nextMode","constMode1up","init","fullscreenAllowed","bindFullscreenChangeListener","e","data","resize","updateBrClasses","cboxOverlay","cbox","isFullscreenActive","getFullscreenElement","append","document","body","enterFullWindow","_this","refs","$brContainer","css","window","width","onePageMinBreakpoint","switchMode","jumpToIndex","currentIndex","animate","opacity","on","concat","keyCode","exitFullScreen","exitFullWindow","off","isFullscreen","toggleFullscreen","exitFullscreen","requestFullscreen","$br","util","fullscreenElement","webkitFullscreenElement","mozFullScreenElement","msFullscreenElement","webkitExitFullscreen","mozCancelFullScreen","msExitFullscreen","element","webkitRequestFullscreen","mozRequestFullScreen","msRequestFullscreen","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullScreenEnabled","fullscreenchangeListener","event","all_events","join","orientation","navigator","userAgent","indexOf"],"sourceRoot":""}
1
+ {"version":3,"file":"plugins/plugin.vendor-fullscreen.js","mappings":"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","sources":["webpack://@internetarchive/bookreader/./src/plugins/plugin.vendor-fullscreen.js"],"sourcesContent":["/* global BookReader */\n\n/**\n * Toggles browser's native fullscreen mode if available device is not mobile\n */\nif (!isMobile()) {\n const EVENT_NAMESPACE = '.bookreader_vendor-fullscreen';\n\n jQuery.extend(BookReader.defaultOptions, {\n /** @type {boolean} */\n enableVendorFullscreenPlugin: true,\n });\n\n /** @override */\n BookReader.prototype.setup = (function(super_) {\n return function(options) {\n super_.call(this, options);\n\n this.isVendorFullscreenActive = false;\n };\n })(BookReader.prototype.setup);\n\n /** @override */\n BookReader.prototype.getInitialMode = (function(super_) {\n return function(params) {\n let nextMode = super_.call(this, params);\n if (this.isVendorFullscreenActive) {\n nextMode = this.constMode1up;\n }\n return nextMode;\n };\n })(BookReader.prototype.getInitialMode);\n\n /** @override */\n BookReader.prototype.init = (function(super_) {\n return function() {\n super_.call(this);\n\n if (!fullscreenAllowed()) {\n return;\n }\n // In fullscreen mode the colorbox and overlay need to be inside the fullscreen element to display properly.\n bindFullscreenChangeListener(this, (e) => {\n e.data.resize();\n e.data.updateBrClasses();\n const cboxOverlay = $('#cboxOverlay');\n const cbox = $('#colorbox');\n if (isFullscreenActive()) {\n // In full screen mode, the colorbox and overlay need\n // to be children of the fullscreen element to display properly.\n const $fullscreen = $(getFullscreenElement());\n $fullscreen.append(cboxOverlay).append(cbox);\n } else {\n // In non-fullscreen mode, the colorbox and overlay need\n // to be children of the main document body.\n $(document.body).append(cboxOverlay).append(cbox);\n }\n });\n };\n })(BookReader.prototype.init);\n\n /**\n * Start fullscreen mode\n */\n BookReader.prototype.enterFullWindow = function() {\n this.refs.$brContainer.css('opacity', 0);\n\n const windowWidth = $(window).width();\n if (windowWidth <= this.onePageMinBreakpoint) {\n this.switchMode(this.constMode1up);\n }\n\n this.isVendorFullscreenActive = true;\n this.updateBrClasses();\n\n this.resize();\n this.jumpToIndex(this.currentIndex());\n\n this.refs.$brContainer.animate({ opacity: 1 }, 400, 'linear');\n\n $(document).on(`keyup.${EVENT_NAMESPACE}`, e => {\n if (e.keyCode === 27) this.exitFullScreen();\n });\n };\n\n /**\n * Exit from fullscreen mode\n */\n BookReader.prototype.exitFullWindow = function() {\n this.refs.$brContainer.css('opacity', 0);\n\n $(document).off('keyup' + EVENT_NAMESPACE);\n\n this.isFullscreenActive = false;\n this.updateBrClasses();\n\n this.resize();\n this.refs.$brContainer.animate({ opacity: 1 }, 400, 'linear');\n };\n\n /**\n * Returns true if fullscreen mode is enabled\n *\n * @returns {boolean}\n */\n BookReader.prototype.isFullscreen = function() {\n return isFullscreenActive() || this.isVendorFullscreenActive;\n };\n\n /**\n * Toggle screen\n */\n BookReader.prototype.toggleFullscreen = function() {\n if (this.isFullscreen()) {\n if (fullscreenAllowed()) {\n exitFullscreen();\n } else {\n this.exitFullWindow();\n }\n } else {\n if (fullscreenAllowed()) {\n requestFullscreen(this.refs.$br[0]);\n } else {\n this.enterFullWindow();\n }\n }\n };\n\n /** @deprecated */\n BookReader.util.isMobile = isMobile;\n\n /** @deprecated */\n BookReader.util.getFullscreenElement = getFullscreenElement;\n\n /** @deprecated */\n BookReader.util.bindFullscreenChangeListener = bindFullscreenChangeListener;\n\n /** @deprecated */\n BookReader.util.fullscreenAllowed = fullscreenAllowed;\n\n /** @deprecated */\n BookReader.util.requestFullscreen = requestFullscreen;\n\n /** @deprecated */\n BookReader.util.exitFullscreen = exitFullscreen;\n\n /** @deprecated */\n BookReader.util.isFullscreenActive = isFullscreenActive;\n}\n\n\n/**\n * Returns the DOM element being used for fullscreen.\n *\n * @returns {HTMLElement}\n * @see https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/fullscreenElement\n */\nexport function getFullscreenElement() {\n return document.fullscreenElement ||\n document.webkitFullscreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement;\n}\n\n/**\n * Returns true if the document is in fullscreen mode.\n *\n * @returns {boolean}\n */\nexport function isFullscreenActive() {\n const fullscreenElement = getFullscreenElement();\n return fullscreenElement !== null && fullscreenElement !== undefined;\n}\n\n/**\n * Exits fullscreen mode.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/exitFullscreen\n */\nexport function exitFullscreen() {\n if (document.exitFullscreen) {\n document.exitFullscreen();\n } else if (document.webkitExitFullscreen) {\n document.webkitExitFullscreen();\n } else if (document.mozCancelFullScreen) {\n document.mozCancelFullScreen();\n } else if (document.msExitFullscreen) {\n document.msExitFullscreen();\n }\n}\n\n/**\n * Requests fullscreen mode for the given element\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullscreen\n */\nexport function requestFullscreen(element) {\n if (element.requestFullscreen) {\n element.requestFullscreen();\n } else if (element.webkitRequestFullscreen) {\n element.webkitRequestFullscreen();\n } else if (element.mozRequestFullScreen) {\n element.mozRequestFullScreen();\n } else if (element.msRequestFullscreen) {\n element.msRequestFullscreen();\n }\n}\n\n/**\n * Returns true if fullscreen mode is allowed on this device and document.\n *\n * @returns {boolean}\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/fullscreenEnabled\n */\nexport function fullscreenAllowed() {\n return (document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullScreenEnabled);\n}\n\n/**\n * jQuery-style binding to a fullscreenchange event.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/fullscreenchange_event\n */\nexport function bindFullscreenChangeListener(\n data, fullscreenchangeListener,\n) {\n const event = 'fullscreenchange ';\n const vendor_prefixes = [\n 'webkit',\n 'moz',\n 'ms',\n ];\n const all_events = (event + vendor_prefixes.join(event) + event).trim();\n $(document).on(all_events, data, fullscreenchangeListener);\n}\n\n/**\n * Returns true if current device is mobile\n *\n * @returns {boolean}\n */\nexport function isMobile() {\n return (typeof window.orientation !== 'undefined') || (navigator.userAgent.indexOf('IEMobile') !== -1);\n}\n"],"names":["super_","isMobile","EVENT_NAMESPACE","jQuery","extend","BookReader","defaultOptions","enableVendorFullscreenPlugin","prototype","setup","options","call","this","isVendorFullscreenActive","getInitialMode","params","nextMode","constMode1up","init","fullscreenAllowed","bindFullscreenChangeListener","e","data","resize","updateBrClasses","cboxOverlay","$","cbox","isFullscreenActive","getFullscreenElement","append","document","body","enterFullWindow","_this","refs","$brContainer","css","window","width","onePageMinBreakpoint","switchMode","jumpToIndex","currentIndex","animate","opacity","on","concat","keyCode","exitFullScreen","exitFullWindow","off","isFullscreen","toggleFullscreen","exitFullscreen","requestFullscreen","$br","util","fullscreenElement","webkitFullscreenElement","mozFullScreenElement","msFullscreenElement","webkitExitFullscreen","mozCancelFullScreen","msExitFullscreen","element","webkitRequestFullscreen","mozRequestFullScreen","msRequestFullscreen","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullScreenEnabled","fullscreenchangeListener","event","all_events","join","trim","orientation","navigator","userAgent","indexOf"],"sourceRoot":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/bookreader",
3
- "version": "5.0.0-112",
3
+ "version": "5.0.0-113",
4
4
  "description": "The Internet Archive BookReader.",
5
5
  "type": "module",
6
6
  "files": [
@@ -9,7 +9,7 @@ export class SelectionObserver {
9
9
 
10
10
  /**
11
11
  * @param {string} selector
12
- * @param {function('started' | 'cleared' | 'focusChanged', HTMLElement): any} handler
12
+ * @param {function('started' | 'cleared' | 'changed', HTMLElement): any} handler
13
13
  */
14
14
  constructor(selector, handler) {
15
15
  this.selector = selector;
@@ -42,7 +42,7 @@ export class SelectionObserver {
42
42
 
43
43
  if (this.selecting && (this.lastKnownFocusNode != sel.focusNode || sel.toString() && !sel.isCollapsed)) {
44
44
  this.lastKnownFocusNode = sel.focusNode;
45
- this.handler('focusChanged', this.target);
45
+ this.handler('changed', this.target);
46
46
  }
47
47
 
48
48
  if (this.selecting && (sel.isCollapsed || !sel.toString() || !$(sel.anchorNode).closest(this.selector)[0])) {
package/src/BookReader.js CHANGED
@@ -41,6 +41,7 @@ import { ModeThumb } from './BookReader/ModeThumb.js';
41
41
  import { ImageCache } from './BookReader/ImageCache.js';
42
42
  import { PageContainer } from './BookReader/PageContainer.js';
43
43
  import { NAMED_REDUCE_SETS } from './BookReader/ReduceSet.js';
44
+ import {BookReaderTextFragment} from './util/TextSelectionManager.js';
44
45
 
45
46
  /**
46
47
  * BookReader
@@ -644,7 +645,6 @@ BookReader.prototype.init = function() {
644
645
  this.pageScale = this.reduce; // preserve current reduce
645
646
 
646
647
  const params = this.initParams();
647
-
648
648
  this.firstIndex = params.index ? params.index : 0;
649
649
 
650
650
  // Setup Navbars and other UI
@@ -1971,12 +1971,13 @@ BookReader.prototype.queryStringFromParams = function(
1971
1971
  newParams.set('q', params.search);
1972
1972
  }
1973
1973
 
1974
- let textFragmentParam = '';
1974
+ /** @type {BookReaderTextFragment | null} */
1975
+ let textFragmentParam = null;
1975
1976
  // Need to pull out text separately to avoid the spaces becoming encoded as +, which
1976
1977
  // the browser seems not to handle with the text fragment
1977
1978
  if (newParams.get('text')) {
1978
1979
  newParams.delete('text');
1979
- textFragmentParam = `text=${this.urlPlugin.retrieveTextFragment(currQueryString)}`;
1980
+ textFragmentParam = BookReaderTextFragment.fromUrl(currQueryString, this.book, this.firstIndex);
1980
1981
  }
1981
1982
 
1982
1983
  // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/toString
@@ -1984,7 +1985,7 @@ BookReader.prototype.queryStringFromParams = function(
1984
1985
  let result = newParams.toString();
1985
1986
  if (textFragmentParam) {
1986
1987
  if (result) result += '&';
1987
- result += textFragmentParam;
1988
+ result += `text=${textFragmentParam.toUrlString()}`;
1988
1989
  }
1989
1990
  if (result) result = '?' + result;
1990
1991
 
@@ -101,8 +101,11 @@ svg.BRPageLayer {
101
101
  }
102
102
 
103
103
  // Hides page layers during page flip animation
104
- .BRpageFlipping .BRtextLayer {
105
- display: none;
104
+ .BRpageFlipping {
105
+ // If the text layer has an annotation, don't hide it
106
+ .BRpagecontainer:not(:has(hypothesis-highlight)):not(:has(.BRhighlight)) .BRtextLayer {
107
+ display: none;
108
+ }
106
109
  }
107
110
 
108
111
  .br-mode-2up__root {
@@ -54,13 +54,6 @@
54
54
  }
55
55
  }
56
56
 
57
- // Style URI TextFragments, eg #:~:text=example
58
- .BRtextLayer ::target-text {
59
- // Similar colour to the default one used in Safari, Firefox. Note Chrome uses a purple colour
60
- background-color: hsla(45, 80%, 66%, 0.6);
61
- color: transparent;
62
- }
63
-
64
57
  .BRtranslateLayer ::selection {
65
58
  background: hsla(210, 74%, 62%, 0.4);
66
59
  }
@@ -82,7 +75,7 @@
82
75
  // Hide text layer for performance during zooming & scrolling
83
76
  .BRsmooth-zooming, .BRscrolling-active {
84
77
  // If the text layer has an annotation, don't hide it
85
- .BRpagecontainer:not(.BRpagecontainer--hasSelection):not(:has(hypothesis-highlight)) .BRtextLayer {
78
+ .BRpagecontainer:not(.BRpagecontainer--hasSelection):not(:has(hypothesis-highlight)):not(:has(.BRhighlight)) .BRtextLayer {
86
79
  display: none;
87
80
  }
88
81
  }
@@ -209,4 +202,17 @@
209
202
  width: auto;
210
203
  margin-left: 4px;
211
204
  opacity: 1;
212
- }
205
+ }
206
+
207
+ .BRtextLayer .BRhighlight {
208
+ background-color: yellow;
209
+ pointer-events: all;
210
+ color: transparent;
211
+ }
212
+
213
+ // Style URI TextFragments, eg #:~:text=example
214
+ .BRtextLayer .BRhighlight--target-text, .BRtextLayer ::target-text {
215
+ // Similar colour to the default one used in Safari, Firefox. Note Chrome uses a purple colour
216
+ background-color: hsla(45, 80%, 66%, 0.6);
217
+ color: transparent;
218
+ }
@@ -7,8 +7,10 @@ import { sleep } from '../BookReader/utils.js';
7
7
  // @ts-ignore
8
8
  const BookReader = /** @type {typeof import('@/src/BookReader.js').default} */(window.BookReader);
9
9
 
10
+ /** @typedef {'copyLinkToHighlight' | 'annotateHighlight' | 'translate' | 'hypothesis'} ExperimentName */
11
+
10
12
  class ExperimentModel {
11
- /** @type {string} test */
13
+ /** @type {ExperimentName} */
12
14
  name;
13
15
  /** @type {string} */
14
16
  title;
@@ -58,13 +60,29 @@ export class ExperimentsPlugin extends BookReaderPlugin {
58
60
  allExperiments = [
59
61
  new class extends ExperimentModel {
60
62
  name = 'copyLinkToHighlight';
61
- title = 'Copy to Selection URL';
62
- description = 'Share text selection via URL';
63
- learnMore = 'none';
63
+ title = 'Copy Link to Highlight';
64
+ description = 'Shareable link to a text selection';
64
65
  icon = null;
65
66
  enabled = false;
66
67
  async enable ({ manual = false }) {
67
- this.br.plugins.textSelection.enableSelectionMenu();
68
+ if (manual) {
69
+ this.br.plugins.textSelection.textSelectionManager.selectMenu.copyLinkToHighlightEnabled = true;
70
+ }
71
+ }
72
+ async disable() {
73
+ this.br.plugins.textSelection.textSelectionManager.selectMenu.copyLinkToHighlightEnabled = false;
74
+ }
75
+ }(),
76
+ new class extends ExperimentModel {
77
+ name = 'annotateHighlight';
78
+ title = 'Highlight and annotate';
79
+ description = 'Create private highlights and annotations for this book';
80
+ icon = null;
81
+ enabled = false;
82
+ async enable ({ manual = false }) {
83
+ if (manual) {
84
+ this.br.plugins.textSelection.textSelectionManager.selectMenu.highlightAnnotationEnabled = true;
85
+ }
68
86
  }
69
87
  async disable() {
70
88
  sleep(0).then(() => {
@@ -150,6 +168,14 @@ export class ExperimentsPlugin extends BookReaderPlugin {
150
168
  this._render();
151
169
  }
152
170
 
171
+ /**
172
+ * @param {ExperimentName} experimentName
173
+ */
174
+ isEnabled(experimentName) {
175
+ const experiment = this.allExperiments.find(exp => exp.name === experimentName);
176
+ return experiment?.enabled;
177
+ }
178
+
153
179
  _loadExperimentStates() {
154
180
  const savedStates = JSON.parse(localStorage.getItem(this.options.localStorageKey) || '{}');
155
181
  this.allExperiments.forEach(experiment => {
@@ -4,7 +4,7 @@ import { BookReaderPlugin } from '../BookReaderPlugin.js';
4
4
  import { applyVariables } from '../util/strings.js';
5
5
  import { Cache } from '../util/cache.js';
6
6
  import { toISO6391 } from './tts/utils.js';
7
- import { TextSelectionManager } from '../util/TextSelectionManager.js';
7
+ import { BookReaderTextFragment, renderHighlight, TextSelectionManager } from '../util/TextSelectionManager.js';
8
8
  /** @typedef {import('../util/strings.js').StringWithVars} StringWithVars */
9
9
  /** @typedef {import('../BookReader/PageContainer.js').PageContainer} PageContainer */
10
10
 
@@ -46,7 +46,7 @@ export class TextSelectionPlugin extends BookReaderPlugin {
46
46
  // now we do make that assumption.
47
47
  /** Whether the book is right-to-left */
48
48
  this.rtl = this.br.pageProgression === 'rl';
49
- this.textSelectionManager = new TextSelectionManager('.BRtextLayer', this.br, {selectionElement: ['.BRwordElement', '.BRspace']}, this.options.maxProtectedWords);
49
+ this.textSelectionManager = new TextSelectionManager('.BRtextLayer', this.br, {selectionElement: ['.BRwordElement', '.BRspace', 'mark']}, this.options.maxProtectedWords);
50
50
  }
51
51
 
52
52
  /** @override */
@@ -54,18 +54,27 @@ export class TextSelectionPlugin extends BookReaderPlugin {
54
54
  if (!this.options.enabled) return;
55
55
 
56
56
  this.br.on('pageVisible', (_, {pageContainerEl}) => {
57
- if (pageContainerEl.querySelector('.BRtextLayer')) {
58
- this.br.trigger('textLayerVisible', {pageContainerEl});
57
+ const textLayer = pageContainerEl.querySelector('.BRtextLayer');
58
+ if (textLayer) {
59
+ this.br.trigger('textLayerVisible', {pageContainerEl, textLayer});
59
60
  }
60
61
  });
61
62
 
62
63
  this.loadData();
63
64
  this.textSelectionManager.init();
64
- }
65
65
 
66
- enableSelectionMenu() {
67
- this.textSelectionManager.selectionMenuEnabled = true;
68
- this.textSelectionManager.renderSelectionMenu();
66
+ // Init text fragment
67
+ this.targetTextFragment = BookReaderTextFragment.fromUrl(location.search, this.br.book, this.br.firstIndex);
68
+ if (this.targetTextFragment) {
69
+ const targetTextFragment = this.targetTextFragment;
70
+ this.br.on('textLayerVisible', async (_, {pageContainerEl, textLayer}) => {
71
+ const pageIndex = targetTextFragment.pageIndex;
72
+ const hasTargetText = pageIndex === parseFloat(pageContainerEl.getAttribute('data-index'));
73
+ if (hasTargetText) {
74
+ renderHighlight(textLayer, targetTextFragment, 'BRhighlight--target-text');
75
+ }
76
+ });
77
+ }
69
78
  }
70
79
 
71
80
  /**
@@ -76,7 +85,7 @@ export class TextSelectionPlugin extends BookReaderPlugin {
76
85
  _configurePageContainer(pageContainer) {
77
86
  // Disable if thumb mode; it's too janky
78
87
  // .page can be null for "pre-cover" region
79
- if (this.br.mode !== this.br.constModeThumb && pageContainer.page) {
88
+ if (this.br.mode !== this.br.constModeThumb && pageContainer.page?.isViewable) {
80
89
  this.createTextLayer(pageContainer);
81
90
  }
82
91
  return pageContainer;
@@ -210,7 +219,7 @@ export class TextSelectionPlugin extends BookReaderPlugin {
210
219
 
211
220
  // Check if page is visible
212
221
  if ($container.hasClass('BRpage-visible')) {
213
- this.br.trigger('textLayerVisible', {pageContainerEl: $container[0]});
222
+ this.br.trigger('textLayerVisible', {pageContainerEl: $container[0], textLayer});
214
223
  }
215
224
  }
216
225
 
@@ -575,49 +584,3 @@ class Rect {
575
584
  get top() { return this.y; }
576
585
  get left() { return this.x; }
577
586
  }
578
-
579
- /**
580
- * Depth traverse the DOM tree starting at `start`, and ending at `end`.
581
- * @param {Node} start
582
- * @param {Node} end
583
- * @returns {Generator<Node>}
584
- */
585
- export function* walkBetweenNodes(start, end) {
586
- let done = false;
587
-
588
- /**
589
- * @param {Node} node
590
- */
591
- function* walk(node, {children = true, parents = true, siblings = true} = {}) {
592
- if (node === end) {
593
- done = true;
594
- yield node;
595
- return;
596
- }
597
-
598
- // yield self
599
- yield node;
600
-
601
- // First iterate children (depth-first traversal)
602
- if (children && node.firstChild) {
603
- yield* walk(node.firstChild, {children: true, parents: false, siblings: true});
604
- if (done) return;
605
- }
606
-
607
- // Then iterate siblings
608
- if (siblings) {
609
- for (let sib = node.nextSibling; sib; sib = sib.nextSibling) {
610
- yield* walk(sib, {children: true, parents: false, siblings: false});
611
- if (done) return;
612
- }
613
- }
614
-
615
- // Finally, move up the tree
616
- if (parents && node.parentNode) {
617
- yield* walk(node.parentNode, {children: false, parents: true, siblings: true});
618
- if (done) return;
619
- }
620
- }
621
-
622
- yield* walk(start);
623
- }
@@ -190,22 +190,9 @@ export class UrlPlugin {
190
190
  }
191
191
 
192
192
  /**
193
- * Get the hash out of the current URL. Also augments it with the text
194
- * from the main part of the URL, since that is not readable by JS
195
- * from the actual hash
196
- * @returns
193
+ * Get the hash out of the current URL
197
194
  */
198
195
  getHash() {
199
- const text = this.retrieveTextFragment(window.location.search);
200
- const textFragment = text ? `:~:text=${text[0]}` : '';
201
- return `${window.location.hash.slice(1)}${textFragment}`;
202
- }
203
-
204
- /**
205
- * @param {string} urlString
206
- * @returns {string}
207
- */
208
- retrieveTextFragment(urlString) {
209
- return urlString.match(/(?<=[&?]?text=)[^&]*/);
196
+ return window.location.hash.slice(1);
210
197
  }
211
198
  }
@@ -1,7 +1,6 @@
1
1
  /* global BookReader */
2
2
 
3
3
  import { UrlPlugin } from "./UrlPlugin.js";
4
- import { sleep } from "../../BookReader/utils.js";
5
4
 
6
5
  /**
7
6
  * Plugin for URL management in BookReader
@@ -43,10 +42,6 @@ BookReader.prototype.setup = (function(super_) {
43
42
  this.locationPollId = null;
44
43
  this.oldLocationHash = null;
45
44
  this.oldUserHash = null;
46
- // Should include the :~:text= prefix
47
- this.textFragment = null;
48
- // Tracks the original textFragment page num when first loaded
49
- this.textFragmentPage = null;
50
45
  };
51
46
  })(BookReader.prototype.setup);
52
47
 
@@ -146,22 +141,16 @@ BookReader.prototype.urlUpdateFragment = function() {
146
141
  }, {});
147
142
 
148
143
  // eg 'page/3/mode/2up'; no query params (in hash mode, it might have /search/term)
149
- // Does NOT have the :~:text fragment
150
144
  const newFragment = this.fragmentFromParams(params, this.options.urlMode);
151
145
  const newFragmentWithSlash = newFragment === '' ? '' : `/${newFragment}`;
152
146
  // eg 'page/3/mode/2up'; no query params
153
- // WILL CONTAIN the :~:text fragment in hash mode (!)
154
147
  const currFragment = this.urlReadFragment();
155
148
  // This should have both ?q=foo&text=bar (and any other params) as an encoded string
156
149
  const currQueryString = this.getLocationSearch();
157
150
  // Eg ?q=foo&text=bar; only query params, no fragment
158
151
  const newQueryString = this.queryStringFromParams(params, currQueryString, this.options.urlMode);
159
-
160
- // NOTE: If ?text is in the URL, we will fire fragment change events on every render; which is
161
- // not desireable, but currently don't have a way to handle re-writing ?text to the hash text
162
- // fragment form, :~:text=foo.
163
- const hasTextParam = this.urlPlugin.retrieveTextFragment(currQueryString);
164
- if (currFragment === newFragment && currQueryString === newQueryString && !hasTextParam) {
152
+ // Avoid infinite loop if there are no changes
153
+ if (currFragment === newFragment && currQueryString === newQueryString) {
165
154
  return;
166
155
  }
167
156
 
@@ -170,19 +159,11 @@ BookReader.prototype.urlUpdateFragment = function() {
170
159
  this.options.urlMode = 'hash';
171
160
  } else {
172
161
  const baseWithoutSlash = this.options.urlHistoryBasePath.replace(/\/+$/, '');
173
- const textFragment = this.urlPlugin.retrieveTextFragment(newQueryString);
174
162
  const newUrlPath = `${baseWithoutSlash}${newFragmentWithSlash}${newQueryString}`;
175
- const extractedPage = this.urlPlugin.urlStringToUrlState(newFragmentWithSlash)?.page;
176
- if (!this.textFragmentPage && textFragment) {
177
- this.textFragmentPage = extractedPage ? extractedPage : null;
178
- this.textFragment = `:~:text=${textFragment}`;
179
- }
163
+
180
164
  try {
181
165
  window.history.replaceState({}, null, newUrlPath);
182
166
  this.oldLocationHash = newFragment + newQueryString;
183
- if (textFragment) {
184
- this.oldLocationHash += `:~:text=${textFragment[0]}`;
185
- }
186
167
  } catch (e) {
187
168
  // DOMException on Chrome when in sandboxed iframe
188
169
  this.options.urlMode = 'hash';
@@ -192,22 +173,8 @@ BookReader.prototype.urlUpdateFragment = function() {
192
173
 
193
174
  if (this.options.urlMode === 'hash') {
194
175
  const newQueryStringSearch = this.urlParamsFiltersOnlySearch(this.readQueryString());
195
- let textFragment = this.urlPlugin.retrieveTextFragment(this.readQueryString());
196
- const extractedPage = this.urlPlugin.urlStringToUrlState(newFragmentWithSlash)?.page;
197
-
198
- if (textFragment) {
199
- textFragment = `:~:text=${textFragment[0]}`;
200
- } else {
201
- textFragment = '';
202
- }
203
- if (!this.textFragmentPage && textFragment) {
204
- this.textFragmentPage = extractedPage ? extractedPage : null;
205
- this.textFragment = textFragment;
206
- } else if (this.textFragmentPage && extractedPage != this.textFragmentPage) {
207
- textFragment = '';
208
- }
209
- window.location.replace('#' + newFragment + newQueryStringSearch + textFragment);
210
- this.oldLocationHash = newFragment + newQueryStringSearch + textFragment;
176
+ window.location.replace('#' + newFragment + newQueryStringSearch);
177
+ this.oldLocationHash = newFragment + newQueryStringSearch;
211
178
  }
212
179
  };
213
180
 
@@ -248,28 +215,9 @@ export class BookreaderUrlPlugin extends BookReader {
248
215
  init() {
249
216
  if (this.options.enableUrlPlugin) {
250
217
  this.urlPlugin = new UrlPlugin(this.options);
251
- const location = this.getLocationSearch();
252
- if (location.includes("text=")) {
253
- this.on('textLayerVisible', async (_, {pageContainerEl}) => {
254
- const visiblePageNum = pageContainerEl.getAttribute('data-page-num');
255
-
256
- // Hack: More time mode 1up page "settle down" from user scrolling
257
- await sleep(this.mode === 1 ? 900 : 100);
258
-
259
- // No textFragment found or the textFragment stored doesn't match current visible page loaded
260
- if (!this.textFragment || this.textFragmentPage !== visiblePageNum) return;
261
- if (this.options.urlMode === 'history') {
262
- window.location.replace(`#${this.textFragment}`);
263
- } else {
264
- // for urlMode hash, textFragment is stored in oldLocationHash already
265
- window.location.replace(`#${this.oldLocationHash}`);
266
- }
267
- });
268
- }
269
- this.bind(BookReader.eventNames.PostInit, () => {
270
- const { urlMode } = this.options;
271
218
 
272
- if (urlMode === 'hash') {
219
+ this.on(BookReader.eventNames.PostInit, () => {
220
+ if (this.options.urlMode === 'hash') {
273
221
  this.urlPlugin.listenForHashChanges();
274
222
  }
275
223
  });