Skip to content

Commit 8eb648a

Browse files
committed
Code review changes
1 parent a59db21 commit 8eb648a

6 files changed

Lines changed: 90 additions & 57 deletions

File tree

src/BookReader.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,7 +1958,7 @@ BookReader.prototype.queryStringFromParams = function(
19581958
urlMode = 'hash',
19591959
) {
19601960
const newParams = new URLSearchParams(currQueryString);
1961-
let textFragmentParam = '';
1961+
19621962
if (params.view) {
19631963
// Set ?view=theater when fullscreen
19641964
newParams.set('view', params.view);
@@ -1970,14 +1970,25 @@ BookReader.prototype.queryStringFromParams = function(
19701970
if (params.search && urlMode === 'history') {
19711971
newParams.set('q', params.search);
19721972
}
1973+
1974+
let textFragmentParam = '';
1975+
// Need to pull out text separately to avoid the spaces becoming encoded as +, which
1976+
// the browser seems not to handle with the text fragment
19731977
if (newParams.get('text')) {
19741978
newParams.delete('text');
1975-
textFragmentParam = `text=${currQueryString.match(/(?<=&?text=)[^&]*/)}`;
1979+
textFragmentParam = `text=${this.urlPlugin.retrieveTextFragment(currQueryString)}`;
19761980
}
1981+
19771982
// https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/toString
19781983
// Note: This method returns the query string without the question mark.
1979-
const result = textFragmentParam ? newParams.toString() + textFragmentParam : newParams.toString();
1980-
return result ? '?' + result : '';
1984+
let result = newParams.toString();
1985+
if (textFragmentParam) {
1986+
if (result) result += '&';
1987+
result += textFragmentParam;
1988+
}
1989+
if (result) result = '?' + result;
1990+
1991+
return result;
19811992
};
19821993

19831994
/**

src/BookReader/utils/SelectionObserver.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export class SelectionObserver {
44
startedInSelector = false;
55
/** @type {HTMLElement} */
66
target = null;
7+
/** @type {Node} */
78
lastKnownFocusNode = null;
89

910
/**

src/css/_TextSelection.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,8 @@
161161
height: 30px;
162162
top: inherit;
163163
left: inherit;
164+
}
165+
166+
.textFragmentButtonBar {
167+
display: none;
164168
}

src/plugins/url/UrlPlugin.js

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -155,52 +155,57 @@ export class UrlPlugin {
155155
}
156156
this.oldLocationHash = urlStrPath;
157157
}
158+
158159
/**
159160
* Get the hash out of the current URL. Also augments it with the text
160161
* from the main part of the URL, since that is not readable by JS
161162
* from the actual hash
162163
* @returns
163164
*/
164-
getHash = () => {
165-
const text = this.retrieveTextFragment(window.location.search);
166-
const textFragment = text ? `:~:text=${text[0]}` : '';
167-
return `${window.location.hash.slice(1)}${textFragment}`;
168-
}
165+
getHash = () => {
166+
const text = this.retrieveTextFragment(window.location.search);
167+
const textFragment = text ? `:~:text=${text[0]}` : '';
168+
return `${window.location.hash.slice(1)}${textFragment}`;
169+
}
169170

170-
/**
171+
/**
171172
* Get the url and check if it has changed
172173
* If it was changeed, update the urlState
173174
*/
174-
listenForHashChanges() {
175-
this.oldLocationHash = this.getHash();
176-
if (this.urlLocationPollId) {
177-
clearInterval(this.urlLocationPollId);
178-
this.urlLocationPollId = null;
179-
}
175+
listenForHashChanges() {
176+
this.oldLocationHash = this.getHash();
177+
if (this.urlLocationPollId) {
178+
clearInterval(this.urlLocationPollId);
179+
this.urlLocationPollId = null;
180+
}
180181

181-
// check if the URL changes
182-
const updateHash = () => {
183-
const newFragment = this.getHash();
184-
const hasFragmentChange = newFragment != this.oldLocationHash;
182+
// check if the URL changes
183+
const updateHash = () => {
184+
const newFragment = this.getHash();
185+
const hasFragmentChange = newFragment != this.oldLocationHash;
185186

186-
if (!hasFragmentChange) { return; }
187+
if (!hasFragmentChange) { return; }
187188

188-
this.urlState = this.urlStringToUrlState(newFragment);
189-
};
190-
this.urlLocationPollId = setInterval(updateHash, 500);
191-
}
189+
this.urlState = this.urlStringToUrlState(newFragment);
190+
};
191+
this.urlLocationPollId = setInterval(updateHash, 500);
192+
}
192193

193-
/**
194+
/**
194195
* Will read either the hash or URL and return the bookreader fragment
195196
*/
196-
pullFromAddressBar (location = window.location) {
197-
const path = this.urlMode === 'history'
198-
? (location.pathname.substr(this.urlHistoryBasePath.length) + location.search)
199-
: location.hash.substr(1);
200-
this.urlState = this.urlStringToUrlState(path);
201-
}
197+
pullFromAddressBar(location = window.location) {
198+
const path = this.urlMode === 'history'
199+
? (location.pathname.substr(this.urlHistoryBasePath.length) + location.search)
200+
: location.hash.substr(1);
201+
this.urlState = this.urlStringToUrlState(path);
202+
}
202203

203-
retrieveTextFragment (urlString) {
204-
return urlString.match(/(?<=&?text=)[^&]*/);
205-
}
204+
/**
205+
* @param {string} urlString
206+
* @returns {string}
207+
*/
208+
retrieveTextFragment(urlString) {
209+
return urlString.match(/(?<=[&?]?text=)[^&]*/);
210+
}
206211
}

src/plugins/url/plugin.url.js

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,21 @@ BookReader.prototype.urlUpdateFragment = function() {
140140
return validParams;
141141
}, {});
142142

143+
// eg 'page/3/mode/2up'; no query params (in hash mode, it might have /search/term)
144+
// Does NOT have the :~:text fragment
143145
const newFragment = this.fragmentFromParams(params, this.options.urlMode);
146+
// eg 'page/3/mode/2up'; no query params
147+
// WILL CONTAIN the :~:text fragment in hash mode (!)
144148
const currFragment = this.urlReadFragment();
149+
// This should have both ?q=foo&text=bar (and any other params) as an encoded string
145150
const currQueryString = this.getLocationSearch();
151+
// Eg ?q=foo&text=bar; only query params, no fragment
146152
const newQueryString = this.queryStringFromParams(params, currQueryString, this.options.urlMode);
147-
const hasTextParam = currQueryString.includes("text");
153+
154+
// NOTE: If ?text is in the URL, we will fire fragment change events on every render; which is
155+
// not desireable, but currently don't have a way to handle re-writing ?text to the hash text
156+
// fragment form, :~:text=foo.
157+
const hasTextParam = this.urlPlugin.retrieveTextFragment(currQueryString);
148158
if (currFragment === newFragment && currQueryString === newQueryString && !hasTextParam) {
149159
return;
150160
}
@@ -155,21 +165,14 @@ BookReader.prototype.urlUpdateFragment = function() {
155165
} else {
156166
const baseWithoutSlash = this.options.urlHistoryBasePath.replace(/\/+$/, '');
157167
const newFragmentWithSlash = newFragment === '' ? '' : `/${newFragment}`;
158-
let textFragment = "";
159-
if (this.urlPlugin.retrieveTextFragment(newQueryString)) {
160-
textFragment = this.urlParamsFiltersOnlySearch(this.readQueryString());
161-
// newQueryString = newQueryString.replace(this.urlPlugin.retrieveTextFragment(newQueryString)[0], "").replace(/(\?text=)/, "")
162-
}
163-
console.log("this is newQueryString", newQueryString);
168+
const textFragment = this.urlPlugin.retrieveTextFragment(newQueryString);
164169
const newUrlPath = `${baseWithoutSlash}${newFragmentWithSlash}${newQueryString}`;
165-
console.log("this is newURLPath", newUrlPath);
166170
try {
167171
window.history.replaceState({}, null, newUrlPath);
168-
this.oldLocationHash = newFragment + newQueryString + textFragment;
169-
// if (textFragment) {
170-
// window.location.replace('#' + textFragment);
171-
// this.oldLocationHash = textFragment;
172-
// }
172+
this.oldLocationHash = newFragment + newQueryString;
173+
if (textFragment) {
174+
this.oldLocationHash += `:~:text=${textFragment[0]}`;
175+
}
173176
} catch (e) {
174177
// DOMException on Chrome when in sandboxed iframe
175178
this.options.urlMode = 'hash';
@@ -179,8 +182,12 @@ BookReader.prototype.urlUpdateFragment = function() {
179182

180183
if (this.options.urlMode === 'hash') {
181184
const newQueryStringSearch = this.urlParamsFiltersOnlySearch(this.readQueryString());
182-
window.location.replace('#' + newFragment + newQueryStringSearch);
183-
this.oldLocationHash = newFragment + newQueryStringSearch;
185+
let textFragment = this.urlPlugin.retrieveTextFragment(this.readQueryString());
186+
if (textFragment) {
187+
textFragment = `:~:text=${textFragment[0]}`;
188+
}
189+
window.location.replace('#' + newFragment + newQueryStringSearch + textFragment);
190+
this.oldLocationHash = newFragment + newQueryStringSearch + textFragment;
184191
}
185192
};
186193

@@ -194,11 +201,9 @@ BookReader.prototype.urlUpdateFragment = function() {
194201

195202
// testing with this URL http://127.0.0.1:8000/BookReaderDemo/demo-internetarchive.html?ocaid=adventureofsherl0000unse&text=Well%2C I found my plans very seriously menaced.&q=breaking the law#page/18/mode/2up
196203
BookReader.prototype.urlParamsFiltersOnlySearch = function(url) {
197-
const text = this.urlPlugin.retrieveTextFragment(url);
198204
const params = new URLSearchParams(url);
199205
let output = '';
200206
output += params.has('q') ? `?${new URLSearchParams({ q: params.get('q') })}` : '';
201-
output += text ? `:~:text=${text[0]}` : '';
202207
return output;
203208
};
204209

@@ -230,10 +235,15 @@ export class BookreaderUrlPlugin extends BookReader {
230235
const location = this.getLocationSearch();
231236
if (location.includes("text=")) {
232237
this.on('textLayerRendered', (_, {pageIndex, container}) => {
233-
window.location.replace(`#${this.oldLocationHash}`);
234-
});
235-
this.on('pageVisible', (_) => {
236-
window.location.replace(`#${this.oldLocationHash}`);
238+
if (this.options.urlMode === 'history') {
239+
// only want the text fragment forwarded
240+
if (this.oldLocationHash.includes(':~:')) {
241+
const newHash = this.oldLocationHash.split(':~:')[1];
242+
window.location.replace(`#:~:${newHash}`);
243+
}
244+
} else {
245+
window.location.replace(`#${this.oldLocationHash}`);
246+
}
237247
});
238248
}
239249
this.bind(BookReader.eventNames.PostInit, () => {

src/util/TextSelectionManager.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,12 @@ export class TextSelectionManager {
108108
* @param {HTMLElement} target
109109
*/
110110
_onSelectionChange = (type, target) => {
111-
if (type === 'started' || type === 'focusChanged') {
111+
if (type === 'started') {
112112
this.textSelectingMode(target);
113113
} else if (type === 'cleared') {
114114
this.defaultMode(target);
115+
} else if (type === 'focusChanged') {
116+
// do nothing, just wait for the mouseup to trigger the styling change
115117
} else {
116118
throw new Error(`Unknown type ${type}`);
117119
}

0 commit comments

Comments
 (0)