Skip to content

Commit

Permalink
Move PDFHistory from viewer.js to its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonas authored and Jonas committed Jul 18, 2013
1 parent af8e96c commit 09e0c9b
Show file tree
Hide file tree
Showing 3 changed files with 342 additions and 320 deletions.
338 changes: 338 additions & 0 deletions web/pdf_history.js
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
};
1 change: 1 addition & 0 deletions web/viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<script type="text/javascript" src="text_layer_builder.js"></script>
<script type="text/javascript" src="pdf_find_bar.js"></script>
<script type="text/javascript" src="pdf_find_controller.js"></script>
<script type="text/javascript" src="pdf_history.js"></script>
<!--#endif-->

<script type="text/javascript" src="debugger.js"></script>
Expand Down
Loading

0 comments on commit 09e0c9b

Please sign in to comment.