diff --git a/web/pdf_history.js b/web/pdf_history.js
new file mode 100644
index 000000000..ee00c6b3b
--- /dev/null
+++ b/web/pdf_history.js
@@ -0,0 +1,338 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* globals PDFJS, PDFView */
+
+'use strict';
+
+var PDFHistory = {
+ initialized: false,
+ initialDestination: null,
+
+ initialize: function pdfHistoryInitialize(fingerprint) {
+ if (PDFJS.disableHistory || window.parent !== window) {
+ // The browsing history is only enabled when the viewer is standalone,
+ // i.e. not when it is embedded in a page.
+ return;
+ }
+ this.initialized = true;
+ this.reInitialized = false;
+ this.allowHashChange = true;
+ this.historyUnlocked = true;
+
+ this.previousHash = window.location.hash.substring(1);
+ this.currentBookmark = '';
+ this.currentPage = 0;
+ this.updatePreviousBookmark = false;
+ this.previousBookmark = '';
+ this.previousPage = 0;
+ this.nextHashParam = '';
+
+ this.fingerprint = fingerprint;
+ this.currentUid = this.uid = 0;
+ this.current = {};
+
+ var state = window.history.state;
+ if (this._isStateObjectDefined(state)) {
+ // This corresponds to navigating back to the document
+ // from another page in the browser history.
+ if (state.target.dest) {
+ this.initialDestination = state.target.dest;
+ } else {
+ PDFView.initialBookmark = state.target.hash;
+ }
+ this.currentUid = state.uid;
+ this.uid = state.uid + 1;
+ this.current = state.target;
+ } else {
+ // This corresponds to the loading of a new document.
+ if (state && state.fingerprint &&
+ this.fingerprint !== state.fingerprint) {
+ // Reinitialize the browsing history when a new document
+ // is opened in the web viewer.
+ this.reInitialized = true;
+ }
+ window.history.replaceState({ fingerprint: this.fingerprint }, '', '');
+ }
+
+ var self = this;
+ window.addEventListener('popstate', function pdfHistoryPopstate(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+
+ if (!self.historyUnlocked) {
+ return;
+ }
+ if (evt.state) {
+ // Move back/forward in the history.
+ self._goTo(evt.state);
+ } else {
+ // Handle the user modifying the hash of a loaded document.
+ self.previousHash = window.location.hash.substring(1);
+
+ // If the history is empty when the hash changes,
+ // update the previous entry in the browser history.
+ if (self.uid === 0) {
+ var previousParams = (self.previousHash && self.currentBookmark &&
+ self.previousHash !== self.currentBookmark) ?
+ { hash: self.currentBookmark, page: self.currentPage } :
+ { page: 1 };
+ self.historyUnlocked = false;
+ self.allowHashChange = false;
+ window.history.back();
+ self._pushToHistory(previousParams, false, true);
+ window.history.forward();
+ self.historyUnlocked = true;
+ }
+ self._pushToHistory({ hash: self.previousHash }, false, true);
+ self._updatePreviousBookmark();
+ }
+ }, false);
+
+ function pdfHistoryBeforeUnload() {
+ var previousParams = self._getPreviousParams(null, true);
+ if (previousParams) {
+ var replacePrevious = (!self.current.dest &&
+ self.current.hash !== self.previousHash);
+ self._pushToHistory(previousParams, false, replacePrevious);
+ self._updatePreviousBookmark();
+ }
+ // Remove the event listener when navigating away from the document,
+ // since 'beforeunload' prevents Firefox from caching the document.
+ window.removeEventListener('beforeunload', pdfHistoryBeforeUnload, false);
+ }
+ window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false);
+
+ window.addEventListener('pageshow', function pdfHistoryPageShow(evt) {
+ // If the entire viewer (including the PDF file) is cached in the browser,
+ // we need to reattach the 'beforeunload' event listener since
+ // the 'DOMContentLoaded' event is not fired on 'pageshow'.
+ window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false);
+ }, false);
+ },
+
+ _isStateObjectDefined: function pdfHistory_isStateObjectDefined(state) {
+ return (state && state.uid >= 0 &&
+ state.fingerprint && this.fingerprint === state.fingerprint &&
+ state.target && state.target.hash) ? true : false;
+ },
+
+ get isHashChangeUnlocked() {
+ if (!this.initialized) {
+ return true;
+ }
+ // If the current hash changes when moving back/forward in the history,
+ // this will trigger a 'popstate' event *as well* as a 'hashchange' event.
+ // Since the hash generally won't correspond to the exact the position
+ // stored in the history's state object, triggering the 'hashchange' event
+ // can thus corrupt the browser history.
+ //
+ // When the hash changes during a 'popstate' event, we *only* prevent the
+ // first 'hashchange' event and immediately reset allowHashChange.
+ // If it is not reset, the user would not be able to change the hash.
+
+ var temp = this.allowHashChange;
+ this.allowHashChange = true;
+ return temp;
+ },
+
+ _updatePreviousBookmark: function pdfHistory_updatePreviousBookmark() {
+ if (this.updatePreviousBookmark &&
+ this.currentBookmark && this.currentPage) {
+ this.previousBookmark = this.currentBookmark;
+ this.previousPage = this.currentPage;
+ this.updatePreviousBookmark = false;
+ }
+ },
+
+ updateCurrentBookmark: function pdfHistoryUpdateCurrentBookmark(bookmark,
+ pageNum) {
+ if (this.initialized) {
+ this.currentBookmark = bookmark.substring(1);
+ this.currentPage = pageNum | 0;
+ this._updatePreviousBookmark();
+ }
+ },
+
+ updateNextHashParam: function pdfHistoryUpdateNextHashParam(param) {
+ if (this.initialized) {
+ this.nextHashParam = param;
+ }
+ },
+
+ push: function pdfHistoryPush(params, isInitialBookmark) {
+ if (!(this.initialized && this.historyUnlocked)) {
+ return;
+ }
+ if (params.dest && !params.hash) {
+ params.hash = (this.current.hash && this.current.dest &&
+ this.current.dest === params.dest) ?
+ this.current.hash :
+ PDFView.getDestinationHash(params.dest).split('#')[1];
+ }
+ if (params.page) {
+ params.page |= 0;
+ }
+ if (isInitialBookmark) {
+ var target = window.history.state.target;
+ if (!target) {
+ // Invoked when the user specifies an initial bookmark,
+ // thus setting PDFView.initialBookmark, when the document is loaded.
+ this._pushToHistory(params, false);
+ this.previousHash = window.location.hash.substring(1);
+ }
+ this.updatePreviousBookmark = this.nextHashParam ? false : true;
+ if (target) {
+ // If the current document is reloaded,
+ // avoid creating duplicate entries in the history.
+ this._updatePreviousBookmark();
+ }
+ return;
+ }
+ if (this.nextHashParam && this.nextHashParam === params.hash) {
+ this.nextHashParam = null;
+ this.updatePreviousBookmark = true;
+ return;
+ }
+
+ if (params.hash) {
+ if (this.current.hash) {
+ if (this.current.hash !== params.hash) {
+ this._pushToHistory(params, true);
+ } else {
+ if (!this.current.page && params.page) {
+ this._pushToHistory(params, false, true);
+ }
+ this.updatePreviousBookmark = true;
+ }
+ } else {
+ this._pushToHistory(params, true);
+ }
+ } else if (this.current.page && params.page &&
+ this.current.page !== params.page) {
+ this._pushToHistory(params, true);
+ }
+ },
+
+ _getPreviousParams: function pdfHistory_getPreviousParams(onlyCheckPage,
+ beforeUnload) {
+ if (!(this.currentBookmark && this.currentPage)) {
+ return null;
+ }
+ if ((!this.current.dest && !onlyCheckPage) || beforeUnload) {
+ if (this.previousBookmark === this.currentBookmark) {
+ return null;
+ }
+ } else if (this.current.page || onlyCheckPage) {
+ if (this.previousPage === this.currentPage) {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ var params = { hash: this.currentBookmark, page: this.currentPage };
+ if (PDFView.isPresentationMode) {
+ params.hash = null;
+ }
+ return params;
+ },
+
+ _stateObj: function pdfHistory_stateObj(params) {
+ return { fingerprint: this.fingerprint, uid: this.uid, target: params };
+ },
+
+ _pushToHistory: function pdfHistory_pushToHistory(params,
+ addPrevious, overwrite) {
+ if (!this.initialized) {
+ return;
+ }
+ if (!params.hash && params.page) {
+ params.hash = ('page=' + params.page);
+ }
+ if (addPrevious && !overwrite) {
+ var previousParams = this._getPreviousParams();
+ if (previousParams) {
+ var replacePrevious = (this.current.hash !== this.previousHash);
+ this._pushToHistory(previousParams, false, replacePrevious);
+ }
+ }
+ if (overwrite || this.uid === 0) {
+ window.history.replaceState(this._stateObj(params), '', '');
+ } else {
+ window.history.pushState(this._stateObj(params), '', '');
+ }
+ this.currentUid = this.uid++;
+ this.current = params;
+ this.updatePreviousBookmark = true;
+ },
+
+ _goTo: function pdfHistory_goTo(state) {
+ if (!(this.initialized && this.historyUnlocked &&
+ this._isStateObjectDefined(state))) {
+ return;
+ }
+ if (!this.reInitialized && state.uid < this.currentUid) {
+ var previousParams = this._getPreviousParams(true);
+ if (previousParams) {
+ this._pushToHistory(this.current, false);
+ this._pushToHistory(previousParams, false);
+ this.currentUid = state.uid;
+ window.history.back();
+ return;
+ }
+ }
+ this.historyUnlocked = false;
+
+ if (state.target.dest) {
+ PDFView.navigateTo(state.target.dest);
+ } else {
+ PDFView.setHash(state.target.hash);
+ }
+ this.currentUid = state.uid;
+ if (state.uid > this.uid) {
+ this.uid = state.uid;
+ }
+ this.current = state.target;
+ this.updatePreviousBookmark = true;
+
+ var currentHash = window.location.hash.substring(1);
+ if (this.previousHash !== currentHash) {
+ this.allowHashChange = false;
+ }
+ this.previousHash = currentHash;
+
+ this.historyUnlocked = true;
+ },
+
+ back: function pdfHistoryBack() {
+ this.go(-1);
+ },
+
+ forward: function pdfHistoryForward() {
+ this.go(1);
+ },
+
+ go: function pdfHistoryGo(direction) {
+ if (this.initialized && this.historyUnlocked) {
+ var state = window.history.state;
+ if (direction === -1 && state && state.uid > 0) {
+ window.history.back();
+ } else if (direction === 1 && state && state.uid < (this.uid - 1)) {
+ window.history.forward();
+ }
+ }
+ }
+};
diff --git a/web/viewer.html b/web/viewer.html
index 7d6fcc0c4..61b745c05 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -83,6 +83,7 @@ limitations under the License.
+
diff --git a/web/viewer.js b/web/viewer.js
index ae968334a..efba01624 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -16,7 +16,8 @@
*/
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar, CustomStyle,
PDFFindController, ProgressBar, TextLayerBuilder, DownloadManager,
- getFileName, getOutputScale, scrollIntoView, getPDFFileNameFromURL */
+ getFileName, getOutputScale, scrollIntoView, getPDFFileNameFromURL,
+ PDFHistory */
'use strict';
@@ -165,325 +166,7 @@ var currentPageNumber = 1;
// got resolved
//#include pdf_find_bar.js
//#include pdf_find_controller.js
-
-var PDFHistory = {
- initialized: false,
- initialDestination: null,
-
- initialize: function pdfHistoryInitialize(fingerprint) {
- if (PDFJS.disableHistory || window.parent !== window) {
- // The browsing history is only enabled when the viewer is standalone,
- // i.e. not when it is embedded in a page.
- return;
- }
- this.initialized = true;
- this.reInitialized = false;
- this.allowHashChange = true;
- this.historyUnlocked = true;
-
- this.previousHash = window.location.hash.substring(1);
- this.currentBookmark = '';
- this.currentPage = 0;
- this.updatePreviousBookmark = false;
- this.previousBookmark = '';
- this.previousPage = 0;
- this.nextHashParam = '';
-
- this.fingerprint = fingerprint;
- this.currentUid = this.uid = 0;
- this.current = {};
-
- var state = window.history.state;
- if (this._isStateObjectDefined(state)) {
- // This corresponds to navigating back to the document
- // from another page in the browser history.
- if (state.target.dest) {
- this.initialDestination = state.target.dest;
- } else {
- PDFView.initialBookmark = state.target.hash;
- }
- this.currentUid = state.uid;
- this.uid = state.uid + 1;
- this.current = state.target;
- } else {
- // This corresponds to the loading of a new document.
- if (state && state.fingerprint &&
- this.fingerprint !== state.fingerprint) {
- // Reinitialize the browsing history when a new document
- // is opened in the web viewer.
- this.reInitialized = true;
- }
- window.history.replaceState({ fingerprint: this.fingerprint }, '', '');
- }
-
- var self = this;
- window.addEventListener('popstate', function pdfHistoryPopstate(evt) {
- evt.preventDefault();
- evt.stopPropagation();
-
- if (!self.historyUnlocked) {
- return;
- }
- if (evt.state) {
- // Move back/forward in the history.
- self._goTo(evt.state);
- } else {
- // Handle the user modifying the hash of a loaded document.
- self.previousHash = window.location.hash.substring(1);
-
- // If the history is empty when the hash changes,
- // update the previous entry in the browser history.
- if (self.uid === 0) {
- var previousParams = (self.previousHash && self.currentBookmark &&
- self.previousHash !== self.currentBookmark) ?
- { hash: self.currentBookmark, page: self.currentPage } :
- { page: 1 };
- self.historyUnlocked = false;
- self.allowHashChange = false;
- window.history.back();
- self._pushToHistory(previousParams, false, true);
- window.history.forward();
- self.historyUnlocked = true;
- }
- self._pushToHistory({ hash: self.previousHash }, false, true);
- self._updatePreviousBookmark();
- }
- }, false);
-
- function pdfHistoryBeforeUnload() {
- var previousParams = self._getPreviousParams(null, true);
- if (previousParams) {
- var replacePrevious = (!self.current.dest &&
- self.current.hash !== self.previousHash);
- self._pushToHistory(previousParams, false, replacePrevious);
- self._updatePreviousBookmark();
- }
- // Remove the event listener when navigating away from the document,
- // since 'beforeunload' prevents Firefox from caching the document.
- window.removeEventListener('beforeunload', pdfHistoryBeforeUnload, false);
- }
- window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false);
-
- window.addEventListener('pageshow', function pdfHistoryPageShow(evt) {
- // If the entire viewer (including the PDF file) is cached in the browser,
- // we need to reattach the 'beforeunload' event listener since
- // the 'DOMContentLoaded' event is not fired on 'pageshow'.
- window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false);
- }, false);
- },
-
- _isStateObjectDefined: function pdfHistory_isStateObjectDefined(state) {
- return (state && state.uid >= 0 &&
- state.fingerprint && this.fingerprint === state.fingerprint &&
- state.target && state.target.hash) ? true : false;
- },
-
- get isHashChangeUnlocked() {
- if (!this.initialized) {
- return true;
- }
- // If the current hash changes when moving back/forward in the history,
- // this will trigger a 'popstate' event *as well* as a 'hashchange' event.
- // Since the hash generally won't correspond to the exact the position
- // stored in the history's state object, triggering the 'hashchange' event
- // can thus corrupt the browser history.
- //
- // When the hash changes during a 'popstate' event, we *only* prevent the
- // first 'hashchange' event and immediately reset allowHashChange.
- // If it is not reset, the user would not be able to change the hash.
-
- var temp = this.allowHashChange;
- this.allowHashChange = true;
- return temp;
- },
-
- _updatePreviousBookmark: function pdfHistory_updatePreviousBookmark() {
- if (this.updatePreviousBookmark &&
- this.currentBookmark && this.currentPage) {
- this.previousBookmark = this.currentBookmark;
- this.previousPage = this.currentPage;
- this.updatePreviousBookmark = false;
- }
- },
-
- updateCurrentBookmark: function pdfHistoryUpdateCurrentBookmark(bookmark,
- pageNum) {
- if (this.initialized) {
- this.currentBookmark = bookmark.substring(1);
- this.currentPage = pageNum | 0;
- this._updatePreviousBookmark();
- }
- },
-
- updateNextHashParam: function pdfHistoryUpdateNextHashParam(param) {
- if (this.initialized) {
- this.nextHashParam = param;
- }
- },
-
- push: function pdfHistoryPush(params, isInitialBookmark) {
- if (!(this.initialized && this.historyUnlocked)) {
- return;
- }
- if (params.dest && !params.hash) {
- params.hash = (this.current.hash && this.current.dest &&
- this.current.dest === params.dest) ?
- this.current.hash :
- PDFView.getDestinationHash(params.dest).split('#')[1];
- }
- if (params.page) {
- params.page |= 0;
- }
- if (isInitialBookmark) {
- var target = window.history.state.target;
- if (!target) {
- // Invoked when the user specifies an initial bookmark,
- // thus setting PDFView.initialBookmark, when the document is loaded.
- this._pushToHistory(params, false);
- this.previousHash = window.location.hash.substring(1);
- }
- this.updatePreviousBookmark = this.nextHashParam ? false : true;
- if (target) {
- // If the current document is reloaded,
- // avoid creating duplicate entries in the history.
- this._updatePreviousBookmark();
- }
- return;
- }
- if (this.nextHashParam && this.nextHashParam === params.hash) {
- this.nextHashParam = null;
- this.updatePreviousBookmark = true;
- return;
- }
-
- if (params.hash) {
- if (this.current.hash) {
- if (this.current.hash !== params.hash) {
- this._pushToHistory(params, true);
- } else {
- if (!this.current.page && params.page) {
- this._pushToHistory(params, false, true);
- }
- this.updatePreviousBookmark = true;
- }
- } else {
- this._pushToHistory(params, true);
- }
- } else if (this.current.page && params.page &&
- this.current.page !== params.page) {
- this._pushToHistory(params, true);
- }
- },
-
- _getPreviousParams: function pdfHistory_getPreviousParams(onlyCheckPage,
- beforeUnload) {
- if (!(this.currentBookmark && this.currentPage)) {
- return null;
- }
- if ((!this.current.dest && !onlyCheckPage) || beforeUnload) {
- if (this.previousBookmark === this.currentBookmark) {
- return null;
- }
- } else if (this.current.page || onlyCheckPage) {
- if (this.previousPage === this.currentPage) {
- return null;
- }
- } else {
- return null;
- }
- var params = { hash: this.currentBookmark, page: this.currentPage };
- if (PDFView.isPresentationMode) {
- params.hash = null;
- }
- return params;
- },
-
- _stateObj: function pdfHistory_stateObj(params) {
- return { fingerprint: this.fingerprint, uid: this.uid, target: params };
- },
-
- _pushToHistory: function pdfHistory_pushToHistory(params,
- addPrevious, overwrite) {
- if (!this.initialized) {
- return;
- }
- if (!params.hash && params.page) {
- params.hash = ('page=' + params.page);
- }
- if (addPrevious && !overwrite) {
- var previousParams = this._getPreviousParams();
- if (previousParams) {
- var replacePrevious = (this.current.hash !== this.previousHash);
- this._pushToHistory(previousParams, false, replacePrevious);
- }
- }
- if (overwrite || this.uid === 0) {
- window.history.replaceState(this._stateObj(params), '', '');
- } else {
- window.history.pushState(this._stateObj(params), '', '');
- }
- this.currentUid = this.uid++;
- this.current = params;
- this.updatePreviousBookmark = true;
- },
-
- _goTo: function pdfHistory_goTo(state) {
- if (!(this.initialized && this.historyUnlocked &&
- this._isStateObjectDefined(state))) {
- return;
- }
- if (!this.reInitialized && state.uid < this.currentUid) {
- var previousParams = this._getPreviousParams(true);
- if (previousParams) {
- this._pushToHistory(this.current, false);
- this._pushToHistory(previousParams, false);
- this.currentUid = state.uid;
- window.history.back();
- return;
- }
- }
- this.historyUnlocked = false;
-
- if (state.target.dest) {
- PDFView.navigateTo(state.target.dest);
- } else {
- PDFView.setHash(state.target.hash);
- }
- this.currentUid = state.uid;
- if (state.uid > this.uid) {
- this.uid = state.uid;
- }
- this.current = state.target;
- this.updatePreviousBookmark = true;
-
- var currentHash = window.location.hash.substring(1);
- if (this.previousHash !== currentHash) {
- this.allowHashChange = false;
- }
- this.previousHash = currentHash;
-
- this.historyUnlocked = true;
- },
-
- back: function pdfHistoryBack() {
- this.go(-1);
- },
-
- forward: function pdfHistoryForward() {
- this.go(1);
- },
-
- go: function pdfHistoryGo(direction) {
- if (this.initialized && this.historyUnlocked) {
- var state = window.history.state;
- if (direction === -1 && state && state.uid > 0) {
- window.history.back();
- } else if (direction === 1 && state && state.uid < (this.uid - 1)) {
- window.history.forward();
- }
- }
- }
-};
+//#include pdf_history.js
var PDFView = {
pages: [],