Commit 50cae699 by Brian Wilson

define pdfviewer.js, and use from static_pdfbook.html

parent c234f362
...@@ -95,26 +95,17 @@ select { ...@@ -95,26 +95,17 @@ select {
*/ */
/* outer/inner center provides horizontal center */ /* outer/inner center provides horizontal center */
html[dir='ltr'] .outerCenter { .outerCenter {
float: right; float: right;
position: relative; position: relative;
right: 50%; right: 50%;
} }
html[dir='rtl'] .outerCenter {
float: left; .innerCenter {
position: relative;
left: 50%;
}
html[dir='ltr'] .innerCenter {
float: right; float: right;
position: relative; position: relative;
right: -50%; right: -50%;
} }
html[dir='rtl'] .innerCenter {
float: left;
position: relative;
left: -50%;
}
#outerContainer { #outerContainer {
width: 100%; width: 100%;
...@@ -228,9 +219,9 @@ html[dir='rtl'] #sidebarContent { ...@@ -228,9 +219,9 @@ html[dir='rtl'] #sidebarContent {
} }
.toolbar { .toolbar {
/* position: absolute; position: absolute;
left: 0; left: 0;
right: 0; */ right: 0;
height: 32px; height: 32px;
z-index: 9999; z-index: 9999;
cursor: default; cursor: default;
...@@ -367,11 +358,17 @@ html[dir='rtl'] .doorHanger:before { ...@@ -367,11 +358,17 @@ html[dir='rtl'] .doorHanger:before {
background-color: rgb(255, 137, 153); background-color: rgb(255, 137, 153);
} }
html[dir='ltr'] #toolbarViewerLeft { #toolbarViewerLeft {
margin-left: -1px; margin-left: -1px;
position: absolute;
top: 0;
left: 0;
} }
html[dir='rtl'] #toolbarViewerRight {
margin-left: -1px; #toolbarViewerRight {
position: absolute;
top: 0;
right: 0;
} }
/* /*
...@@ -387,35 +384,21 @@ html[dir='rtl'] #toolbarViewerLeft { ...@@ -387,35 +384,21 @@ html[dir='rtl'] #toolbarViewerLeft {
top: 0; top: 0;
right: 0; right: 0;
} }
*/html[dir='ltr'] #toolbarViewerLeft > *, */
html[dir='ltr'] #toolbarViewerMiddle > *, #toolbarViewerLeft > *,
html[dir='ltr'] #toolbarViewerRight > *, #toolbarViewerMiddle > *,
html[dir='ltr'] .findbar > * { #toolbarViewerRight > * {
float: left; float: left;
} }
html[dir='rtl'] #toolbarViewerLeft > *,
html[dir='rtl'] #toolbarViewerMiddle > *,
html[dir='rtl'] #toolbarViewerRight > *,
html[dir='rtl'] .findbar > * {
float: right;
}
html[dir='ltr'] .splitToolbarButton { .splitToolbarButton {
margin: 3px 2px 4px 0; margin: 3px 2px 4px 0;
display: inline-block; display: inline-block;
} }
html[dir='rtl'] .splitToolbarButton { .splitToolbarButton > .toolbarButton {
margin: 3px 0 4px 2px;
display: inline-block;
}
html[dir='ltr'] .splitToolbarButton > .toolbarButton {
border-radius: 0; border-radius: 0;
float: left; float: left;
} }
html[dir='rtl'] .splitToolbarButton > .toolbarButton {
border-radius: 0;
float: right;
}
.toolbarButton { .toolbarButton {
border: 0 none; border: 0 none;
...@@ -487,8 +470,7 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton { ...@@ -487,8 +470,7 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton {
0 0 1px hsla(0,0%,0%,.05); 0 0 1px hsla(0,0%,0%,.05);
z-index: 199; z-index: 199;
} }
html[dir='ltr'] .splitToolbarButton > .toolbarButton:first-child, .splitToolbarButton > .toolbarButton:first-child {
html[dir='rtl'] .splitToolbarButton > .toolbarButton:last-child {
position: relative; position: relative;
margin: 0; margin: 0;
margin-right: -1px; margin-right: -1px;
...@@ -496,8 +478,7 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton:last-child { ...@@ -496,8 +478,7 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton:last-child {
border-bottom-left-radius: 2px; border-bottom-left-radius: 2px;
border-right-color: transparent; border-right-color: transparent;
} }
html[dir='ltr'] .splitToolbarButton > .toolbarButton:last-child, .splitToolbarButton > .toolbarButton:last-child {
html[dir='rtl'] .splitToolbarButton > .toolbarButton:first-child {
position: relative; position: relative;
margin: 0; margin: 0;
margin-left: -1px; margin-left: -1px;
...@@ -513,12 +494,8 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton:first-child { ...@@ -513,12 +494,8 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton:first-child {
box-shadow: 0 0 0 1px hsla(0,0%,100%,.08); box-shadow: 0 0 0 1px hsla(0,0%,100%,.08);
display: inline-block; display: inline-block;
margin: 5px 0; margin: 5px 0;
}
html[dir='ltr'] .splitToolbarButtonSeparator {
float:left; float:left;
} }
html[dir='rtl'] .splitToolbarButtonSeparator {
float:right;
} }
.splitToolbarButton:hover > .splitToolbarButtonSeparator, .splitToolbarButton:hover > .splitToolbarButtonSeparator,
.splitToolbarButton.toggled > .splitToolbarButtonSeparator { .splitToolbarButton.toggled > .splitToolbarButtonSeparator {
...@@ -573,14 +550,9 @@ html[dir='rtl'] .splitToolbarButtonSeparator { ...@@ -573,14 +550,9 @@ html[dir='rtl'] .splitToolbarButtonSeparator {
transition-timing-function: ease; transition-timing-function: ease;
} }
html[dir='ltr'] .toolbarButton, .toolbarButton {
html[dir='ltr'] .dropdownToolbarButton {
margin: 3px 2px 4px 0; margin: 3px 2px 4px 0;
} }
html[dir='rtl'] .toolbarButton,
html[dir='rtl'] .dropdownToolbarButton {
margin: 3px 0 4px 2px;
}
.toolbarButton:hover, .toolbarButton:hover,
.toolbarButton:focus, .toolbarButton:focus,
...@@ -671,13 +643,8 @@ html[dir='rtl'] .dropdownToolbarButton { ...@@ -671,13 +643,8 @@ html[dir='rtl'] .dropdownToolbarButton {
padding: 3px 2px 2px; padding: 3px 2px 2px;
overflow: hidden; overflow: hidden;
background: url(images/toolbarButton-menuArrows.png) no-repeat; background: url(images/toolbarButton-menuArrows.png) no-repeat;
}
html[dir='ltr'] .dropdownToolbarButton {
background-position: 95%; background-position: 95%;
} }
html[dir='rtl'] .dropdownToolbarButton {
background-position: 5%;
}
.dropdownToolbarButton > select { .dropdownToolbarButton > select {
-webkit-appearance: none; -webkit-appearance: none;
...@@ -703,18 +670,12 @@ html[dir='rtl'] .dropdownToolbarButton { ...@@ -703,18 +670,12 @@ html[dir='rtl'] .dropdownToolbarButton {
border-bottom: 1px rgba(255, 255, 255, .5) solid; border-bottom: 1px rgba(255, 255, 255, .5) solid;
} }
html[dir='ltr'] .splitToolbarButton:first-child, .splitToolbarButton:first-child,
html[dir='ltr'] .toolbarButton:first-child, .toolbarButton:first-child,
html[dir='rtl'] .splitToolbarButton:last-child, .splitToolbarButton:last-child,
html[dir='rtl'] .toolbarButton:last-child { .toolbarButton:last-child {
margin-left: 4px; margin-left: 4px;
} }
html[dir='ltr'] .splitToolbarButton:last-child,
html[dir='ltr'] .toolbarButton:last-child,
html[dir='rtl'] .splitToolbarButton:first-child,
html[dir='rtl'] .toolbarButton:first-child {
margin-right: 4px;
}
.toolbarButtonSpacer { .toolbarButtonSpacer {
width: 30px; width: 30px;
...@@ -1047,7 +1008,7 @@ canvas { ...@@ -1047,7 +1008,7 @@ canvas {
display: block; display: block;
} }
.page { .pdfpage {
direction: ltr; direction: ltr;
width: 816px; width: 816px;
height: 1056px; height: 1056px;
...@@ -1060,12 +1021,12 @@ canvas { ...@@ -1060,12 +1021,12 @@ canvas {
background-color: white; background-color: white;
} }
.page > a { .pdfpage > a {
display: block; display: block;
/* position: absolute; */ /* position: absolute; */
} }
.page > a:hover { .pdfpage > a:hover {
opacity: 0.2; opacity: 0.2;
background: #ff0; background: #ff0;
-webkit-box-shadow: 0px 2px 10px #ff0; -webkit-box-shadow: 0px 2px 10px #ff0;
......
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Modified (and JQuerified) from PDF-JS sample code (viewer.js)
*/
/* globals: PDFJS as defined in pdf.js. Also assumes that jquery is included. */
//
// Disable workers to avoid yet another cross-origin issue (workers need the URL of
// the script to be loaded, and currently do not allow cross-origin scripts)
//
PDFJS.disableWorker = true;
(function($) {
$.fn.PDFViewer = function(options) {
var pdfViewer = this;
var pdfDocument = null;
var url = options['url'];
var pageNum = 1;
if (options.pageNum) {
pageNum = int(options.pageNum);
}
var currentScale = 1.0;
var currentScaleValue = "1";
var viewerElement = document.getElementById('viewer');
var ANNOT_MIN_SIZE = 10;
var DEFAULT_SCALE_DELTA = 1.1;
var UNKNOWN_SCALE = 0;
var MIN_SCALE = 0.25;
var MAX_SCALE = 4.0;
var setupText = function setupText(textdiv, content, viewport) {
function bindLink(link, dest) {
// TODO: get this to work for document-internal links
// link.href = PDFView.getDestinationHash(dest);
// link.onclick = function pageViewSetupLinksOnclick() {
// if (dest)
// PDFView.navigateTo(dest);
// return false;
// };
}
function createElementWithStyle(tagName, item, rect) {
if (!rect) {
rect = viewport.convertToViewportRectangle(item.rect);
rect = PDFJS.Util.normalizeRect(rect);
}
var element = document.createElement(tagName);
element.style.left = Math.floor(rect[0]) + 'px';
element.style.top = Math.floor(rect[1]) + 'px';
element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
// BW: my additions here, but should use css:
// TODO: move these to css
element.style.position = 'absolute';
element.style.cursor = 'auto';
return element;
}
function createTextAnnotation(item) {
var container = document.createElement('section');
container.className = 'annotText';
var rect = viewport.convertToViewportRectangle(item.rect);
rect = PDFJS.Util.normalizeRect(rect);
// sanity check because of OOo-generated PDFs
if ((rect[3] - rect[1]) < ANNOT_MIN_SIZE) {
rect[3] = rect[1] + ANNOT_MIN_SIZE;
}
if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) {
rect[2] = rect[0] + (rect[3] - rect[1]);
// make it square
}
var image = createElementWithStyle('img', item, rect);
var iconName = item.name;
}
content.getAnnotations().then(function(items) {
for (var i = 0; i < items.length; i++) {
var item = items[i];
switch (item.type) {
case 'Link':
var link = createElementWithStyle('a', item);
link.href = item.url || '';
if (!item.url)
bindLink(link, ('dest' in item) ? item.dest : null);
textdiv.appendChild(link);
break;
case 'Text':
var textAnnotation = createTextAnnotation(item);
if (textAnnotation)
textdiv.appendChild(textAnnotation);
break;
}
}
});
}
//
// Get page info from document, resize canvas accordingly, and render page
//
// function renderPage(num) {
renderPage = function(num) {
// Update logging:
log_event("book", { "type" : "gotopage", "old" : pageNum, "new" : num });
parentElement = viewerElement;
while (parentElement.hasChildNodes())
parentElement.removeChild(parentElement.lastChild);
// Using promise to fetch the page
pdfDocument.getPage(num).then(function(page) {
var viewport = page.getViewport(currentScale);
var pageDisplayWidth = viewport.width;
var pageDisplayHeight = viewport.height;
var pageDivHolder = document.createElement('div');
pageDivHolder.className = 'pdfpage';
pageDivHolder.style.width = pageDisplayWidth + 'px';
pageDivHolder.style.height = pageDisplayHeight + 'px';
parentElement.appendChild(pageDivHolder);
// Prepare canvas using PDF page dimensions
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = pageDisplayWidth;
canvas.height = pageDisplayHeight;
pageDivHolder.appendChild(canvas);
// Render PDF page into canvas context
var renderContext = {
canvasContext : context,
viewport : viewport
};
page.render(renderContext);
// Prepare and populate text elements layer
setupText(pageDivHolder, page, viewport);
});
pageNum = num;
// Update page counters
document.getElementById('numPages').textContent = 'of ' + pdfDocument.numPages;
$("#pageNumber").max = pdfDocument.numPages;
$("#pageNumber").val(pageNum);
}
// Go to previous page
prevPage = function prev_page() {
if (pageNum <= 1)
return;
renderPage(pageNum - 1);
log_event("book", { "type" : "prevpage", "new" : pageNum });
}
// Go to next page
nextPage = function next_page() {
if (pageNum >= pdfDocument.numPages)
return;
renderPage(pageNum + 1);
log_event("book", { "type" : "nextpage", "new" : pageNum });
}
// Check to see if
selectScaleOption = function(value) {
var options = $('#scaleSelect').options;
var predefinedValueFound = false;
for (var i = 0; i < options.length; i++) {
var option = options[i];
if (option.value != value) {
option.selected = false;
continue;
}
option.selected = true;
predefinedValueFound = true;
}
return predefinedValueFound;
}
setScale = function pdfViewSetScale(val, resetAutoSettings, noScroll) {
if (val == currentScale)
return;
currentScale = val;
var customScaleOption = $('#customScaleOption')[0];
customScaleOption.selected = false
var predefinedValueFound = selectScaleOption('' + currentScale);
if (!predefinedValueFound) {
customScaleOption.textContent = Math.round(currentScale * 10000) / 100 + '%';
customScaleOption.selected = true;
}
$('#zoom_in').disabled = (currentScale === MAX_SCALE);
$('#zoom_out').disabled = (currentScale === MIN_SCALE);
// Just call renderPage once the scale
// has been changed. If we were saving information about
// the rendering of other pages, we would need
// to reset those as well.
renderPage(pageNum);
};
parseScale = function pdfViewParseScale(value, resetAutoSettings, noScroll) {
// we shouldn't be choosing the 'custom' value -- it's only for display.
// Check, just in case.
if ('custom' == value)
return;
var scale = parseFloat(value);
if (scale) {
currentScaleValue = value;
setScale(scale, true, noScroll);
return;
}
};
zoomIn = function pdfViewZoomIn() {
var newScale = (currentScale * DEFAULT_SCALE_DELTA).toFixed(2);
newScale = Math.min(MAX_SCALE, newScale);
parseScale(newScale, true);
};
zoomOut = function pdfViewZoomOut() {
var newScale = (currentScale / DEFAULT_SCALE_DELTA).toFixed(2);
newScale = Math.max(MIN_SCALE, newScale);
parseScale(newScale, true);
};
//
// Asynchronously download PDF as an ArrayBuffer
//
PDFJS.getDocument(url).then(
function getDocument(_pdfDocument) {
pdfDocument = _pdfDocument;
renderPage(pageNum);
},
function getDocumentError(message, exception) {
// placeholder: don't expect errors :)
},
function getDocumentProgress(progressData) {
// placeholder: not yet ready to display loading progress
});
$("#previous").click(function(event) {
prevPage();
});
$("#next").click(function(event) {
nextPage();
});
$('#zoom_in').click(function(event) {
zoomIn();
});
$('#zoom_out').click(function(event) {
zoomOut();
});
$('#scaleSelect').change(function(event) {
parseScale(this.value);
});
}
})(jQuery);
<%inherit file="main.html" /> <%inherit file="main.html" />
<%namespace name='static' file='static_content.html'/> <%namespace name='static' file='static_content.html'/>
<%block name="title"><title>${course.number} Textbook</title></%block> <%block name="title">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>${course.number} Textbook</title>
</%block>
<%block name="headextra"> <%block name="headextra">
<%static:css group='course'/> <%static:css group='course'/>
<%static:js group='courseware'/> <%static:js group='courseware'/>
<link rel="stylesheet" href="/static/css/vendor/pdfjs/myviewer.css"/>
<script type="text/javascript" src="/static/js/vendor/pdfjs/pdf.js"></script>
<script type="text/javascript" src="/static/js/pdfviewer.js"></script>
</%block> </%block>
<%block name="js_extra"> <%block name="js_extra">
<script type="text/javascript" src="/static/js/vendor/pdf.js"></script>
<script type="text/javascript"> <script type="text/javascript">
//
// NOTE:
// Modifying the URL below to another server will likely *NOT* work. Because of browser
// security restrictions, we have to use a file server with special headers
// (CORS) - most servers don't support cross-origin browser requests.
//
var url = "${textbook['url']}";
//
// Disable workers to avoid yet another cross-origin issue (workers need the URL of
// the script to be loaded, and currently do not allow cross-origin scripts)
//
PDFJS.disableWorker = true;
var pdfDoc = null,
pageNum = ${int(page) if page is not None else 1},
scale = 0.8,
canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d');
//
// Get page info from document, resize canvas accordingly, and render page
//
function renderPage(num) {
// Using promise to fetch the page
pdfDoc.getPage(num).then(function(page) {
var viewport = page.getViewport(scale);
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context var url = "${textbook['url']}";
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
page.render(renderContext);
});
// Update page counters
document.getElementById('page_num').textContent = pageNum;
document.getElementById('page_count').textContent = pdfDoc.numPages;
}
//
// Go to previous page
//
function goPrevious() {
if (pageNum <= 1)
return;
pageNum--;
renderPage(pageNum);
}
//
// Go to next page
//
function goNext() {
if (pageNum >= pdfDoc.numPages)
return;
pageNum++;
renderPage(pageNum);
}
// $(document).ready(function() {
// Asynchronously download PDF as an ArrayBuffer $('#outerContainer').PDFViewer( {
// % if page is not None:
PDFJS.getDocument(url).then(function getPdfHelloWorld(_pdfDoc) { 'pageNum' : page,
pdfDoc = _pdfDoc; % endif
renderPage(pageNum); 'url' : url
});
}); });
</script> </script>
</%block> </%block>
<%include file="/courseware/course_navigation.html" args="active_page='pdftextbook/{0}'.format(book_index)" /> <%include file="/courseware/course_navigation.html" args="active_page='pdftextbook/{0}'.format(book_index)" />
<section class="container">
<div class="book-wrapper">
<section class="book">
<section class="page">
<div>
<button id="prev" onclick="goPrevious()">Previous</button>
<button id="next" onclick="goNext()">Next</button>
&nbsp; &nbsp;
<span>Page: <span id="page_num"></span> / <span id="page_count"></span></span>
</div>
<div>
<canvas id="the-canvas" style="border:1px solid black"></canvas>
</div>
</section> <div id="outerContainer">
</section> <div id="mainContainer">
</div> <div class="toolbar">
</section> <div id="toolbarContainer">
<div id="toolbarViewer">
<div id="toolbarViewerLeft">
<div class="splitToolbarButton">
<button class="toolbarButton pageUp" title="Previous Page" id="previous" tabindex="5">
<span>Previous</span>
</button>
<div class="splitToolbarButtonSeparator"></div>
<button class="toolbarButton pageDown" title="Next Page" id="next" tabindex="6">
<span>Next</span>
</button>
</div>
<label id="pageNumberLabel" class="toolbarLabel" for="pageNumber">Page: </label>
<input type="number" id="pageNumber" class="toolbarField pageNumber" value="1" size="4" min="1" tabindex="7">
</input>
<span id="numPages" class="toolbarLabel"></span>
</div>
<div class="outerCenter">
<div class="innerCenter" id="toolbarViewerMiddle">
<div class="splitToolbarButton">
<button class="toolbarButton zoomOut" id="zoom_out" title="Zoom Out" tabindex="8">
<span>Zoom Out</span>
</button>
<div class="splitToolbarButtonSeparator"></div>
<button class="toolbarButton zoomIn" id="zoom_in" title="Zoom In" tabindex="9">
<span>Zoom In</span>
</button>
</div>
<span id="scaleSelectContainer" class="dropdownToolbarButton">
<select id="scaleSelect" title="Zoom" oncontextmenu="return false;" tabindex="10">
<!--
<option id="pageAutoOption" value="auto" selected="selected">Automatic Zoom</option>
<option id="pageActualOption" value="page-actual">Actual Size</option>
<option id="pageFitOption" value="page-fit">Fit Page</option>
<option id="pageWidthOption" value="page-width">Full Width</option>
-->
<option id="customScaleOption" value="custom"></option>
<option value="0.5">50%</option>
<option value="0.75">75%</option>
<option value="1">100%</option>
<option value="1.25">125%</option>
<option value="1.5">150%</option>
<option value="2">200%</option>
</select>
</span>
</div>
</div>
</div>
</div>
</div>
<div id="viewerContainer">
<div id="viewer" contextmenu="viewerContextMenu"></div>
</div>
</div> <!-- mainContainer -->
</div> <!-- outerContainer -->
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment