leaflet
Version:
JavaScript library for mobile-friendly interactive maps
132 lines (101 loc) • 4.07 kB
JavaScript
/*
* Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
*/
L.extend(L.DomEvent, {
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',
TAG_WHITE_LIST: ['INPUT', 'SELECT', 'OPTION'],
_pointers: {},
_pointersCount: 0,
// Provides a touch events wrapper for (ms)pointer events.
// ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890
addPointerListener: function (obj, type, handler, id) {
if (type === 'touchstart') {
this._addPointerStart(obj, handler, id);
} else if (type === 'touchmove') {
this._addPointerMove(obj, handler, id);
} else if (type === 'touchend') {
this._addPointerEnd(obj, handler, id);
}
return this;
},
removePointerListener: function (obj, type, id) {
var handler = obj['_leaflet_' + type + id];
if (type === 'touchstart') {
obj.removeEventListener(this.POINTER_DOWN, handler, false);
} else if (type === 'touchmove') {
obj.removeEventListener(this.POINTER_MOVE, handler, false);
} else if (type === 'touchend') {
obj.removeEventListener(this.POINTER_UP, handler, false);
obj.removeEventListener(this.POINTER_CANCEL, handler, false);
}
return this;
},
_addPointerStart: function (obj, handler, id) {
var onDown = L.bind(function (e) {
if (e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
// In IE11, some touch events needs to fire for form controls, or
// the controls will stop working. We keep a whitelist of tag names that
// need these events. For other target tags, we prevent default on the event.
if (this.TAG_WHITE_LIST.indexOf(e.target.tagName) < 0) {
L.DomEvent.preventDefault(e);
} else {
return;
}
}
this._handlePointer(e, handler);
}, this);
obj['_leaflet_touchstart' + id] = onDown;
obj.addEventListener(this.POINTER_DOWN, onDown, false);
// need to keep track of what pointers and how many are active to provide e.touches emulation
if (!this._pointerDocListener) {
var pointerUp = L.bind(this._globalPointerUp, this);
// we listen documentElement as any drags that end by moving the touch off the screen get fired there
document.documentElement.addEventListener(this.POINTER_DOWN, L.bind(this._globalPointerDown, this), true);
document.documentElement.addEventListener(this.POINTER_MOVE, L.bind(this._globalPointerMove, this), true);
document.documentElement.addEventListener(this.POINTER_UP, pointerUp, true);
document.documentElement.addEventListener(this.POINTER_CANCEL, pointerUp, true);
this._pointerDocListener = true;
}
},
_globalPointerDown: function (e) {
this._pointers[e.pointerId] = e;
this._pointersCount++;
},
_globalPointerMove: function (e) {
if (this._pointers[e.pointerId]) {
this._pointers[e.pointerId] = e;
}
},
_globalPointerUp: function (e) {
delete this._pointers[e.pointerId];
this._pointersCount--;
},
_handlePointer: function (e, handler) {
e.touches = [];
for (var i in this._pointers) {
e.touches.push(this._pointers[i]);
}
e.changedTouches = [e];
handler(e);
},
_addPointerMove: function (obj, handler, id) {
var onMove = L.bind(function (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; }
this._handlePointer(e, handler);
}, this);
obj['_leaflet_touchmove' + id] = onMove;
obj.addEventListener(this.POINTER_MOVE, onMove, false);
},
_addPointerEnd: function (obj, handler, id) {
var onUp = L.bind(function (e) {
this._handlePointer(e, handler);
}, this);
obj['_leaflet_touchend' + id] = onUp;
obj.addEventListener(this.POINTER_UP, onUp, false);
obj.addEventListener(this.POINTER_CANCEL, onUp, false);
}
});