fix Don't let the browser to zoom or select the map on feature selection, r=erilem (closes #3212)

git-svn-id: http://svn.openlayers.org/trunk/openlayers@11829 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
Stéphane Brunner
2011-03-31 09:45:50 +00:00
parent 0628c05fc3
commit c9d459c7fe
5 changed files with 156 additions and 25 deletions

View File

@@ -7,6 +7,10 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="stylesheet" href="style.mobile.css" type="text/css">
<script src="../lib/OpenLayers.js?mobile"></script>
<script src="http://192.168.1.49:8124/debug.js?ns=OpenLayers.Console"></script>
<script>
OpenLayers.Console.log("start");
</script>
<script src="mobile.js"></script>
<style>
html, body {

View File

@@ -1,34 +1,14 @@
// initialize map when page ready
var map;
// Get rid of address bar on iphone/ipod
var fixSize = function() {
window.scrollTo(0,0);
document.body.style.height = '100%';
if (!(/(iphone|ipod)/.test(navigator.userAgent.toLowerCase()))) {
if (document.body.parentNode) {
document.body.parentNode.style.height = '100%';
}
}
};
setTimeout(fixSize, 700);
setTimeout(fixSize, 1500);
var init = function () {
// create map
map = new OpenLayers.Map({
div: "map",
theme: null,
controls: [
new OpenLayers.Control.Attribution(),
new OpenLayers.Control.TouchNavigation({
dragPanOptions: {
interval: 100,
enableKinetic: true
}
}),
new OpenLayers.Control.ZoomPanel()
],
controls: [],
layers: [
new OpenLayers.Layer.OSM("OpenStreetMap", null, {
transitionEffect: 'resize'

View File

@@ -57,6 +57,13 @@ OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
*/
up: null,
/**
* Property: touch
* {Boolean} When a touchstart event is fired, touch will be true and all
* mouse related listeners will do nothing.
*/
touch: false,
/**
* Property: clickTolerance
* {Number} The number of pixels the mouse can move between mousedown
@@ -129,9 +136,33 @@ OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
* {Boolean} Let the event propagate.
*/
touchstart: function(evt) {
if(!this.touch) {
this.touch = true;
this.map.events.un({
mousedown: this.mousedown,
mouseup: this.mouseup,
mousemove: this.mousemove,
click: this.click,
dblclick: this.dblclick,
scope: this
});
}
return this.mousedown(evt);
},
/**
* Method: touchmove
* Handle touchmove events. We just prevent the browser default behavior,
* for Android Webkit not to select text when moving the finger after
* selecting a feature.
*
* Parameters:
* evt - {Event}
*/
touchmove: function(evt) {
OpenLayers.Event.stop(evt);
},
/**
* Method: mousedown
* Handle mouse down. Stop propagation if a feature is targeted by this
@@ -251,6 +282,11 @@ OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
this.lastFeature = null;
}
if(this.feature) {
if(evt.type === "touchstart") {
// stop the event to prevent Android Webkit from
// "flashing" the map div
OpenLayers.Event.stop(evt);
}
var inNew = (this.feature != this.lastFeature);
if(this.geometryTypeMatches(this.feature)) {
// in to a feature
@@ -349,6 +385,7 @@ OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
this.lastFeature = null;
this.down = null;
this.up = null;
this.touch = false;
this.map.events.un({
"removelayer": this.handleMapEvents,
"changelayer": this.handleMapEvents,

View File

@@ -59,6 +59,12 @@ OpenLayers.Handler.Path = OpenLayers.Class(OpenLayers.Handler.Point, {
*/
timerId: null,
/**
* Propery: stopTouchEnd
* {Boolean} Stop event propagation of the next touch up.
*/
stopTouchEnd: false,
/**
* Constructor: OpenLayers.Handler.Path
* Create a new path hander
@@ -244,6 +250,8 @@ OpenLayers.Handler.Path = OpenLayers.Class(OpenLayers.Handler.Point, {
// double-tap, finalize the geometry
this.lastTouchPx = evt.xy; // for up() to detect dblclick and do nothing
this.finishGeometry();
this.stopTouchEnd = true;
OpenLayers.Event.stop(evt);
window.clearTimeout(this.timerId);
this.timerId = null;
return false;
@@ -260,6 +268,27 @@ OpenLayers.Handler.Path = OpenLayers.Class(OpenLayers.Handler.Point, {
}
},
/**
* Method: touchend
* Handle touchend.
*
* Parameters:
* evt - {Event} The browser event
*
* Returns:
* {Boolean} Allow event propagation
*/
touchend: function(evt) {
evt.xy = this.lastTouchPx;
if (this.stopTouchEnd) {
// don't zoom on the page at feature end
OpenLayers.Event.stop(evt);
this.stopTouchEnd = false;
return false;
}
return this.up(evt);
},
/**
* Method: mousedown
* Handle mouse down. Add a new point to the geometry and
@@ -330,6 +359,8 @@ OpenLayers.Handler.Path = OpenLayers.Class(OpenLayers.Handler.Point, {
} else {
if (this.passesTolerance(this.lastDown, evt.xy, this.pixelTolerance)) {
if (this.touch) {
// don't allow the browser to zoom
OpenLayers.Event.stop(evt);
this.modifyFeature(evt.xy);
}
if(this.lastUp == null && this.persist) {
@@ -370,6 +401,9 @@ OpenLayers.Handler.Path = OpenLayers.Class(OpenLayers.Handler.Point, {
* {Boolean} Allow event propagation
*/
dblclick: function(evt) {
if (this.touch) {
return;
}
if(!this.freehandMode(evt)) {
this.finishGeometry();
}

View File

@@ -53,7 +53,7 @@
}
function test_events(t) {
t.plan(30);
t.plan(35);
var map = new OpenLayers.Map('map');
var control = new OpenLayers.Control();
@@ -64,8 +64,8 @@
// list below events that should be handled (events) and those
// that should not be handled (nonevents) by the handler
var events = ["mousedown", "mouseup", "mousemove", "click", "dblclick", "touchstart"];
var nonevents = ["mouseout", "resize", "focus", "blur"];
var events = ["mousedown", "mouseup", "mousemove", "click", "dblclick", "touchstart", "touchmove"];
var nonevents = ["mouseout", "resize", "focus", "blur", "touchend"];
map.events.registerPriority = function(type, obj, func) {
var output = func();
// Don't listen for setEvent handlers (#902)
@@ -255,6 +255,82 @@
map.events.triggerEvent('touchstart', evtPx);
}
function test_touchstart(t) {
// a test to verify that the touchstart function does
// unregister the mouse listeners when it's called the
// first time
t.plan(4);
// set up
var map = new OpenLayers.Map('map', {controls: []});
var control = new OpenLayers.Control();
map.addControl(control);
var layer = new OpenLayers.Layer();
map.addLayer(layer);
var handler = new OpenLayers.Handler.Feature(control, layer, {});
handler.mousedown = function() {}; // mock mousedown
handler.activate();
function allRegistered() {
var eventTypes = ['mousedown', 'mouseup', 'mousemove', 'click', 'dblclick'],
eventType,
listeners,
listener,
flag;
for(var i=0, ilen=eventTypes.length; i<ilen; i++) {
flag = false;
eventType = eventTypes[i];
listeners = map.events.listeners[eventType];
for(var j=0, jlen=listeners.length; j<jlen; j++) {
listener = listeners[j];
if(listener.func === handler[eventType] && listener.obj === handler) {
flag = true;
break;
}
}
if(!flag) {
return false;
}
}
return true;
}
function noneRegistered() {
var eventTypes = ['mousedown', 'mouseup', 'mousemove', 'click', 'dblclick'],
eventType,
listeners,
listener;
for(var i=0, ilen=eventTypes.length; i<ilen; i++) {
eventType = eventTypes[i];
listeners = map.events.listeners[eventType];
for(var j=0, jlen=listeners.length; j<jlen; j++) {
listener = listeners[j];
if(listener.func === handler[eventType] && listener.obj === handler) {
return false;
}
}
}
return true;
}
// test
t.ok(allRegistered(), 'mouse listeners are registered');
handler.touchstart({xy: new OpenLayers.Pixel(0, 0)});
t.ok(noneRegistered(), 'mouse listeners are unregistered');
t.ok(handler.touch, 'handler.touch is set');
handler.deactivate();
t.ok(!handler.touch, 'handler.touch is not set');
// tear down
map.destroy();
}
function test_deactivate(t) {
t.plan(3);
var map = new OpenLayers.Map('map');