--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_gis/resources/js/TouchEvents.js Thu May 18 17:23:48 2017 +0200
@@ -0,0 +1,272 @@
+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;
+ }
+});