From ae2f36963bd847f08453148747ba1fcfcd44b495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Junod?= Date: Thu, 31 Mar 2011 14:34:05 +0000 Subject: [PATCH] drag feature support on mobile. r=erilem (closes #3231) git-svn-id: http://svn.openlayers.org/trunk/openlayers@11845 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- lib/OpenLayers/Control/DragFeature.js | 39 +++++++++++++- tests/Control/DragFeature.html | 73 +++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/lib/OpenLayers/Control/DragFeature.js b/lib/OpenLayers/Control/DragFeature.js index e6c1fb36d0..5aea2f95e7 100644 --- a/lib/OpenLayers/Control/DragFeature.js +++ b/lib/OpenLayers/Control/DragFeature.js @@ -151,6 +151,10 @@ OpenLayers.Control.DragFeature = OpenLayers.Class(OpenLayers.Control, { ), feature: new OpenLayers.Handler.Feature( this, this.layer, OpenLayers.Util.extend({ + // 'click' and 'clickout' callback are for the mobile + // support: no 'over' or 'out' in touch based browsers. + click: this.clickFeature, + clickout: this.clickoutFeature, over: this.overFeature, out: this.outFeature }, this.featureCallbacks), @@ -158,7 +162,34 @@ OpenLayers.Control.DragFeature = OpenLayers.Class(OpenLayers.Control, { ) }; }, - + + /** + * Method: clickFeature + * Called when the feature handler detects a click-in on a feature. + * + * Parameters: + * feature - {} + */ + clickFeature: function(feature) { + if (this.overFeature(feature)) { + this.handlers.drag.dragstart(this.handlers.feature.evt); + // to let the events propagate to the feature handler (click callback) + this.handlers.drag.stopDown = false; + } + }, + + /** + * Method: clickoutFeature + * Called when the feature handler detects a click-out on a feature. + * + * Parameters: + * feature - {} + */ + clickoutFeature: function(feature) { + this.outFeature(feature); + this.handlers.drag.stopDown = true; + }, + /** * APIMethod: destroy * Take care of things that are not handled in superclass @@ -207,11 +238,16 @@ OpenLayers.Control.DragFeature = OpenLayers.Class(OpenLayers.Control, { * * Parameters: * feature - {} The selected feature. + * + * Returns: + * {Boolean} Successfully activated the drag handler. */ overFeature: function(feature) { + var activated = false; if(!this.handlers.drag.dragging) { this.feature = feature; this.handlers.drag.activate(); + activated = true; this.over = true; OpenLayers.Element.addClass(this.map.viewPortDiv, this.displayClass + "Over"); this.onEnter(feature); @@ -222,6 +258,7 @@ OpenLayers.Control.DragFeature = OpenLayers.Class(OpenLayers.Control, { this.over = false; } } + return activated; }, /** diff --git a/tests/Control/DragFeature.html b/tests/Control/DragFeature.html index b83ec88559..06f09b0db2 100644 --- a/tests/Control/DragFeature.html +++ b/tests/Control/DragFeature.html @@ -103,6 +103,41 @@ "onEnter called with expected feature"); } + function test_Control_DragFeature_over_touch(t) { + t.plan(7); + var log = []; + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer, { + onEnter: function(f) { log.push({feature: f}); } + }); + map.addControl(control); + + control.activate(); + t.ok(!control.handlers.drag.active, + "drag handler is not active before touch on a feature"); + + // simulate a touch on a feature + var feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + layer.getFeatureFromEvent = function(evt) { + return feature; + } + map.events.triggerEvent("touchstart", {type: "touchstart", touches: ['foo']}); + + t.eq(control.feature.id, feature.id, + "control gets the proper feature from the feature handler"); + t.ok(control.handlers.drag.active, + "drag handler activated when touch on a feature"); + t.ok(control.handlers.drag.started, "drag handler has started"); + t.ok(!control.handlers.drag.stopDown, "drag handler is not stopping down"); + t.eq(log.length, 1, + "onEnter called exactly once"); + t.eq(log[0].feature.id, feature.id, + "onEnter called with expected feature"); + } + function test_Control_DragFeature_down(t) { t.plan(3); var map = new OpenLayers.Map("map"); @@ -284,6 +319,44 @@ "onLeave called with expected feature"); } + function test_Control_DragFeature_out_touch(t) { + t.plan(5); + var log = []; + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer, { + onLeave: function(f) { log.push({feature: f}); } + }); + map.addControl(control); + + control.activate(); + + // simulate a touch on a feature + var feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + layer.getFeatureFromEvent = function() { + return feature; + }; + map.events.triggerEvent("touchstart", {type: "touchstart", touches: ['foo']}); + t.eq(control.feature.id, feature.id, + "feature is set on mouse over"); + + // simulate a touch outside the feature + layer.getFeatureFromEvent = function() { + return null; + }; + map.events.triggerEvent("touchstart", {type: "touchstart", touches: ['foo']}); + t.ok(control.feature == null, + "feature is set to null on mouse out"); + t.ok(control.handlers.drag.stopDown, + "drag handler is stopping down again"); + t.eq(log.length, 1, + "onLeave called exactly once"); + t.eq(log[0].feature.id, feature.id, + "onLeave called with expected feature"); + } +