Merge branch 'newui' of http://github.com/rajbot/bookreader into swipe
authorMichael Ang <mang@archive.org>
Tue, 19 Oct 2010 20:47:19 +0000 (20:47 +0000)
committerMichael Ang <mang@archive.org>
Tue, 19 Oct 2010 20:47:19 +0000 (20:47 +0000)
BookReader/BookReader.css
BookReader/BookReader.js
BookReader/jquery.ui.ipad.js

index 568c796..5a083ed 100644 (file)
@@ -103,6 +103,13 @@ a {
     background-color: rgb(234, 226, 205);
 }
 
+/* Disable selection on Firefox and WebKit */
+.BRnoselect {
+    -moz-user-select: none;
+    -webkit-user-select: none;
+    -webkit-user-drag: none;
+}
+
 .BRleafEdgeR {
     /*
     border-style: solid solid solid none;
index 36032e7..db4fe25 100644 (file)
@@ -370,7 +370,7 @@ BookReader.prototype.setClickHandler2UP = function( element, data, handler) {
     //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);
     });
 }
@@ -1473,7 +1473,7 @@ BookReader.prototype.prepareTwoPageView = function(centerPercentageX, centerPerc
     $('#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
@@ -2377,8 +2377,13 @@ BookReader.prototype.setMouseHandlers2UP = function() {
     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();
         }
     );
@@ -2386,6 +2391,10 @@ BookReader.prototype.setMouseHandlers2UP = function() {
     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();
@@ -2411,7 +2420,7 @@ BookReader.prototype.prefetchImg = function(index) {
     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({
@@ -3872,10 +3881,26 @@ BookReader.prototype.bindNavigationHandlers = function() {
         self.search($('#textSrch').val());
     });
 
+    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
@@ -3902,6 +3927,100 @@ BookReader.prototype.navigationMousemoveHandler = function(event) {
     }
 }
 
+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
index 6ee5160..c73a1bd 100644 (file)
 *
 * Project Home: 
 * http://code.google.com/p/jquery-ui-for-ipad-and-iphone/
-*/\r
-\r
-\r
-$(function() {\r
-       //\r
-       // Extend jQuery feature detection\r
-       //\r
-       $.extend($.support, {\r
-               touch: typeof Touch == "object"\r
-       });\r
-       \r
-       //\r
-       // Hook up touch events\r
-       //\r
-       if ($.support.touch) {\r
-               document.addEventListener("touchstart", iPadTouchHandler, false);\r
-               document.addEventListener("touchmove", iPadTouchHandler, false);\r
-               document.addEventListener("touchend", iPadTouchHandler, false);\r
-               document.addEventListener("touchcancel", iPadTouchHandler, false);\r
-       }\r
-});\r
-\r
-\r
-var lastTap = null;                    // Holds last tapped element (so we can compare for double tap)\r
-var tapValid = false;                  // Are we still in the .6 second window where a double tap can occur\r
-var tapTimeout = null;                 // The timeout reference\r
-\r
-function cancelTap() {\r
-       tapValid = false;\r
-}\r
-\r
-\r
-var rightClickPending = false; // Is a right click still feasible\r
-var rightClickEvent = null;            // the original event\r
-var holdTimeout = null;                        // timeout reference\r
-var cancelMouseUp = false;             // prevents a click from occuring as we want the context menu\r
-\r
-\r
-function cancelHold() {\r
-       if (rightClickPending) {\r
-               window.clearTimeout(holdTimeout);\r
-               rightClickPending = false;\r
-               rightClickEvent = null;\r
-       }\r
-}\r
-\r
-function startHold(event) {\r
-       if (rightClickPending)\r
-               return;\r
-\r
-       rightClickPending = true; // We could be performing a right click\r
-       rightClickEvent = (event.changedTouches)[0];\r
-       holdTimeout = window.setTimeout("doRightClick();", 800);\r
-}\r
-\r
-\r
-function doRightClick() {\r
-       rightClickPending = false;\r
-\r
-       //\r
-       // We need to mouse up (as we were down)\r
-       //\r
-       var first = rightClickEvent,\r
-               simulatedEvent = document.createEvent("MouseEvent");\r
-       simulatedEvent.initMouseEvent("mouseup", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,\r
-                       false, false, false, false, 0, null);\r
-       first.target.dispatchEvent(simulatedEvent);\r
-\r
-       //\r
-       // emulate a right click\r
-       //\r
-       simulatedEvent = document.createEvent("MouseEvent");\r
-       simulatedEvent.initMouseEvent("mousedown", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,\r
-                       false, false, false, false, 2, null);\r
-       first.target.dispatchEvent(simulatedEvent);\r
-\r
-       //\r
-       // Show a context menu\r
-       //\r
-       simulatedEvent = document.createEvent("MouseEvent");\r
-       simulatedEvent.initMouseEvent("contextmenu", true, true, window, 1, first.screenX + 50, first.screenY + 5, first.clientX + 50, first.clientY + 5,\r
-                                  false, false, false, false, 2, null);\r
-       first.target.dispatchEvent(simulatedEvent);\r
-\r
-\r
-       //\r
-       // Note:: I don't mouse up the right click here however feel free to add if required\r
-       //\r
-\r
-\r
-       cancelMouseUp = true;\r
-       rightClickEvent = null; // Release memory\r
-}\r
-\r
-\r
-//\r
-// mouse over event then mouse down\r
-//\r
-function iPadTouchStart(event) {\r
-       var touches = event.changedTouches,\r
-               first = touches[0],\r
-               type = "mouseover",\r
-               simulatedEvent = document.createEvent("MouseEvent");\r
-       //\r
-       // Mouse over first - I have live events attached on mouse over\r
-       //\r
-       simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,\r
-                            false, false, false, false, 0, null);\r
-       first.target.dispatchEvent(simulatedEvent);\r
-\r
-       type = "mousedown";\r
-       simulatedEvent = document.createEvent("MouseEvent");\r
-\r
-       simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,\r
-                            false, false, false, false, 0, null);\r
-       first.target.dispatchEvent(simulatedEvent);\r
-\r
-\r
-       if (!tapValid) {\r
-               lastTap = first.target;\r
-               tapValid = true;\r
-               tapTimeout = window.setTimeout("cancelTap();", 600);\r
-               startHold(event);\r
-       }\r
-       else {\r
-               window.clearTimeout(tapTimeout);\r
-\r
-               //\r
-               // If a double tap is still a possibility and the elements are the same\r
-               //      Then perform a double click\r
-               //\r
-               if (first.target == lastTap) {\r
-                       lastTap = null;\r
-                       tapValid = false;\r
-\r
-                       type = "click";\r
-                       simulatedEvent = document.createEvent("MouseEvent");\r
-\r
-                       simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,\r
-                               false, false, false, false, 0/*left*/, null);\r
-                       first.target.dispatchEvent(simulatedEvent);\r
-\r
-                       type = "dblclick";\r
-                       simulatedEvent = document.createEvent("MouseEvent");\r
-\r
-                       simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,\r
-                               false, false, false, false, 0/*left*/, null);\r
-                       first.target.dispatchEvent(simulatedEvent);\r
-               }\r
-               else {\r
-                       lastTap = first.target;\r
-                       tapValid = true;\r
-                       tapTimeout = window.setTimeout("cancelTap();", 600);\r
-                       startHold(event);\r
-               }\r
-       }\r
-}\r
-\r
-function iPadTouchHandler(event) {\r
-       var type = "",\r
-               button = 0; /*left*/\r
-\r
-       if (event.touches.length > 1)\r
-               return;\r
-\r
-       switch (event.type) {\r
-               case "touchstart":\r
-                       if ($(event.changedTouches[0].target).is("select")) {\r
-                               return;\r
-                       }\r
-                       iPadTouchStart(event); /*We need to trigger two events here to support one touch drag and drop*/\r
-                       event.preventDefault();\r
-                       return false;\r
-                       break;\r
-\r
-               case "touchmove":\r
-                       cancelHold();\r
-                       type = "mousemove";\r
-                       event.preventDefault();\r
-                       break;\r
-\r
-               case "touchend":\r
-                       if (cancelMouseUp) {\r
-                               cancelMouseUp = false;\r
-                               event.preventDefault();\r
-                               return false;\r
-                       }\r
-                       cancelHold();\r
-                       type = "mouseup";\r
-                       break;\r
-\r
-               default:\r
-                       return;\r
-       }\r
-\r
-       var touches = event.changedTouches,\r
-               first = touches[0],\r
-               simulatedEvent = document.createEvent("MouseEvent");\r
-\r
-       simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,\r
-                            false, false, false, false, button, null);\r
-\r
-       first.target.dispatchEvent(simulatedEvent);\r
-\r
-       if (type == "mouseup" && tapValid && first.target == lastTap) { // This actually emulates the ipads default behaviour (which we prevented)\r
-               simulatedEvent = document.createEvent("MouseEvent");            // This check avoids click being emulated on a double tap\r
-\r
-               simulatedEvent.initMouseEvent("click", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,\r
-                            false, false, false, false, button, null);\r
-\r
-               first.target.dispatchEvent(simulatedEvent);\r
-       }\r
-}\r
-\r
-\r
+*/
+
+
+
+
+
+$(function() {
+
+       //
+
+       // Extend jQuery feature detection
+
+       //
+
+       $.extend($.support, {
+
+               touch: typeof Touch == "object"
+
+       });
+
+       
+
+       //
+
+       // Hook up touch events
+
+       //
+
+       if ($.support.touch) {
+
+               document.addEventListener("touchstart", iPadTouchHandler, false);
+
+               document.addEventListener("touchmove", iPadTouchHandler, false);
+
+               document.addEventListener("touchend", iPadTouchHandler, false);
+
+               document.addEventListener("touchcancel", iPadTouchHandler, false);
+
+       }
+
+});
+
+
+
+
+
+var lastTap = null;                    // Holds last tapped element (so we can compare for double tap)
+
+var tapValid = false;                  // Are we still in the .6 second window where a double tap can occur
+
+var tapTimeout = null;                 // The timeout reference
+
+
+
+function cancelTap() {
+
+       tapValid = false;
+
+}
+
+
+
+
+
+var rightClickPending = false; // Is a right click still feasible
+
+var rightClickEvent = null;            // the original event
+
+var holdTimeout = null;                        // timeout reference
+
+var cancelMouseUp = false;             // prevents a click from occuring as we want the context menu
+
+
+
+
+
+function cancelHold() {
+
+       if (rightClickPending) {
+
+               window.clearTimeout(holdTimeout);
+
+               rightClickPending = false;
+
+               rightClickEvent = null;
+
+       }
+
+}
+
+
+
+function startHold(event) {
+
+       if (rightClickPending)
+
+               return;
+
+
+
+       rightClickPending = true; // We could be performing a right click
+
+       rightClickEvent = (event.changedTouches)[0];
+
+       holdTimeout = window.setTimeout("doRightClick();", 800);
+
+}
+
+
+
+
+
+function doRightClick() {
+
+       rightClickPending = false;
+
+
+
+       //
+
+       // We need to mouse up (as we were down)
+
+       //
+
+       var first = rightClickEvent,
+
+               simulatedEvent = document.createEvent("MouseEvent");
+
+       simulatedEvent.initMouseEvent("mouseup", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
+
+                       false, false, false, false, 0, null);
+
+       first.target.dispatchEvent(simulatedEvent);
+
+
+
+       //
+
+       // emulate a right click
+
+       //
+
+       simulatedEvent = document.createEvent("MouseEvent");
+
+       simulatedEvent.initMouseEvent("mousedown", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
+
+                       false, false, false, false, 2, null);
+
+       first.target.dispatchEvent(simulatedEvent);
+
+
+
+       //
+
+       // Show a context menu
+
+       //
+
+       simulatedEvent = document.createEvent("MouseEvent");
+
+       simulatedEvent.initMouseEvent("contextmenu", true, true, window, 1, first.screenX + 50, first.screenY + 5, first.clientX + 50, first.clientY + 5,
+
+                                  false, false, false, false, 2, null);
+
+       first.target.dispatchEvent(simulatedEvent);
+
+
+
+
+
+       //
+
+       // Note:: I don't mouse up the right click here however feel free to add if required
+
+       //
+
+
+
+
+
+       //cancelMouseUp = true; // XXXmang this was preventing swipe from working! make sure rest of code is okay with setting this false
+       cancelMouseUp = false;
+
+       rightClickEvent = null; // Release memory
+
+}
+
+
+
+
+
+//
+
+// mouse over event then mouse down
+
+//
+
+function iPadTouchStart(event) {
+
+       var touches = event.changedTouches,
+
+               first = touches[0],
+
+               type = "mouseover",
+
+               simulatedEvent = document.createEvent("MouseEvent");
+
+       //
+
+       // Mouse over first - I have live events attached on mouse over
+
+       //
+
+       simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
+
+                            false, false, false, false, 0, null);
+
+       first.target.dispatchEvent(simulatedEvent);
+
+
+
+       type = "mousedown";
+
+       simulatedEvent = document.createEvent("MouseEvent");
+
+
+
+       simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
+
+                            false, false, false, false, 0, null);
+
+       first.target.dispatchEvent(simulatedEvent);
+
+
+
+
+
+       if (!tapValid) {
+
+               lastTap = first.target;
+
+               tapValid = true;
+
+               tapTimeout = window.setTimeout("cancelTap();", 600);
+
+               startHold(event);
+
+       }
+
+       else {
+
+               window.clearTimeout(tapTimeout);
+
+
+
+               //
+
+               // If a double tap is still a possibility and the elements are the same
+
+               //      Then perform a double click
+
+               //
+
+               if (first.target == lastTap) {
+
+                       lastTap = null;
+
+                       tapValid = false;
+
+
+
+                       type = "click";
+
+                       simulatedEvent = document.createEvent("MouseEvent");
+
+
+
+                       simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
+
+                               false, false, false, false, 0/*left*/, null);
+
+                       first.target.dispatchEvent(simulatedEvent);
+
+
+
+                       type = "dblclick";
+
+                       simulatedEvent = document.createEvent("MouseEvent");
+
+
+
+                       simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
+
+                               false, false, false, false, 0/*left*/, null);
+
+                       first.target.dispatchEvent(simulatedEvent);
+
+               }
+
+               else {
+
+                       lastTap = first.target;
+
+                       tapValid = true;
+
+                       tapTimeout = window.setTimeout("cancelTap();", 600);
+
+                       startHold(event);
+
+               }
+
+       }
+
+}
+
+
+
+function iPadTouchHandler(event) {
+
+       var type = "",
+
+               button = 0; /*left*/
+
+
+
+       if (event.touches.length > 1)
+
+               return;
+
+
+
+       switch (event.type) {
+
+               case "touchstart":
+
+                       if ($(event.changedTouches[0].target).is("select")) {
+
+                               return;
+
+                       }
+
+                       iPadTouchStart(event); /*We need to trigger two events here to support one touch drag and drop*/
+
+                       event.preventDefault();
+
+                       return false;
+
+                       break;
+
+
+
+               case "touchmove":
+
+                       cancelHold();
+
+                       type = "mousemove";
+
+                       event.preventDefault();
+
+                       break;
+
+
+
+               case "touchend":
+
+                       if (cancelMouseUp) {
+
+                               cancelMouseUp = false;
+
+                               event.preventDefault();
+
+                               return false;
+
+                       }
+
+                       cancelHold();
+
+                       type = "mouseup";
+
+                       break;
+
+
+
+               default:
+
+                       return;
+
+       }
+
+
+
+       var touches = event.changedTouches,
+
+               first = touches[0],
+
+               simulatedEvent = document.createEvent("MouseEvent");
+
+
+
+       simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
+
+                            false, false, false, false, button, null);
+
+
+
+       first.target.dispatchEvent(simulatedEvent);
+
+
+
+       if (type == "mouseup" && tapValid && first.target == lastTap) { // This actually emulates the ipads default behaviour (which we prevented)
+
+               simulatedEvent = document.createEvent("MouseEvent");            // This check avoids click being emulated on a double tap
+
+
+
+               simulatedEvent.initMouseEvent("click", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
+
+                            false, false, false, false, button, null);
+
+
+
+               first.target.dispatchEvent(simulatedEvent);
+
+       }
+
+}
+
+
+
+
+