diff --git a/src/core/annotation.js b/src/core/annotation.js index 3ba5e32ea..b5bc36a23 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -346,6 +346,24 @@ var Annotation = (function AnnotationClosure() { } }, + /** + * Prepare the annotation for working with a popup in the display layer. + * + * @private + * @memberof Annotation + * @param {Dict} dict - The annotation's data dictionary + */ + _preparePopup: function Annotation_preparePopup(dict) { + if (!dict.has('C')) { + // Fall back to the default background color. + this.data.color = null; + } + + this.data.hasPopup = dict.has('Popup'); + this.data.title = stringToPDFString(dict.get('T') || ''); + this.data.contents = stringToPDFString(dict.get('Contents') || ''); + }, + loadResources: function Annotation_loadResources(keys) { return new Promise(function (resolve, reject) { this.appearance.dict.getAsync('Resources').then(function (resources) { @@ -663,23 +681,15 @@ var TextAnnotation = (function TextAnnotationClosure() { this.data.annotationType = AnnotationType.TEXT; - var dict = parameters.dict; if (this.data.hasAppearance) { this.data.name = 'NoIcon'; } else { this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE; this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE; - this.data.name = dict.has('Name') ? dict.get('Name').name : 'Note'; + this.data.name = parameters.dict.has('Name') ? + parameters.dict.get('Name').name : 'Note'; } - - if (!dict.has('C')) { - // Fall back to the default background color. - this.data.color = null; - } - - this.data.hasPopup = dict.has('Popup'); - this.data.title = stringToPDFString(dict.get('T') || ''); - this.data.contents = stringToPDFString(dict.get('Contents') || ''); + this._preparePopup(parameters.dict); } Util.inherit(TextAnnotation, Annotation, {}); @@ -798,7 +808,7 @@ var HighlightAnnotation = (function HighlightAnnotationClosure() { Annotation.call(this, parameters); this.data.annotationType = AnnotationType.HIGHLIGHT; - this.data.hasPopup = parameters.dict.has('Popup'); + this._preparePopup(parameters.dict); // PDF viewers completely ignore any border styles. this.data.borderStyle.setWidth(0); @@ -814,7 +824,7 @@ var UnderlineAnnotation = (function UnderlineAnnotationClosure() { Annotation.call(this, parameters); this.data.annotationType = AnnotationType.UNDERLINE; - this.data.hasPopup = parameters.dict.has('Popup'); + this._preparePopup(parameters.dict); // PDF viewers completely ignore any border styles. this.data.borderStyle.setWidth(0); @@ -830,7 +840,7 @@ var SquigglyAnnotation = (function SquigglyAnnotationClosure() { Annotation.call(this, parameters); this.data.annotationType = AnnotationType.SQUIGGLY; - this.data.hasPopup = parameters.dict.has('Popup'); + this._preparePopup(parameters.dict); // PDF viewers completely ignore any border styles. this.data.borderStyle.setWidth(0); @@ -846,7 +856,7 @@ var StrikeOutAnnotation = (function StrikeOutAnnotationClosure() { Annotation.call(this, parameters); this.data.annotationType = AnnotationType.STRIKEOUT; - this.data.hasPopup = parameters.dict.has('Popup'); + this._preparePopup(parameters.dict); // PDF viewers completely ignore any border styles. this.data.borderStyle.setWidth(0); @@ -861,20 +871,11 @@ var FileAttachmentAnnotation = (function FileAttachmentAnnotationClosure() { function FileAttachmentAnnotation(parameters) { Annotation.call(this, parameters); - var dict = parameters.dict; - var file = new FileSpec(dict.get('FS'), parameters.xref); + var file = new FileSpec(parameters.dict.get('FS'), parameters.xref); this.data.annotationType = AnnotationType.FILEATTACHMENT; this.data.file = file.serializable; - - if (!dict.has('C')) { - // Fall back to the default background color. - this.data.color = null; - } - - this.data.hasPopup = dict.has('Popup'); - this.data.title = stringToPDFString(dict.get('T') || ''); - this.data.contents = stringToPDFString(dict.get('Contents') || ''); + this._preparePopup(parameters.dict); } Util.inherit(FileAttachmentAnnotation, Annotation, {}); diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index 303487b81..ea038f2bb 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -205,6 +205,43 @@ var AnnotationElement = (function AnnotationElementClosure() { return container; }, + /** + * Create a popup for the annotation's HTML element. This is used for + * annotations that do not have a Popup entry in the dictionary, but + * are of a type that works with popups (such as Highlight annotations). + * + * @private + * @param {HTMLSectionElement} container + * @param {HTMLDivElement|HTMLImageElement|null} trigger + * @param {Object} data + * @memberof AnnotationElement + */ + _createPopup: + function AnnotationElement_createPopup(container, trigger, data) { + // If no trigger element is specified, create it. + if (!trigger) { + trigger = document.createElement('div'); + trigger.style.height = container.style.height; + trigger.style.width = container.style.width; + container.appendChild(trigger); + } + + var popupElement = new PopupElement({ + container: container, + trigger: trigger, + color: data.color, + title: data.title, + contents: data.contents, + hideWrapper: true + }); + var popup = popupElement.render(); + + // Position the popup next to the annotation's container. + popup.style.left = container.style.width; + + container.appendChild(popup); + }, + /** * Render the annotation's HTML element in the empty container. * @@ -333,20 +370,7 @@ var TextAnnotationElement = (function TextAnnotationElementClosure() { image.dataset.l10nArgs = JSON.stringify({type: this.data.name}); if (!this.data.hasPopup) { - var popupElement = new PopupElement({ - container: this.container, - trigger: image, - color: this.data.color, - title: this.data.title, - contents: this.data.contents, - hideWrapper: true - }); - var popup = popupElement.render(); - - // Position the popup next to the Text annotation's container. - popup.style.left = image.style.width; - - this.container.appendChild(popup); + this._createPopup(this.container, image, this.data); } this.container.appendChild(image); @@ -623,7 +647,8 @@ var PopupElement = (function PopupElementClosure() { var HighlightAnnotationElement = ( function HighlightAnnotationElementClosure() { function HighlightAnnotationElement(parameters) { - var isRenderable = parameters.data.hasPopup; + var isRenderable = !!(parameters.data.hasPopup || + parameters.data.title || parameters.data.contents); AnnotationElement.call(this, parameters, isRenderable); } @@ -637,6 +662,11 @@ var HighlightAnnotationElement = ( */ render: function HighlightAnnotationElement_render() { this.container.className = 'highlightAnnotation'; + + if (!this.data.hasPopup) { + this._createPopup(this.container, null, this.data); + } + return this.container; } }); @@ -651,7 +681,8 @@ var HighlightAnnotationElement = ( var UnderlineAnnotationElement = ( function UnderlineAnnotationElementClosure() { function UnderlineAnnotationElement(parameters) { - var isRenderable = parameters.data.hasPopup; + var isRenderable = !!(parameters.data.hasPopup || + parameters.data.title || parameters.data.contents); AnnotationElement.call(this, parameters, isRenderable); } @@ -665,6 +696,11 @@ var UnderlineAnnotationElement = ( */ render: function UnderlineAnnotationElement_render() { this.container.className = 'underlineAnnotation'; + + if (!this.data.hasPopup) { + this._createPopup(this.container, null, this.data); + } + return this.container; } }); @@ -678,7 +714,8 @@ var UnderlineAnnotationElement = ( */ var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() { function SquigglyAnnotationElement(parameters) { - var isRenderable = parameters.data.hasPopup; + var isRenderable = !!(parameters.data.hasPopup || + parameters.data.title || parameters.data.contents); AnnotationElement.call(this, parameters, isRenderable); } @@ -692,6 +729,11 @@ var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() { */ render: function SquigglyAnnotationElement_render() { this.container.className = 'squigglyAnnotation'; + + if (!this.data.hasPopup) { + this._createPopup(this.container, null, this.data); + } + return this.container; } }); @@ -706,7 +748,8 @@ var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() { var StrikeOutAnnotationElement = ( function StrikeOutAnnotationElementClosure() { function StrikeOutAnnotationElement(parameters) { - var isRenderable = parameters.data.hasPopup; + var isRenderable = !!(parameters.data.hasPopup || + parameters.data.title || parameters.data.contents); AnnotationElement.call(this, parameters, isRenderable); } @@ -720,6 +763,11 @@ var StrikeOutAnnotationElement = ( */ render: function StrikeOutAnnotationElement_render() { this.container.className = 'strikeoutAnnotation'; + + if (!this.data.hasPopup) { + this._createPopup(this.container, null, this.data); + } + return this.container; } }); @@ -758,21 +806,7 @@ var FileAttachmentAnnotationElement = ( trigger.addEventListener('dblclick', this._download.bind(this)); if (!this.data.hasPopup && (this.data.title || this.data.contents)) { - var popupElement = new PopupElement({ - container: this.container, - trigger: trigger, - color: this.data.color, - title: this.data.title, - contents: this.data.contents, - hideWrapper: true - }); - var popup = popupElement.render(); - - // Position the popup next to the FileAttachment annotation's - // container. - popup.style.left = this.container.style.width; - - this.container.appendChild(popup); + this._createPopup(this.container, trigger, this.data); } this.container.appendChild(trigger); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index ec2d0568e..a771174a0 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -211,6 +211,7 @@ !issue6108.pdf !issue6113.pdf !openoffice.pdf +!issue7014.pdf !annotation-link-text-popup.pdf !annotation-text-without-popup.pdf !annotation-underline.pdf diff --git a/test/pdfs/issue7014.pdf b/test/pdfs/issue7014.pdf new file mode 100644 index 000000000..988356f7e Binary files /dev/null and b/test/pdfs/issue7014.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index a6d4c5d09..edb7abf20 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -2730,6 +2730,13 @@ "rounds": 1, "type": "load" }, + { "id": "issue7014", + "file": "pdfs/issue7014.pdf", + "md5": "b410891d7a01af791364e9c530d61b17", + "rounds": 1, + "type": "eq", + "annotations": true + }, { "id": "annotation-link-text-popup", "file": "pdfs/annotation-link-text-popup.pdf", "md5": "4bbf56e81d47232de5f305124ab0ba27",