1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-21 15:48:06 +02:00

Merge pull request #7341 from Snuffleupagus/getDestinationHash-Array

[api-minor] Improve handling of links that are using explicit destination arrays
This commit is contained in:
Tim van der Meij 2016-06-09 00:29:10 +02:00
commit f97d52182a
10 changed files with 201 additions and 44 deletions

View file

@ -857,6 +857,7 @@ var PDFViewerApplication = {
pdfViewer.setDocument(pdfDocument);
var firstPagePromise = pdfViewer.firstPagePromise;
var pagesPromise = pdfViewer.pagesPromise;
var onePageRendered = pdfViewer.onePageRendered;
this.pageRotation = 0;
@ -962,9 +963,8 @@ var PDFViewerApplication = {
}
});
// outline depends on pagesRefMap
var promises = [pagesPromise, this.animationStartedPromise];
Promise.all(promises).then(function() {
Promise.all([onePageRendered, this.animationStartedPromise]).then(
function() {
pdfDocument.getOutline().then(function(outline) {
self.pdfOutlineViewer.render({ outline: outline });
});

View file

@ -29,6 +29,11 @@
var parseQueryString = uiUtils.parseQueryString;
var PageNumberRegExp = /^\d+$/;
function isPageNumber(str) {
return PageNumberRegExp.test(str);
}
/**
* @typedef {Object} PDFLinkServiceOptions
* @property {EventBus} eventBus - The application event bus.
@ -40,7 +45,7 @@ var parseQueryString = uiUtils.parseQueryString;
* @class
* @implements {IPDFLinkService}
*/
var PDFLinkService = (function () {
var PDFLinkService = (function PDFLinkServiceClosure() {
/**
* @constructs PDFLinkService
* @param {PDFLinkServiceOptions} options
@ -100,7 +105,7 @@ var PDFLinkService = (function () {
var self = this;
var goToDestination = function(destRef) {
// dest array looks like that: <page-ref> </XYZ|FitXXX> <args..>
// dest array looks like that: <page-ref> </XYZ|/FitXXX> <args..>
var pageNumber = destRef instanceof Object ?
self._pagesRefCache[destRef.num + ' ' + destRef.gen + ' R'] :
(destRef + 1);
@ -150,30 +155,15 @@ var PDFLinkService = (function () {
*/
getDestinationHash: function PDFLinkService_getDestinationHash(dest) {
if (typeof dest === 'string') {
return this.getAnchorUrl('#' + escape(dest));
// In practice, a named destination may contain only a number.
// If that happens, use the '#nameddest=' form to avoid the link
// redirecting to a page, instead of the correct destination.
return this.getAnchorUrl(
'#' + (isPageNumber(dest) ? 'nameddest=' : '') + escape(dest));
}
if (dest instanceof Array) {
var destRef = dest[0]; // see navigateTo method for dest format
var pageNumber = destRef instanceof Object ?
this._pagesRefCache[destRef.num + ' ' + destRef.gen + ' R'] :
(destRef + 1);
if (pageNumber) {
var pdfOpenParams = this.getAnchorUrl('#page=' + pageNumber);
var destKind = dest[1];
if (typeof destKind === 'object' && 'name' in destKind &&
destKind.name === 'XYZ') {
var scale = (dest[4] || this.pdfViewer.currentScaleValue);
var scaleNumber = parseFloat(scale);
if (scaleNumber) {
scale = scaleNumber * 100;
}
pdfOpenParams += '&zoom=' + scale;
if (dest[2] || dest[3]) {
pdfOpenParams += ',' + (dest[2] || 0) + ',' + (dest[3] || 0);
}
}
return pdfOpenParams;
}
var str = JSON.stringify(dest);
return this.getAnchorUrl('#' + escape(str));
}
return this.getAnchorUrl('');
},
@ -192,6 +182,7 @@ var PDFLinkService = (function () {
* @param {string} hash
*/
setHash: function PDFLinkService_setHash(hash) {
var pageNumber, dest;
if (hash.indexOf('=') >= 0) {
var params = parseQueryString(hash);
if ('search' in params) {
@ -209,7 +200,6 @@ var PDFLinkService = (function () {
this.navigateTo(params.nameddest);
return;
}
var pageNumber, dest;
if ('page' in params) {
pageNumber = (params.page | 0) || 1;
}
@ -259,13 +249,23 @@ var PDFLinkService = (function () {
mode: params.pagemode
});
}
} else if (/^\d+$/.test(hash)) { // page number
this.page = hash;
} else { // named destination
if (this.pdfHistory) {
this.pdfHistory.updateNextHashParam(unescape(hash));
} else if (isPageNumber(hash)) { // Page number.
this.page = hash | 0;
} else { // Named (or explicit) destination.
dest = unescape(hash);
try {
dest = JSON.parse(dest);
} catch (ex) {}
if (typeof dest === 'string' || isValidExplicitDestination(dest)) {
if (this.pdfHistory) {
this.pdfHistory.updateNextHashParam(dest);
}
this.navigateTo(dest);
return;
}
this.navigateTo(unescape(hash));
console.error('PDFLinkService_setHash: \'' + unescape(hash) +
'\' is not a valid destination.');
}
},
@ -323,6 +323,60 @@ var PDFLinkService = (function () {
}
};
function isValidExplicitDestination(dest) {
if (!(dest instanceof Array)) {
return false;
}
var destLength = dest.length, allowNull = true;
if (destLength < 2) {
return false;
}
var page = dest[0];
if (!(typeof page === 'object' &&
typeof page.num === 'number' && (page.num | 0) === page.num &&
typeof page.gen === 'number' && (page.gen | 0) === page.gen) &&
!(typeof page === 'number' && (page | 0) === page && page >= 0)) {
return false;
}
var zoom = dest[1];
if (!(typeof zoom === 'object' && typeof zoom.name === 'string')) {
return false;
}
switch (zoom.name) {
case 'XYZ':
if (destLength !== 5) {
return false;
}
break;
case 'Fit':
case 'FitB':
return destLength === 2;
case 'FitH':
case 'FitBH':
case 'FitV':
case 'FitBV':
if (destLength !== 3) {
return false;
}
break;
case 'FitR':
if (destLength !== 6) {
return false;
}
allowNull = false;
break;
default:
return false;
}
for (var i = 2; i < destLength; i++) {
var param = dest[i];
if (!(typeof param === 'number' || (allowNull && param === null))) {
return false;
}
}
return true;
}
return PDFLinkService;
})();

View file

@ -587,6 +587,8 @@ var PDFViewer = (function pdfViewer() {
scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
break;
default:
console.error('PDFViewer_scrollPageIntoView: \'' + dest[1].name +
'\' is not a valid destination type.');
return;
}