123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- 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;
- }
- });
|