Skip to content

Commit bbcb05a

Browse files
committed
Implement page rotation controls using keyboard (R/shift-R) and context menu.
1 parent 455bb6d commit bbcb05a

File tree

4 files changed

+109
-11
lines changed

4 files changed

+109
-11
lines changed

l10n/en-US/viewer.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ thumb_page_title=Page {{page}}
5050
# number.
5151
thumb_page_canvas=Thumbnail of Page {{page}}
5252

53+
# Context menu
54+
page_rotate_cw=Rotate Clockwise
55+
page_rotate_ccw=Rotate Counter-Clockwise
56+
5357
# Search panel button title and messages
5458
search=Find
5559
search_terms_not_found=(Not found)

web/viewer.css

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -778,8 +778,6 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
778778
.thumbnail {
779779
margin-bottom: 15px;
780780
float: left;
781-
width: 114px;
782-
height: 142px;
783781
}
784782

785783
.thumbnail:not([data-loaded]) {

web/viewer.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,15 @@
185185
</div>
186186
</div>
187187

188+
<menu type="context" id="viewerContextMenu">
189+
<menuitem label="Rotate Counter-Clockwise" id="page_rotate_ccw"
190+
data-l10n-id="page_rotate_ccw" ></menuitem>
191+
<menuitem label="Rotate Clockwise" id="page_rotate_cw"
192+
data-l10n-id="page_rotate_cw" ></menuitem>
193+
</menu>
194+
188195
<div id="viewerContainer">
189-
<div id="viewer"></div>
196+
<div id="viewer" contextmenu="viewerContextMenu"></div>
190197
</div>
191198

192199
<div id="loadingBox">

web/viewer.js

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ var PDFView = {
224224
thumbnailViewScroll: null,
225225
isFullscreen: false,
226226
previousScale: null,
227+
pageRotation: 0,
227228

228229
// called once when the document is loaded
229230
initialize: function pdfViewInitialize() {
@@ -707,6 +708,8 @@ var PDFView = {
707708
storedHash = 'page=' + page + '&zoom=' + zoom + ',' + left + ',' + top;
708709
}
709710

711+
this.pageRotation = 0;
712+
710713
var pages = this.pages = [];
711714
this.pageText = [];
712715
this.startedTextExtraction = false;
@@ -1180,6 +1183,34 @@ var PDFView = {
11801183
this.isFullscreen = false;
11811184
this.parseScale(this.previousScale);
11821185
this.page = this.page;
1186+
},
1187+
1188+
rotatePages: function pdfViewPageRotation(delta) {
1189+
1190+
this.pageRotation = (this.pageRotation + 360 + delta) % 360;
1191+
1192+
for (var i = 0, l = this.pages.length; i < l; i++) {
1193+
var page = this.pages[i];
1194+
page.update(page.scale, this.pageRotation);
1195+
}
1196+
1197+
for (var i = 0, l = this.thumbnails.length; i < l; i++) {
1198+
var thumb = this.thumbnails[i];
1199+
thumb.updateRotation(this.pageRotation);
1200+
}
1201+
1202+
var currentPage = this.pages[this.page - 1];
1203+
1204+
if (this.isFullscreen) {
1205+
this.parseScale('page-fit', true);
1206+
}
1207+
1208+
this.renderHighestPriority();
1209+
1210+
// Wait for fullscreen to take effect
1211+
setTimeout(function() {
1212+
currentPage.scrollIntoView();
1213+
}, 0);
11831214
}
11841215
};
11851216

@@ -1188,8 +1219,9 @@ var PageView = function pageView(container, pdfPage, id, scale,
11881219
this.id = id;
11891220
this.pdfPage = pdfPage;
11901221

1222+
this.rotation = 0;
11911223
this.scale = scale || 1.0;
1192-
this.viewport = this.pdfPage.getViewport(this.scale);
1224+
this.viewport = this.pdfPage.getViewport(this.scale, this.pdfPage.rotate);
11931225

11941226
this.renderingState = RenderingStates.INITIAL;
11951227
this.resume = null;
@@ -1200,6 +1232,8 @@ var PageView = function pageView(container, pdfPage, id, scale,
12001232
var div = this.el = document.createElement('div');
12011233
div.id = 'pageContainer' + this.id;
12021234
div.className = 'page';
1235+
div.style.width = this.viewport.width + 'px';
1236+
div.style.height = this.viewport.height + 'px';
12031237

12041238
container.appendChild(anchor);
12051239
container.appendChild(div);
@@ -1209,12 +1243,18 @@ var PageView = function pageView(container, pdfPage, id, scale,
12091243
this.pdfPage.destroy();
12101244
};
12111245

1212-
this.update = function pageViewUpdate(scale) {
1246+
this.update = function pageViewUpdate(scale, rotation) {
12131247
this.renderingState = RenderingStates.INITIAL;
12141248
this.resume = null;
12151249

1250+
if (typeof rotation !== 'undefined') {
1251+
this.rotation = rotation;
1252+
}
1253+
12161254
this.scale = scale || this.scale;
1217-
var viewport = this.pdfPage.getViewport(this.scale);
1255+
1256+
var totalRotation = (this.rotation + this.pdfPage.rotate) % 360;
1257+
var viewport = this.pdfPage.getViewport(this.scale, totalRotation);
12181258

12191259
this.viewport = viewport;
12201260
div.style.width = viewport.width + 'px';
@@ -1545,7 +1585,9 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
15451585
return false;
15461586
};
15471587

1548-
var viewport = pdfPage.getViewport(1);
1588+
var rotation = 0;
1589+
var totalRotation = (rotation + pdfPage.rotate) % 360;
1590+
var viewport = pdfPage.getViewport(1, totalRotation);
15491591
var pageWidth = this.width = viewport.width;
15501592
var pageHeight = this.height = viewport.height;
15511593
var pageRatio = pageWidth / pageHeight;
@@ -1560,12 +1602,41 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
15601602
div.id = 'thumbnailContainer' + id;
15611603
div.className = 'thumbnail';
15621604

1605+
var ring = document.createElement('div');
1606+
ring.className = 'thumbnailSelectionRing';
1607+
ring.style.width = canvasWidth + 'px';
1608+
ring.style.height = canvasHeight + 'px';
1609+
1610+
div.appendChild(ring);
15631611
anchor.appendChild(div);
15641612
container.appendChild(anchor);
15651613

15661614
this.hasImage = false;
15671615
this.renderingState = RenderingStates.INITIAL;
15681616

1617+
this.updateRotation = function(rot) {
1618+
1619+
rotation = rot;
1620+
totalRotation = (rotation + pdfPage.rotate) % 360;
1621+
viewport = pdfPage.getViewport(1, totalRotation);
1622+
pageWidth = this.width = viewport.width;
1623+
pageHeight = this.height = viewport.height;
1624+
pageRatio = pageWidth / pageHeight;
1625+
1626+
canvasHeight = canvasWidth / this.width * this.height;
1627+
scaleX = this.scaleX = (canvasWidth / pageWidth);
1628+
scaleY = this.scaleY = (canvasHeight / pageHeight);
1629+
1630+
div.removeAttribute('data-loaded');
1631+
ring.textContent = '';
1632+
ring.style.width = canvasWidth + 'px';
1633+
ring.style.height = canvasHeight + 'px';
1634+
1635+
this.hasImage = false;
1636+
this.renderingState = RenderingStates.INITIAL;
1637+
this.resume = null;
1638+
}
1639+
15691640
function getPageDrawContext() {
15701641
var canvas = document.createElement('canvas');
15711642
canvas.id = 'thumbnail' + id;
@@ -1579,10 +1650,7 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
15791650

15801651
div.setAttribute('data-loaded', true);
15811652

1582-
var ring = document.createElement('div');
1583-
ring.className = 'thumbnailSelectionRing';
15841653
ring.appendChild(canvas);
1585-
div.appendChild(ring);
15861654

15871655
var ctx = canvas.getContext('2d');
15881656
ctx.save();
@@ -1608,7 +1676,7 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
16081676

16091677
var self = this;
16101678
var ctx = getPageDrawContext();
1611-
var drawViewport = pdfPage.getViewport(scaleX);
1679+
var drawViewport = pdfPage.getViewport(scaleX, totalRotation);
16121680
var renderContext = {
16131681
canvasContext: ctx,
16141682
viewport: drawViewport,
@@ -2016,6 +2084,15 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
20162084
PDFView.parseScale(this.value);
20172085
});
20182086

2087+
document.getElementById('page_rotate_ccw').addEventListener('click',
2088+
function() {
2089+
PDFView.rotatePages(-90);
2090+
});
2091+
2092+
document.getElementById('page_rotate_cw').addEventListener('click',
2093+
function() {
2094+
PDFView.rotatePages(90);
2095+
});
20192096

20202097
//#if (FIREFOX || MOZCENTRAL)
20212098
//if (FirefoxCom.requestSync('getLoadingType') == 'passive') {
@@ -2268,6 +2345,18 @@ window.addEventListener('keydown', function keydown(evt) {
22682345
handled = true;
22692346
}
22702347
break;
2348+
2349+
case 82: // 'r'
2350+
PDFView.rotatePages(90);
2351+
break;
2352+
}
2353+
}
2354+
2355+
if (cmd == 4) { // shift-key
2356+
switch (evt.keyCode) {
2357+
case 82: // 'r'
2358+
PDFView.rotatePages(-90);
2359+
break;
22712360
}
22722361
}
22732362

0 commit comments

Comments
 (0)