X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=BookReader%2FBookReader.js;h=36379a126d77b251fcde88a8f45dc2c324022ef4;hb=32dcce1c6c33c22670b8c651356595c6a8c2a0ad;hp=c8b36de09041f63c6c25d36c86a4265abe3bae41;hpb=4aa498933124c7ba3702fcfe39d33d89924ac1e7;p=bookreader.git
diff --git a/BookReader/BookReader.js b/BookReader/BookReader.js
index c8b36de..36379a1 100644
--- a/BookReader/BookReader.js
+++ b/BookReader/BookReader.js
@@ -36,16 +36,25 @@ This file is part of BookReader.
// You must also add a numLeafs property before calling init().
function BookReader() {
+
+ // Mode constants
+ this.constMode1up = 1;
+ this.constMode2up = 2;
+ this.constModeThumb = 3;
+
this.reduce = 4;
- this.padding = 0;
- this.mode = 1; //1, 2, 3
- this.ui = 'full'; // UI mode
+ this.padding = 10; // Padding in 1up
+
+ this.mode = this.constMode1up;
+ this.ui = 'full'; // UI mode
+ this.uiAutoHide = false; // Controls whether nav/toolbar will autohide
// thumbnail mode
this.thumbWidth = 100; // will be overridden during prepareThumbnailView
this.thumbRowBuffer = 2; // number of rows to pre-cache out a view
this.thumbColumns = 6; // default
this.thumbMaxLoading = 4; // number of thumbnails to load at once
+ this.thumbPadding = 10; // spacing between thumbnails
this.displayedRows=[];
this.displayedIndices = [];
@@ -73,7 +82,7 @@ function BookReader() {
// We link to index.php to avoid redirect which breaks back button
// Should be overriden (before init) by custom implmentations.
- this.logoURL = 'http://www.archive.org/index.php';
+ this.logoURL = 'http://openlibrary.org';
// Base URL for UI images - should be overriden (before init) by
// custom implementations.
@@ -81,10 +90,6 @@ function BookReader() {
// path in the CSS. Would be better to automagically find that path.
this.imagesBaseURL = '/bookreader/images/';
- // Mode constants
- this.constMode1up = 1;
- this.constMode2up = 2;
- this.constModeThumb = 3;
// Zoom levels
// $$$ provide finer grained zooming
@@ -108,6 +113,25 @@ function BookReader() {
autofit: 'auto'
};
+ // This object/dictionary controls which optional features are enabled
+ // XXXmang in progress
+ this.features = {
+ // search
+ // read aloud
+ // open library entry
+ // table of contents
+ // embed/share ui
+ // info ui
+ };
+
+ // Text-to-Speech params
+ this.ttsPlaying = false;
+ this.ttsIndex = null; //leaf index
+ this.ttsPosition = -1; //chunk (paragraph) number
+ this.ttsBuffering = false;
+ this.ttsPoller = null;
+ this.ttsFormat = null;
+
return this;
};
@@ -157,13 +181,22 @@ BookReader.prototype.init = function() {
$("#BookReader").empty();
this.initToolbar(this.mode, this.ui); // Build inside of toolbar div
+
$("#BookReader").append("
");
$("#BRcontainer").append("");
+
+ // Autohide nav after showing for awhile
+ var self = this;
+ if (this.uiAutoHide) {
+ $(window).bind('load', function() {
+ setTimeout(function() { self.hideNavigation(); }, 3000);
+ });
+ };
$("#BRcontainer").bind('scroll', this, function(e) {
e.data.loadLeafs();
});
-
+
this.setupKeyListeners();
this.startLocationPolling();
@@ -235,6 +268,16 @@ BookReader.prototype.init = function() {
// Enact other parts of initial params
this.updateFromParams(params);
+
+ // We init the nav bar after the params processing so that the nav slider knows where
+ // it should start (doesn't jump after init)
+ this.initNavbar();
+ this.bindNavigationHandlers();
+
+ // Start AJAX request for OL data
+ if (this.getOpenLibraryRecord) {
+ this.getOpenLibraryRecord(this.gotOpenLibraryRecord);
+ }
}
BookReader.prototype.setupKeyListeners = function() {
@@ -321,7 +364,6 @@ BookReader.prototype.bindGestures = function(jElement) {
br.zoom(-1);
}
});
-
}
BookReader.prototype.setClickHandler2UP = function( element, data, handler) {
@@ -484,7 +526,7 @@ BookReader.prototype.drawLeafsThumbnail = function( seekIndex ) {
// Calculate the position of every thumbnail. $$$ cache instead of calculating on every draw
for (i=0; i viewWidth){
+ if (rightPos + (leafWidth + this.thumbPadding) > viewWidth){
currentRow++;
rightPos = 0;
leafIndex = 0;
@@ -504,13 +546,13 @@ BookReader.prototype.drawLeafsThumbnail = function( seekIndex ) {
if (leafHeight > leafMap[currentRow].height) {
leafMap[currentRow].height = leafHeight;
}
- if (leafIndex===0) { bottomPos += this.padding + leafMap[currentRow].height; }
- rightPos += leafWidth + this.padding;
+ if (leafIndex===0) { bottomPos += this.thumbPadding + leafMap[currentRow].height; }
+ rightPos += leafWidth + this.thumbPadding;
if (rightPos > maxRight) { maxRight = rightPos; }
leafIndex++;
if (i == seekIndex) {
- seekTop = bottomPos - this.padding - leafMap[currentRow].height;
+ seekTop = bottomPos - this.thumbPadding - leafMap[currentRow].height;
}
}
@@ -537,7 +579,7 @@ BookReader.prototype.drawLeafsThumbnail = function( seekIndex ) {
// Determine the thumbnails in view
for (i=0; i= scrollTop) && (leafTop <= scrollBottom);
var bottomInView = (leafBottom >= scrollTop) && (leafBottom <= scrollBottom);
var middleInView = (leafTop <=scrollTop) && (leafBottom>=scrollBottom);
@@ -595,7 +637,7 @@ BookReader.prototype.drawLeafsThumbnail = function( seekIndex ) {
div.style.position = "absolute";
div.className = "BRpagedivthumb";
- left += this.padding;
+ left += this.thumbPadding;
$(div).css('top', leafTop + 'px');
$(div).css('left', left+'px');
$(div).css('width', leafWidth+'px');
@@ -1077,7 +1119,7 @@ BookReader.prototype.zoomThumb = function(direction) {
// Note: #BRpageview must already exist since its width is used to calculate the
// thumbnail width
BookReader.prototype.getThumbnailWidth = function(thumbnailColumns) {
- var padding = (thumbnailColumns + 1) * this.padding;
+ var padding = (thumbnailColumns + 1) * this.thumbPadding;
var width = ($('#BRpageview').width() - padding) / (thumbnailColumns + 0.5); // extra 0.5 is for some space at sides
return parseInt(width);
}
@@ -1166,6 +1208,8 @@ BookReader.prototype.jumpToPage = function(pageNum) {
//______________________________________________________________________________
BookReader.prototype.jumpToIndex = function(index, pageX, pageY) {
+ this.updateNavIndex(index);
+
if (this.constMode2up == this.mode) {
this.autoStop();
@@ -1190,7 +1234,7 @@ BookReader.prototype.jumpToIndex = function(index, pageX, pageY) {
for (i=0; i<(index+1); i++) {
leafWidth = this.thumbWidth;
- if (rightPos + (leafWidth + this.padding) > viewWidth){
+ if (rightPos + (leafWidth + this.thumbPadding) > viewWidth){
rightPos = 0;
rowHeight = 0;
leafIndex = 0;
@@ -1199,8 +1243,8 @@ BookReader.prototype.jumpToIndex = function(index, pageX, pageY) {
leafHeight = parseInt((this.getPageHeight(leafIndex)*this.thumbWidth)/this.getPageWidth(leafIndex), 10);
if (leafHeight > rowHeight) { rowHeight = leafHeight; }
if (leafIndex==0) { leafTop = bottomPos; }
- if (leafIndex==0) { bottomPos += this.padding + rowHeight; }
- rightPos += leafWidth + this.padding;
+ if (leafIndex==0) { bottomPos += this.thumbPadding + rowHeight; }
+ rightPos += leafWidth + this.thumbPadding;
leafIndex++;
}
this.firstIndex=index;
@@ -1261,6 +1305,7 @@ BookReader.prototype.switchMode = function(mode) {
}
this.autoStop();
+ this.ttsStop();
this.removeSearchHilites();
this.mode = mode;
@@ -1282,8 +1327,8 @@ BookReader.prototype.switchMode = function(mode) {
} else if (3 == mode) {
$('button.thumb').hide();
$('button.twopg').show();
+ this.reduce = this.quantizeReduce(this.reduce, this.reductionFactors);
this.prepareThumbnailView();
- this.reduce = this.quantizeReduce(this.reduce);
} else {
// $$$ why don't we save autofit?
// this.twoPage.autofit = null; // Take zoom level from other mode
@@ -1435,21 +1480,13 @@ BookReader.prototype.prepareTwoPageView = function(centerPercentageX, centerPerc
width: this.twoPage.bookCoverDivWidth + 'px',
height: this.twoPage.bookCoverDivHeight+'px',
visibility: 'visible',
- position: 'absolute',
- backgroundColor: 'transparent',
- backgroundImage: 'url(back_pages.png)',
- left: this.twoPage.bookCoverDivLeft + 'px',
- top: this.twoPage.bookCoverDivTop+'px',
- MozBoxShadow: '0 0 2px #000',
- WebkitBoxShadow: '0 0 2px #000'
}).appendTo('#BRtwopageview');
this.leafEdgeR = document.createElement('div');
this.leafEdgeR.className = 'BRleafEdgeR';
$(this.leafEdgeR).css({
- background: 'transparent url(back_pages.png) repeat scroll 0% 0%',
width: this.twoPage.leafEdgeWidthR + 'px',
- height: this.twoPage.height-1 + 'px',
+ height: this.twoPage.height + 'px',
left: this.twoPage.gutter+this.twoPage.scaledWR+'px',
top: this.twoPage.bookCoverDivTop+this.twoPage.coverInternalPadding+'px'
}).appendTo('#BRtwopageview');
@@ -1458,7 +1495,7 @@ BookReader.prototype.prepareTwoPageView = function(centerPercentageX, centerPerc
this.leafEdgeL.className = 'BRleafEdgeL';
$(this.leafEdgeL).css({
width: this.twoPage.leafEdgeWidthL + 'px',
- height: this.twoPage.height-1 + 'px',
+ height: this.twoPage.height + 'px',
left: this.twoPage.bookCoverDivLeft+this.twoPage.coverInternalPadding+'px',
top: this.twoPage.bookCoverDivTop+this.twoPage.coverInternalPadding+'px'
}).appendTo('#BRtwopageview');
@@ -1537,20 +1574,7 @@ BookReader.prototype.prepareTwoPagePopUp = function() {
this.twoPagePopUp = document.createElement('div');
this.twoPagePopUp.className = 'BRtwoPagePopUp';
$(this.twoPagePopUp).css({
- zIndex: '1000',
- // XXXmang move to CSS
- padding: '6px',
- position: 'absolute',
- fontFamily: 'Arial,sans-serif',
- fontSize: '11px',
- color: 'white',
- zIndex: '1000',
- backgroundColor: '#939598',
- opacity: 0.85,
- webkitBorderRadius: '4px',
- mozBorderRadius: '4px',
- borderRadius: '4px',
- whiteSpace: 'nowrap'
+ zIndex: '1000'
}).appendTo('#BRcontainer');
$(this.twoPagePopUp).hide();
@@ -1564,12 +1588,14 @@ BookReader.prototype.prepareTwoPagePopUp = function() {
$(this.leafEdgeL).bind('click', this, function(e) {
e.data.autoStop();
+ e.data.ttsStop();
var jumpIndex = e.data.jumpIndexForLeftEdgePageX(e.pageX);
e.data.jumpToIndex(jumpIndex);
});
$(this.leafEdgeR).bind('click', this, function(e) {
e.data.autoStop();
+ e.data.ttsStop();
var jumpIndex = e.data.jumpIndexForRightEdgePageX(e.pageX);
e.data.jumpToIndex(jumpIndex);
});
@@ -1639,7 +1665,7 @@ BookReader.prototype.calculateSpreadSize = function() {
// Book cover
// The width of the book cover div. The combined width of both pages, twice the width
// of the book cover internal padding (2*10) and the page edges
- this.twoPage.bookCoverDivWidth = this.twoPage.scaledWL + this.twoPage.scaledWR + 2 * this.twoPage.coverInternalPadding + this.twoPage.edgeWidth;
+ this.twoPage.bookCoverDivWidth = this.twoPageCoverWidth(this.twoPage.scaledWL + this.twoPage.scaledWR);
// The height of the book cover div
this.twoPage.bookCoverDivHeight = this.twoPage.height + 2 * this.twoPage.coverInternalPadding;
@@ -2006,6 +2032,8 @@ BookReader.prototype.flipBackToIndex = function(index) {
}
//if (index<0) return;
+ this.updateNavIndex(index);
+
var previousIndices = this.getSpreadIndices(index);
if (previousIndices[0] < this.firstDisplayableIndex() || previousIndices[1] < this.firstDisplayableIndex()) {
@@ -2079,7 +2107,7 @@ BookReader.prototype.flipLeftToRight = function(newIndexL, newIndexR) {
this.leafEdgeTmp.className = 'BRleafEdgeTmp';
$(this.leafEdgeTmp).css({
width: leafEdgeTmpW + 'px',
- height: this.twoPage.height-1 + 'px',
+ height: this.twoPage.height + 'px',
left: leftEdgeTmpLeft + 'px',
top: top+'px',
zIndex:1000
@@ -2178,7 +2206,7 @@ BookReader.prototype.flipLeftToRight = function(newIndexL, newIndexR) {
BookReader.prototype.flipFwdToIndex = function(index) {
if (this.animating) return;
-
+
if (null != this.leafEdgeTmp) {
alert('error: leafEdgeTmp should be null!');
return;
@@ -2189,6 +2217,8 @@ BookReader.prototype.flipFwdToIndex = function(index) {
}
if (index > this.lastDisplayableIndex()) return;
+ this.updateNavIndex(index);
+
this.animating = true;
var nextIndices = this.getSpreadIndices(index);
@@ -2228,7 +2258,7 @@ BookReader.prototype.flipRightToLeft = function(newIndexL, newIndexR) {
this.leafEdgeTmp.className = 'BRleafEdgeTmp';
$(this.leafEdgeTmp).css({
width: leafEdgeTmpW + 'px',
- height: this.twoPage.height-1 + 'px',
+ height: this.twoPage.height + 'px',
left: gutter+scaledW+'px',
top: top+'px',
zIndex:1000
@@ -2304,6 +2334,7 @@ BookReader.prototype.setMouseHandlers2UP = function() {
this.setClickHandler2UP( this.prefetchedImgs[this.twoPage.currentIndexL],
{ self: this },
function(e) {
+ e.data.self.ttsStop();
e.data.self.left();
e.preventDefault();
}
@@ -2312,6 +2343,7 @@ BookReader.prototype.setMouseHandlers2UP = function() {
this.setClickHandler2UP( this.prefetchedImgs[this.twoPage.currentIndexR],
{ self: this },
function(e) {
+ e.data.self.ttsStop();
e.data.self.right();
e.preventDefault();
}
@@ -2824,28 +2856,7 @@ BookReader.prototype.updateSearchHilites2UP = function() {
//console.log('appending ' + key);
}
- // We calculate the reduction factor for the specific page because it can be different
- // for each page in the spread
- var height = this._getPageHeight(key);
- var width = this._getPageWidth(key)
- var reduce = this.twoPage.height/height;
- var scaledW = parseInt(width*reduce);
-
- var gutter = this.twoPageGutter();
- var pageL;
- if ('L' == this.getPageSide(key)) {
- pageL = gutter-scaledW;
- } else {
- pageL = gutter;
- }
- var pageT = this.twoPageTop();
-
- $(result.div).css({
- width: (result.r-result.l)*reduce + 'px',
- height: (result.b-result.t)*reduce + 'px',
- left: pageL+(result.l)*reduce + 'px',
- top: pageT+(result.t)*reduce +'px'
- });
+ this.setHilightCss2UP(result.div, key, result.l, result.r, result.t, result.b);
} else {
//console.log(key + ' not displayed');
@@ -2858,6 +2869,35 @@ BookReader.prototype.updateSearchHilites2UP = function() {
}
}
+// setHilightCss2UP()
+//______________________________________________________________________________
+//position calculation shared between search and text-to-speech functions
+BookReader.prototype.setHilightCss2UP = function(div, index, left, right, top, bottom) {
+
+ // We calculate the reduction factor for the specific page because it can be different
+ // for each page in the spread
+ var height = this._getPageHeight(index);
+ var width = this._getPageWidth(index)
+ var reduce = this.twoPage.height/height;
+ var scaledW = parseInt(width*reduce);
+
+ var gutter = this.twoPageGutter();
+ var pageL;
+ if ('L' == this.getPageSide(index)) {
+ pageL = gutter-scaledW;
+ } else {
+ pageL = gutter;
+ }
+ var pageT = this.twoPageTop();
+
+ $(div).css({
+ width: (right-left)*reduce + 'px',
+ height: (bottom-top)*reduce + 'px',
+ left: pageL+left*reduce + 'px',
+ top: pageT+top*reduce +'px'
+ });
+}
+
// removeSearchHilites()
//______________________________________________________________________________
BookReader.prototype.removeSearchHilites = function() {
@@ -2951,6 +2991,12 @@ BookReader.prototype.updatePrintFrame = function(delta) {
// showEmbedCode()
//______________________________________________________________________________
BookReader.prototype.showEmbedCode = function() {
+ if (null != this.embedPopup) { // check if already showing
+ return;
+ }
+ this.autoStop();
+ this.ttsStop();
+
this.embedPopup = document.createElement("div");
$(this.embedPopup).css({
position: 'absolute',
@@ -3179,30 +3225,353 @@ BookReader.prototype.jumpIndexForRightEdgePageX = function(pageX) {
}
}
+// initNavbar
+//______________________________________________________________________________
+// Initialize the navigation bar.
+// $$$ this could also add the base elements to the DOM, so disabling the nav bar
+// could be as simple as not calling this function
+BookReader.prototype.initNavbar = function() {
+ // Setup nav / chapter / search results bar
+
+ // $$$ should make this work inside the BookReader div (self-contained), rather than after
+ $('#BookReader').after(
+ '
'
+ + '
'
+ + ''
+ + ''
+ + '
'
+ + '
'
+ + ''
+ + ''
+ + '
'
+ + ''
+ + ''
+ + '
'
+ + '
'
+ + '
'
+ );
+
+/*
+
+
+ A related distinction is between the emotion and the results of the emotion, principally behaviors and emotional expressions. People often behave in certain ways as a direct result of their emotional state, such as crying, fighting or fleeing. Page 163
+