From 5fa3ef6c19bb216d265d8c15838fb7a7c47df7ae Mon Sep 17 00:00:00 2001 From: Justin D'Arcangelo Date: Sun, 26 Jun 2011 02:14:57 -0400 Subject: [PATCH] Added experimental slide-out sidebar with page thumbnails. --- multi_page_viewer.css | 41 +++++++++++++++++-- multi_page_viewer.html | 13 +++--- multi_page_viewer.js | 90 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 132 insertions(+), 12 deletions(-) diff --git a/multi_page_viewer.css b/multi_page_viewer.css index b3eaab792..2eaca4870 100644 --- a/multi_page_viewer.css +++ b/multi_page_viewer.css @@ -74,6 +74,20 @@ span { width: 100%; } +.thumbnailPageNumber { + color: #fff; + font-size: 0.55em; + text-align: right; + margin: -6px 2px 6px 0px; + width: 102px; +} + +.thumbnail { + width: 104px; + height: 134px; + margin: 0px auto 10px; +} + .page { width: 816px; height: 1056px; @@ -163,27 +177,46 @@ span { } #sidebar { - background-color: rgba(0, 0, 0, 0.8); position: fixed; - width: 150px; + width: 200px; top: 62px; bottom: 18px; + left: -170px; + transition: left 0.25s ease-in-out 1s; + -moz-transition: left 0.25s ease-in-out 1s; + -webkit-transition: left 0.25s ease-in-out 1s; +} + +#sidebar:hover { + left: 0px; + transition: left 0.25s ease-in-out 0s; + -moz-transition: left 0.25s ease-in-out 0s; + -webkit-transition: left 0.25s ease-in-out 0s; +} + +#sidebarBox { + background-color: rgba(0, 0, 0, 0.7); + width: 150px; + height: 100%; 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; + box-shadow: 0px 2px 8px #000; + -moz-box-shadow: 0px 2px 8px #000; + -webkit-box-shadow: 0px 2px 8px #000; } #sidebarScrollView { position: absolute; overflow: hidden; overflow-y: auto; - top: 40px; - right: 10px; + top: 10px; bottom: 10px; left: 10px; + width: 130px; } #sidebarContentView { diff --git a/multi_page_viewer.html b/multi_page_viewer.html index 649e3a7cc..e90606a23 100644 --- a/multi_page_viewer.html +++ b/multi_page_viewer.html @@ -40,13 +40,16 @@ Open File - + --> + +
diff --git a/multi_page_viewer.js b/multi_page_viewer.js index aeb9ea38f..4f2bd5197 100644 --- a/multi_page_viewer.js +++ b/multi_page_viewer.js @@ -10,6 +10,8 @@ var PDFViewer = { element: null, + sidebarContentView: null, + previousPageButton: null, nextPageButton: null, pageNumberInput: null, @@ -52,6 +54,78 @@ var PDFViewer = { return pages; }, + createThumbnail: function(num) { + if (PDFViewer.sidebarContentView) { + var anchor = document.createElement('a'); + anchor.href = '#' + num; + + var containerDiv = document.createElement('div'); + containerDiv.id = 'thumbnailContainer' + num; + containerDiv.className = 'thumbnail'; + + var pageNumberDiv = document.createElement('div'); + pageNumberDiv.className = 'thumbnailPageNumber'; + pageNumberDiv.innerHTML = '' + num; + + anchor.appendChild(containerDiv); + PDFViewer.sidebarContentView.appendChild(anchor); + PDFViewer.sidebarContentView.appendChild(pageNumberDiv); + } + }, + + removeThumbnail: function(num) { + var div = document.getElementById('thumbnailContainer' + num); + + if (div) { + while (div.hasChildNodes()) { + div.removeChild(div.firstChild); + } + } + }, + + drawThumbnail: function(num) { + if (!PDFViewer.pdf) + return; + + var div = document.getElementById('thumbnailContainer' + num); + + if (div && !div.hasChildNodes()) { + var page = PDFViewer.pdf.getPage(num); + var canvas = document.createElement('canvas'); + + canvas.id = 'thumbnail' + 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 = 104; + canvas.height = 134; + div.appendChild(canvas); + + 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); + + // page.compile will collect all fonts for us, once we have loaded them + // we can trigger the actual page rendering with page.display + var fonts = []; + page.compile(gfx, fonts); + + var loadFont = function() { + if (!FontLoader.bind(fonts)) { + pageTimeout = window.setTimeout(loadFont, 10); + return; + } + page.display(gfx); + } + loadFont(); + } + }, + createPage: function(num) { var anchor = document.createElement('a'); anchor.name = '' + num; @@ -81,11 +155,11 @@ var PDFViewer = { return; var div = document.getElementById('pageContainer' + num); - var canvas = document.createElement('canvas'); - + if (div && !div.hasChildNodes()) { var page = PDFViewer.pdf.getPage(num); - + var canvas = document.createElement('canvas'); + canvas.id = 'page' + num; canvas.mozOpaque = true; @@ -130,6 +204,7 @@ var PDFViewer = { if (PDFViewer.pdf) { for (i = 1; i <= PDFViewer.numberOfPages; i++) { + PDFViewer.createThumbnail(i); PDFViewer.createPage(i); } } @@ -218,6 +293,13 @@ var PDFViewer = { if (PDFViewer.numberOfPages > 0) { PDFViewer.drawPage(1); document.location.hash = 1; + + setTimeout(function() { + for (var i = 1; i <= PDFViewer.numberOfPages; i++) { + PDFViewer.createThumbnail(i); + PDFViewer.drawThumbnail(i); + } + }, 500); } PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ? 'disabled' : ''; @@ -242,6 +324,8 @@ window.onload = function() { PDFViewer.element = document.getElementById('viewer'); + PDFViewer.sidebarContentView = document.getElementById('sidebarContentView'); + PDFViewer.pageNumberInput = document.getElementById('pageNumber'); PDFViewer.pageNumberInput.onkeydown = function(evt) { var charCode = evt.charCode || evt.keyCode;