diff --git a/l10n/en-US/viewer.properties b/l10n/en-US/viewer.properties index 1c4dd1cde..6bc477309 100644 --- a/l10n/en-US/viewer.properties +++ b/l10n/en-US/viewer.properties @@ -18,6 +18,8 @@ zoom_in_label=Zoom In zoom.title=Zoom print.title=Print print_label=Print +fullscreen.title=Fullscreen +fullscreen_label=Fullscreen open_file.title=Open File open_file_label=Open download.title=Download diff --git a/web/images/toolbarButton-fullscreen.png b/web/images/toolbarButton-fullscreen.png new file mode 100644 index 000000000..fa7309550 Binary files /dev/null and b/web/images/toolbarButton-fullscreen.png differ diff --git a/web/viewer.css b/web/viewer.css index 80a8c5a40..c47dbf8fb 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -27,6 +27,50 @@ select { display: none !important; } +#viewerContainer:-webkit-full-screen { + top: 0px; + padding-top: 6px; + padding-bottom: 24px; + background-color: #404040; + background-image: url(images/texture.png); + width: 100%; + height: 100%; + overflow: auto; +} + +:-webkit-full-screen #viewer { + margin: 0pt; + padding: 0pt; + height: 100%; + width: 100%; + overflow: hidden; +} + +:-webkit-full-screen .page { + margin: 0px auto; + margin-bottom: 10px; +} + +#viewerContainer:-moz-full-screen { + background-color: #404040; + background-image: url(images/texture.png); + width: 100%; + height: 100%; + overflow: hidden; +} + +:-moz-full-screen .page:last-child { + margin-bottom: 40px; +} + +#viewerContainer:full-screen { + top: 0px; + background-color: #404040; + background-image: url(images/texture.png); + width: 100%; + height: 100%; +} + /* outer/inner center provides horizontal center */ html[dir='ltr'] .outerCenter { float: right; @@ -609,6 +653,11 @@ html[dir='rtl'] .toolbarButton.pageDown::before { content: url(images/toolbarButton-zoomIn.png); } +.toolbarButton.fullscreen::before { + display: inline-block; + content: url(images/toolbarButton-fullscreen.png); +} + .toolbarButton.print::before { display: inline-block; content: url(images/toolbarButton-print.png); diff --git a/web/viewer.html b/web/viewer.html index 28e57f700..58b35464f 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -98,19 +98,25 @@
- + + - - - Current View + Current View
diff --git a/web/viewer.js b/web/viewer.js index e24e694f2..4de66b5af 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -241,6 +241,8 @@ var PDFView = { sidebarOpen: false, pageViewScroll: null, thumbnailViewScroll: null, + isFullscreen: false, + previousScale: null, // called once when the document is loaded initialize: function pdfViewInitialize() { @@ -307,6 +309,7 @@ var PDFView = { var container = this.container; var currentPage = this.pages[this.page - 1]; + var pageWidthScale = (container.clientWidth - kScrollbarPadding) / currentPage.width * currentPage.scale / kCssUnits; var pageHeightScale = (container.clientHeight - kScrollbarPadding) / @@ -390,6 +393,17 @@ var PDFView = { return value; }, + get supportsFullscreen() { + var doc = document.documentElement; + var support = doc.requestFullScreen || doc.mozRequestFullScreen || + doc.webkitRequestFullScreen; + Object.defineProperty(this, 'supportsFullScreen', { value: support, + enumerable: true, + configurable: true, + writable: false }); + return support; + }, + open: function pdfViewOpen(url, scale, password) { var parameters = {password: password}; if (typeof url === 'string') { // URL @@ -786,7 +800,7 @@ var PDFView = { } for (var i = 0; i < numVisible; ++i) { var view = visibleViews[i].view; - if (!this.isViewFinshed(view)) + if (!this.isViewFinished(view)) return view; } @@ -795,19 +809,19 @@ var PDFView = { var lastVisible = visibleViews[visibleViews.length - 1]; var nextPageIndex = lastVisible.id; // ID's start at 1 so no need to add 1. - if (views[nextPageIndex] && !this.isViewFinshed(views[nextPageIndex])) + if (views[nextPageIndex] && !this.isViewFinished(views[nextPageIndex])) return views[nextPageIndex]; } else { var previousPageIndex = visibleViews[0].id - 2; if (views[previousPageIndex] && - !this.isViewFinshed(views[previousPageIndex])) + !this.isViewFinished(views[previousPageIndex])) return views[previousPageIndex]; } // Everything that needs to be rendered has been. return false; }, - isViewFinshed: function pdfViewNeedsRendering(view) { + isViewFinished: function pdfViewNeedsRendering(view) { return view.renderingState === RenderingStates.FINISHED; }, @@ -1029,6 +1043,18 @@ var PDFView = { } var visible = []; + + // Algorithm broken in fullscreen mode + if (this.isFullscreen) { + var currentPage = this.pages[this.page - 1]; + visible.push({ + id: currentPage.id, + view: currentPage + }); + + return visible; + } + var bottom = top + scrollEl.clientHeight; for (; i <= views.length && currentHeight < bottom; ++i) { view = views[i - 1]; @@ -1072,6 +1098,44 @@ var PDFView = { var div = document.getElementById('printContainer'); while (div.hasChildNodes()) div.removeChild(div.lastChild); + }, + + fullscreen: function pdfViewFullscreen() { + var isFullscreen = document.fullscreen || document.mozFullScreen || + document.webkitIsFullScreen; + + if (isFullscreen) { + return false; + } + + var wrapper = document.getElementById('viewerContainer'); + if (document.documentElement.requestFullScreen) { + wrapper.requestFullScreen(); + } else if (document.documentElement.mozRequestFullScreen) { + wrapper.mozRequestFullScreen(); + } else if (document.documentElement.webkitRequestFullScreen) { + wrapper.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); + } else { + return false; + } + + this.isFullscreen = true; + var currentPage = this.pages[this.page - 1]; + this.previousScale = this.currentScaleValue; + this.parseScale('page-fit', true); + + // Wait for fullscreen to take effect + setTimeout(function() { + currentPage.scrollIntoView(); + }, 0); + + return true; + }, + + exitFullscreen: function pdfViewExitFullscreen() { + this.isFullscreen = false; + this.parseScale(this.previousScale); + this.page = this.page; } }; @@ -1785,6 +1849,10 @@ window.addEventListener('load', function webViewerLoad(evt) { document.getElementById('print').classList.add('hidden'); } + if (!PDFView.supportsFullscreen) { + document.getElementById('fullscreen').classList.add('hidden'); + } + // Listen for warnings to trigger the fallback UI. Errors should be caught // and call PDFView.error() so we don't need to listen for those. PDFJS.LogManager.addLogger({ @@ -1823,11 +1891,14 @@ function updateViewarea() { PDFView.renderHighestPriority(); - updateViewarea.inProgress = true; // used in "set page" var currentId = PDFView.page; var firstPage = visiblePages[0]; - PDFView.page = firstPage.id; - updateViewarea.inProgress = false; + + if (!PDFView.isFullscreen) { + updateViewarea.inProgress = true; // used in "set page" + PDFView.page = firstPage.id; + updateViewarea.inProgress = false; + } var currentScale = PDFView.currentScale; var currentScaleValue = PDFView.currentScaleValue; @@ -2013,7 +2084,7 @@ window.addEventListener('keydown', function keydown(evt) { return; var controlsElement = document.getElementById('controls'); while (curElement) { - if (curElement === controlsElement) + if (curElement === controlsElement && !PDFView.isFullscreen) return; // ignoring if the 'controls' element is focused curElement = curElement.parentNode; } @@ -2032,6 +2103,13 @@ window.addEventListener('keydown', function keydown(evt) { PDFView.page++; handled = true; break; + + case 32: // spacebar + if (PDFView.isFullscreen) { + PDFView.page++; + handled = true; + } + break; } } @@ -2047,3 +2125,18 @@ window.addEventListener('beforeprint', function beforePrint(evt) { window.addEventListener('afterprint', function afterPrint(evt) { PDFView.afterPrint(); }); + +(function fullscreenClosure() { + function fullscreenChange(e) { + var isFullscreen = document.fullscreen || document.mozFullScreen || + document.webkitIsFullScreen; + + if (!isFullscreen) { + PDFView.exitFullscreen(); + } + } + + window.addEventListener('fullscreenchange', fullscreenChange, false); + window.addEventListener('mozfullscreenchange', fullscreenChange, false); + window.addEventListener('webkitfullscreenchange', fullscreenChange, false); +})();