diff --git a/src/core/obj.js b/src/core/obj.js index c4659799983b3..98d6d3d6d3e06 100644 --- a/src/core/obj.js +++ b/src/core/obj.js @@ -47,6 +47,7 @@ var shadow = sharedUtil.shadow; var stringToPDFString = sharedUtil.stringToPDFString; var stringToUTF8String = sharedUtil.stringToUTF8String; var warn = sharedUtil.warn; +var isValidUrl = sharedUtil.isValidUrl; var Ref = corePrimitives.Ref; var RefSet = corePrimitives.RefSet; var RefSetCache = corePrimitives.RefSetCache; @@ -146,9 +147,17 @@ var Catalog = (function CatalogClosure() { if (!outlineDict.has('Title')) { error('Invalid outline item'); } - var dest = outlineDict.get('A'); - if (dest) { - dest = dest.get('D'); + var actionDict = outlineDict.get('A'), dest = null, url = null; + if (actionDict) { + var destEntry = actionDict.get('D'); + if (destEntry) { + dest = destEntry; + } else { + var uriEntry = actionDict.get('URI'); + if (isString(uriEntry) && isValidUrl(uriEntry, false)) { + url = uriEntry; + } + } } else if (outlineDict.has('Dest')) { dest = outlineDict.getRaw('Dest'); if (isName(dest)) { @@ -158,6 +167,7 @@ var Catalog = (function CatalogClosure() { var title = outlineDict.get('Title'); var outlineItem = { dest: dest, + url: url, title: stringToPDFString(title), color: outlineDict.get('C') || [0, 0, 0], count: outlineDict.get('Count'), diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index cd4fffd5c39b0..2107012c1a165 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -31,9 +31,7 @@ var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType; var AnnotationType = sharedUtil.AnnotationType; var Util = sharedUtil.Util; -var isExternalLinkTargetSet = sharedUtil.isExternalLinkTargetSet; -var LinkTargetStringMap = sharedUtil.LinkTargetStringMap; -var removeNullCharacters = sharedUtil.removeNullCharacters; +var addLinkAttributes = sharedUtil.addLinkAttributes; var warn = sharedUtil.warn; var CustomStyle = displayDOMUtils.CustomStyle; @@ -233,17 +231,7 @@ var LinkAnnotationElement = (function LinkAnnotationElementClosure() { this.container.className = 'linkAnnotation'; var link = document.createElement('a'); - link.href = link.title = (this.data.url ? - removeNullCharacters(this.data.url) : ''); - - if (this.data.url && isExternalLinkTargetSet()) { - link.target = LinkTargetStringMap[PDFJS.externalLinkTarget]; - } - - // Strip referrer from the URL. - if (this.data.url) { - link.rel = PDFJS.externalLinkRel; - } + addLinkAttributes(link, { url: this.data.url }); if (!this.data.url) { if (this.data.action) { diff --git a/src/display/api.js b/src/display/api.js index 864a80ebed379..9a1ad451a630b 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -714,6 +714,7 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { * italic: boolean, * color: rgb array, * dest: dest obj, + * url: string, * items: array of more items like this * }, * ... diff --git a/src/shared/util.js b/src/shared/util.js index 286968881e39b..23b3592274373 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -318,6 +318,26 @@ function isValidUrl(url, allowRelative) { } PDFJS.isValidUrl = isValidUrl; +/** + * Adds various attributes (href, title, target, rel) to hyperlinks. + * @param {HTMLLinkElement} link - The link element. + * @param {Object} params - An object with the properties: + * @param {string} params.url - An absolute URL. + */ +function addLinkAttributes(link, params) { + var url = params && params.url; + link.href = link.title = (url ? removeNullCharacters(url) : ''); + + if (url) { + if (isExternalLinkTargetSet()) { + link.target = LinkTargetStringMap[PDFJS.externalLinkTarget]; + } + // Strip referrer from the URL. + link.rel = PDFJS.externalLinkRel; + } +} +PDFJS.addLinkAttributes = addLinkAttributes; + function shadow(obj, prop, value) { Object.defineProperty(obj, prop, { value: value, enumerable: true, @@ -2292,6 +2312,7 @@ exports.isInt = isInt; exports.isNum = isNum; exports.isString = isString; exports.isValidUrl = isValidUrl; +exports.addLinkAttributes = addLinkAttributes; exports.loadJpegStream = loadJpegStream; exports.log2 = log2; exports.readInt8 = readInt8; diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 23b656a16c26e..528ed8ddd28d2 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -10,6 +10,7 @@ !issue1155r.pdf !issue2391-1.pdf !issue2391-2.pdf +!issue3214.pdf !issue4665.pdf !issue5801.pdf !issue5946.pdf diff --git a/test/pdfs/issue3214.pdf b/test/pdfs/issue3214.pdf new file mode 100644 index 0000000000000..17a4f1445907d Binary files /dev/null and b/test/pdfs/issue3214.pdf differ diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index 705195400fcd3..a1213bec0c9bc 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -371,11 +371,33 @@ describe('api', function() { var promise = doc.getOutline(); waitsForPromiseResolved(promise, function(outline) { // Two top level entries. + expect(outline instanceof Array).toEqual(true); expect(outline.length).toEqual(2); // Make sure some basic attributes are set. - expect(outline[1].title).toEqual('Chapter 1'); - expect(outline[1].items.length).toEqual(1); - expect(outline[1].items[0].title).toEqual('Paragraph 1.1'); + var outlineItem = outline[1]; + expect(outlineItem.title).toEqual('Chapter 1'); + expect(outlineItem.dest instanceof Array).toEqual(true); + expect(outlineItem.url).toEqual(null); + + expect(outlineItem.items.length).toEqual(1); + expect(outlineItem.items[0].title).toEqual('Paragraph 1.1'); + }); + }); + it('gets outline containing a url', function() { + var pdfUrl = combineUrl(window.location.href, '../pdfs/issue3214.pdf'); + var loadingTask = PDFJS.getDocument(pdfUrl); + + loadingTask.promise.then(function (pdfDocument) { + pdfDocument.getOutline().then(function (outline) { + expect(outline instanceof Array).toEqual(true); + expect(outline.length).toEqual(5); + + var outlineItem = outline[2]; + expect(outlineItem.dest).toEqual(null); + expect(outlineItem.url).toEqual('http://google.com'); + + loadingTask.destroy(); // Cleanup the worker. + }); }); }); it('gets metadata', function() { diff --git a/web/pdf_outline_view.js b/web/pdf_outline_view.js index c82131da74c49..132b7d188247c 100644 --- a/web/pdf_outline_view.js +++ b/web/pdf_outline_view.js @@ -62,6 +62,10 @@ var PDFOutlineView = (function PDFOutlineViewClosure() { * @private */ _bindLink: function PDFOutlineView_bindLink(element, item) { + if (item.url) { + PDFJS.addLinkAttributes(element, { url: item.url }); + return; + } var linkService = this.linkService; element.href = linkService.getDestinationHash(item.dest); element.onclick = function goToDestination(e) {