make drag handler work with touch events, p=lotsofpeople, r=tschaub (closes #2995)

git-svn-id: http://svn.openlayers.org/trunk/openlayers@11189 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
Éric Lemoine
2011-02-21 15:07:55 +00:00
parent 7a1cb00fe4
commit 07160f5385
3 changed files with 201 additions and 86 deletions
+24 -3
View File
@@ -90,6 +90,20 @@ OpenLayers.Event = {
return event.target || event.srcElement; return event.target || event.srcElement;
}, },
/**
* Method: isSingleTouch
* Determine whether event was caused by a single touch
*
* Parameters:
* event - {Event}
*
* Returns:
* {Boolean}
*/
isSingleTouch: function(event) {
return event.touches && event.touches.length == 1;
},
/** /**
* Method: isLeftClick * Method: isLeftClick
* Determine whether event was caused by a left click. * Determine whether event was caused by a left click.
@@ -369,7 +383,8 @@ OpenLayers.Events = OpenLayers.Class({
"mouseover", "mouseout", "mouseover", "mouseout",
"mousedown", "mouseup", "mousemove", "mousedown", "mouseup", "mousemove",
"click", "dblclick", "rightclick", "dblrightclick", "click", "dblclick", "rightclick", "dblrightclick",
"resize", "focus", "blur" "resize", "focus", "blur",
"touchstart", "touchmove", "touchend"
], ],
/** /**
@@ -846,10 +861,16 @@ OpenLayers.Events = OpenLayers.Class({
if (!this.element.offsets) { if (!this.element.offsets) {
this.element.offsets = OpenLayers.Util.pagePosition(this.element); this.element.offsets = OpenLayers.Util.pagePosition(this.element);
} }
var clientX = evt.clientX;
var clientY = evt.clientY;
if (evt.touches && evt.touches.length > 0) {
clientX = evt.touches[0].clientX;
clientY = evt.touches[0].clientY;
}
return new OpenLayers.Pixel( return new OpenLayers.Pixel(
(evt.clientX + this.element.scrolls[0]) - this.element.offsets[0] (clientX + this.element.scrolls[0]) - this.element.offsets[0]
- this.element.lefttop[0], - this.element.lefttop[0],
(evt.clientY + this.element.scrolls[1]) - this.element.offsets[1] (clientY + this.element.scrolls[1]) - this.element.offsets[1]
- this.element.lefttop[1] - this.element.lefttop[1]
); );
}, },
+165 -72
View File
@@ -32,8 +32,8 @@ OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, {
/** /**
* Property: started * Property: started
* {Boolean} When a mousedown event is received, we want to record it, but * {Boolean} When a mousedown or touchstart event is received, we want to
* not set 'dragging' until the mouse moves after starting. * record it, but not set 'dragging' until the mouse moves after starting.
*/ */
started: false, started: false,
@@ -131,6 +131,119 @@ OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, {
} }
}, },
/**
* Method: dragstart
* This private method is factorized from mousedown and touchstart methods
*
* Parameters:
* evt - {Event} The event
*
* Returns:
* {Boolean} Let the event propagate.
*/
dragstart: function (evt) {
var propagate = true;
this.dragging = false;
if (this.checkModifiers(evt) &&
(OpenLayers.Event.isLeftClick(evt) ||
OpenLayers.Event.isSingleTouch(evt))) {
this.started = true;
this.start = evt.xy;
this.last = evt.xy;
OpenLayers.Element.addClass(
this.map.viewPortDiv, "olDragDown"
);
this.down(evt);
this.callback("down", [evt.xy]);
OpenLayers.Event.stop(evt);
if(!this.oldOnselectstart) {
this.oldOnselectstart = document.onselectstart ?
document.onselectstart : OpenLayers.Function.True;
}
document.onselectstart = OpenLayers.Function.False;
propagate = !this.stopDown;
} else {
this.started = false;
this.start = null;
this.last = null;
}
return propagate;
},
/**
* Method: dragmove
* This private method is factorized from mousemove and touchmove methods
*
* Parameters:
* evt - {Event} The event
*
* Returns:
* {Boolean} Let the event propagate.
*/
dragmove: function (evt) {
if (this.started && !this.timeoutId && (evt.xy.x != this.last.x ||
evt.xy.y != this.last.y)) {
if(this.documentDrag === true && this.documentEvents) {
if(evt.element === document) {
this.adjustXY(evt);
// do setEvent manually because the documentEvents are not
// registered with the map
this.setEvent(evt);
} else {
this.removeDocumentEvents();
}
}
if (this.interval > 0) {
this.timeoutId = setTimeout(
OpenLayers.Function.bind(this.removeTimeout, this),
this.interval);
}
this.dragging = true;
this.move(evt);
this.callback("move", [evt.xy]);
if(!this.oldOnselectstart) {
this.oldOnselectstart = document.onselectstart;
document.onselectstart = OpenLayers.Function.False;
}
this.last = this.evt.xy;
}
return true;
},
/**
* Method: dragend
* This private method is factorized from mouseup and touchend methods
*
* Parameters:
* evt - {Event} The event
*
* Returns:
* {Boolean} Let the event propagate.
*/
dragend: function (evt) {
if (this.started) {
if(this.documentDrag === true && this.documentEvents) {
this.adjustXY(evt);
this.removeDocumentEvents();
}
var dragged = (this.start != this.last);
this.started = false;
this.dragging = false;
OpenLayers.Element.removeClass(
this.map.viewPortDiv, "olDragDown"
);
this.up(evt);
this.callback("up", [evt.xy]);
if(dragged) {
this.callback("done", [evt.xy]);
}
document.onselectstart = this.oldOnselectstart;
}
return true;
},
/** /**
* The four methods below (down, move, up, and out) are used by subclasses * The four methods below (down, move, up, and out) are used by subclasses
* to do their own processing related to these mouse events. * to do their own processing related to these mouse events.
@@ -197,32 +310,22 @@ OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, {
* Returns: * Returns:
* {Boolean} Let the event propagate. * {Boolean} Let the event propagate.
*/ */
mousedown: function (evt) { mousedown: function(evt) {
var propagate = true; return this.dragstart(evt);
this.dragging = false; },
if (this.checkModifiers(evt) && OpenLayers.Event.isLeftClick(evt)) {
this.started = true;
this.start = evt.xy;
this.last = evt.xy;
OpenLayers.Element.addClass(
this.map.viewPortDiv, "olDragDown"
);
this.down(evt);
this.callback("down", [evt.xy]);
OpenLayers.Event.stop(evt);
if(!this.oldOnselectstart) { /**
this.oldOnselectstart = (document.onselectstart) ? document.onselectstart : OpenLayers.Function.True; * Method: touchstart
} * Handle touchstart events
document.onselectstart = OpenLayers.Function.False; *
* Parameters:
propagate = !this.stopDown; * evt - {Event}
} else { *
this.started = false; * Returns:
this.start = null; * {Boolean} Let the event propagate.
this.last = null; */
} touchstart: function(evt) {
return propagate; return this.dragstart(evt);
}, },
/** /**
@@ -235,31 +338,22 @@ OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, {
* Returns: * Returns:
* {Boolean} Let the event propagate. * {Boolean} Let the event propagate.
*/ */
mousemove: function (evt) { mousemove: function(evt) {
if (this.started && !this.timeoutId && (evt.xy.x != this.last.x || evt.xy.y != this.last.y)) { return this.dragmove(evt);
if(this.documentDrag === true && this.documentEvents) { },
if(evt.element === document) {
this.adjustXY(evt); /**
// do setEvent manually because the documentEvents are not * Method: touchmove
// registered with the map * Handle touchmove events
this.setEvent(evt); *
} else { * Parameters:
this.removeDocumentEvents(); * evt - {Event}
} *
} * Returns:
if (this.interval > 0) { * {Boolean} Let the event propagate.
this.timeoutId = setTimeout(OpenLayers.Function.bind(this.removeTimeout, this), this.interval); */
} touchmove: function(evt) {
this.dragging = true; return this.dragmove(evt);
this.move(evt);
this.callback("move", [evt.xy]);
if(!this.oldOnselectstart) {
this.oldOnselectstart = document.onselectstart;
document.onselectstart = OpenLayers.Function.False;
}
this.last = this.evt.xy;
}
return true;
}, },
/** /**
@@ -280,26 +374,25 @@ OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, {
* Returns: * Returns:
* {Boolean} Let the event propagate. * {Boolean} Let the event propagate.
*/ */
mouseup: function (evt) { mouseup: function(evt) {
if (this.started) { return this.dragend(evt);
if(this.documentDrag === true && this.documentEvents) { },
this.adjustXY(evt);
this.removeDocumentEvents(); /**
} * Method: touchend
var dragged = (this.start != this.last); * Handle touchend events
this.started = false; *
this.dragging = false; * Parameters:
OpenLayers.Element.removeClass( * evt - {Event}
this.map.viewPortDiv, "olDragDown" *
); * Returns:
this.up(evt); * {Boolean} Let the event propagate.
this.callback("up", [evt.xy]); */
if(dragged) { touchend: function(evt) {
this.callback("done", [evt.xy]); // override evt.xy with last position since touchend does not have
} // any touch position
document.onselectstart = this.oldOnselectstart; evt.xy = this.last;
} return this.dragend(evt);
return true;
}, },
/** /**
+3 -2
View File
@@ -45,7 +45,7 @@
} }
function test_Handler_Drag_events(t) { function test_Handler_Drag_events(t) {
t.plan(25); t.plan(40);
var map = new OpenLayers.Map('map'); var map = new OpenLayers.Map('map');
var control = new OpenLayers.Control(); var control = new OpenLayers.Control();
@@ -54,7 +54,8 @@
// list below events that should be handled (events) and those // list below events that should be handled (events) and those
// that should not be handled (nonevents) by the handler // that should not be handled (nonevents) by the handler
var events = ["mousedown", "mouseup", "mousemove", "mouseout", "click"]; var events = ["mousedown", "mouseup", "mousemove", "mouseout", "click",
"touchstart", "touchmove", "touchend"];
var nonevents = ["dblclick", "resize", "focus", "blur"]; var nonevents = ["dblclick", "resize", "focus", "blur"];
map.events.registerPriority = function(type, obj, func) { map.events.registerPriority = function(type, obj, func) {
var r = func(); var r = func();