diff --git a/web/pdf_attachment_view.js b/web/pdf_attachment_viewer.js similarity index 69% rename from web/pdf_attachment_view.js rename to web/pdf_attachment_viewer.js index a2757c637..e5a1d541d 100644 --- a/web/pdf_attachment_view.js +++ b/web/pdf_attachment_viewer.js @@ -17,28 +17,34 @@ 'use strict'; /** - * @typedef {Object} PDFAttachmentViewOptions + * @typedef {Object} PDFAttachmentViewerOptions * @property {HTMLDivElement} container - The viewer element. - * @property {Array} attachments - An array of attachment objects. * @property {DownloadManager} downloadManager - The download manager. */ +/** + * @typedef {Object} PDFAttachmentViewerRenderParameters + * @property {Array|null} attachments - An array of attachment objects. + */ + /** * @class */ -var PDFAttachmentView = (function PDFAttachmentViewClosure() { +var PDFAttachmentViewer = (function PDFAttachmentViewerClosure() { /** - * @constructs PDFAttachmentView - * @param {PDFAttachmentViewOptions} options + * @constructs PDFAttachmentViewer + * @param {PDFAttachmentViewerOptions} options */ - function PDFAttachmentView(options) { + function PDFAttachmentViewer(options) { + this.attachments = null; this.container = options.container; - this.attachments = options.attachments; this.downloadManager = options.downloadManager; } - PDFAttachmentView.prototype = { - reset: function PDFAttachmentView_reset() { + PDFAttachmentViewer.prototype = { + reset: function PDFAttachmentViewer_reset() { + this.attachments = null; + var container = this.container; while (container.firstChild) { container.removeChild(container.firstChild); @@ -48,7 +54,8 @@ var PDFAttachmentView = (function PDFAttachmentViewClosure() { /** * @private */ - _dispatchEvent: function PDFAttachmentView_dispatchEvent(attachmentsCount) { + _dispatchEvent: + function PDFAttachmentViewer_dispatchEvent(attachmentsCount) { var event = document.createEvent('CustomEvent'); event.initCustomEvent('attachmentsloaded', true, true, { attachmentsCount: attachmentsCount @@ -59,18 +66,25 @@ var PDFAttachmentView = (function PDFAttachmentViewClosure() { /** * @private */ - _bindLink: function PDFAttachmentView_bindLink(button, content, filename) { + _bindLink: + function PDFAttachmentViewer_bindLink(button, content, filename) { button.onclick = function downloadFile(e) { this.downloadManager.downloadData(content, filename, ''); return false; }.bind(this); }, - render: function PDFAttachmentView_render() { - var attachments = this.attachments; + /** + * @param {PDFAttachmentViewerRenderParameters} params + */ + render: function PDFAttachmentViewer_render(params) { + var attachments = (params && params.attachments) || null; var attachmentsCount = 0; - this.reset(); + if (this.attachments) { + this.reset(); + } + this.attachments = attachments; if (!attachments) { this._dispatchEvent(attachmentsCount); @@ -98,5 +112,5 @@ var PDFAttachmentView = (function PDFAttachmentViewClosure() { } }; - return PDFAttachmentView; + return PDFAttachmentViewer; })(); diff --git a/web/pdf_outline_view.js b/web/pdf_outline_viewer.js similarity index 79% rename from web/pdf_outline_view.js rename to web/pdf_outline_viewer.js index 08b2e0206..42331c3e8 100644 --- a/web/pdf_outline_view.js +++ b/web/pdf_outline_viewer.js @@ -19,40 +19,46 @@ var DEFAULT_TITLE = '\u2013'; /** - * @typedef {Object} PDFOutlineViewOptions + * @typedef {Object} PDFOutlineViewerOptions * @property {HTMLDivElement} container - The viewer element. - * @property {Array} outline - An array of outline objects. * @property {IPDFLinkService} linkService - The navigation/linking service. */ +/** + * @typedef {Object} PDFOutlineViewerRenderParameters + * @property {Array|null} outline - An array of outline objects. + */ + /** * @class */ -var PDFOutlineView = (function PDFOutlineViewClosure() { +var PDFOutlineViewer = (function PDFOutlineViewerClosure() { /** - * @constructs PDFOutlineView - * @param {PDFOutlineViewOptions} options + * @constructs PDFOutlineViewer + * @param {PDFOutlineViewerOptions} options */ - function PDFOutlineView(options) { + function PDFOutlineViewer(options) { + this.outline = null; + this.lastToggleIsShow = true; this.container = options.container; - this.outline = options.outline; this.linkService = options.linkService; - this.lastToggleIsShow = true; } - PDFOutlineView.prototype = { - reset: function PDFOutlineView_reset() { + PDFOutlineViewer.prototype = { + reset: function PDFOutlineViewer_reset() { + this.outline = null; + this.lastToggleIsShow = true; + var container = this.container; while (container.firstChild) { container.removeChild(container.firstChild); } - this.lastToggleIsShow = true; }, /** * @private */ - _dispatchEvent: function PDFOutlineView_dispatchEvent(outlineCount) { + _dispatchEvent: function PDFOutlineViewer_dispatchEvent(outlineCount) { var event = document.createEvent('CustomEvent'); event.initCustomEvent('outlineloaded', true, true, { outlineCount: outlineCount @@ -63,7 +69,7 @@ var PDFOutlineView = (function PDFOutlineViewClosure() { /** * @private */ - _bindLink: function PDFOutlineView_bindLink(element, item) { + _bindLink: function PDFOutlineViewer_bindLink(element, item) { if (item.url) { PDFJS.addLinkAttributes(element, { url: item.url }); return; @@ -82,7 +88,7 @@ var PDFOutlineView = (function PDFOutlineViewClosure() { * * @private */ - _addToggleButton: function PDFOutlineView_addToggleButton(div) { + _addToggleButton: function PDFOutlineViewer_addToggleButton(div) { var toggler = document.createElement('div'); toggler.className = 'outlineItemToggler'; toggler.onclick = function(event) { @@ -106,7 +112,8 @@ var PDFOutlineView = (function PDFOutlineViewClosure() { * * @private */ - _toggleOutlineItem: function PDFOutlineView_toggleOutlineItem(root, show) { + _toggleOutlineItem: + function PDFOutlineViewer_toggleOutlineItem(root, show) { this.lastToggleIsShow = show; var togglers = root.querySelectorAll('.outlineItemToggler'); for (var i = 0, ii = togglers.length; i < ii; ++i) { @@ -117,15 +124,24 @@ var PDFOutlineView = (function PDFOutlineViewClosure() { /** * Collapse or expand all subtrees of the outline. */ - toggleOutlineTree: function PDFOutlineView_toggleOutlineTree() { + toggleOutlineTree: function PDFOutlineViewer_toggleOutlineTree() { + if (!this.outline) { + return; + } this._toggleOutlineItem(this.container, !this.lastToggleIsShow); }, - render: function PDFOutlineView_render() { - var outline = this.outline; + /** + * @param {PDFOutlineViewerRenderParameters} params + */ + render: function PDFOutlineViewer_render(params) { + var outline = (params && params.outline) || null; var outlineCount = 0; - this.reset(); + if (this.outline) { + this.reset(); + } + this.outline = outline; if (!outline) { this._dispatchEvent(outlineCount); @@ -174,5 +190,5 @@ var PDFOutlineView = (function PDFOutlineViewClosure() { } }; - return PDFOutlineView; + return PDFOutlineViewer; })(); diff --git a/web/pdf_sidebar.js b/web/pdf_sidebar.js new file mode 100644 index 000000000..0490ef249 --- /dev/null +++ b/web/pdf_sidebar.js @@ -0,0 +1,324 @@ +/* Copyright 2016 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /* globals RenderingStates */ + +'use strict'; + +var SidebarView = { + NONE: 0, + THUMBS: 1, + OUTLINE: 2, + ATTACHMENTS: 3 +}; + +/** + * @typedef {Object} PDFSidebarOptions + * @property {PDFViewer} - The document viewer. + * @property {PDFThumbnailViewer} - The thumbnail viewer. + * @property {PDFOutlineViewer} - The outline viewer. + * @property {HTMLDivElement} mainContainer - The main container + * (in which the viewer element is placed). + * @property {HTMLDivElement} outerContainer - The outer container + * (encasing both the viewer and sidebar elements). + * @property {HTMLButtonElement} toggleButton - The button used for + * opening/closing the sidebar. + * @property {HTMLButtonElement} thumbnailButton - The button used to show + * the thumbnail view. + * @property {HTMLButtonElement} outlineButton - The button used to show + * the outline view. + * @property {HTMLButtonElement} attachmentsButton - The button used to show + * the attachments view. + * @property {HTMLDivElement} thumbnailView - The container in which + * the thumbnails are placed. + * @property {HTMLDivElement} outlineView - The container in which + * the outline is placed. + * @property {HTMLDivElement} attachmentsView - The container in which + * the attachments are placed. + */ + +/** + * @class + */ +var PDFSidebar = (function PDFSidebarClosure() { + /** + * @constructs PDFSidebar + * @param {PDFSidebarOptions} options + */ + function PDFSidebar(options) { + this.isOpen = false; + this.active = SidebarView.THUMBS; + this.isInitialViewSet = false; + + /** + * Callback used when the sidebar has been opened/closed, to ensure that + * the viewers (PDFViewer/PDFThumbnailViewer) are updated correctly. + */ + this.onToggled = null; + + this.pdfViewer = options.pdfViewer; + this.pdfThumbnailViewer = options.pdfThumbnailViewer; + this.pdfOutlineViewer = options.pdfOutlineViewer; + + this.mainContainer = options.mainContainer; + this.outerContainer = options.outerContainer; + this.toggleButton = options.toggleButton; + + this.thumbnailButton = options.thumbnailButton; + this.outlineButton = options.outlineButton; + this.attachmentsButton = options.attachmentsButton; + + this.thumbnailView = options.thumbnailView; + this.outlineView = options.outlineView; + this.attachmentsView = options.attachmentsView; + + this._addEventListeners(); + } + + PDFSidebar.prototype = { + reset: function PDFSidebar_reset() { + this.isInitialViewSet = false; + + this.close(); + this.switchView(SidebarView.THUMBS); + + this.outlineButton.disabled = false; + this.attachmentsButton.disabled = false; + }, + + /** + * @returns {number} One of the values in {SidebarView}. + */ + get visibleView() { + return (this.isOpen ? this.active : SidebarView.NONE); + }, + + get isThumbnailViewVisible() { + return (this.isOpen && this.active === SidebarView.THUMBS); + }, + + get isOutlineViewVisible() { + return (this.isOpen && this.active === SidebarView.OUTLINE); + }, + + get isAttachmentsViewVisible() { + return (this.isOpen && this.active === SidebarView.ATTACHMENTS); + }, + + /** + * @param {number} view - The sidebar view that should become visible, + * must be one of the values in {SidebarView}. + */ + setInitialView: function PDFSidebar_setInitialView(view) { + if (this.isInitialViewSet) { + return; + } + this.isInitialViewSet = true; + + if (this.isOpen && view === SidebarView.NONE) { + // If the user has already manually opened the sidebar, + // immediately closing it would be bad UX. + return; + } + this.switchView(view, true); + }, + + /** + * @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. + * The default value is false. + */ + switchView: function PDFSidebar_switchView(view, forceOpen) { + if (view === SidebarView.NONE) { + this.close(); + return; + } + if (forceOpen) { + this.open(); + } + var shouldForceRendering = false; + + switch (view) { + case SidebarView.THUMBS: + this.thumbnailButton.classList.add('toggled'); + this.outlineButton.classList.remove('toggled'); + this.attachmentsButton.classList.remove('toggled'); + + this.thumbnailView.classList.remove('hidden'); + this.outlineView.classList.add('hidden'); + this.attachmentsView.classList.add('hidden'); + + if (this.isOpen && view !== this.active) { + this._updateThumbnailViewer(); + shouldForceRendering = true; + } + break; + case SidebarView.OUTLINE: + if (this.outlineButton.disabled) { + return; + } + this.thumbnailButton.classList.remove('toggled'); + this.outlineButton.classList.add('toggled'); + this.attachmentsButton.classList.remove('toggled'); + + this.thumbnailView.classList.add('hidden'); + this.outlineView.classList.remove('hidden'); + this.attachmentsView.classList.add('hidden'); + break; + case SidebarView.ATTACHMENTS: + if (this.attachmentsButton.disabled) { + return; + } + this.thumbnailButton.classList.remove('toggled'); + this.outlineButton.classList.remove('toggled'); + this.attachmentsButton.classList.add('toggled'); + + this.thumbnailView.classList.add('hidden'); + this.outlineView.classList.add('hidden'); + this.attachmentsView.classList.remove('hidden'); + break; + default: + console.error('PDFSidebar_switchView: "' + view + + '" is an unsupported value.'); + return; + } + // Update the active view *after* it has been validated above, + // in order to prevent setting it to an invalid state. + this.active = view | 0; + + if (shouldForceRendering) { + this._forceRendering(); + } + }, + + open: function PDFSidebar_open() { + if (this.isOpen) { + return; + } + this.isOpen = true; + this.toggleButton.classList.add('toggled'); + + this.outerContainer.classList.add('sidebarMoving'); + this.outerContainer.classList.add('sidebarOpen'); + + if (this.active === SidebarView.THUMBS) { + this._updateThumbnailViewer(); + } + this._forceRendering(); + }, + + close: function PDFSidebar_close() { + if (!this.isOpen) { + return; + } + this.isOpen = false; + this.toggleButton.classList.remove('toggled'); + + this.outerContainer.classList.add('sidebarMoving'); + this.outerContainer.classList.remove('sidebarOpen'); + + this._forceRendering(); + }, + + toggle: function PDFSidebar_toggle() { + if (this.isOpen) { + this.close(); + } else { + this.open(); + } + }, + + /** + * @private + */ + _forceRendering: function PDFSidebar_forceRendering() { + if (this.onToggled) { + this.onToggled(); + } else { // Fallback + this.pdfViewer.forceRendering(); + this.pdfThumbnailViewer.forceRendering(); + } + }, + + /** + * @private + */ + _updateThumbnailViewer: function PDFSidebar_updateThumbnailViewer() { + var pdfViewer = this.pdfViewer; + var thumbnailViewer = this.pdfThumbnailViewer; + + // Use the rendered pages to set the corresponding thumbnail images. + var pagesCount = pdfViewer.pagesCount; + for (var pageIndex = 0; pageIndex < pagesCount; pageIndex++) { + var pageView = pdfViewer.getPageView(pageIndex); + if (pageView && pageView.renderingState === RenderingStates.FINISHED) { + var thumbnailView = thumbnailViewer.getThumbnail(pageIndex); + thumbnailView.setImage(pageView); + } + } + thumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber); + }, + + /** + * @private + */ + _addEventListeners: function PDFSidebar_addEventListeners() { + var self = this; + + self.mainContainer.addEventListener('transitionend', function(evt) { + if (evt.target === /* mainContainer */ this) { + self.outerContainer.classList.remove('sidebarMoving'); + } + }); + + // Buttons for switching views. + self.thumbnailButton.addEventListener('click', function() { + self.switchView(SidebarView.THUMBS); + }); + + self.outlineButton.addEventListener('click', function() { + self.switchView(SidebarView.OUTLINE); + }); + self.outlineButton.addEventListener('dblclick', function() { + self.pdfOutlineViewer.toggleOutlineTree(); + }); + + self.attachmentsButton.addEventListener('click', function() { + self.switchView(SidebarView.ATTACHMENTS); + }); + + // Disable/enable views. + self.outlineView.addEventListener('outlineloaded', function(evt) { + var outlineCount = evt.detail.outlineCount; + + self.outlineButton.disabled = !outlineCount; + if (!outlineCount && self.active === SidebarView.OUTLINE) { + self.switchView(SidebarView.THUMBS); + } + }); + + self.attachmentsView.addEventListener('attachmentsloaded', function(evt) { + var attachmentsCount = evt.detail.attachmentsCount; + + self.attachmentsButton.disabled = !attachmentsCount; + if (!attachmentsCount && self.active === SidebarView.ATTACHMENTS) { + self.switchView(SidebarView.THUMBS); + } + }); + }, + }; + + return PDFSidebar; +})(); diff --git a/web/preferences.js b/web/preferences.js index e62b10d21..f0cd46f89 100644 --- a/web/preferences.js +++ b/web/preferences.js @@ -18,13 +18,6 @@ //#include default_preferences.js -var SidebarView = { - NONE: 0, - THUMBS: 1, - OUTLINE: 2, - ATTACHMENTS: 3 -}; - /** * Preferences - Utility for storing persistent settings. * Used for settings that should be applied to all opened documents, diff --git a/web/viewer.html b/web/viewer.html index 662e7fcfd..98ee82954 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -74,8 +74,9 @@ See https://github.com/adobe-type-tools/cmap-resources - - + + + diff --git a/web/viewer.js b/web/viewer.js index f2567fcae..1ab9ca30f 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -15,9 +15,9 @@ /* globals PDFJS, PDFBug, FirefoxCom, Stats, ProgressBar, DownloadManager, getPDFFileNameFromURL, PDFHistory, Preferences, SidebarView, ViewHistory, Stats, PDFThumbnailViewer, URL, noContextMenuHandler, - SecondaryToolbar, PasswordPrompt, PDFPresentationMode, + SecondaryToolbar, PasswordPrompt, PDFPresentationMode, PDFSidebar, PDFDocumentProperties, HandTool, Promise, PDFLinkService, - PDFOutlineView, PDFAttachmentView, OverlayManager, + PDFOutlineViewer, PDFAttachmentViewer, OverlayManager, PDFFindController, PDFFindBar, PDFViewer, PDFRenderingQueue, PresentationModeState, parseQueryString, RenderingStates, UNKNOWN_SCALE, DEFAULT_SCALE_VALUE, @@ -83,8 +83,9 @@ var mozL10n = document.mozL10n || document.webL10n; //#include pdf_document_properties.js //#include pdf_viewer.js //#include pdf_thumbnail_viewer.js -//#include pdf_outline_view.js -//#include pdf_attachment_view.js +//#include pdf_sidebar.js +//#include pdf_outline_viewer.js +//#include pdf_attachment_viewer.js var PDFViewerApplication = { initialBookmark: document.location.hash.substring(1), @@ -93,7 +94,6 @@ var PDFViewerApplication = { fellback: false, pdfDocument: null, pdfLoadingTask: null, - sidebarOpen: false, printing: false, /** @type {PDFViewer} */ pdfViewer: null, @@ -109,6 +109,12 @@ var PDFViewerApplication = { pdfLinkService: null, /** @type {PDFHistory} */ pdfHistory: null, + /** @type {PDFSidebar} */ + pdfSidebar: null, + /** @type {PDFOutlineViewer} */ + pdfOutlineViewer: null, + /** @type {PDFAttachmentViewer} */ + pdfAttachmentViewer: null, pageRotation: 0, isInitialViewSet: false, animationStartedPromise: null, @@ -245,6 +251,35 @@ var PDFViewerApplication = { passwordCancel: document.getElementById('passwordCancel') }); + this.pdfOutlineViewer = new PDFOutlineViewer({ + container: document.getElementById('outlineView'), + linkService: pdfLinkService, + }); + + this.pdfAttachmentViewer = new PDFAttachmentViewer({ + container: document.getElementById('attachmentsView'), + downloadManager: new DownloadManager(), + }); + + this.pdfSidebar = new PDFSidebar({ + pdfViewer: this.pdfViewer, + pdfThumbnailViewer: this.pdfThumbnailViewer, + pdfOutlineViewer: this.pdfOutlineViewer, + // Divs (and sidebar button) + mainContainer: document.getElementById('mainContainer'), + outerContainer: document.getElementById('outerContainer'), + toggleButton: document.getElementById('sidebarToggle'), + // Buttons + thumbnailButton: document.getElementById('viewThumbnail'), + outlineButton: document.getElementById('viewOutline'), + attachmentsButton: document.getElementById('viewAttachments'), + // Views + thumbnailView: document.getElementById('thumbnailView'), + outlineView: document.getElementById('outlineView'), + attachmentsView: document.getElementById('attachmentsView'), + }); + this.pdfSidebar.onToggled = this.forceRendering.bind(this); + var self = this; var initializedPromise = Promise.all([ Preferences.get('enableWebGL').then(function resolved(value) { @@ -526,6 +561,10 @@ var PDFViewerApplication = { this.pdfLinkService.setDocument(null, null); } + this.pdfSidebar.reset(); + this.pdfOutlineViewer.reset(); + this.pdfAttachmentViewer.reset(); + this.findController.reset(); this.findBar.reset(); @@ -950,49 +989,13 @@ var PDFViewerApplication = { var promises = [pagesPromise, this.animationStartedPromise]; Promise.all(promises).then(function() { pdfDocument.getOutline().then(function(outline) { - var container = document.getElementById('outlineView'); - self.outline = new PDFOutlineView({ - container: container, - outline: outline, - linkService: self.pdfLinkService - }); - self.outline.render(); - document.getElementById('viewOutline').disabled = !outline; - - if (!outline && !container.classList.contains('hidden')) { - self.switchSidebarView('thumbs'); - } - if (outline && - self.preferenceSidebarViewOnLoad === SidebarView.OUTLINE) { - self.switchSidebarView('outline', true); - } + self.pdfOutlineViewer.render({ outline: outline }); }); pdfDocument.getAttachments().then(function(attachments) { - var container = document.getElementById('attachmentsView'); - self.attachments = new PDFAttachmentView({ - container: container, - attachments: attachments, - downloadManager: new DownloadManager() - }); - self.attachments.render(); - document.getElementById('viewAttachments').disabled = !attachments; - - if (!attachments && !container.classList.contains('hidden')) { - self.switchSidebarView('thumbs'); - } - if (attachments && - self.preferenceSidebarViewOnLoad === SidebarView.ATTACHMENTS) { - self.switchSidebarView('attachments', true); - } + self.pdfAttachmentViewer.render({ attachments: attachments }); }); }); - if (self.preferenceSidebarViewOnLoad === SidebarView.THUMBS) { - Promise.all([firstPagePromise, onePageRendered]).then(function () { - self.switchSidebarView('thumbs', true); - }); - } - pdfDocument.getMetadata().then(function(data) { var info = data.info, metadata = data.metadata; self.documentInfo = info; @@ -1071,6 +1074,8 @@ var PDFViewerApplication = { document.getElementById('pageNumber').value = this.pdfViewer.currentPageNumber; + this.pdfSidebar.setInitialView(this.preferenceSidebarViewOnLoad); + if (this.initialDestination) { this.pdfLinkService.navigateTo(this.initialDestination); this.initialDestination = null; @@ -1103,83 +1108,11 @@ var PDFViewerApplication = { forceRendering: function pdfViewForceRendering() { this.pdfRenderingQueue.printing = this.printing; - this.pdfRenderingQueue.isThumbnailViewEnabled = this.sidebarOpen; + this.pdfRenderingQueue.isThumbnailViewEnabled = + this.pdfSidebar.isThumbnailViewVisible; this.pdfRenderingQueue.renderHighestPriority(); }, - refreshThumbnailViewer: function pdfViewRefreshThumbnailViewer() { - var pdfViewer = this.pdfViewer; - var thumbnailViewer = this.pdfThumbnailViewer; - - // set thumbnail images of rendered pages - var pagesCount = pdfViewer.pagesCount; - for (var pageIndex = 0; pageIndex < pagesCount; pageIndex++) { - var pageView = pdfViewer.getPageView(pageIndex); - if (pageView && pageView.renderingState === RenderingStates.FINISHED) { - var thumbnailView = thumbnailViewer.getThumbnail(pageIndex); - thumbnailView.setImage(pageView); - } - } - - thumbnailViewer.scrollThumbnailIntoView(this.page); - }, - - switchSidebarView: function pdfViewSwitchSidebarView(view, openSidebar) { - if (openSidebar && !this.sidebarOpen) { - document.getElementById('sidebarToggle').click(); - } - var thumbsView = document.getElementById('thumbnailView'); - var outlineView = document.getElementById('outlineView'); - var attachmentsView = document.getElementById('attachmentsView'); - - var thumbsButton = document.getElementById('viewThumbnail'); - var outlineButton = document.getElementById('viewOutline'); - var attachmentsButton = document.getElementById('viewAttachments'); - - switch (view) { - case 'thumbs': - var wasAnotherViewVisible = thumbsView.classList.contains('hidden'); - - thumbsButton.classList.add('toggled'); - outlineButton.classList.remove('toggled'); - attachmentsButton.classList.remove('toggled'); - thumbsView.classList.remove('hidden'); - outlineView.classList.add('hidden'); - attachmentsView.classList.add('hidden'); - - this.forceRendering(); - - if (wasAnotherViewVisible) { - this.pdfThumbnailViewer.ensureThumbnailVisible(this.page); - } - break; - - case 'outline': - if (outlineButton.disabled) { - return; - } - thumbsButton.classList.remove('toggled'); - outlineButton.classList.add('toggled'); - attachmentsButton.classList.remove('toggled'); - thumbsView.classList.add('hidden'); - outlineView.classList.remove('hidden'); - attachmentsView.classList.add('hidden'); - break; - - case 'attachments': - if (attachmentsButton.disabled) { - return; - } - thumbsButton.classList.remove('toggled'); - outlineButton.classList.remove('toggled'); - attachmentsButton.classList.add('toggled'); - thumbsView.classList.add('hidden'); - outlineView.classList.add('hidden'); - attachmentsView.classList.remove('hidden'); - break; - } - }, - beforePrint: function pdfViewSetupBeforePrint() { if (!this.supportsPrinting) { var printMessage = mozL10n.get('printing_not_supported', null, @@ -1518,48 +1451,18 @@ function webViewerInitialized() { // Suppress context menus for some controls document.getElementById('scaleSelect').oncontextmenu = noContextMenuHandler; - var mainContainer = document.getElementById('mainContainer'); - var outerContainer = document.getElementById('outerContainer'); - mainContainer.addEventListener('transitionend', function(e) { - if (e.target === mainContainer) { - var event = document.createEvent('UIEvents'); - event.initUIEvent('resize', false, false, window, 0); - window.dispatchEvent(event); - outerContainer.classList.remove('sidebarMoving'); - } - }, true); - - document.getElementById('sidebarToggle').addEventListener('click', - function() { - this.classList.toggle('toggled'); - outerContainer.classList.add('sidebarMoving'); - outerContainer.classList.toggle('sidebarOpen'); - PDFViewerApplication.sidebarOpen = - outerContainer.classList.contains('sidebarOpen'); - if (PDFViewerApplication.sidebarOpen) { - PDFViewerApplication.refreshThumbnailViewer(); + document.getElementById('mainContainer').addEventListener('transitionend', + function(e) { + if (e.target === /* mainContainer */ this) { + var event = document.createEvent('UIEvents'); + event.initUIEvent('resize', false, false, window, 0); + window.dispatchEvent(event); } - PDFViewerApplication.forceRendering(); - }); + }, true); - document.getElementById('viewThumbnail').addEventListener('click', - function() { - PDFViewerApplication.switchSidebarView('thumbs'); - }); - - document.getElementById('viewOutline').addEventListener('click', - function() { - PDFViewerApplication.switchSidebarView('outline'); - }); - - document.getElementById('viewOutline').addEventListener('dblclick', - function() { - PDFViewerApplication.outline.toggleOutlineTree(); - }); - - document.getElementById('viewAttachments').addEventListener('click', + document.getElementById('sidebarToggle').addEventListener('click', function() { - PDFViewerApplication.switchSidebarView('attachments'); + PDFViewerApplication.pdfSidebar.toggle(); }); document.getElementById('previous').addEventListener('click', @@ -1659,7 +1562,8 @@ document.addEventListener('pagerendered', function (e) { var pageIndex = pageNumber - 1; var pageView = PDFViewerApplication.pdfViewer.getPageView(pageIndex); - if (PDFViewerApplication.sidebarOpen) { + // Use the rendered page to set the corresponding thumbnail image. + if (PDFViewerApplication.pdfSidebar.isThumbnailViewVisible) { var thumbnailView = PDFViewerApplication.pdfThumbnailViewer. getThumbnail(pageIndex); thumbnailView.setImage(pageView); @@ -1727,23 +1631,26 @@ document.addEventListener('pagemode', function (evt) { return; } // Handle the 'pagemode' hash parameter, see also `PDFLinkService_setHash`. - var mode = evt.detail.mode; + var mode = evt.detail.mode, view; switch (mode) { - case 'bookmarks': - // Note: Our code calls this property 'outline', even though the - // Open Parameter specification calls it 'bookmarks'. - mode = 'outline'; - /* falls through */ case 'thumbs': + view = SidebarView.THUMBS; + break; + case 'bookmarks': + case 'outline': + view = SidebarView.OUTLINE; + break; case 'attachments': - PDFViewerApplication.switchSidebarView(mode, true); + view = SidebarView.ATTACHMENTS; break; case 'none': - if (PDFViewerApplication.sidebarOpen) { - document.getElementById('sidebarToggle').click(); - } + view = SidebarView.NONE; break; + default: + console.error('Invalid "pagemode" hash parameter: ' + mode); + return; } + PDFViewerApplication.pdfSidebar.switchView(view, /* forceOpen = */ true); }, true); document.addEventListener('namedaction', function (e) { @@ -1945,7 +1852,8 @@ window.addEventListener('pagechange', function pagechange(evt) { var page = evt.pageNumber; if (evt.previousPageNumber !== page) { document.getElementById('pageNumber').value = page; - if (PDFViewerApplication.sidebarOpen) { + + if (PDFViewerApplication.pdfSidebar.isThumbnailViewVisible) { PDFViewerApplication.pdfThumbnailViewer.scrollThumbnailIntoView(page); } }