diff --git a/src/shared/annotation.js b/src/shared/annotation.js index 6c740a677..ff46ab9a5 100644 --- a/src/shared/annotation.js +++ b/src/shared/annotation.js @@ -129,6 +129,7 @@ var Annotation = (function AnnotationClosure() { this.appearance = getDefaultAppearance(dict); data.hasAppearance = !!this.appearance; + data.id = params.ref.num; } Annotation.prototype = { diff --git a/web/page_view.js b/web/page_view.js index d20113ea8..27f01b6c0 100644 --- a/web/page_view.js +++ b/web/page_view.js @@ -68,7 +68,7 @@ var PageView = function pageView(container, id, scale, } }; - this.reset = function pageViewReset() { + this.reset = function pageViewReset(keepAnnotations) { if (this.renderTask) { this.renderTask.cancel(); } @@ -81,14 +81,23 @@ var PageView = function pageView(container, id, scale, var childNodes = div.childNodes; for (var i = div.childNodes.length - 1; i >= 0; i--) { var node = childNodes[i]; - if (this.zoomLayer && this.zoomLayer === node) { + if ((this.zoomLayer && this.zoomLayer === node) || + (keepAnnotations && this.annotationLayer === node)) { continue; } div.removeChild(node); } div.removeAttribute('data-loaded'); - this.annotationLayer = null; + if (keepAnnotations) { + if (this.annotationLayer) { + // Hide annotationLayer until all elements are resized + // so they are not displayed on the already-resized page + this.annotationLayer.setAttribute('hidden', 'true'); + } + } else { + this.annotationLayer = null; + } delete this.canvas; @@ -120,7 +129,7 @@ var PageView = function pageView(container, id, scale, if (this.zoomLayer) { this.cssTransform(this.zoomLayer.firstChild); } - this.reset(); + this.reset(true); }; this.cssTransform = function pageCssTransform(canvas) { @@ -269,60 +278,73 @@ var PageView = function pageView(container, id, scale, } pdfPage.getAnnotations().then(function(annotationsData) { - if (self.annotationLayer) { - // If an annotationLayer already exists, delete it to avoid creating - // duplicate annotations when rapidly re-zooming the document. - pageDiv.removeChild(self.annotationLayer); - self.annotationLayer = null; - } viewport = viewport.clone({ dontFlip: true }); - for (var i = 0; i < annotationsData.length; i++) { - var data = annotationsData[i]; - var annotation = PDFJS.Annotation.fromData(data); - if (!annotation || !annotation.hasHtml()) { - continue; - } + var transform = viewport.transform; + var transformStr = 'matrix(' + transform.join(',') + ')'; + var data, element, i, ii; - var element = annotation.getHtmlElement(pdfPage.commonObjs); - mozL10n.translate(element); - - data = annotation.getData(); - var rect = data.rect; - var view = pdfPage.view; - rect = PDFJS.Util.normalizeRect([ - rect[0], - view[3] - rect[1] + view[1], - rect[2], - view[3] - rect[3] + view[1] - ]); - element.style.left = rect[0] + 'px'; - element.style.top = rect[1] + 'px'; - element.style.position = 'absolute'; - - var transform = viewport.transform; - var transformStr = 'matrix(' + transform.join(',') + ')'; - CustomStyle.setProp('transform', element, transformStr); - var transformOriginStr = -rect[0] + 'px ' + -rect[1] + 'px'; - CustomStyle.setProp('transformOrigin', element, transformOriginStr); - - if (data.subtype === 'Link' && !data.url) { - var link = element.getElementsByTagName('a')[0]; - if (link) { - if (data.action) { - bindNamedAction(link, data.action); - } else { - bindLink(link, ('dest' in data) ? data.dest : null); - } + if (self.annotationLayer) { + // If an annotationLayer already exists, refresh its children's + // transformation matrices + for (i = 0, ii = annotationsData.length; i < ii; i++) { + data = annotationsData[i]; + element = self.annotationLayer.querySelector( + '[data-annotation-id="' + data.id + '"]'); + if (element) { + CustomStyle.setProp('transform', element, transformStr); } } + // See this.reset() + self.annotationLayer.removeAttribute('hidden'); + } else { + for (i = 0, ii = annotationsData.length; i < ii; i++) { + data = annotationsData[i]; + var annotation = PDFJS.Annotation.fromData(data); + if (!annotation || !annotation.hasHtml()) { + continue; + } - if (!self.annotationLayer) { - var annotationLayerDiv = document.createElement('div'); - annotationLayerDiv.className = 'annotationLayer'; - pageDiv.appendChild(annotationLayerDiv); - self.annotationLayer = annotationLayerDiv; + element = annotation.getHtmlElement(pdfPage.commonObjs); + element.setAttribute('data-annotation-id', data.id); + mozL10n.translate(element); + + data = annotation.getData(); + var rect = data.rect; + var view = pdfPage.view; + rect = PDFJS.Util.normalizeRect([ + rect[0], + view[3] - rect[1] + view[1], + rect[2], + view[3] - rect[3] + view[1] + ]); + element.style.left = rect[0] + 'px'; + element.style.top = rect[1] + 'px'; + element.style.position = 'absolute'; + + CustomStyle.setProp('transform', element, transformStr); + var transformOriginStr = -rect[0] + 'px ' + -rect[1] + 'px'; + CustomStyle.setProp('transformOrigin', element, transformOriginStr); + + if (data.subtype === 'Link' && !data.url) { + var link = element.getElementsByTagName('a')[0]; + if (link) { + if (data.action) { + bindNamedAction(link, data.action); + } else { + bindLink(link, ('dest' in data) ? data.dest : null); + } + } + } + + if (!self.annotationLayer) { + var annotationLayerDiv = document.createElement('div'); + annotationLayerDiv.className = 'annotationLayer'; + pageDiv.appendChild(annotationLayerDiv); + self.annotationLayer = annotationLayerDiv; + } + + self.annotationLayer.appendChild(element); } - self.annotationLayer.appendChild(element); } }); } @@ -458,7 +480,12 @@ var PageView = function pageView(container, id, scale, var canvas = document.createElement('canvas'); canvas.id = 'page' + this.id; canvasWrapper.appendChild(canvas); - div.appendChild(canvasWrapper); + if (this.annotationLayer) { + // annotationLayer needs to stay on top + div.insertBefore(canvasWrapper, this.annotationLayer); + } else { + div.appendChild(canvasWrapper); + } this.canvas = canvas; var ctx = canvas.getContext('2d'); @@ -486,7 +513,12 @@ var PageView = function pageView(container, id, scale, textLayerDiv.className = 'textLayer'; textLayerDiv.style.width = canvas.style.width; textLayerDiv.style.height = canvas.style.height; - div.appendChild(textLayerDiv); + if (this.annotationLayer) { + // annotationLayer needs to stay on top + div.insertBefore(textLayerDiv, this.annotationLayer); + } else { + div.appendChild(textLayerDiv); + } } var textLayer = this.textLayer = textLayerDiv ? new TextLayerBuilder({