forked from mozilla/pdf.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move PDFHistory from viewer.js to its own file
- Loading branch information
Jonas
authored and
Jonas
committed
Jul 18, 2013
1 parent
af8e96c
commit 09e0c9b
Showing
3 changed files
with
342 additions
and
320 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.