this.twoPagePopUp = null;
this.leafEdgeTmp = null;
this.embedPopup = null;
- this.printPopup = null;
+ this.popup = null;
this.searchTerm = '';
this.searchResults = {};
// Object to hold parameters related to 1up mode
this.onePage = {
autofit: 'height' // valid values are height, width, none
- },
+ };
// Object to hold parameters related to 2up mode
this.twoPage = {
coverInternalPadding: 10, // Width of cover
coverExternalPadding: 10, // Padding outside of cover
bookSpineDivWidth: 30, // Width of book spine $$$ consider sizing based on book length
- autofit: 'auto',
+ autofit: 'auto'
};
- // Background color for pages (e.g. when loading page image)
- // $$$ TODO dynamically calculate based on page images
- this.pageDefaultBackgroundColor = 'rgb(234, 226, 205)';
+ // Text-to-Speech params
+ this.ttsIndex = null; //leaf index
+ this.ttsPosition = -1; //chunk (paragraph) number
+
return this;
};
left: this.twoPage.gutter-this.twoPage.scaledWL+'px',
right: '',
top: top+'px',
- backgroundColor: this.getPageBackgroundColor(indexL),
height: this.twoPage.height +'px', // $$$ height forced the same for both pages
width: this.twoPage.scaledWL + 'px',
borderRight: '1px solid black',
left: this.twoPage.gutter+'px',
right: '',
top: top+'px',
- backgroundColor: this.getPageBackgroundColor(indexR),
height: this.twoPage.height + 'px', // $$$ height forced the same for both pages
width: this.twoPage.scaledWR + 'px',
borderLeft: '1px solid black',
var offset = parseInt( (pageX) / this.reduce);
offset -= $('#BRcontainer').attr('clientWidth') >> 1;
leafLeft += offset;
+ } else {
+ // Preserve left position
+ leafLeft = $('#BRcontainer').scrollLeft();
}
//$('#BRcontainer').attr('scrollTop', leafTop);
visibility: 'visible',
position: 'absolute',
left: this.twoPage.bookCoverDivLeft + 'px',
- top: this.twoPage.bookCoverDivTop+'px',
+ top: this.twoPage.bookCoverDivTop+'px'
}).appendTo('#BRtwopageview');
this.leafEdgeR = document.createElement('div');
width: this.twoPage.leafEdgeWidthR + 'px',
height: this.twoPage.height-1 + 'px',
left: this.twoPage.gutter+this.twoPage.scaledWR+'px',
- top: this.twoPage.bookCoverDivTop+this.twoPage.coverInternalPadding+'px',
+ top: this.twoPage.bookCoverDivTop+this.twoPage.coverInternalPadding+'px'
}).appendTo('#BRtwopageview');
this.leafEdgeL = document.createElement('div');
width: this.twoPage.leafEdgeWidthL + 'px',
height: this.twoPage.height-1 + 'px',
left: this.twoPage.bookCoverDivLeft+this.twoPage.coverInternalPadding+'px',
- top: this.twoPage.bookCoverDivTop+this.twoPage.coverInternalPadding+'px',
+ top: this.twoPage.bookCoverDivTop+this.twoPage.coverInternalPadding+'px'
}).appendTo('#BRtwopageview');
div = document.createElement('div');
this.twoPagePopUp = document.createElement('div');
this.twoPagePopUp.className = 'BRtwoPagePopUp';
$(this.twoPagePopUp).css({
- zIndex: '1000',
+ zIndex: '1000'
}).appendTo('#BRcontainer');
$(this.twoPagePopUp).hide();
if (loadImage) {
//console.log('prefetching ' + index);
var img = document.createElement("img");
+ img.className = 'BRpageimage';
+ if (index < 0 || index > (this.numLeafs - 1) ) {
+ // Facing page at beginning or end, or beyond
+ $(img).css({
+ 'background-color': 'transparent'
+ });
+ }
img.src = pageURI;
img.uri = pageURI; // browser may rewrite src so we stash raw URI here
this.prefetchedImgs[index] = img;
top: top+'px',
height: this.twoPage.height,
width: scaledW+'px',
- backgroundColor: this.getPageBackgroundColor(prevL),
borderRight: '1px solid black',
zIndex: 1
}
top: top+'px',
height: this.twoPage.height,
width: '0px',
- backgroundColor: this.getPageBackgroundColor(prevR),
borderLeft: '1px solid black',
zIndex: 2
}
position: 'absolute',
left: gutter+'px',
top: top+'px',
- backgroundColor: this.getPageBackgroundColor(nextR),
height: this.twoPage.height,
width: scaledW+'px',
borderLeft: '1px solid black',
position: 'absolute',
right: $('#BRtwopageview').attr('clientWidth')-gutter+'px',
top: top+'px',
- backgroundColor: this.getPageBackgroundColor(nextL),
height: this.twoPage.height,
width: 0+'px', // Start at 0 width, then grow to the left
borderRight: '1px solid black',
//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');
}
}
+// 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() {
//______________________________________________________________________________
BookReader.prototype.printPage = function() {
window.open(this.getPrintURI(), 'printpage', 'width=400, height=500, resizable=yes, scrollbars=no, toolbar=no, location=no');
-
- /* iframe implementation
-
- if (null != this.printPopup) { // check if already showing
- return;
- }
- this.printPopup = document.createElement("div");
- $(this.printPopup).css({
- position: 'absolute',
- top: '20px',
- left: ($('#BRcontainer').width()-400)/2 + 'px',
- width: '400px',
- padding: "20px",
- border: "3px double #999999",
- zIndex: 3,
- backgroundColor: "#fff"
- }).appendTo('#BookReader');
-
- var indexToPrint;
- if (this.constMode1up == this.mode) {
- indexToPrint = this.firstIndex;
- } else {
- indexToPrint = this.twoPage.currentIndexL;
- }
-
- this.indexToPrint = indexToPrint;
-
- var htmlStr = '<div style="text-align: center;">';
- htmlStr = '<p style="text-align:center;"><b><a href="javascript:void(0);" onclick="window.frames[0].focus(); window.frames[0].print(); return false;">Click here to print this page</a></b></p>';
- htmlStr += '<div id="printDiv" name="printDiv" style="text-align: center; width: 233px; margin: auto">'
- htmlStr += '<p style="text-align:right; margin: 0; font-size: 0.85em">';
- //htmlStr += '<button class="BRicon rollover book_up" onclick="br.updatePrintFrame(-1); return false;"></button> ';
- //htmlStr += '<button class="BRicon rollover book_down" onclick="br.updatePrintFrame(1); return false;"></button>';
- htmlStr += '<a href="#" onclick="br.updatePrintFrame(-1); return false;">Prev</a> <a href="#" onclick="br.updatePrintFrame(1); return false;">Next</a>';
- htmlStr += '</p>';
- htmlStr += '</div>';
- htmlStr += '<p style="text-align:center;"><a href="" onclick="br.printPopup = null; $(this.parentNode.parentNode).remove(); return false">Close popup</a></p>';
- htmlStr += '</div>';
-
- this.printPopup.innerHTML = htmlStr;
-
- var iframe = document.createElement('iframe');
- iframe.id = 'printFrame';
- iframe.name = 'printFrame';
- iframe.width = '233px'; // 8.5 x 11 aspect
- iframe.height = '300px';
-
- var self = this; // closure
-
- $(iframe).load(function() {
- var doc = BookReader.util.getIFrameDocument(this);
- $('body', doc).html(self.getPrintFrameContent(self.indexToPrint));
- });
-
- $('#printDiv').prepend(iframe);
- */
}
// Get print URI from current indices and mode
indexToPrint = this.firstIndex; // $$$ the index in the middle of the viewport would make more sense
}
- var options = 'id=' + this.bookId + '&server=' + this.server + '&zip=' + this.zip
+ var options = 'id=' + this.subPrefix + '&server=' + this.server + '&zip=' + this.zip
+ '&format=' + this.imageFormat + '&file=' + this._getPageFile(indexToPrint)
+ '&width=' + this._getPageWidth(indexToPrint) + '&height=' + this._getPageHeight(indexToPrint);
$("#BookReader").append("<div id='BRtoolbar'>"
+ "<span id='BRtoolbarbuttons' style='float: right'>"
+ + "<button class='BRicon rollover read_aloud' onclick='br.ttsStart(); return false;'/>"
+ "<button class='BRicon print rollover' /> <button class='BRicon rollover embed' />"
+ "<form class='BRpageform' action='javascript:' onsubmit='br.jumpToPage(this.elements[0].value)'> <span class='label'>Page:<input id='BRpagenum' type='text' size='3' onfocus='br.autoStop();'></input></span></form>"
+ "<div class='BRtoolbarmode2' style='display: none'><button class='BRicon rollover book_leftmost' /><button class='BRicon rollover book_left' /><button class='BRicon rollover book_right' /><button class='BRicon rollover book_rightmost' /></div>"
}
if (autofit) {
- value = autofit[0].toUpperCase() + autofit.slice(1);
+ value = autofit.slice(0,1).toUpperCase() + autofit.slice(1);
} else {
value = (100 / reduce).toFixed(2);
// Strip trailing zeroes and decimal if all zeroes
return false;
}
-// getPageBackgroundColor
-//--------
-// Returns a CSS property string for the background color for the given page
-// $$$ turn into regular CSS?
-BookReader.prototype.getPageBackgroundColor = function(index) {
- if (index >= 0 && index < this.numLeafs) {
- // normal page
- return this.pageDefaultBackgroundColor;
- }
-
- return '';
-}
-
// _getPageWidth
//--------
// Returns the page width for the given index, or first or last page if out of range
}
// The final property here must NOT have a comma after it - IE7
}
+
+
+// ttsStart()
+//______________________________________________________________________________
+BookReader.prototype.ttsStart = function () {
+ console.log('starting readAloud');
+ var url = 'http://'+this.server+'/BookReader/BookReaderGetTextWrapper.php?path='+this.bookPath+'_djvu.xml&page='+this.currentIndex();
+ this.ttsIndex = this.currentIndex();
+ $.ajax({url:url, dataType:'jsonp', jsonpCallback:'ttsStartCB'});
+}
+
+// ttsGetText()
+//______________________________________________________________________________
+BookReader.prototype.ttsGetText = function(index, callback) {
+ var url = 'http://'+this.server+'/BookReader/BookReaderGetTextWrapper.php?path='+this.bookPath+'_djvu.xml&page='+index;
+ $.ajax({url:url, dataType:'jsonp', jsonpCallback:callback});
+}
+
+// ttsStartCB(): text-to-speech callback
+//______________________________________________________________________________
+BookReader.prototype.ttsStartCB = function (data) {
+ console.log('ttsStartCB got data:');
+ console.log(data);
+ this.ttsChunks = data;
+ this.ttsHilites = [];
+ //$.ajax({url:'http://'+this.ttsServer+'/renderAudio.py', data:{string:data[0][0], format:'ogg'}, dataType:'json'});
+
+ this.ttsShowPopup();
+
+ this.ttsPosition = -1;
+ var snd = soundManager.createSound({
+ id: 'chunk'+this.ttsIndex+'-0',
+ //url: 'http://home.us.archive.org/~rkumar/arctic.ogg',
+ url: 'http://home.us.archive.org/~rkumar/getOgg.php?string=' + escape(data[0][0]) + '&f=.ogg', //the .ogg is to trick SoundManager2 to use the HTML5 audio player
+ whileloading: function(){if (this.bytesLoaded == this.bytesTotal) {$(br.popup).remove(); br.popup=null;}} //onload never fires...
+ });
+ snd.br = this;
+ snd.load();
+
+ this.ttsNextChunk();
+}
+
+// ttsShowPopup
+//______________________________________________________________________________
+BookReader.prototype.ttsShowPopup = function() {
+ this.popup = document.createElement("div");
+ $(this.popup).css({
+ position: 'absolute',
+ top: '20%',
+ left: ($('#BRcontainer').attr('clientWidth')-600)/2 + 'px',
+ width: '600px',
+ padding: "20px",
+ border: "3px double #999999",
+ zIndex: 3,
+ backgroundColor: "#f00",
+ color: "#fff",
+ fontSize: '1.875em'
+ }).appendTo('#BookReader');
+
+ htmlStr = '<p style="text-align:center;"><b>Ever wanted to wait while audio loads?</b><br/>';
+ htmlStr += "It's OK. We all do.</p>";
+
+ this.popup.innerHTML = htmlStr;
+}
+
+// ttsNextPageCB
+//______________________________________________________________________________
+BookReader.prototype.ttsNextPageCB = function (data) {
+ this.ttsNextChunks = data;
+ console.log('preloaded next chunks.. data is');
+}
+
+// ttsLoadChunk
+//______________________________________________________________________________
+BookReader.prototype.ttsLoadChunk = function (page, pos, string) {
+ var snd = soundManager.createSound({
+ id: 'chunk'+page+'-'+pos,
+ url: 'http://home.us.archive.org/~rkumar/getOgg.php?string=' + escape(string) + '&f=.ogg' //the .ogg is to trick SoundManager2 to use the HTML5 audio player
+ });
+ snd.br = this;
+ snd.load()
+}
+
+
+// ttsNextChunk()
+//______________________________________________________________________________
+BookReader.prototype.ttsNextChunk = function () {
+ console.log(this);
+ console.log(this.ttsPosition);
+
+ if (-1 != this.ttsPosition) {
+ soundManager.destroySound('chunk'+this.ttsIndex+'-'+this.ttsPosition);
+ }
+
+ this.ttsPosition++;
+ console.log('next chunk is ');
+ console.log(this.ttsPosition);
+
+ if (this.ttsPosition >= this.ttsChunks.length) {
+
+ if (this.ttsIndex == (this.numLeafs-1)) {
+ console.log('tts stop');
+ return;
+ } else {
+ if (null != this.ttsNextChunks) {
+ console.log('moving to next page!');
+ this.ttsIndex++;
+ this.ttsPosition = 0;
+ this.ttsChunks = this.ttsNextChunks;
+ this.ttsNextChunks = null;
+ } else {
+ console.log('ttsNextChunks is null');
+ return;
+ }
+ }
+ }
+
+ //prefetch next page of text
+ if (0 == this.ttsPosition) {
+ if (this.ttsIndex<(this.numLeafs-1)) {
+ this.ttsGetText(this.ttsIndex+1, 'ttsNextPageCB');
+ }
+ }
+
+ var chunk = this.ttsChunks[this.ttsPosition];
+ console.log('position = ' + this.ttsPosition);
+ console.log('chunk = ' + chunk);
+ console.log(this.ttsChunks);
+
+ //remove old hilights
+ $(this.ttsHilites).remove();
+ this.ttsHilites = [];
+
+ //add new hilights
+ if (2 == this.mode) {
+ this.ttsHilite2UP(chunk);
+ } else {
+ alert('only 2 page mode supported for TTS..');
+ }
+
+ //preload next chunk
+ var nextPos = this.ttsPosition+1;
+ if (nextPos < this.ttsChunks.length) {
+ this.ttsLoadChunk(this.ttsIndex, nextPos, this.ttsChunks[nextPos][0]);
+ } else {
+ this.ttsLoadChunk(this.ttsIndex+1, 0, this.ttsNextChunks[0][0]);
+ }
+
+ //play current chunk
+ soundManager.play('chunk'+this.ttsIndex+'-'+this.ttsPosition,{onfinish:function(){br.ttsNextChunk();}});
+}
+
+
+// ttsHilite2UP()
+//______________________________________________________________________________
+BookReader.prototype.ttsHilite2UP = function (chunk) {
+ var i;
+ for (i=0; i<chunk.length; i++) {
+ //each rect is an array of l,b,r,t coords (djvu.xml ordering...)
+ var l = chunk[i][0];
+ var b = chunk[i][1];
+ var r = chunk[i][2];
+ var t = chunk[i][3];
+
+ var div = document.createElement('div');
+ this.ttsHilites.push(div);
+ $(div).attr('className', 'BookReaderSearchHilite').css('zIndex', 3).appendTo('#BRtwopageview');
+ this.setHilightCss2UP(div, this.ttsIndex, l, r, t, b);
+ }
+}