Add support for updating the document hash, off by default, when the browser history is updated (issue 5753)
This is *really* the best that we can do here, since other proposed solutions would interfere with (and break) the painstakingly implemented browsing history that's present in the default viewer. I'm still not convinced that this is a good idea in general, but this patch implements it in a way where it is possible to toggle[1] for users that wish to have this feature. In particular, there's a couple of reasons why I'm not finding this feature necessary/great: - It's already possible to easily obtain the current hash, by simply clicking on the `viewBookmark` button at any time. - Hash changes requires a bit of special handling[2], i.e. extra code, to prevent issues when the browser history is traversed (see `PDFHistory._popState`). Currently this is only necessary when the user has manually changed the hash, with this patch it will always be the case (assuming the feature is active). - It's not always possible to change the URL when updating the browser history. For example: In the Firefox built-in viewer, the URL cannot be modified for local files (i.e. those using the `file://` protocol). This leads to inconsistent behaviour, and may in some cases even result in errors being thrown and the history thus not updating, if the browser prevents changes to the URL during `pushState`/`replaceState` calls. --- [1] Using the `historyUpdateUrl` viewer preference. [2] This depends, to a great extent, on browsers always firing `popstate` events *before* `hashchange` events, which may or may not actually be guaranteed.
This commit is contained in:
parent
af31b980b0
commit
4773bf6fcb
@ -147,6 +147,10 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"historyUpdateUrl": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"enablePrintAutoRotate": {
|
||||
"title": "Automatically rotate printed pages",
|
||||
"description": "When enabled, pages whose orientation differ from the first page are rotated when printed.",
|
||||
|
@ -903,8 +903,11 @@ let PDFViewerApplication = {
|
||||
if (!AppOptions.get('disableHistory') && !this.isViewerEmbedded) {
|
||||
// The browsing history is only enabled when the viewer is standalone,
|
||||
// i.e. not when it is embedded in a web page.
|
||||
let resetHistory = !AppOptions.get('showPreviousViewOnLoad');
|
||||
this.pdfHistory.initialize(pdfDocument.fingerprint, resetHistory);
|
||||
this.pdfHistory.initialize({
|
||||
fingerprint: pdfDocument.fingerprint,
|
||||
resetHistory: !AppOptions.get('showPreviousViewOnLoad'),
|
||||
updateUrl: AppOptions.get('historyUpdateUrl'),
|
||||
});
|
||||
|
||||
if (this.pdfHistory.initialBookmark) {
|
||||
this.initialBookmark = this.pdfHistory.initialBookmark;
|
||||
|
@ -91,6 +91,11 @@ const defaultOptions = {
|
||||
value: 0,
|
||||
kind: OptionKind.VIEWER,
|
||||
},
|
||||
historyUpdateUrl: {
|
||||
/** @type {boolean} */
|
||||
value: false,
|
||||
kind: OptionKind.VIEWER,
|
||||
},
|
||||
imageResourcesPath: {
|
||||
/** @type {string} */
|
||||
value: './images/',
|
||||
|
@ -19,6 +19,7 @@
|
||||
"disableOpenActionDestination": true,
|
||||
"disablePageMode": false,
|
||||
"disablePageLabels": false,
|
||||
"historyUpdateUrl": false,
|
||||
"scrollModeOnLoad": 0,
|
||||
"spreadModeOnLoad": 0
|
||||
}
|
||||
|
@ -86,10 +86,9 @@ class IPDFLinkService {
|
||||
*/
|
||||
class IPDFHistory {
|
||||
/**
|
||||
* @param {string} fingerprint - The PDF document's unique fingerprint.
|
||||
* @param {boolean} resetHistory - (optional) Reset the browsing history.
|
||||
* @param {Object} params
|
||||
*/
|
||||
initialize(fingerprint, resetHistory = false) {}
|
||||
initialize({ fingerprint, resetHistory = false, updateUrl = false, }) {}
|
||||
|
||||
/**
|
||||
* @param {Object} params
|
||||
|
@ -30,6 +30,14 @@ const UPDATE_VIEWAREA_TIMEOUT = 1000; // milliseconds
|
||||
* @property {EventBus} eventBus - The application event bus.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} InitializeParameters
|
||||
* @property {string} fingerprint - The PDF document's unique fingerprint.
|
||||
* @property {boolean} resetHistory - (optional) Reset the browsing history.
|
||||
* @property {boolean} updateUrl - (optional) Attempt to update the document
|
||||
* URL, with the current hash, when pushing/replacing browser history entries.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PushParameters
|
||||
* @property {string} namedDest - (optional) The named destination. If absent,
|
||||
@ -82,10 +90,9 @@ class PDFHistory {
|
||||
/**
|
||||
* Initialize the history for the PDF document, using either the current
|
||||
* browser history entry or the document hash, whichever is present.
|
||||
* @param {string} fingerprint - The PDF document's unique fingerprint.
|
||||
* @param {boolean} resetHistory - (optional) Reset the browsing history.
|
||||
* @param {InitializeParameters} params
|
||||
*/
|
||||
initialize(fingerprint, resetHistory = false) {
|
||||
initialize({ fingerprint, resetHistory = false, updateUrl = false, }) {
|
||||
if (!fingerprint || typeof fingerprint !== 'string') {
|
||||
console.error(
|
||||
'PDFHistory.initialize: The "fingerprint" must be a non-empty string.');
|
||||
@ -93,6 +100,7 @@ class PDFHistory {
|
||||
}
|
||||
let reInitialized = this.initialized && this.fingerprint !== fingerprint;
|
||||
this.fingerprint = fingerprint;
|
||||
this._updateUrl = (updateUrl === true);
|
||||
|
||||
if (!this.initialized) {
|
||||
this._bindEvents();
|
||||
@ -290,11 +298,18 @@ class PDFHistory {
|
||||
}
|
||||
this._updateInternalState(destination, newState.uid);
|
||||
|
||||
let newUrl;
|
||||
if (this._updateUrl && destination && destination.hash) {
|
||||
const baseUrl = document.location.href.split('#')[0];
|
||||
if (!baseUrl.startsWith('file://')) { // Prevent errors in Firefox.
|
||||
newUrl = `${baseUrl}#${destination.hash}`;
|
||||
}
|
||||
}
|
||||
if (shouldReplace) {
|
||||
window.history.replaceState(newState, '');
|
||||
window.history.replaceState(newState, '', newUrl);
|
||||
} else {
|
||||
this._maxUid = this._uid;
|
||||
window.history.pushState(newState, '');
|
||||
window.history.pushState(newState, '', newUrl);
|
||||
}
|
||||
|
||||
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME') &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user