fix search on mobile safari
[bookreader.git] / BookReader / BookReader.js
index cf2ce2d..5d532a9 100644 (file)
@@ -1239,6 +1239,8 @@ BookReader.prototype.jumpToIndex = function(index, pageX, pageY) {
 
     this.willChangeToIndex(index);
 
+    this.ttsStop();
+
     if (this.constMode2up == this.mode) {
         this.autoStop();
         
@@ -1344,8 +1346,6 @@ BookReader.prototype.switchMode = function(mode) {
         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 {
@@ -2415,7 +2415,7 @@ BookReader.prototype.prefetchImg = function(index) {
         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;
@@ -2636,6 +2636,9 @@ BookReader.prototype.getPageWidth2UP = function(index) {
 //______________________________________________________________________________
 BookReader.prototype.search = function(term) {
     //console.log('search called with term=' + term);
+    
+    $('#textSrch').blur(); //cause mobile safari to hide the keyboard 
+    
     var url = 'http://'+this.server.replace(/:.+/, ''); //remove the port and userdir
     url    += '/~edward/inside_jsonp.php?item_id='+this.bookId;
     url    += '&doc='+this.subPrefix;   //TODO: test with subitem
@@ -2647,7 +2650,7 @@ BookReader.prototype.search = function(term) {
     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'});    
 }
 
@@ -2660,6 +2663,17 @@ function BRSearchCallback(results) {
     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));
@@ -3249,6 +3263,12 @@ BookReader.prototype.initNavbar = function() {
     $('#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>'
@@ -3260,6 +3280,7 @@ BookReader.prototype.initNavbar = function() {
         +             '<div class="BRnavend" id="BRnavright"></div>'
         +         '</div>'     
         +     '</div>'
+        +     '<div id="BRnavCntlBtm" class="BRnavCntl BRdn"></div>'
         + '</div>'
     );
     
@@ -3355,10 +3376,13 @@ BookReader.prototype.initNavbar = function() {
     .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();
     });
     
@@ -3407,7 +3431,7 @@ BookReader.prototype.addSearchResult = function(queryString, pageIndex) {
     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({
@@ -3454,7 +3478,7 @@ BookReader.prototype.addSearchResult = function(queryString, pageIndex) {
         $(this).data('self').jumpToIndex($(this).data('pageIndex'));
     });
     
-    $(marker).css('top', -$('#BRcontainer').height()+'px').animate({top:'-25px'}, 'slow');
+    $(marker).animate({top:'-25px'}, 'slow');
 
 }
 
@@ -3478,8 +3502,7 @@ BookReader.prototype.addChapter = function(chapterTitle, pageNumber, pageIndex)
         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',
@@ -3588,7 +3611,7 @@ BookReader.prototype.initToolbar = function(mode, ui) {
           "<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>"
+        +     "<form action='javascript:br.search($(\"#textSrch\").val());' 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 info'></button>"
         +     "<button class='BRicon share'></button>"
@@ -3598,7 +3621,7 @@ BookReader.prototype.initToolbar = function(mode, ui) {
         +   "<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>"
@@ -3608,7 +3631,9 @@ BookReader.prototype.initToolbar = function(mode, ui) {
         +     "</div>"
         +     "<button class='BRicon zoom_in'></button>"
         +   "</div>"
-        + "</div>");
+        + "</div>"
+        */
+        );
     
     this.updateToolbarZoom(this.reduce); // Pretty format
         
@@ -3621,8 +3646,9 @@ BookReader.prototype.initToolbar = function(mode, ui) {
     
     // 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',
@@ -3704,24 +3730,67 @@ BookReader.prototype.switchToolbarMode = function(mode) {
     }
 }
 
-// bindToolbarNavHandlers
+// updateToolbarZoom(reduce)
 //______________________________________________________________________________
-// Binds the toolbar handlers
-BookReader.prototype.bindToolbarNavHandlers = function(jToolbar) {
+// 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() {
 
     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 {
@@ -3730,7 +3799,7 @@ BookReader.prototype.bindToolbarNavHandlers = function(jToolbar) {
         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 {
@@ -3739,103 +3808,75 @@ BookReader.prototype.bindToolbarNavHandlers = function(jToolbar) {
         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;
     });
     
-    $('#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);
-}
+    // XXX fix integration
+    // XXX Mobile safari was not picking up this handler, so 
+    //     I explictly set the form action in initToolbar()
+    // $('#booksearch').bind('submit', function() {
+    //    self.search($('#textSrch').val());
+    // });
 
-// bindNavigationHandlers
-//______________________________________________________________________________
-// Bind navigation handlers
-BookReader.prototype.bindNavigationHandlers = function() {
     $('#BookReader').die('mousemove.navigation').live('mousemove.navigation',
         { 'br': this },
         this.navigationMousemoveHandler
@@ -3888,7 +3929,7 @@ BookReader.prototype.hideNavigation = function() {
         // $$$ don't hardcode height
         $('#BRtoolbar').animate({top:-60});
         $('#BRnav').animate({bottom:-60});
-        $('#BRzoomer').animate({right:-26});
+        //$('#BRzoomer').animate({right:-26});
     }
 }
 
@@ -3900,7 +3941,7 @@ BookReader.prototype.showNavigation = function() {
     if (!this.navigationIsVisible()) {
         $('#BRtoolbar').animate({top:0});
         $('#BRnav').animate({bottom:0});
-        $('#BRzoomer').animate({right:0});
+        //$('#BRzoomer').animate({right:0});
     }
 }
 
@@ -4304,7 +4345,7 @@ BookReader.prototype._getPageHeight= function(index) {
 // 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)) {
@@ -4401,7 +4442,7 @@ BookReader.util = {
 BookReader.prototype.ttsToggle = function () {
     if (false == this.ttsPlaying) {
         this.ttsPlaying = true;
-        this.showProgressPopup();    
+        this.showProgressPopup('Loading audio...');    
         if(soundManager.supported()) {
             this.ttsStart();            
         } else {               
@@ -4474,7 +4515,7 @@ BookReader.prototype.ttsStartCB = function (data) {
         return;
     }
     
-    this.showProgressPopup();
+    this.showProgressPopup('Loading audio...');
     
     ///// whileloading: broken on safari
     ///// onload fires on safari, but *after* the sound starts playing..
@@ -4494,21 +4535,30 @@ BookReader.prototype.ttsStartCB = function (data) {
 
 // showProgressPopup
 //______________________________________________________________________________
-BookReader.prototype.showProgressPopup = function() {
-    if (soundManager.debugMode) console.log('showProgressPopup index='+this.ttsIndex+' pos='+this.ttsPosition);
+BookReader.prototype.showProgressPopup = function(msg) {
     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 =  '&nbsp;';
+    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
@@ -4807,3 +4857,41 @@ BookReader.prototype.ttsStartPolling = function () {
         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);
+            };
+        });
+    });
+