this.constModeThumb = 3;
// Zoom levels
+ // $$$ provide finer grained zooming
this.reductionFactors = [0.5, 1, 2, 4, 8, 16];
// Object to hold parameters related to 2up mode
}
$("#BookReader").empty();
+
this.initToolbar(this.mode, this.ui); // Build inside of toolbar div
$("#BookReader").append("<div id='BRcontainer'></div>");
$("#BRcontainer").append("<div id='BRpageview'></div>");
$("#BRcontainer").bind('scroll', this, function(e) {
e.data.loadLeafs();
});
-
+
this.setupKeyListeners();
this.startLocationPolling();
// $$$ refactor this so it's enough to set the first index and call preparePageView
// (get rid of mode-specific logic at this point)
if (1 == this.mode) {
- this.resizePageView();
this.firstIndex = startIndex;
+ this.prepareOnePageView();
this.jumpToIndex(startIndex);
} else if (3 == this.mode) {
this.firstIndex = startIndex;
}
-// setDragHandler()
+// bindGestures(jElement)
//______________________________________________________________________________
-BookReader.prototype.setDragHandler = function(div) {
- div.dragging = false;
+BookReader.prototype.bindGestures = function(jElement) {
- $(div).unbind('mousedown').bind('mousedown', function(e) {
+ jElement.unbind('gesturechange').bind('gesturechange', function(e) {
e.preventDefault();
-
- //console.log('mousedown at ' + e.pageY);
-
- this.dragging = true;
- this.prevMouseX = e.pageX;
- this.prevMouseY = e.pageY;
-
- var startX = e.pageX;
- var startY = e.pageY;
- var startTop = $('#BRcontainer').attr('scrollTop');
- var startLeft = $('#BRcontainer').attr('scrollLeft');
-
- });
-
- $(div).unbind('mousemove').bind('mousemove', function(ee) {
- ee.preventDefault();
-
- // console.log('mousemove ' + ee.pageX + ',' + ee.pageY);
-
- var offsetX = ee.pageX - this.prevMouseX;
- var offsetY = ee.pageY - this.prevMouseY;
-
- if (this.dragging) {
- $('#BRcontainer').attr('scrollTop', $('#BRcontainer').attr('scrollTop') - offsetY);
- $('#BRcontainer').attr('scrollLeft', $('#BRcontainer').attr('scrollLeft') - offsetX);
- }
-
- this.prevMouseX = ee.pageX;
- this.prevMouseY = ee.pageY;
-
- });
-
- $(div).unbind('mouseup').bind('mouseup', function(ee) {
- ee.preventDefault();
- //console.log('mouseup');
-
- this.dragging = false;
- });
-
- $(div).unbind('mouseleave').bind('mouseleave', function(e) {
- e.preventDefault();
- //console.log('mouseleave');
-
- this.dragging = false;
- });
-
- $(div).unbind('mouseenter').bind('mouseenter', function(e) {
- e.preventDefault();
- //console.log('mouseenter');
-
- this.dragging = false;
- });
-}
-
-// setDragHandler2UP()
-//______________________________________________________________________________
-BookReader.prototype.setDragHandler2UP = function(div) {
- div.dragging = false;
-
- $(div).unbind('mousedown').bind('mousedown', function(e) {
- e.preventDefault();
-
- //console.log('mousedown at ' + e.pageY);
-
- this.dragStart = {x: e.pageX, y: e.pageY };
- this.mouseDown = true;
- this.dragging = false; // wait until drag distance
- this.prevMouseX = e.pageX;
- this.prevMouseY = e.pageY;
-
- var startX = e.pageX;
- var startY = e.pageY;
- var startTop = $('#BRcontainer').attr('scrollTop');
- var startLeft = $('#BRcontainer').attr('scrollLeft');
-
- });
-
- $(div).unbind('mousemove').bind('mousemove', function(ee) {
- ee.preventDefault();
-
- // console.log('mousemove ' + ee.pageX + ',' + ee.pageY);
-
- var offsetX = ee.pageX - this.prevMouseX;
- var offsetY = ee.pageY - this.prevMouseY;
-
- var minDragDistance = 5; // $$$ constant
-
- var distance = Math.max(Math.abs(offsetX), Math.abs(offsetY));
-
- if (this.mouseDown && (distance > minDragDistance)) {
- //console.log('drag start!');
-
- this.dragging = true;
- }
-
- if (this.dragging) {
- $('#BRcontainer').attr('scrollTop', $('#BRcontainer').attr('scrollTop') - offsetY);
- $('#BRcontainer').attr('scrollLeft', $('#BRcontainer').attr('scrollLeft') - offsetX);
- this.prevMouseX = ee.pageX;
- this.prevMouseY = ee.pageY;
+ if (e.originalEvent.scale > 1.5) {
+ br.zoom(1);
+ } else if (e.originalEvent.scale < 0.6) {
+ br.zoom(-1);
}
-
-
- });
-
- /*
- $(div).unbind('mouseup').bind('mouseup', function(ee) {
- ee.preventDefault();
- //console.log('mouseup');
-
- this.dragging = false;
- this.mouseDown = false;
- });
- */
-
-
- $(div).unbind('mouseleave').bind('mouseleave', function(e) {
- e.preventDefault();
- //console.log('mouseleave');
-
- this.dragging = false;
- this.mouseDown = false;
});
-
- $(div).unbind('mouseenter').bind('mouseenter', function(e) {
- e.preventDefault();
- //console.log('mouseenter');
- this.dragging = false;
- this.mouseDown = false;
- });
}
BookReader.prototype.setClickHandler2UP = function( element, data, handler) {
//console.log('setting handler');
//console.log(element.tagName);
- $(element).unbind('click').bind('click', data, function(e) {
- e.preventDefault();
-
- //console.log('click!');
-
- if (this.mouseDown && (!this.dragging)) {
- //console.log('click not dragging!');
- handler(e);
- }
-
- this.dragging = false;
- this.mouseDown = false;
+ $(element).unbind('tap').bind('tap', data, function(e) {
+ handler(e);
});
}
leafTop += height +10;
leafBottom += 10;
}
-
+
var firstIndexToDraw = indicesToDisplay[0];
this.firstIndex = firstIndexToDraw;
$(div).css('height', height+'px');
//$(div).text('loading...');
- this.setDragHandler(div);
-
$('#BRpageview').append(div);
var img = document.createElement("img");
// drawLeafsThumbnail()
//______________________________________________________________________________
-BookReader.prototype.drawLeafsThumbnail = function() {
+// If seekIndex is defined, the view will be drawn with that page visible (without any
+// animated scrolling)
+BookReader.prototype.drawLeafsThumbnail = function( seekIndex ) {
//alert('drawing leafs!');
this.timer = null;
-
+
var viewWidth = $('#BRcontainer').attr('scrollWidth') - 20; // width minus buffer
//console.log('top=' + scrollTop + ' bottom='+scrollBottom);
var leafMap = [];
var self = this;
+
+ // Will be set to top of requested seek index, if set
+ var seekTop;
// Calculate the position of every thumbnail. $$$ cache instead of calculating on every draw
for (i=0; i<this.numLeafs; i++) {
rightPos += leafWidth + this.padding;
if (rightPos > maxRight) { maxRight = rightPos; }
leafIndex++;
+
+ if (i == seekIndex) {
+ seekTop = bottomPos - this.padding - leafMap[currentRow].height;
+ }
}
// reset the bottom position based on thumbnails
$('#BRpageview').height(bottomPos);
var pageViewBuffer = Math.floor(($('#BRcontainer').attr('scrollWidth') - maxRight) / 2) - 14;
+
+ // If seekTop is defined, seeking was requested and target found
+ if (typeof(seekTop) != 'undefined') {
+ $('#BRcontainer').scrollTop( seekTop );
+ }
+
var scrollTop = $('#BRcontainer').attr('scrollTop');
var scrollBottom = scrollTop + $('#BRcontainer').height();
var leafBottom = 0;
var rowsToDisplay = [];
+ // Visible leafs with least/greatest index
+ var leastVisible = this.numLeafs - 1;
+ var mostVisible = 0;
+
// Determine the thumbnails in view
for (i=0; i<leafMap.length; i++) {
leafBottom += this.padding + leafMap[i].height;
if (topInView | bottomInView | middleInView) {
//console.log('row to display: ' + j);
rowsToDisplay.push(i);
+ if (leafMap[i].leafs[0].num < leastVisible) {
+ leastVisible = leafMap[i].leafs[0].num;
+ }
+ if (leafMap[i].leafs[leafMap[i].leafs.length - 1].num > mostVisible) {
+ mostVisible = leafMap[i].leafs[leafMap[i].leafs.length - 1].num;
+ }
}
if (leafTop > leafMap[i].top) { leafMap[i].top = leafTop; }
leafTop = leafBottom;
if (firstRow-i >= 0) { rowsToDisplay.push(firstRow-i); }
}
- // Update hash, but only if we're currently displaying a leaf
- // Hack that fixes #365790
- if (this.displayedRows.length > 0) {
- this.updateLocationHash();
- }
-
// Create the thumbnail divs and images (lazy loaded)
var j;
var row;
// link to page in single page mode
link = document.createElement("a");
$(link).data('leaf', leaf);
- $(link).bind('click', function(event) {
+ $(link).bind('tap', function(event) {
self.firstIndex = $(this).data('leaf');
self.switchMode(self.constMode1up);
event.preventDefault();
}
}
}
-
- // remove previous highlights
- $('.BRpagedivthumb_highlight').removeClass('BRpagedivthumb_highlight');
-
- // highlight current page
- $('#pagediv'+this.currentIndex()).addClass('BRpagedivthumb_highlight');
// Remove thumbnails that are not to be displayed
var k;
}
}
+ // Update which page is considered current to make sure a visible page is the current one
+ var currentIndex = this.currentIndex();
+ // console.log('current ' + currentIndex);
+ // console.log('least visible ' + leastVisible + ' most visible ' + mostVisible);
+ if (currentIndex < leastVisible) {
+ this.setCurrentIndex(leastVisible);
+ } else if (currentIndex > mostVisible) {
+ this.setCurrentIndex(mostVisible);
+ }
+
this.displayedRows = rowsToDisplay.slice();
+ // Update hash, but only if we're currently displaying a leaf
+ // Hack that fixes #365790
+ if (this.displayedRows.length > 0) {
+ this.updateLocationHash();
+ }
+
+ // remove previous highlights
+ $('.BRpagedivthumb_highlight').removeClass('BRpagedivthumb_highlight');
+
+ // highlight current page
+ $('#pagediv'+this.currentIndex()).addClass('BRpagedivthumb_highlight');
+
this.lazyLoadThumbnails();
// Update page number box. $$$ refactor to function
// e.g. does not preserve position in thumbnail mode
// See http://bugs.launchpad.net/bookreader/+bug/552972
+ switch (this.mode) {
+ case this.constMode1up:
+ case this.constMode2up:
+ this.resizePageView1up();
+ break;
+ case this.constModeThumb:
+ this.prepareThumbnailView( this.currentIndex() );
+ break;
+ default:
+ alert('Resize not implemented for this mode');
+ }
+}
+
+BookReader.prototype.resizePageView1up = function() {
var i;
var viewHeight = 0;
//var viewWidth = $('#BRcontainer').width(); //includes scrollBar
if (width>viewWidth) viewWidth=width;
}
$('#BRpageview').height(viewHeight);
- $('#BRpageview').width(viewWidth);
+ $('#BRpageview').width(viewWidth);
var newCenterY = scrollRatio*viewHeight;
var newTop = Math.max(0, Math.floor( newCenterY - $('#BRcontainer').height()/2 ));
//this.centerPageView();
this.loadLeafs();
-
- // $$$ jump to index here? index is not preserved when resizing in thumb mode
-
- // Not really needed until there is 1up autofit
+
this.removeSearchHilites();
this.updateSearchHilites();
}
+
// centerX1up()
//______________________________________________________________________________
// Returns the current offset of the viewport center in scaled document coordinates.
if (this.thumbColumns != oldColumns) {
this.prepareThumbnailView();
- this.jumpToIndex(this.currentIndex());
}
}
rowHeight = 0;
leafIndex = 0;
}
- leafHeight = parseInt((this.getPageHeight(leaf)*this.thumbWidth)/this.getPageWidth(leaf), 10);
+
+ 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; }
} else if (3 == mode) {
this.reduce = this.quantizeReduce(this.reduce);
this.prepareThumbnailView();
- this.jumpToIndex(this.currentIndex());
} else {
// $$$ why don't we save autofit?
this.twoPage.autofit = false; // Take zoom level from other mode
// var startLeaf = this.displayedIndices[0];
var startLeaf = this.currentIndex();
-
+
$('#BRcontainer').empty();
$('#BRcontainer').css({
overflowY: 'scroll',
overflowX: 'auto'
});
-
+
$("#BRcontainer").append("<div id='BRpageview'></div>");
+
+ // Attaches to first child - child must be present
+ $('#BRcontainer').dragscrollable();
+ this.bindGestures($('#BRcontainer'));
+
// $$$ keep select enabled for now since disabling it breaks keyboard
// nav in FF 3.6 (https://bugs.edge.launchpad.net/bookreader/+bug/544666)
// BookReader.util.disableSelect($('#BRpageview'));
- this.resizePageView();
+ this.resizePageView();
this.jumpToIndex(startLeaf);
this.displayedIndices = [];
overflowY: 'scroll',
overflowX: 'auto'
});
-
+
$("#BRcontainer").append("<div id='BRpageview'></div>");
+
+ $('#BRcontainer').dragscrollable();
+ this.bindGestures($('#BRcontainer'));
// $$$ keep select enabled for now since disabling it breaks keyboard
// nav in FF 3.6 (https://bugs.edge.launchpad.net/bookreader/+bug/544666)
// BookReader.util.disableSelect($('#BRpageview'));
- var startLeaf = this.currentIndex();
this.thumbWidth = this.getThumbnailWidth(this.thumbColumns);
this.reduce = this.getPageWidth(0)/this.thumbWidth;
- this.resizePageView();
-
this.displayedRows = [];
+
+ // Draw leafs with current index directly in view (no animating to the index)
+ this.drawLeafsThumbnail( this.currentIndex() );
- // $$$ resizePageView will do a delayed load -- this will make it happen faster
- this.drawLeafsThumbnail();
}
// prepareTwoPageView()
// Add the two page view
// $$$ Can we get everything set up and then append?
$('#BRcontainer').append('<div id="BRtwopageview"></div>');
+
+ // Attaches to first child, so must come after we add the page view
+ $('#BRcontainer').dragscrollable();
+ this.bindGestures($('#BRcontainer'));
// $$$ calculate first then set
$('#BRtwopageview').css( {
this.twoPage.coverDiv = document.createElement('div');
$(this.twoPage.coverDiv).attr('id', 'BRbookcover').css({
- border: '1px solid rgb(68, 25, 17)',
width: this.twoPage.bookCoverDivWidth + 'px',
height: this.twoPage.bookCoverDivHeight+'px',
visibility: 'visible',
position: 'absolute',
- backgroundColor: '#663929',
left: this.twoPage.bookCoverDivLeft + 'px',
top: this.twoPage.bookCoverDivTop+'px',
- MozBorderRadiusTopleft: '7px',
- MozBorderRadiusTopright: '7px',
- MozBorderRadiusBottomright: '7px',
- MozBorderRadiusBottomleft: '7px'
}).appendTo('#BRtwopageview');
this.leafEdgeR = document.createElement('div');
this.leafEdgeR.className = 'leafEdgeR'; // $$$ the static CSS should be moved into the .css file
$(this.leafEdgeR).css({
- borderStyle: 'solid solid solid none',
- borderColor: 'rgb(51, 51, 34)',
- borderWidth: '1px 1px 1px 0px',
background: 'transparent url(' + this.imagesBaseURL + 'right_edges.png) repeat scroll 0% 0%',
width: this.twoPage.leafEdgeWidthR + 'px',
height: this.twoPage.height-1 + 'px',
this.leafEdgeL = document.createElement('div');
this.leafEdgeL.className = 'leafEdgeL';
- $(this.leafEdgeL).css({ // $$$ static CSS should be moved to file
- borderStyle: 'solid none solid solid',
- borderColor: 'rgb(51, 51, 34)',
- borderWidth: '1px 0px 1px 1px',
+ $(this.leafEdgeL).css({
background: 'transparent url(' + this.imagesBaseURL + 'left_edges.png) repeat scroll 0% 0%',
width: this.twoPage.leafEdgeWidthL + 'px',
height: this.twoPage.height-1 + 'px',
div = document.createElement('div');
$(div).attr('id', 'BRbookspine').css({
- border: '1px solid rgb(68, 25, 17)',
width: this.twoPage.bookSpineDivWidth+'px',
height: this.twoPage.bookSpineDivHeight+'px',
position: 'absolute',
- backgroundColor: 'rgb(68, 25, 17)',
left: this.twoPage.bookSpineDivLeft+'px',
top: this.twoPage.bookSpineDivTop+'px'
}).appendTo('#BRtwopageview');
}
}
-/*
-// Returns the current index if visible, or the logically current visible
-// thumbnail
-BookReader.prototype.currentIndexOrVisibleThumb = function() {
- // XXX finish implementation
- var index = this.currentIndex();
- if (!this.indexIsVisbleThumb(this.currentIndex()) {
- // XXX search for visible
- }
- return index;
-}
-
-// Returns true if the given index is visible
-BookReader.prototype.indexIsVisibleThumb = function(index, onlyCompletelyVisible = true) {
- // XXX implement
- // $$$ I'd prefer to go through a stored leaf map instead of DOM
-
-
+// setCurrentIndex(index)
+//______________________________________________________________________________
+// Sets the idea of current index without triggering other actions such as animation.
+// Compare to jumpToIndex which animates to that index
+BookReader.prototype.setCurrentIndex = function(index) {
+ this.firstIndex = index;
}
-*/
// right()
// setMouseHandlers2UP
//______________________________________________________________________________
BookReader.prototype.setMouseHandlers2UP = function() {
- /*
- $(this.prefetchedImgs[this.twoPage.currentIndexL]).bind('dblclick', function() {
- //self.prevPage();
- self.autoStop();
- self.left();
- });
- $(this.prefetchedImgs[this.twoPage.currentIndexR]).bind('dblclick', function() {
- //self.nextPage();'
- self.autoStop();
- self.right();
- });
- */
-
- this.setDragHandler2UP( this.prefetchedImgs[this.twoPage.currentIndexL] );
this.setClickHandler2UP( this.prefetchedImgs[this.twoPage.currentIndexL],
{ self: this },
function(e) {
e.data.self.left();
+ e.preventDefault();
}
);
- this.setDragHandler2UP( this.prefetchedImgs[this.twoPage.currentIndexR] );
this.setClickHandler2UP( this.prefetchedImgs[this.twoPage.currentIndexR],
{ self: this },
function(e) {
e.data.self.right();
+ e.preventDefault();
}
);
}
this.updateToolbarZoom(this.reduce); // Pretty format
- if (ui == "embed") {
+ if (ui == "embed" || ui == "touch") {
$("#BookReader a.logo").attr("target","_blank");
}