Merge pull request #11380 from Snuffleupagus/PDFHistory-reset
Add a `reset` method to the `PDFHistory` implementation
This commit is contained in:
commit
7ceb394c43
@ -130,6 +130,10 @@ var PDFViewerApplication = {
|
|||||||
|
|
||||||
this.pdfViewer.setDocument(null);
|
this.pdfViewer.setDocument(null);
|
||||||
this.pdfLinkService.setDocument(null, null);
|
this.pdfLinkService.setDocument(null, null);
|
||||||
|
|
||||||
|
if (this.pdfHistory) {
|
||||||
|
this.pdfHistory.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
|
@ -593,6 +593,9 @@ let PDFViewerApplication = {
|
|||||||
this.pdfOutlineViewer.reset();
|
this.pdfOutlineViewer.reset();
|
||||||
this.pdfAttachmentViewer.reset();
|
this.pdfAttachmentViewer.reset();
|
||||||
|
|
||||||
|
if (this.pdfHistory) {
|
||||||
|
this.pdfHistory.reset();
|
||||||
|
}
|
||||||
if (this.findBar) {
|
if (this.findBar) {
|
||||||
this.findBar.reset();
|
this.findBar.reset();
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,8 @@ class IPDFHistory {
|
|||||||
*/
|
*/
|
||||||
initialize({ fingerprint, resetHistory = false, updateUrl = false, }) {}
|
initialize({ fingerprint, resetHistory = false, updateUrl = false, }) {}
|
||||||
|
|
||||||
|
reset() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} params
|
* @param {Object} params
|
||||||
*/
|
*/
|
||||||
|
@ -50,17 +50,6 @@ function getCurrentHash() {
|
|||||||
return document.location.hash;
|
return document.location.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseCurrentHash(linkService) {
|
|
||||||
let hash = unescape(getCurrentHash()).substring(1);
|
|
||||||
let params = parseQueryString(hash);
|
|
||||||
|
|
||||||
let page = params.page | 0;
|
|
||||||
if (!(Number.isInteger(page) && page > 0 && page <= linkService.pagesCount)) {
|
|
||||||
page = null;
|
|
||||||
}
|
|
||||||
return { hash, page, rotation: linkService.rotation, };
|
|
||||||
}
|
|
||||||
|
|
||||||
class PDFHistory {
|
class PDFHistory {
|
||||||
/**
|
/**
|
||||||
* @param {PDFHistoryOptions} options
|
* @param {PDFHistoryOptions} options
|
||||||
@ -69,21 +58,25 @@ class PDFHistory {
|
|||||||
this.linkService = linkService;
|
this.linkService = linkService;
|
||||||
this.eventBus = eventBus || getGlobalEventBus();
|
this.eventBus = eventBus || getGlobalEventBus();
|
||||||
|
|
||||||
this.initialized = false;
|
this._initialized = false;
|
||||||
this.initialBookmark = null;
|
this._fingerprint = '';
|
||||||
this.initialRotation = null;
|
this.reset();
|
||||||
|
|
||||||
this._boundEvents = Object.create(null);
|
this._boundEvents = null;
|
||||||
this._isViewerInPresentationMode = false;
|
this._isViewerInPresentationMode = false;
|
||||||
this._isPagesLoaded = false;
|
|
||||||
|
|
||||||
// Ensure that we don't miss either a 'presentationmodechanged' or a
|
// Ensure that we don't miss either a 'presentationmodechanged' or a
|
||||||
// 'pagesloaded' event, by registering the listeners immediately.
|
// 'pagesinit' event, by registering the listeners immediately.
|
||||||
this.eventBus.on('presentationmodechanged', (evt) => {
|
this.eventBus.on('presentationmodechanged', (evt) => {
|
||||||
this._isViewerInPresentationMode = evt.active || evt.switchInProgress;
|
this._isViewerInPresentationMode = evt.active || evt.switchInProgress;
|
||||||
});
|
});
|
||||||
this.eventBus.on('pagesloaded', (evt) => {
|
this.eventBus.on('pagesinit', () => {
|
||||||
this._isPagesLoaded = !!evt.pagesCount;
|
this._isPagesLoaded = false;
|
||||||
|
|
||||||
|
const onPagesLoaded = (evt) => {
|
||||||
|
this.eventBus.off('pagesloaded', onPagesLoaded);
|
||||||
|
this._isPagesLoaded = !!evt.pagesCount;
|
||||||
|
};
|
||||||
|
this.eventBus.on('pagesloaded', onPagesLoaded);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,18 +91,18 @@ class PDFHistory {
|
|||||||
'PDFHistory.initialize: The "fingerprint" must be a non-empty string.');
|
'PDFHistory.initialize: The "fingerprint" must be a non-empty string.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let reInitialized = this.initialized && this.fingerprint !== fingerprint;
|
// Ensure that any old state is always reset upon initialization.
|
||||||
this.fingerprint = fingerprint;
|
if (this._initialized) {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
const reInitialized = (this._fingerprint !== '' &&
|
||||||
|
this._fingerprint !== fingerprint);
|
||||||
|
this._fingerprint = fingerprint;
|
||||||
this._updateUrl = (updateUrl === true);
|
this._updateUrl = (updateUrl === true);
|
||||||
|
|
||||||
if (!this.initialized) {
|
this._initialized = true;
|
||||||
this._bindEvents();
|
this._bindEvents();
|
||||||
}
|
const state = window.history.state;
|
||||||
let state = window.history.state;
|
|
||||||
|
|
||||||
this.initialized = true;
|
|
||||||
this.initialBookmark = null;
|
|
||||||
this.initialRotation = null;
|
|
||||||
|
|
||||||
this._popStateInProgress = false;
|
this._popStateInProgress = false;
|
||||||
this._blockHashChange = 0;
|
this._blockHashChange = 0;
|
||||||
@ -121,7 +114,7 @@ class PDFHistory {
|
|||||||
this._position = null;
|
this._position = null;
|
||||||
|
|
||||||
if (!this._isValidState(state, /* checkReload = */ true) || resetHistory) {
|
if (!this._isValidState(state, /* checkReload = */ true) || resetHistory) {
|
||||||
let { hash, page, rotation, } = parseCurrentHash(this.linkService);
|
const { hash, page, rotation, } = this._parseCurrentHash();
|
||||||
|
|
||||||
if (!hash || reInitialized || resetHistory) {
|
if (!hash || reInitialized || resetHistory) {
|
||||||
// Ensure that the browser history is reset on PDF document load.
|
// Ensure that the browser history is reset on PDF document load.
|
||||||
@ -145,29 +138,48 @@ class PDFHistory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (destination.rotation !== undefined) {
|
if (destination.rotation !== undefined) {
|
||||||
this.initialRotation = destination.rotation;
|
this._initialRotation = destination.rotation;
|
||||||
}
|
}
|
||||||
if (destination.dest) {
|
if (destination.dest) {
|
||||||
this.initialBookmark = JSON.stringify(destination.dest);
|
this._initialBookmark = JSON.stringify(destination.dest);
|
||||||
|
|
||||||
// If the history is updated, e.g. through the user changing the hash,
|
// If the history is updated, e.g. through the user changing the hash,
|
||||||
// before the initial destination has become visible, then we do *not*
|
// before the initial destination has become visible, then we do *not*
|
||||||
// want to potentially add `this._position` to the browser history.
|
// want to potentially add `this._position` to the browser history.
|
||||||
this._destination.page = null;
|
this._destination.page = null;
|
||||||
} else if (destination.hash) {
|
} else if (destination.hash) {
|
||||||
this.initialBookmark = destination.hash;
|
this._initialBookmark = destination.hash;
|
||||||
} else if (destination.page) {
|
} else if (destination.page) {
|
||||||
// Fallback case; shouldn't be necessary, but better safe than sorry.
|
// Fallback case; shouldn't be necessary, but better safe than sorry.
|
||||||
this.initialBookmark = `page=${destination.page}`;
|
this._initialBookmark = `page=${destination.page}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the current `PDFHistory` instance, and consequently prevent any
|
||||||
|
* further updates and/or navigation of the browser history.
|
||||||
|
*/
|
||||||
|
reset() {
|
||||||
|
if (this._initialized) {
|
||||||
|
this._pageHide(); // Simulate a 'pagehide' event when resetting.
|
||||||
|
|
||||||
|
this._initialized = false;
|
||||||
|
this._unbindEvents();
|
||||||
|
}
|
||||||
|
if (this._updateViewareaTimeout) {
|
||||||
|
clearTimeout(this._updateViewareaTimeout);
|
||||||
|
this._updateViewareaTimeout = null;
|
||||||
|
}
|
||||||
|
this._initialBookmark = null;
|
||||||
|
this._initialRotation = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push an internal destination to the browser history.
|
* Push an internal destination to the browser history.
|
||||||
* @param {PushParameters}
|
* @param {PushParameters}
|
||||||
*/
|
*/
|
||||||
push({ namedDest = null, explicitDest, pageNumber, }) {
|
push({ namedDest = null, explicitDest, pageNumber, }) {
|
||||||
if (!this.initialized) {
|
if (!this._initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (namedDest && typeof namedDest !== 'string') {
|
if (namedDest && typeof namedDest !== 'string') {
|
||||||
@ -237,7 +249,7 @@ class PDFHistory {
|
|||||||
* Push the current position to the browser history.
|
* Push the current position to the browser history.
|
||||||
*/
|
*/
|
||||||
pushCurrentPosition() {
|
pushCurrentPosition() {
|
||||||
if (!this.initialized || this._popStateInProgress) {
|
if (!this._initialized || this._popStateInProgress) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._tryPushCurrentPosition();
|
this._tryPushCurrentPosition();
|
||||||
@ -248,7 +260,7 @@ class PDFHistory {
|
|||||||
* NOTE: Avoids navigating away from the document, useful for "named actions".
|
* NOTE: Avoids navigating away from the document, useful for "named actions".
|
||||||
*/
|
*/
|
||||||
back() {
|
back() {
|
||||||
if (!this.initialized || this._popStateInProgress) {
|
if (!this._initialized || this._popStateInProgress) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let state = window.history.state;
|
let state = window.history.state;
|
||||||
@ -262,7 +274,7 @@ class PDFHistory {
|
|||||||
* NOTE: Avoids navigating away from the document, useful for "named actions".
|
* NOTE: Avoids navigating away from the document, useful for "named actions".
|
||||||
*/
|
*/
|
||||||
forward() {
|
forward() {
|
||||||
if (!this.initialized || this._popStateInProgress) {
|
if (!this._initialized || this._popStateInProgress) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let state = window.history.state;
|
let state = window.history.state;
|
||||||
@ -276,17 +288,25 @@ class PDFHistory {
|
|||||||
* browser history, useful e.g. for skipping the next 'hashchange' event.
|
* browser history, useful e.g. for skipping the next 'hashchange' event.
|
||||||
*/
|
*/
|
||||||
get popStateInProgress() {
|
get popStateInProgress() {
|
||||||
return this.initialized &&
|
return this._initialized &&
|
||||||
(this._popStateInProgress || this._blockHashChange > 0);
|
(this._popStateInProgress || this._blockHashChange > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get initialBookmark() {
|
||||||
|
return this._initialized ? this._initialBookmark : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get initialRotation() {
|
||||||
|
return this._initialized ? this._initialRotation : null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_pushOrReplaceState(destination, forceReplace = false) {
|
_pushOrReplaceState(destination, forceReplace = false) {
|
||||||
let shouldReplace = forceReplace || !this._destination;
|
let shouldReplace = forceReplace || !this._destination;
|
||||||
let newState = {
|
let newState = {
|
||||||
fingerprint: this.fingerprint,
|
fingerprint: this._fingerprint,
|
||||||
uid: shouldReplace ? this._uid : (this._uid + 1),
|
uid: shouldReplace ? this._uid : (this._uid + 1),
|
||||||
destination,
|
destination,
|
||||||
};
|
};
|
||||||
@ -378,12 +398,12 @@ class PDFHistory {
|
|||||||
if (!state) {
|
if (!state) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (state.fingerprint !== this.fingerprint) {
|
if (state.fingerprint !== this._fingerprint) {
|
||||||
if (checkReload) {
|
if (checkReload) {
|
||||||
// Potentially accept the history entry, even if the fingerprints don't
|
// Potentially accept the history entry, even if the fingerprints don't
|
||||||
// match, when the viewer was reloaded (see issue 6847).
|
// match, when the viewer was reloaded (see issue 6847).
|
||||||
if (typeof state.fingerprint !== 'string' ||
|
if (typeof state.fingerprint !== 'string' ||
|
||||||
state.fingerprint.length !== this.fingerprint.length) {
|
state.fingerprint.length !== this._fingerprint.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const [perfEntry] = performance.getEntriesByType('navigation');
|
const [perfEntry] = performance.getEntriesByType('navigation');
|
||||||
@ -427,6 +447,20 @@ class PDFHistory {
|
|||||||
this._numPositionUpdates = 0;
|
this._numPositionUpdates = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_parseCurrentHash() {
|
||||||
|
const hash = unescape(getCurrentHash()).substring(1);
|
||||||
|
let page = parseQueryString(hash).page | 0;
|
||||||
|
|
||||||
|
if (!(Number.isInteger(page) &&
|
||||||
|
page > 0 && page <= this.linkService.pagesCount)) {
|
||||||
|
page = null;
|
||||||
|
}
|
||||||
|
return { hash, page, rotation: this.linkService.rotation, };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@ -493,13 +527,13 @@ class PDFHistory {
|
|||||||
let newHash = getCurrentHash(), hashChanged = this._currentHash !== newHash;
|
let newHash = getCurrentHash(), hashChanged = this._currentHash !== newHash;
|
||||||
this._currentHash = newHash;
|
this._currentHash = newHash;
|
||||||
|
|
||||||
if (!state ||
|
if ((typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME') &&
|
||||||
(typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME') &&
|
state && state.chromecomState && !this._isValidState(state)) ||
|
||||||
state.chromecomState && !this._isValidState(state))) {
|
!state) {
|
||||||
// This case corresponds to the user changing the hash of the document.
|
// This case corresponds to the user changing the hash of the document.
|
||||||
this._uid++;
|
this._uid++;
|
||||||
|
|
||||||
let { hash, page, rotation, } = parseCurrentHash(this.linkService);
|
const { hash, page, rotation, } = this._parseCurrentHash();
|
||||||
this._pushOrReplaceState({ hash, page, rotation, },
|
this._pushOrReplaceState({ hash, page, rotation, },
|
||||||
/* forceReplace = */ true);
|
/* forceReplace = */ true);
|
||||||
return;
|
return;
|
||||||
@ -564,25 +598,47 @@ class PDFHistory {
|
|||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_bindEvents() {
|
_pageHide() {
|
||||||
let { _boundEvents, eventBus, } = this;
|
// Attempt to push the `this._position` into the browser history when
|
||||||
|
// navigating away from the document. This is *only* done if the history
|
||||||
|
// is empty/temporary, since otherwise an existing browser history entry
|
||||||
|
// will end up being overwritten (given that new entries cannot be pushed
|
||||||
|
// into the browser history when the 'unload' event has already fired).
|
||||||
|
if (!this._destination || this._destination.temporary) {
|
||||||
|
this._tryPushCurrentPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_boundEvents.updateViewarea = this._updateViewarea.bind(this);
|
/**
|
||||||
_boundEvents.popState = this._popState.bind(this);
|
* @private
|
||||||
_boundEvents.pageHide = (evt) => {
|
*/
|
||||||
// Attempt to push the `this._position` into the browser history when
|
_bindEvents() {
|
||||||
// navigating away from the document. This is *only* done if the history
|
if (this._boundEvents) {
|
||||||
// is empty/temporary, since otherwise an existing browser history entry
|
return; // The event listeners were already added.
|
||||||
// will end up being overwritten (given that new entries cannot be pushed
|
}
|
||||||
// into the browser history when the 'unload' event has already fired).
|
this._boundEvents = {
|
||||||
if (!this._destination || this._destination.temporary) {
|
updateViewarea: this._updateViewarea.bind(this),
|
||||||
this._tryPushCurrentPosition();
|
popState: this._popState.bind(this),
|
||||||
}
|
pageHide: this._pageHide.bind(this),
|
||||||
};
|
};
|
||||||
|
|
||||||
eventBus.on('updateviewarea', _boundEvents.updateViewarea);
|
this.eventBus.on('updateviewarea', this._boundEvents.updateViewarea);
|
||||||
window.addEventListener('popstate', _boundEvents.popState);
|
window.addEventListener('popstate', this._boundEvents.popState);
|
||||||
window.addEventListener('pagehide', _boundEvents.pageHide);
|
window.addEventListener('pagehide', this._boundEvents.pageHide);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_unbindEvents() {
|
||||||
|
if (!this._boundEvents) {
|
||||||
|
return; // The event listeners were already removed.
|
||||||
|
}
|
||||||
|
this.eventBus.off('updateviewarea', this._boundEvents.updateViewarea);
|
||||||
|
window.removeEventListener('popstate', this._boundEvents.popState);
|
||||||
|
window.removeEventListener('pagehide', this._boundEvents.pageHide);
|
||||||
|
|
||||||
|
this._boundEvents = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user