[OpenLayers-Commits] r11201 - in trunk/openlayers: lib/OpenLayers/Handler tests/Handler

commits-20090109 at openlayers.org commits-20090109 at openlayers.org
Mon Feb 21 11:04:34 EST 2011


Author: erilem
Date: 2011-02-21 08:04:34 -0800 (Mon, 21 Feb 2011)
New Revision: 11201

Modified:
   trunk/openlayers/lib/OpenLayers/Handler/Click.js
   trunk/openlayers/tests/Handler/Click.html
Log:
make click handler work with touch events (closes #2996)

Modified: trunk/openlayers/lib/OpenLayers/Handler/Click.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Handler/Click.js	2011-02-21 16:02:19 UTC (rev 11200)
+++ trunk/openlayers/lib/OpenLayers/Handler/Click.js	2011-02-21 16:04:34 UTC (rev 11201)
@@ -22,7 +22,6 @@
  *  - <OpenLayers.Handler> 
  */
 OpenLayers.Handler.Click = OpenLayers.Class(OpenLayers.Handler, {
-
     /**
      * APIProperty: delay
      * {Number} Number of milliseconds between clicks before the event is
@@ -89,7 +88,14 @@
      * {<OpenLayers.Pixel>} The pixel location of the last mousedown.
      */
     down: null,
-    
+
+    /** 
+     * Property: last
+     * {<OpenLayers.Pixel>} The pixel for the last touchmove. This is
+     * used to 
+     */
+    last: null,
+
     /**
      * Property: rightclickTimerId
      * {Number} The id of the right mouse timeout waiting to clear the 
@@ -118,7 +124,7 @@
         // optionally register for mouseup and mousedown
         if(this.pixelTolerance != null) {
             this.mousedown = function(evt) {
-                this.down = evt.xy;
+                this.down = evt;
                 return true;
             };
         }
@@ -135,22 +141,35 @@
     mousedown: null,
 
     /**
+     * Method: touchstart
+     * Handle touchstart.
+     *
+     * Returns:
+     * {Boolean} Continue propagating this event.
+     */
+    touchstart: function(evt) {
+        this.down = evt;
+        this.last = null;
+        return true;
+    },
+
+    /**
      * Method: mouseup
      * Handle mouseup.  Installed to support collection of right mouse events.
      * 
      * Returns:
      * {Boolean} Continue propagating this event.
      */
-    mouseup:  function (evt) {
+    mouseup: function (evt) {
         var propagate = true;
 
         // Collect right mouse clicks from the mouseup
         //  IE - ignores the second right click in mousedown so using
         //  mouseup instead
-        if (this.checkModifiers(evt) && 
-            this.control.handleRightClicks && 
-            OpenLayers.Event.isRightClick(evt)) {
-          propagate = this.rightclick(evt);
+        if(this.checkModifiers(evt) &&
+           this.control.handleRightClicks &&
+           OpenLayers.Event.isRightClick(evt)) {
+            propagate = this.rightclick(evt);
         }
 
         return propagate;
@@ -216,7 +235,10 @@
      * {Boolean} Continue propagating this event.
      */
     dblclick: function(evt) {
-        if(this.passesTolerance(evt)) {
+        // for touch devices trigger dblclick only for
+        // "one finger" touch
+        if(this.passesTolerance(evt) &&
+           (!evt.lastTouches || evt.lastTouches.length == 1)) {
             if(this["double"]) {
                 this.callback('dblclick', [evt]);
             }
@@ -226,6 +248,30 @@
     },
     
     /**
+     * Method: touchmove
+     *    Store position of last move, because touchend event can have
+     *    an empty "touches" property.
+     */
+    touchmove: function(evt) {
+        this.last = evt;
+    },
+
+    /**
+     * Method: touchend
+     *   Correctly set event xy property, and add lastTouches to have
+     *   touches property from last touchstart or touchmove
+     */
+    touchend: function(evt) {
+        if(!evt) {
+            return false;
+        }
+        var last = this.last || this.down;
+        evt.xy = last.xy;
+        evt.lastTouches = last.touches;
+        return evt.xy ? this.click(evt) : false;
+    },
+
+    /**
      * Method: click
      * Handle click.
      *
@@ -236,7 +282,12 @@
         if(this.passesTolerance(evt)) {
             if(this.timerId != null) {
                 // already received a click
-                this.clearTimer();
+                if(evt.lastTouches) {
+                    // touch device - we may trigger dblclick
+                    this.dblclick(evt);
+                } else {
+                    this.clearTimer();
+                }
             } else {
                 // set the timer, send evt only if single is true
                 //use a clone of the event object because it will no longer 
@@ -246,7 +297,7 @@
                 this.timerId = window.setTimeout(
                     OpenLayers.Function.bind(this.delayedCall, this, clickEvent),
                     this.delay
-                );
+               );
             }
         }
         return !this.stopSingle;
@@ -265,10 +316,10 @@
      */
     passesTolerance: function(evt) {
         var passes = true;
-        if(this.pixelTolerance != null && this.down) {
+        if(this.pixelTolerance != null && this.down && this.down.xy) {
             var dpx = Math.sqrt(
-                Math.pow(this.down.x - evt.xy.x, 2) +
-                Math.pow(this.down.y - evt.xy.y, 2)
+                Math.pow(this.down.xy.x - evt.xy.x, 2) +
+                Math.pow(this.down.xy.y - evt.xy.y, 2)
             );
             if(dpx > this.pixelTolerance) {
                 passes = false;
@@ -316,6 +367,7 @@
         if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
             this.clearTimer();
             this.down = null;
+            this.last = null;
             deactivated = true;
         }
         return deactivated;

Modified: trunk/openlayers/tests/Handler/Click.html
===================================================================
--- trunk/openlayers/tests/Handler/Click.html	2011-02-21 16:02:19 UTC (rev 11200)
+++ trunk/openlayers/tests/Handler/Click.html	2011-02-21 16:04:34 UTC (rev 11201)
@@ -43,7 +43,7 @@
     }
     
     function test_Handler_Click_events(t) {
-        t.plan(50);
+        t.plan(80);
         
         var map = new OpenLayers.Map('map');
         var control = {
@@ -72,7 +72,7 @@
 
         // list below events that should be handled (events) and those
         // that should not be handled (nonevents) by the handler
-        var events = ["click", "dblclick", "mousedown", "mouseup", "rightclick"];
+        var events = ["click", "dblclick", "mousedown", "mouseup", "rightclick", "touchstart", "touchmove", "touchend"];
         var nonevents = ["mousemove", "resize", "focus", "blur"];
         var handler = new OpenLayers.Handler.Click(control);
         // set browser event like properties on the handler
@@ -82,7 +82,7 @@
         handler.activate();
 
         // different listeners registered for pixelTolerance option
-        var events = ["click", "dblclick", "mousedown", "mouseup", "rightclick"];
+        var events = ["click", "dblclick", "mousedown", "mouseup", "rightclick", "touchstart", "touchmove", "touchend"];
         var nonevents = ["mousemove", "resize", "focus", "blur"];
         var handler = new OpenLayers.Handler.Click(control, {}, {
             pixelTolerance: 2
@@ -290,7 +290,90 @@
         OpenLayers.Event.isRightClick = temp;
     }
 
+    function test_touch_click(t) {
+        t.plan(4);
 
+        // set up
+
+        var log;
+
+        var map = new OpenLayers.Map('map');
+        var control = {map: map};
+
+        var callbacks = {
+            'click': function(e) {
+                log = {x: e.xy.x, y: e.xy.y,
+                       lastTouches: e.lastTouches};
+            }
+        };
+
+        var handler = new OpenLayers.Handler.Click(
+                control, callbacks,
+                {'single': true, pixelTolerance: null});
+
+        // test
+
+        log = null;
+        handler.touchstart({xy: {x: 1, y: 1}, touches: ["foo"]});
+        handler.touchend({});
+
+        t.delay_call(1, function() {
+            t.ok(log != null, "click callback called");
+            if(log != null) {
+                t.eq(log.x, 1, "evt.xy.x as expected");
+                t.eq(log.y, 1, "evt.xy.y as expected");
+                t.eq(log.lastTouches, ["foo"], "evt.lastTouches as expected");
+            }
+            // tear down
+            map.destroy();
+        });
+    }
+
+    function test_touch_dblclick(t) {
+        t.plan(5);
+
+        // set up
+
+        var log;
+
+        var map = new OpenLayers.Map('map');
+        var control = {map: map};
+
+        var callbacks = {
+            'click': function(e) {
+                log.click = {x: e.xy.x, y: e.xy.y,
+                   lastTouches: e.lastTouches};
+            },
+            'dblclick': function(e) {
+                log.dblclick = {x: e.xy.x, y: e.xy.y,
+                   lastTouches: e.lastTouches};
+            }
+        };
+
+        var handler = new OpenLayers.Handler.Click(
+                control, callbacks,
+                {'double': true, pixelTolerance: null});
+
+        // test
+
+        log = {};
+        handler.touchstart({xy: {x: 1, y: 1}, touches: ["foo"]});
+        handler.touchend({});
+        handler.touchstart({xy: {x: 1, y: 1}, touches: ["foo"]});
+        handler.touchend({});
+
+        t.eq(log.click, undefined, "click callback not called");
+        t.ok(log.dblclick != undefined, "dblclick callback called");
+        if(log.dblclick != undefined) {
+            t.eq(log.dblclick.x, 1, "evt.xy.x as expected");
+            t.eq(log.dblclick.y, 1, "evt.xy.y as expected");
+            t.eq(log.dblclick.lastTouches, ["foo"], "evt.lastTouches as expected");
+        }
+
+        // tear down
+        map.destroy();
+    }
+
   </script>
 </head>
 <body>



More information about the Commits mailing list