diff --git a/web/app.js b/web/app.js index 016a0764d..e173c1ded 100644 --- a/web/app.js +++ b/web/app.js @@ -1583,6 +1583,19 @@ function webViewerPageRendered(e) { var pageIndex = pageNumber - 1; var pageView = PDFViewerApplication.pdfViewer.getPageView(pageIndex); + // If the page is still visible when it has finished rendering, + // ensure that the page number input loading indicator is hidden. + if (pageNumber === PDFViewerApplication.page) { + var pageNumberInput = PDFViewerApplication.appConfig.toolbar.pageNumber; + pageNumberInput.classList.remove(PAGE_NUMBER_LOADING_INDICATOR); + } + + // Prevent errors in the edge-case where the PDF document is removed *before* + // the 'pagerendered' event handler is invoked. + if (!pageView) { + return; + } + // Use the rendered page to set the corresponding thumbnail image. if (PDFViewerApplication.pdfSidebar.isThumbnailViewVisible) { var thumbnailView = PDFViewerApplication.pdfThumbnailViewer. @@ -1599,13 +1612,6 @@ function webViewerPageRendered(e) { 'An error occurred while rendering the page.'), pageView.error); } - // If the page is still visible when it has finished rendering, - // ensure that the page number input loading indicator is hidden. - if (pageNumber === PDFViewerApplication.page) { - var pageNumberInput = PDFViewerApplication.appConfig.toolbar.pageNumber; - pageNumberInput.classList.remove(PAGE_NUMBER_LOADING_INDICATOR); - } - //#if !PRODUCTION if (true) { return; @@ -1626,18 +1632,13 @@ function webViewerPageRendered(e) { } function webViewerTextLayerRendered(e) { - var pageIndex = e.pageNumber - 1; - var pageView = PDFViewerApplication.pdfViewer.getPageView(pageIndex); - //#if !PRODUCTION if (true) { return; } //#endif //#if (FIREFOX || MOZCENTRAL) - if (pageView.textLayer && pageView.textLayer.textDivs && - pageView.textLayer.textDivs.length > 0 && - !PDFViewerApplication.supportsDocumentColors) { + if (e.numTextDivs > 0 && !PDFViewerApplication.supportsDocumentColors) { console.error(mozL10n.get('document_colors_not_allowed', null, 'PDF documents are not allowed to use their own colors: ' + '\'Allow pages to choose their own colors\' ' + diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js index ee87bf8b2..4d1be7233 100644 --- a/web/pdf_page_view.js +++ b/web/pdf_page_view.js @@ -92,6 +92,7 @@ var PDFPageView = (function PDFPageViewClosure() { this.textLayerFactory = textLayerFactory; this.annotationLayerFactory = annotationLayerFactory; + this.renderTask = null; this.renderingState = RenderingStates.INITIAL; this.resume = null; @@ -135,11 +136,7 @@ var PDFPageView = (function PDFPageViewClosure() { }, reset: function PDFPageView_reset(keepZoomLayer, keepAnnotations) { - if (this.renderTask) { - this.renderTask.cancel(); - } - this.resume = null; - this.renderingState = RenderingStates.INITIAL; + this.cancelRendering(); var div = this.div; div.style.width = Math.floor(this.viewport.width) + 'px'; @@ -225,6 +222,20 @@ var PDFPageView = (function PDFPageViewClosure() { this.reset(/* keepZoomLayer = */ true, /* keepAnnotations = */ true); }, + cancelRendering: function PDFPageView_cancelRendering() { + if (this.renderTask) { + this.renderTask.cancel(); + this.renderTask = null; + } + this.renderingState = RenderingStates.INITIAL; + this.resume = null; + + if (this.textLayer) { + this.textLayer.cancel(); + this.textLayer = null; + } + }, + /** * Called when moved in the parent's container. */ @@ -320,6 +331,7 @@ var PDFPageView = (function PDFPageViewClosure() { draw: function PDFPageView_draw() { if (this.renderingState !== RenderingStates.INITIAL) { console.error('Must be in new state before drawing'); + this.reset(); // Ensure that we reset all state to prevent issues. } this.renderingState = RenderingStates.RUNNING; diff --git a/web/pdf_thumbnail_view.js b/web/pdf_thumbnail_view.js index 1d96af77b..c91b9830b 100644 --- a/web/pdf_thumbnail_view.js +++ b/web/pdf_thumbnail_view.js @@ -98,8 +98,9 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() { this.linkService = linkService; this.renderingQueue = renderingQueue; - this.resume = null; + this.renderTask = null; this.renderingState = RenderingStates.INITIAL; + this.resume = null; this.disableCanvasToImageConversion = disableCanvasToImageConversion; this.pageWidth = this.viewport.width; @@ -151,11 +152,7 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() { }, reset: function PDFThumbnailView_reset() { - if (this.renderTask) { - this.renderTask.cancel(); - } - this.resume = null; - this.renderingState = RenderingStates.INITIAL; + this.cancelRendering(); this.pageWidth = this.viewport.width; this.pageHeight = this.viewport.height; @@ -199,6 +196,15 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() { this.reset(); }, + cancelRendering: function PDFThumbnailView_cancelRendering() { + if (this.renderTask) { + this.renderTask.cancel(); + this.renderTask = null; + } + this.renderingState = RenderingStates.INITIAL; + this.resume = null; + }, + /** * @private */ diff --git a/web/pdf_thumbnail_viewer.js b/web/pdf_thumbnail_viewer.js index 54c6bf42f..aa4181195 100644 --- a/web/pdf_thumbnail_viewer.js +++ b/web/pdf_thumbnail_viewer.js @@ -135,15 +135,14 @@ var PDFThumbnailViewer = (function PDFThumbnailViewerClosure() { this.thumbnails = []; this._pagesRotation = 0; this._pagesRequests = []; + + // Remove the thumbnails from the DOM. + this.container.textContent = ''; }, setDocument: function PDFThumbnailViewer_setDocument(pdfDocument) { if (this.pdfDocument) { - // cleanup of the elements and views - var thumbsView = this.container; - while (thumbsView.hasChildNodes()) { - thumbsView.removeChild(thumbsView.lastChild); - } + this._cancelRendering(); this._resetView(); } @@ -169,6 +168,17 @@ var PDFThumbnailViewer = (function PDFThumbnailViewerClosure() { }.bind(this)); }, + /** + * @private + */ + _cancelRendering: function PDFThumbnailViewer_cancelRendering() { + for (var i = 0, ii = this.thumbnails.length; i < ii; i++) { + if (this.thumbnails[i]) { + this.thumbnails[i].cancelRendering(); + } + } + }, + /** * @param {PDFThumbnailView} thumbView * @returns {PDFPage} diff --git a/web/pdf_viewer.js b/web/pdf_viewer.js index 6b47781c3..c6abb724f 100644 --- a/web/pdf_viewer.js +++ b/web/pdf_viewer.js @@ -299,6 +299,7 @@ var PDFViewer = (function pdfViewer() { */ setDocument: function (pdfDocument) { if (this.pdfDocument) { + this._cancelRendering(); this._resetView(); } @@ -424,10 +425,8 @@ var PDFViewer = (function pdfViewer() { this._pagesRequests = []; this._pageViewsReady = false; - var container = this.viewer; - while (container.hasChildNodes()) { - container.removeChild(container.lastChild); - } + // Remove the pages from the DOM. + this.viewer.textContent = ''; }, _scrollUpdate: function PDFViewer_scrollUpdate() { @@ -802,6 +801,17 @@ var PDFViewer = (function pdfViewer() { } }, + /** + * @private + */ + _cancelRendering: function PDFViewer_cancelRendering() { + for (var i = 0, ii = this._pages.length; i < ii; i++) { + if (this._pages[i]) { + this._pages[i].cancelRendering(); + } + } + }, + /** * @param {PDFPageView} pageView * @returns {PDFPage} diff --git a/web/text_layer_builder.js b/web/text_layer_builder.js index 0a03a428a..34791d05a 100644 --- a/web/text_layer_builder.js +++ b/web/text_layer_builder.js @@ -18,8 +18,7 @@ (function (root, factory) { if (typeof define === 'function' && define.amd) { define('pdfjs-web/text_layer_builder', ['exports', 'pdfjs-web/dom_events', - 'pdfjs-web/pdfjs'], - factory); + 'pdfjs-web/pdfjs'], factory); } else if (typeof exports !== 'undefined') { factory(exports, require('./dom_events.js'), require('./pdfjs.js')); } else { @@ -52,8 +51,8 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() { function TextLayerBuilder(options) { this.textLayerDiv = options.textLayerDiv; this.eventBus = options.eventBus || domEvents.getGlobalEventBus(); + this.textContent = null; this.renderingDone = false; - this.divContentDone = false; this.pageIdx = options.pageIndex; this.pageNumber = this.pageIdx + 1; this.matches = []; @@ -66,6 +65,9 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() { } TextLayerBuilder.prototype = { + /** + * @private + */ _finishRendering: function TextLayerBuilder_finishRendering() { this.renderingDone = true; @@ -77,7 +79,8 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() { this.eventBus.dispatch('textlayerrendered', { source: this, - pageNumber: this.pageNumber + pageNumber: this.pageNumber, + numTextDivs: this.textDivs.length, }); }, @@ -87,14 +90,10 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() { * for specified amount of ms. */ render: function TextLayerBuilder_render(timeout) { - if (!this.divContentDone || this.renderingDone) { + if (!this.textContent || this.renderingDone) { return; } - - if (this.textLayerRenderTask) { - this.textLayerRenderTask.cancel(); - this.textLayerRenderTask = null; - } + this.cancel(); this.textDivs = []; var textLayerFrag = document.createDocumentFragment(); @@ -111,17 +110,23 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() { this._finishRendering(); this.updateMatches(); }.bind(this), function (reason) { - // canceled or failed to render text layer -- skipping errors + // cancelled or failed to render text layer -- skipping errors }); }, - setTextContent: function TextLayerBuilder_setTextContent(textContent) { + /** + * Cancels rendering of the text layer. + */ + cancel: function TextLayerBuilder_cancel() { if (this.textLayerRenderTask) { this.textLayerRenderTask.cancel(); this.textLayerRenderTask = null; } + }, + + setTextContent: function TextLayerBuilder_setTextContent(textContent) { + this.cancel(); this.textContent = textContent; - this.divContentDone = true; }, convertMatches: function TextLayerBuilder_convertMatches(matches, @@ -324,6 +329,7 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() { var div = this.textLayerDiv; var self = this; var expandDivsTimer = null; + div.addEventListener('mousedown', function (e) { if (self.enhanceTextSelection && self.textLayerRenderTask) { self.textLayerRenderTask.expandTextDivs(true); @@ -357,11 +363,14 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() { //#endif end.classList.add('active'); }); + div.addEventListener('mouseup', function (e) { if (self.enhanceTextSelection && self.textLayerRenderTask) { //#if !(MOZCENTRAL || FIREFOX) expandDivsTimer = setTimeout(function() { - self.textLayerRenderTask.expandTextDivs(false); + if (self.textLayerRenderTask) { + self.textLayerRenderTask.expandTextDivs(false); + } expandDivsTimer = null; }, EXPAND_DIVS_TIMEOUT); //#else