diff --git a/web/app.js b/web/app.js index 9d03cc234..9b54fcd2c 100644 --- a/web/app.js +++ b/web/app.js @@ -150,6 +150,8 @@ var PDFViewerApplication = { pdfOutlineViewer: null, /** @type {PDFAttachmentViewer} */ pdfAttachmentViewer: null, + /** @type {ViewHistory} */ + store: null, pageRotation: 0, isInitialViewSet: false, animationStartedPromise: null, @@ -603,6 +605,8 @@ var PDFViewerApplication = { this.pdfViewer.setDocument(null); this.pdfLinkService.setDocument(null, null); } + this.store = null; + this.isInitialViewSet = false; this.pdfSidebar.reset(); this.pdfOutlineViewer.reset(); @@ -925,7 +929,6 @@ var PDFViewerApplication = { var onePageRendered = pdfViewer.onePageRendered; this.pageRotation = 0; - this.isInitialViewSet = false; this.pdfThumbnailViewer.setDocument(pdfDocument); @@ -960,7 +963,7 @@ var PDFViewerApplication = { }; store.initializedPromise.then(function resolved() { - var storedHash = null; + var storedHash = null, sidebarView = null; if (self.preferenceShowPreviousViewOnLoad && store.get('exists', false)) { var pageNum = store.get('page', '1'); @@ -971,10 +974,13 @@ var PDFViewerApplication = { storedHash = 'page=' + pageNum + '&zoom=' + zoom + ',' + left + ',' + top; + + sidebarView = store.get('sidebarView', SidebarView.NONE); } else if (self.preferenceDefaultZoomValue) { storedHash = 'page=1&zoom=' + self.preferenceDefaultZoomValue; } - self.setInitialView(storedHash, scale); + self.setInitialView(storedHash, + { scale: scale, sidebarView: sidebarView }); initialParams.hash = storedHash; @@ -985,7 +991,7 @@ var PDFViewerApplication = { } }, function rejected(reason) { console.error(reason); - self.setInitialView(null, scale); + self.setInitialView(null, { scale: scale }); }); // For documents with different page sizes, @@ -1002,7 +1008,7 @@ var PDFViewerApplication = { self.initialBookmark = initialParams.bookmark; self.pdfViewer.currentScaleValue = self.pdfViewer.currentScaleValue; - self.setInitialView(initialParams.hash, scale); + self.setInitialView(initialParams.hash); }); }); @@ -1109,7 +1115,10 @@ var PDFViewerApplication = { }); }, - setInitialView: function pdfViewSetInitialView(storedHash, scale) { + setInitialView: function pdfViewSetInitialView(storedHash, options) { + var scale = options && options.scale; + var sidebarView = options && options.sidebarView; + this.isInitialViewSet = true; // When opening a new file, when one is already loaded in the viewer, @@ -1117,7 +1126,8 @@ var PDFViewerApplication = { document.getElementById('pageNumber').value = this.pdfViewer.currentPageNumber; - this.pdfSidebar.setInitialView(this.preferenceSidebarViewOnLoad); + this.pdfSidebar.setInitialView(this.preferenceSidebarViewOnLoad || + (sidebarView | 0)); if (this.initialDestination) { this.pdfLinkService.navigateTo(this.initialDestination); @@ -1682,23 +1692,40 @@ window.addEventListener('presentationmodechanged', function (e) { active ? PresentationModeState.FULLSCREEN : PresentationModeState.NORMAL; }); +window.addEventListener('sidebarviewchanged', function (evt) { + if (!PDFViewerApplication.initialized) { + return; + } + PDFViewerApplication.pdfRenderingQueue.isThumbnailViewEnabled = + PDFViewerApplication.pdfSidebar.isThumbnailViewVisible; + + var store = PDFViewerApplication.store; + if (!store || !PDFViewerApplication.isInitialViewSet) { + // Only update the storage when the document has been loaded *and* rendered. + return; + } + store.initializedPromise.then(function() { + store.set('sidebarView', evt.detail.view).catch(function() {}); + }); +}, true); + window.addEventListener('updateviewarea', function (evt) { if (!PDFViewerApplication.initialized) { return; } - var location = evt.location; + var location = evt.location, store = PDFViewerApplication.store; - PDFViewerApplication.store.initializedPromise.then(function() { - PDFViewerApplication.store.setMultiple({ - 'exists': true, - 'page': location.pageNumber, - 'zoom': location.scale, - 'scrollLeft': location.left, - 'scrollTop': location.top - }).catch(function() { - // unable to write to storage + if (store) { + store.initializedPromise.then(function() { + store.setMultiple({ + 'exists': true, + 'page': location.pageNumber, + 'zoom': location.scale, + 'scrollLeft': location.left, + 'scrollTop': location.top, + }).catch(function() { /* unable to write to storage */ }); }); - }); + } var href = PDFViewerApplication.pdfLinkService.getAnchorUrl(location.pdfOpenParams); document.getElementById('viewBookmark').href = href; diff --git a/web/pdf_sidebar.js b/web/pdf_sidebar.js index c28b4db49..0cbae2c50 100644 --- a/web/pdf_sidebar.js +++ b/web/pdf_sidebar.js @@ -37,9 +37,9 @@ var SidebarView = { /** * @typedef {Object} PDFSidebarOptions - * @property {PDFViewer} - The document viewer. - * @property {PDFThumbnailViewer} - The thumbnail viewer. - * @property {PDFOutlineViewer} - The outline viewer. + * @property {PDFViewer} pdfViewer - The document viewer. + * @property {PDFThumbnailViewer} pdfThumbnailViewer - The thumbnail viewer. + * @property {PDFOutlineViewer} pdfOutlineViewer - The outline viewer. * @property {HTMLDivElement} mainContainer - The main container * (in which the viewer element is placed). * @property {HTMLDivElement} outerContainer - The outer container @@ -139,17 +139,25 @@ var PDFSidebar = (function PDFSidebarClosure() { this.isInitialViewSet = true; if (this.isOpen && view === SidebarView.NONE) { + this._dispatchEvent(); // If the user has already manually opened the sidebar, // immediately closing it would be bad UX. return; } - this.switchView(view, true); + var isViewPreserved = (view === this.visibleView); + this.switchView(view, /* forceOpen */ true); + + if (isViewPreserved) { + // Prevent dispatching two back-to-back `sidebarviewchanged` events, + // since `this.switchView` dispatched the event if the view changed. + this._dispatchEvent(); + } }, /** * @param {number} view - The sidebar view that should be switched to, * must be one of the values in {SidebarView}. - * @param {boolean} forceOpen - Ensure that the sidebar is opened. + * @param {boolean} forceOpen - (optional) Ensure that the sidebar is open. * The default value is false. */ switchView: function PDFSidebar_switchView(view, forceOpen) { @@ -157,9 +165,7 @@ var PDFSidebar = (function PDFSidebarClosure() { this.close(); return; } - if (forceOpen) { - this.open(); - } + var isViewChanged = (view !== this.active); var shouldForceRendering = false; switch (view) { @@ -172,7 +178,7 @@ var PDFSidebar = (function PDFSidebarClosure() { this.outlineView.classList.add('hidden'); this.attachmentsView.classList.add('hidden'); - if (this.isOpen && view !== this.active) { + if (this.isOpen && isViewChanged) { this._updateThumbnailViewer(); shouldForceRendering = true; } @@ -210,9 +216,17 @@ var PDFSidebar = (function PDFSidebarClosure() { // in order to prevent setting it to an invalid state. this.active = view | 0; + if (forceOpen && !this.isOpen) { + this.open(); + // NOTE: `this.open` will trigger rendering, and dispatch the event. + return; + } if (shouldForceRendering) { this._forceRendering(); } + if (isViewChanged) { + this._dispatchEvent(); + } }, open: function PDFSidebar_open() { @@ -229,6 +243,7 @@ var PDFSidebar = (function PDFSidebarClosure() { this._updateThumbnailViewer(); } this._forceRendering(); + this._dispatchEvent(); }, close: function PDFSidebar_close() { @@ -242,6 +257,7 @@ var PDFSidebar = (function PDFSidebarClosure() { this.outerContainer.classList.remove('sidebarOpen'); this._forceRendering(); + this._dispatchEvent(); }, toggle: function PDFSidebar_toggle() { @@ -252,6 +268,17 @@ var PDFSidebar = (function PDFSidebarClosure() { } }, + /** + * @private + */ + _dispatchEvent: function PDFSidebar_dispatchEvent() { + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('sidebarviewchanged', true, true, { + view: this.visibleView, + }); + this.outerContainer.dispatchEvent(event); + }, + /** * @private */