From 2dc1af8028119e2662df67ca94c9f1876fe35bfe Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Thu, 29 Jan 2015 13:37:49 +0100 Subject: [PATCH] Break dependencies between PresentationMode and other code, and add PresentationMode related utility methods to PDFViewer This patch: - Adds a couple of utility methods to `PDFViewer` to enable checking `presentationModeState` without cumbersome comparisons. - Disentangles `PresentationMode` from `PDFHistory` and `HandTool`, by adding event listeners for `presentationmodechanged` to both of them. - Adds a utility function to `PDFViewerApplication` for requesting PresentationMode. - Prevents initialization of `PresentationMode` if the browser does not support the fullscreen API. --- web/hand_tool.js | 11 ++++++ web/pdf_history.js | 8 +++- web/pdf_viewer.js | 34 ++++++++--------- web/presentation_mode.js | 8 ++-- web/secondary_toolbar.js | 3 +- web/viewer.js | 82 +++++++++++++++++++++------------------- 6 files changed, 83 insertions(+), 63 deletions(-) diff --git a/web/hand_tool.js b/web/hand_tool.js index b929a1ed1..70d04f07c 100644 --- a/web/hand_tool.js +++ b/web/hand_tool.js @@ -51,6 +51,17 @@ var HandTool = { } }.bind(this), function rejected(reason) {}); }.bind(this)); + + window.addEventListener('presentationmodechanged', function (evt) { + if (evt.detail.switchInProgress) { + return; + } + if (evt.detail.active) { + this.enterPresentationMode(); + } else { + this.exitPresentationMode(); + } + }.bind(this)); } }, diff --git a/web/pdf_history.js b/web/pdf_history.js index e15e03a66..4000803ba 100644 --- a/web/pdf_history.js +++ b/web/pdf_history.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* globals PDFJS, PresentationMode */ 'use strict'; @@ -31,6 +30,7 @@ var PDFHistory = { this.reInitialized = false; this.allowHashChange = true; this.historyUnlocked = true; + this.isViewerInPresentationMode = false; this.previousHash = window.location.hash.substring(1); this.currentBookmark = ''; @@ -122,6 +122,10 @@ var PDFHistory = { // the 'DOMContentLoaded' event is not fired on 'pageshow'. window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false); }, false); + + window.addEventListener('presentationmodechanged', function(e) { + self.isViewerInPresentationMode = !!e.detail.active; + }); }, _isStateObjectDefined: function pdfHistory_isStateObjectDefined(state) { @@ -286,7 +290,7 @@ var PDFHistory = { return null; } var params = { hash: this.currentBookmark, page: this.currentPage }; - if (PresentationMode.active) { + if (this.isViewerInPresentationMode) { params.hash = null; } return params; diff --git a/web/pdf_viewer.js b/web/pdf_viewer.js index 9cee8bf4c..16315bbed 100644 --- a/web/pdf_viewer.js +++ b/web/pdf_viewer.js @@ -374,11 +374,8 @@ var PDFViewer = (function pdfViewer() { if (!noScroll) { var page = this._currentPageNumber, dest; - var inPresentationMode = - this.presentationModeState === PresentationModeState.CHANGING || - this.presentationModeState === PresentationModeState.FULLSCREEN; - if (this.location && !inPresentationMode && - !IGNORE_CURRENT_POSITION_ON_ZOOM) { + if (this.location && !IGNORE_CURRENT_POSITION_ON_ZOOM && + !(this.isInPresentationMode || this.isChangingPresentationMode)) { page = this.location.pageNumber; dest = [null, { name: 'XYZ' }, this.location.left, this.location.top, null]; @@ -402,11 +399,9 @@ var PDFViewer = (function pdfViewer() { if (!currentPage) { return; } - var inPresentationMode = - this.presentationModeState === PresentationModeState.FULLSCREEN; - var hPadding = (inPresentationMode || this.removePageBorders) ? + var hPadding = (this.isInPresentationMode || this.removePageBorders) ? 0 : SCROLLBAR_PADDING; - var vPadding = (inPresentationMode || this.removePageBorders) ? + var vPadding = (this.isInPresentationMode || this.removePageBorders) ? 0 : VERTICAL_PADDING; var pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale; @@ -452,8 +447,7 @@ var PDFViewer = (function pdfViewer() { dest) { var pageView = this.pages[pageNumber - 1]; - if (this.presentationModeState === - PresentationModeState.FULLSCREEN) { + if (this.isInPresentationMode) { if (this.linkService.page !== pageView.id) { // Avoid breaking getVisiblePages in presentation mode. this.linkService.page = pageView.id; @@ -607,7 +601,7 @@ var PDFViewer = (function pdfViewer() { currentId = visiblePages[0].id; } - if (this.presentationModeState !== PresentationModeState.FULLSCREEN) { + if (!this.isInPresentationMode) { this.currentPageNumber = currentId; } @@ -632,13 +626,21 @@ var PDFViewer = (function pdfViewer() { this.container.blur(); }, + get isInPresentationMode() { + return this.presentationModeState === PresentationModeState.FULLSCREEN; + }, + + get isChangingPresentationMode() { + return this.PresentationModeState === PresentationModeState.CHANGING; + }, + get isHorizontalScrollbarEnabled() { - return (this.presentationModeState === PresentationModeState.FULLSCREEN ? + return (this.isInPresentationMode ? false : (this.container.scrollWidth > this.container.clientWidth)); }, _getVisiblePages: function () { - if (this.presentationModeState !== PresentationModeState.FULLSCREEN) { + if (!this.isInPresentationMode) { return getVisibleElements(this.container, this.pages, true); } else { // The algorithm in getVisibleElements doesn't work in all browsers and @@ -709,13 +711,11 @@ var PDFViewer = (function pdfViewer() { * @returns {TextLayerBuilder} */ createTextLayerBuilder: function (textLayerDiv, pageIndex, viewport) { - var isViewerInPresentationMode = - this.presentationModeState === PresentationModeState.FULLSCREEN; return new TextLayerBuilder({ textLayerDiv: textLayerDiv, pageIndex: pageIndex, viewport: viewport, - findController: isViewerInPresentationMode ? null : this.findController + findController: this.isInPresentationMode ? null : this.findController }); }, diff --git a/web/presentation_mode.js b/web/presentation_mode.js index f94ef7b08..6c4fe4643 100644 --- a/web/presentation_mode.js +++ b/web/presentation_mode.js @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* globals scrollIntoView, HandTool, PDFViewerApplication */ +/* globals scrollIntoView, PDFViewerApplication */ 'use strict'; @@ -23,6 +23,7 @@ var SELECTOR = 'presentationControls'; var DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1000; // in ms var PresentationMode = { + initialized: false, active: false, args: null, contextMenuOpen: false, @@ -31,6 +32,7 @@ var PresentationMode = { //#endif initialize: function presentationModeInitialize(options) { + this.initialized = true; this.container = options.container; this.secondaryToolbar = options.secondaryToolbar; @@ -93,7 +95,7 @@ var PresentationMode = { }, request: function presentationModeRequest() { - if (!PDFViewerApplication.supportsFullscreen || this.isFullscreen || + if (!this.initialized || this.isFullscreen || !this.viewer.hasChildNodes()) { return false; } @@ -147,7 +149,6 @@ var PresentationMode = { window.addEventListener('contextmenu', this.contextMenu, false); this.showControls(); - HandTool.enterPresentationMode(); this.contextMenuOpen = false; this.container.setAttribute('contextmenu', 'viewerContextMenu'); @@ -178,7 +179,6 @@ var PresentationMode = { this.hideControls(); PDFViewerApplication.clearMouseScrollState(); - HandTool.exitPresentationMode(); this.container.removeAttribute('contextmenu'); this.contextMenuOpen = false; diff --git a/web/secondary_toolbar.js b/web/secondary_toolbar.js index 7c94b3185..0b3f3d596 100644 --- a/web/secondary_toolbar.js +++ b/web/secondary_toolbar.js @@ -25,7 +25,6 @@ var SecondaryToolbar = { initialize: function secondaryToolbarInitialize(options) { this.toolbar = options.toolbar; - this.presentationMode = options.presentationMode; this.documentProperties = options.documentProperties; this.buttonContainer = this.toolbar.firstElementChild; @@ -72,7 +71,7 @@ var SecondaryToolbar = { // Event handling functions. presentationModeClick: function secondaryToolbarPresentationModeClick(evt) { - this.presentationMode.request(); + PDFViewerApplication.requestPresentationMode(); this.close(); }, diff --git a/web/viewer.js b/web/viewer.js index 62c9f9182..b80d9781f 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -174,7 +174,6 @@ var PDFViewerApplication = { SecondaryToolbar.initialize({ toolbar: document.getElementById('secondaryToolbar'), - presentationMode: PresentationMode, toggleButton: document.getElementById('secondaryToolbarToggle'), presentationModeButton: document.getElementById('secondaryPresentationMode'), @@ -190,14 +189,16 @@ var PDFViewerApplication = { documentPropertiesButton: document.getElementById('documentProperties') }); - PresentationMode.initialize({ - container: container, - secondaryToolbar: SecondaryToolbar, - firstPage: document.getElementById('contextFirstPage'), - lastPage: document.getElementById('contextLastPage'), - pageRotateCw: document.getElementById('contextPageRotateCw'), - pageRotateCcw: document.getElementById('contextPageRotateCcw') - }); + if (this.supportsFullscreen) { + PresentationMode.initialize({ + container: container, + secondaryToolbar: SecondaryToolbar, + firstPage: document.getElementById('contextFirstPage'), + lastPage: document.getElementById('contextLastPage'), + pageRotateCw: document.getElementById('contextPageRotateCw'), + pageRotateCcw: document.getElementById('contextPageRotateCcw') + }); + } PasswordPrompt.initialize({ overlayName: 'passwordOverlay', @@ -1334,6 +1335,13 @@ var PDFViewerApplication = { this.pdfViewer.scrollPageIntoView(pageNumber); }, + requestPresentationMode: function pdfViewRequestPresentationMode() { + if (!this.supportsFullscreen) { + return; + } + PresentationMode.request(); + }, + /** * This function flips the page in presentation mode if the user scrolls up * or down with large enough motion and prevents page flipping too often. @@ -1976,7 +1984,7 @@ function handleMouseWheel(evt) { evt.wheelDelta / MOUSE_WHEEL_DELTA_FACTOR; var direction = (ticks < 0) ? 'zoomOut' : 'zoomIn'; - if (PresentationMode.active) { + if (PDFViewerApplication.pdfViewer.isInPresentationMode) { evt.preventDefault(); PDFViewerApplication.mouseScroll(ticks * MOUSE_WHEEL_DELTA_FACTOR); } else if (evt.ctrlKey || evt.metaKey) { @@ -1990,9 +1998,9 @@ window.addEventListener('DOMMouseScroll', handleMouseWheel); window.addEventListener('mousewheel', handleMouseWheel); window.addEventListener('click', function click(evt) { - if (!PresentationMode.active) { + if (!PDFViewerApplication.pdfViewer.isInPresentationMode) { if (SecondaryToolbar.opened && - PDFViewerApplication.pdfViewer.containsElement(evt.target)) { + PDFViewerApplication.pdfViewer.containsElement(evt.target)) { SecondaryToolbar.close(); } } else if (evt.button === 0) { @@ -2013,15 +2021,13 @@ window.addEventListener('keydown', function keydown(evt) { (evt.shiftKey ? 4 : 0) | (evt.metaKey ? 8 : 0); + var pdfViewer = PDFViewerApplication.pdfViewer; + var isViewerInPresentationMode = pdfViewer && pdfViewer.isInPresentationMode; + // First, handle the key bindings that are independent whether an input // control is selected or not. if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) { // either CTRL or META key with optional SHIFT. - var pdfViewer = PDFViewerApplication.pdfViewer; - var inPresentationMode = pdfViewer && - (pdfViewer.presentationModeState === PresentationModeState.CHANGING || - pdfViewer.presentationModeState === PresentationModeState.FULLSCREEN); - switch (evt.keyCode) { case 70: // f if (!PDFViewerApplication.supportsIntegratedFind) { @@ -2040,7 +2046,7 @@ window.addEventListener('keydown', function keydown(evt) { case 107: // FF '+' and '=' case 187: // Chrome '+' case 171: // FF with German keyboard - if (!inPresentationMode) { + if (!isViewerInPresentationMode) { PDFViewerApplication.zoomIn(); } handled = true; @@ -2048,14 +2054,14 @@ window.addEventListener('keydown', function keydown(evt) { case 173: // FF/Mac '-' case 109: // FF '-' case 189: // Chrome '-' - if (!inPresentationMode) { + if (!isViewerInPresentationMode) { PDFViewerApplication.zoomOut(); } handled = true; break; case 48: // '0' case 96: // '0' on Numpad of Swedish keyboard - if (!inPresentationMode) { + if (!isViewerInPresentationMode) { // keeping it unhandled (to restore page zoom to 100%) setTimeout(function () { // ... and resetting the scale after browser adjusts its scale @@ -2083,7 +2089,7 @@ window.addEventListener('keydown', function keydown(evt) { if (cmd === 3 || cmd === 10) { switch (evt.keyCode) { case 80: // p - SecondaryToolbar.presentationModeClick(); + PDFViewerApplication.requestPresentationMode(); handled = true; break; case 71: // g @@ -2117,15 +2123,15 @@ window.addEventListener('keydown', function keydown(evt) { case 38: // up arrow case 33: // pg up case 8: // backspace - if (!PresentationMode.active && - PDFViewerApplication.currentScaleValue !== 'page-fit') { + if (!isViewerInPresentationMode && + PDFViewerApplication.currentScaleValue !== 'page-fit') { break; } /* in presentation mode */ /* falls through */ case 37: // left arrow // horizontal scrolling using arrow keys - if (PDFViewerApplication.pdfViewer.isHorizontalScrollbarEnabled) { + if (pdfViewer.isHorizontalScrollbarEnabled) { break; } /* falls through */ @@ -2148,14 +2154,14 @@ window.addEventListener('keydown', function keydown(evt) { case 40: // down arrow case 34: // pg down case 32: // spacebar - if (!PresentationMode.active && + if (!isViewerInPresentationMode && PDFViewerApplication.currentScaleValue !== 'page-fit') { break; } /* falls through */ case 39: // right arrow // horizontal scrolling using arrow keys - if (PDFViewerApplication.pdfViewer.isHorizontalScrollbarEnabled) { + if (pdfViewer.isHorizontalScrollbarEnabled) { break; } /* falls through */ @@ -2166,13 +2172,13 @@ window.addEventListener('keydown', function keydown(evt) { break; case 36: // home - if (PresentationMode.active || PDFViewerApplication.page > 1) { + if (isViewerInPresentationMode || PDFViewerApplication.page > 1) { PDFViewerApplication.page = 1; handled = true; } break; case 35: // end - if (PresentationMode.active || (PDFViewerApplication.pdfDocument && + if (isViewerInPresentationMode || (PDFViewerApplication.pdfDocument && PDFViewerApplication.page < PDFViewerApplication.pagesCount)) { PDFViewerApplication.page = PDFViewerApplication.pagesCount; handled = true; @@ -2180,7 +2186,7 @@ window.addEventListener('keydown', function keydown(evt) { break; case 72: // 'h' - if (!PresentationMode.active) { + if (!isViewerInPresentationMode) { HandTool.toggle(); } break; @@ -2193,7 +2199,7 @@ window.addEventListener('keydown', function keydown(evt) { if (cmd === 4) { // shift-key switch (evt.keyCode) { case 32: // spacebar - if (!PresentationMode.active && + if (!isViewerInPresentationMode && PDFViewerApplication.currentScaleValue !== 'page-fit') { break; } @@ -2207,25 +2213,25 @@ window.addEventListener('keydown', function keydown(evt) { } } - if (!handled && !PresentationMode.active) { + if (!handled && !isViewerInPresentationMode) { // 33=Page Up 34=Page Down 35=End 36=Home // 37=Left 38=Up 39=Right 40=Down if (evt.keyCode >= 33 && evt.keyCode <= 40 && - !PDFViewerApplication.pdfViewer.containsElement(curElement)) { + !pdfViewer.containsElement(curElement)) { // The page container is not focused, but a page navigation key has been // pressed. Change the focus to the viewer container to make sure that // navigation by keyboard works as expected. - PDFViewerApplication.pdfViewer.focus(); + pdfViewer.focus(); } // 32=Spacebar if (evt.keyCode === 32 && curElementTagName !== 'BUTTON') { //#if (FIREFOX || MOZCENTRAL) // // Workaround for issue in Firefox, that prevents scroll keys from // // working when elements with 'tabindex' are focused. (#3498) -// PDFViewerApplication.pdfViewer.blur(); +// pdfViewer.blur(); //#else - if (!PDFViewerApplication.pdfViewer.containsElement(curElement)) { - PDFViewerApplication.pdfViewer.focus(); + if (!pdfViewer.containsElement(curElement)) { + pdfViewer.focus(); } //#endif } @@ -2234,13 +2240,13 @@ window.addEventListener('keydown', function keydown(evt) { if (cmd === 2) { // alt-key switch (evt.keyCode) { case 37: // left arrow - if (PresentationMode.active) { + if (isViewerInPresentationMode) { PDFHistory.back(); handled = true; } break; case 39: // right arrow - if (PresentationMode.active) { + if (isViewerInPresentationMode) { PDFHistory.forward(); handled = true; }