diff --git a/src/ol/interaction/dblclickzoom.js b/src/ol/interaction/dblclickzoom.js index 587f776265..f01587843c 100644 --- a/src/ol/interaction/dblclickzoom.js +++ b/src/ol/interaction/dblclickzoom.js @@ -1,7 +1,7 @@ goog.provide('ol.interaction.DblClickZoom'); -goog.require('goog.events.EventType'); goog.require('ol.MapBrowserEvent'); +goog.require('ol.MapBrowserEvent.EventType'); goog.require('ol.interaction.Constraints'); goog.require('ol.interaction.Interaction'); @@ -24,8 +24,8 @@ goog.inherits(ol.interaction.DblClickZoom, ol.interaction.Interaction); ol.interaction.DblClickZoom.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { var browserEvent = mapBrowserEvent.browserEvent; - if (browserEvent.type == goog.events.EventType.DBLCLICK && - browserEvent.isMouseActionButton()) { + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DBLCLICK && + mapBrowserEvent.isMouseActionButton()) { var map = mapBrowserEvent.map; var resolution = map.getResolution(); var delta = mapBrowserEvent.browserEvent.shiftKey ? -1 : 1; diff --git a/src/ol/interaction/drag.js b/src/ol/interaction/drag.js index 2009e93364..fbe57dfd54 100644 --- a/src/ol/interaction/drag.js +++ b/src/ol/interaction/drag.js @@ -93,19 +93,19 @@ ol.interaction.Drag.prototype.handleMapBrowserEvent = } var browserEvent = mapBrowserEvent.browserEvent; if (this.dragging_) { - if (mapBrowserEvent.type == goog.fx.Dragger.EventType.DRAG) { + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAG) { goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); this.deltaX = browserEvent.clientX - this.startX; this.deltaY = browserEvent.clientY - this.startY; this.handleDrag(mapBrowserEvent); - } else if (mapBrowserEvent.type == goog.fx.Dragger.EventType.END) { + } else if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAGEND) { goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); this.deltaX = browserEvent.clientX - this.startX; this.deltaY = browserEvent.clientY - this.startY; this.handleDragEnd(mapBrowserEvent); this.dragging_ = false; } - } else if (mapBrowserEvent.type == goog.fx.Dragger.EventType.START) { + } else if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAGSTART) { goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); this.startX = browserEvent.clientX; this.startY = browserEvent.clientY; diff --git a/src/ol/map.js b/src/ol/map.js index 35d1650410..4372cbad2b 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -22,8 +22,6 @@ goog.require('goog.events.MouseWheelEvent'); goog.require('goog.events.MouseWheelHandler'); goog.require('goog.events.MouseWheelHandler.EventType'); goog.require('goog.functions'); -goog.require('goog.fx.DragEvent'); -goog.require('goog.fx.Dragger'); goog.require('goog.fx.anim'); goog.require('goog.fx.anim.Animated'); goog.require('goog.object'); @@ -98,12 +96,6 @@ ol.Map = function( this.logger = goog.debug.Logger.getLogger('ol.map.' + goog.getUid(this)); } - /** - * @type {boolean} Are we a touch device? - * @private - */ - this.isTouch_ = false; - /** * @type {ol.TransformFunction} * @private @@ -159,9 +151,15 @@ ol.Map = function( this.viewport_.style.zIndex = ol.MapPaneZIndex.VIEWPORT; goog.dom.appendChild(container, this.viewport_); - goog.events.listen(this.viewport_, [ - goog.events.EventType.DBLCLICK - ], this.handleBrowserEvent, false, this); + var mapBrowserEventHandler = new ol.MapBrowserEventHandler(this); + goog.events.listen(mapBrowserEventHandler, [ + ol.MapBrowserEvent.EventType.CLICK, + ol.MapBrowserEvent.EventType.DBLCLICK, + ol.MapBrowserEvent.EventType.DRAGSTART, + ol.MapBrowserEvent.EventType.DRAG, + ol.MapBrowserEvent.EventType.DRAGEND + ], this.handleMapBrowserEvent, false, this); + this.registerDisposable(mapBrowserEventHandler); // FIXME we probably shouldn't listen on document... var keyHandler = new goog.events.KeyHandler(document); @@ -175,17 +173,6 @@ ol.Map = function( this.handleBrowserEvent, false, this); this.registerDisposable(mouseWheelHandler); - var dragger = new goog.fx.Dragger(this.viewport_); - dragger.defaultAction = function() {}; - goog.events.listen(dragger, [ - goog.fx.Dragger.EventType.START, - goog.fx.Dragger.EventType.DRAG, - goog.fx.Dragger.EventType.END - ], this.handleDraggerEvent, false, this); - goog.events.listen(this.viewport_, goog.events.EventType.TOUCHSTART, - this.handleTouchstart, false, this); - this.registerDisposable(dragger); - /** * @type {ol.renderer.Map} * @private @@ -501,6 +488,14 @@ ol.Map.prototype.getViewport = function() { ol.Map.prototype.handleBrowserEvent = function(browserEvent, opt_type) { var type = opt_type || browserEvent.type; var mapBrowserEvent = new ol.MapBrowserEvent(type, this, browserEvent); + this.handleMapBrowserEvent(mapBrowserEvent); +}; + + +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent The event to handle. + */ +ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { var interactions = this.getInteractions(); var interactionsArray = /** @type {Array.} */ interactions.getArray(); @@ -511,28 +506,11 @@ ol.Map.prototype.handleBrowserEvent = function(browserEvent, opt_type) { }; -/** - * @param {goog.events.Event} browserEvent Browser event. - */ -ol.Map.prototype.handleTouchstart = function(browserEvent) { - this.isTouch_ = true; - // now we know that we are a touch device - goog.events.unlisten(this.viewport_, goog.events.EventType.TOUCHSTART, - this.handleTouchstart, false, this); -}; - - /** * @param {goog.fx.DragEvent} dragEvent Drag event. */ ol.Map.prototype.handleDraggerEvent = function(dragEvent) { - var browserEvent = dragEvent.browserEvent; - // workaround for goog.fx.Dragger issue that causes both mousemove and - // touchmove to trigger a drag event on touch devices - if ((this.isTouch_ && browserEvent.type != goog.events.EventType.MOUSEMOVE) || - !this.isTouch_) { - this.handleBrowserEvent(browserEvent, dragEvent.type); - } + this.handleBrowserEvent(dragEvent.browserEvent, dragEvent.type); }; diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index 0fa253d952..53bd1ba68c 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -1,6 +1,11 @@ goog.provide('ol.MapBrowserEvent'); +goog.provide('ol.MapBrowserEvent.EventType'); +goog.provide('ol.MapBrowserEventHandler'); +goog.require('goog.asserts'); goog.require('goog.events.BrowserEvent'); +goog.require('goog.events.EventTarget'); +goog.require('goog.events.EventType'); goog.require('goog.style'); goog.require('ol.Coordinate'); goog.require('ol.MapEvent'); @@ -51,3 +56,240 @@ ol.MapBrowserEvent.prototype.getCoordinate = function() { return coordinate; } }; + + +/** + * @return {boolean} Do we have a left click? + */ +ol.MapBrowserEvent.prototype.isMouseActionButton = function() { + // always assume a left-click on touch devices + return ('ontouchstart' in document.documentElement) || + this.browserEvent.isMouseActionButton(); +}; + + + +/** + * @param {ol.Map} map The map with the viewport to listen to events on. + * @constructor + * @extends {goog.events.EventTarget} + */ +ol.MapBrowserEventHandler = function(map) { + + /** + * This is the element that we will listen to the real events on. + * @type {ol.Map} + * @private + */ + this.map_ = map; + + /** + * @type {Object} + * @private + */ + this.previous_ = null; + + /** + * @type {boolean} + * @private + */ + this.dragged_ = false; + + /** + * @type {number|undefined} + * @private + */ + this.timestamp_; + + /** + * @type {Array.} + * @private + */ + this.dragListenerKeys_ = null; + + /** + * @type {goog.events.BrowserEvent} + * @private + */ + this.down_ = null; + + /** + * @type {boolean} + * @private + */ + this.isTouch_ = document && ('ontouchstart' in document.documentElement); + + var element = this.map_.getViewport(); + goog.events.listen(element, + this.isTouch_ ? + goog.events.EventType.TOUCHSTART : + goog.events.EventType.MOUSEDOWN, + this.dragstart_, false, this); + goog.events.listen(element, + this.isTouch_ ? + goog.events.EventType.TOUCHEND : + goog.events.EventType.MOUSEUP, + this.dblclick_, false, this); + goog.events.listen(element, + goog.events.EventType.CLICK, this.click_, false, this); +}; +goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget); + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.touchEnableBrowserEvent_ = + function(browserEvent) { + if (this.isTouch_) { + goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); + var nativeEvent = browserEvent.getBrowserEvent(); + if (nativeEvent.touches && nativeEvent.touches.length) { + var nativeTouch = nativeEvent.touches[0]; + browserEvent.clientX = nativeTouch.clientX; + browserEvent.clientY = nativeTouch.clientY; + } + } +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.click_ = function(browserEvent) { + if (!this.dragged_) { + this.touchEnableBrowserEvent_(browserEvent); + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.CLICK, this.map_, browserEvent); + this.down_ = null; + this.dispatchEvent(newEvent); + } +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.dblclick_ = function(browserEvent) { + if (!this.dragged_) { + var now = new Date().getTime(); + if (!this.timestamp_ || now - this.timestamp_ > 250) { + this.timestamp_ = now; + } else { + this.timestamp_ = undefined; + this.touchEnableBrowserEvent_(this.down_); + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, this.down_); + this.down_ = null; + this.dispatchEvent(newEvent); + } + } +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.dragstart_ = function(browserEvent) { + if (!this.previous_) { + this.touchEnableBrowserEvent_(browserEvent); + this.previous_ = { + clientX: browserEvent.clientX, + clientY: browserEvent.clientY + }; + this.down_ = browserEvent; + this.dragged_ = false; + if (this.isTouch_) { + this.dragListenerKeys_ = [ + goog.events.listen(document, + goog.events.EventType.TOUCHMOVE, this.drag_, false, this), + goog.events.listen(document, + goog.events.EventType.TOUCHEND, this.dragend_, false, this) + ]; + } else { + this.dragListenerKeys_ = [ + goog.events.listen(document, + goog.events.EventType.MOUSEMOVE, this.drag_, false, this), + goog.events.listen(document, + goog.events.EventType.MOUSEUP, this.dragend_, false, this) + ]; + } + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DRAGSTART, this.map_, browserEvent); + this.dispatchEvent(newEvent); + } +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.drag_ = function(browserEvent) { + this.dragged_ = true; + this.touchEnableBrowserEvent_(browserEvent); + this.previous_ = { + clientX: browserEvent.clientX, + clientY: browserEvent.clientY + }; + // prevent viewport dragging on touch devices + browserEvent.preventDefault(); + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DRAG, this.map_, browserEvent); + this.dispatchEvent(newEvent); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.dragend_ = function(browserEvent) { + if (this.previous_) { + goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); + this.dragListenerKeys_ = null; + this.previous_ = null; + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DRAGEND, this.map_, browserEvent); + this.down_ = null; + this.dispatchEvent(newEvent); + } +}; + + +/** @override */ +ol.MapBrowserEventHandler.prototype.disposeInternal = function() { + var element = this.map_.getViewport(); + goog.events.unlisten(element, + this.isTouch_ ? + goog.events.EventType.TOUCHSTART : + goog.events.EventType.MOUSEDOWN, + this.dragstart_, false, this); + goog.events.unlisten(element, + this.isTouch_ ? + goog.events.EventType.TOUCHEND : + goog.events.EventType.MOUSEUP, + this.dblclick_, false, this); + goog.events.unlisten(element, + goog.events.EventType.CLICK, this.click_, false, this); + goog.asserts.assert(goog.isDef(this.dragListenerKeys_)); + goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); + this.dragListenerKeys_ = null; +}; + + +/** + * Constants for event names. + * @enum {string} + */ +ol.MapBrowserEvent.EventType = { + CLICK: goog.events.EventType.CLICK, + DBLCLICK: goog.events.EventType.DBLCLICK, + DRAGSTART: 'dragstart', + DRAG: 'drag', + DRAGEND: 'dragend' +};