X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=BookReader%2FBookReader.js;h=e2e1de7eaedc065da8f5c41e8e83dedf3f7d0488;hb=2f18c355b86fad952ddbecc2c623823405cec310;hp=0c101a3e84bc00f6e8d21bd01d2691209954e3cc;hpb=dfb5a3ab7ef6be1a92ecbfd65935534980e6ff7d;p=bookreader.git diff --git a/BookReader/BookReader.js b/BookReader/BookReader.js index 0c101a3..e2e1de7 100644 --- a/BookReader/BookReader.js +++ b/BookReader/BookReader.js @@ -36,14 +36,28 @@ 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 = 10; - this.mode = 1; //1, 2, 3 - this.ui = 'full'; // UI mode - this.thumbWidth = 100; - this.thumbRowBuffer = 3; // number of rows to pre-cache out a view + this.padding = 10; // Padding in 1up + + this.mode = this.constMode1up; + this.ui = 'full'; // UI mode + this.uiAutoHide = true; // 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 = []; + + this.displayedIndices = []; //this.indicesToDisplay = []; this.imgs = {}; this.prefetchedImgs = {}; //an object with numeric keys cooresponding to page index @@ -67,30 +81,58 @@ 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 - this.constMode1up = 1; - this.constMode2up = 2; - 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' + }; + + // 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; - // 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; }; // init() @@ -102,16 +144,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); + } } } @@ -127,20 +178,28 @@ 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; + 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(); @@ -148,6 +207,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 = []; @@ -183,11 +245,14 @@ BookReader.prototype.init = function() { $('.BRpagediv1up').bind('mousedown', this, function(e) { // $$$ the purpose of this is to disable selection of the image (makes it turn blue) // but this also interferes with right-click. See https://bugs.edge.launchpad.net/gnubook/+bug/362626 + return false; }); + // $$$ 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; @@ -206,6 +271,11 @@ BookReader.prototype.init = function() { // Enact other parts of initial params this.updateFromParams(params); + + // Start AJAX request for OL data + if (this.getOpenLibraryRecord) { + this.getOpenLibraryRecord(this.gotOpenLibraryRecord); + } } BookReader.prototype.setupKeyListeners = function() { @@ -272,169 +342,35 @@ 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(); } -} - -// setDragHandler() -//______________________________________________________________________________ -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'); - - 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() +// bindGestures(jElement) //______________________________________________________________________________ -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(); +BookReader.prototype.bindGestures = function(jElement) { - // 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; - } - - - }); - - /* - $(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) { + jElement.unbind('gesturechange').bind('gesturechange', function(e) { e.preventDefault(); - //console.log('mouseleave'); - - this.dragging = false; - this.mouseDown = false; + if (e.originalEvent.scale > 1.5) { + br.zoom(1); + } else if (e.originalEvent.scale < 0.6) { + br.zoom(-1); + } }); - - $(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); }); } @@ -470,7 +406,7 @@ BookReader.prototype.drawLeafsOnePage = function() { leafTop += height +10; leafBottom += 10; } - + var firstIndexToDraw = indicesToDisplay[0]; this.firstIndex = firstIndexToDraw; @@ -504,7 +440,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"); @@ -519,8 +455,6 @@ BookReader.prototype.drawLeafsOnePage = function() { $(div).css('height', height+'px'); //$(div).text('loading...'); - this.setDragHandler(div); - $('#BRpageview').append(div); var img = document.createElement("img"); @@ -538,7 +472,7 @@ BookReader.prototype.drawLeafsOnePage = function() { } for (i=0; iEmbed 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 += ''; + 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 = '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() { @@ -2861,7 +3070,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; @@ -3009,35 +3218,309 @@ 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( + ' ' + ); + +/* +