filestash/public/assets/lib/vendor/leaflet/ext/TouchEvents.js
2024-08-28 02:05:24 +10:00

272 lines
7.2 KiB
JavaScript

L.Map.mergeOptions({
touchExtend: true
});
/**
* @class L.Map.TouchExtend
* @aka TouchExtend
*/
L.Map.TouchExtend = L.Handler.extend({
// @method initialize(): void
// Sets TouchExtend private accessor variables
initialize: function (map) {
this._map = map;
this._container = map._container;
this._pane = map._panes.overlayPane;
},
// @method addHooks(): void
// Adds dom listener events to the map container
addHooks: function () {
L.DomEvent.on(this._container, 'touchstart', this._onTouchStart, this);
L.DomEvent.on(this._container, 'touchend', this._onTouchEnd, this);
L.DomEvent.on(this._container, 'touchmove', this._onTouchMove, this);
if (this._detectIE()) {
L.DomEvent.on(this._container, 'MSPointerDown', this._onTouchStart, this);
L.DomEvent.on(this._container, 'MSPointerUp', this._onTouchEnd, this);
L.DomEvent.on(this._container, 'MSPointerMove', this._onTouchMove, this);
L.DomEvent.on(this._container, 'MSPointerCancel', this._onTouchCancel, this);
} else {
L.DomEvent.on(this._container, 'touchcancel', this._onTouchCancel, this);
L.DomEvent.on(this._container, 'touchleave', this._onTouchLeave, this);
}
},
// @method removeHooks(): void
// Removes dom listener events from the map container
removeHooks: function () {
L.DomEvent.off(this._container, 'touchstart', this._onTouchStart);
L.DomEvent.off(this._container, 'touchend', this._onTouchEnd);
L.DomEvent.off(this._container, 'touchmove', this._onTouchMove);
if (this._detectIE()) {
L.DomEvent.off(this._container, 'MSPointerDowm', this._onTouchStart);
L.DomEvent.off(this._container, 'MSPointerUp', this._onTouchEnd);
L.DomEvent.off(this._container, 'MSPointerMove', this._onTouchMove);
L.DomEvent.off(this._container, 'MSPointerCancel', this._onTouchCancel);
} else {
L.DomEvent.off(this._container, 'touchcancel', this._onTouchCancel);
L.DomEvent.off(this._container, 'touchleave', this._onTouchLeave);
}
},
_touchEvent: function (e, type) {
// #TODO: fix the pageX error that is do a bug in Android where a single touch triggers two click events
// _filterClick is what leaflet uses as a workaround.
// This is a problem with more things than just android. Another problem is touchEnd has no touches in
// its touch list.
var touchEvent = {};
if (typeof e.touches !== 'undefined') {
if (!e.touches.length) {
return;
}
touchEvent = e.touches[0];
} else if (e.pointerType === 'touch') {
touchEvent = e;
if (!this._filterClick(e)) {
return;
}
} else {
return;
}
var containerPoint = this._map.mouseEventToContainerPoint(touchEvent),
layerPoint = this._map.mouseEventToLayerPoint(touchEvent),
latlng = this._map.layerPointToLatLng(layerPoint);
this._map.fire(type, {
latlng: latlng,
layerPoint: layerPoint,
containerPoint: containerPoint,
pageX: touchEvent.pageX,
pageY: touchEvent.pageY,
originalEvent: e
});
},
/** Borrowed from Leaflet and modified for bool ops **/
_filterClick: function (e) {
var timeStamp = (e.timeStamp || e.originalEvent.timeStamp),
elapsed = L.DomEvent._lastClick && (timeStamp - L.DomEvent._lastClick);
// are they closer together than 500ms yet more than 100ms?
// Android typically triggers them ~300ms apart while multiple listeners
// on the same event should be triggered far faster;
// or check if click is simulated on the element, and if it is, reject any non-simulated events
if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) {
L.DomEvent.stop(e);
return false;
}
L.DomEvent._lastClick = timeStamp;
return true;
},
_onTouchStart: function (e) {
if (!this._map._loaded) {
return;
}
var type = 'touchstart';
this._touchEvent(e, type);
},
_onTouchEnd: function (e) {
if (!this._map._loaded) {
return;
}
var type = 'touchend';
this._touchEvent(e, type);
},
_onTouchCancel: function (e) {
if (!this._map._loaded) {
return;
}
var type = 'touchcancel';
if (this._detectIE()) {
type = 'pointercancel';
}
this._touchEvent(e, type);
},
_onTouchLeave: function (e) {
if (!this._map._loaded) {
return;
}
var type = 'touchleave';
this._touchEvent(e, type);
},
_onTouchMove: function (e) {
if (!this._map._loaded) {
return;
}
var type = 'touchmove';
this._touchEvent(e, type);
},
_detectIE: function () {
var ua = window.navigator.userAgent;
var msie = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older => return version number
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
}
var trident = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11 => return version number
var rv = ua.indexOf('rv:');
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
}
var edge = ua.indexOf('Edge/');
if (edge > 0) {
// IE 12 => return version number
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
}
// other browser
return false;
}
});
L.Map.addInitHook('addHandler', 'touchExtend', L.Map.TouchExtend);
/**
* @class L.Marker.Touch
* @aka Marker.Touch
*
* This isn't full Touch support. This is just to get markers to also support dom touch events after creation
* #TODO: find a better way of getting markers to support touch.
*/
L.Marker.Touch = L.Marker.extend({
_initInteraction: function () {
if (!this.addInteractiveTarget) {
// 0.7.x support
return this._initInteractionLegacy();
}
// TODO this may need be updated to re-add touch events for 1.0+
return L.Marker.prototype._initInteraction.apply(this);
},
// This is an exact copy of https://github.com/Leaflet/Leaflet/blob/v0.7/src/layer/marker/Marker.js
// with the addition of the touch events
_initInteractionLegacy: function () {
if (!this.options.clickable) {
return;
}
// TODO refactor into something shared with Map/Path/etc. to DRY it up
var icon = this._icon,
events = ['dblclick',
'mousedown',
'mouseover',
'mouseout',
'contextmenu',
'touchstart',
'touchend',
'touchmove'];
if (this._detectIE) {
events.concat(['MSPointerDown',
'MSPointerUp',
'MSPointerMove',
'MSPointerCancel']);
} else {
events.concat(['touchcancel']);
}
L.DomUtil.addClass(icon, 'leaflet-clickable');
L.DomEvent.on(icon, 'click', this._onMouseClick, this);
L.DomEvent.on(icon, 'keypress', this._onKeyPress, this);
for (var i = 0; i < events.length; i++) {
L.DomEvent.on(icon, events[i], this._fireMouseEvent, this);
}
if (L.Handler.MarkerDrag) {
this.dragging = new L.Handler.MarkerDrag(this);
if (this.options.draggable) {
this.dragging.enable();
}
}
},
_detectIE: function () {
var ua = window.navigator.userAgent;
var msie = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older => return version number
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
}
var trident = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11 => return version number
var rv = ua.indexOf('rv:');
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
}
var edge = ua.indexOf('Edge/');
if (edge > 0) {
// IE 12 => return version number
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
}
// other browser
return false;
}
});