src/pyams_gis/resources/js/TouchEvents.js
changeset 0 c73bb834ccbe
equal deleted inserted replaced
-1:000000000000 0:c73bb834ccbe
       
     1 L.Map.mergeOptions({
       
     2 	touchExtend: true
       
     3 });
       
     4 
       
     5 /**
       
     6  * @class L.Map.TouchExtend
       
     7  * @aka TouchExtend
       
     8  */
       
     9 L.Map.TouchExtend = L.Handler.extend({
       
    10 
       
    11 	// @method initialize(): void
       
    12 	// Sets TouchExtend private accessor variables
       
    13 	initialize: function (map) {
       
    14 		this._map = map;
       
    15 		this._container = map._container;
       
    16 		this._pane = map._panes.overlayPane;
       
    17 	},
       
    18 
       
    19 	// @method addHooks(): void
       
    20 	// Adds dom listener events to the map container
       
    21 	addHooks: function () {
       
    22 		L.DomEvent.on(this._container, 'touchstart', this._onTouchStart, this);
       
    23 		L.DomEvent.on(this._container, 'touchend', this._onTouchEnd, this);
       
    24 		L.DomEvent.on(this._container, 'touchmove', this._onTouchMove, this);
       
    25 		if (this._detectIE()) {
       
    26 			L.DomEvent.on(this._container, 'MSPointerDown', this._onTouchStart, this);
       
    27 			L.DomEvent.on(this._container, 'MSPointerUp', this._onTouchEnd, this);
       
    28 			L.DomEvent.on(this._container, 'MSPointerMove', this._onTouchMove, this);
       
    29 			L.DomEvent.on(this._container, 'MSPointerCancel', this._onTouchCancel, this);
       
    30 
       
    31 		} else {
       
    32 			L.DomEvent.on(this._container, 'touchcancel', this._onTouchCancel, this);
       
    33 			L.DomEvent.on(this._container, 'touchleave', this._onTouchLeave, this);
       
    34 		}
       
    35 	},
       
    36 
       
    37 	// @method removeHooks(): void
       
    38 	// Removes dom listener events from the map container
       
    39 	removeHooks: function () {
       
    40 		L.DomEvent.off(this._container, 'touchstart', this._onTouchStart);
       
    41 		L.DomEvent.off(this._container, 'touchend', this._onTouchEnd);
       
    42 		L.DomEvent.off(this._container, 'touchmove', this._onTouchMove);
       
    43 		if (this._detectIE()) {
       
    44 			L.DomEvent.off(this._container, 'MSPointerDowm', this._onTouchStart);
       
    45 			L.DomEvent.off(this._container, 'MSPointerUp', this._onTouchEnd);
       
    46 			L.DomEvent.off(this._container, 'MSPointerMove', this._onTouchMove);
       
    47 			L.DomEvent.off(this._container, 'MSPointerCancel', this._onTouchCancel);
       
    48 		} else {
       
    49 			L.DomEvent.off(this._container, 'touchcancel', this._onTouchCancel);
       
    50 			L.DomEvent.off(this._container, 'touchleave', this._onTouchLeave);
       
    51 		}
       
    52 	},
       
    53 
       
    54 	_touchEvent: function (e, type) {
       
    55 		// #TODO: fix the pageX error that is do a bug in Android where a single touch triggers two click events
       
    56 		// _filterClick is what leaflet uses as a workaround.
       
    57 		// This is a problem with more things than just android. Another problem is touchEnd has no touches in
       
    58 		// its touch list.
       
    59 		var touchEvent = {};
       
    60 		if (typeof e.touches !== 'undefined') {
       
    61 			if (!e.touches.length) {
       
    62 				return;
       
    63 			}
       
    64 			touchEvent = e.touches[0];
       
    65 		} else if (e.pointerType === 'touch') {
       
    66 			touchEvent = e;
       
    67 			if (!this._filterClick(e)) {
       
    68 				return;
       
    69 			}
       
    70 		} else {
       
    71 			return;
       
    72 		}
       
    73 
       
    74 		var containerPoint = this._map.mouseEventToContainerPoint(touchEvent),
       
    75 			layerPoint = this._map.mouseEventToLayerPoint(touchEvent),
       
    76 			latlng = this._map.layerPointToLatLng(layerPoint);
       
    77 
       
    78 		this._map.fire(type, {
       
    79 			latlng: latlng,
       
    80 			layerPoint: layerPoint,
       
    81 			containerPoint: containerPoint,
       
    82 			pageX: touchEvent.pageX,
       
    83 			pageY: touchEvent.pageY,
       
    84 			originalEvent: e
       
    85 		});
       
    86 	},
       
    87 
       
    88 	/** Borrowed from Leaflet and modified for bool ops **/
       
    89 	_filterClick: function (e) {
       
    90 		var timeStamp = (e.timeStamp || e.originalEvent.timeStamp),
       
    91 			elapsed = L.DomEvent._lastClick && (timeStamp - L.DomEvent._lastClick);
       
    92 
       
    93 		// are they closer together than 500ms yet more than 100ms?
       
    94 		// Android typically triggers them ~300ms apart while multiple listeners
       
    95 		// on the same event should be triggered far faster;
       
    96 		// or check if click is simulated on the element, and if it is, reject any non-simulated events
       
    97 		if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) {
       
    98 			L.DomEvent.stop(e);
       
    99 			return false;
       
   100 		}
       
   101 		L.DomEvent._lastClick = timeStamp;
       
   102 		return true;
       
   103 	},
       
   104 
       
   105 	_onTouchStart: function (e) {
       
   106 		if (!this._map._loaded) {
       
   107 			return;
       
   108 		}
       
   109 
       
   110 		var type = 'touchstart';
       
   111 		this._touchEvent(e, type);
       
   112 
       
   113 	},
       
   114 
       
   115 	_onTouchEnd: function (e) {
       
   116 		if (!this._map._loaded) {
       
   117 			return;
       
   118 		}
       
   119 
       
   120 		var type = 'touchend';
       
   121 		this._touchEvent(e, type);
       
   122 	},
       
   123 
       
   124 	_onTouchCancel: function (e) {
       
   125 		if (!this._map._loaded) {
       
   126 			return;
       
   127 		}
       
   128 
       
   129 		var type = 'touchcancel';
       
   130 		if (this._detectIE()) {
       
   131 			type = 'pointercancel';
       
   132 		}
       
   133 		this._touchEvent(e, type);
       
   134 	},
       
   135 
       
   136 	_onTouchLeave: function (e) {
       
   137 		if (!this._map._loaded) {
       
   138 			return;
       
   139 		}
       
   140 
       
   141 		var type = 'touchleave';
       
   142 		this._touchEvent(e, type);
       
   143 	},
       
   144 
       
   145 	_onTouchMove: function (e) {
       
   146 		if (!this._map._loaded) {
       
   147 			return;
       
   148 		}
       
   149 
       
   150 		var type = 'touchmove';
       
   151 		this._touchEvent(e, type);
       
   152 	},
       
   153 
       
   154 	_detectIE: function () {
       
   155 		var ua = window.navigator.userAgent;
       
   156 
       
   157 		var msie = ua.indexOf('MSIE ');
       
   158 		if (msie > 0) {
       
   159 			// IE 10 or older => return version number
       
   160 			return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
       
   161 		}
       
   162 
       
   163 		var trident = ua.indexOf('Trident/');
       
   164 		if (trident > 0) {
       
   165 			// IE 11 => return version number
       
   166 			var rv = ua.indexOf('rv:');
       
   167 			return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
       
   168 		}
       
   169 
       
   170 		var edge = ua.indexOf('Edge/');
       
   171 		if (edge > 0) {
       
   172 			// IE 12 => return version number
       
   173 			return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
       
   174 		}
       
   175 
       
   176 		// other browser
       
   177 		return false;
       
   178 	}
       
   179 });
       
   180 
       
   181 L.Map.addInitHook('addHandler', 'touchExtend', L.Map.TouchExtend);
       
   182 
       
   183 
       
   184 /**
       
   185  * @class L.Marker.Touch
       
   186  * @aka Marker.Touch
       
   187  *
       
   188  * This isn't full Touch support. This is just to get markers to also support dom touch events after creation
       
   189  * #TODO: find a better way of getting markers to support touch.
       
   190  */
       
   191 L.Marker.Touch = L.Marker.extend({
       
   192 
       
   193 	_initInteraction: function () {
       
   194 		if (!this.addInteractiveTarget) {
       
   195 			// 0.7.x support
       
   196 			return this._initInteractionLegacy();
       
   197 		}
       
   198 		// TODO this may need be updated to re-add touch events for 1.0+
       
   199 		return L.Marker.prototype._initInteraction.apply(this);
       
   200 	},
       
   201 
       
   202 	// This is an exact copy of https://github.com/Leaflet/Leaflet/blob/v0.7/src/layer/marker/Marker.js
       
   203 	// with the addition of the touch events
       
   204 	_initInteractionLegacy: function () {
       
   205 
       
   206 		if (!this.options.clickable) {
       
   207 			return;
       
   208 		}
       
   209 
       
   210 		// TODO refactor into something shared with Map/Path/etc. to DRY it up
       
   211 
       
   212 		var icon = this._icon,
       
   213 			events = ['dblclick',
       
   214 					  'mousedown',
       
   215 					  'mouseover',
       
   216 					  'mouseout',
       
   217 					  'contextmenu',
       
   218 					  'touchstart',
       
   219 					  'touchend',
       
   220 					  'touchmove'];
       
   221 		if (this._detectIE) {
       
   222 			events.concat(['MSPointerDown',
       
   223 						   'MSPointerUp',
       
   224 						   'MSPointerMove',
       
   225 						   'MSPointerCancel']);
       
   226 		} else {
       
   227 			events.concat(['touchcancel']);
       
   228 		}
       
   229 
       
   230 		L.DomUtil.addClass(icon, 'leaflet-clickable');
       
   231 		L.DomEvent.on(icon, 'click', this._onMouseClick, this);
       
   232 		L.DomEvent.on(icon, 'keypress', this._onKeyPress, this);
       
   233 
       
   234 		for (var i = 0; i < events.length; i++) {
       
   235 			L.DomEvent.on(icon, events[i], this._fireMouseEvent, this);
       
   236 		}
       
   237 
       
   238 		if (L.Handler.MarkerDrag) {
       
   239 			this.dragging = new L.Handler.MarkerDrag(this);
       
   240 
       
   241 			if (this.options.draggable) {
       
   242 				this.dragging.enable();
       
   243 			}
       
   244 		}
       
   245 	},
       
   246 
       
   247 	_detectIE: function () {
       
   248 		var ua = window.navigator.userAgent;
       
   249 
       
   250 		var msie = ua.indexOf('MSIE ');
       
   251 		if (msie > 0) {
       
   252 			// IE 10 or older => return version number
       
   253 			return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
       
   254 		}
       
   255 
       
   256 		var trident = ua.indexOf('Trident/');
       
   257 		if (trident > 0) {
       
   258 			// IE 11 => return version number
       
   259 			var rv = ua.indexOf('rv:');
       
   260 			return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
       
   261 		}
       
   262 
       
   263 		var edge = ua.indexOf('Edge/');
       
   264 		if (edge > 0) {
       
   265 			// IE 12 => return version number
       
   266 			return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
       
   267 		}
       
   268 
       
   269 		// other browser
       
   270 		return false;
       
   271 	}
       
   272 });