diff --git a/multi-page-viewer.css b/multi-page-viewer.css
deleted file mode 100644
index 7f4701022..000000000
--- a/multi-page-viewer.css
+++ /dev/null
@@ -1,197 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
-/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
-
-body {
- background-color: #929292;
- font-family: 'Lucida Grande', 'Lucida Sans Unicode', Helvetica, Arial, Verdana, sans-serif;
- margin: 0px;
- padding: 0px;
-}
-
-canvas {
- box-shadow: 0px 4px 10px #000;
- -moz-box-shadow: 0px 4px 10px #000;
- -webkit-box-shadow: 0px 4px 10px #000;
-}
-
-span {
- font-size: 0.8em;
-}
-
-.control {
- display: inline-block;
- float: left;
- margin: 0px 20px 0px 0px;
- padding: 0px 4px 0px 0px;
-}
-
-.control > input {
- float: left;
- border: 1px solid #4d4d4d;
- height: 20px;
- padding: 0px;
- margin: 0px 2px 0px 0px;
- border-radius: 4px;
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
- -moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
- -webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
-}
-
-.control > select {
- float: left;
- border: 1px solid #4d4d4d;
- height: 22px;
- padding: 2px 0px 0px;
- margin: 0px 0px 1px;
- border-radius: 4px;
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
- -moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
- -webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
-}
-
-.control > span {
- cursor: default;
- float: left;
- height: 18px;
- margin: 5px 2px 0px;
- padding: 0px;
- user-select: none;
- -moz-user-select: none;
- -webkit-user-select: none;
-}
-
-.control .label {
- clear: both;
- float: left;
- font-size: 0.65em;
- margin: 2px 0px 0px;
- position: relative;
- text-align: center;
- width: 100%;
-}
-
-.page {
- width: 816px;
- height: 1056px;
- margin: 10px auto;
-}
-
-#controls {
- background-color: #eee;
- border-bottom: 1px solid #666;
- padding: 4px 0px 0px 8px;
- position: fixed;
- left: 0px;
- top: 0px;
- height: 40px;
- width: 100%;
- box-shadow: 0px 2px 8px #000;
- -moz-box-shadow: 0px 2px 8px #000;
- -webkit-box-shadow: 0px 2px 8px #000;
-}
-
-#controls input {
- user-select: text;
- -moz-user-select: text;
- -webkit-user-select: text;
-}
-
-#previousPageButton {
- background: url('images/buttons.png') no-repeat 0px -23px;
- cursor: default;
- display: inline-block;
- float: left;
- margin: 0px;
- width: 28px;
- height: 23px;
-}
-
-#previousPageButton.down {
- background: url('images/buttons.png') no-repeat 0px -46px;
-}
-
-#previousPageButton.disabled {
- background: url('images/buttons.png') no-repeat 0px 0px;
-}
-
-#nextPageButton {
- background: url('images/buttons.png') no-repeat -28px -23px;
- cursor: default;
- display: inline-block;
- float: left;
- margin: 0px;
- width: 28px;
- height: 23px;
-}
-
-#nextPageButton.down {
- background: url('images/buttons.png') no-repeat -28px -46px;
-}
-
-#nextPageButton.disabled {
- background: url('images/buttons.png') no-repeat -28px 0px;
-}
-
-#openFileButton {
- background: url('images/buttons.png') no-repeat -56px -23px;
- cursor: default;
- display: inline-block;
- float: left;
- margin: 0px 0px 0px 3px;
- width: 29px;
- height: 23px;
-}
-
-#openFileButton.down {
- background: url('images/buttons.png') no-repeat -56px -46px;
-}
-
-#openFileButton.disabled {
- background: url('images/buttons.png') no-repeat -56px 0px;
-}
-
-#fileInput {
- display: none;
-}
-
-#pageNumber {
- text-align: right;
-}
-
-#sidebar {
- background-color: rgba(0, 0, 0, 0.8);
- position: fixed;
- width: 150px;
- top: 62px;
- bottom: 18px;
- border-top-right-radius: 8px;
- border-bottom-right-radius: 8px;
- -moz-border-radius-topright: 8px;
- -moz-border-radius-bottomright: 8px;
- -webkit-border-top-right-radius: 8px;
- -webkit-border-bottom-right-radius: 8px;
-}
-
-#sidebarScrollView {
- position: absolute;
- overflow: hidden;
- overflow-y: auto;
- top: 40px;
- right: 10px;
- bottom: 10px;
- left: 10px;
-}
-
-#sidebarContentView {
- height: auto;
- width: 100px;
-}
-
-#viewer {
- margin: 44px 0px 0px;
- padding: 8px 0px;
-}
diff --git a/multi-page-viewer.html b/multi-page-viewer.html
deleted file mode 100644
index ffbdfe707..000000000
--- a/multi-page-viewer.html
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-pdf.js Multi-Page Viewer
-
-
-
-
-
-
-
-
-
-
-
-
- Previous/Next
-
-
-
- /
- --
- Page Number
-
-
-
- Zoom
-
-
-
-
- Open File
-
-
-
-
-
-
diff --git a/multi-page-viewer.js b/multi-page-viewer.js
deleted file mode 100644
index baad7809e..000000000
--- a/multi-page-viewer.js
+++ /dev/null
@@ -1,466 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
-/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
-
-"use strict";
-
-var PDFViewer = {
- queryParams: {},
-
- element: null,
-
- previousPageButton: null,
- nextPageButton: null,
- pageNumberInput: null,
- scaleSelect: null,
- fileInput: null,
-
- willJumpToPage: false,
-
- pdf: null,
-
- url: 'compressed.tracemonkey-pldi-09.pdf',
- pageNumber: 1,
- numberOfPages: 1,
-
- scale: 1.0,
-
- pageWidth: function() {
- return 816 * PDFViewer.scale;
- },
-
- pageHeight: function() {
- return 1056 * PDFViewer.scale;
- },
-
- lastPagesDrawn: [],
-
- visiblePages: function() {
- var pageHeight = PDFViewer.pageHeight() + 20; // Add 20 for the margins.
- var windowTop = window.pageYOffset;
- var windowBottom = window.pageYOffset + window.innerHeight;
- var pageStartIndex = Math.floor(windowTop / pageHeight);
- var pageStopIndex = Math.ceil(windowBottom / pageHeight);
-
- var pages = [];
-
- for (var i = pageStartIndex; i <= pageStopIndex; i++) {
- pages.push(i + 1);
- }
-
- return pages;
- },
-
- createPage: function(num) {
- var anchor = document.createElement('a');
- anchor.name = '' + num;
-
- var div = document.createElement('div');
- div.id = 'pageContainer' + num;
- div.className = 'page';
- div.style.width = PDFViewer.pageWidth() + 'px';
- div.style.height = PDFViewer.pageHeight() + 'px';
-
- PDFViewer.element.appendChild(anchor);
- PDFViewer.element.appendChild(div);
- },
-
- removePage: function(num) {
- var div = document.getElementById('pageContainer' + num);
-
- if (div) {
- while (div.hasChildNodes()) {
- div.removeChild(div.firstChild);
- }
- }
- },
-
- drawPage: function(num) {
- if (!PDFViewer.pdf) {
- return;
- }
-
- var div = document.getElementById('pageContainer' + num);
- var canvas = document.createElement('canvas');
-
- if (div && !div.hasChildNodes()) {
- div.appendChild(canvas);
-
- var page = PDFViewer.pdf.getPage(num);
-
- canvas.id = 'page' + num;
- canvas.mozOpaque = true;
-
- // Canvas dimensions must be specified in CSS pixels. CSS pixels
- // are always 96 dpi. These dimensions are 8.5in x 11in at 96dpi.
- canvas.width = PDFViewer.pageWidth();
- canvas.height = PDFViewer.pageHeight();
-
- var ctx = canvas.getContext('2d');
- ctx.save();
- ctx.fillStyle = 'rgb(255, 255, 255)';
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- ctx.restore();
-
- var gfx = new CanvasGraphics(ctx);
- var fonts = [];
-
- // page.compile will collect all fonts for us, once we have loaded them
- // we can trigger the actual page rendering with page.display
- page.compile(gfx, fonts);
-
- var areFontsReady = true;
-
- // Inspect fonts and translate the missing one
- var fontCount = fonts.length;
-
- for (var i = 0; i < fontCount; i++) {
- var font = fonts[i];
-
- if (Fonts[font.name]) {
- areFontsReady = areFontsReady && !Fonts[font.name].loading;
- continue;
- }
-
- new Font(font.name, font.file, font.properties);
-
- areFontsReady = false;
- }
-
- var pageInterval;
-
- var delayLoadFont = function() {
- for (var i = 0; i < fontCount; i++) {
- if (Fonts[font.name].loading) {
- return;
- }
- }
-
- clearInterval(pageInterval);
-
- while (div.hasChildNodes()) {
- div.removeChild(div.firstChild);
- }
-
- PDFViewer.drawPage(num);
- }
-
- if (!areFontsReady) {
- pageInterval = setInterval(delayLoadFont, 10);
- return;
- }
-
- page.display(gfx);
- }
- },
-
- changeScale: function(num) {
- while (PDFViewer.element.hasChildNodes()) {
- PDFViewer.element.removeChild(PDFViewer.element.firstChild);
- }
-
- PDFViewer.scale = num / 100;
-
- var i;
-
- if (PDFViewer.pdf) {
- for (i = 1; i <= PDFViewer.numberOfPages; i++) {
- PDFViewer.createPage(i);
- }
-
- if (PDFViewer.numberOfPages > 0) {
- PDFViewer.drawPage(1);
- }
- }
-
- for (i = 0; i < PDFViewer.scaleSelect.childNodes; i++) {
- var option = PDFViewer.scaleSelect.childNodes[i];
-
- if (option.value == num) {
- if (!option.selected) {
- option.selected = 'selected';
- }
- } else {
- if (option.selected) {
- option.removeAttribute('selected');
- }
- }
- }
-
- PDFViewer.scaleSelect.value = Math.floor(PDFViewer.scale * 100) + '%';
- },
-
- goToPage: function(num) {
- if (1 <= num && num <= PDFViewer.numberOfPages) {
- PDFViewer.pageNumber = num;
- PDFViewer.pageNumberInput.value = PDFViewer.pageNumber;
- PDFViewer.willJumpToPage = true;
-
- document.location.hash = PDFViewer.pageNumber;
-
- PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ?
- 'disabled' : '';
- PDFViewer.nextPageButton.className = (PDFViewer.pageNumber === PDFViewer.numberOfPages) ?
- 'disabled' : '';
- }
- },
-
- goToPreviousPage: function() {
- if (PDFViewer.pageNumber > 1) {
- PDFViewer.goToPage(--PDFViewer.pageNumber);
- }
- },
-
- goToNextPage: function() {
- if (PDFViewer.pageNumber < PDFViewer.numberOfPages) {
- PDFViewer.goToPage(++PDFViewer.pageNumber);
- }
- },
-
- openURL: function(url) {
- PDFViewer.url = url;
- document.title = url;
-
- var req = new XMLHttpRequest();
- req.open('GET', url);
- req.mozResponseType = req.responseType = 'arraybuffer';
- req.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200;
-
- req.onreadystatechange = function() {
- if (req.readyState === 4 && req.status === req.expected) {
- var data = req.mozResponseArrayBuffer ||
- req.mozResponse ||
- req.responseArrayBuffer ||
- req.response;
-
- PDFViewer.readPDF(data);
- }
- };
-
- req.send(null);
- },
-
- readPDF: function(data) {
- while (PDFViewer.element.hasChildNodes()) {
- PDFViewer.element.removeChild(PDFViewer.element.firstChild);
- }
-
- PDFViewer.pdf = new PDFDoc(new Stream(data));
- PDFViewer.numberOfPages = PDFViewer.pdf.numPages;
- document.getElementById('numPages').innerHTML = PDFViewer.numberOfPages.toString();
-
- for (var i = 1; i <= PDFViewer.numberOfPages; i++) {
- PDFViewer.createPage(i);
- }
-
- if (PDFViewer.numberOfPages > 0) {
- PDFViewer.drawPage(1);
- document.location.hash = 1;
- }
-
- PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ?
- 'disabled' : '';
- PDFViewer.nextPageButton.className = (PDFViewer.pageNumber === PDFViewer.numberOfPages) ?
- 'disabled' : '';
- }
-};
-
-window.onload = function() {
-
- // Parse the URL query parameters into a cached object.
- PDFViewer.queryParams = function() {
- var qs = window.location.search.substring(1);
- var kvs = qs.split('&');
- var params = {};
- for (var i = 0; i < kvs.length; ++i) {
- var kv = kvs[i].split('=');
- params[unescape(kv[0])] = unescape(kv[1]);
- }
-
- return params;
- }();
-
- PDFViewer.element = document.getElementById('viewer');
-
- PDFViewer.pageNumberInput = document.getElementById('pageNumber');
- PDFViewer.pageNumberInput.onkeydown = function(evt) {
- var charCode = evt.charCode || evt.keyCode;
-
- // Up arrow key.
- if (charCode === 38) {
- PDFViewer.goToNextPage();
- this.select();
- }
-
- // Down arrow key.
- else if (charCode === 40) {
- PDFViewer.goToPreviousPage();
- this.select();
- }
-
- // All other non-numeric keys (excluding Left arrow, Right arrow,
- // Backspace, and Delete keys).
- else if ((charCode < 48 || charCode > 57) &&
- charCode !== 8 && // Backspace
- charCode !== 46 && // Delete
- charCode !== 37 && // Left arrow
- charCode !== 39 // Right arrow
- ) {
- return false;
- }
-
- return true;
- };
- PDFViewer.pageNumberInput.onkeyup = function(evt) {
- var charCode = evt.charCode || evt.keyCode;
-
- // All numeric keys, Backspace, and Delete.
- if ((charCode >= 48 && charCode <= 57) ||
- charCode === 8 || // Backspace
- charCode === 46 // Delete
- ) {
- PDFViewer.goToPage(this.value);
- }
-
- this.focus();
- };
-
- PDFViewer.previousPageButton = document.getElementById('previousPageButton');
- PDFViewer.previousPageButton.onclick = function(evt) {
- if (this.className.indexOf('disabled') === -1) {
- PDFViewer.goToPreviousPage();
- }
- };
- PDFViewer.previousPageButton.onmousedown = function(evt) {
- if (this.className.indexOf('disabled') === -1) {
- this.className = 'down';
- }
- };
- PDFViewer.previousPageButton.onmouseup = function(evt) {
- this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
- };
- PDFViewer.previousPageButton.onmouseout = function(evt) {
- this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
- };
-
- PDFViewer.nextPageButton = document.getElementById('nextPageButton');
- PDFViewer.nextPageButton.onclick = function(evt) {
- if (this.className.indexOf('disabled') === -1) {
- PDFViewer.goToNextPage();
- }
- };
- PDFViewer.nextPageButton.onmousedown = function(evt) {
- if (this.className.indexOf('disabled') === -1) {
- this.className = 'down';
- }
- };
- PDFViewer.nextPageButton.onmouseup = function(evt) {
- this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
- };
- PDFViewer.nextPageButton.onmouseout = function(evt) {
- this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
- };
-
- PDFViewer.scaleSelect = document.getElementById('scaleSelect');
- PDFViewer.scaleSelect.onchange = function(evt) {
- PDFViewer.changeScale(parseInt(this.value));
- };
-
- if (window.File && window.FileReader && window.FileList && window.Blob) {
- var openFileButton = document.getElementById('openFileButton');
- openFileButton.onclick = function(evt) {
- if (this.className.indexOf('disabled') === -1) {
- PDFViewer.fileInput.click();
- }
- };
- openFileButton.onmousedown = function(evt) {
- if (this.className.indexOf('disabled') === -1) {
- this.className = 'down';
- }
- };
- openFileButton.onmouseup = function(evt) {
- this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
- };
- openFileButton.onmouseout = function(evt) {
- this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
- };
-
- PDFViewer.fileInput = document.getElementById('fileInput');
- PDFViewer.fileInput.onchange = function(evt) {
- var files = evt.target.files;
-
- if (files.length > 0) {
- var file = files[0];
- var fileReader = new FileReader();
-
- document.title = file.name;
-
- // Read the local file into a Uint8Array.
- fileReader.onload = function(evt) {
- var data = evt.target.result;
- var buffer = new ArrayBuffer(data.length);
- var uint8Array = new Uint8Array(buffer);
-
- for (var i = 0; i < data.length; i++) {
- uint8Array[i] = data.charCodeAt(i);
- }
-
- PDFViewer.readPDF(uint8Array);
- };
-
- // Read as a binary string since "readAsArrayBuffer" is not yet
- // implemented in Firefox.
- fileReader.readAsBinaryString(file);
- }
- };
- PDFViewer.fileInput.value = null;
- } else {
- document.getElementById('fileWrapper').style.display = 'none';
- }
-
- PDFViewer.pageNumber = parseInt(PDFViewer.queryParams.page) || PDFViewer.pageNumber;
- PDFViewer.scale = parseInt(PDFViewer.scaleSelect.value) / 100 || 1.0;
-
- PDFViewer.openURL(PDFViewer.queryParams.file || PDFViewer.url);
-
- window.onscroll = function(evt) {
- var lastPagesDrawn = PDFViewer.lastPagesDrawn;
- var visiblePages = PDFViewer.visiblePages();
-
- var pagesToDraw = [];
- var pagesToKeep = [];
- var pagesToRemove = [];
-
- var i;
-
- // Determine which visible pages were not previously drawn.
- for (i = 0; i < visiblePages.length; i++) {
- if (lastPagesDrawn.indexOf(visiblePages[i]) === -1) {
- pagesToDraw.push(visiblePages[i]);
- PDFViewer.drawPage(visiblePages[i]);
- } else {
- pagesToKeep.push(visiblePages[i]);
- }
- }
-
- // Determine which previously drawn pages are no longer visible.
- for (i = 0; i < lastPagesDrawn.length; i++) {
- if (visiblePages.indexOf(lastPagesDrawn[i]) === -1) {
- pagesToRemove.push(lastPagesDrawn[i]);
- PDFViewer.removePage(lastPagesDrawn[i]);
- }
- }
-
- PDFViewer.lastPagesDrawn = pagesToDraw.concat(pagesToKeep);
-
- // Update the page number input with the current page number.
- if (!PDFViewer.willJumpToPage && visiblePages.length > 0) {
- PDFViewer.pageNumber = PDFViewer.pageNumberInput.value = visiblePages[0];
- PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ?
- 'disabled' : '';
- PDFViewer.nextPageButton.className = (PDFViewer.pageNumber === PDFViewer.numberOfPages) ?
- 'disabled' : '';
- } else {
- PDFViewer.willJumpToPage = false;
- }
- };
-};
diff --git a/multi_page_viewer.css b/multi_page_viewer.css
new file mode 100644
index 000000000..b3eaab792
--- /dev/null
+++ b/multi_page_viewer.css
@@ -0,0 +1,197 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+body {
+ background-color: #929292;
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode', Helvetica, Arial, Verdana, sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+canvas {
+ box-shadow: 0px 4px 10px #000;
+ -moz-box-shadow: 0px 4px 10px #000;
+ -webkit-box-shadow: 0px 4px 10px #000;
+}
+
+span {
+ font-size: 0.8em;
+}
+
+.control {
+ display: inline-block;
+ float: left;
+ margin: 0px 20px 0px 0px;
+ padding: 0px 4px 0px 0px;
+}
+
+.control > input {
+ float: left;
+ border: 1px solid #4d4d4d;
+ height: 20px;
+ padding: 0px;
+ margin: 0px 2px 0px 0px;
+ border-radius: 4px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
+ -moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
+ -webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
+}
+
+.control > select {
+ float: left;
+ border: 1px solid #4d4d4d;
+ height: 22px;
+ padding: 2px 0px 0px;
+ margin: 0px 0px 1px;
+ border-radius: 4px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
+ -moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
+ -webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
+}
+
+.control > span {
+ cursor: default;
+ float: left;
+ height: 18px;
+ margin: 5px 2px 0px;
+ padding: 0px;
+ user-select: none;
+ -moz-user-select: none;
+ -webkit-user-select: none;
+}
+
+.control .label {
+ clear: both;
+ float: left;
+ font-size: 0.65em;
+ margin: 2px 0px 0px;
+ position: relative;
+ text-align: center;
+ width: 100%;
+}
+
+.page {
+ width: 816px;
+ height: 1056px;
+ margin: 10px auto;
+}
+
+#controls {
+ background-color: #eee;
+ border-bottom: 1px solid #666;
+ padding: 4px 0px 0px 8px;
+ position: fixed;
+ left: 0px;
+ top: 0px;
+ height: 40px;
+ width: 100%;
+ box-shadow: 0px 2px 8px #000;
+ -moz-box-shadow: 0px 2px 8px #000;
+ -webkit-box-shadow: 0px 2px 8px #000;
+}
+
+#controls input {
+ user-select: text;
+ -moz-user-select: text;
+ -webkit-user-select: text;
+}
+
+#previousPageButton {
+ background: url('images/buttons.png') no-repeat 0px -23px;
+ cursor: default;
+ display: inline-block;
+ float: left;
+ margin: 0px;
+ width: 28px;
+ height: 23px;
+}
+
+#previousPageButton.down {
+ background: url('images/buttons.png') no-repeat 0px -46px;
+}
+
+#previousPageButton.disabled {
+ background: url('images/buttons.png') no-repeat 0px 0px;
+}
+
+#nextPageButton {
+ background: url('images/buttons.png') no-repeat -28px -23px;
+ cursor: default;
+ display: inline-block;
+ float: left;
+ margin: 0px;
+ width: 28px;
+ height: 23px;
+}
+
+#nextPageButton.down {
+ background: url('images/buttons.png') no-repeat -28px -46px;
+}
+
+#nextPageButton.disabled {
+ background: url('images/buttons.png') no-repeat -28px 0px;
+}
+
+#openFileButton {
+ background: url('images/buttons.png') no-repeat -56px -23px;
+ cursor: default;
+ display: inline-block;
+ float: left;
+ margin: 0px 0px 0px 3px;
+ width: 29px;
+ height: 23px;
+}
+
+#openFileButton.down {
+ background: url('images/buttons.png') no-repeat -56px -46px;
+}
+
+#openFileButton.disabled {
+ background: url('images/buttons.png') no-repeat -56px 0px;
+}
+
+#fileInput {
+ display: none;
+}
+
+#pageNumber {
+ text-align: right;
+}
+
+#sidebar {
+ background-color: rgba(0, 0, 0, 0.8);
+ position: fixed;
+ width: 150px;
+ top: 62px;
+ bottom: 18px;
+ border-top-right-radius: 8px;
+ border-bottom-right-radius: 8px;
+ -moz-border-radius-topright: 8px;
+ -moz-border-radius-bottomright: 8px;
+ -webkit-border-top-right-radius: 8px;
+ -webkit-border-bottom-right-radius: 8px;
+}
+
+#sidebarScrollView {
+ position: absolute;
+ overflow: hidden;
+ overflow-y: auto;
+ top: 40px;
+ right: 10px;
+ bottom: 10px;
+ left: 10px;
+}
+
+#sidebarContentView {
+ height: auto;
+ width: 100px;
+}
+
+#viewer {
+ margin: 44px 0px 0px;
+ padding: 8px 0px;
+}
diff --git a/multi_page_viewer.html b/multi_page_viewer.html
new file mode 100644
index 000000000..47234686d
--- /dev/null
+++ b/multi_page_viewer.html
@@ -0,0 +1,51 @@
+
+
+
+pdf.js Multi-Page Viewer
+
+
+
+
+
+
+
+
+
+
+
+
+ Previous/Next
+
+
+
+ /
+ --
+ Page Number
+
+
+
+ Zoom
+
+
+
+
+ Open File
+
+
+
+
+
+
diff --git a/multi_page_viewer.js b/multi_page_viewer.js
new file mode 100644
index 000000000..3a02ea332
--- /dev/null
+++ b/multi_page_viewer.js
@@ -0,0 +1,458 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+"use strict";
+
+var PDFViewer = {
+ queryParams: {},
+
+ element: null,
+
+ previousPageButton: null,
+ nextPageButton: null,
+ pageNumberInput: null,
+ scaleSelect: null,
+ fileInput: null,
+
+ willJumpToPage: false,
+
+ pdf: null,
+
+ url: 'compressed.tracemonkey-pldi-09.pdf',
+ pageNumber: 1,
+ numberOfPages: 1,
+
+ scale: 1.0,
+
+ pageWidth: function() {
+ return 816 * PDFViewer.scale;
+ },
+
+ pageHeight: function() {
+ return 1056 * PDFViewer.scale;
+ },
+
+ lastPagesDrawn: [],
+
+ visiblePages: function() {
+ var pageHeight = PDFViewer.pageHeight() + 20; // Add 20 for the margins.
+ var windowTop = window.pageYOffset;
+ var windowBottom = window.pageYOffset + window.innerHeight;
+ var pageStartIndex = Math.floor(windowTop / pageHeight);
+ var pageStopIndex = Math.ceil(windowBottom / pageHeight);
+
+ var pages = [];
+
+ for (var i = pageStartIndex; i <= pageStopIndex; i++) {
+ pages.push(i + 1);
+ }
+
+ return pages;
+ },
+
+ createPage: function(num) {
+ var anchor = document.createElement('a');
+ anchor.name = '' + num;
+
+ var div = document.createElement('div');
+ div.id = 'pageContainer' + num;
+ div.className = 'page';
+ div.style.width = PDFViewer.pageWidth() + 'px';
+ div.style.height = PDFViewer.pageHeight() + 'px';
+
+ PDFViewer.element.appendChild(anchor);
+ PDFViewer.element.appendChild(div);
+ },
+
+ removePage: function(num) {
+ var div = document.getElementById('pageContainer' + num);
+
+ if (div) {
+ while (div.hasChildNodes()) {
+ div.removeChild(div.firstChild);
+ }
+ }
+ },
+
+ drawPage: function(num) {
+ if (!PDFViewer.pdf) {
+ return;
+ }
+
+ var div = document.getElementById('pageContainer' + num);
+ var canvas = document.createElement('canvas');
+
+ if (div && !div.hasChildNodes()) {
+ div.appendChild(canvas);
+
+ var page = PDFViewer.pdf.getPage(num);
+
+ canvas.id = 'page' + num;
+ canvas.mozOpaque = true;
+
+ // Canvas dimensions must be specified in CSS pixels. CSS pixels
+ // are always 96 dpi. These dimensions are 8.5in x 11in at 96dpi.
+ canvas.width = PDFViewer.pageWidth();
+ canvas.height = PDFViewer.pageHeight();
+
+ var ctx = canvas.getContext('2d');
+ ctx.save();
+ ctx.fillStyle = 'rgb(255, 255, 255)';
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ ctx.restore();
+
+ var gfx = new CanvasGraphics(ctx);
+ var fonts = [];
+
+ // page.compile will collect all fonts for us, once we have loaded them
+ // we can trigger the actual page rendering with page.display
+ page.compile(gfx, fonts);
+
+ var areFontsReady = true;
+
+ // Inspect fonts and translate the missing one
+ var fontCount = fonts.length;
+
+ for (var i = 0; i < fontCount; i++) {
+ var font = fonts[i];
+
+ if (Fonts[font.name]) {
+ areFontsReady = areFontsReady && !Fonts[font.name].loading;
+ continue;
+ }
+
+ new Font(font.name, font.file, font.properties);
+
+ areFontsReady = false;
+ }
+
+ var pageInterval;
+
+ var delayLoadFont = function() {
+ for (var i = 0; i < fontCount; i++) {
+ if (Fonts[font.name].loading) {
+ return;
+ }
+ }
+
+ clearInterval(pageInterval);
+
+ while (div.hasChildNodes()) {
+ div.removeChild(div.firstChild);
+ }
+
+ PDFViewer.drawPage(num);
+ }
+
+ if (!areFontsReady) {
+ pageInterval = setInterval(delayLoadFont, 10);
+ return;
+ }
+
+ page.display(gfx);
+ }
+ },
+
+ changeScale: function(num) {
+ while (PDFViewer.element.hasChildNodes()) {
+ PDFViewer.element.removeChild(PDFViewer.element.firstChild);
+ }
+
+ PDFViewer.scale = num / 100;
+
+ var i;
+
+ if (PDFViewer.pdf) {
+ for (i = 1; i <= PDFViewer.numberOfPages; i++) {
+ PDFViewer.createPage(i);
+ }
+
+ if (PDFViewer.numberOfPages > 0) {
+ PDFViewer.drawPage(1);
+ }
+ }
+
+ for (i = 0; i < PDFViewer.scaleSelect.childNodes; i++) {
+ var option = PDFViewer.scaleSelect.childNodes[i];
+
+ if (option.value == num) {
+ if (!option.selected) {
+ option.selected = 'selected';
+ }
+ } else {
+ if (option.selected) {
+ option.removeAttribute('selected');
+ }
+ }
+ }
+
+ PDFViewer.scaleSelect.value = Math.floor(PDFViewer.scale * 100) + '%';
+ },
+
+ goToPage: function(num) {
+ if (1 <= num && num <= PDFViewer.numberOfPages) {
+ PDFViewer.pageNumber = num;
+ PDFViewer.pageNumberInput.value = PDFViewer.pageNumber;
+ PDFViewer.willJumpToPage = true;
+
+ document.location.hash = PDFViewer.pageNumber;
+
+ PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ? 'disabled' : '';
+ PDFViewer.nextPageButton.className = (PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
+ }
+ },
+
+ goToPreviousPage: function() {
+ if (PDFViewer.pageNumber > 1) {
+ PDFViewer.goToPage(--PDFViewer.pageNumber);
+ }
+ },
+
+ goToNextPage: function() {
+ if (PDFViewer.pageNumber < PDFViewer.numberOfPages) {
+ PDFViewer.goToPage(++PDFViewer.pageNumber);
+ }
+ },
+
+ openURL: function(url) {
+ PDFViewer.url = url;
+ document.title = url;
+
+ var req = new XMLHttpRequest();
+ req.open('GET', url);
+ req.mozResponseType = req.responseType = 'arraybuffer';
+ req.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200;
+
+ req.onreadystatechange = function() {
+ if (req.readyState === 4 && req.status === req.expected) {
+ var data = req.mozResponseArrayBuffer || req.mozResponse || req.responseArrayBuffer || req.response;
+
+ PDFViewer.readPDF(data);
+ }
+ };
+
+ req.send(null);
+ },
+
+ readPDF: function(data) {
+ while (PDFViewer.element.hasChildNodes()) {
+ PDFViewer.element.removeChild(PDFViewer.element.firstChild);
+ }
+
+ PDFViewer.pdf = new PDFDoc(new Stream(data));
+ PDFViewer.numberOfPages = PDFViewer.pdf.numPages;
+ document.getElementById('numPages').innerHTML = PDFViewer.numberOfPages.toString();
+
+ for (var i = 1; i <= PDFViewer.numberOfPages; i++) {
+ PDFViewer.createPage(i);
+ }
+
+ if (PDFViewer.numberOfPages > 0) {
+ PDFViewer.drawPage(1);
+ document.location.hash = 1;
+ }
+
+ PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ? 'disabled' : '';
+ PDFViewer.nextPageButton.className = (PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
+ }
+};
+
+window.onload = function() {
+
+ // Parse the URL query parameters into a cached object.
+ PDFViewer.queryParams = function() {
+ var qs = window.location.search.substring(1);
+ var kvs = qs.split('&');
+ var params = {};
+
+ for (var i = 0; i < kvs.length; ++i) {
+ var kv = kvs[i].split('=');
+ params[unescape(kv[0])] = unescape(kv[1]);
+ }
+
+ return params;
+ }();
+
+ PDFViewer.element = document.getElementById('viewer');
+
+ PDFViewer.pageNumberInput = document.getElementById('pageNumber');
+ PDFViewer.pageNumberInput.onkeydown = function(evt) {
+ var charCode = evt.charCode || evt.keyCode;
+
+ // Up arrow key.
+ if (charCode === 38) {
+ PDFViewer.goToNextPage();
+ this.select();
+ }
+
+ // Down arrow key.
+ else if (charCode === 40) {
+ PDFViewer.goToPreviousPage();
+ this.select();
+ }
+
+ // All other non-numeric keys (excluding Left arrow, Right arrow,
+ // Backspace, and Delete keys).
+ else if ((charCode < 48 || charCode > 57) &&
+ charCode !== 8 && // Backspace
+ charCode !== 46 && // Delete
+ charCode !== 37 && // Left arrow
+ charCode !== 39 // Right arrow
+ ) {
+ return false;
+ }
+
+ return true;
+ };
+ PDFViewer.pageNumberInput.onkeyup = function(evt) {
+ var charCode = evt.charCode || evt.keyCode;
+
+ // All numeric keys, Backspace, and Delete.
+ if ((charCode >= 48 && charCode <= 57) ||
+ charCode === 8 || // Backspace
+ charCode === 46 // Delete
+ ) {
+ PDFViewer.goToPage(this.value);
+ }
+
+ this.focus();
+ };
+
+ PDFViewer.previousPageButton = document.getElementById('previousPageButton');
+ PDFViewer.previousPageButton.onclick = function(evt) {
+ if (this.className.indexOf('disabled') === -1) {
+ PDFViewer.goToPreviousPage();
+ }
+ };
+ PDFViewer.previousPageButton.onmousedown = function(evt) {
+ if (this.className.indexOf('disabled') === -1) {
+ this.className = 'down';
+ }
+ };
+ PDFViewer.previousPageButton.onmouseup = function(evt) {
+ this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+ };
+ PDFViewer.previousPageButton.onmouseout = function(evt) {
+ this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+ };
+
+ PDFViewer.nextPageButton = document.getElementById('nextPageButton');
+ PDFViewer.nextPageButton.onclick = function(evt) {
+ if (this.className.indexOf('disabled') === -1) {
+ PDFViewer.goToNextPage();
+ }
+ };
+ PDFViewer.nextPageButton.onmousedown = function(evt) {
+ if (this.className.indexOf('disabled') === -1) {
+ this.className = 'down';
+ }
+ };
+ PDFViewer.nextPageButton.onmouseup = function(evt) {
+ this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+ };
+ PDFViewer.nextPageButton.onmouseout = function(evt) {
+ this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+ };
+
+ PDFViewer.scaleSelect = document.getElementById('scaleSelect');
+ PDFViewer.scaleSelect.onchange = function(evt) {
+ PDFViewer.changeScale(parseInt(this.value));
+ };
+
+ if (window.File && window.FileReader && window.FileList && window.Blob) {
+ var openFileButton = document.getElementById('openFileButton');
+ openFileButton.onclick = function(evt) {
+ if (this.className.indexOf('disabled') === -1) {
+ PDFViewer.fileInput.click();
+ }
+ };
+ openFileButton.onmousedown = function(evt) {
+ if (this.className.indexOf('disabled') === -1) {
+ this.className = 'down';
+ }
+ };
+ openFileButton.onmouseup = function(evt) {
+ this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+ };
+ openFileButton.onmouseout = function(evt) {
+ this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+ };
+
+ PDFViewer.fileInput = document.getElementById('fileInput');
+ PDFViewer.fileInput.onchange = function(evt) {
+ var files = evt.target.files;
+
+ if (files.length > 0) {
+ var file = files[0];
+ var fileReader = new FileReader();
+
+ document.title = file.name;
+
+ // Read the local file into a Uint8Array.
+ fileReader.onload = function(evt) {
+ var data = evt.target.result;
+ var buffer = new ArrayBuffer(data.length);
+ var uint8Array = new Uint8Array(buffer);
+
+ for (var i = 0; i < data.length; i++) {
+ uint8Array[i] = data.charCodeAt(i);
+ }
+
+ PDFViewer.readPDF(uint8Array);
+ };
+
+ // Read as a binary string since "readAsArrayBuffer" is not yet
+ // implemented in Firefox.
+ fileReader.readAsBinaryString(file);
+ }
+ };
+ PDFViewer.fileInput.value = null;
+ } else {
+ document.getElementById('fileWrapper').style.display = 'none';
+ }
+
+ PDFViewer.pageNumber = parseInt(PDFViewer.queryParams.page) || PDFViewer.pageNumber;
+ PDFViewer.scale = parseInt(PDFViewer.scaleSelect.value) / 100 || 1.0;
+
+ PDFViewer.openURL(PDFViewer.queryParams.file || PDFViewer.url);
+
+ window.onscroll = function(evt) {
+ var lastPagesDrawn = PDFViewer.lastPagesDrawn;
+ var visiblePages = PDFViewer.visiblePages();
+
+ var pagesToDraw = [];
+ var pagesToKeep = [];
+ var pagesToRemove = [];
+
+ var i;
+
+ // Determine which visible pages were not previously drawn.
+ for (i = 0; i < visiblePages.length; i++) {
+ if (lastPagesDrawn.indexOf(visiblePages[i]) === -1) {
+ pagesToDraw.push(visiblePages[i]);
+ PDFViewer.drawPage(visiblePages[i]);
+ } else {
+ pagesToKeep.push(visiblePages[i]);
+ }
+ }
+
+ // Determine which previously drawn pages are no longer visible.
+ for (i = 0; i < lastPagesDrawn.length; i++) {
+ if (visiblePages.indexOf(lastPagesDrawn[i]) === -1) {
+ pagesToRemove.push(lastPagesDrawn[i]);
+ PDFViewer.removePage(lastPagesDrawn[i]);
+ }
+ }
+
+ PDFViewer.lastPagesDrawn = pagesToDraw.concat(pagesToKeep);
+
+ // Update the page number input with the current page number.
+ if (!PDFViewer.willJumpToPage && visiblePages.length > 0) {
+ PDFViewer.pageNumber = PDFViewer.pageNumberInput.value = visiblePages[0];
+ PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ? 'disabled' : '';
+ PDFViewer.nextPageButton.className = (PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
+ } else {
+ PDFViewer.willJumpToPage = false;
+ }
+ };
+};