X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=BookReader%2FBookReader.js;h=f670591c8bf8a0988c817565af5d830d92a94923;hb=0cb1153f073d3f3406700c72b0e00048224a5b17;hp=d9d438d75f01ff8a55206b9af8ff954d09cb7c14;hpb=6d6ef45f1ecfc76af4d7e04e28c801d65326a1ea;p=bookreader.git diff --git a/BookReader/BookReader.js b/BookReader/BookReader.js index d9d438d..f670591 100644 --- a/BookReader/BookReader.js +++ b/BookReader/BookReader.js @@ -37,7 +37,7 @@ This file is part of BookReader. function BookReader() { this.reduce = 4; - this.padding = 10; + this.padding = 0; this.mode = 1; //1, 2, 3 this.ui = 'full'; // UI mode @@ -72,9 +72,13 @@ function BookReader() { this.lastDisplayableIndex2up = null; // 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'; - // Base URL for images + // Base URL for UI images - should be overriden (before init) by + // custom implementations. + // $$$ This is the same directory as the images referenced by relative + // path in the CSS. Would be better to automagically find that path. this.imagesBaseURL = '/bookreader/images/'; // Mode constants @@ -83,20 +87,27 @@ function BookReader() { this.constModeThumb = 3; // Zoom levels - this.reductionFactors = [0.5, 1, 2, 4, 8, 16]; - + // $$$ provide finer grained zooming + this.reductionFactors = [ {reduce: 0.5, autofit: null}, + {reduce: 1, autofit: null}, + {reduce: 2, autofit: null}, + {reduce: 4, autofit: null}, + {reduce: 8, autofit: null}, + {reduce: 16, autofit: null} ]; + + // 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: true + coverInternalPadding: 0, // Width of cover + coverExternalPadding: 0, // Padding outside of cover + bookSpineDivWidth: 0, // Width of book spine $$$ consider sizing based on book length + 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)'; - return this; }; @@ -109,16 +120,25 @@ BookReader.prototype.init = function() { // Find start index and mode if set in location hash var params = this.paramsFromFragment(window.location.hash); + + // Sanitize/process parameters + + if ( !this.canSwitchToMode( this.mode ) ) { + this.mode = this.constMode1up; + } if ('undefined' != typeof(params.index)) { startIndex = params.index; } else if ('undefined' != typeof(params.page)) { startIndex = this.getPageIndex(params.page); } - + if ('undefined' == typeof(startIndex)) { if ('undefined' != typeof(this.titleLeaf)) { - startIndex = this.leafNumToIndex(this.titleLeaf); + // title leaf is known - but only use as default if book has a few pages + if (this.numLeafs > 2) { + startIndex = this.leafNumToIndex(this.titleLeaf); + } } } @@ -134,20 +154,26 @@ BookReader.prototype.init = function() { // search engine visibility document.title = this.shortTitle(50); - // Sanitize parameters - if ( !this.canSwitchToMode( this.mode ) ) { - this.mode = this.constMode1up; - } - $("#BookReader").empty(); + this.initToolbar(this.mode, this.ui); // Build inside of toolbar div + $("#BookReader").append("
"); $("#BRcontainer").append("
"); + + this.initNavbar(); + this.bindNavigationHandlers(); + + // Autohide nav after showing for awhile + var self = this; + $(window).bind('load', function() { + setTimeout(function() { self.hideNavigation(); }, 3000); + }); $("#BRcontainer").bind('scroll', this, function(e) { e.data.loadLeafs(); }); - + this.setupKeyListeners(); this.startLocationPolling(); @@ -155,6 +181,9 @@ BookReader.prototype.init = function() { //console.log('resize!'); if (1 == e.data.mode) { //console.log('centering 1page view'); + if (e.data.autofit) { + e.data.resizePageView(); + } e.data.centerPageView(); $('#BRpageview').empty() e.data.displayedIndices = []; @@ -196,8 +225,8 @@ BookReader.prototype.init = function() { // $$$ 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; @@ -216,6 +245,8 @@ BookReader.prototype.init = function() { // Enact other parts of initial params this.updateFromParams(params); + + //XXXmang window.setTimeout(self.hideNavigation, 3000); } BookReader.prototype.setupKeyListeners = function() { @@ -282,7 +313,7 @@ BookReader.prototype.setupKeyListeners = function() { BookReader.prototype.drawLeafs = function() { if (1 == this.mode) { this.drawLeafsOnePage(); - } else if(3 == this.mode) { + } else if (3 == this.mode) { this.drawLeafsThumbnail(); } else { this.drawLeafsTwoPage(); @@ -290,162 +321,27 @@ BookReader.prototype.drawLeafs = function() { } -// setDragHandler() +// bindGestures(jElement) //______________________________________________________________________________ -BookReader.prototype.setDragHandler = function(div) { - div.dragging = false; - - $(div).unbind('mousedown').bind('mousedown', 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'); +BookReader.prototype.bindGestures = function(jElement) { - this.dragging = false; - }); - - $(div).unbind('mouseleave').bind('mouseleave', function(e) { + jElement.unbind('gesturechange').bind('gesturechange', 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); }); } @@ -481,7 +377,7 @@ BookReader.prototype.drawLeafsOnePage = function() { leafTop += height +10; leafBottom += 10; } - + var firstIndexToDraw = indicesToDisplay[0]; this.firstIndex = firstIndexToDraw; @@ -515,7 +411,7 @@ BookReader.prototype.drawLeafsOnePage = function() { var index = indicesToDisplay[i]; var height = parseInt(this._getPageHeight(index)/this.reduce); - if(-1 == jQuery.inArray(indicesToDisplay[i], this.displayedIndices)) { + if (BookReader.util.notInArray(indicesToDisplay[i], this.displayedIndices)) { var width = parseInt(this._getPageWidth(index)/this.reduce); //console.log("displaying leaf " + indicesToDisplay[i] + ' leafTop=' +leafTop); var div = document.createElement("div"); @@ -530,8 +426,6 @@ BookReader.prototype.drawLeafsOnePage = function() { $(div).css('height', height+'px'); //$(div).text('loading...'); - this.setDragHandler(div); - $('#BRpageview').append(div); var img = document.createElement("img"); @@ -549,7 +443,7 @@ BookReader.prototype.drawLeafsOnePage = function() { } for (i=0; i mostVisible) { + mostVisible = leafMap[i].leafs[leafMap[i].leafs.length - 1].num; + } } - if(leafTop > leafMap[i].top) { leafMap[i].top = leafTop; } + if (leafTop > leafMap[i].top) { leafMap[i].top = leafTop; } leafTop = leafBottom; } @@ -658,12 +577,6 @@ BookReader.prototype.drawLeafsThumbnail = function() { 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; @@ -674,7 +587,7 @@ BookReader.prototype.drawLeafsThumbnail = function() { var img; var page; for (i=0; i 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 @@ -863,10 +792,8 @@ BookReader.prototype.drawLeafsTwoPage = function() { 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', zIndex: 2 }).appendTo('#BRtwopageview'); @@ -883,10 +810,8 @@ BookReader.prototype.drawLeafsTwoPage = function() { 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', zIndex: 2 }).appendTo('#BRtwopageview'); @@ -934,33 +859,47 @@ BookReader.prototype.loadLeafs = function() { BookReader.prototype.zoom = function(direction) { switch (this.mode) { case this.constMode1up: - return this.zoom1up(direction); + if (direction == 1) { + // XXX other cases + return this.zoom1up('in'); + } else { + return this.zoom1up('out'); + } + case this.constMode2up: - return this.zoom2up(direction); + if (direction == 1) { + // XXX other cases + return this.zoom2up('in'); + } else { + return this.zoom2up('out'); + } + case this.constModeThumb: + // XXX update zoomThumb for named directions return this.zoomThumb(direction); + } } // zoom1up(dir) //______________________________________________________________________________ -BookReader.prototype.zoom1up = function(dir) { +BookReader.prototype.zoom1up = function(direction) { if (2 == this.mode) { //can only zoom in 1-page mode this.switchMode(1); return; } - // $$$ with flexible zoom we could "snap" to /2 page reductions - // for better scaling - if (1 == dir) { - if (this.reduce <= 0.5) return; - this.reduce*=0.5; //zoom in - } else { - if (this.reduce >= 8) return; - this.reduce*=2; //zoom out + var reduceFactor = this.nextReduce(this.reduce, direction, this.onePage.reductionFactors); + + if (this.reduce == reduceFactor.reduce) { + // Already at this level + return; } - + + this.reduce = reduceFactor.reduce; // $$$ incorporate into function + this.onePage.autofit = reduceFactor.autofit; + this.pageScale = this.reduce; // preserve current reduce this.resizePageView(); @@ -984,6 +923,20 @@ BookReader.prototype.resizePageView = 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 @@ -1003,13 +956,22 @@ BookReader.prototype.resizePageView = function() { var scrollRatio = 0; } + // Recalculate 1up reduction factors + this.onePageCalculateReductionFactors( $('#BRcontainer').attr('clientWidth'), + $('#BRcontainer').attr('clientHeight') ); + // Update current reduce (if in autofit) + if (this.onePage.autofit) { + var reductionFactor = this.nextReduce(this.reduce, this.onePage.autofit, this.onePage.reductionFactors); + this.reduce = reductionFactor.reduce; + } + for (i=0; iviewWidth) 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 )); @@ -1024,14 +986,12 @@ BookReader.prototype.resizePageView = function() { //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. @@ -1074,13 +1034,17 @@ BookReader.prototype.zoom2up = function(direction) { // Hard stop autoplay this.stopFlipAnimations(); - // Get new zoom state - var newZoom = this.twoPageNextReduce(this.reduce, direction); - if ((this.reduce == newZoom.reduce) && (this.twoPage.autofit == newZoom.autofit)) { + // Recalculate autofit factors + this.twoPageCalculateReductionFactors(); + + // Get new zoom state + var reductionFactor = this.nextReduce(this.reduce, direction, this.twoPage.reductionFactors); + if ((this.reduce == reductionFactor.reduce) && (this.twoPage.autofit == reductionFactor.autofit)) { + // Same zoom return; } - this.twoPage.autofit = newZoom.autofit; - this.reduce = newZoom.reduce; + this.twoPage.autofit = reductionFactor.autofit; + this.reduce = reductionFactor.reduce; this.pageScale = this.reduce; // preserve current reduce // Preserve view center position @@ -1118,7 +1082,6 @@ BookReader.prototype.zoomThumb = function(direction) { if (this.thumbColumns != oldColumns) { this.prepareThumbnailView(); - this.jumpToIndex(this.currentIndex()); } } @@ -1134,70 +1097,62 @@ BookReader.prototype.getThumbnailWidth = function(thumbnailColumns) { // quantizeReduce(reduce) //______________________________________________________________________________ // Quantizes the given reduction factor to closest power of two from set from 12.5% to 200% -BookReader.prototype.quantizeReduce = function(reduce) { - var quantized = this.reductionFactors[0]; +BookReader.prototype.quantizeReduce = function(reduce, reductionFactors) { + var quantized = reductionFactors[0].reduce; var distance = Math.abs(reduce - quantized); - for (var i = 1; i < this.reductionFactors.length; i++) { - newDistance = Math.abs(reduce - this.reductionFactors[i]); + for (var i = 1; i < reductionFactors.length; i++) { + newDistance = Math.abs(reduce - reductionFactors[i].reduce); if (newDistance < distance) { distance = newDistance; - quantized = this.reductionFactors[i]; + quantized = reductionFactors[i].reduce; } } return quantized; } -// twoPageNextReduce() -//______________________________________________________________________________ -// Returns the next reduction level -BookReader.prototype.twoPageNextReduce = function(reduce, direction) { - var result = {}; - var autofitReduce = this.twoPageGetAutofitReduce(); +// reductionFactors should be array of sorted reduction factors +// e.g. [ {reduce: 0.25, autofit: null}, {reduce: 0.3, autofit: 'width'}, {reduce: 1, autofit: null} ] +BookReader.prototype.nextReduce = function( currentReduce, direction, reductionFactors ) { - if (0 == direction) { // autofit - result.autofit = true; - result.reduce = autofitReduce; - - } else if (1 == direction) { // zoom in - var newReduce = this.reductionFactors[0]; + // XXX add 'closest', to replace quantize function + + if (direction == 'in') { + var newReduceIndex = 0; - for (var i = 1; i < this.reductionFactors.length; i++) { - if (this.reductionFactors[i] < reduce) { - newReduce = this.reductionFactors[i]; + for (var i = 1; i < reductionFactors.length; i++) { + if (reductionFactors[i].reduce < currentReduce) { + newReduceIndex = i; } } + return reductionFactors[newReduceIndex]; - if (!this.twoPage.autofit && (autofitReduce < reduce && autofitReduce > newReduce)) { - // use autofit - result.autofit = true; - result.reduce = autofitReduce; - } else { - result.autofit = false; - result.reduce = newReduce; - } - - } else { // zoom out - var lastIndex = this.reductionFactors.length - 1; - var newReduce = this.reductionFactors[lastIndex]; + } else if (direction == 'out') { // zoom out + var lastIndex = reductionFactors.length - 1; + var newReduceIndex = lastIndex; for (var i = lastIndex; i >= 0; i--) { - if (this.reductionFactors[i] > reduce) { - newReduce = this.reductionFactors[i]; + if (reductionFactors[i].reduce > currentReduce) { + newReduceIndex = i; } } - - if (!this.twoPage.autofit && (autofitReduce > reduce && autofitReduce < newReduce)) { - // use autofit - result.autofit = true; - result.reduce = autofitReduce; - } else { - result.autofit = false; - result.reduce = newReduce; + return reductionFactors[newReduceIndex]; + } + + // Asked for specific autofit mode + for (var i = 0; i < reductionFactors.length; i++) { + if (reductionFactors[i].autofit == direction) { + return reductionFactors[i]; } } - return result; + alert('Could not find reduction factor for direction ' + direction); + return reductionFactors[0]; + +} + +BookReader.prototype._reduceSort = function(a, b) { + return a.reduce - b.reduce; } // jumpToPage() @@ -1223,7 +1178,7 @@ BookReader.prototype.jumpToPage = function(pageNum) { //______________________________________________________________________________ BookReader.prototype.jumpToIndex = function(index, pageX, pageY) { - if (2 == this.mode) { + if (this.constMode2up == this.mode) { this.autoStop(); // By checking against min/max we do nothing if requested index @@ -1234,7 +1189,7 @@ BookReader.prototype.jumpToIndex = function(index, pageX, pageY) { this.flipFwdToIndex(index); } - } else if (3 == this.mode) { + } else if (this.constModeThumb == this.mode) { var viewWidth = $('#BRcontainer').attr('scrollWidth') - 20; // width minus buffer var i; var leafWidth = 0; @@ -1252,8 +1207,9 @@ BookReader.prototype.jumpToIndex = function(index, pageX, pageY) { rowHeight = 0; leafIndex = 0; } - leafHeight = parseInt((this.getPageHeight(leaf)*this.thumbWidth)/this.getPageWidth(leaf), 10); - if(leafHeight > rowHeight) { rowHeight = leafHeight; } + + 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; @@ -1266,6 +1222,7 @@ BookReader.prototype.jumpToIndex = function(index, pageX, pageY) { $('#BRcontainer').animate({scrollTop: leafTop },'fast'); } } else { + // 1up var i; var leafTop = 0; var leafLeft = 0; @@ -1281,12 +1238,18 @@ BookReader.prototype.jumpToIndex = function(index, pageX, pageY) { offset -= $('#BRcontainer').attr('clientHeight') >> 1; //console.log( 'jumping to ' + leafTop + ' ' + offset); leafTop += offset; + } else { + // Show page just a little below the top + leafTop -= this.padding / 2; } if (pageX) { var offset = parseInt( (pageX) / this.reduce); offset -= $('#BRcontainer').attr('clientWidth') >> 1; leafLeft += offset; + } else { + // Preserve left position + leafLeft = $('#BRcontainer').scrollLeft(); } //$('#BRcontainer').attr('scrollTop', leafTop); @@ -1313,7 +1276,7 @@ BookReader.prototype.switchMode = function(mode) { this.removeSearchHilites(); this.mode = mode; - this.switchToolbarMode(mode); + //this.switchToolbarMode(mode); // reinstate scale if moving from thumbnail view if (this.pageScale != this.reduce) { @@ -1323,17 +1286,23 @@ BookReader.prototype.switchMode = function(mode) { // $$$ TODO preserve center of view when switching between mode // See https://bugs.edge.launchpad.net/gnubook/+bug/416682 + // XXX maybe better to preserve zoom in each mode if (1 == mode) { - this.reduce = this.quantizeReduce(this.reduce); + this.onePageCalculateReductionFactors( $('#BRcontainer').attr('clientWidth'), $('#BRcontainer').attr('clientHeight')); + this.reduce = this.quantizeReduce(this.reduce, this.onePage.reductionFactors); this.prepareOnePageView(); } else if (3 == mode) { - this.reduce = this.quantizeReduce(this.reduce); + $('button.thumb').hide(); + $('button.twopg').show(); + this.reduce = this.quantizeReduce(this.reduce, this.reductionFactors); this.prepareThumbnailView(); - this.jumpToIndex(this.currentIndex()); } else { // $$$ why don't we save autofit? - this.twoPage.autofit = false; // Take zoom level from other mode - this.reduce = this.quantizeReduce(this.reduce); + // this.twoPage.autofit = null; // Take zoom level from other mode + this.twoPageCalculateReductionFactors(); + this.reduce = this.quantizeReduce(this.reduce, this.twoPage.reductionFactors); + $('button.thumb').show(); + $('button.twopg').hide(); this.prepareTwoPageView(); this.twoPageCenterView(0.5, 0.5); // $$$ TODO preserve center } @@ -1346,19 +1315,24 @@ BookReader.prototype.prepareOnePageView = function() { // var startLeaf = this.displayedIndices[0]; var startLeaf = this.currentIndex(); - + $('#BRcontainer').empty(); $('#BRcontainer').css({ overflowY: 'scroll', overflowX: 'auto' }); - + $("#BRcontainer").append("
"); + + // 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 = []; @@ -1375,23 +1349,24 @@ BookReader.prototype.prepareThumbnailView = function() { overflowY: 'scroll', overflowX: 'auto' }); - + $("#BRcontainer").append("
"); + + $('#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() @@ -1444,6 +1419,10 @@ BookReader.prototype.prepareTwoPageView = function(centerPercentageX, centerPerc // Add the two page view // $$$ Can we get everything set up and then append? $('#BRcontainer').append('
'); + + // Attaches to first child, so must come after we add the page view + $('#BRcontainer').dragscrollable(); + this.bindGestures($('#BRcontainer')); // $$$ calculate first then set $('#BRtwopageview').css( { @@ -1465,56 +1444,33 @@ BookReader.prototype.prepareTwoPageView = function(centerPercentageX, centerPerc 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.className = 'BRleafEdgeR'; $(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', - /*right: '10px',*/ + height: this.twoPage.height + 'px', left: this.twoPage.gutter+this.twoPage.scaledWR+'px', - top: this.twoPage.bookCoverDivTop+this.twoPage.coverInternalPadding+'px', - position: 'absolute' + top: this.twoPage.bookCoverDivTop+this.twoPage.coverInternalPadding+'px' }).appendTo('#BRtwopageview'); 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', - background: 'transparent url(' + this.imagesBaseURL + 'left_edges.png) repeat scroll 0% 0%', + 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', - position: 'absolute' + top: this.twoPage.bookCoverDivTop+this.twoPage.coverInternalPadding+'px' }).appendTo('#BRtwopageview'); 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'); @@ -1533,7 +1489,7 @@ BookReader.prototype.prepareTwoPageView = function(centerPercentageX, centerPerc top: this.twoPageFlipAreaTop() + 'px', cursor: 'w-resize', zIndex: 100 - }).bind('click', function(e) { + }).click(function(e) { self.left(); }).bind('mousedown', function(e) { e.preventDefault(); @@ -1550,7 +1506,7 @@ BookReader.prototype.prepareTwoPageView = function(centerPercentageX, centerPerc top: this.twoPageFlipAreaTop() + 'px', cursor: 'e-resize', zIndex: 100 - }).bind('click', function(e) { + }).click(function(e) { self.right(); }).bind('mousedown', function(e) { e.preventDefault(); @@ -1583,15 +1539,9 @@ BookReader.prototype.prepareTwoPageView = function(centerPercentageX, centerPerc BookReader.prototype.prepareTwoPagePopUp = function() { this.twoPagePopUp = document.createElement('div'); + this.twoPagePopUp.className = 'BRtwoPagePopUp'; $(this.twoPagePopUp).css({ - border: '1px solid black', - padding: '2px 6px', - position: 'absolute', - fontFamily: 'sans-serif', - fontSize: '14px', - zIndex: '1000', - backgroundColor: 'rgb(255, 255, 238)', - opacity: 0.85 + zIndex: '1000' }).appendTo('#BRcontainer'); $(this.twoPagePopUp).hide(); @@ -1623,7 +1573,7 @@ BookReader.prototype.prepareTwoPagePopUp = function() { // $$$ TODO: Make sure popup is positioned so that it is in view // (https://bugs.edge.launchpad.net/gnubook/+bug/327456) $(e.data.twoPagePopUp).css({ - left: e.pageX- $('#BRcontainer').offset().left + $('#BRcontainer').scrollLeft() + 20 + 'px', + left: e.pageX- $('#BRcontainer').offset().left + $('#BRcontainer').scrollLeft() - 100 + 'px', top: e.pageY - $('#BRcontainer').offset().top + $('#BRcontainer').scrollTop() + 'px' }); }); @@ -1636,7 +1586,7 @@ BookReader.prototype.prepareTwoPagePopUp = function() { // $$$ TODO: Make sure popup is positioned so that it is in view // (https://bugs.edge.launchpad.net/gnubook/+bug/327456) $(e.data.twoPagePopUp).css({ - left: e.pageX - $('#BRcontainer').offset().left + $('#BRcontainer').scrollLeft() - $(e.data.twoPagePopUp).width() - 25 + 'px', + left: e.pageX - $('#BRcontainer').offset().left + $('#BRcontainer').scrollLeft() - $(e.data.twoPagePopUp).width() + 100 + 'px', top: e.pageY-$('#BRcontainer').offset().top + $('#BRcontainer').scrollTop() + 'px' }); }); @@ -1680,7 +1630,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; @@ -1803,6 +1753,55 @@ BookReader.prototype.twoPageGetAutofitReduce = function() { return spreadSize.reduce; } +BookReader.prototype.onePageGetAutofitWidth = function() { + var widthPadding = 20; + return (this.getMedianPageSize().width + 0.0) / ($('#BRcontainer').attr('clientWidth') - widthPadding * 2); +} + +BookReader.prototype.onePageGetAutofitHeight = function() { + return (this.getMedianPageSize().height + 0.0) / ($('#BRcontainer').attr('clientHeight') - this.padding * 2); // make sure a little of adjacent pages show +} + +BookReader.prototype.getMedianPageSize = function() { + if (this._medianPageSize) { + return this._medianPageSize; + } + + // A little expensive but we just do it once + var widths = []; + var heights = []; + for (var i = 0; i < this.numLeafs; i++) { + widths.push(this.getPageWidth(i)); + heights.push(this.getPageHeight(i)); + } + + widths.sort(); + heights.sort(); + + this._medianPageSize = { width: widths[parseInt(widths.length / 2)], height: heights[parseInt(heights.length / 2)] }; + return this._medianPageSize; +} + +// Update the reduction factors for 1up mode given the available width and height. Recalculates +// the autofit reduction factors. +BookReader.prototype.onePageCalculateReductionFactors = function( width, height ) { + this.onePage.reductionFactors = this.reductionFactors.concat( + [ + { reduce: this.onePageGetAutofitWidth(), autofit: 'width' }, + { reduce: this.onePageGetAutofitHeight(), autofit: 'height'} + ]); + this.onePage.reductionFactors.sort(this._reduceSort); +} + +BookReader.prototype.twoPageCalculateReductionFactors = function() { + this.twoPage.reductionFactors = this.reductionFactors.concat( + [ + { reduce: this.getIdealSpreadSize( this.twoPage.currentIndexL, this.twoPage.currentIndexR ).reduce, + autofit: 'auto' } + ]); + this.twoPage.reductionFactors.sort(this._reduceSort); +} + // twoPageSetCursor() //______________________________________________________________________________ // Set the cursor for two page view @@ -1833,6 +1832,15 @@ BookReader.prototype.currentIndex = function() { } } +// 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() //______________________________________________________________________________ // Flip the right page over onto the left @@ -1919,10 +1927,15 @@ BookReader.prototype.last = function() { //______________________________________________________________________________ // Scrolls down one screen view BookReader.prototype.scrollDown = function() { - if ($.inArray(this.mode, [this.constMode2up, this.constModeThumb])) { + if ($.inArray(this.mode, [this.constMode1up, this.constModeThumb]) >= 0) { + if ( this.mode == this.constMode1up && (this.reduce >= this.onePageGetAutofitHeight()) ) { + // Whole pages are visible, scroll whole page only + return this.next(); + } + $('#BRcontainer').animate( - { scrollTop: '+=' + $('#BRcontainer').height() * 0.95 + 'px'}, - 450, 'easeInOutQuint' + { scrollTop: '+=' + this._scrollAmount() + 'px'}, + 400, 'easeInOutExpo' ); return true; } else { @@ -1934,10 +1947,15 @@ BookReader.prototype.scrollDown = function() { //______________________________________________________________________________ // Scrolls up one screen view BookReader.prototype.scrollUp = function() { - if ($.inArray(this.mode, [this.constMode2up, this.constModeThumb])) { + if ($.inArray(this.mode, [this.constMode1up, this.constModeThumb]) >= 0) { + if ( this.mode == this.constMode1up && (this.reduce >= this.onePageGetAutofitHeight()) ) { + // Whole pages are visible, scroll whole page only + return this.prev(); + } + $('#BRcontainer').animate( - { scrollTop: '-=' + $('#BRcontainer').height() * 0.95 + 'px'}, - 450, 'easeInOutQuint' + { scrollTop: '-=' + this._scrollAmount() + 'px'}, + 400, 'easeInOutExpo' ); return true; } else { @@ -1945,6 +1963,18 @@ BookReader.prototype.scrollUp = function() { } } +// _scrollAmount() +//______________________________________________________________________________ +// The amount to scroll vertically in integer pixels +BookReader.prototype._scrollAmount = function() { + if (this.constMode1up == this.mode) { + // Overlap by % of page size + return parseInt($('#BRcontainer').attr('clientHeight') - this.getPageHeight(this.currentIndex()) / this.reduce * 0.03); + } + + return parseInt(0.9 * $('#BRcontainer').attr('clientHeight')); +} + // flipBackToIndex() //______________________________________________________________________________ @@ -2037,16 +2067,12 @@ BookReader.prototype.flipLeftToRight = function(newIndexL, newIndexR) { var leftEdgeTmpLeft = gutter - currWidthL - leafEdgeTmpW; this.leafEdgeTmp = document.createElement('div'); + this.leafEdgeTmp.className = 'BRleafEdgeTmp'; $(this.leafEdgeTmp).css({ - borderStyle: 'solid none solid solid', - borderColor: 'rgb(51, 51, 34)', - borderWidth: '1px 0px 1px 1px', - background: 'transparent url(' + this.imagesBaseURL + 'left_edges.png) repeat scroll 0% 0%', width: leafEdgeTmpW + 'px', - height: this.twoPage.height-1 + 'px', + height: this.twoPage.height + 'px', left: leftEdgeTmpLeft + 'px', - top: top+'px', - position: 'absolute', + top: top+'px', zIndex:1000 }).appendTo('#BRtwopageview'); @@ -2190,16 +2216,12 @@ BookReader.prototype.flipRightToLeft = function(newIndexL, newIndexR) { var gutter = middle + this.gutterOffsetForIndex(newIndexL); this.leafEdgeTmp = document.createElement('div'); + this.leafEdgeTmp.className = 'BRleafEdgeTmp'; $(this.leafEdgeTmp).css({ - borderStyle: 'solid none solid solid', - borderColor: 'rgb(51, 51, 34)', - borderWidth: '1px 0px 1px 1px', - background: 'transparent url(' + this.imagesBaseURL + 'left_edges.png) repeat scroll 0% 0%', width: leafEdgeTmpW + 'px', - height: this.twoPage.height-1 + 'px', + height: this.twoPage.height + 'px', left: gutter+scaledW+'px', top: top+'px', - position: 'absolute', zIndex:1000 }).appendTo('#BRtwopageview'); @@ -2270,32 +2292,19 @@ BookReader.prototype.flipRightToLeft = function(newIndexL, newIndexR) { // 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(); } ); } @@ -2318,6 +2327,13 @@ BookReader.prototype.prefetchImg = function(index) { 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; @@ -2359,8 +2375,7 @@ BookReader.prototype.prepareFlipLeftToRight = function(prevL, prevR) { top: top+'px', height: this.twoPage.height, width: scaledW+'px', - backgroundColor: this.getPageBackgroundColor(prevL), - borderRight: '1px solid black', + borderRight: '1px solid black', // XXXmang check zIndex: 1 } @@ -2376,9 +2391,8 @@ BookReader.prototype.prepareFlipLeftToRight = function(prevL, prevR) { right: '', top: top+'px', height: this.twoPage.height, - width: '0px', - backgroundColor: this.getPageBackgroundColor(prevR), - borderLeft: '1px solid black', + borderLeft: '1px solid black', // XXXmang check + width: '0', zIndex: 2 } @@ -2412,10 +2426,8 @@ BookReader.prototype.prepareFlipRightToLeft = function(nextL, nextR) { position: 'absolute', left: gutter+'px', top: top+'px', - backgroundColor: this.getPageBackgroundColor(nextR), height: this.twoPage.height, width: scaledW+'px', - borderLeft: '1px solid black', zIndex: 1 }); @@ -2430,10 +2442,8 @@ BookReader.prototype.prepareFlipRightToLeft = function(nextL, nextR) { 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', zIndex: 2 }); @@ -2643,9 +2653,9 @@ BookReader.prototype.updateSearchHilites1UP = function() { for (var key in this.searchResults) { - if (-1 != jQuery.inArray(parseInt(key), this.displayedIndices)) { + if (jQuery.inArray(parseInt(key), this.displayedIndices) >= 0) { var result = this.searchResults[key]; - if(null == result.div) { + if (null == result.div) { result.div = document.createElement('div'); $(result.div).attr('className', 'BookReaderSearchHilite').appendTo('#pagediv'+key); //console.log('appending ' + key); @@ -2797,9 +2807,9 @@ BookReader.prototype.updateSearchHilites2UP = function() { for (var key in this.searchResults) { key = parseInt(key, 10); - if (-1 != jQuery.inArray(key, this.displayedIndices)) { + if (jQuery.inArray(key, this.displayedIndices) >= 0) { var result = this.searchResults[key]; - if(null == result.div) { + if (null == result.div) { result.div = document.createElement('div'); $(result.div).attr('className', 'BookReaderSearchHilite').css('zIndex', 3).appendTo('#BRtwopageview'); //console.log('appending ' + key); @@ -2854,62 +2864,6 @@ 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 = '
'; - htmlStr = '

Click here to print this page

'; - htmlStr += '
' - htmlStr += '

'; - //htmlStr += ' '; - //htmlStr += ''; - htmlStr += 'Prev Next'; - htmlStr += '

'; - htmlStr += '
'; - htmlStr += '

Close popup

'; - htmlStr += '
'; - - 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 @@ -2921,7 +2875,7 @@ BookReader.prototype.getPrintURI = function() { 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); @@ -2988,33 +2942,74 @@ BookReader.prototype.updatePrintFrame = function(delta) { // showEmbedCode() //______________________________________________________________________________ BookReader.prototype.showEmbedCode = function() { - if (null != this.embedPopup) { // check if already showing - return; - } - this.autoStop(); this.embedPopup = document.createElement("div"); $(this.embedPopup).css({ position: 'absolute', - top: '20px', + top: ($('#BRcontainer').attr('clientHeight')-250)/2 + 'px', left: ($('#BRcontainer').attr('clientWidth')-400)/2 + 'px', width: '400px', - padding: "20px", - border: "3px double #999999", - zIndex: 3, - backgroundColor: "#fff" + height: '250px', + padding: '0', + fontSize: '12px', + color: '#333', + zIndex: 300, + border: '10px solid #615132', + backgroundColor: "#fff", + MozBorderRadius: '8px', + MozBoxShadow: '0 0 6px #000', + WebkitBorderRadius: '8px', + WebkitBoxShadow: '0 0 6px #000' }).appendTo('#BookReader'); - htmlStr = '

Embed Bookreader in your blog!

'; - htmlStr += '

The bookreader uses iframes for embedding. It will not work on web hosts that block iframes. The embed feature has been tested on blogspot.com blogs as well as self-hosted Wordpress blogs. This feature will NOT work on wordpress.com blogs.

'; - htmlStr += '

Embed Code:

'; - htmlStr += '

Close popup

'; + htmlStr = '

Embed Bookreader

'; + htmlStr += '

The bookreader uses iframes for embedding. It will not work on web hosts that block iframes. The embed feature has been tested on blogspot.com blogs as well as self-hosted Wordpress blogs. This feature will NOT work on wordpress.com blogs.

'; + htmlStr += ''; + htmlStr += 'Close'; this.embedPopup.innerHTML = htmlStr; - $(this.embedPopup).find('input').bind('click', function() { + $('#BookReader').append('
'); + $(this.embedPopup).find('textarea').click(function() { this.select(); }) + $(this.embedPopup).addClass("popped"); } +// showBookmarkCode() +//______________________________________________________________________________ +BookReader.prototype.showBookmarkCode = function() { + this.bookmarkPopup = document.createElement("div"); + $(this.bookmarkPopup).css({ + position: 'absolute', + top: ($('#BRcontainer').attr('clientHeight')-250)/2 + 'px', + left: ($('#BRcontainer').attr('clientWidth')-400)/2 + 'px', + width: '400px', + height: '250px', + padding: '0', + fontSize: '12px', + color: '#333', + zIndex: 300, + border: '10px solid #615132', + backgroundColor: "#fff", + MozBorderRadius: '8px', + MozBoxShadow: '0 0 6px #000', + WebkitBorderRadius: '8px', + WebkitBoxShadow: '0 0 6px #000' + }).appendTo('#BookReader'); + + htmlStr = '

Add a bookmark

'; + htmlStr += '

You can add a bookmark to any page in any book. If you elect to make your bookmark public, other readers will be able to see it. You must be logged in to your Open Library account to add bookmarks.

'; + htmlStr += '



'; + htmlStr += 'Close'; + + this.bookmarkPopup.innerHTML = htmlStr; + $('#BookReader').append('
'); + $(this.bookmarkPopup).find('textarea').click(function() { + this.select(); + }) + $(this.bookmarkPopup).addClass("popped"); +} + + // autoToggle() //______________________________________________________________________________ BookReader.prototype.autoToggle = function() { @@ -3027,7 +3022,7 @@ BookReader.prototype.autoToggle = function() { // Change to autofit if book is too large if (this.reduce < this.twoPageGetAutofitReduce()) { - this.zoom2up(0); + this.zoom2up('auto'); } var self = this; @@ -3175,36 +3170,167 @@ 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 + $('.chapter').bt({ + contentSelector: '$(this).find(".title")', + trigger: 'hover', + closeWhenOthersOpen: true, + cssStyles: { + backgroundColor: '#000', + border: '2px solid #e2dcc5', + borderBottom: 'none', + padding: '5px 10px', + fontFamily: '"Arial", sans-serif', + fontSize: '11px', + fontWeight: '700', + color: '#fff', + whiteSpace: 'nowrap' + }, + shrinkToFit: true, + width: '200px', + padding: 0, + spikeGirth: 0, + spikeLength: 0, + overlap: '16px', + overlay: false, + killTitle: true, + textzIndex: 9999, + boxzIndex: 9998, + wrapperzIndex: 9997, + offsetParent: null, + positions: ['top'], + fill: 'black', + windowMargin: 10, + strokeWidth: 0, + cornerRadius: 0, + centerPointX: 0, + centerPointY: 0, + shadow: false + }); + $('.search').bt({ + contentSelector: '$(this).find(".query")', + trigger: 'click', + closeWhenOthersOpen: true, + cssStyles: { + padding: '10px 10px 15px', + backgroundColor: '#fff', + border: '3px solid #e2dcc5', + borderBottom: 'none', + fontFamily: '"Lucida Grande","Arial",sans-serif', + fontSize: '12px', + lineHeight: '18px', + color: '#615132' + }, + shrinkToFit: false, + width: '230px', + padding: 0, + spikeGirth: 0, + spikeLength: 0, + overlap: '10px', + overlay: false, + killTitle: false, + textzIndex: 9999, + boxzIndex: 9998, + wrapperzIndex: 9997, + offsetParent: null, + positions: ['top'], + fill: 'white', + windowMargin: 10, + strokeWidth: 3, + strokeStyle: '#e2dcc5', + cornerRadius: 0, + centerPointX: 0, + centerPointY: 0, + shadow: false + }); + $('.searchChap').bt({ + contentSelector: '$(this).find(".query")', + trigger: 'click', + closeWhenOthersOpen: true, + cssStyles: { + width: '250px', + padding: '10px 10px 15px', + backgroundColor: '#fff', + border: '3px solid #e2dcc5', + borderBottom: 'none', + fontFamily: '"Lucida Grande","Arial",sans-serif', + fontSize: '12px', + lineHeight: '18px', + color: '#615132' + }, + shrinkToFit: false, + width: '230px', + padding: 0, + spikeGirth: 0, + spikeLength: 0, + overlap: '10px', + overlay: false, + killTitle: true, + textzIndex: 9999, + boxzIndex: 9998, + wrapperzIndex: 9997, + offsetParent: null, + positions: ['top'], + fill: 'white', + windowMargin: 10, + strokeWidth: 3, + strokeStyle: '#e2dcc5', + cornerRadius: 0, + centerPointX: 0, + centerPointY: 0, + shadow: false + }); + $('.chapter').each(function(){ + $(this).hover(function(){ + $(this).addClass('front'); + },function(){ + $(this).removeClass('front'); + }); + }); + $('.search').each(function(){ + $(this).hover(function(){ + $(this).addClass('front'); + },function(){ + $(this).removeClass('front'); + }); + }); + $('.searchChap').each(function(){ + $(this).hover(function(){ + $(this).addClass('front'); + },function(){ + $(this).removeClass('front'); + }); + }); + $("#BRslider").draggable({axis:'x',containment:'parent'}); +} + BookReader.prototype.initToolbar = function(mode, ui) { - $("#BookReader").append("
" - + "" - + "
" - + "" - + "" - + "" + + "" + + "" + + "" + + "" + "" + "" - + "" - + "