diff --git a/examples/mobile-wmts-vienna.css b/examples/mobile-wmts-vienna.css index 82af86790b..605932a424 100644 --- a/examples/mobile-wmts-vienna.css +++ b/examples/mobile-wmts-vienna.css @@ -12,6 +12,9 @@ html, body, #map { #title, #tags, #shortdesc { display: none; } +div.olMapViewport { + -ms-touch-action: none; +} /* Turn on GPU support where available */ .olTileImage { diff --git a/lib/OpenLayers/Events.js b/lib/OpenLayers/Events.js index 8699601cef..dd9875a7c8 100644 --- a/lib/OpenLayers/Events.js +++ b/lib/OpenLayers/Events.js @@ -566,6 +566,7 @@ OpenLayers.Events = OpenLayers.Class({ this.listeners = {}; this.extensions = {}; this.extensionCount = {}; + this._msTouches = []; // if a dom element is specified, add a listeners list // for browser events on the element and register them @@ -632,11 +633,16 @@ OpenLayers.Events = OpenLayers.Class({ ); } this.element = element; + var msTouch = !!window.navigator.msMaxTouchPoints; + var type; for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) { + type = this.BROWSER_EVENTS[i]; // register the event cross-browser - OpenLayers.Event.observe( - element, this.BROWSER_EVENTS[i], this.eventHandler + OpenLayers.Event.observe(element, type, this.eventHandler ); + if (msTouch && type.indexOf('touch') === 0) { + this.addMsTouchListener(element, type, this.eventHandler); + } } // disable dragstart in IE so that mousedown/move/up works normally OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop); @@ -1014,5 +1020,154 @@ OpenLayers.Events = OpenLayers.Class({ ); }, + /** + * Method: addMsTouchListener + * + * Parameters: + * element - {DOMElement} The DOM element to register the listener on + * type - {String} The event type + * handler - {Function} the handler + */ + addMsTouchListener: function (element, type, handler) { + var eventHandler = this.eventHandler; + var touches = this._msTouches; + + function msHandler(evt) { + handler(OpenLayers.Util.applyDefaults({ + stopPropagation: function() { + for (var i=touches.length-1; i>=0; --i) { + touches[i].stopPropagation(); + } + }, + preventDefault: function() { + for (var i=touches.length-1; i>=0; --i) { + touches[i].preventDefault(); + } + }, + type: type + }, evt)); + } + + switch (type) { + case 'touchstart': + return this.addMsTouchListenerStart(element, type, msHandler); + case 'touchend': + return this.addMsTouchListenerEnd(element, type, msHandler); + case 'touchmove': + return this.addMsTouchListenerMove(element, type, msHandler); + default: + throw 'Unknown touch event type'; + } + }, + + /** + * Method: addMsTouchListenerStart + * + * Parameters: + * element - {DOMElement} The DOM element to register the listener on + * type - {String} The event type + * handler - {Function} the handler + */ + addMsTouchListenerStart: function(element, type, handler) { + var touches = this._msTouches; + + var cb = function(e) { + + var alreadyInArray = false; + for (var i = 0; i < touches.length; i++) { + if (touches[i].pointerId == e.pointerId) { + alreadyInArray = true; + break; + } + } + if (!alreadyInArray) { + touches.push(e); + } + + e.touches = touches.slice(); + e.changedTouches = [e]; + + handler(e); + }; + + OpenLayers.Event.observe(element, 'MSPointerDown', cb); + + // Need to also listen for end events to keep the _msTouches list + // accurate + var internalCb = function(e) { + for (var i = 0; i < touches.length; i++) { + if (touches[i].pointerId == e.pointerId) { + touches.splice(i, 1); + break; + } + } + }; + OpenLayers.Event.observe(element, 'MSPointerUp', internalCb); + }, + + /** + * Method: addMsTouchListenerMove + * + * Parameters: + * element - {DOMElement} The DOM element to register the listener on + * type - {String} The event type + * handler - {Function} the handler + */ + addMsTouchListenerMove: function (element, type, handler) { + var touches = this._msTouches; + var cb = function(e) { + + //Don't fire touch moves when mouse isn't down + if (e.pointerType == e.MSPOINTER_TYPE_MOUSE && e.buttons == 0) { + return; + } + + for (var i = 0; i < touches.length; i++) { + if (touches[i].pointerId == e.pointerId) { + touches[i] = e; + break; + } + } + + e.touches = touches.slice(); + e.changedTouches = [e]; + e.type = type; + + handler(e); + }; + + OpenLayers.Event.observe(element, 'MSPointerMove', cb); + }, + + /** + * Method: addMsTouchListenerEnd + * + * Parameters: + * element - {DOMElement} The DOM element to register the listener on + * type - {String} The event type + * handler - {Function} the handler + */ + addMsTouchListenerEnd: function (element, type, handler) { + var touches = this._msTouches; + + var cb = function(e) { + + for (var i = 0; i < touches.length; i++) { + if (touches[i].pointerId == e.pointerId) { + touches.splice(i, 1); + break; + } + } + + e.touches = touches.slice(); + e.changedTouches = [e]; + e.type = type; + + handler(e); + }; + + OpenLayers.Event.observe(element, 'MSPointerUp', cb); + }, + CLASS_NAME: "OpenLayers.Events" }); diff --git a/theme/default/style.css b/theme/default/style.css index 398df4bff9..c523a46295 100644 --- a/theme/default/style.css +++ b/theme/default/style.css @@ -7,6 +7,7 @@ div.olMap { div.olMapViewport { text-align: left; + -ms-touch-action: none; } div.olLayerDiv { diff --git a/theme/default/style.mobile.css b/theme/default/style.mobile.css index fadff9e416..92e7d00d4c 100644 --- a/theme/default/style.mobile.css +++ b/theme/default/style.mobile.css @@ -43,6 +43,9 @@ div.olControlZoom a:hover { background: rgba(0, 60, 136, 0.5); } } +div.olMapViewport { + -ms-touch-action: none; +} .olLayerGrid .olTileImage { -webkit-transition: opacity 0.2s linear; -moz-transition: opacity 0.2s linear;