leaflet
Version:
JavaScript library for mobile-friendly interactive maps
157 lines (124 loc) • 4.11 kB
JavaScript
/*
* Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
*/
L.extend(L.DomEvent, {
//static
POINTER_DOWN: L.Browser.msPointer ? 'MSPointerDown' : 'pointerdown',
POINTER_MOVE: L.Browser.msPointer ? 'MSPointerMove' : 'pointermove',
POINTER_UP: L.Browser.msPointer ? 'MSPointerUp' : 'pointerup',
POINTER_CANCEL: L.Browser.msPointer ? 'MSPointerCancel' : 'pointercancel',
_pointers: [],
_pointerDocumentListener: false,
// Provides a touch events wrapper for (ms)pointer events.
// Based on changes by veproza https://github.com/CloudMade/Leaflet/pull/1019
//ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890
addPointerListener: function (obj, type, handler, id) {
switch (type) {
case 'touchstart':
return this.addPointerListenerStart(obj, type, handler, id);
case 'touchend':
return this.addPointerListenerEnd(obj, type, handler, id);
case 'touchmove':
return this.addPointerListenerMove(obj, type, handler, id);
default:
throw 'Unknown touch event type';
}
},
addPointerListenerStart: function (obj, type, handler, id) {
var pre = '_leaflet_',
pointers = this._pointers;
var cb = function (e) {
if (e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
L.DomEvent.preventDefault(e);
}
var alreadyInArray = false;
for (var i = 0; i < pointers.length; i++) {
if (pointers[i].pointerId === e.pointerId) {
alreadyInArray = true;
break;
}
}
if (!alreadyInArray) {
pointers.push(e);
}
e.touches = pointers.slice();
e.changedTouches = [e];
handler(e);
};
obj[pre + 'touchstart' + id] = cb;
obj.addEventListener(this.POINTER_DOWN, cb, false);
// need to also listen for end events to keep the _pointers list accurate
// this needs to be on the body and never go away
if (!this._pointerDocumentListener) {
var internalCb = function (e) {
for (var i = 0; i < pointers.length; i++) {
if (pointers[i].pointerId === e.pointerId) {
pointers.splice(i, 1);
break;
}
}
};
//We listen on the documentElement as any drags that end by moving the touch off the screen get fired there
document.documentElement.addEventListener(this.POINTER_UP, internalCb, false);
document.documentElement.addEventListener(this.POINTER_CANCEL, internalCb, false);
this._pointerDocumentListener = true;
}
return this;
},
addPointerListenerMove: function (obj, type, handler, id) {
var pre = '_leaflet_',
touches = this._pointers;
function cb(e) {
// don't fire touch moves when mouse isn't down
if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; }
for (var i = 0; i < touches.length; i++) {
if (touches[i].pointerId === e.pointerId) {
touches[i] = e;
break;
}
}
e.touches = touches.slice();
e.changedTouches = [e];
handler(e);
}
obj[pre + 'touchmove' + id] = cb;
obj.addEventListener(this.POINTER_MOVE, cb, false);
return this;
},
addPointerListenerEnd: function (obj, type, handler, id) {
var pre = '_leaflet_',
touches = this._pointers;
var cb = function (e) {
for (var i = 0; i < touches.length; i++) {
if (touches[i].pointerId === e.pointerId) {
touches.splice(i, 1);
break;
}
}
e.touches = touches.slice();
e.changedTouches = [e];
handler(e);
};
obj[pre + 'touchend' + id] = cb;
obj.addEventListener(this.POINTER_UP, cb, false);
obj.addEventListener(this.POINTER_CANCEL, cb, false);
return this;
},
removePointerListener: function (obj, type, id) {
var pre = '_leaflet_',
cb = obj[pre + type + id];
switch (type) {
case 'touchstart':
obj.removeEventListener(this.POINTER_DOWN, cb, false);
break;
case 'touchmove':
obj.removeEventListener(this.POINTER_MOVE, cb, false);
break;
case 'touchend':
obj.removeEventListener(this.POINTER_UP, cb, false);
obj.removeEventListener(this.POINTER_CANCEL, cb, false);
break;
}
return this;
}
});