//console.log('setting handler');
//console.log(element.tagName);
- $(element).unbind('tap').bind('tap', data, function(e) {
+ $(element).unbind('click').bind('click', data, function(e) {
handler(e);
});
}
this.willChangeToIndex(index);
+ this.ttsStop();
+
if (this.constMode2up == this.mode) {
this.autoStop();
this.reduce = this.quantizeReduce(this.reduce, this.onePage.reductionFactors);
this.prepareOnePageView();
} else if (3 == mode) {
- $('button.thumb').hide();
- $('button.twopg').show();
this.reduce = this.quantizeReduce(this.reduce, this.reductionFactors);
this.prepareThumbnailView();
} else {
// 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
}
$('#BRcontainer').append('<div id="BRtwopageview"></div>');
// Attaches to first child, so must come after we add the page view
- $('#BRcontainer').dragscrollable();
+ //$('#BRcontainer').dragscrollable();
this.bindGestures($('#BRcontainer'));
// $$$ calculate first then set
this.setClickHandler2UP( this.prefetchedImgs[this.twoPage.currentIndexL],
{ self: this },
function(e) {
+ if (e.button == 2) {
+ // right click
+ return;
+ }
e.data.self.ttsStop();
e.data.self.left();
+
e.preventDefault();
}
);
this.setClickHandler2UP( this.prefetchedImgs[this.twoPage.currentIndexR],
{ self: this },
function(e) {
+ if (e.button == 2) {
+ // right click
+ return;
+ }
e.data.self.ttsStop();
e.data.self.right();
e.preventDefault();
if (loadImage) {
//console.log('prefetching ' + index);
var img = document.createElement("img");
- img.className = 'BRpageimage';
+ $(img).addClass('BRpageimage').addClass('BRnoselect');
if (index < 0 || index > (this.numLeafs - 1) ) {
// Facing page at beginning or end, or beyond
$(img).css({
- 'background-color': 'transparent'
+ 'background-color': '#efefef'
});
}
img.src = pageURI;
this.searchTerm = term;
this.removeSearchResults();
- this.showProgressPopup();
+ this.showProgressPopup('<img id="searchmarker" src="'+this.imagesBaseURL + 'marker_srch-on.png'+'"> Search results will appear below...');
this.ttsAjax = $.ajax({url:url, dataType:'jsonp', jsonpCallback:'BRSearchCallback'});
}
br.removeSearchResults();
br.searchResults = results;
//console.log(br.searchResults);
+
+ if (0 == results.matches.length) {
+ $(br.popup).text('No matches were found.');
+ setTimeout(function(){
+ $(br.popup).fadeOut('slow', function() {
+ br.removeProgressPopup();
+ })
+ },1000);
+ return;
+ }
+
var i;
for (i=0; i<results.matches.length; i++) {
br.addSearchResult(results.matches[i].text, br.leafNumToIndex(results.matches[i].par[0].page));
$('#BookReader').after(
'<div id="BRnav">'
+ '<div id="BRpage">' // Page turn buttons
+ + '<button class="BRicon onepg"></button>'
+ + '<button class="BRicon twopg"></button>'
+ + '<button class="BRicon thumb"></button>'
+ + '<button class="BRicon fit"></button>'
+ + '<button class="BRicon zoom_in"></button>'
+ + '<button class="BRicon zoom_out"></button>'
+ '<button class="BRicon book_left"></button>'
+ '<button class="BRicon book_right"></button>'
+ '</div>'
+ '<div class="BRnavend" id="BRnavright"></div>'
+ '</div>'
+ '</div>'
+ + '<div id="BRnavCntlBtm" class="BRnavCntl BRdn"></div>'
+ '</div>'
);
.append('<div id="pagenum"><span class="currentpage"></span></div>');
//.wrap('<div class="ui-handle-helper-parent"></div>').parent(); // XXXmang is this used for hiding the tooltip?
+ // $$$mang, why are these set both here and in bindNavigationHandlers?
$('.BRicon.book_left').bind('click', function() {
+ self.ttsStop();
self.left();
});
$('.BRicon.book_right').bind('click', function() {
+ self.ttsStop();
self.right();
});
var re = new RegExp('{{{(.+?)}}}', 'g');
queryString = queryString.replace(re, '<a href="#" onclick="br.jumpToIndex('+pageIndex+'); return false;">$1</a>')
- var marker = $('<div class="search" style="left:' + percentThrough + ';" title="' + uiStringSearch + '"><div class="query">'
+ var marker = $('<div class="search" style="top:'+(-$('#BRcontainer').height())+'px; left:' + percentThrough + ';" title="' + uiStringSearch + '"><div class="query">'
+ queryString + '<span>' + uiStringPage + ' ' + pageNumber + '</span></div>')
.data({'self': this, 'pageIndex': pageIndex })
.appendTo('#BRnavline').bt({
$(this).data('self').jumpToIndex($(this).data('pageIndex'));
});
- $(marker).css('top', -$('#BRcontainer').height()+'px').animate({top:'-25px'}, 'slow');
+ $(marker).animate({top:'-25px'}, 'slow');
}
closeWhenOthersOpen: true,
cssStyles: {
padding: '12px 14px',
- //backgroundColor: '#000',
- backgroundColor: '#444', // To set it off slightly from the chapter marker
+ backgroundColor: '#000',
border: '4px solid #e2dcc5',
//borderBottom: 'none',
fontFamily: '"Arial", sans-serif',
BookReader.prototype.initToolbar = function(mode, ui) {
// $$$mang should be contained within the BookReader div instead of body
- var readIcon = ''
+
+ var readIcon = '';
if (!navigator.userAgent.match(/mobile/i)) {
readIcon = "<button class='BRicon read modal'></button>";
}
-
+
$("body").append(
"<div id='BRtoolbar'>"
+ "<span id='BRtoolbarbuttons'>"
/* XXXmang integrate search */
+ "<form action='javascript:' id='booksearch'><input type='search' id='textSrch' name='textSrch' val='' placeholder='Search inside'/><button type='submit' id='btnSrch' name='btnSrch'>GO</button></form>"
// XXXmang icons incorrect or handlers wrong
+ + "<button class='BRicon play'></button>"
+ + "<button class='BRicon pause'></button>"
+ "<button class='BRicon info'></button>"
+ "<button class='BRicon share'></button>"
+ readIcon
- + "<button class='BRicon full'></button>"
+ //+ "<button class='BRicon full'></button>"
+ "</span>"
+ "<span><a class='logo' href='" + this.logoURL + "'></a></span>"
+ "<span id='BRreturn'><span>Back to</span><a href='" + this.bookUrl + "'>" + this.bookTitle + "</a></span>"
+ "</div>"
-
+ /*
+ "<div id='BRzoomer'>"
+ "<div id='BRzoompos'>"
+ "<button class='BRicon zoom_out'></button>"
+ "</div>"
+ "<button class='BRicon zoom_in'></button>"
+ "</div>"
- + "</div>");
+ + "</div>"
+ */
+ );
+
+ $('#BRtoolbar .pause').hide();
this.updateToolbarZoom(this.reduce); // Pretty format
// We build in mode 2
jToolbar.append();
-
- this.bindToolbarNavHandlers(jToolbar);
+
+ // Navigation handlers will be bound after all UI is in place -- makes moving icons between
+ // the toolbar and nav bar easier
// Setup tooltips -- later we could load these from a file for i18n
var titles = { '.logo': 'Go to Archive.org',
'.embed': 'Embed BookReader',
'.link': 'Link to this book (and page)',
'.bookmark': 'Bookmark this page',
- '.read': 'Allow BookReader to read this aloud',
+ '.read': 'Read this book aloud',
'.full': 'Show fullscreen',
'.book_left': 'Flip left',
'.book_right': 'Flip right',
}
}
-// bindToolbarNavHandlers
+// updateToolbarZoom(reduce)
+//______________________________________________________________________________
+// Update the displayed zoom factor based on reduction factor
+BookReader.prototype.updateToolbarZoom = function(reduce) {
+ var value;
+ var autofit = null;
+
+ // $$$ TODO preserve zoom/fit for each mode
+ if (this.mode == this.constMode2up) {
+ autofit = this.twoPage.autofit;
+ } else {
+ autofit = this.onePage.autofit;
+ }
+
+ if (autofit) {
+ value = autofit.slice(0,1).toUpperCase() + autofit.slice(1);
+ } else {
+ value = (100 / reduce).toFixed(2);
+ // Strip trailing zeroes and decimal if all zeroes
+ value = value.replace(/0+$/,'');
+ value = value.replace(/\.$/,'');
+ value += '%';
+ }
+ $('#BRzoom').text(value);
+}
+
+// bindNavigationHandlers
//______________________________________________________________________________
-// Binds the toolbar handlers
-BookReader.prototype.bindToolbarNavHandlers = function(jToolbar) {
+// Bind navigation handlers
+BookReader.prototype.bindNavigationHandlers = function() {
var self = this; // closure
+ jIcons = $('.BRicon');
- jToolbar.find('.book_left').click(function(e) {
+ jIcons.filter('.onepg').bind('click', function(e) {
+ self.switchMode(self.constMode1up);
+ });
+
+ jIcons.filter('.twopg').bind('click', function(e) {
+ self.switchMode(self.constMode2up);
+ });
+
+ jIcons.filter('.thumb').bind('click', function(e) {
+ self.switchMode(self.constModeThumb);
+ });
+
+ jIcons.filter('.fit').bind('fit', function(e) {
+ // XXXmang implement autofit zoom
+ });
+
+ jIcons.filter('.book_left').click(function(e) {
self.left();
return false;
});
- jToolbar.find('.book_right').click(function(e) {
+ jIcons.filter('.book_right').click(function(e) {
self.right();
return false;
});
- jToolbar.find('.book_up').bind('click', function(e) {
+ jIcons.filter('.book_up').bind('click', function(e) {
if ($.inArray(self.mode, [self.constMode1up, self.constModeThumb]) >= 0) {
self.scrollUp();
} else {
return false;
});
- jToolbar.find('.book_down').bind('click', function(e) {
+ jIcons.filter('.book_down').bind('click', function(e) {
if ($.inArray(self.mode, [self.constMode1up, self.constModeThumb]) >= 0) {
self.scrollDown();
} else {
return false;
});
- jToolbar.find('.print').click(function(e) {
+ jIcons.filter('.print').click(function(e) {
self.printPage();
return false;
});
- jToolbar.find('.embed').click(function(e) {
+ jIcons.filter('.embed').click(function(e) {
self.showEmbedCode();
return false;
});
- jToolbar.find('.bookmark').click(function(e) {
+ jIcons.filter('.bookmark').click(function(e) {
self.showBookmarkCode();
return false;
});
- jToolbar.find('.play').click(function(e) {
+ jIcons.filter('.play').click(function(e) {
self.autoToggle();
return false;
});
- jToolbar.find('.pause').click(function(e) {
+ jIcons.filter('.pause').click(function(e) {
self.autoToggle();
return false;
});
- jToolbar.find('.book_top').click(function(e) {
+ jIcons.filter('.book_top').click(function(e) {
self.first();
return false;
});
- jToolbar.find('.book_bottom').click(function(e) {
+ jIcons.filter('.book_bottom').click(function(e) {
self.last();
return false;
});
- jToolbar.find('.book_leftmost').click(function(e) {
+ jIcons.filter('.book_leftmost').click(function(e) {
self.leftmost();
return false;
});
- jToolbar.find('.book_rightmost').click(function(e) {
+ jIcons.filter('.book_rightmost').click(function(e) {
self.rightmost();
return false;
});
- jToolbar.find('.read').click(function(e) {
+ jIcons.filter('.read').click(function(e) {
self.ttsToggle();
return false;
});
- // $$$mang cleanup
- $('#BRzoomer .zoom_in').bind('click', function() {
+ jIcons.filter('.zoom_in').bind('click', function() {
+ self.ttsStop();
self.zoom(1);
return false;
});
- $('#BRzoomer .zoom_out').bind('click', function() {
+ jIcons.filter('.zoom_out').bind('click', function() {
+ self.ttsStop();
self.zoom(-1);
return false;
});
+ // XXX fix integration
$('#booksearch').bind('submit', function() {
self.search($('#textSrch').val());
});
-
-}
-
-// updateToolbarZoom(reduce)
-//______________________________________________________________________________
-// Update the displayed zoom factor based on reduction factor
-BookReader.prototype.updateToolbarZoom = function(reduce) {
- var value;
- var autofit = null;
-
- // $$$ TODO preserve zoom/fit for each mode
- if (this.mode == this.constMode2up) {
- autofit = this.twoPage.autofit;
- } else {
- autofit = this.onePage.autofit;
- }
-
- if (autofit) {
- value = autofit.slice(0,1).toUpperCase() + autofit.slice(1);
- } else {
- value = (100 / reduce).toFixed(2);
- // Strip trailing zeroes and decimal if all zeroes
- value = value.replace(/0+$/,'');
- value = value.replace(/\.$/,'');
- value += '%';
- }
- $('#BRzoom').text(value);
-}
-// bindNavigationHandlers
-//______________________________________________________________________________
-// Bind navigation handlers
-BookReader.prototype.bindNavigationHandlers = function() {
+ this.initSwipeData();
$('#BookReader').die('mousemove.navigation').live('mousemove.navigation',
{ 'br': this },
this.navigationMousemoveHandler
);
+
+ $('.BRpageimage').die('mousedown.swipe').live('mousedown.swipe',
+ { 'br': this },
+ this.swipeMousedownHandler
+ )
+ .die('mousemove.swipe').live('mousemove.swipe',
+ { 'br': this },
+ this.swipeMousemoveHandler
+ )
+ .die('mouseup.swipe').live('mouseup.swipe',
+ { 'br': this },
+ this.swipeMouseupHandler
+ );
+
+ this.bindMozTouchHandlers();
}
// unbindNavigationHandlers
}
}
+BookReader.prototype.initSwipeData = function(clientX, clientY) {
+ /*
+ * Based on the really quite awesome "Today's Guardian" at http://guardian.gyford.com/
+ */
+ this._swipe = {
+ mightBeSwiping: false,
+ startTime: (new Date).getTime(),
+ startX: clientX,
+ startY: clientY,
+ deltaX: 0,
+ deltaY: 0,
+ deltaT: 0
+ }
+}
+
+BookReader.prototype.swipeMousedownHandler = function(event) {
+ //console.log('swipe mousedown');
+ //console.log(event);
+
+ var self = event.data['br'];
+ self.initSwipeData(event.clientX, event.clientY);
+ self._swipe.mightBeSwiping = true;
+
+ // We should be the last bubble point for the page images
+ // Disable image drag and select, but keep right-click
+ if ($(event.originalTarget).hasClass('BRpageimage') && event.button != 2) {
+ event.preventDefault();
+ }
+}
+
+BookReader.prototype.swipeMousemoveHandler = function(event) {
+ //console.log('swipe move ' + event.clientX + ',' + event.clientY);
+
+ var _swipe = event.data['br']._swipe;
+ if (! _swipe.mightBeSwiping) {
+ return;
+ }
+
+ // Update swipe data
+ _swipe.deltaX = event.clientX - _swipe.startX;
+ _swipe.deltaY = event.clientY - _swipe.startY;
+ _swipe.deltaT = (new Date).getTime() - _swipe.startTime;
+
+ var absX = Math.abs(_swipe.deltaX);
+ var absY = Math.abs(_swipe.deltaY);
+
+ // Minimum distance in the amount of tim to trigger the swipe
+ var minSwipeLength = Math.max($('#BookReader').width() / 5, 100);
+ var maxSwipeTime = 1000;
+
+ // Check for horizontal swipe
+ if (absX > absY && (absX > minSwipeLength) && _swipe.deltaT < maxSwipeTime) {
+ //console.log('swipe! ' + _swipe.deltaX + ',' + _swipe.deltaY + ' ' + _swipe.deltaT + 'ms');
+
+ _swipe.mightBeSwiping = false; // only trigger once
+ if (event.data['br'].mode == event.data['br'].constMode2up) {
+ if (_swipe.deltaX < 0) {
+ event.data['br'].right();
+ } else {
+ event.data['br'].left();
+ }
+ }
+ }
+}
+BookReader.prototype.swipeMouseupHandler = function(event) {
+ //console.log('swipe mouseup');
+ //console.log(event);
+ event.data['br']._swipe.mightBeSwiping = false;
+}
+
+BookReader.prototype.bindMozTouchHandlers = function() {
+ var self = this;
+
+ // Currently only want touch handlers in 2up
+ $('#BookReader').bind('MozTouchDown', function(event) {
+ //console.log('MozTouchDown ' + event.streamId + ' ' + event.clientX + ',' + event.clientY);
+ if (this.mode == this.constMode2up) {
+ event.preventDefault();
+ }
+ })
+ .bind('MozTouchMove', function(event) {
+ //console.log('MozTouchMove - ' + event.streamId + ' ' + event.clientX + ',' + event.clientY)
+ if (this.mode == this.constMode2up) {
+ event.preventDefault();
+ }
+ })
+ .bind('MozTouchUp', function(event) {
+ //console.log('MozTouchUp - ' + event.streamId + ' ' + event.clientX + ',' + event.clientY);
+ if (this.mode = this.constMode2up) {
+ event.preventDefault();
+ }
+ });
+}
+
// navigationIsVisible
//______________________________________________________________________________
// Returns true if the navigation elements are currently visible
// $$$ don't hardcode height
$('#BRtoolbar').animate({top:-60});
$('#BRnav').animate({bottom:-60});
- $('#BRzoomer').animate({right:-26});
+ //$('#BRzoomer').animate({right:-26});
}
}
if (!this.navigationIsVisible()) {
$('#BRtoolbar').animate({top:0});
$('#BRnav').animate({bottom:0});
- $('#BRzoomer').animate({right:0});
+ //$('#BRzoomer').animate({right:0});
}
}
// Returns the page URI or transparent image if out of range
BookReader.prototype._getPageURI = function(index, reduce, rotate) {
if (index < 0 || index >= this.numLeafs) { // Synthesize page
- return this.imagesBaseURL + "/transparent.png";
+ return this.imagesBaseURL + "transparent.png";
}
if ('undefined' == typeof(reduce)) {
BookReader.prototype.ttsToggle = function () {
if (false == this.ttsPlaying) {
this.ttsPlaying = true;
- this.showProgressPopup();
+ this.showProgressPopup('Loading audio...');
if(soundManager.supported()) {
this.ttsStart();
} else {
return;
}
- this.showProgressPopup();
+ this.showProgressPopup('Loading audio...');
///// whileloading: broken on safari
///// onload fires on safari, but *after* the sound starts playing..
// showProgressPopup
//______________________________________________________________________________
-BookReader.prototype.showProgressPopup = function() {
+BookReader.prototype.showProgressPopup = function(msg) {
if (soundManager.debugMode) console.log('showProgressPopup index='+this.ttsIndex+' pos='+this.ttsPosition);
if (this.popup) return;
this.popup = document.createElement("div");
$(this.popup).css({
- top: $('#BRtoolbar').height() + 'px',
- left: $('#BookReader').width()-220 + 'px',
- width: '220px',
- height: '20px',
- }).attr('className', 'BRprogresspopup').appendTo('#BookReader');
+ top: ($('#BookReader').height()*0.5-100) + 'px',
+ left: ($('#BookReader').width()-300)*0.5 + 'px',
+ width: '300px',
+ border: '2px solid black'
+ }).attr('className', 'BRprogresspopup');
- htmlStr = ' ';
+ var bar = document.createElement("div");
+ $(bar).css({
+ height: '20px'
+ }).attr('className', 'BRprogressbar');
+ $(this.popup).append(bar);
- this.popup.innerHTML = htmlStr;
+ if (msg) {
+ var msgdiv = document.createElement("div");
+ msgdiv.innerHTML = msg;
+ $(this.popup).append(msgdiv);
+ }
+
+ $(this.popup).appendTo('#BookReader');
}
// removeProgressPopup
self.ttsNextChunk();
},500);
}
+//FADING, ETC.
+ function changeArrow(){
+ setTimeout(function(){
+ $('#BRnavCntlBtm').removeClass('BRdn').addClass('BRup');
+ },3000);
+ };
+ $().ready(function(){
+ $('#BRtoolbar').animate({top:0},3000).animate({top:-40});
+ $('#BRnav').animate({bottom:0},3000).animate({bottom:-53});
+ changeArrow();
+ $('.BRnavCntl').animate({opacity:1},3000).animate({height:'43px'}).animate({opacity:1},1000).animate({opacity:.25},1000);
+ $('.BRnavCntl').click(
+ function(){
+ if ($('#BRnavCntlBtm').hasClass('BRdn')) {
+ $('#BRtoolbar').animate({top:-40});
+ $('#BRnav').animate({bottom:-53});
+ $('#BRnavCntlBtm').addClass('BRup').removeClass('BRdn');
+ $('.BRnavCntl').animate({height:'43px'}).animate({opacity:1},1000).animate({opacity:.25},1000);
+ } else {
+ $('#BRtoolbar').animate({top:0});
+ $('#BRnav').animate({bottom:0});
+ $('#BRnavCntlBtm').addClass('BRdn').removeClass('BRup');
+ $('.BRnavCntl').animate({opacity:1,height:'30px'});
+ };
+ }
+ );
+ $('#BRnavCntlBtm').mouseover(function(){
+ if ($(this).hasClass('BRup')) {
+ $('.BRnavCntl').animate({opacity:1},250);
+ };
+ });
+ $('#BRnavCntlBtm').mouseleave(function(){
+ if ($(this).hasClass('BRup')) {
+ $('.BRnavCntl').animate({opacity:.25},250);
+ };
+ });
+ });
+