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 @@
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);
+})();